A Docker-based bridge that exposes a TCP api to Bluetooth Low Energy (BLE) Meshtastic devices. Designed for use with MeshMonitor, but works with any tool that supports the Meshtastic TCP interface.
Features:
- BLE-to-TCP protocol translation
- Automatic reconnection on node reboots or disconnects (v1.3+)
- Optional config caching for faster reconnections (v1.4.0+)
- Configurable cache size limits for memory management (v1.4.0+)
- mDNS/Avahi autodiscovery for zero-configuration networking
- Automatic service registration and cleanup
- Graceful shutdown with proper resource cleanup
- Comprehensive test suite with CI/CD
meshmonitor-ble-bridge/
├── README.md # This file
├── QUICK_START.md # Get up and running fast
├── docker-compose.ble.yml # Docker Compose configuration
├── src/
│ ├── ble_tcp_bridge.py # Main bridge application
│ ├── Dockerfile # Container build instructions
│ └── .dockerignore # Docker build exclusions
└── docs/
├── CLAUDE_BLE_BRIDGE.md # Claude Code context & technical details
├── BLE_TCP_BRIDGE_ANALYSIS.md # Comprehensive technical analysis
├── README_BLE_BRIDGE.md # User documentation
└── DEPLOY_BLE_BRIDGE.md # Deployment guide
- Docker installed
- Bluetooth adapter (built-in or USB)
- Meshtastic device with BLE enabled
docker pull ghcr.io/yeraze/meshtastic-ble-bridge:latestdocker run --rm --privileged \
-v /var/run/dbus:/var/run/dbus \
ghcr.io/yeraze/meshtastic-ble-bridge:latest --scanbluetoothctl
pair AA:BB:CC:DD:EE:FF # Replace with your device MAC
trust AA:BB:CC:DD:EE:FF
exitdocker run -d --name ble-bridge \
--privileged \
-p 4403:4403 \
--restart unless-stopped \
-v /var/run/dbus:/var/run/dbus \
-v /var/lib/bluetooth:/var/lib/bluetooth:ro \
-v /etc/avahi/services:/etc/avahi/services \
ghcr.io/yeraze/meshtastic-ble-bridge:latest AA:BB:CC:DD:EE:FFThe bridge will automatically register an mDNS service for network autodiscovery.
Point MeshMonitor to:
- IP:
<bridge-host-ip> - Port:
4403
Or use mDNS autodiscovery to find the bridge automatically on your network:
# Test mDNS discovery
avahi-browse -rt _meshtastic._tcpThe bridge advertises itself as _meshtastic._tcp.local. with TXT records containing:
bridge=bleport=4403ble_address=<device-mac>version=1.4.0
- Quick Start: See
QUICK_START.mdfor step-by-step setup - Deployment: See
docs/DEPLOY_BLE_BRIDGE.mdfor production deployment - User Guide: See
docs/README_BLE_BRIDGE.mdfor usage and troubleshooting - Technical Details: See
docs/CLAUDE_BLE_BRIDGE.mdfor architecture and development - Analysis: See
docs/BLE_TCP_BRIDGE_ANALYSIS.mdfor comprehensive protocol analysis
This package includes docs/CLAUDE_BLE_BRIDGE.md which provides complete context for working on the BLE bridge with Claude Code. Simply:
- Extract this tarball on your target machine
- Open the directory in Claude Code
- Reference
docs/CLAUDE_BLE_BRIDGE.mdfor full technical context
┌──────────────┐ TCP 4403 ┌───────────────┐
│ MeshMonitor │ ←────────────────→│ BLE Bridge │
└──────────────┘ └───────┬───────┘
↑ │ BLE
│ mDNS autodiscovery ┌───────▼───────┐
└─────────────────────────────│ Meshtastic │
└───────────────┘
The bridge translates between:
- BLE: Raw protobuf bytes on Meshtastic GATT characteristics
- TCP: Framed protocol
[0x94][0xC3][LEN][PROTOBUF]
And provides:
- mDNS: Automatic service discovery via Avahi (
_meshtastic._tcp.local.)
For MeshMonitor users, use the included docker-compose.ble.yml as an overlay:
# Copy to MeshMonitor directory
cp docker-compose.ble.yml /path/to/meshmonitor/
# Create .env file
echo "BLE_ADDRESS=AA:BB:CC:DD:EE:FF" > /path/to/meshmonitor/.env
# Start both services
cd /path/to/meshmonitor
docker compose -f docker-compose.yml -f docker-compose.ble.yml up -dsudo systemctl start bluetoothContainer needs --privileged flag for BLE access
- Ensure device BLE is enabled
- Move closer (BLE range ~10-30m)
- Check device not connected to another app
- Verify bridge listening on
0.0.0.0:4403 - Check firewall allows port 4403
- Test with:
telnet <bridge-ip> 4403
The bridge now automatically handles node reboots and BLE disconnections:
Internal Reconnection:
- Detects disconnections immediately via callback and polling
- Attempts up to 5 reconnections with exponential backoff (2s, 4s, 8s, 16s, 32s)
- Continues operation if reconnection succeeds
Container Restart:
- If all reconnection attempts fail, the container exits with error code 1
- Docker's
restart: unless-stoppedpolicy automatically restarts the container - Fresh container attempts clean connection to the device
Recommended Docker Configuration:
services:
ble-bridge:
restart: unless-stopped # Auto-restart on failure
healthcheck:
test: ["CMD-SHELL", "netstat -tln | grep -q :4403 || exit 1"]
interval: 30s
timeout: 10s
retries: 3Monitoring: Check logs to see reconnection activity:
docker logs -f ble-bridgeLook for:
⚠️ BLE device disconnected- Initial disconnect detected🔄 Reconnection attempt X/5- Retry in progress✅ Reconnected successfully- Success💀 Failed to reconnect- Container will exit and restart
For issues, questions, or contributions:
- MeshMonitor: https://github.com/Yeraze/meshmonitor
- Meshtastic: https://meshtastic.org
BSD-3-Clause (same as MeshMonitor)