Skip to content

AkitaEngineering/Akita-Zmodem-MeshCore

Repository files navigation

Akita-Zmodem-MeshCore

This repository contains a Python implementation of a lightweight ZMODEM-like file transfer protocol that is tightly integrated with the MeshCore mesh networking client. The code is intended to be self‑contained, dependency‑free (other than MeshCore when used), and covered by an extensive unit test suite.

Development notes

  • The project follows PEP 8 style; run black/autopep8 or flake8 in the virtualenv before committing. A requirements-dev.txt is provided for the linter and test runner.
  • Use pytest (with pytest-asyncio) to execute the tests. The test harness used in CI also relies on pytest-timeout to prevent hanging tests; it's included in requirements-dev.txt.

Running tests (recommended workflow):

python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements-dev.txt
pytest -v

If tests hang locally, pytest-timeout enforces per-test time limits; you can adjust timeouts via --timeout=<seconds> when invoking pytest.

python -m venv .venv
source .venv/bin/activate
pip install -r requirements-dev.txt
pytest -q
  • All lint warnings have been cleared; contributions should remain free of E722/E701/unused-imports etc. autopep8 --in-place is handy for bulk fixes.

License: GPL v3

Akita-Zmodem-MeshCore is a robust file transfer utility developed by Akita Engineering (www.akitaengineering.com). It enables reliable file and directory transfers over low-bandwidth, high-latency MeshCore networks (based on ripplebiz/MeshCore) using the venerable Zmodem protocol.

This utility is designed for asynchronous operation, making it suitable for environments where network responsiveness can vary.

Key Features

  • Built‑in Zmodem Protocol: A fully self‑contained, Z‑modem‑like implementation lives in zmodem.py, so there is no requirement to install an external Zmodem library. The code handles handshakes, CRC32 framing, resumable transfers, per‑chunk port headers, and stale duplicate ACK/RESUME suppression for reliable operation over the mesh.
  • MeshCore Integration: Uses Python bindings for MeshCore networks (tested with fdlamotte/meshcore_py but compatible with any API providing MeshCore.create_*, mesh.subscribe, and mesh.commands.send_msg).
  • Async I/O with asyncio: Non‑blocking operations keep transfers responsive even on poor links.
  • File & Directory Support: Send files directly or zip directories on‑the‑fly; received zips are automatically extracted.
  • Chunk Header Handling: Data sent over the mesh is split into mesh_packet_chunk_size fragments; each fragment begins with an application port header so the receiver can reassemble correctly. The default is 184 bytes, matching the current MeshCore payload ceiling.
  • Configurable Timeouts: Automatic cancellation of stalled transfers.
  • JSON Configuration: Tweak ports, chunk sizes, MeshCore connection params, and more via akita_zmodem_meshcore_config.json or CLI overrides.
  • Robust CLI: Commands (send, receive, status, cancel) either run as a one‑off or the script can operate as a long‑running daemon.
  • Daemon Mode & Status: Run as a listener and query active transfers.
  • Cancellation & Safety: Cancel mid‑transfer and protect against unwanted overwrites.
  • Detailed Logging: Built‑in logging at INFO/DEBUG levels aids debugging and monitoring.
  • Operational Context: See USE_CASES.md for concrete deployment scenarios across UAS, agriculture, SAR, infrastructure, research, and remote maintenance.

Important Note on Dependencies

Because the Zmodem protocol is implemented internally, the only mandatory third‑party dependency is the meshcore Python library (to communicate with a MeshCore radio). You do not need to install any separate zmodem package; if one is present it will be ignored in favor of the built‑in implementation.

  • MeshCore Python Library – must expose the basic API used here (MeshCore.create_serial/create_tcp, mesh.subscribe, mesh.commands.send_msg, etc.). This library handles the low‑level radio/TCP transport.
  • Optional: tqdm for progress bars in CLI sessions (not required). If absent, the program falls back to plain logging.

