MicroMesh
MicroMesh is a small, dependency-free Meshtastic client for MicroPython. It talks to a
Meshtastic device over its serial API and implements the protobuf wire format directly,
so google.protobuf, threads, and pyserial are not required.
The initial release supports:
- serial
ToRadio/FromRadioframing and resynchronization; - the configuration handshake and a small in-memory node list;
- text, arbitrary data, and position packets;
- routing acknowledgements, node/user data, waypoints, and device metrics;
- familiar generated-protobuf methods:
SerializeToString,ParseFromString,CopyFrom,HasField,ClearField, andWhichOneof; - preservation of unknown protobuf fields for forward compatibility.
This is intentionally not a complete replacement for the desktop
meshtastic package. Configuration and admin
messages are currently returned as raw encoded bytes.
Install
From a checkout of this repository, install with a current mpremote:
mpremote mip install package.json
Alternatively, copy the micromesh directory to /lib on the board. After this
repository is published on GitHub it can also be installed as
mpremote mip install github:ORG/micromesh.
It can also be installed on CPython for development:
python -m pip install .
After the first PyPI release, install it by name with:
python -m pip install micromesh
Quick start
from machine import UART, Pin
from micromesh import PortNum, SerialInterface
uart = UART(1, baudrate=115200, tx=Pin(17), rx=Pin(16), timeout=0)
def received(packet):
if packet.WhichOneof("payload_variant") != "decoded":
return
if packet.decoded.portnum == PortNum.TEXT_MESSAGE_APP:
print("from !%08x:" % packet.from_, packet.decoded.payload.decode())
mesh = SerialInterface(uart, on_packet=received)
mesh.connect()
mesh.sendText("hello mesh")
while True:
mesh.poll()
The UART baud rate and pins depend on the attached Meshtastic device. poll() is
non-blocking when the UART is configured with timeout=0.
Ready-to-run wiring and code for the Seeed Studio XIAO RP2040, Raspberry Pi Pico, and
generic ESP32 boards are in examples/.
Direct messages accept either an integer or Meshtastic's hexadecimal node ID:
mesh.sendText("hello", destinationId="!a1b2c3d4", wantAck=True)
mesh.sendPosition(45.5152, -122.6784, altitude=15)
mesh.sendData(b"custom", portNum=PortNum.PRIVATE_APP)
Protobufs
Messages can be used without a radio:
from micromesh import Data, PortNum
data = Data(portnum=PortNum.TEXT_MESSAGE_APP, payload=b"hello")
encoded = data.SerializeToString()
decoded = Data().ParseFromString(encoded)
Generated-module-style imports are available as micromesh.mesh_pb2 and
micromesh.portnums_pb2 for easier porting from the desktop library.
Only the commonly useful schemas are modeled. Unknown fields survive a decode/encode
round trip, but their contents are not interpreted. A field named from is accessed as
packet.from_ because from is a Python keyword.
Development
python -m unittest discover -s tests
Releasing to PyPI
PyPI publishing uses GitHub Trusted Publishing, so no API token is stored in the
repository. Configure a pending publisher at
pypi.org/manage/account/publishing
with these values:
- PyPI project name:
micromesh - GitHub owner:
pdxlocations - Repository:
micromesh - Workflow:
release.yaml - Environment:
pypi
Keep the version in pyproject.toml, package.json, and micromesh/__init__.py in
sync. Push the change, create a matching GitHub release such as v0.1.0, and publish
the release. The workflow builds, validates, and uploads both the wheel and source
distribution.
The API protocol is defined by the
meshtastic/protobufs project. Update the
field declarations in micromesh/messages.py when adopting newer schemas.
manifest.py is also included for freezing the package into custom MicroPython firmware.