UART & Sensors
Build, push image, and notify Watchtower / build-image (push) Successful in 1m39s
Build, push image, and notify Watchtower / notify (push) Successful in 1m43s

This commit is contained in:
2026-07-23 15:50:43 +02:00
parent 1ec3ee7abf
commit 2dd664c4b4
25 changed files with 2333 additions and 71 deletions
+101 -24
View File
@@ -1,7 +1,12 @@
import json
import threading
import queue
import time
from shared import get_lora, get_mqtt_client, deviceTypes, config
import traceback
from orchestrateur.sensors import gps
from shared import get_lora, get_mqtt_client, deviceTypes, config, payloads
from shared.logging import log
from sensors import ultrasonicRanger, temp_hum, button, camera
# --- Read Unique Device ID ---
try:
@@ -49,6 +54,7 @@ mqtt_client = get_mqtt_client(
)
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)
print(f"Subscribed to topic: {config.MQTT_TOPIC_SENSOR}")
# --- THE CRUCIAL PAHO FIX ---
@@ -66,51 +72,122 @@ def mqtt_listener():
message = mqtt_client.get_message()
if message:
# Try to parse the payload as a python dictionary, but if it fails, just print the raw payload
try:
payload = json.loads(message['payload'])
except Exception as e:
print(f"Error parsing MQTT payload: {e}")
payload = message['payload'] # Fallback to raw payload if parsing fails
print(f"\n[Thread MQTT] Message reçu : {message}")
data_queue.put({"source": "MQTT", "data": message})
data_queue.put({"source": "MQTT", "topic": message['topic'] ,"data": payload})
# --- THE CPU FIX ---
# Sleep for 100ms. Prevents the thread from turning into an infinite 100% CPU hog.
time.sleep(0.1)
time.sleep(0.2)
# Button
button_state = False
def button_callback():
global button_state
button_state = not button_state
print(f"\n[Thread Button] Button state changed to: {button_state}")
button.set_callback(button_callback)
# Launch background monitoring workers
threading.Thread(target=lora_listener, daemon=True).start()
threading.Thread(target=mqtt_listener, daemon=True).start()
# threading.Thread(target=lora_listener, daemon=True).start()
# threading.Thread(target=mqtt_listener, daemon=True).start()
# Launch button monitoring thread
button.start_button_monitoring_thread()
print("Orchestrateur prêt. Le main loop est libre.")
# Sensor reading
def read_sensors():
"""Read all sensors and return a dictionary of their values."""
log("\nLecture des capteurs...")
sensor_data = {}
# Read Ultrasonic Ranger
distance = ultrasonicRanger.get_dish_height()
if distance is not None:
log(f"\nLecture du capteur Ultrason : {distance}")
sensor_data["ultrasonic_distance"] = distance
# Read Temperature and Humidity
temperature, humidity = temp_hum.get_temperature_and_humidity()
if temperature is not None and humidity is not None:
log(f"\nLecture du capteur Temp/Hum : {temperature}, {humidity}")
sensor_data["temperature"] = temperature
sensor_data["humidity"] = humidity
# Read GPS Data
gps_data = gps.get_gps_data()
if gps_data:
log(f"\nLecture du capteur GPS : {gps_data}")
sensor_data["gps"] = gps_data
# Camera
picture_bytes = None
try:
picture_bytes = camera.get_picture()
log(f"\nLecture du capteur Caméra : {len(picture_bytes)} bytes")
sensor_data["camera_image"] = picture_bytes
except Exception as e:
log(f"Error reading camera data: {e}")
# Read Button State (last because he can still change state while reading other sensors)
sensor_data["button_state"] = button_state
return sensor_data
# --- MAIN EXECUTION LOOP ---
while True:
try:
# Check for non-heartbeat data safely
# Check for non-heartbeat data
try:
msg = data_queue.get(block=False)
print(f"\n[Main Loop] Données traitées : {msg['data']}")
# print(msg)
if msg["source"] == "LoRa":
print(f"\n[Main Loop] LoRa : Données traitées : {msg['data']}")
elif msg["source"] == "MQTT":
if (msg["topic"] == config.MQTT_TOPIC_HELLO.decode('utf-8')):
if ("id_orchestrator" in msg["data"] and msg["data"]["id_orchestrator"] == DEVICE_ID):
# Do not answer to messages coming from me
continue
microwave_id = msg["data"]["id_microwave"]
print(f"\n[Main Loop] MQTT : Hello reçu de {microwave_id}.")
# Responds
mqtt_client.publish(config.MQTT_TOPIC_HELLO, payloads.mqtt_hello_ack(DEVICE_ID, microwave_id), qos=config.MQTT_QOS)
print(f"[Main Loop] MQTT : Réponse Hello envoyée à {microwave_id}.")
# TODO : Save in database
print(f"\n[Main Loop] MQTT : Données traitées : {msg['data']}")
except queue.Empty:
pass
# DEBUG : Read sensors
sensor_values = read_sensors()
if sensor_values:
sensor_values_print = sensor_values.copy()
if "camera_image" in sensor_values_print:
sensor_values_print["camera_image"] = f"<{len(sensor_values_print['camera_image'])} bytes>"
print(f"\nCapteurs Données lues : {sensor_values_print}")
time.sleep(1)
# Publish debug telemetry message
print("[Main Loop] Envoi d'un message de debug sur MQTT...")
response = mqtt_client.publish(
config.MQTT_TOPIC_COOKING,
f"Orchestrateur actif, ID: {DEVICE_ID}",
qos=config.MQTT_QOS
)
# This will now unblock instantly because loop_start() handles the delivery confirmation!
response.wait_for_publish()
print("[Main Loop] Message de debug publié avec succès.")
time.sleep(9)
time.sleep(3)
except KeyboardInterrupt:
break
except Exception as e:
traceback.print_exc()
time.sleep(1) # Prevents rapid error logging in case of persistent issues
# Clean termination
if hasattr(mqtt_client._client, "loop_stop"):
mqtt_client._client.loop_stop()
mqtt_client.close()
mqtt_client.close()