diff --git a/gauge.py b/gauge.py index 891b48f..f73546e 100644 --- a/gauge.py +++ b/gauge.py @@ -877,6 +877,28 @@ def _subscribe_all(c): c.subscribe(f"{prefix}/status_led/green/set") +def _mqtt_connect_with_timeout(client, timeout_s=10): + """Call client.connect() with a socket-level timeout to avoid blocking forever.""" + try: + import usocket as _sm + except ImportError: + import socket as _sm + _orig = _sm.socket + def _timed(*a, **kw): + s = _orig(*a, **kw) + s.settimeout(timeout_s) + return s + _sm.socket = _timed + try: + client.connect() + finally: + _sm.socket = _orig + try: + client.sock.settimeout(None) + except Exception: + pass + + def connect_mqtt(): global client_ref, _mqtt_connected info(f"Connecting to MQTT broker {MQTT_BROKER}:{MQTT_PORT} ...") @@ -896,10 +918,9 @@ def connect_mqtt(): user=MQTT_USER, password=MQTT_PASSWORD, keepalive=30, - socket_timeout=10, ) client.set_callback(on_message) - client.connect() + _mqtt_connect_with_timeout(client) client_ref = client _mqtt_connected = True info(f"MQTT connected client_id={MQTT_CLIENT_ID}") @@ -962,10 +983,9 @@ def check_mqtt(): user=MQTT_USER, password=MQTT_PASSWORD, keepalive=30, - socket_timeout=10, ) client_ref.set_callback(on_message) - client_ref.connect() + _mqtt_connect_with_timeout(client_ref) _mqtt_connected = True info("MQTT reconnected!") schedule_discovery() @@ -1304,7 +1324,21 @@ def main(): connect_wifi(WIFI_SSID, WIFI_PASSWORD, force_reconnect=False) - connect_mqtt() + mqtt_attempts = 0 + while True: + try: + connect_mqtt() + break + except Exception as e: + mqtt_attempts += 1 + log_err(f"MQTT connect failed: {e} (attempt {mqtt_attempts})") + if mqtt_attempts % 3 == 0: + log_err("WiFi may be stale — forcing reconnect...") + try: + connect_wifi(WIFI_SSID, WIFI_PASSWORD, force_reconnect=True) + except Exception as we: + log_err(f"WiFi reconnect failed: {we}") + utime.sleep_ms(5000) _subscribe_all(client_ref) schedule_discovery()