فهرست منبع

修复固件bug

moki 5 ساعت پیش
والد
کامیت
c53a4360f1
1فایلهای تغییر یافته به همراه141 افزوده شده و 89 حذف شده
  1. 141 89
      firmware/ai_light/ai_light.ino

+ 141 - 89
firmware/ai_light/ai_light.ino

@@ -51,7 +51,7 @@
 // BLE 配置
 // =====================================================
 const char* BLE_DEVICE_NAME = "AI-Light";
-const char* FW_VERSION = "1.0.0";
+const char* FW_VERSION = "1.1.0";
 #define SERVICE_UUID        "b8b7e001-7a6b-4f4f-9a8b-11c0ffee0001"
 #define MODE_CHAR_UUID      "b8b7e002-7a6b-4f4f-9a8b-11c0ffee0001"
 #define CONFIG_CHAR_UUID    "b8b7e003-7a6b-4f4f-9a8b-11c0ffee0001"
@@ -78,6 +78,29 @@ const unsigned long LONG_PRESS_MS = 3000;
 const unsigned long TRIPLE_PRESS_WINDOW_MS = 1500;
 const int TRIPLE_PRESS_COUNT = 3;
 
+// 非阻塞连接超时
+const unsigned long WIFI_CONNECT_TIMEOUT_MS = 10000;
+const unsigned long MQTT_CONNECT_TIMEOUT_MS = 5000;
+const unsigned long MQTT_RECONNECT_INTERVAL_MS = 3000;
+
+// =====================================================
+// 连接状态机
+// =====================================================
+enum ConnState {
+  CONN_IDLE,
+  CONN_WIFI_CONNECTING,
+  CONN_MQTT_CONNECTING,
+  CONN_CONNECTED,
+  CONN_WIFI_FAILED,
+  CONN_MQTT_FAILED
+};
+
+ConnState connState = CONN_IDLE;
+unsigned long connStateStart = 0;
+unsigned long lastMqttReconnectAttempt = 0;
+int connRetryCount = 0;
+const int MAX_CONN_RETRIES = 3;
+
 // =====================================================
 // 全局状态
 // =====================================================
@@ -413,24 +436,6 @@ void updateInit() {
   setOnly(brightness, brightness, brightness);
 }
 
-void breathingGreen(int times) {
-  const unsigned long period = 2500;
-  for (int i = 0; i < times; i++) {
-    unsigned long start = millis();
-    while (millis() - start < period) {
-      unsigned long t = millis() - start;
-      int brightness;
-      if (t < 800) brightness = map(t, 0, 800, 0, GREEN_MAX);
-      else if (t < 1200) brightness = GREEN_MAX;
-      else if (t < 2000) brightness = map(t, 1200, 2000, GREEN_MAX, 0);
-      else brightness = 0;
-      setOnly(0, 0, brightness);
-      delay(5);
-    }
-  }
-  allOff();
-}
-
 
 // =====================================================
 // BOOT 按钮处理
@@ -504,7 +509,7 @@ void checkBootButton() {
 
 void updateStatusLed() {
   if (useMQTT) {
-    if (wifiConnected) {
+    if (wifiConnected && mqttClient.connected()) {
       digitalWrite(STATUS_PIN, LOW);
     } else {
       digitalWrite(STATUS_PIN, HIGH);
@@ -608,58 +613,93 @@ void mqttCallback(char* topic, byte* payload, unsigned int length) {
   }
 }
 
-bool connectWiFi() {
-  Serial.print("Connecting WiFi");
-  WiFi.mode(WIFI_STA);
-  WiFi.begin(cfgWifiSsid.c_str(), cfgWifiPass.c_str());
+void mqttSubscribe() {
+  mqttClient.subscribe(cfgMqttTopic.c_str());
+  mqttClient.subscribe(cfgMqttTopicConfig.c_str());
+}
+
+void updateConnection() {
+  unsigned long now = millis();
+
+  switch (connState) {
+    case CONN_IDLE:
+      break;
+
+    case CONN_WIFI_CONNECTING:
+      if (WiFi.status() == WL_CONNECTED) {
+        Serial.printf("\nWiFi OK. IP: %s\n", WiFi.localIP().toString().c_str());
+        wifiConnected = true;
+        digitalWrite(STATUS_PIN, LOW);
+        mqttClient.setServer(cfgMqttBroker.c_str(), cfgMqttPort);
+        mqttClient.setCallback(mqttCallback);
+        connState = CONN_MQTT_CONNECTING;
+        connStateStart = now;
+        Serial.println("MQTT connecting...");
+      } else if (now - connStateStart > WIFI_CONNECT_TIMEOUT_MS) {
+        Serial.println("\nWiFi connect timeout.");
+        WiFi.disconnect(true);
+        WiFi.mode(WIFI_OFF);
+        wifiConnected = false;
+        connState = CONN_WIFI_FAILED;
+      }
+      break;
+
+    case CONN_MQTT_CONNECTING:
+      if (mqttClient.connect(cfgMqttClient.c_str(), cfgMqttUser.c_str(), cfgMqttPass.c_str())) {
+        Serial.println("MQTT OK.");
+        mqttSubscribe();
+        setMode("traffic");
+        connState = CONN_CONNECTED;
+        connRetryCount = 0;
+      } else if (now - connStateStart > MQTT_CONNECT_TIMEOUT_MS) {
+        Serial.println("MQTT connect timeout.");
+        connState = CONN_MQTT_FAILED;
+      }
+      break;
+
+    case CONN_CONNECTED:
+      break;
+
+    case CONN_WIFI_FAILED:
+      if (connRetryCount >= MAX_CONN_RETRIES) {
+        Serial.println("Max WiFi retries reached. Falling back to BLE mode...");
+        WiFi.disconnect(true);
+        WiFi.mode(WIFI_OFF);
+        wifiConnected = false;
+        connState = CONN_IDLE;
+        setMode("init");
+        setupBLE();
+        Serial.println("BLE advertising. Waiting for connection...");
+      }
+      break;
 
-  for (int retry = 1; retry <= 5; retry++) {
-    Serial.printf("\nWiFi %d/5", retry);
-    int attempts = 0;
-    while (WiFi.status() != WL_CONNECTED && attempts < 60) {
-      delay(5);
-      updateInit();
-      updateStatusLed();
-      Serial.print(".");
-      attempts++;
-    }
-    if (WiFi.status() == WL_CONNECTED) {
-      Serial.printf("\nWiFi OK. IP: %s\n", WiFi.localIP().toString().c_str());
-      digitalWrite(STATUS_PIN, LOW);
-      return true;
-    }
-    Serial.println("\nFailed, retrying..."); delay(2000);
+    case CONN_MQTT_FAILED:
+      if (currentMode != "error") setMode("error");
+      break;
   }
+}
 
-  Serial.println("\nWiFi failed. Turning off WiFi.");
-  WiFi.disconnect(true);
-  WiFi.mode(WIFI_OFF);
-  return false;
-}
-
-bool connectMQTT() {
-  mqttClient.setServer(cfgMqttBroker.c_str(), cfgMqttPort);
-  mqttClient.setCallback(mqttCallback);
-  Serial.print("MQTT connecting");
-  int attempts = 0;
-  while (!mqttClient.connected()) {
-    if (mqttClient.connect(cfgMqttClient.c_str(), cfgMqttUser.c_str(), cfgMqttPass.c_str())) {
-      Serial.println("\nMQTT OK.");
-      mqttClient.subscribe(cfgMqttTopic.c_str());
-      mqttClient.subscribe(cfgMqttTopicConfig.c_str());
-      allOff(); breathingGreen(3); publishStatus();
-      return true;
-    }
-    Serial.print("."); delay(500);
-    if (++attempts > 60) { Serial.println("\nMQTT failed!"); return false; }
-  }
-  return false;
+void startConnection() {
+  Serial.printf("Starting WiFi connection (attempt %d/%d)...\n", connRetryCount + 1, MAX_CONN_RETRIES);
+  WiFi.mode(WIFI_STA);
+  WiFi.begin(cfgWifiSsid.c_str(), cfgWifiPass.c_str());
+  connState = CONN_WIFI_CONNECTING;
+  connStateStart = millis();
 }
 
-void checkMQTTConnection() {
-  if (useMQTT && !mqttClient.connected()) {
-    Serial.println("MQTT reconnecting...");
-    connectMQTT();
+void handleMqttReconnect() {
+  if (connState != CONN_CONNECTED) return;
+  if (mqttClient.connected()) return;
+
+  unsigned long now = millis();
+  if (now - lastMqttReconnectAttempt < MQTT_RECONNECT_INTERVAL_MS) return;
+  lastMqttReconnectAttempt = now;
+
+  Serial.println("MQTT reconnecting...");
+  if (mqttClient.connect(cfgMqttClient.c_str(), cfgMqttUser.c_str(), cfgMqttPass.c_str())) {
+    Serial.println("MQTT reconnected.");
+    mqttSubscribe();
+    publishStatus();
   }
 }
 
@@ -694,18 +734,12 @@ void setup() {
   Serial.printf("Pins: R=%d G=%d Y=%d\n", redPin, greenPin, yellowPin);
 
   if (useMQTT && isConfigComplete()) {
-    wifiConnected = connectWiFi();
-    if (wifiConnected) {
-      connectMQTT();
-      setMode("traffic");
-      Serial.println("WiFi/MQTT mode. Long press BOOT (3s) to switch.");
-      return;
-    }
-    Serial.println("WiFi failed. Entering BLE config mode.");
+    startConnection();
+    Serial.println("WiFi/MQTT mode. Long press BOOT (3s) to switch.");
+  } else {
+    setupBLE();
+    Serial.println("BLE advertising. Waiting for connection...");
   }
-
-  setupBLE();
-  Serial.println("BLE advertising. Waiting for connection...");
 }
 
 
@@ -717,18 +751,36 @@ void loop() {
   updateStatusLed();
   checkBootButton();
 
-  if (useMQTT && wifiConnected) {
-    if (WiFi.status() != WL_CONNECTED) {
-      Serial.println("WiFi lost, reconnecting...");
-      wifiConnected = false;
-      wifiConnected = connectWiFi();
-      if (!wifiConnected) {
-        Serial.println("WiFi failed. BLE config mode active.");
+  if (useMQTT && isConfigComplete()) {
+    updateConnection();
+
+    if (connState == CONN_CONNECTED) {
+      if (WiFi.status() != WL_CONNECTED) {
+        Serial.println("WiFi lost, restarting connection...");
+        wifiConnected = false;
+        connState = CONN_IDLE;
+        startConnection();
+      } else {
+        handleMqttReconnect();
+        mqttClient.loop();
+      }
+    } else if (connState == CONN_WIFI_FAILED) {
+      if (connRetryCount < MAX_CONN_RETRIES) {
+        static unsigned long lastRetry = 0;
+        if (millis() - lastRetry > 5000) {
+          lastRetry = millis();
+          connRetryCount++;
+          startConnection();
+        }
+      }
+    } else if (connState == CONN_MQTT_FAILED) {
+      static unsigned long lastMqttRetry = 0;
+      if (millis() - lastMqttRetry > MQTT_RECONNECT_INTERVAL_MS) {
+        lastMqttRetry = millis();
+        connState = CONN_MQTT_CONNECTING;
+        connStateStart = millis();
+        Serial.println("MQTT retrying...");
       }
-    }
-    if (wifiConnected) {
-      checkMQTTConnection();
-      mqttClient.loop();
     }
   }