gcc, python3-dev, libjpeg-dev, zlib1g-dev are needed to compile
Pillow and pycryptodome from source on linux/arm/v7 (no pre-built
wheels available). Build deps are purged after pip install.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
In-container BLE reconnection is unreliable because bleak leaves stale
GATT notification handles after abnormal disconnect, and adapter power-
cycling from within Docker corrupts bleak's internal BlueZ manager state.
New approach:
- On BLE disconnect or keepalive failure, immediately mark as permanently
failed (no in-container reconnect attempts)
- Health endpoint returns 503, Docker healthcheck triggers container restart
- Docker entrypoint script disconnects stale BLE connections before app
starts, ensuring clean GATT state for bleak
This is reliable because:
- MeshCore.create_ble(address=...) works on fresh container starts
- The BlueZ daemon on the host maintains adapter state correctly
- Container restart is fast (~5s) and gives a truly clean BLE state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Integrate meshcore library's BLE connection (via bleak) as a third
transport option alongside serial and TCP. Priority: BLE > TCP > Serial.
Config: MC_BLE_ADDRESS and MC_BLE_PIN environment variables.
Docker: bluez/dbus packages, NET_ADMIN cap, D-Bus socket mount.
UI: transport type badge in navbar, transport_type in /api/status.
Watchdog: skip USB reset for BLE connections (same as TCP).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace two-container bridge architecture with single container.
Dockerfile adds udev for serial device support.
docker-compose.yml: one service with cgroup rules for ttyUSB/ttyACM,
SQLite DB path, backup settings, optional TCP mode.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added two new HTTP endpoints to meshcore-bridge for managing pending contacts
(contacts awaiting manual approval when manual_add_contacts mode is enabled):
New endpoints:
- GET /pending_contacts - List all pending contacts awaiting approval
- Parses meshcli output format: "Name: <hex_public_key>"
- Returns JSON array with {name, public_key} objects
- Includes raw_stdout for debugging
- POST /add_pending - Approve and add a pending contact
- Accepts JSON body: {"selector": "<name_or_pubkey>"}
- Validates selector is non-empty string
- Executes meshcli add_pending command via persistent session
Additional changes:
- Added curl to mc-webui Dockerfile for testing endpoints
- Updated README with Testing Bridge API section
- Included example curl commands and expected responses
Implementation notes:
- Uses existing MeshCLISession.execute_command() - no new processes
- Same persistent session and command queue architecture
- Consistent error handling with existing /cli endpoint
Enables future UI for manual contact approval workflow.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
BREAKING CHANGE: Switched from single-container to multi-container setup
This commit introduces a meshcore-bridge service that isolates USB device
access from the main application, resolving persistent USB timeout and
deadlock issues in Docker + VM environments.
Changes:
- Add meshcore-bridge/ - Lightweight HTTP API wrapper for meshcli
- Flask server exposes /cli endpoint (port 5001, internal only)
- Exclusive USB device access via --device flag
- Health check endpoint at /health
- Refactor app/meshcore/cli.py
- Replace subprocess calls with HTTP requests to bridge
- Add requests library dependency
- Better error handling for bridge communication
- Update docker-compose.yml
- Define meshcore-bridge and mc-webui services
- Create meshcore-net Docker network
- Add depends_on with health check condition
- Bridge gets USB device, main app uses HTTP only
- Modify Dockerfile
- Remove meshcore-cli installation from main app
- Lighter image without gcc dependencies
- Update config.py
- Add MC_BRIDGE_URL environment variable
- Remove meshcli_command property (no longer needed)
- Update documentation (README.md, .claude/instructions.md)
- Document 2-container architecture
- Add troubleshooting section for bridge
- Update prerequisites (no host meshcore-cli needed)
- Add architecture diagram in project structure
Benefits:
✅ Solves USB device locking after container restarts
✅ Restartable main app without USB reset
✅ Better separation of concerns
✅ Easier debugging (isolated meshcli logs)
✅ No manual USB recovery scripts needed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Moved Dockerfile and docker-compose.yml from docker/ to root directory for simpler workflow.
This allows running 'docker compose up' directly without -f flag.
Changes:
- Moved docker/Dockerfile -> Dockerfile
- Moved docker/docker-compose.yml -> docker-compose.yml
- Updated docker-compose.yml context and env_file paths
- Updated README.md with simplified Docker commands
- Updated CLAUDE_CODE_PROMPT.md project structure
- Moved .claude/instructions.md to root (from technotes/)
- Updated all documentation to reflect new structure
Now deployment is simpler:
docker compose up -d --build
instead of:
docker compose -f docker/docker-compose.yml up -d --build