Sensor Data Over MeshCore: Pull-Based Telemetry and CayenneLPP
Part one of this series looked at sensor telemetry over Reticulum, and landed on a specific trade-off: Reticulum gives you cryptographic primitives (Destinations, Links, LXMF’s delivery methods) and leaves the shape of a telemetry deployment up to you. MeshCore takes the opposite approach. It has an actual sensor node role, a standard payload encoding, and a query model built around telemetry specifically, not general-purpose messaging repurposed for it.

The Sensor Node Role
LPWAN Meshes: MeshCore - Moving Beyond the Ad-Hoc already covered MeshCore’s two main node roles: Companions (end-user devices that stay quiet to save battery) and Repeaters (dedicated infrastructure that handles routing). There is a third role, less discussed, that matters most for this article: the Sensor node.
A Sensor node is a leaf. It reads whatever hardware is attached to it and answers questions about those readings, but it does not relay other nodes’ traffic, and it does not repeat. It spends most of its time asleep rather than transmitting, and it only wakes fully to sample its sensors or respond to a query, though staying reachable for that query carries its own cost, covered below. That last part is the important design choice: a MeshCore sensor node does not spray readings into the air on a timer. It waits.
Pull, Not Push
The mechanism is a permission-gated query. In the firmware, it’s a single method call: querySensors(permissions, CayenneLPP&), which populates a telemetry buffer with whatever the caller is allowed to see, and returns it. A Companion node with the right permission asks; the Sensor node answers with exactly the readings that permission covers, nothing more.
This inverts the usual assumption about sensor networks, where the sensor decides when to transmit and everyone else has to listen for it. On MeshCore, the sensor stays silent by default and the network stays quiet by default. Nothing goes over the air until something on the other end actually wants it. For a battery-powered node in the field, that’s the difference between a radio that wakes up and transmits every 10 minutes whether anyone’s listening or not, and one that transmits only when there’s a genuine reason to.
It’s also a useful contrast with Reticulum’s telemetry pattern from part one of this series. Reticulum’s opportunistic delivery still has the sensor deciding when to send, on its own timer, and trusts LXMF’s store-and-forward Propagation Nodes to hold the reading until someone’s ready for it. MeshCore inverts that: the sensor doesn’t decide, the request does. Neither is wrong, they’re different answers to the same question, whether the network should be built around messages that get sent, or around questions that get asked.
What Reachability Actually Costs
The pull model has a practical downside worth being direct about: querySensors() can only answer a request if the sensor’s radio is actually listening at the moment the request arrives. A node can’t just sit at deep-sleep current and hope to be pulled, because nothing wakes it up from the outside. Reachability has to be maintained, and maintaining it costs real, ongoing current, not just the odd burst of transmit power.
The numbers make this concrete. Semtech’s SX1262, the LoRa radio under most MeshCore hardware, draws around 4.2 to 4.6 mA while actively receiving, against roughly 1.6 µA in sleep, a gap of close to three orders of magnitude. A sensor node that has to stay answerable to an incoming query can’t spend its life at the 1.6 µA figure.
MeshCore’s own community power-tuning documentation resolves this with a light sleep mode: the microcontroller sleeps, but the radio wakes on a timer to listen for a short window, keeping the node reachable at a fraction of continuous-receive cost, commonly documented at somewhere around 2 to 5 mA average on nRF52-class hardware, well above the 1 to 100 µA of true deep sleep. Deep sleep is available too, but it makes the node unreachable until its own wake timer fires, which isn’t a real option for a sensor node whose entire job is answering queries, it would just mean queries that get asked and never answered.
That leaves an operator with a genuine dial to set, not a default to trust. A short listen interval keeps the node responsive, at the cost of average current draw running in the low milliamps rather than the microamps the “spends almost all its time asleep” framing suggests. A long listen interval stretches battery life back out, but a query arriving mid-interval can sit unanswered for most of a minute before the radio next wakes to hear it. Sizing a battery or solar panel for a MeshCore sensor node means budgeting for that periodic receive current on top of the occasional CayenneLPP reply, not just for the reply itself. Part three of this series lays out the fuller comparison, against both Reticulum’s push model and LoRaWAN’s own low-power end-device behaviour.
CayenneLPP: A Small, Borrowed Format
Readings are packed using CayenneLPP, a compact binary encoding originally developed for Cayenne (myDevices) and widely adopted across the LoRaWAN and The Things Network community for exactly the same reason MeshCore uses it here: airtime is expensive, so every byte in a payload should carry a reading, not framing overhead. Each data point is encoded as a channel number, a type byte identifying the sensor kind (temperature, humidity, GPS, and so on, each with an agreed-upon scale and precision), and the value itself. A full temperature, humidity, and pressure reading fits in a handful of bytes on the air.
A concrete example illustrates the byte efficiency:
01 67 00 D6 -> Channel 1: Temperature (0x67), 21.4°C (value: 214 / 10)
02 68 82 -> Channel 2: Relative Humidity (0x68), 65.0% (value: 130 / 2)
03 02 01 73 -> Channel 3: Analog/Battery (0x02), 3.71V (value: 371 / 100)That entire three-sensor payload is packed into just 11 bytes of raw airtime.
The detail worth sitting with: CayenneLPP is not a MeshCore invention. It’s LoRaWAN tooling, reused wholesale by a project that has nothing to do with LoRaWAN’s network-server model. The payload format and the transport underneath it turn out to be separable concerns, and MeshCore’s choice to reuse an existing, already-interoperable encoding rather than inventing a new one is a small, practical example of that.
What’s Already Supported
MeshCore’s own firmware compiles in support for a specific, named set of sensors, conditionally, so a build only carries the code for hardware actually attached:
- BME680 (via Bosch’s BSEC library, temperature/humidity/pressure/gas)
- BME280 and AHTX0 (temperature/humidity/pressure, simpler and cheaper alternatives to the BME680)
- INA3221 (three-channel power monitor, high-precision voltage and current on multiple rails, useful for tracking a solar/battery setup’s actual health rather than guessing from a single ADC pin)
- VL53L0X (time-of-flight distance sensor, tank level, gate position, anything measured by “how far away is the nearest object”)
- RAK12035 (soil moisture)
- GPS, via MicroNMEALocationProvider for serial NMEA feeds or u-blox modules over I2C
Board-level battery voltage is read separately, typically off an ADC pin, as a baseline health signal even on nodes with no other sensors attached.
Existing Open-Source Tooling
As with Reticulum, none of this requires starting from a blank firmware image:
- MeshCore’s own repository includes an official Simple Sensor example firmware, which turns a cheap LoRa development board into a working off-grid weather station, temperature, humidity, pressure, served to anyone on the mesh who asks, out of the box.
- RF Lab’s MeshCore sensor firmware guide is a real, independent, community-written walkthrough of deploying it, worth reading alongside the official docs rather than instead of them.
- b-parasite is a well-known open-hardware DIY soil moisture sensor design. It isn’t MeshCore-specific, but it’s a natural pairing given MeshCore’s own RAK12035 soil-moisture support, and it’s a good example of the kind of open hardware this community is starting to absorb rather than build from scratch every time.
- awesome-meshcore is a curated resource list covering the wider project, firmware forks, and community tooling.
Structured Versus Primitive
Put side by side with part one, the shape of the trade-off is clear. Reticulum hands you cryptographic primitives and a general-purpose message format, and building sensor telemetry on top means deciding, yourself, when to send, how to structure the payload, and whether a Propagation Node is worth running. MeshCore hands you a finished sensor role, a standard payload encoding shared with an entirely different ecosystem, and a query model that keeps the network quiet until something asks. Reticulum is the toolkit. MeshCore is the appliance. Neither claim is a criticism, they’re aimed at different points on the same spectrum, and part three compares both against LoRaWAN’s centralised gateway model.
Both descriptions above highlight how the firmware and protocol operate under real conditions. MeshCore and Reticulum are not built to displace LoRaWAN where high-density municipal or commercial infrastructure exists; rather, they carve out a distinct domain: autonomous, zero-backhaul telemetry for edge environments where centralised infrastructure is impractical or unavailable.
Part two of three. Previously: Sensor Data Over Reticulum: LXMF, Propagation Nodes, and the Low-Power Case. Next: No Gateway Required: Mesh Telemetry Versus LoRaWAN's Centralised Model. Related reading: LPWAN Meshes: MeshCore - Moving Beyond the Ad-Hoc for MeshCore’s full architecture.
Sources
- meshcore-dev, MeshCore. Sensor node role,
querySensors(), Simple Sensor example firmware, supported hardware list. - DeepWiki, MeshCore: Sensor Integration and Repeater Nodes. Architectural detail on the sensor/repeater/companion role split.
- RF Lab, MeshCore Sensor Firmware: Weather Data Over the Mesh. Independent deployment guide.
- rbaron, b-parasite. Open-hardware soil moisture sensor.
- samuk, awesome-meshcore. Curated project list.
- Semtech, SX1262 LoRa Connect Transceiver. Receive and sleep current specifications.
- LocalMesh, MeshCore Power Consumption Optimization. Community-documented light sleep/deep sleep current figures for MeshCore hardware.
Webmentions
Want to comment? Reply to this post from your Mastodon/Fediverse account, or mention this post's URL in your reply. Your comment will appear here automatically!
Have your own blog? Send a webmention
to https://webmention.io/gaggl.com/webmention