mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-03-28 17:42:45 +01:00
feat: Auto-detect serial port from /dev/serial/by-id/
When MC_SERIAL_PORT=auto, bridge scans /dev/serial/by-id/ and: - Uses the device if exactly one found - Fails with helpful message if multiple devices (list provided) - Fails if no devices found docker-compose.yml now uses device_cgroup_rules instead of explicit device mapping, allowing auto-detection inside the container. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,10 +5,11 @@
|
||||
# MeshCore Device Configuration
|
||||
# ============================================
|
||||
|
||||
# Serial port path (use /dev/serial/by-id for stable device names)
|
||||
# Find your device: ls /dev/serial/by-id/
|
||||
# Example: usb-Espressif_Systems_heltec_wifi_lora_32_v4__16_MB_FLASH__2_MB_PSRAM__90706984A000-if00
|
||||
MC_SERIAL_PORT=/dev/serial/by-id/[YOUR_DEVICE_ID]
|
||||
# Serial port path
|
||||
# Use "auto" for automatic detection (recommended if only one USB device)
|
||||
# Or specify manually: /dev/serial/by-id/usb-xxx or /dev/ttyUSB0
|
||||
# Find available devices: ls /dev/serial/by-id/
|
||||
MC_SERIAL_PORT=auto
|
||||
|
||||
# Your MeshCore device name (used for .msgs file)
|
||||
# Use "auto" for automatic detection from meshcli (recommended)
|
||||
|
||||
@@ -68,11 +68,15 @@ For detailed feature documentation, see the [User Guide](docs/user-guide.md).
|
||||
```
|
||||
|
||||
**Required changes in .env:**
|
||||
- `MC_SERIAL_PORT=/dev/serial/by-id/<your-device-id>`
|
||||
- `MC_SERIAL_PORT=auto` (recommended) or `/dev/serial/by-id/<your-device-id>`
|
||||
- `MC_DEVICE_NAME=auto` (recommended) or your device name
|
||||
- `TZ=Europe/Warsaw` (optional, set your timezone)
|
||||
|
||||
**Note:** With `MC_DEVICE_NAME=auto`, the system automatically detects your device name from meshcli. This is the recommended setting as it ensures the `.msgs` file always matches your actual device name.
|
||||
**Note:** With `auto` settings, the system automatically detects:
|
||||
- **Serial port** from `/dev/serial/by-id/` (works if only one USB device connected)
|
||||
- **Device name** from meshcli prompt (ensures `.msgs` file matches actual device)
|
||||
|
||||
If you have multiple USB serial devices, run `ls /dev/serial/by-id/` and specify `MC_SERIAL_PORT` explicitly.
|
||||
|
||||
**Leave these as default:**
|
||||
```bash
|
||||
|
||||
@@ -6,14 +6,17 @@ services:
|
||||
dockerfile: Dockerfile
|
||||
container_name: meshcore-bridge
|
||||
restart: unless-stopped
|
||||
devices:
|
||||
- "${MC_SERIAL_PORT}:${MC_SERIAL_PORT}"
|
||||
# Grant access to all ttyUSB devices (major 188) for auto-detection
|
||||
# This allows MC_SERIAL_PORT=auto to work without specifying device upfront
|
||||
device_cgroup_rules:
|
||||
- 'c 188:* rmw'
|
||||
volumes:
|
||||
- "${MC_CONFIG_DIR}:/root/.config/meshcore:rw"
|
||||
- "/dev:/dev"
|
||||
environment:
|
||||
- MC_SERIAL_PORT=${MC_SERIAL_PORT}
|
||||
- MC_SERIAL_PORT=${MC_SERIAL_PORT:-auto}
|
||||
- MC_CONFIG_DIR=/root/.config/meshcore
|
||||
- MC_DEVICE_NAME=${MC_DEVICE_NAME}
|
||||
- MC_DEVICE_NAME=${MC_DEVICE_NAME:-auto}
|
||||
- TZ=${TZ:-UTC}
|
||||
networks:
|
||||
- meshcore-net
|
||||
|
||||
@@ -36,12 +36,71 @@ app = Flask(__name__)
|
||||
socketio = SocketIO(app, cors_allowed_origins="*", async_mode='gevent')
|
||||
|
||||
# Configuration
|
||||
MC_SERIAL_PORT = os.getenv('MC_SERIAL_PORT', '/dev/ttyUSB0')
|
||||
MC_CONFIG_DIR = os.getenv('MC_CONFIG_DIR', '/config')
|
||||
MC_DEVICE_NAME = os.getenv('MC_DEVICE_NAME', 'meshtastic')
|
||||
DEFAULT_TIMEOUT = 10
|
||||
RECV_TIMEOUT = 60
|
||||
|
||||
# Serial port detection
|
||||
SERIAL_BY_ID_PATH = Path('/dev/serial/by-id')
|
||||
SERIAL_PORT_SOURCE = "config" # Will be updated by detect_serial_port()
|
||||
|
||||
|
||||
def detect_serial_port() -> str:
|
||||
"""
|
||||
Auto-detect serial port from /dev/serial/by-id/.
|
||||
|
||||
Returns:
|
||||
Path to detected serial device
|
||||
|
||||
Raises:
|
||||
RuntimeError: If no device found or multiple devices without explicit selection
|
||||
"""
|
||||
global SERIAL_PORT_SOURCE
|
||||
|
||||
env_port = os.getenv('MC_SERIAL_PORT', 'auto')
|
||||
|
||||
# If explicit port specified (not "auto"), use it directly
|
||||
if env_port and env_port.lower() != 'auto':
|
||||
logger.info(f"Using configured serial port: {env_port}")
|
||||
SERIAL_PORT_SOURCE = "config"
|
||||
return env_port
|
||||
|
||||
# Auto-detect from /dev/serial/by-id/
|
||||
logger.info("Auto-detecting serial port...")
|
||||
|
||||
if not SERIAL_BY_ID_PATH.exists():
|
||||
raise RuntimeError(
|
||||
"No serial devices found: /dev/serial/by-id/ does not exist. "
|
||||
"Make sure a MeshCore device is connected via USB."
|
||||
)
|
||||
|
||||
devices = list(SERIAL_BY_ID_PATH.iterdir())
|
||||
|
||||
if len(devices) == 0:
|
||||
raise RuntimeError(
|
||||
"No serial devices found in /dev/serial/by-id/. "
|
||||
"Make sure a MeshCore device is connected via USB."
|
||||
)
|
||||
|
||||
if len(devices) == 1:
|
||||
device_path = str(devices[0])
|
||||
logger.info(f"Auto-detected serial port: {device_path}")
|
||||
SERIAL_PORT_SOURCE = "detected"
|
||||
return device_path
|
||||
|
||||
# Multiple devices found - list them and fail
|
||||
device_list = '\n - '.join(str(d.name) for d in devices)
|
||||
raise RuntimeError(
|
||||
f"Multiple serial devices found. Please specify MC_SERIAL_PORT in .env:\n"
|
||||
f" - {device_list}\n\n"
|
||||
f"Example: MC_SERIAL_PORT=/dev/serial/by-id/{devices[0].name}"
|
||||
)
|
||||
|
||||
|
||||
# Detect serial port at startup
|
||||
MC_SERIAL_PORT = detect_serial_port()
|
||||
|
||||
class MeshCLISession:
|
||||
"""
|
||||
Manages a persistent meshcli subprocess session.
|
||||
@@ -608,6 +667,7 @@ def health():
|
||||
return jsonify({
|
||||
'status': session_status,
|
||||
'serial_port': MC_SERIAL_PORT,
|
||||
'serial_port_source': SERIAL_PORT_SOURCE,
|
||||
'advert_log': str(meshcli_session.advert_log_path) if meshcli_session else None,
|
||||
'device_name': device_name,
|
||||
'device_name_source': name_source
|
||||
|
||||
Reference in New Issue
Block a user