mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-03-28 17:42:45 +01:00
fix(bridge): Replace polling with msg_subscribe for real-time messages
Critical fixes based on user feedback:
1. **Remove auto-recv polling (30s interval)**
- Polling with 'recv' doesn't fetch NEW messages, only reads from .msgs
- Wasteful - creates unnecessary command traffic
2. **Add msg_subscribe for real-time message reception**
- meshcli's msg_subscribe enables automatic message events
- Messages arrive via EventType.CHANNEL_MSG_RECV events
- No polling needed - truly asynchronous
3. **Make TZ configurable via .env instead of hardcoded**
- Changed docker-compose.yml: TZ=${TZ:-UTC}
- Added TZ=Europe/Warsaw to .env.example
- Users can now set their own timezone
4. **Remove unused shlex import**
- Not needed after switching to manual double-quote wrapping
Technical details:
- msg_subscribe sends subscription command to meshcli at init
- meshcli then emits events when messages arrive
- Events trigger TTY errors (harmless - meshcli tries to print_above)
- Messages are still saved to .msgs file by meshcli core
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
12
.env.example
12
.env.example
@@ -13,7 +13,7 @@ MC_SERIAL_PORT=/dev/serial/by-id/usb-Espressif_Systems_heltec_wifi_lora_32_v4__1
|
||||
MC_DEVICE_NAME=MarWoj
|
||||
|
||||
# MeshCore configuration directory (where .msgs file is stored)
|
||||
MC_CONFIG_DIR=/root/.config/meshcore
|
||||
MC_CONFIG_DIR=/home/marek/.config/meshcore
|
||||
|
||||
# ============================================
|
||||
# Application Settings
|
||||
@@ -30,7 +30,7 @@ MC_INACTIVE_HOURS=48
|
||||
# ============================================
|
||||
|
||||
# Directory for storing archived messages
|
||||
MC_ARCHIVE_DIR=/mnt/archive/meshcore
|
||||
MC_ARCHIVE_DIR=/home/marek/.config/meshcore/archive
|
||||
|
||||
# Enable automatic daily archiving at midnight
|
||||
MC_ARCHIVE_ENABLED=true
|
||||
@@ -50,3 +50,11 @@ FLASK_PORT=5000
|
||||
|
||||
# Debug mode (true/false) - use false in production
|
||||
FLASK_DEBUG=false
|
||||
|
||||
# ============================================
|
||||
# System Configuration
|
||||
# ============================================
|
||||
|
||||
# Timezone for container logs (default: UTC)
|
||||
# Examples: Europe/Warsaw, America/New_York, Asia/Tokyo
|
||||
TZ=Europe/Warsaw
|
||||
|
||||
@@ -14,7 +14,7 @@ services:
|
||||
- MC_SERIAL_PORT=${MC_SERIAL_PORT}
|
||||
- MC_CONFIG_DIR=/root/.config/meshcore
|
||||
- MC_DEVICE_NAME=${MC_DEVICE_NAME}
|
||||
- TZ=Europe/Warsaw
|
||||
- TZ=${TZ:-UTC}
|
||||
networks:
|
||||
- meshcore-net
|
||||
healthcheck:
|
||||
@@ -48,7 +48,7 @@ services:
|
||||
- FLASK_HOST=${FLASK_HOST:-0.0.0.0}
|
||||
- FLASK_PORT=${FLASK_PORT:-5000}
|
||||
- FLASK_DEBUG=${FLASK_DEBUG:-false}
|
||||
- TZ=Europe/Warsaw
|
||||
- TZ=${TZ:-UTC}
|
||||
env_file:
|
||||
- .env
|
||||
depends_on:
|
||||
|
||||
@@ -18,7 +18,6 @@ import time
|
||||
import json
|
||||
import queue
|
||||
import uuid
|
||||
import shlex
|
||||
from pathlib import Path
|
||||
from flask import Flask, request, jsonify
|
||||
|
||||
@@ -74,14 +73,10 @@ class MeshCLISession:
|
||||
self.stderr_thread = None
|
||||
self.stdin_thread = None
|
||||
self.watchdog_thread = None
|
||||
self.auto_recv_thread = None
|
||||
|
||||
# Shutdown flag
|
||||
self.shutdown_flag = threading.Event()
|
||||
|
||||
# Auto-recv interval (seconds) - periodic message sync
|
||||
self.auto_recv_interval = 30
|
||||
|
||||
# Start session
|
||||
self._start_session()
|
||||
|
||||
@@ -114,9 +109,6 @@ class MeshCLISession:
|
||||
self.watchdog_thread = threading.Thread(target=self._watchdog, daemon=True, name="watchdog")
|
||||
self.watchdog_thread.start()
|
||||
|
||||
self.auto_recv_thread = threading.Thread(target=self._auto_recv, daemon=True, name="auto-recv")
|
||||
self.auto_recv_thread.start()
|
||||
|
||||
# Initialize session settings
|
||||
time.sleep(0.5) # Let meshcli initialize
|
||||
self._init_session_settings()
|
||||
@@ -128,7 +120,7 @@ class MeshCLISession:
|
||||
raise
|
||||
|
||||
def _init_session_settings(self):
|
||||
"""Configure meshcli session for advert logging"""
|
||||
"""Configure meshcli session for advert logging and message subscription"""
|
||||
logger.info("Configuring meshcli session settings")
|
||||
|
||||
# Send configuration commands directly to stdin (bypass queue for init)
|
||||
@@ -136,8 +128,9 @@ class MeshCLISession:
|
||||
try:
|
||||
self.process.stdin.write('set json_log_rx on\n')
|
||||
self.process.stdin.write('set print_adverts on\n')
|
||||
self.process.stdin.write('msg_subscribe\n')
|
||||
self.process.stdin.flush()
|
||||
logger.info("Session settings applied: json_log_rx=on, print_adverts=on")
|
||||
logger.info("Session settings applied: json_log_rx=on, print_adverts=on, msg_subscribe")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to apply session settings: {e}")
|
||||
|
||||
@@ -284,32 +277,6 @@ class MeshCLISession:
|
||||
|
||||
logger.info("watchdog thread exiting")
|
||||
|
||||
def _auto_recv(self):
|
||||
"""Thread: Periodically call recv to sync messages in background"""
|
||||
logger.info(f"auto-recv thread started (interval: {self.auto_recv_interval}s)")
|
||||
|
||||
# Wait a bit before first recv to let session initialize
|
||||
time.sleep(5)
|
||||
|
||||
while not self.shutdown_flag.is_set():
|
||||
try:
|
||||
# Execute recv command via internal queue
|
||||
logger.debug("Auto-recv: fetching new messages")
|
||||
result = self.execute_command(['recv'], timeout=RECV_TIMEOUT)
|
||||
|
||||
if result['success']:
|
||||
logger.debug("Auto-recv: messages synced successfully")
|
||||
else:
|
||||
logger.warning(f"Auto-recv failed: {result.get('stderr', 'unknown error')}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Auto-recv error: {e}")
|
||||
|
||||
# Wait for next interval (or until shutdown)
|
||||
self.shutdown_flag.wait(self.auto_recv_interval)
|
||||
|
||||
logger.info("auto-recv thread exiting")
|
||||
|
||||
def _is_advert_json(self, line):
|
||||
"""Check if line is a JSON advert"""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user