discover · compare · collections · requirements · contribute · feed · watching · stats · help with your tokens
Vapmuz/Mocktastic · source
Snapshot 1 · 2026-11-04T18:50:48Z · C · MIT
Content fingerprint
33266f81f52da1afd03a6a8e73a621d073c39d55402f589319b79d18327a391bGitHub description at capture
Custom client implementation in C++ of Meshtastic for ArduinoIDE and ESP32 (Lilygo T3 v1.6.1).
README at capture
= Mocktastic Mocktastic is a small, customizable Meshtastic-compatible LoRa client for ESP32 boards using ArduinoIDE environment. It is an educational and experimental implementation, not a fork of the official Meshtastic firmware. The project demonstrates how to build and decode Meshtastic packets in C++, and includes a working environmental-sensor example. The firmware has two compile-time modes: * *DECODER* provides an interactive serial shell for receiving, decoding, and sending text messages on configured Meshtastic channels and direct messages. * *SENSOR* turns the board into a DHT22 temperature and humidity sensor. It can send measurements and respond to `/dht` messages on its configured private channel. The implementation targets the LilyGO T3 LoRa32 V1.6.1 (ESP32-PICO and SX1276) and is intended to be adapted to other compatible ESP32/LoRa hardware. == Dependencies installed The project uses MBDTLS for the cryptographic part during the test phase and Nano-Protobuf as a lightweight protobuf encoder. The tests are written using Doctest's lightweight C++ tests. == Repository layout The repository root contains `meshtastic_decoder/`, which holds the firmware and host-side tests: [cols="1,3",options="header"] |=== |File or directory |Purpose |`meshtastic_decoder/meshtastic_decoder.ino` |Arduino entry point, board integration, radio setup, and compile-time mode selection. |`meshtastic_decoder/functions.h`, `functions.cpp` |General-purpose packet, byte, and string helpers. |`meshtastic_decoder/crypto.h`, `crypto.cpp` |Cryptographic operations used by the client, including AES and X25519. |`meshtastic_decoder/meshtastic.h`, `meshtastic.cpp` |Higher-level Meshtastic packet handling, encryption, and Protobuf payloads. |`meshtastic_decoder/lora_shell.h`, `lora_shell.cpp` |Shell command parsing and high-level message operations; a good starting point when extending the client. |`meshtastic_decoder/keys.h` |Channel and node identity configuration. |`meshtastic_decoder/nanopb_meshtastic/` |Nanopb runtime and generated Meshtastic Protobuf definitions. |`meshtastic_decoder/mbedtls/` |The bundled mbedTLS sources used by host-side tests. |`meshtastic_decoder/test/` |Doctest-based unit tests for the platform-independent logic. |=== == Build and run the host tests I used Python's `unittest` approach as a model for testing individual, predictable units of logic. The project keeps protocol and utility logic separate from hardware effects so it can be exercised on a development machine. The tests themselves are written with the lightweight doctest framework and compile with bundled test dependencies. From `meshtastic_decoder`, run: [source,shell] ---- cd meshtastic_decoder make test ---- The Makefile builds and runs the tests as one step. Tests cover the platform-independent functions, cryptography, Meshtastic packet handling, and shell parsing; changes to radio or sensor behavior should also be checked on the target hardware. To build the API documentation, install Doxygen and Graphviz, then run `make doxygen` from `meshtastic_decoder/`; the generated documentation is written to `meshtastic_decoder/docs/html/`. == Creating a Mocktastic node === Requirements You need an ESP32 board and a Semtech SX1276-family LoRa radio. The SENSOR variant also requires a DHT22. The tested board is the LilyGO T3 LoRa32 V1.6.1, which integrates the ESP32 and LoRa radio. Install Arduino IDE, download or clone this repository, and open `meshtastic_decoder/meshtastic_decoder.ino`. Install these libraries through the Arduino Library Manager: * LoRa by Sandeep Mistry * Adafruit Unified Sensor * DHT sensor library by Adafruit open `build_opt.h` and put your hard-coded filepath. It should result like this: "Hard/coded/path/.../Mocktastic/meshtastic_decoder/nanopb_meshtastic/src" === LoRa pins Check your board's specifications to identify the corresponding pins. The following mapping is for the LilyGO T3 V1.6.1: [cols="2,1",options="header"] |=== |SX1276 signal |LilyGO T3 V1.6.1 GPIO |VCC |3.3 V |GND |GND |SCK |5 |MISO |19 |MOSI |27 |NSS |18 |NRESET |23 |DIO0 |26 |=== Enter the pins for your board in the LoRa pin definitions in `meshtastic_decoder/meshtastic_decoder.ino`: [source,cpp] ---- #define LORA_SCK 5 #define LORA_MISO 19 #define LORA_MOSI 27 #define LORA_SS 18 #define LORA_RST 23 #define LORA_DIO0 26 ---- === Regional radio presets Use the following table as a reference for Meshtastic radio presets. Confirm that your selected preset and frequency are supported in your region. [cols="2,2,1,1,1,1,1",options="header"] |=== |Radio preset |Alternative name |Data rate |SF / symbols |Coding rate |Bandwidth |Link budget |Short Range / Turbo |Short Turbo |21.88 kbps |7 / 128 |4/5 |500 kHz |140 dB |Short Range / Fast |Short Fast |10.94 kbps |7 / 128 |4/5 |250 kHz |143 dB |Short Range / Slow |Short Slow |6.25 kbps |8 / 256 |4/5 |250 kHz |145.5 dB |Medium Range / Fast |Medium Fast |3.52 kbps |9 / 512 |4/5 |250 kHz |148 dB |Medium Range / Slow |Medium Slow |1.95 kbps |10 / 1024 |4/5 |250 kHz |150.5 dB |Long Range / Turbo |Long Turbo |1.34 kbps |11 / 2048 |4/8 |500 kHz |150 dB |Long Range / Fast |Long Fast |1.07 kbps |11 / 2048 |4/5 |250 kHz |153 dB |Long Range / Moderate |Long Moderate |0.34 kbps |11 / 2048 |4/8 |125 kHz |156 dB |Long Range / Slow (deprecated) |Long Slow |0.18 kbps |12 / 4096 |4/8 |125 kHz |158.5 dB |=== The sketch's default is EU Medium Fast, configured as follows: [source,cpp] ---- LoRa.begin(869525024); LoRa.setSpreadingFactor(9); LoRa.setSignalBandwidth(250E3); LoRa.setCodingRate4(5); LoRa.setSyncWord(0x2B); LoRa.setPreambleLength(16); LoRa.enableCrc(); ---- Always verify local radio regulations before transmitting. In the Meshtastic documentation's *Overview* page, use *Radio Settings* and its *Frequency Slot Calculator* to select a channel and slot and determine the corresponding frequency. Use that frequency in the sketch and make sure it matches the other nodes. === Configure `keys.h` Before compiling, configure `PublicChannel`, `PrivateChannel`, `Admn`, and `Device` in `meshtastic_decoder/keys.h`: * For `PublicChannel`, enter the name and key of the public channel used at the selected frequency. The channel name corresponds to the radio preset (for example, `MediumFast`). * For `PrivateChannel`, enter the name and key of the private channel used for messages. * For `Admn`, enter the name or node ID and public key of the main node from which you will read messages. Do not put a private key in this entry. * For `Device`, enter this node's name, public key, and private key. Read the channel configuration and node details using the Meshtastic software connected to the relevant node. The `Channel` structure contains `name` and `key`; `Friend` contains `name` and `publicKey`; and `User` contains `name`, `publicKey`, and `privateKey`, in that order. Keys must be hexadecimal strings. Meshtastic may provide them in Base64; convert them to hexadecimal with `b64StrToHexStr()` before adding them to the configuration. Use your own credentials and keep private keys and channel keys secret. Do not publish them in a public repository. === Select the firmware variant The sketch selects its mode at compile time. Near the top of `meshtastic_decoder/meshtastic_decoder.ino`, keep `DECODER` defined for the serial shell, or replace it with `SENSOR` for the DHT22 sensor variant: [source,cpp] ---- #define DECODER ---- For the sensor build, replace that line with: [source,cpp] ---- #define SENSOR ---- Build and upload the sketch with Arduino IDE for your selected ESP32 board. === LoRa shell (DECODER) The DECODER variant is operated over the serial connection. Open the serial monitor at 115200 baud. Its commands are: [cols="1,3",options="header"] |=== |Command |Description |`/echo <text>` |Print text to the serial console. |`/pub <text>` |Send a Meshtastic packet on the public channel. |`/cantine <text>` |Send a Meshtastic packet on the private channel. |`/admn <text>` |Send a private direct message to ADMIN. |`/r` |Repeat the previous command. |`/rssi` |Show the current LoRa RSSI. |`/pwr17 <value>` |Set LoRa transmit power. |`/gain <value>` |Set LoRa gain. |`/help` |Show the command help. |`/send_key` |Start direct messaging by sending this node's public key. |`/raw <text>` |Send a prepared packet for testing. |=== For example, send `/pub 42 is the answer` to write on the public channel. To send `hello, world!` on the private channel, use `/cantine hello, world!`. To enable direct messages with `Admn`, first send `/send_key`. This sends this node's public key so that the official Meshtastic node can establish a private conversation. Then send a direct message with `/admn hello, world!`. === SENSOR variant The SENSOR variant has no interactive shell. It can only be controlled by sending a Meshtastic message on the private channel configured in `keys.h`. Send `/dht` on that channel to make the sensor measure temperature and humidity; it sends the result back as a text message on the same channel. Connect the DHT22 data pin to GPIO 21. A battery is also required for standalone operation. == Extending the client Keep protocol and parsing logic separate from hardware effects where possible. The portable logic is exercised by host-side tests, while the `.ino` sketch handles radio, serial, GPIO, and sensor interactions. For a new shell command, follow the existing pattern in `meshtastic_decoder/lora_shell.h` and `meshtastic_decoder/lora_shell.cpp`: add the command to the parser and command enum, then handle it in the dispatcher in `meshtastic_decoder/meshtastic_decoder.ino`. For higher-level packet operations, start with the functions in `lora_shell` and the interfaces in `meshtastic.h`; use `functions.h` for lower-level helpers. Run `make test` from `meshtastic_decoder/` after changing platform-independent logic. Hardware behavior still needs to be verified on the target board and against compatible Meshtastic nodes. == Scope and limitations This code is a learning and prototyping project. It has limited field testing, does not provide the reliability or power efficiency of the official Meshtastic firmware, and is not recommended for safety-critical or production use. Its SENSOR battery life, channel handling, and regional radio configuration may need further work for a particular application.