Metrum: A Telemetry System for Reticulum Networks
Metrum is an open-source telemetry system designed for Reticulum networks. It provides a standardized way to collect, process, and transmit sensor data, enabling efficient and reliable communication between devices and nodes.
How Metrum Works
Metrum is a framework designed for sending telemetry data (sensor readings) over Reticulum networks. It implements a publisher-subscriber pattern that allows sensor data to be efficiently transmitted from sensor nodes (publishers) to data collection nodes (subscribers).
Key components of the system include:
- Publisher: Collects data from sensors and distributes it to interested subscribers
- Subscriber: Discovers publishers and subscribes to their sensor data
- Reticulum Network: The underlying transport mechanism that enables communication
- SenML Format: A standardized format for representing sensor measurements
- CBOR Encoding: Efficient binary serialization for compact data transmission
The Publisher Side
The publisher in Metrum operates as follows:
-
Initialization:
- The publisher is created with a specific sensor interface
- It establishes its identity on the Reticulum network
- It announces its presence as a telemetry publisher
-
Sensor Data Collection:
- Periodically reads data from connected sensors
- Formats this data according to the SenML specification
- Encodes the data using CBOR for efficient transmission
-
Data Distribution:
- Manages a list of active subscribers
- Distributes sensor readings to all subscribed nodes
- Periodically re-announces its presence to allow new subscribers to discover it
The sensors are abstracted through a SensorInterface class, which handles the specifics of reading from physical or virtual sensors.
The Subscriber Side
The subscriber operates as follows:
-
Discovery:
- Monitors the Reticulum network for publisher announcements
- Records information about discovered publishers
-
Connection:
- Establishes links to publishers of interest
- Sends subscription requests to activate the data flow
-
Data Processing:
- Receives CBOR-encoded SenML data from publishers
- Decodes the data and processes it through a callback function
- In the provided example, stores the data in InfluxDB for later analysis
- Implements a retry queue for handling temporary database unavailability
-
Reconnection:
- Monitors the status of publisher connections
- Automatically attempts to reconnect to disconnected publishers
Communication Flow
The communication between publisher and subscriber follows these steps:
- The publisher announces its presence on the Reticulum network
- The subscriber discovers the publisher through these announcements
- The subscriber establishes a connection to the publisher
- The subscriber sends a subscription request
- The publisher adds the subscriber to its active list
- The publisher periodically collects and transmits sensor data
- The subscriber receives, processes, and stores the data
This approach allows for a flexible and resilient system where publishers and subscribers can dynamically discover each other and establish communication without centralized coordination.
Data Format
The data is structured using SenML (Sensor Measurement Lists), which provides a standardized way to represent sensor readings. A SenML record typically includes:
- Name: Identifies the sensor or measurement (e.g., "temperature")
- Value: The actual reading value
- Unit: The unit of measurement (e.g., "Celsius")
- Timestamp: When the reading was taken
This structured format ensures that all sensor data is properly labeled and can be correctly interpreted by the receiving systems.
Advantages of this Architecture
- Decentralization: No single point of failure in the system
- Flexibility: Easy to add new sensors or subscribers
- Efficiency: CBOR encoding minimizes bandwidth usage
- Standardization: Using SenML ensures interoperability
- Resilience: Automatic reconnection and data queuing handle network instability
This architecture makes Metrum well-suited for sensor networks in challenging environments or where network connections may be intermittent.
Diátaxis Structure
Our documentation is structured around the four needs identified by Diátaxis:
- Tutorials: Step-by-step guides for getting started with Metrum.
- How-to Guides: Practical instructions for achieving specific goals with Metrum.
- Technical Reference: Detailed descriptions of Metrum's components, APIs, and interfaces.
- Explanation: In-depth discussions of Metrum's architecture, design decisions, and underlying principles.
This structure allows us to provide a comprehensive and user-friendly documentation set that addresses the needs of different users.
Contributors
- Tom Hensel code@jitter.eu, DO2THX, 5620
Metrum is a framework for decentralized sensor data communication that works over Reticulum networks. It follows a publisher-subscriber pattern and uses standardized formats like SenML (Sensor Measurement Lists) and CBOR (Concise Binary Object Representation) for efficient data transmission.
Communication Philosophy
Metrum's communication philosophy is based on the following principles:
- Heterogeneity: Metrum is designed to work in diverse and heterogeneous networks, where devices and sensors may have different capabilities, protocols, and data formats.
- Scalability: Metrum is built to scale, handling large amounts of sensor data from multiple devices and sources.
- Flexibility: Metrum provides a flexible framework for integrating with different sensors, devices, and systems.
- Efficiency: Metrum optimizes data transmission and reception, minimizing overhead and ensuring reliable communication.
Communication Architecture
The system consists of the following components:
flowchart TB
subgraph "Publisher Node"
Sensor["Sensor Interface"] --> MetrumPublisher["MetrumSensorPublisher"]
MetrumPublisher --> CBOR1["CBOR Encoding"]
CBOR1 --> SenML1["SenML Formatting"]
end
subgraph "Reticulum Network"
Network["Decentralized Network"]
end
subgraph "Subscriber Node"
MetrumSubscriber["MetrumSensorSubscriber"] --> CBOR2["CBOR Decoding"]
CBOR2 --> SenML2["SenML Processing"]
SenML2 --> InfluxDB["InfluxDB Storage"]
end
MetrumPublisher -->|"Announce/Publish"| Network
Network -->|"Connect/Subscribe"| MetrumSubscriber
classDef sensor fill:#f9f,stroke:#333,stroke-width:2px
classDef publisher fill:#bbf,stroke:#333,stroke-width:2px
classDef network fill:#dfd,stroke:#333,stroke-width:2px
classDef subscriber fill:#fbb,stroke:#333,stroke-width:2px
classDef storage fill:#ffd,stroke:#333,stroke-width:2px
class Sensor sensor
class MetrumPublisher,CBOR1,SenML1 publisher
class Network network
class MetrumSubscriber,CBOR2,SenML2 subscriber
class InfluxDB storage
- Publishers: Devices or nodes that collect and transmit sensor data.
- Subscribers: Devices or nodes that receive and process sensor data.
- Reticulum Network: A decentralized network that enables communication between devices and nodes.
- InfluxDB: Time series database (TSDV) used for storing IoT Datapoints.
Specifications
Metrum uses the following specifications for communication:
- CBOR Encoding: Metrum uses CBOR (Concise Binary Object Representation) encoding for transmitting sensor data.
- Reticulum Protocol: Metrum communicates over Reticulum networks using the Reticulum protocol.
- Sensor Data Format: Metrum uses a standardized sensor data format, which includes:
- Metric: A string representing the sensor measurement (e.g., temperature, humidity).
- Value: The sensor reading value.
- Unit: The unit of measurement for the sensor reading (e.g., Celsius, Fahrenheit).
- Timestamp: The timestamp for the sensor reading.
Defining Sensors
To define a sensor in Metrum, you need to create a class that inherits from the SensorInterface abstract base class. The class should implement the following methods:
read_sensors: This method collects sensor data and returns it as a dictionary.
Here is an example of a sensor definition:
from metrum import SensorInterface
class ExampleSensor(SensorInterface):
"""Mock sensor for testing serialization"""
def read_sensors(self):
"""Return mock sensor readings with proper SenML formatting"""
readings = {
"temperature": {
"value": 25.5,
"unit": SenmlUnits.SENML_UNIT_DEGREES_CELSIUS,
"name": SenmlNames.KPN_SENML_TEMPERATURE,
},
"pressure": {
"value": 101325,
"unit": SenmlUnits.SENML_UNIT_PASCAL,
"name": SenmlNames.KPN_SENML_PRESSURE,
},
"humidity": {
"value": 65.0,
"unit": SenmlUnits.SENML_UNIT_RELATIVE_HUMIDITY,
"name": SenmlNames.KPN_SENML_HUMIDITY,
},
}
return readings
The SensorInterface takes serializes the sensor readings as SenML using CBOR encoding.
Sensor Data Format
The sensor data format used in Metrum is based on the SenML (Sensor Measurement Lists) specification. SenML is a lightweight, binary format for representing sensor data.
A SenML record consists of the following fields:
- Name: A string representing the sensor measurement (e.g., temperature, humidity).
- Value: The sensor reading value.
- Unit: The unit of measurement for the sensor reading (e.g., Celsius, Fahrenheit).
- Timestamp: The timestamp for the sensor reading.
Communication Flow
The communication flow in Metrum is as follows:
- Publisher Announcement: The publisher announces its presence and available metrics to the Reticulum network.
- Subscriber Connection: The subscriber establishes a connection to the publisher and requests subscription to specific metrics.
- Telemetry Data Transmission: The publisher transmits telemetry data to the subscriber using CBOR encoding.
- Data Processing: The subscriber processes the received telemetry data and stores it in a database or performs other actions.
flowchart TB
subgraph "Data Collection"
S1["Temperature Sensor"] --> |"Reading"| SI["Sensor Interface"]
S2["Pressure Sensor"] --> |"Reading"| SI
S3["Humidity Sensor"] --> |"Reading"| SI
end
subgraph "Publisher Processing"
SI --> |"read_sensors()"| SP["SenML Pack"]
SP --> |"CBOR encoding"| CD["CBOR Data"]
end
subgraph "Transmission"
CD --> |"Reticulum Transport"| RN["Reticulum Network"]
RN --> |"Packet Delivery"| SD["Subscriber Decoder"]
end
subgraph "Subscriber Processing"
SD --> |"CBOR decoding"| SP2["SenML Pack"]
SP2 --> |"Data Processing"| DP["Data Points"]
DP --> |"Write API"| IF["InfluxDB"]
DP --> |"If InfluxDB unavailable"| RQ["Retry Queue"]
RQ -.-> |"Retry later"| IF
end
classDef collection fill:#e1f5fe,stroke:#333,stroke-width:1px
classDef publisher fill:#e8f5e9,stroke:#333,stroke-width:1px
classDef network fill:#fff9c4,stroke:#333,stroke-width:1px
classDef subscriber fill:#f9e1fd,stroke:#333,stroke-width:1px
class S1,S2,S3,SI collection
class SP,CD publisher
class RN network
class SD,SP2,DP,IF,RQ subscriber
Example Use Case
Here is an example of how to define a sensor and use it with Metrum:
# Define a sensor class like above
publisher = MetrumPublisher(sensor=ExampleSensor(), config_path="config.toml")
# Announce the publisher and publish telemetry data
publisher.announce()
publisher.publish_telemetry()
This example demonstrates how to define a sensor class, create a Metrum publisher instance, and publish telemetry data using the Reticulum protocol.
TODO Later
- pluggable transport layer
- use minimal amount of bandwith
- try to use standards when possible
Design Decisions
Metrum's design is based on the following principles:
- Scalability: Metrum is designed to handle large amounts of sensor data from multiple devices.
- Flexibility: Metrum provides a flexible framework for integrating with different sensors, devices, and systems.
Communication Flow
The following workflow diagram illustrates the process of publishing and subscribing to telemetry data using Metrum:
sequenceDiagram
participant S as Sensor
participant P as Publisher
participant R as Reticulum Network
participant Sub as Subscriber
participant DB as InfluxDB
Note over P,R: Publisher Initialization
P->>P: Initialize with sensor interface
P->>R: Announce presence (with SenML capability)
Note over R,Sub: Subscriber Discovery
R->>Sub: Forward publisher announce
Sub->>Sub: Record publisher details
Note over Sub,P: Connection Establishment
Sub->>R: Request path to publisher
R->>Sub: Path established
Sub->>P: Establish link
P->>Sub: Link acknowledged
Sub->>P: Send subscription request
P->>P: Activate subscriber
loop At collection interval
S->>P: Read sensor data
P->>P: Format as SenML
P->>P: Encode with CBOR
P->>Sub: Send telemetry data
Sub->>Sub: Decode CBOR
Sub->>DB: Store SenML data
alt InfluxDB unavailable
Sub->>Sub: Queue data for retry
end
end
loop At announce interval
P->>R: Re-announce presence
end
Hardware Guide
Quick Start: Recommended Purchase Options
Always make sure on AliExpress and similar sites, that you are buying the full chip, not just a module. Often the sellers list the cheapest module or case, as the list price.
Budget Starter Kit (5 Nodes) - ~€150 Total
| Device | Heltec LoRa 32 V3 | Quantity | Unit Price | Total |
|---|---|---|---|---|
| MCU | ESP32-S3FN8 | 5x | €25 | €125 |
| Purchase Links | AliExpress Search | |||
| Antennas | 868/915 MHz 2dBi | 5x | €3 | €15 |
| Cases | Optional plastic | 5x | €2 | €10 |
Pros: Cheap, WiFi+BLE, OLED display, good for learning
Cons: Power-hungry (~90-200mA), not suitable for long-term battery use
Best for: Indoor nodes, mains power, development, short-term mobile use
Low-Power Starter Kit (5 Nodes) - ~€300 Total
| Device | Heltec T114 Mesh Node V2 | Quantity | Unit Price | Total |
|---|---|---|---|---|
| MCU | nRF52840 + SX1262 | 5x | €50 | €250 |
| Purchase Links | AliExpress Muzi Works | Rokland | Amazon | |||
| Solar Panels | 1W each | 5x | €8 | €40 |
| Cases | Waterproof IP65 | 5x | €2 | €10 |
Pros: Ultra-low power (11µA sleep), solar-ready, 1.14" TFT display, no soldering required, built-in BMS
Cons: More expensive, BLE only (no WiFi)
Best for: Long-term deployment, solar nodes, battery operation, remote locations
Why T114 over RAK4631? The Heltec T114 is plug-and-play with built-in battery management and display, while RAK4631 requires additional BMS components and soldering.
Protocol Architecture Comparison
This guide covers three distinct mesh networking approaches with fundamentally different transport mechanisms:
- Meshtastic: Application-layer mesh protocol over LoRa PHY/MAC
- Reticulum: SDLC-based (Synchronous Data Link Control) networking stack, transport-agnostic
- OpenMANET: IP-based MANET (Mobile Ad-Hoc Network) over WiFi HaLow (802.11ah)
Critical Engineering Distinction: Reticulum operates at the data link layer without IP dependencies, while OpenMANET maintains full IP stack compatibility. This architectural difference impacts power consumption, protocol overhead, and network interoperability.
Hardware Platform Analysis
Microcontroller Architectures
ESP32 Family Characteristics
- Architecture: Xtensa 32-bit LX6/LX7 dual-core
- Power Profile: High consumption - 90-200mA active, ~900µA deep sleep
- Radio Integration: WiFi + Bluetooth + LoRa (external)
- Use Cases: Mains-powered base stations, vehicle installations, development
- Cost: Low (€15-35 per node)
nRF52840 Characteristics
- Architecture: 32-bit ARM Cortex-M4F with FPU, 64MHz
- Power Profile: Ultra-low - 2-11µA sleep, ~125mA TX@20dBm
- Radio Integration: BLE 5.0 + LoRa (external)
- Use Cases: Battery/solar nodes, remote sensors, handheld devices
- Cost: Medium (€40-70 per node)
LoRa Transceiver Performance Matrix
| Parameter | SX1276/1278 | SX1262/1268 | SX1280 |
|---|---|---|---|
| Frequency Range | 137-1020 MHz | 150-960 MHz | 2.4 GHz |
| Max TX Power | +20 dBm | +22 dBm | +12.5 dBm |
| RX Sensitivity | -148 dBm | -148 dBm | -132 dBm |
| Sleep Current | 0.2 µA | 1.6 µA | 1.1 µA |
| RX Current | 10.8 mA | 4.2 mA | 6.8 mA |
| TX Current @20dBm | 87 mA | 38 mA | 25 mA |
| Efficiency | Legacy | Best | High speed |
Recommendation: SX1262/1268 offers the best power efficiency and is used in modern devices like Heltec T114.
Complete Hardware Bill of Materials
Meshtastic Devices
Budget ESP32 Platforms
| Device | Heltec LoRa 32 V3 |
|---|---|
| MCU | ESP32-S3FN8 (240MHz dual-core) |
| LoRa | SX1262 |
| Frequency | 433/868/915/923 MHz variants |
| TX Power | 22 dBm |
| Display | 0.96" OLED 128×64 |
| WiFi/BT | Yes / BLE 5.0 |
| GPS | No |
| Battery | JST SH1.25-2 connector, built-in BMS |
| Case | Optional plastic case available |
| Price | €25-30 |
| Power | 90-200mA active, ~900µA sleep |
| Best For | Learning, indoor nodes, short-term mobile |
| Purchase | AliExpress | Amazon |
| Device | LILYGO T-Beam |
|---|---|
| MCU | ESP32 WROVER-B |
| LoRa | SX1276/SX1278 |
| Frequency | 433/868/915/923 MHz variants |
| TX Power | 20 dBm |
| Display | Optional 0.96" OLED |
| WiFi/BT | Yes / Classic BT + BLE |
| GPS | NEO-6M/NEO-8M |
| Battery | 18650 holder |
| Case | No (requires DIY) |
| Price | €35-45 |
| Power | 150-300mA active (with GPS) |
| Best For | Mobile tracking, vehicle installation |
| Purchase | AliExpress |
Ultra-Low Power nRF52 Platforms
| Device | Heltec T114 Mesh Node V2 |
|---|---|
| MCU | nRF52840 (ARM Cortex-M4F, 64MHz) |
| LoRa | SX1262 |
| Frequency | 433/470/868/915 MHz variants |
| TX Power | 22 dBm |
| Display | 1.14" TFT 135×240, 262K colors |
| WiFi/BT | No / BLE 5.0 |
| GPS | Optional module |
| Battery | JST 1.25mm connector, built-in BMS |
| Solar | JST 1.25mm solar input |
| Case | Optional enclosures |
| Price | €45-60 |
| Power | 11µA sleep, 23µA Meshtastic mode |
| Best For | Solar nodes, long-term battery deployment |
| Purchase | Muzi Works | Rokland |
| User Review | "Nearly a week on single 18650 without solar. Stays fully charged even on cloudy days." |
All-in-One Solutions
| Device | LILYGO T-Echo |
|---|---|
| MCU | nRF52840 |
| LoRa | SX1262 |
| Frequency | 433/868/915/923 MHz variants |
| TX Power | 22 dBm |
| Display | 1.54" E-Paper (ultra-low power) |
| WiFi/BT | No / BLE 5.0 |
| GPS | Air530Z |
| Battery | Built-in 1200mAh |
| Case | Injection-molded (included) |
| Price | €55-70 |
| Power | Ultra-low with e-paper display |
| Best For | Handheld use, harsh environments |
Reticulum RNode Hardware
Important: Reticulum supports the Heltec T114 and other nRF52840 devices via RNode firmware as nodes.
Supported Platforms
| Device | LILYGO LoRa32 V2.1 |
|---|---|
| MCU | ESP32 WROVER-B |
| LoRa | SX1276/SX1278 |
| Frequency | 433/868/915 MHz variants |
| TX Power | 17 dBm |
| Display | 0.96" OLED |
| WiFi/BT | Yes / BLE |
| GPS | No |
| Battery | JST connector |
| Case | 3D-printable STL files |
| Price | €20-30 |
| Firmware | RNode via rnodeconf --autoinstall |
| Best For | DIY handheld RNodes |
| Device | Heltec T114 (RNode Compatible) |
|---|---|
| Support | Full RNode firmware support |
| Installation | rnodeconf --autoinstall |
| Advantages | Ultra-low power, professional grade |
| Use Case | Battery-powered RNode deployments |
RNode Firmware Support Matrix
| MCU Platform | Supported Boards | Flash Method | Reticulum Support |
|---|---|---|---|
| ESP32 | Generic ESP32, LILYGO, Heltec | Serial/USB | ✅ Full |
| nRF52840 | T114, RAK4631, custom designs | UF2 bootloader | ✅ Full |
| ATmega1284p | Homebrew designs | ISP/Arduino | ✅ Limited |
| ATmega2560 | Arduino Mega compatible | USB/ISP | ✅ Limited |
WiFi HaLow Hardware (Experimental)
Development Modules
| Device | Seeed Studio Wio WM6180 |
|---|---|
| Standard | IEEE 802.11ah (WiFi HaLow) |
| Frequency | 902-928 MHz ISM band |
| Range | Up to 1 km (line of sight) |
| Data Rate | 150 kbit/s - 32.5 Mbps |
| TX Power | 21±1 dBm |
| Price | €50-80 |
| Status | Experimental, OpenMANET compatible |
| Reticulum | Not directly supported (IP-based vs SDLC) |
| Purchase | Seeed Studio |
Antenna Specifications
LoRa Antennas
| Type | Frequency | Gain | Impedance | Price | Application |
|---|---|---|---|---|---|
| Omnidirectional | 868/915 MHz | 2-3 dBi | 50Ω | €5-15 | Base stations |
| High-gain Yagi | 868/915 MHz | 8-12 dBi | 50Ω | €20-50 | Point-to-point links |
| Magnetic Mount | 433 MHz | 3 dBi | 50Ω | €10-25 | Vehicle mobile |
| Whip Antenna | All bands | 2.1 dBi | 50Ω | €3-8 | Handheld devices |
Purchase Links: AliExpress Antennas | Search for your specific frequency band
Power and Environmental
Solar Power Systems
| Component | Specification | Price | Purpose |
|---|---|---|---|
| 1W Solar Panel | 6V, 167mA | €8-15 | Single T114 node |
| 5W Solar Panel | 12V, 417mA | €25-40 | Multiple ESP32 nodes |
| Charge Controller | 6-24V input | €15-40 | Waveshare Module |
| 18650 Battery | 2500-3500mAh | €5-12 | Primary storage |
Enclosures
| Type | IP Rating | Material | Price Range | Use Case |
|---|---|---|---|---|
| Waterproof Box | IP65-IP67 | ABS Plastic | €10-30 | Permanent outdoor |
| Transparent Case | IP54 | Polycarbonate | €5-15 | Temporary/indoor |
| Metal Enclosure | IP67 | Aluminum | €25-60 | Professional installation |
Power Analysis
Battery Life Calculations
| Platform | Sleep Current | Active Current | Battery Life (2500mAh) |
|---|---|---|---|
| ESP32 + SX1276 | 900µA - 2mA | 87-200mA | 2-14 days |
| nRF52 + SX1262 (T114) | 11µA | 38-125mA | 6+ months |
| WiFi HaLow | ~10-50µA | 40-60mA | 3-6 months |
Solar Sizing Guidelines
Daily Power = (Sleep Hours × Sleep Current) + (TX Hours × TX Current)
ESP32 Node: ~0.1W average → 5W panel minimum (3x safety factor)
T114 Node: ~0.01W average → 1W panel sufficient (10x safety factor)
Regional Frequency Regulations
| Region | Primary Band | Power Limit | Duty Cycle | Notes |
|---|---|---|---|---|
| Europe | 868 MHz | 25mW ERP | 1% or 10% | SRD regulations |
| North America | 915 MHz | 1W EIRP | None | Part 15.247 |
| Asia-Pacific | 433/923 MHz | 25-50mW | Varies | Country-specific |
| Germany | 868 MHz | 25mW ERP | 1%/10% | BNetzA approved |
Network Architecture
Meshtastic Topology
- Max nodes per channel: 100-200 (duty cycle limited)
- Hop limit: 3-7 hops typical
- Channel utilization: <10% (regulatory requirement)
- Optimal spacing: 1-5 km (terrain dependent)
Reticulum Network Design
- Transport agnostic: LoRa, WiFi, Ethernet, Serial, Packet Radio
- No hop limits: Dynamic route discovery
- Bandwidth adaptation: Automatic rate adjustment
- Heterogeneous: Mix different radio technologies
OpenMANET Architecture
- IP-based: Full TCP/IP stack
- Range: Up to 3 km (WiFi HaLow)
- Device capacity: 1000+ nodes per AP
- Protocols: B.A.T.M.A.N. Advanced, OLSR
Setup and Configuration
Video Resources
Hardware Setup Guide: YouTube - RNode Hardware Setup
Application Usage: YouTube - Meshtastic App Tutorial
Installation Commands
Reticulum/RNode Setup
# Install RNode configuration utility
pip install rns --upgrade
# Auto-install firmware (supports T114)
# Or use the web based installer: https://liamcottle.github.io/rnode-flasher/
rnodeconf --autoinstall
Meshtastic Firmware
# Web-based installer (recommended)
# Visit: https://flasher.meshtastic.org/
# For T114: Select "Heltec Mesh Node T114"
OpenMANET (WiFi HaLow)
# Download OpenWRT image
wget https://github.com/OpenMANET/openwrt/releases/latest
# Flash to supported hardware
# See: https://openmanet.github.io/docs/initial-setup.html
Integration Notes
Reticulum + OpenMANET
Currently incompatible due to fundamental differences:
- Reticulum: SDLC-based, no IP layer
- OpenMANET: IP-based MANET protocols
Future Integration: Possible through bridge applications or protocol gateways.
OpenMANET Resources:
- Website: openmanet.net
- Documentation: Setup Guide
- B.A.T.M.A.N. Advanced: Configuration
Purchasing Summary
Recommended First Purchase (Germany/Europe)
For Beginners: 2x Heltec LoRa 32 V3 (€50) + antennas (€10) = €60 total
For Serious Deployment: 5x Heltec T114 (€250) + solar panels (€40) + cases (€10) = €300 total
Purchase Priority:
- T114 for battery/solar nodes - No soldering, built-in BMS, ultra-low power
- ESP32 for mains-powered base stations - WiFi capability, lower cost
- Professional antennas for range improvement
- Proper enclosures for permanent deployment
Further Reading
- Reticulum Network Stack: Official Manual
- RNode Technical Guide: Linux in a Bit Blog
- Meshtastic Hardware: Official Device List
- Amateur Radio Integration: KISS TNC Guide
This guide reflects current hardware availability as of September 2025. Verify specifications and regional compliance before deployment.
Installation
You can install it with
uv pip install metrum
Or install from this git repo
Fix GPIO and I2C permission errors
How to fix I2C and GPIO permission errors. Run as root
chown :i2c /dev/i2c-1
chown :gpio /dev/gpiochip0
chown :gpio /dev/gpio
chown :gpio /dev/gpiomem
chown :i2c /dev/i2c-2
Getting Started with Metrum
This tutorial will guide you through the process of installing and configuring Metrum on your Reticulum network.
Step 1: Install Metrum
To install Metrum, run the following command:
uv pip install metrum
Step 2: Configure Your Reticulum Network Follow this guide on how to write your reticulum config file.
Step 3: Configure Metrum
Metrum can be configured using a TOML file. The default configuration file path is ~/.config/metrum/config.toml.
[sensor]
class = "metrum.sensors.computer.ExampleSensor"
device_id = "urn:dev:metrum:b97893bb5cb3170e5b09c653c7f759b7"
read_interval = 1
collection_interval = 10
announce_interval = 20
id_filename = "id_computer_sensor"
[influxdb]
url = "url of the influx db server"
org = "first-org"
bucket = "sensor-data"
retry_interval = 60
Step 4: Define a Sensor
Create a new class that inherits from SensorInterface:
class ExampleSensor(SensorInterface):
"""Mock sensor for testing serialization"""
def read_sensors(self):
"""Return mock sensor readings with proper SenML formatting"""
readings = {
"temperature": {
"value": 25.5,
"unit": SenmlUnits.SENML_UNIT_DEGREES_CELSIUS,
"name": SenmlNames.KPN_SENML_TEMPERATURE,
},
"pressure": {
"value": 101325,
"unit": SenmlUnits.SENML_UNIT_PASCAL,
"name": SenmlNames.KPN_SENML_PRESSURE,
},
"humidity": {
"value": 65.0,
"unit": SenmlUnits.SENML_UNIT_RELATIVE_HUMIDITY,
"name": SenmlNames.KPN_SENML_HUMIDITY,
},
}
return readings
Run the your custom Environmental Sensor with settings from your config:
uv run --extra computer metrum -p
Or if you have lm_sensors installed, you can run the Computer Sensor
uv run --extra computer metrum -p
Start the subscriber on any device, which is inside connected by the Reticulum network
uv run metrum -s
Caveats
Currently, there are two bugs:
- Announces do not show up. Workaround read log of publisher and then run
uv run metrum -s --dest <dest id> - Loading classes is hard-coded, will be fixed ASAP. Workaround: add your class to the
run_publisherfunction insrc/metrum/cli.py
How to Define a New Sensor Interface
Create a new class that inherits from SensorInterface inside sensor py
class ExampleSensor(SensorInterface):
"""Mock sensor for testing serialization"""
def read_sensors(self):
"""Return mock sensor readings with proper SenML formatting"""
readings = {
"temperature": {
"value": 25.5,
"unit": SenmlUnits.SENML_UNIT_DEGREES_CELSIUS,
"name": SenmlNames.KPN_SENML_TEMPERATURE,
},
"pressure": {
"value": 101325,
"unit": SenmlUnits.SENML_UNIT_PASCAL,
"name": SenmlNames.KPN_SENML_PRESSURE,
},
"humidity": {
"value": 65.0,
"unit": SenmlUnits.SENML_UNIT_RELATIVE_HUMIDITY,
"name": SenmlNames.KPN_SENML_HUMIDITY,
},
}
return readings
TODO
- explain how to define a good sensor and implement concise efficient packets
- Create a PR for merging the sensor definiton into its own file
Metrum API
The Metrum API provides a set of classes and functions for working with sensors and telemetry data.
classDiagram
class SensorInterface {
+device_id
+read_sensors()
+collect_datapoints()
+collect_reading()
}
class ExampleSensor {
+read_sensors()
}
class MetrumSensorPublisher {
-reticulum
-identity
-sensor
-destination
-subscribers
+announce()
+encode_announce_data()
+get_subscriber_hash(link)
+link_established(link)
+packet_received(data, packet)
+link_closed(link)
+publish_senml()
+run(collection_interval, announce_interval, read_interval)
}
class MetrumSensorSubscriber {
-reticulum
-identity
-publishers
-senml_callback
+received_announce(destination_hash, announced_identity, app_data)
+connect_to_publisher(destination_hash)
+link_established(link, destination_hash)
+link_closed(link, destination_hash)
+packet_received(data, packet)
+reconnect_disconnected(max_age)
}
class RNS {
+Identity
+Destination
+Link
+Packet
+Transport
}
SensorInterface <|-- ExampleSensor
MetrumSensorPublisher --> SensorInterface
MetrumSensorPublisher --> RNS
MetrumSensorSubscriber --> RNS
- Classes:
MetrumPublisher: A class for publishing telemetry data.MetrumSubscriber: A class for subscribing to telemetry data.
- Functions:
announce(): Announces the publisher's presence to the Reticulum network.publish_telemetry(): Publishes telemetry data to the Reticulum network.
Technical Reference
Reticulum Protocol
The Reticulum protocol is used for communication between devices and nodes on the network.
- Transport: The Reticulum protocol uses a transport layer to ensure reliable data transmission.
- Encryption: Metrum uses end-to-end encryption to secure telemetry data.
Explanation
System Architecture
Metrum is designed as a decentralized system, with publishers and subscribers communicating directly with each other.
- Publishers: Devices or nodes that collect and transmit sensor data.
- Subscribers: Devices or nodes that receive and process sensor data.
Minimal Efficient Telemetry Reporting Using Mesh (METRUM) Status: Draft Version: 0.2
Abstract
This document specifies a protocol for sensor telemetry over Reticulum networks. It defines a publish-subscribe pattern using Reticulum's destination announce mechanism for discovery and standardized CBOR tags for efficient sensor data representation.
-
Introduction
This specification defines a protocol for sending telemetry data over Reticulum networks. It leverages standardized CBOR tags for structured sensor data representation and Reticulum's native capabilities for network transport, discovery, and security.
METRUM uses CBOR Tag 120 (IoT Data Point) as its primary data format, with Tag 103 (Geographic Coordinates) for location information when relevant. Together, these provide a complete representation for IoT telemetry that is both efficient and standardized.
-
Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Publisher: A node that produces telemetry data Subscriber: A node that consumes telemetry data IoT Data Point: A measurement value with associated metadata (timestamp, location) Geographic Coordinates: Location information in WGS-84 reference system
-
Protocol Overview
The protocol follows a publish-subscribe pattern:
- Publishers announce their presence with metadata describing available metrics
- Subscribers listen for announces and establish links to publishers
- Subscribers send subscription requests over links
- Publishers maintain subscriber lists and send telemetry data to subscribers
- Data is formatted using standardized CBOR tags
-
Publisher Behavior
4.1. Announce Mechanism
Publishers MUST create a Reticulum destination with appropriate identity. Publishers MUST announce periodically using CBOR-encoded app_data that includes:
- "type": Set to "telemetry"
- "metrics": Array of available metrics
- "version": Protocol version, currently "0.2"
4.2. Subscription Handling
Publishers MUST maintain a list of subscriber destinations. Upon receiving a subscription message, publishers SHOULD validate the request and add the subscriber to their list.
Publishers SHOULD remove subscribers from their list when the corresponding Reticulum link is broken.
- Subscriber Behavior
5.1. Discovery
Subscribers MUST register announce handlers to detect publishers. Subscribers SHOULD filter announces by app_data type field. The publisher's identity serves as the unique identifier for establishing connections.
5.2. Subscription
Subscribers MUST establish a link to desired publishers. Subscribers MUST send a subscription message containing:
- "subscribe": Boolean set to true
- "version": Protocol version, currently "0.2"
- Message Formats
6.1. Telemetry Data Structure
Each telemetry message MUST be a CBOR map containing:
- "metric": String name of the measurement
- "data": IoT Data Point (Tag 120) containing the measurement value and metadata
6.2. IoT Data Point (Tag 120)
METRUM uses CBOR Tag 120 to represent IoT Data Points as defined in its specification.
Tag 120 MUST be applied in one of two ways:
-
Simple format: 120(value) This indicates a data point with the current UTC time as timestamp and undefined location.
-
Array format: 120([value, timestamp_tag, location_tag]) Where:
- value: The measurement value (REQUIRED)
- timestamp_tag: Tag 1(epoch_time) (OPTIONAL)
- location_tag: Tag 103([lat, lon, ...]) (OPTIONAL)
If the timestamp is omitted or null, it MUST be interpreted as the current UTC time. If the location is omitted or null, it MUST be interpreted as undefined geographic coordinates.
6.3. Geographic Coordinates (Tag 103)
When location information is included, METRUM uses CBOR Tag 103 as defined in its specification.
Tag 103 MUST be applied to an array with 2-4 elements:
103([latitude, longitude, elevation, uncertainty])
Where:
-
latitude: Decimal degrees (positive = North) (REQUIRED)
-
longitude: Decimal degrees (positive = East) (REQUIRED)
-
elevation: Height in meters (OPTIONAL)
-
uncertainty: Location uncertainty in meters (OPTIONAL)
The coordinate reference system MUST be WGS-84. Omitting or setting elevation or uncertainty to null indicates these values are not provided.
6.4. Data Models and Examples
The following examples illustrate common telemetry data patterns using the CBOR tags:
6.4.1. Basic Measurement
A simple temperature reading without location:
{
"metric": "temperature",
"data": 120([23.5, 1(1500000000)])
}
6.4.2. Geo-tagged Measurement
A temperature reading with full location context:
{
"metric": "temperature",
"data": 120([23.5, 1(1500000000), 103([44.78659, 20.44890, 117, 5])])
}
Where the location array represents [latitude, longitude, elevation, uncertainty].
-
Protocol Evolution
This protocol is designed to evolve with Reticulum's capabilities. When Reticulum implements "group destinations" in future versions, METRUM will be extended to utilize this feature for more efficient multicast delivery of telemetry data to multiple subscribers.
-
Security Considerations
This protocol inherits security properties from Reticulum. All telemetry data is encrypted using Reticulum's mechanisms. Access control is provided through Reticulum's authentication capabilities.
-
References
9.1. Normative References
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC8428] Jennings, C., et al., "Sensor Measurement Lists (SenML)", RFC 8428, August 2018.
[RNS] Qvist, M., "Reticulum Network Stack", https://github.com/markqvist/Reticulum
[TAG120] Vidovic, D., "CBOR Tag 120 - Internet of Things Data Points", https://github.com/allthingstalk/cbor/blob/master/CBOR-Tag120-Internet-of-Things-Data-Points.md
[TAG103] Vidovic, D., "CBOR Tag 103 - Geographic Coordinates", https://github.com/allthingstalk/cbor/blob/master/CBOR-Tag103-Geographic-Coordinates.md
[WGS-84] National Imagery and Mapping Agency, "Department of Defense World Geodetic System 1984", NIMA TR8350.2, January 2000.