Version: 1.1.0
Adds reliable, targeted node-to-node file transfers to Meshtastic LoRa networks.
Contents:
AkitaMeshZmodem— Arduino library embedding a non-blocking ZModem engine.ZmodemModule— Meshtastic firmware module for in-firmware operation.
License: GNU GPLv3 — see LICENSE.
- Zero External Dependencies: The ZModem protocol stack is entirely built-in (
src/utility/ZModemEngine), eliminating reliance on external, unstable, or missing ZModem libraries. - Non-Blocking Operation: The implementation is designed to run seamlessly within the main Meshtastic firmware loop, ensuring the device remains responsive, routing packets, and managing the mesh network during transfers.
- Targeted Sending: Files are sent directly to a specified Node ID, not broadcast across the entire mesh, which is efficient and network-friendly.
- Reliable Protocol: Utilizes simplified ZModem state handling and CRC checks optimized for robust, 8-bit clean LoRa links.
- Dedicated Port Handling: Uses separate, configurable Meshtastic PortNums for command initiation and data transmission to prevent conflicts.
- Filesystem Agnostic: Uses the standard Arduino
FSAPI for compatibility with SPIFFS, LittleFS, or SD cards.
- Hardware: Meshtastic-compatible devices (ESP32-based recommended) with sufficient flash memory for the firmware and a filesystem (SPIFFS/LittleFS) to store files.
- Required Arduino Libraries (Minimal):
Meshtastic(Official Meshtastic device library/firmware source)StreamUtils(A common utility library, included in PlatformIO/Arduino)FS(Part of the ESP32 core)
- Install Dependencies: Ensure
MeshtasticandStreamUtilsare installed via the Arduino Library Manager or PlatformIO. - Install AkitaMeshZmodem Library:
- PlatformIO (Recommended): Add the library directly to your
platformio.inidependencies:lib_deps = meshtastic/Meshtastic bblanchon/ArduinoStreamUtils https://github.com/AkitaEngineering/Meshtastic-Zmodem.git - Arduino IDE: Download this repository as a ZIP and install it via the Arduino IDE's
Sketch->Include Library->Add .ZIP Library...option.
- PlatformIO (Recommended): Add the library directly to your
This is the preferred method for running file transfers as a service and requires building the Meshtastic firmware from source using PlatformIO.
- Create the library folder: Inside your Meshtastic firmware checkout, create a library folder that preserves the same relative include layout used by this repository:
lib/Akita_Meshtastic_Zmodem/src/ lib/Akita_Meshtastic_Zmodem/src/utility/ - Copy only the runtime library files: Copy these files into that folder:
Keep the
src/AkitaMeshZmodem.h src/AkitaMeshZmodem.cpp src/AkitaMeshZmodemConfig.h src/utility/ZModemEngine.h src/utility/ZModemEngine.cpputility/subdirectory intact so includes such asutility/ZModemEngine.hcontinue to resolve. - Do not copy the standalone stub files: These files exist in this repository only to let the library compile outside the full Meshtastic firmware tree and should not overwrite firmware-provided headers:
src/main.cpp src/globals.h src/module.h src/mesh-core.h src/serial-interface.h - Install the Meshtastic module: Copy
src/modules/ZmodemModule.handsrc/modules/ZmodemModule.cppinto the Meshtastic firmware'ssrc/modules/directory. - Register the module: Edit the main firmware file (
src/mesh-core.cppor similar) to include the module header and instantiate the module, allowing it to hook into the main loop:#include "modules/ZmodemModule.h" // ... modules.push_back(new ZmodemModule(*this));
- Confirm firmware-side prerequisites:
- The real Meshtastic firmware must provide
Filesystem,Log,Module,MeshInterface, and the packet delivery path used byhandleReceived(). - The filesystem must be mounted before
ZmodemModule::setup()runs. AKZ_ZMODEM_COMMAND_PORTNUMandAKZ_ZMODEM_DATA_PORTNUMmust not collide with any other application ports in your firmware build.
- The real Meshtastic firmware must provide
- If you integrate the library without
ZmodemModule: Forward all packets received onAKZ_ZMODEM_DATA_PORTNUMtoakitaZmodem.processDataPacket(packet)during any active transfer. The sender also depends on responses received on the data port.
Control is handled by sending specific text commands to the device on the Command Port (AKZ_ZMODEM_COMMAND_PORTNUM, default 250).
| Action | Format | Example (using CLI) |
|---|---|---|
| Start Send | SEND:!NodeID:/local/file.bin |
meshtastic --sendtext "SEND:!a1b2c3d4:/test.txt" --portnum 250 |
| Start Receive | RECV:/save/path.bin |
meshtastic --sendtext "RECV:/received.bin" --portnum 250 |
When integrating into custom code:
begin(mesh, Filesystem, &Serial): Initialize the engine and set up the transport streams.loop(): Must be called continuously in your main loop to process the ZModem state machine.processDataPacket(MeshPacket& packet): CRITICAL. Forward every packet received on the Data Port (AKZ_ZMODEM_DATA_PORTNUM) while a transfer is active. The sender needs control responses on this port just as much as the receiver needs file data.
Two helper scripts have been added under tools/ to simplify exercising the
module on a host machine:
serial_proxy.py– creates a PTY and proxies it to a real serial device. Run your host-side serial tool against the PTY to talk to the board. Requirespython3andpyserial.auto_xmodem_test.py– automation harness that invokessz --xmodemand validates the received file. Requirespython3andszfromlrzsz.
These tools are for local protocol experimentation only. The default library
and module flow documented in this repository is the Meshtastic ZModem path
driven by SEND: and RECV: commands over the command and data ports.
The PlatformIO project has been configured to allow the code to compile with
only stubbed versions of the Meshtastic and StreamUtils libraries (see
lib/…); this makes it possible to verify the ZModem engine builds even
when the real dependencies are not available. To perform a full build the
real Meshtastic package from the Arduino registry is required.
- Fixed several protocol/parser bugs in the internal ZModem engine (
src/utility/ZModemEngine.cpp) including proper ZDLE-escaping and header scanning for robustness over noisy links. - Resolved stream-handling issues in the library wrapper (
src/AkitaMeshZmodem.cpp), including buffering multiple data-port packets while the engine drains the stream. - Corrected the module and example integration so packets on the data port are forwarded during both send and receive operations.
- The example sketch
examples/Basic_Transfer/Basic_Transfer.inowas corrected for proper packet handling, command parsing, and transfer-state cleanup. - Stub headers and library stubs were improved so the library can be compiled and verified with PlatformIO even when the full Meshtastic firmware is not present.
These fixes were verified by building the project with PlatformIO on ESP32 (env: esp32dev). End-to-end radio validation on real Meshtastic nodes is still recommended before treating the transfer path as field-proven. See the quick build steps in USAGE.md.