fix: Refactor main loop for graceful shutdown and improved error handling

This commit is contained in:
Aaron 2025-11-15 14:11:20 -05:00
parent d76b11430c
commit c8102e62ee

208
main.py
View File

@ -369,95 +369,119 @@ retry_ntp_attempts = 0
max_ntp_attempts = 5 # Try up to 5 times after initial failure max_ntp_attempts = 5 # Try up to 5 times after initial failure
last_ntp_sync = time.time() # Track when we last synced last_ntp_sync = time.time() # Track when we last synced
# ===== START: Main Loop ===== try:
# Main monitoring loop (runs forever until Ctrl+C) while True:
last_monitor_run = {
"wifi": 0, # ===== START: Main Loop =====
"schedule": 0, # Main monitoring loop (runs forever until Ctrl+C)
"ac": 0, last_monitor_run = {
"heater": 0, "wifi": 0,
"inside_temp": 0, "schedule": 0,
"outside_temp": 0, "ac": 0,
} "heater": 0,
"inside_temp": 0,
while True: "outside_temp": 0,
now = time.time() }
# WiFi monitor every 5 seconds (can be stateless) while True:
if now - last_monitor_run["wifi"] >= 5: now = time.time()
from scripts.monitors import WiFiMonitor
wifi_monitor = WiFiMonitor(wifi, led, interval=5, reconnect_cooldown=60, config=config) # WiFi monitor every 5 seconds (can be stateless)
try: if now - last_monitor_run["wifi"] >= 5:
wifi_monitor.run() from scripts.monitors import WiFiMonitor
except Exception as e: wifi_monitor = WiFiMonitor(wifi, led, interval=5, reconnect_cooldown=60, config=config)
print("WiFiMonitor error:", e) try:
del wifi_monitor wifi_monitor.run()
gc.collect() except Exception as e:
last_monitor_run["wifi"] = now print("WiFiMonitor error:", e)
del wifi_monitor
# Schedule monitor every 60 seconds (persistent) gc.collect()
if now - last_monitor_run["schedule"] >= 60: last_monitor_run["wifi"] = now
try:
schedule_monitor.run() # Schedule monitor every 60 seconds (persistent)
except Exception as e: if now - last_monitor_run["schedule"] >= 60:
print("ScheduleMonitor error:", e) try:
last_monitor_run["schedule"] = now schedule_monitor.run()
except Exception as e:
# AC monitor every 30 seconds (persistent) print("ScheduleMonitor error:", e)
if now - last_monitor_run["ac"] >= 30: last_monitor_run["schedule"] = now
try:
ac_monitor.run() # AC monitor every 30 seconds (persistent)
except Exception as e: if now - last_monitor_run["ac"] >= 30:
print("ACMonitor error:", e) try:
last_monitor_run["ac"] = now ac_monitor.run()
except Exception as e:
# Heater monitor every 30 seconds (persistent) print("ACMonitor error:", e)
if now - last_monitor_run["heater"] >= 30: last_monitor_run["ac"] = now
try:
heater_monitor.run() # Heater monitor every 30 seconds (persistent)
except Exception as e: if now - last_monitor_run["heater"] >= 30:
print("HeaterMonitor error:", e) try:
last_monitor_run["heater"] = now heater_monitor.run()
except Exception as e:
# Inside temperature monitor every 10 seconds (can be stateless) print("HeaterMonitor error:", e)
if now - last_monitor_run["inside_temp"] >= 10: last_monitor_run["heater"] = now
from scripts.monitors import TemperatureMonitor
inside_monitor = TemperatureMonitor( # Inside temperature monitor every 10 seconds (can be stateless)
sensor=sensors['inside'], if now - last_monitor_run["inside_temp"] >= 10:
label=SENSOR_CONFIG['inside']['label'], from scripts.monitors import TemperatureMonitor
check_interval=10, inside_monitor = TemperatureMonitor(
report_interval=30, sensor=sensors['inside'],
alert_high=SENSOR_CONFIG['inside']['alert_high'], label=SENSOR_CONFIG['inside']['label'],
alert_low=SENSOR_CONFIG['inside']['alert_low'], check_interval=10,
log_file="/temp_logs.csv", report_interval=30,
send_alerts_to_separate_channel=True alert_high=SENSOR_CONFIG['inside']['alert_high'],
) alert_low=SENSOR_CONFIG['inside']['alert_low'],
inside_monitor.run() log_file="/temp_logs.csv",
del inside_monitor send_alerts_to_separate_channel=True
gc.collect() )
last_monitor_run["inside_temp"] = now inside_monitor.run()
del inside_monitor
# Outside temperature monitor every 10 seconds (can be stateless) gc.collect()
if now - last_monitor_run["outside_temp"] >= 10: last_monitor_run["inside_temp"] = now
from scripts.monitors import TemperatureMonitor
outside_monitor = TemperatureMonitor( # Outside temperature monitor every 10 seconds (can be stateless)
sensor=sensors['outside'], if now - last_monitor_run["outside_temp"] >= 10:
label=SENSOR_CONFIG['outside']['label'], from scripts.monitors import TemperatureMonitor
check_interval=10, outside_monitor = TemperatureMonitor(
report_interval=30, sensor=sensors['outside'],
alert_high=SENSOR_CONFIG['outside']['alert_high'], label=SENSOR_CONFIG['outside']['label'],
alert_low=SENSOR_CONFIG['outside']['alert_low'], check_interval=10,
log_file="/temp_logs.csv", report_interval=30,
send_alerts_to_separate_channel=False alert_high=SENSOR_CONFIG['outside']['alert_high'],
) alert_low=SENSOR_CONFIG['outside']['alert_low'],
outside_monitor.run() log_file="/temp_logs.csv",
del outside_monitor send_alerts_to_separate_channel=False
gc.collect() )
last_monitor_run["outside_temp"] = now outside_monitor.run()
del outside_monitor
# Web requests (keep web server loaded if needed) gc.collect()
web_server.check_requests(sensors, ac_monitor, heater_monitor, schedule_monitor, config) last_monitor_run["outside_temp"] = now
gc.collect() # Web requests (keep web server loaded if needed)
time.sleep(0.1) web_server.check_requests(sensors, ac_monitor, heater_monitor, schedule_monitor, config)
# ===== END: Main Loop =====
gc.collect()
time.sleep(0.1)
# ===== END: Main Loop =====
except KeyboardInterrupt:
print("\n" + "="*50)
print("Shutting down gracefully...")
print("="*50)
try:
print("Turning off AC...")
ac_controller.turn_off()
except Exception as e:
print("AC shutdown error:", e)
try:
print("Turning off heater...")
heater_controller.turn_off()
except Exception as e:
print("Heater shutdown error:", e)
try:
print("Turning off LED...")
led.low()
except Exception as e:
print("LED shutdown error:", e)
print("Shutdown complete!")
print("="*50)