2026-06-09 22:26:36 +01:00
2026-06-09 16:10:37 -04:00
2026-06-09 14:11:30 -04:00
2026-06-08 20:22:45 -04:00
2025-10-24 13:36:22 +01:00

pyMC Repeater

Lightweight Python MeshCore repeater daemon built on pymc_core.

pyMC Repeater is designed to run continuously on low-power Linux hardware such as Raspberry Pi-class devices, Proxmox LXC containers, and network-attached radio modems. It forwards LoRa packets, exposes a web dashboard, and provides configuration tools for radio setup, policy management, monitoring, and integrations.

Contents

Overview

The repeater daemon runs as a background service and forwards LoRa packets using the pymc_core dispatcher and routing stack. The project favors a simple, hackable architecture:

  • CherryPy provides a lightweight HTTP server for the web UI and API.
  • The web interface supports setup, monitoring, logs, configuration, and updates.
  • Packet routing, policy checks, storage, sensors, GPS, MQTT, and optional pyMC_Glass integration are kept in modular components.
  • Hardware support covers direct SPI radios, CH341 USB-to-SPI adapters, pyMC TCP/USB modem firmware, and KISS serial modems.

Real-world deployment feedback is especially welcome. Dense networks, unusual hardware, and production-style installations are the best way to find the rough edges and make the repeater better for everyone.

Screenshots

Dashboard

Dashboard

Real-time packet statistics, neighbor discovery, and system status.

Statistics

Statistics

Historical statistics and performance metrics.

Supported Hardware

pyMC Repeater supports these radio backends:

  • SX1262 over Linux SPI: set radio_type: sx1262
  • SX1262 over CH341 USB-to-SPI: set radio_type: sx1262_ch341
  • pyMC TCP modem: set radio_type: pymc_tcp
  • pyMC USB-CDC modem: set radio_type: pymc_usb
  • KISS serial modem: set radio_type: kiss
  • No radio hardware: set radio_type: null for setup, testing, or API-only work

Caution

Compatibility

This project targets single-radio SX1262-class transceivers and supported modem integrations. It does not support UART-only HATs or SX1302/SX1303 concentrator boards.

Interface Status
Native SX1262 SPI radio Supported
CH341 USB-to-SPI bridge Supported
pyMC TCP modem Supported
pyMC USB-CDC modem Supported
KISS serial modem Supported
UART-only HATs Not supported
SX1302/SX1303 concentrator boards Not supported

The following devices have out-of-the-box presets or known support:

Device Name Platform TX Power Connection Radio Module Link
HackerGadgets uConsole uConsole / Raspberry Pi CM Up to 22 dBm SPI SX1262-class View
Zindello Industries UltraPeater Luckfox Up to 30 dBm SPI E22, E22P View
MeshSmith PiMesh-1W Raspberry Pi Up to 30 dBm SPI E22P View
MeshSmith EtherMesh-1W Network Up to 30 dBm TCP E22P View
Frequency Labs meshadv-mini Raspberry Pi Up to 30 dBm SPI E22 View
Frequency Labs meshadv Raspberry Pi Up to 30 dBm SPI E22 View

Always confirm pin mappings, antenna setup, regional frequency rules, and TX power limits before transmitting.

Installation

Install Git

sudo apt update
sudo apt install git -y

Clone The Repository

git clone https://github.com/rightup/pyMC_Repeater.git
cd pyMC_Repeater

Quick Install

sudo bash ./manage.sh install

The installer will:

  • Create a dedicated repeater service user with hardware access
  • Install application files to /opt/pymc_repeater
  • Create the configuration directory at /etc/pymc_repeater
  • Create the log directory at /var/log/pymc_repeater
  • Launch the interactive radio and hardware setup wizard
  • Install and enable the pymc-repeater systemd service

After installation:

# View live logs
sudo journalctl -u pymc-repeater -f

Open the web dashboard at:

http://<repeater-ip>:8000

Development Install

pip install -e .

For development tools:

pip install -e ".[dev]"

Configuration

The main configuration file is created during installation:

/etc/pymc_repeater/config.yaml

Setup Wizard

The web-based setup flow guides you through repeater identity, hardware selection, radio presets, and login setup.

