From 8b6ab086fdadc7ca1c8f73402b11a290598f173a Mon Sep 17 00:00:00 2001 From: Matthias Guillitte Date: Mon, 17 Aug 2026 13:45:51 +0200 Subject: [PATCH] better alerts and connected_components --- orchestrateur/external_display_manager.py | 4 +-- orchestrateur/main.py | 40 ++++++++++++++++++++--- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/orchestrateur/external_display_manager.py b/orchestrateur/external_display_manager.py index 2598ed9..00631ca 100644 --- a/orchestrateur/external_display_manager.py +++ b/orchestrateur/external_display_manager.py @@ -50,7 +50,7 @@ class DisplayManager: self.screens[name] = url if self._on_screens_change_callback: - self._on_screens_change_callback(self.screens) + self._on_screens_change_callback(self.screens, is_removed=False, modified_name=name) print(f"[DisplayManager] 📺 Screen registered: {name} -> {url}") elif state_change == ServiceStateChange.Removed: @@ -58,7 +58,7 @@ class DisplayManager: print(f"[DisplayManager] ❌ Screen disconnected: {name}") self.screens.pop(name, None) if self._on_screens_change_callback: - self._on_screens_change_callback(self.screens) + self._on_screens_change_callback(self.screens, is_removed=True, modified_name=name) def set_on_screens_change_callback(self, callback): """Set a callback function to be called when screens are added or removed.""" diff --git a/orchestrateur/main.py b/orchestrateur/main.py index d241c6e..ec421d9 100644 --- a/orchestrateur/main.py +++ b/orchestrateur/main.py @@ -50,6 +50,12 @@ def save_connected_component(component_id: str, component_type: str): db.execute(DB_PATH, sql, (str(component_id), str(component_type), current_time)) print(f"[DB] Component saved/updated -> ID: {component_id}, Type: {component_type}, Timestamp: {current_time}") +def remove_connected_component(component_id: str): + """Removes a component from the database (blocking sync worker).""" + sql = "DELETE FROM connected_components WHERE id = ?;" + db.execute(DB_PATH, sql, (str(component_id),)) + print(f"[DB] Component removed -> ID: {component_id}") + def get_connected_components(): """Returns a list of all connected components from the database.""" sql = "SELECT id, type, timestamp FROM connected_components;" @@ -213,11 +219,21 @@ async def cloud_mqtt_listener_task(): "data": payload }) await asyncio.sleep(0.1) + # === LCD DISPLAY === -def on_screens_change(screens): +def on_screens_change(screens, is_removed: bool, modified_name: str): """Callback for when screens are added or removed.""" log(f"[DisplayManager] Screens changed. Current screens: {list(screens.keys())}") rgb_lcd_manager.set_external_screen_count(len(screens)) + + # Add Or remove from database of connected components + # 1. Extract id from name (assuming format "smartwave-epaper-._displaytcp._tcp.local") + display_id = modified_name.split("-")[-1].split(".")[0] + if is_removed: + remove_connected_component(display_id) + else: + save_connected_component(display_id, "external_display") + display_manager.set_on_screens_change_callback(on_screens_change) def update_lcd_microwave_count(): @@ -283,11 +299,18 @@ alert_manager = None def on_new_alert(alert: Alert): # Sends to cloud server alert_dict = alert.to_dict() - alert_dict["orchestrator_id"] = DEVICE_ID + + logs_list = get_systemd_logs(lines=200, service_name="smartwave") + + payload = { + "orchestrator_id": DEVICE_ID, + "alert": alert_dict, + "logs": logs_list + } response = requests.post( "https://smartwave.matthiasg.dev/alert", - json=alert_dict, + json=payload, ) response.raise_for_status() @@ -612,10 +635,13 @@ async def handle_telemetry_request(endpoint: str): # 2. Unpack temperature and humidity ambient_temp, ambient_humidity = temp_hum.get_temperature_and_humidity_with_retry() + # Unpack microwave states + microwave_states_snapshot = {mw_id: mw_state.to_dict() for mw_id, mw_state in microwave_states.items()} + # 3. Build the telemetry payload (returns a JSON string) telemetry_payload = payloads.telemetry_payload( device_id=DEVICE_ID, - microwave_states=microwave_states.to_dict(), + microwave_states=microwave_states_snapshot, button_state=button_state, cloud_alert=cloud_alert, gps_data=gps.get_gps_data(), @@ -641,10 +667,14 @@ async def handle_telemetry_request(endpoint: str): ) response.raise_for_status() + + set_cloud_alert(False) # Clear any previous cloud alert on success + print(f"[Telemetry] Successfully dispatched telemetry (HTTP {response.status_code}).") except requests.exceptions.RequestException as req_err: print(f"[Telemetry] HTTP Request failed to {endpoint}: {req_err}") + set_cloud_alert(True) # Set cloud alert on HTTP failure except Exception as e: print(f"[Telemetry] Error handling telemetry request: {e}") @@ -730,6 +760,8 @@ async def main(): # Start mDNS Display discovery await display_manager.start() + save_connected_component(DEVICE_ID, "orchestrateur") + async_event_queue = asyncio.Queue() display_update_queue = asyncio.Queue()