From 988cb7958c2bbc09bd974d0a1a7afdd5d2977cb9 Mon Sep 17 00:00:00 2001 From: Matthias Guillitte Date: Fri, 7 Aug 2026 16:50:14 +0200 Subject: [PATCH] Better cooking_state_temperature_provider --- micro_ondes/esp_lora/main.py | 84 +++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/micro_ondes/esp_lora/main.py b/micro_ondes/esp_lora/main.py index ff265cc..cd12d71 100644 --- a/micro_ondes/esp_lora/main.py +++ b/micro_ondes/esp_lora/main.py @@ -36,6 +36,7 @@ defrost_mode = False current_temp = [None, None] last_temp = [None, None] temperature_asked = False +last_temp_request_time = 0 PING_PAYLOAD = { @@ -88,7 +89,7 @@ def lora_hardware_thread(): # 1. Send periodic heartbeat if now - last_heartbeat_time >= config.LORA_HEARTBEAT_INTERVAL: last_heartbeat_time = now - print("\n[LoRa Thread] Sending Heartbeat...") + log("\n[LoRa Thread] Sending Heartbeat...") if lora: lora.send(PING_PAYLOAD) @@ -104,36 +105,44 @@ def lora_hardware_thread(): # --- COOKING STATE CALLBACKS --- def cooking_state_temperature_provider(): - global current_temp, last_temp, temperature_asked, uart_device - - def temp_is_none(temp): - return temp is None or temp[0] is None or temp[1] is None - - # Return the current temperature if available, - # otherwise return the last recorded temperature - # and request a new reading from the WiFi board. - if temp_is_none(current_temp): - if temp_is_none(last_temp): - temps = (0.0, 0.0) - print("[CookingState] No temperature data available. Returning default (0.0, 0.0).") - else: - temps = [last_temp[0], last_temp[1]] - print(f"[CookingState] Returning last known temperature: {temps}") + global current_temp, last_temp, temperature_asked, last_temp_request_time, uart_device + + def temp_is_invalid(temp): + return ( + temp is None + or not isinstance(temp, (list, tuple)) + or len(temp) < 2 + or temp[0] is None + or temp[1] is None + ) + + # 1. Check for UART request timeout (reset lock if 3 seconds pass without a response) + now = time.time() + if temperature_asked and (now - last_temp_request_time > 3): + print("[CookingState] Temperature request timed out. Retrying UART request...") + temperature_asked = False + + # 2. Trigger new UART request if idle + if not temperature_asked and uart_device: + temperature_asked = True + last_temp_request_time = now + uart_device.send_as_command(UARTCommand(UARTCommandType.TEMPERATURE_REQUEST, {})) + + # 3. Handle fresh incoming reading + if not temp_is_invalid(current_temp): + temps = [float(current_temp[0]), float(current_temp[1])] + last_temp = [temps[0], temps[1]] # Keep a safe reference copy - # Asks the esp-wifi the temperature over UART - if not temperature_asked: - temperature_asked = True - uart_device.send_as_command(UARTCommand(UARTCommandType.TEMPERATURE_REQUEST, {})) - print("[CookingState] Requested new temperature reading from WiFi board.") - else: - print(f"[CookingState] Returning current temperature: {current_temp}") - temps = [current_temp[0], current_temp[1]] - last_temp[0] = current_temp[0] - last_temp[1] = current_temp[1] - current_temp[0] = None - current_temp[1] = None - - return temps + # Reset current_temp buffer to consume the value + current_temp = [None, None] + return temps + + # 4. Fallback: Use last valid reading + if not temp_is_invalid(last_temp): + return [float(last_temp[0]), float(last_temp[1])] + + # 5. Default fallback if no data has ever arrived + return (0.0, 0.0) def cooking_state_on_state_change(state): print(f"[CookingState] State changed to: {state.state}") @@ -173,7 +182,7 @@ async def uart_polling_task(): if uart_device and uart_device.any(): command = uart_device.read_as_command() if command: - print(f"[UART Task] Received command from WiFi Board: {command.command_type}") + log(f"[UART Task] Received command from WiFi Board: {command.command_type}") if command.command_type == UARTCommandType.COOKING_PARAMS: params = command.payload print(f"[UART Task] Cooking parameters received: {params}") @@ -193,10 +202,15 @@ async def uart_polling_task(): await asyncio.sleep_ms(200) cooking_state_on_state_change(cooking_state) elif command.command_type == UARTCommandType.TEMPERATURE_RESPONSE: - payload = ujson.loads(command.payload) - current_temp[0] = payload["dish_temp"] - current_temp[1] = payload["ambient_temp"] - temperature_asked = False + try: + # Check if payload is already a dict or needs JSON decoding + payload = ujson.loads(command.payload) if isinstance(command.payload, str) else command.payload + current_temp[0] = payload.get("dish_temp", 0.0) + current_temp[1] = payload.get("ambient_temp", 0.0) + except Exception as e: + print(f"[UART Task] Error parsing temperature payload: {e}") + finally: + temperature_asked = False else: print(f"[UART Task] Unknown command type received: {command.command_type}")