TCP proxy for MeshCore companion radios
Project description
MeshCore Proxy
A TCP proxy that enables remote access to a locally-connected MeshCore companion radio.
Overview
MeshCore Proxy connects to a MeshCore radio via USB Serial or Bluetooth LE and exposes it over TCP, allowing remote clients to interact with the radio as if it were directly connected.
┌─────────────────┐ USB/BLE ┌──────────────────┐
│ MeshCore Radio │ ◄──────────────► │ meshcore-proxy │
│ (Companion FW) │ │ │
└─────────────────┘ │ TCP :5000 │
└────────┬─────────┘
│
┌───────────────────────────────┼───────────────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ MeshCore-CLI │ │ Home Assistant│ │ MeshCore App │
└──────────────┘ └──────────────┘ └──────────────┘
Supported clients:
Installation
From PyPI
pip install meshcore-proxy
Using pipx (isolated environment)
pipx install meshcore-proxy
From source
git clone --recursive https://github.com/rgregg/meshcore-proxy.git
cd meshcore-proxy
pip install -e .
Docker
# Pull the published image (recommended)
docker pull ghcr.io/rgregg/meshcore-proxy:latest
# Or build locally
docker build -t meshcore-proxy .
Quick Start
USB Serial
# Linux
meshcore-proxy --serial /dev/ttyUSB0
# macOS
meshcore-proxy --serial /dev/cu.usbmodem101
# Windows
meshcore-proxy --serial COM3
Bluetooth LE
# Linux/Windows - use MAC address
meshcore-proxy --ble 12:34:56:78:90:AB
# macOS - use UUID or device name (MAC addresses not supported)
meshcore-proxy --ble 7921236E-065C-0C7B-C04D-7F60E849DC47
meshcore-proxy --ble MeshCore-07BA3987
Connect a Client
Once the proxy is running, connect clients to localhost:5000:
meshcore-cli --tcp localhost:5000
Usage
meshcore-proxy [OPTIONS]
Connection (one required):
--serial PORT Serial port path (e.g., /dev/ttyUSB0)
--ble ADDR BLE device address (see platform notes below)
Server options:
--host ADDR TCP bind address (default: 0.0.0.0)
--port PORT TCP port (default: 5000)
Serial options:
--baud RATE Serial baud rate (default: 115200)
BLE options:
--ble-pin PIN BLE pairing PIN (default: 123456)
Logging options:
--quiet Suppress non-error output
--log-events Log event summaries
--log-events-verbose Log full event details with hex payloads
--json Output event logs as JSON
--debug Enable debug logging
BLE Address Format by Platform
| Platform | Address Format | Example |
|---|---|---|
| Linux | MAC address | 12:34:56:78:90:AB |
| Windows | MAC address | 12:34:56:78:90:AB |
| macOS | UUID or device name | 7921236E-065C-0C7B-C04D-7F60E849DC47 or MeshCore-07BA3987 |
macOS uses Core Bluetooth which does not expose MAC addresses. Use the device UUID (found via BLE scanning tools) or the device name broadcast by the radio.
Event Logging
The proxy decodes and displays MeshCore protocol events for debugging and monitoring.
Summary Mode
meshcore-proxy --serial /dev/ttyUSB0 --log-events
-> CMD_APPSTART
<- SELF_INFO
-> CMD_DEVICE_QUERY
<- DEVICE_INFO
-> CMD_GET_CONTACTS
<- CONTACT_START
<- CONTACT_END
Verbose Mode
meshcore-proxy --serial /dev/ttyUSB0 --log-events-verbose
-> CMD_APPSTART [13 bytes]: 01032020202020206d63636c69
<- SELF_INFO [66 bytes]: 05011616bfac8cd412f2e401...
-> CMD_GET_BATTERY [1 bytes]: 14
<- BATTERY [11 bytes]: 0cfc101600000064000000
JSON Mode
meshcore-proxy --serial /dev/ttyUSB0 --log-events --json
{"direction": "TO_RADIO", "packet_type": "CMD_APPSTART", "packet_type_raw": 1}
{"direction": "FROM_RADIO", "packet_type": "SELF_INFO", "packet_type_raw": 5}
Running with Docker
USB Serial
# Linux
docker run -d \
--name meshcore-proxy \
--device=/dev/ttyUSB0 \
-p 5000:5000 \
ghcr.io/rgregg/meshcore-proxy:latest \
--serial /dev/ttyUSB0
# macOS
docker run -d \
--name meshcore-proxy \
--device=/dev/cu.usbmodem101 \
-p 5000:5000 \
ghcr.io/rgregg/meshcore-proxy:latest \
--serial /dev/cu.usbmodem101
Bluetooth LE (Linux only)
BLE in Docker requires Linux with BlueZ. It does not work on macOS or Windows Docker.
# Requires host network and privileges for Bluetooth access
docker run -d \
--name meshcore-proxy \
--net=host \
--privileged \
-v /var/run/dbus:/var/run/dbus:ro \
ghcr.io/rgregg/meshcore-proxy:latest \
--ble 12:34:56:78:90:AB
Docker Compose
# USB Serial
docker compose --profile serial up -d
# BLE (set address in environment)
BLE_ADDRESS=12:34:56:78:90:AB docker compose --profile ble up -d
View Logs
docker logs -f meshcore-proxy
Running from Source
# Clone with submodules
git clone --recursive https://github.com/rgregg/meshcore-proxy.git
cd meshcore-proxy
# Or initialize submodules if already cloned
git submodule update --init --recursive
# Run directly
PYTHONPATH=src:meshcore_py/src python3 -m meshcore_proxy.cli \
--serial /dev/ttyUSB0 --log-events
Configuration Examples
Home Assistant Integration
Configure the MeshCore Home Assistant integration to connect via TCP:
- Host: IP address of machine running the proxy
- Port: 5000 (or your custom port)
Running as a System Service (Linux)
Create /etc/systemd/system/meshcore-proxy.service:
[Unit]
Description=MeshCore Proxy
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/meshcore-proxy --serial /dev/ttyUSB0 --log-events
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable meshcore-proxy
sudo systemctl start meshcore-proxy
Troubleshooting
Permission denied on serial port (Linux)
Add your user to the dialout group:
sudo usermod -aG dialout $USER
# Log out and back in for changes to take effect
Port already in use
Use a different port:
meshcore-proxy --serial /dev/ttyUSB0 --port 5001
BLE connection fails
- Ensure Bluetooth is enabled and the device is in range
- macOS: Use UUID or device name, not MAC address
- Linux: You may need
sudoor add user tobluetoothgroup - PIN-protected devices: Pair at the OS level first (System Preferences on macOS,
bluetoothctlon Linux), then the proxy will use the existing pairing
Radio not responding
- Check that the radio is running companion firmware (not repeater/room server)
- Verify the serial port/BLE address is correct
- Try power cycling the radio
Requirements
- Python 3.10+
- MeshCore companion radio with USB or BLE firmware
Development
Building from Source
git clone --recursive https://github.com/rgregg/meshcore-proxy.git
cd meshcore-proxy
pip install -e ".[dev]"
Running Tests
pytest
Creating a Release
This project uses setuptools-scm for automatic versioning based on git tags.
Version format: Tags should follow the pattern vX.Y.Z or vX.Y.Z-alpha (e.g., v0.4.0, v0.4.0-alpha)
Release process:
- Ensure all changes are committed and pushed
- Create and push a version tag:
git tag v0.4.0-alpha git push origin v0.4.0-alpha
- GitHub Actions will automatically:
- Build the package with the version from the tag
- Publish to PyPI
- Build and publish Docker images to GHCR
Version resolution:
- On a tagged commit: uses the exact tag version (e.g.,
v0.4.0-alpha→0.4.0a0) - Between tags: uses a dev version (e.g.,
0.4.0a1.dev2for 2 commits afterv0.4.0-alpha)
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file meshcore_proxy-0.3.3a0.tar.gz.
File metadata
- Download URL: meshcore_proxy-0.3.3a0.tar.gz
- Upload date:
- Size: 23.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8ca013804d9c9ed11420ee4911e552f323ed4db5d6ebf1d52e945739211126e2
|
|
| MD5 |
8fa3725d64ad24fb3bbbf70ff1ce97aa
|
|
| BLAKE2b-256 |
3657b5f895d5913da90894a10eb924ee51bafd3f4f50bae6ad4efb379964b879
|
File details
Details for the file meshcore_proxy-0.3.3a0-py3-none-any.whl.
File metadata
- Download URL: meshcore_proxy-0.3.3a0-py3-none-any.whl
- Upload date:
- Size: 14.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4eae83737b49e9d8f21a699ea049d5b1c4cd6015e7292ac387adc5681a874822
|
|
| MD5 |
a24e0fe64682a0bcb1cc751ace895493
|
|
| BLAKE2b-256 |
836fd50c85bbafaa2c857da5f4de398b85ba0252bd430da9abb7d2e8a7ede3ba
|