Sending updates to external screen + RGB LCD
This commit is contained in:
+54
-8
@@ -11,9 +11,13 @@ from shared.logging import log
|
||||
from shared.cookingState import CookingStates
|
||||
from shared.lora_device import LoraCommands
|
||||
from shared.alerts import AlertManager, Alert, AlertType
|
||||
from sensors import ultrasonicRanger, temp_hum, button, camera, buzzer
|
||||
from sensors import ultrasonicRanger, temp_hum, button, camera, buzzer, rgb_lcd
|
||||
from lib.systemd_logs import get_systemd_logs
|
||||
from external_display_manager import DisplayManager
|
||||
from rgb_lcd_manager import RGBLCDManager
|
||||
|
||||
rgb_lcd.setRGB(255, 255, 255, brightness=0.8)
|
||||
rgb_lcd.setText("SmartWave\nOrchestrateur")
|
||||
|
||||
# --- CONFIGURATION CONSTANTS ---
|
||||
DISPLAY_DEBOUNCE_SECONDS = 3 # Seconds to wait after first change before broadcasting
|
||||
@@ -69,6 +73,7 @@ display_update_queue = None
|
||||
|
||||
def notify_display_update():
|
||||
"""Safely adds an update event timestamp to the display update queue."""
|
||||
|
||||
if display_update_queue is not None:
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
@@ -79,18 +84,21 @@ def notify_display_update():
|
||||
def set_cloud_alert(state: bool):
|
||||
"""Setter for cloud_alert that triggers a display update when changed."""
|
||||
global cloud_alert
|
||||
|
||||
if cloud_alert != state:
|
||||
cloud_alert = state
|
||||
notify_display_update()
|
||||
update_lcd_cloud_alert()
|
||||
|
||||
# Global state trackers
|
||||
microwave_states = {"2": MicrowaveState("2", on_change_callback=notify_display_update)}
|
||||
button_state = False
|
||||
cloud_alert = False # Global status flag for screen / UI display
|
||||
cloud_alert = None # Global status flag for screen / UI display
|
||||
async_event_queue = None
|
||||
|
||||
# Display Manager instance
|
||||
display_manager = DisplayManager(endpoint_path="/api/display")
|
||||
rgb_lcd_manager = RGBLCDManager(rgb_lcd, brightness=0.8, interval=5.0)
|
||||
|
||||
# Async synchronization trackers for MQTT IR sensors responses
|
||||
ir_data_cache = {} # mw_id -> dict of IR readings
|
||||
@@ -112,6 +120,10 @@ mqtt_client.connect()
|
||||
mqtt_client.subscribe(config.MQTT_TOPIC_SENSOR, qos=config.MQTT_QOS)
|
||||
mqtt_client.subscribe(config.MQTT_TOPIC_HELLO, qos=config.MQTT_QOS)
|
||||
|
||||
# DHT sensor warmup
|
||||
time.sleep(2) # Allow GrovePi MCU and DHT sensor circuits to settle post-service start
|
||||
temp_hum.get_temperature_and_humidity() # Dummy read to flush initial NaN state
|
||||
|
||||
if hasattr(mqtt_client._client, "loop_start"):
|
||||
mqtt_client._client.loop_start()
|
||||
print("[MQTT Local] Paho background loop started.")
|
||||
@@ -192,6 +204,23 @@ async def cloud_mqtt_listener_task():
|
||||
"data": payload
|
||||
})
|
||||
await asyncio.sleep(0.1)
|
||||
# === LCD DISPLAY ===
|
||||
def on_screens_change(screens):
|
||||
"""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))
|
||||
display_manager.set_on_screens_change_callback(on_screens_change)
|
||||
|
||||
def update_lcd_microwave_count():
|
||||
"""Updates the LCD with the current number of connected microwaves."""
|
||||
global microwave_states
|
||||
count = len(microwave_states)
|
||||
rgb_lcd_manager.set_microwave_count(count)
|
||||
|
||||
def update_lcd_cloud_alert():
|
||||
"""Updates the LCD with the current cloud connectivity status."""
|
||||
global cloud_alert
|
||||
rgb_lcd_manager.set_cloud_alert(cloud_alert)
|
||||
|
||||
async def display_broadcast_worker_task():
|
||||
"""
|
||||
@@ -199,6 +228,8 @@ async def display_broadcast_worker_task():
|
||||
Waits until DISPLAY_DEBOUNCE_SECONDS have passed since the first queued update
|
||||
before sending state to all connected screens.
|
||||
"""
|
||||
global display_update_queue, microwave_states, cloud_alert
|
||||
|
||||
print("[Display Worker] Started debounced display broadcast worker.")
|
||||
while True:
|
||||
# Block until the FIRST update reminder arrives in the queue
|
||||
@@ -331,7 +362,7 @@ async def handle_new_dish(microwave_id, detected_height):
|
||||
# 6. Dispatch cloud request task
|
||||
asyncio.create_task(request_cloud_cooking_plan(microwave_id, sensors_data))
|
||||
except asyncio.TimeoutError:
|
||||
print(f"[{microwave_id}] ⚠️ Timeout waiting for MQTT IR data from ESP32.")
|
||||
print(f"[{microwave_id}] Timeout waiting for MQTT IR data from ESP32.")
|
||||
sensors_data["ir_initial_temp"] = None
|
||||
sensors_data["ir_ambient_temp"] = None
|
||||
finally:
|
||||
@@ -376,6 +407,8 @@ async def request_cloud_cooking_plan(microwave_id, sensors_data):
|
||||
return
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
set_cloud_alert(False) # Clear any previous cloud alert
|
||||
|
||||
# JSON extraction
|
||||
res_json = response.json()
|
||||
@@ -400,12 +433,11 @@ async def request_cloud_cooking_plan(microwave_id, sensors_data):
|
||||
c_temp = plan.get("target_temp")
|
||||
|
||||
if c_time is None or c_power is None or c_temp is None:
|
||||
print(f"[{microwave_id}] ❌ Invalid plan received: {res_json}")
|
||||
print(f"[{microwave_id}] Invalid plan received: {res_json}")
|
||||
microwave_states[microwave_id].set_state(MicrowaveState.IDLE)
|
||||
return
|
||||
|
||||
print(f"[{microwave_id}] Cloud Plan Received! Starting microwave: {c_time}s @ {c_power}W")
|
||||
cloud_alert = False # Reset alert flag on success
|
||||
microwave_states[microwave_id].set_state(MicrowaveState.COOKING)
|
||||
|
||||
if config.DEBUG:
|
||||
@@ -417,6 +449,8 @@ async def request_cloud_cooking_plan(microwave_id, sensors_data):
|
||||
payloads.mqtt_cooking_config(microwave_id, c_time, c_power, c_temp),
|
||||
qos=config.MQTT_QOS
|
||||
)
|
||||
|
||||
microwave_states[microwave_id].set_cooking_start_time(time.time())
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
@@ -436,7 +470,7 @@ async def request_cloud_cooking_plan(microwave_id, sensors_data):
|
||||
|
||||
# Executed only if all 3 retries failed
|
||||
print(f"[{microwave_id}] All cloud retries failed. Setting global alert flag.")
|
||||
cloud_alert = True
|
||||
set_cloud_alert(True)
|
||||
microwave_states[microwave_id].set_state(MicrowaveState.DONE)
|
||||
|
||||
# --- MAIN LOGIC TASKS ---
|
||||
@@ -458,6 +492,7 @@ async def process_messages_task():
|
||||
print(f"[LoRa] Microwave {mw_id} state changed to: {n_state}")
|
||||
|
||||
microwave_states[mw_id].set_cooking_state(n_state)
|
||||
update_lcd_microwave_count() # Update the LCD with new microwave count
|
||||
|
||||
if n_state in (CookingStates.DONE, CookingStates.STIRRING_REQUIRED, CookingStates.ALERT):
|
||||
beats = 5 if n_state == CookingStates.ALERT else (1 if n_state == CookingStates.STIRRING_REQUIRED else 3)
|
||||
@@ -465,7 +500,17 @@ async def process_messages_task():
|
||||
if n_state == CookingStates.IDLE and microwave_states.get(mw_id).state == MicrowaveState.COOKING:
|
||||
microwave_states[mw_id].set_state(MicrowaveState.DONE)
|
||||
print(f"[{mw_id}] Cooking finished. Waiting for user to remove dish.")
|
||||
|
||||
if "action" in data.get("data", {}):
|
||||
action = data["data"]["action"]
|
||||
if action == LoraCommands.COOKING_UPDATE:
|
||||
mw_id = data["data"].get("id")
|
||||
if mw_id in microwave_states:
|
||||
state_info = data["data"]
|
||||
microwave_states[mw_id].set_cooking_state(state_info.get("cooking_state", microwave_states[mw_id].cooking_state))
|
||||
microwave_states[mw_id].set_cooking_estimated_remaining_time(state_info.get("estimated_remaining_time", microwave_states[mw_id].cooking_estimated_remaining_time))
|
||||
microwave_states[mw_id].set_paused(state_info.get("paused", microwave_states[mw_id].paused))
|
||||
else:
|
||||
print(f"[LoRa] Unhandled action received: {action} with data: {data['data']}")
|
||||
elif source == "MQTT":
|
||||
topic = msg["topic"]
|
||||
|
||||
@@ -487,7 +532,8 @@ async def process_messages_task():
|
||||
component_id,
|
||||
on_change_callback=notify_display_update
|
||||
)
|
||||
notify_display_update()
|
||||
notify_display_update() # Update the external screens
|
||||
update_lcd_microwave_count() # Update the LCD with new microwave count
|
||||
|
||||
mqtt_client.publish(
|
||||
config.MQTT_TOPIC_HELLO,
|
||||
|
||||
Reference in New Issue
Block a user