Start Setup

Onboarding Step 1

Repeater Name

Onboarding Step 2

Hardware Type

Onboarding Step 3

Choose A Preset

Onboarding Step 5

TX Power

TX power defaults to 14 dBm and can be changed later.

TX Power Notice

Set A Password

Onboarding Step 6

Update TX settings

Radio Configuration

Run CAD Calibration

CAD Calibration

Reconfigure Radio And Hardware

To reconfigure radio and hardware settings after installation:

sudo bash setup-radio-config.sh /etc/pymc_repeater

You can also launch the management menu:

sudo ./manage.sh
sudo systemctl restart pymc-repeater

Optional pyMC_Glass Integration

pyMC Repeater supports an optional glass configuration section for pyMC_Glass control-plane integration. When enabled, the repeater sends periodic /inform payloads to pyMC_Glass, receives queued commands, and reports command results on the next inform cycle.

Minimal example:

glass:
  enabled: true
  base_url: "http://localhost:8080"
  inform_interval_seconds: 30

Policy Engine

Use the policy engine to create packet management rules from the web interface.

Policy

Example: Drop Channel packets over two hops

Policy Example

Upgrading

Web Interface

The web interface can upgrade an installation or switch branches.

Note

Docker installs cannot be upgraded or branch-switched from the web interface. Update the container image instead.

Upgrade

CLI

cd pyMC_Repeater
sudo bash ./manage.sh upgrade

The upgrade script will:

  • Pull the latest code from the main branch
  • Update application files
  • Upgrade Python dependencies if needed
  • Restart the service automatically
  • Preserve the existing configuration

Proxmox LXC Installation

pyMC Repeater can run inside a Proxmox LXC container using a CH341 USB-to-SPI adapter or a TCP modem. This is useful for headless, always-on deployments without dedicating a full Raspberry Pi.

Requirements

Software:

  • Proxmox VE 7.x or 8.x host
  • Internet access for the container

Hardware, choose one:

  • CH341 USB-to-SPI adapter with VID 1a86 and PID 5512, connected to the Proxmox host and wired to an SX1262-based LoRa module such as an Ebyte E22-900M30S
  • TCP modem, such as MeshSmith EtherMesh

One-Line Install

Run this command on the Proxmox host, not inside a container:

bash -c "$(curl -fsSL https://raw.githubusercontent.com/rightup/pyMC_Repeater/main/scripts/proxmox-install.sh)"

Replace main in the URL with another branch name if needed.

The installer will prompt for container settings and then:

  1. Download a Debian 12 LXC template.
  2. Create a privileged container with USB passthrough.
  3. Install a host-side udev rule for the CH341 device.
  4. Clone the repository and pre-seed CH341 GPIO pin mappings.
  5. Run manage.sh install inside the container.
  6. Display the dashboard URL.

Default Container Settings

Setting Default
Hostname pymc-repeater
RAM 1024 MB
Disk 4 GB
CPU cores 2
Bridge vmbr0
Storage local-lvm
Password pymc

After Installation

# Enter the container
pct enter <CTID>

# View service logs
journalctl -u pymc-repeater -f

# Manage the repeater
cd /opt/pymc_repeater
bash manage.sh

Open the dashboard at:

http://<container-ip>:8000

CH341 GPIO Pin Mapping

The Proxmox installer pre-configures CH341 GPIO pins for an E22 module. These are not Raspberry Pi BCM pin numbers:

Function CH341 GPIO Pi BCM Default
CS 0 21
RXEN 1 -1
Reset 2 18
Busy 4 20
IRQ 6 16

The installer also enables use_dio3_tcxo and use_dio2_rf for E22 modules.

Troubleshooting

  • USB device not found: confirm the CH341 is plugged into the Proxmox host and appears in lsusb -d 1a86:5512.

  • Permission denied on USB: the installer creates /etc/udev/rules.d/99-ch341.rules. Run udevadm trigger on the host if needed.

  • Container cannot see USB: verify USB passthrough lines exist in /etc/pve/lxc/<CTID>.conf:

    lxc.cgroup2.devices.allow: c 189:* rwm
    lxc.mount.entry: /dev/bus/usb dev/bus/usb none bind,optional,create=dir 0 0
    
  • NoBackendError for libusb: the installer installs libusb-1.0-0 automatically. If needed, run apt-get install libusb-1.0-0 inside the container.

Uninstallation

sudo bash ./manage.sh uninstall

The uninstaller will:

  • Stop and disable the systemd service
  • Remove the installation directory
  • Optionally remove configuration, logs, and user data
  • Optionally remove the service user account

The script prompts before each optional removal step.

Docker Compose

You can run pyMC Repeater in Docker using the published image.

Copy .env.example to .env before starting:

cp .env.example .env

Set GPIO_GID and SPI_GID from getent group gpio and getent group spi if your host values are different.

Default storage should use Docker named volumes. This avoids Portainer creating root-owned ./config and ./data bind mount folders on first start. If you want host bind mounts, use absolute host paths and pre-create/chown them to 15888:15888.

Do not mount ./config.yaml:/etc/pymc_repeater/config.yaml; Docker can create that source as a directory, which breaks startup.

Setup

  1. Copy .env.example to .env.
  2. Review .env and update PYMC_REPEATER_IMAGE, GPIO_GID, or SPI_GID if needed.
  3. Configure docker-compose.yml for your hardware and device paths.
  4. Uncomment the USB device mapping only if your host has that device path.
  5. Pull and start the container.
docker compose up -d

Example docker-compose.yml

services:
  pymc-repeater:
    image: ${PYMC_REPEATER_IMAGE:-pymcdev/pymc-repeater:main}
    container_name: pymc-repeater
    restart: unless-stopped
    ports:
      - 8000:8000

    devices:
      # SPI devices. Your paths may differ. Remove if not using SPI hardware.
      - /dev/spidev0.0
      - /dev/gpiochip0

      # USB devices. Uncomment/change only if needed.
      # - /dev/bus/usb/002:/dev/bus/usb/002

    cap_add:
      - SYS_RAWIO

    group_add:
      - "${GPIO_GID:-986}"
      - "${SPI_GID:-989}"
      - plugdev

    volumes:
      - ${PYMC_CONFIG_VOLUME:-pymc-repeater-config}:/etc/pymc_repeater
      - ${PYMC_DATA_VOLUME:-pymc-repeater-data}:/var/lib/pymc_repeater

volumes:
  pymc-repeater-config:
  pymc-repeater-data:

Roadmap

  • Public map integration: submit repeater location and details to a public map for discovery.
  • Remote administration over LoRa: manage repeater configuration from the mesh.
  • Trace request handling: respond to trace and diagnostic requests from the mesh network.

Contributing

Contributions are welcome.

  1. Fork the repository and clone your fork.

  2. Create a feature branch from dev:

    git checkout -b feature/your-feature-name dev
    
  3. Make your changes and test with real hardware when possible.

  4. Commit with a clear message:

    git commit -m "feat: describe your change"
    
  5. Push to your fork and open a pull request against dev.

Include a clear description, hardware tested, and any related issues.

Development Setup

# Install in development mode with dev tools (ruff, pytest, mypy, etc)
pip install -e ".[dev]"

# Install pre-commit hooks
pip install pre-commit
pre-commit install

# Run checks manually
pre-commit run --all-files

Hardware support for LoRa radio drivers is included in the base installation through pymc_core[hardware].

Pre-commit hooks will automatically:

  • Lint and auto-fix Python issues with Ruff
  • Validate formatting with Ruff formatter
  • Fix trailing whitespace and other file issues

Support

Disclaimer

This software has been tested on actual hardware, but it is provided "as is" without warranty of any kind, express or implied. No guarantee is made about performance, compatibility, or suitability for any particular purpose.

By using this software, you acknowledge and agree that:

  • You use it entirely at your own risk.
  • The author is not responsible for hardware damage, data loss, or system failures.
  • You are responsible for complying with local radio regulations and licensing requirements.
  • No support or warranty is guaranteed, though community assistance may be available.

This software is intended for educational and experimental use. Always test in a controlled environment before production deployment.

License

This project is licensed under the MIT License. See LICENSE for details.

S
Description
Languages
JavaScript 74.9%
Python 22.3%
Shell 2.8%