All other functionality is self‑contained within the repository.

Installation

  1. Python 3.8+ is recommended.
  2. Clone the repository (or download the script).
  3. Create and activate a virtual environment (recommended):
    python -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
  4. Install the required Python libraries:
    pip install -r requirements.txt
    This installs meshcore plus the optional tqdm helper listed in requirements.txt. No external zmodem package is required.

Configuration

  1. Generate Configuration File: The configuration file akita_zmodem_meshcore_config.json will be created with default settings in the same directory as the script if it doesn't exist on the first run.

    python akita_zmodem_meshcore.py --help # Running with --help or any command will generate it
  2. Edit Configuration: Modify akita_zmodem_meshcore_config.json to suit your needs. Key settings include:

    • zmodem_app_port: An application-level port number used to distinguish Zmodem traffic over MeshCore.
    • mesh_packet_chunk_size: Maximum size of data chunks sent over the mesh network, including the prepended app-port header. The valid MeshCore-safe range is greater than the 2-byte header size and at most 184 bytes.
    • timeout: Transfer timeout in seconds.
    • mesh_connection_type: How to connect to your MeshCore device (serial or tcp).
    • mesh_serial_port, mesh_serial_baud: Settings for serial connection.
    • mesh_tcp_host, mesh_tcp_port: Settings for TCP connection.

    These MeshCore connection settings can also be overridden via CLI arguments. See docs/CONFIGURATION.md for more details.

Usage

The utility is controlled via command-line arguments.

python akita_zmodem_meshcore.py [OPTIONS] [COMMAND] [COMMAND_ARGS]

Global Options (Optional, override config file):

--config <path>          Path to JSON configuration file (created if missing)
--mesh-type [serial|tcp] Override connection type
--serial-port <PORT_PATH> (e.g., /dev/ttyUSB0, COM3)
--serial-baud <BAUDRATE>
--tcp-host <HOST_IP_OR_NAME>
--tcp-port <PORT_NUMBER>

Commands:

Run as a daemon (listener mode):

python akita_zmodem_meshcore.py
# (add connection args if not in config or to override)

Send a file or directory:

python akita_zmodem_meshcore.py send <destination_node_id> <path/to/file_or_dir>

<destination_node_id>: String identifier for the target MeshCore node (e.g., !aabbccdd or a name your MeshCore setup recognizes).

Receive a file or directory:

python akita_zmodem_meshcore.py receive <path/to/save_location> [--overwrite] [--directory]
  • --directory forces the path to be treated as a directory even if it does not yet exist or lacks a recognisable extension. The utility will also infer directory mode automatically when the target already exists and is a directory.

Note: For directory reception, provide the path where the directory's contents should be extracted.

Get transfer status:

python akita_zmodem_meshcore.py status <transfer_id>

Cancel a transfer:

python akita_zmodem_meshcore.py cancel <transfer_id>

See docs/USAGE.md for detailed command explanations and examples.

Example

# On Machine A (Sender):
# Ensure your config file is set up or use CLI overrides for connection:
# e.g., python akita_zmodem_meshcore.py --mesh-type serial --serial-port /dev/ttyUSB0

# Send a file to node with ID "!TargetNodeHexID"
python akita_zmodem_meshcore.py send "!TargetNodeHexID" my_document.txt

# On Machine B (Receiver - running in daemon mode):
# Start the listener (it will use its config for connection)
python akita_zmodem_meshcore.py

# Alternatively, to pre-designate where a file should go on Machine B:
# python akita_zmodem_meshcore.py receive received_files/my_document.txt [--overwrite]
# This command will wait for the specific transfer to complete.

Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues for bug reports and feature requests.
See CONTRIBUTING.md for more details.

License

This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.

About

This repository contains a Python implementation of a lightweight ZMODEM-like file transfer protocol that is tightly integrated with the MeshCore mesh networking client.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages