#include #include #include #include #include #include "wifi_manager.h" #include "radar_manager.h" // ESP32 GPIO控制演示 #define BOOT_BUTTON_PIN 0 // Boot按钮引脚 #define NETWORK_LED_PIN 5 // 网络状态LED指示灯开发板48引脚,雷达板5引脚 #define CONFIG_CLEAR_PIN 4 // 配置清除指示灯 #define GPIO8 8 // 自定义GPIO8 #define GPIO9 9 // 自定义GPIO9 uint8_t WiFi_Connect_First_bit = 1; // WiFi首次连接标志位 // 配置清除指示灯状态枚举 enum ConfigClearStatus { CONFIG_NORMAL, // 正常运行 - LOW CONFIG_PREPARING, // 准备清除 - HIGH CONFIG_CLEARING, // 清除过程中 - 呼吸灯 CONFIG_COMPLETED // 清除完成 - 快速闪烁3次 }; NetworkStatus currentNetworkStatus = NET_INITIAL; // 当前网络状态 unsigned long lastBlinkTime = 0; // 上次LED闪烁时间 bool ledState = false; // LED状态 int breatheValue = 0; // 呼吸灯当前亮度值 bool breatheIncreasing = true; // 呼吸灯是否在增加亮度 ConfigClearStatus currentConfigClearStatus = CONFIG_NORMAL; // 当前配置清除状态 unsigned long lastConfigBlinkTime = 0; // 上次配置清除LED闪烁时间 bool configLedState = false; // 配置清除LED状态 int configBreatheValue = 0; // 配置清除呼吸灯当前亮度值 bool configBreatheIncreasing = true; // 配置清除呼吸灯是否在增加亮度 const int SLOW_BLINK_INTERVAL = 1000; // 慢闪间隔(毫秒) const int FAST_BLINK_INTERVAL = 200; // 快闪间隔(毫秒) const int BREATHE_INTERVAL = 40; // 呼吸灯更新间隔(毫秒) const int BREATHE_MIN = 0; // 呼吸灯最小亮度值 const int BREATHE_MAX = 155; // 呼吸灯最大亮度值 const int BREATHE_STEP = 5; // 呼吸灯亮度步进值 const uint16_t MIN_DEVICE_ID = 1000; // 最小设备ID const uint16_t MAX_DEVICE_ID = 1999; // 最大设备ID const unsigned long CLEAR_CONFIG_DURATION = 3000; // 清除配置持续时间(毫秒) Preferences preferences; // Flash存储对象 WiFiManager wifiManager; // WiFi管理器对象 uint16_t currentDeviceId = 0000; // 当前设备ID bool clearConfigRequested = false; // 清除配置请求标志 bool forceLedOff = false; // 强制关闭LED标志 void configClearLedTask(void *parameter); void bootButtonMonitorTask(void *parameter); void checkBootButton(); void clearStoredConfig(); void ledControlTask(void *parameter); void setNetworkStatus(NetworkStatus status); void wifiMonitorTask(void *parameter); void WiFiEvent(WiFiEvent_t event); void loadDeviceId(); void saveDeviceId(); String getFieldNameByProtocolId(int protocolId); /** * @brief 根据协议ID获取字段名称 * 将协议ID映射到对应的字段名称,用于数据序列化和反序列化 * @param protocolId 协议ID * @return 对应的字段名称字符串 */ String getFieldNameByProtocolId(int protocolId) { switch(protocolId) { case 1: return "heartRate"; case 2: return "breathingRate"; case 13: return "personDetected"; case 14: return "humanActivity"; case 15: return "humanDistance"; case 16: return "humanPosition"; case 17: return "sleepState"; default: return "unknown"; } } /** * @brief 检查Boot按钮状态 * 在启动时检查Boot按钮是否被按下,如果按下则进入配置清除流程 */ void checkBootButton() { Serial.println("🔍 检查Boot按钮状态..."); pinMode(BOOT_BUTTON_PIN, INPUT_PULLUP); delay(10); int buttonState = digitalRead(BOOT_BUTTON_PIN); Serial.printf("📊 Boot按钮状态: %s\n", buttonState == LOW ? "按下" : "释放"); if (buttonState == LOW) { Serial.println("⚠️ 检测到Boot按钮按下,请释放按钮后继续启动"); Serial.println("⏰ 等待按钮释放..."); while (digitalRead(BOOT_BUTTON_PIN) == LOW) { delay(100); } Serial.println("✅ Boot按钮已释放,正常启动"); } else { Serial.println("✅ Boot按钮未按下,正常启动"); } } /** * @brief 加载设备ID * 从Flash中读取保存的设备ID */ void loadDeviceId() { currentDeviceId = preferences.getUShort("deviceId", 1001); Serial.printf("从Flash加载设备ID: %u\n", currentDeviceId); } /** * @brief 保存设备ID * 将设备ID保存到Flash中 */ void saveDeviceId() { preferences.putUShort("deviceId", currentDeviceId); Serial.printf("设备ID已保存到Flash: %u\n", currentDeviceId); } /** * @brief 清除存储的配置 * 清除Flash中保存的所有配置,包括设备ID和WiFi配置 */ void clearStoredConfig() { Serial.println("🧹 开始清除存储的配置..."); uint16_t oldDeviceId = preferences.getUShort("deviceId", 0); preferences.remove("deviceId"); preferences.remove("wifi_first"); wifiManager.clearAllConfigs(); Serial.println("✅ 配置已清除完成"); Serial.printf("🗑️ 被清除的设备ID: %u\n", oldDeviceId); currentDeviceId = 1001; WiFi_Connect_First_bit = 1; WiFi.disconnect(true); setNetworkStatus(NET_DISCONNECTED); Serial.println("🔄 已清除Flash与内存中的配置,请重新配置WiFi和设备ID"); if (deviceConnected) { sendStatusToBLE(); } } /** * @brief 配置清除LED控制任务 * 根据配置清除状态控制CONFIG_CLEAR_PIN引脚的LED显示 * @param parameter 任务参数(未使用) */ void configClearLedTask(void *parameter) { while (1) { switch (currentConfigClearStatus) { case CONFIG_NORMAL: analogWrite(CONFIG_CLEAR_PIN, 0); break; case CONFIG_PREPARING: analogWrite(CONFIG_CLEAR_PIN, 255); break; case CONFIG_CLEARING: if (millis() - lastConfigBlinkTime >= BREATHE_INTERVAL) { analogWrite(CONFIG_CLEAR_PIN, configBreatheValue); if (configBreatheIncreasing) { configBreatheValue += 5; if (configBreatheValue >= BREATHE_MAX) { configBreatheValue = BREATHE_MAX; configBreatheIncreasing = false; } } else { configBreatheValue -= 5; if (configBreatheValue <= BREATHE_MIN) { configBreatheValue = BREATHE_MIN; configBreatheIncreasing = true; } } lastConfigBlinkTime = millis(); } break; case CONFIG_COMPLETED: if (millis() - lastConfigBlinkTime >= FAST_BLINK_INTERVAL) { configLedState = !configLedState; digitalWrite(CONFIG_CLEAR_PIN, configLedState ? HIGH : LOW); lastConfigBlinkTime = millis(); static int blinkCount = 0; blinkCount++; if (blinkCount >= 6) { blinkCount = 0; currentConfigClearStatus = CONFIG_NORMAL; digitalWrite(CONFIG_CLEAR_PIN, LOW); } } break; } vTaskDelay(10 / portTICK_PERIOD_MS); } } /** * @brief BOOT按钮监控任务 * 持续监控BOOT按钮状态,检测长按3秒事件并触发配置清除 * @param parameter 任务参数(未使用) */ void bootButtonMonitorTask(void *parameter) { Serial.println("🔍 启动BOOT按钮监控任务..."); pinMode(BOOT_BUTTON_PIN, INPUT_PULLUP); unsigned long buttonPressStartTime = 0; bool buttonPressed = false; while (1) { int buttonState = digitalRead(BOOT_BUTTON_PIN); if (buttonState == LOW && !buttonPressed) { buttonPressed = true; buttonPressStartTime = millis(); Serial.println("⚠️ 检测到BOOT按钮按下,长按3秒将清除配置"); currentConfigClearStatus = CONFIG_PREPARING; } else if (buttonState == HIGH && buttonPressed) { if (!clearConfigRequested) { currentConfigClearStatus = CONFIG_NORMAL; Serial.println("❌ 按钮释放,取消清除操作"); } buttonPressed = false; } if (buttonPressed && (millis() - buttonPressStartTime >= CLEAR_CONFIG_DURATION)) { if (!clearConfigRequested) { clearConfigRequested = true; forceLedOff = true; ledcWrite(0, 0); Serial.println("✅ 长按3秒确认,将清除配置"); Serial.println("💡 网络LED已强制熄灭"); clearStoredConfig(); Serial.println("🔄 配置清除完成,LED将闪烁3次表示完成..."); analogWrite(CONFIG_CLEAR_PIN, 0); Serial.println("🔄 系统即将重启..."); vTaskDelay(1000 / portTICK_PERIOD_MS); ESP.restart(); } } vTaskDelay(50 / portTICK_PERIOD_MS); esp_task_wdt_reset(); } } /** * @brief LED控制任务 * 根据网络状态控制NETWORK_LED_PIN引脚的LED显示 * 支持慢闪、快闪和呼吸灯效果 * @param parameter 任务参数(未使用) */ void ledControlTask(void *parameter) { while (1) { if (forceLedOff) { ledcWrite(0, 0); vTaskDelay(10 / portTICK_PERIOD_MS); continue; } switch (currentNetworkStatus) { case NET_INITIAL: case NET_DISCONNECTED: if (millis() - lastBlinkTime >= SLOW_BLINK_INTERVAL) { ledState = !ledState; if(ledState) { ledcWrite(0, 255); } else { ledcWrite(0, 0); } lastBlinkTime = millis(); } break; case NET_CONNECTING: if (millis() - lastBlinkTime >= FAST_BLINK_INTERVAL) { ledState = !ledState; if(ledState) { ledcWrite(0, 255); } else { ledcWrite(0, 0); } lastBlinkTime = millis(); } break; case NET_CONNECTED: if (millis() - lastBlinkTime >= BREATHE_INTERVAL) { ledcWrite(0, breatheValue); if (breatheIncreasing) { breatheValue += BREATHE_STEP; if (breatheValue >= BREATHE_MAX) { breatheValue = BREATHE_MAX; breatheIncreasing = false; } } else { breatheValue -= BREATHE_STEP; if (breatheValue <= BREATHE_MIN) { breatheValue = BREATHE_MIN; breatheIncreasing = true; } } lastBlinkTime = millis(); } break; } vTaskDelay(10 / portTICK_PERIOD_MS); } } /** * @brief 设置网络状态 * 更新当前网络状态,并重置呼吸灯参数 * @param status 网络状态 */ void setNetworkStatus(NetworkStatus status) { currentNetworkStatus = status; if (status == NET_CONNECTED) { breatheValue = BREATHE_MIN; breatheIncreasing = true; } } /** * @brief WiFi事件处理函数 * 处理WiFi连接状态变化事件,更新网络状态和LED显示 * @param event WiFi事件类型 */ void WiFiEvent(WiFiEvent_t event) { switch (event) { case ARDUINO_EVENT_WIFI_STA_START: setNetworkStatus(NET_INITIAL); break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: setNetworkStatus(NET_CONNECTING); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: setNetworkStatus(NET_CONNECTED); break; case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: setNetworkStatus(NET_DISCONNECTED); break; case ARDUINO_EVENT_WIFI_STA_STOP: setNetworkStatus(NET_DISCONNECTED); break; } } /** * @brief WiFi监控任务 * 定期更新WiFi管理器状态,处理WiFi重连等逻辑 * @param parameter 任务参数(未使用) */ void wifiMonitorTask(void *parameter) { Serial.println("📡 WiFi监控任务启动"); while(1) { wifiManager.update(); vTaskDelay(500 / portTICK_PERIOD_MS); } } /** * @brief 系统初始化函数 * 初始化所有硬件外设、任务和通信模块 */ void setup() { Serial.begin(115200); checkBootButton(); analogWrite(CONFIG_CLEAR_PIN, 0); Serial.println("🚀 ESP32-R60ABD1系统启动"); Serial.println("🔧 初始化系统组件..."); pinMode(BOOT_BUTTON_PIN, INPUT); pinMode(NETWORK_LED_PIN, OUTPUT); pinMode(CONFIG_CLEAR_PIN, OUTPUT); pinMode(GPIO8, OUTPUT); pinMode(GPIO9, OUTPUT); digitalWrite(CONFIG_CLEAR_PIN, LOW); digitalWrite(GPIO8, LOW); digitalWrite(GPIO9, LOW); digitalWrite(NETWORK_LED_PIN, LOW); digitalWrite(CONFIG_CLEAR_PIN, LOW); ledcSetup(0, 5000, 8); ledcSetup(1, 5000, 8); ledcAttachPin(NETWORK_LED_PIN, 0); ledcAttachPin(CONFIG_CLEAR_PIN, 1); WiFi.onEvent(WiFiEvent); setNetworkStatus(NET_INITIAL); esp_task_wdt_init(30, true); esp_task_wdt_add(NULL); preferences.begin("radar_data", false); wifiManager.begin(); Serial.println("💾 加载设备配置..."); loadDeviceId(); Serial.println("🏗️ 初始化雷达管理器..."); initRadarManager(); xTaskCreate( configClearLedTask, "Config Clear LED Task", 2048, NULL, 1, NULL ); xTaskCreate( bootButtonMonitorTask, "Boot Button Monitor Task", 2048, NULL, 1, NULL ); xTaskCreate( ledControlTask, "LED Control Task", 2048, NULL, 1, NULL ); xTaskCreate( wifiMonitorTask, "WiFi Monitor Task", 4096, NULL, 2, NULL ); Serial.println("✅ FreeRTOS任务创建成功"); Serial.println("📶 初始化BLE服务..."); String deviceName = "Radar_" + String(currentDeviceId); BLEDevice::init(deviceName.c_str()); pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService *pService = pServer->createService(SERVICE_UUID); pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY ); pCharacteristic->setCallbacks(new MyCallbacks()); pCharacteristic->addDescriptor(new BLE2902()); pService->start(); BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(true); pAdvertising->setMinPreferred(0x06); pAdvertising->setMinPreferred(0x12); BLEDevice::startAdvertising(); Serial.println(String("BLE已启动,设备名称: Radar_") + String(currentDeviceId)); Serial.println("🌐 检查WiFi配置..."); if (wifiManager.getSavedNetworkCount() > 0) { Serial.printf("💾 检测到 %d 个已保存的WiFi配置,尝试连接...\n", wifiManager.getSavedNetworkCount()); if (wifiManager.initializeWiFi()) { Serial.println("✅ WiFi连接成功!"); } else { Serial.println("❌ WiFi连接失败,请通过BLE重新配置"); } } else { Serial.println("⚠️ 未检测到WiFi配置,请通过BLE进行网络配置"); } size_t wifi_first_len = preferences.getBytes("wifi_first", &WiFi_Connect_First_bit, sizeof(WiFi_Connect_First_bit)); if (wifi_first_len == sizeof(WiFi_Connect_First_bit)) { Serial.printf("从Flash读取 WiFi_Connect_First_bit: %u\n", WiFi_Connect_First_bit); } else { Serial.println("Flash中无 wifi_first 条目,保留内存中原始值"); } if(WiFi_Connect_First_bit == 0) { unsigned long wifiWaitStart = millis(); unsigned long lastWifiWaitPrint = 0; const unsigned long WIFI_WAIT_TIMEOUT = 15000; while (WiFi.status() != WL_CONNECTED && (millis() - wifiWaitStart) < WIFI_WAIT_TIMEOUT) { if (millis() - lastWifiWaitPrint >= 1000) { Serial.println("等待WiFi连接..."); lastWifiWaitPrint = millis(); } yield(); vTaskDelay(10 / portTICK_PERIOD_MS); } } Serial.println("WiFi连接成功!"); initR60ABD1(); Serial.println("🎉 系统初始化完成,等待雷达数据..."); if (WiFi.status() == WL_CONNECTED) { Serial.println("🌅 启动时发送睡眠数据到数据库"); sendSleepDataToInfluxDB(); } } /** * @brief 主循环函数 * 处理BLE连接状态和定期发送雷达命令 */ void loop() { esp_task_wdt_reset(); if (!deviceConnected && oldDeviceConnected) { vTaskDelay(500 / portTICK_PERIOD_MS); pServer->startAdvertising(); Serial.println("开始BLE广播"); oldDeviceConnected = deviceConnected; } if (deviceConnected && !oldDeviceConnected) { oldDeviceConnected = deviceConnected; } { static const uint8_t radar_cmds[][3] = { {0x84, 0x81, 0x0F}, {0x84, 0x8D, 0x0F}, {0x84, 0x8F, 0x0F}, {0x84, 0x8E, 0x0F}, {0x84, 0x91, 0x0F}, {0x84, 0x92, 0x0F}, {0x84, 0x83, 0x0F}, {0x84, 0x84, 0x0F}, {0x84, 0x85, 0x0F}, {0x84, 0x86, 0x0F}, {0x84, 0x90, 0x0F} }; const size_t cmdCount = sizeof(radar_cmds) / sizeof(radar_cmds[0]); static size_t cmdIndex = 0; static unsigned long lastCmdMillis = 0; const unsigned long CMD_INTERVAL = 2000UL; unsigned long now = millis(); if (now - lastCmdMillis >= CMD_INTERVAL) { sendRadarCommand(radar_cmds[cmdIndex][0], radar_cmds[cmdIndex][1], radar_cmds[cmdIndex][2]); lastCmdMillis = now; cmdIndex++; if (cmdIndex >= cmdCount) cmdIndex = 0; } } processBLEConfig(); esp_task_wdt_reset(); esp_task_wdt_reset(); esp_task_wdt_reset(); }