#include "radar_manager.h" #include "wifi_manager.h" #include #include extern uint16_t currentDeviceId; // 当前设备ID extern Preferences preferences; // Flash存储对象 extern WiFiManager wifiManager; // WiFi管理器对象 const int BAUD_RATE = 115200; // 串口波特率 const int UART1_RX = 3; // UART1接收引脚 const int UART1_TX = 2; // UART1发送引脚 const uint32_t PHASE_SEND_INTERVAL = 1; // 相位数据发送间隔(毫秒) const uint32_t VITAL_SEND_INTERVAL = 10; // 生命体征数据发送间隔(毫秒) const unsigned long SENSOR_TIMEOUT = 40000; // 传感器超时时间(毫秒) static uint32_t packetCounter = 0; // 数据包计数器 static bool shouldSendOtherData = false; // 是否发送其他数据标志 unsigned long lastSleepDataTime = 0; // 上次发送睡眠数据时间 const unsigned long SLEEP_DATA_INTERVAL = 5000; // 睡眠数据发送间隔(毫秒) const char* influxDBHost = "8.134.11.76"; // InfluxDB服务器地址 const int influxDBPort = 8086; // InfluxDB服务器端口 const char* influxDBToken = "KuTa5ZsqoHIhi2IglOO06zExUYw1_mJ6K0mcA9X1y6O6CJDog3_Cgr8mUw1SwpuCCKRElqxa6wAhrrhsYPytkg=="; // InfluxDB访问令牌 const char* influxDBOrg = "gzlg"; // InfluxDB组织名称 const char* influxDBBucket = "gzlg"; // InfluxDB存储桶名称 uint8_t presence_Bit = 1; // 存在标志位 SensorData sensorData; // 传感器数据结构体 HardwareSerial mySerial1(1); // 硬件串口1对象 QueueHandle_t phaseDataQueue; // 相位数据队列句柄 QueueHandle_t vitalDataQueue; // 生命体征数据队列句柄 QueueHandle_t uartQueue; // UART数据队列句柄 TaskHandle_t bleSendTaskHandle = NULL; // BLE发送任务句柄 TaskHandle_t vitalSendTaskHandle = NULL; // 生命体征发送任务句柄 TaskHandle_t uartProcessTaskHandle = NULL; // UART处理任务句柄 BLEServer* pServer = NULL; // BLE服务器指针 BLECharacteristic* pCharacteristic = NULL; // BLE特征值指针 bool deviceConnected = false; // 设备连接状态 bool oldDeviceConnected = false; // 旧设备连接状态 String receivedData = ""; // 接收到的数据 String completeData = ""; // 完整数据 unsigned long lastReceiveTime = 0; // 上次接收数据时间 bool continuousSendEnabled = false; // 持续发送使能标志 unsigned long continuousSendInterval = 500; // 持续发送间隔(毫秒) BLEFlowController bleFlow(500); // BLE流控制器对象 unsigned long lastSensorUpdate = 0; // 上次传感器更新时间 LastSentData lastSentData = {0}; // 上次发送的数据,初始化为0 unsigned long lastCheckTime = 0; // 上次检测时间,初始化为0 /** * @brief BLE流控制器构造函数 * 初始化BLE数据流控制参数,限制数据发送速率 * @param maxBps 最大每秒发送字节数 */ BLEFlowController::BLEFlowController(size_t maxBps) : maxBytesPerSecond(maxBps), bytesSent(0) { lastResetTime = millis(); lastSendTime = 0; } /** * @brief 检查是否可以发送数据 * 检查当前是否满足发送条件,包括速率限制和时间间隔 * @param dataSize 要发送的数据大小 * @return 是否可以发送数据 */ bool BLEFlowController::canSend(size_t dataSize) { unsigned long currentTime = millis(); if(currentTime - lastResetTime >= 1000) { bytesSent = 0; lastResetTime = currentTime; } if((bytesSent + dataSize) > maxBytesPerSecond) { return false; } if(currentTime - lastSendTime < 5) { return false; } return true; } /** * @brief 检查发送时间间隔 * 检查距离上次发送是否满足最小时间间隔 * @return 是否满足发送条件 */ bool BLEFlowController::check() { unsigned long currentTime = millis(); if(currentTime - lastSendTime < 5) { return false; } return true; } /** * @brief 记录数据发送 * 更新已发送字节数和最后发送时间 * @param dataSize 已发送的数据大小 */ void BLEFlowController::recordSend(size_t dataSize) { bytesSent += dataSize; lastSendTime = millis(); } /** * @brief 重置流控制器 * 重置已发送字节数和时间戳 */ void BLEFlowController::reset() { bytesSent = 0; lastResetTime = millis(); lastSendTime = 0; } /** * @brief BLE服务器连接回调 * 当客户端连接时触发 * @param pServer BLE服务器指针 */ void MyServerCallbacks::onConnect(BLEServer* pServer) { deviceConnected = true; Serial.println("✅ [BLE] 客户端已连接"); } /** * @brief BLE服务器断开连接回调 * 当客户端断开连接时触发 * @param pServer BLE服务器指针 */ void MyServerCallbacks::onDisconnect(BLEServer* pServer) { deviceConnected = false; Serial.println("🔴 [BLE] 客户端已断开"); continuousSendEnabled = false; Serial.println("🔄 重置持续发送状态"); } /** * @brief BLE特征值写入回调 * 当客户端写入数据时触发 * @param pCharacteristic BLE特征值指针 */ void MyCallbacks::onWrite(BLECharacteristic *pCharacteristic) { std::string value = pCharacteristic->getValue(); Serial.printf("🔵 [BLE] 收到写入数据,长度: %d 字节\n", value.length()); if (value.length() > 0) { String fragment = ""; for (int i = 0; i < value.length(); i++) fragment += value[i]; Serial.printf("📄 [BLE] 接收数据片段: %s\n", fragment.c_str()); completeData += fragment; lastReceiveTime = millis(); int openBrace = completeData.indexOf('{'); if (openBrace >= 0) { int depth = 0; int closeBrace = -1; for (int i = openBrace; i < completeData.length(); i++) { char c = completeData.charAt(i); if (c == '{') { depth++; } else if (c == '}') { depth--; if (depth == 0) { closeBrace = i; break; } } } if (closeBrace > openBrace) { String jsonData = completeData.substring(openBrace, closeBrace + 1); completeData = completeData.substring(closeBrace + 1); Serial.printf("📥 [BLE] 完整JSON数据: %s\n", jsonData.c_str()); receivedData = jsonData; } } } } /** * @brief 初始化雷达管理器 * 初始化串口、队列和FreeRTOS任务 */ void initRadarManager() { Serial.println("🔧 初始化雷达管理器..."); mySerial1.setRxBufferSize(UART_RX_BUFFER_SIZE); mySerial1.begin(BAUD_RATE, SERIAL_8N1, UART1_RX, UART1_TX); Serial.println("UART1配置完成,缓冲区大小: 4096字节"); phaseDataQueue = xQueueCreate(QUEUE_SIZE, sizeof(PhaseData)); vitalDataQueue = xQueueCreate(QUEUE_SIZE, sizeof(VitalData)); uartQueue = xQueueCreate(2048, sizeof(char)); if (phaseDataQueue == NULL || vitalDataQueue == NULL || uartQueue == NULL) { Serial.println("❌ 队列创建失败"); } else { Serial.println("✅ FreeRTOS队列创建成功"); } mySerial1.onReceive(serialRxCallback); Serial.println("✅ 串口中断回调已设置"); xTaskCreatePinnedToCore( bleSendTask, "BleSendTask", TASK_STACK_SIZE, NULL, 3, &bleSendTaskHandle, 1 ); xTaskCreatePinnedToCore( vitalSendTask, "VitalSendTask", TASK_STACK_SIZE, NULL, 2, &vitalSendTaskHandle, 1 ); xTaskCreatePinnedToCore( radarDataTask, "RadarProcessTask", 4096, NULL, 4, NULL, 1 ); xTaskCreatePinnedToCore( uartProcessTask, "UartProcessTask", 4096, NULL, 5, &uartProcessTaskHandle, 1 ); Serial.println("✅ 雷达管理器初始化完成"); } /** * @brief 初始化R60ABD1雷达模组 * 发送初始化命令激活雷达数据上报功能 */ void initR60ABD1() { Serial.println("🔧 初始化R60ABD1雷达模组..."); Serial.println("📡 发送查询指令以激活数据上报..."); uint8_t queryPresenceCmd[] = {0x53, 0x59, 0x80, 0x81, 0x00, 0x01, 0x00, 0x7D, 0x54, 0x43}; mySerial1.write(queryPresenceCmd, sizeof(queryPresenceCmd)); Serial.println("📡 开启核心监测功能..."); sendRadarCommand(0x80, 0x00, 0x01); delay(50); sendRadarCommand(0x81, 0x00, 0x01); delay(50); sendRadarCommand(0x85, 0x00, 0x01); delay(50); sendRadarCommand(0x84, 0x00, 0x01); delay(50); Serial.println("📡 尝试开启波形数据..."); sendRadarCommand(0x81, 0x0C, 0x01); delay(50); sendRadarCommand(0x85, 0x0A, 0x01); delay(50); sendRadarCommand(0x84, 0x13, 0x01); delay(50); sendRadarCommand(0x84, 0x14, 0x01); delay(50); Serial.println("🔍 查询当前状态..."); sendRadarCommand(0x80, 0x80, 0x0F); delay(50); sendRadarCommand(0x81, 0x80, 0x0F); delay(50); sendRadarCommand(0x85, 0x80, 0x0F); delay(50); sendRadarCommand(0x84, 0x80, 0x0F); Serial.println("✅ R60ABD1雷达初始化完成"); } /** * @brief 解析R60ABD1雷达数据帧 * 解析雷达返回的数据帧并提取传感器数据 * @param frame 数据帧指针 * @param frameLen 数据帧长度 * @return 是否解析成功 */ bool parseR60ABD1Frame(uint8_t *frame, uint16_t frameLen) { if(frameLen < 8) return false; if(frame[0] != FRAME_HEADER1 || frame[1] != FRAME_HEADER2 || frame[frameLen-2] != FRAME_TAIL1 || frame[frameLen-1] != FRAME_TAIL2) { return false; } uint8_t checksum = 0; for(int i = 0; i < frameLen-3; i++) { checksum += frame[i]; if(i % 50 == 0) { esp_task_wdt_reset(); } } if(checksum != frame[frameLen-3]) { Serial.println("❌ R60ABD1帧校验和错误"); return false; } for(int i = 0; i < frameLen && i < 20; i++) { Serial.printf("%02X ", frame[i]); } if(frameLen > 20) Serial.print("... "); Serial.printf("| 校验:0x%02X\n", frame[frameLen-3]); uint8_t ctrlByte = frame[2]; uint8_t cmdByte = frame[3]; uint16_t dataLen = (frame[4] << 8) | frame[5]; switch(ctrlByte) { case CTRL_PRESENCE: switch(cmdByte) { case 0x00: case 0x80: if(dataLen >= 1) { if(frame[6] == 0x01) { Serial.println("🔄 人体存在监测功能已开启"); sendRadarCommand(0x84, 0x00, 0x01); } else { Serial.println("🔄 人体存在监测功能已关闭"); } } break; case 0x01: if(dataLen >= 1) { sensorData.presence = frame[6]; Serial.printf("👤 人体存在: %s\n", sensorData.presence ? "有人" : "无人"); } break; case 0x02: if(dataLen >= 1) { sensorData.motion = frame[6]; const char* states[] = {"无", "静止", "活跃"}; Serial.printf("🏃 运动状态: %s\n", states[sensorData.motion]); } break; case 0x03: if(dataLen >= 1) { sensorData.body_movement = frame[6]; Serial.printf("📊体动参数: %d\n", sensorData.body_movement); } break; case 0x04: if(dataLen >= 2) { sensorData.distance = ((uint16_t)frame[6] << 8) | frame[7]; Serial.printf("📏人体距离: %d cm\n", sensorData.distance); } break; case 0x05: if(dataLen >= 6) { uint16_t x_raw = ((uint16_t)frame[6] << 8) | frame[7]; sensorData.pos_x = parseSignedCoordinate(x_raw); uint16_t y_raw = ((uint16_t)frame[8] << 8) | frame[9]; sensorData.pos_y = parseSignedCoordinate(y_raw); uint16_t z_raw = ((uint16_t)frame[10] << 8) | frame[11]; sensorData.pos_z = parseSignedCoordinate(z_raw); Serial.printf("📍方位坐标 - 原始: X=0x%04X, Y=0x%04X, Z=0x%04X\n", x_raw, y_raw, z_raw); Serial.printf(" 解析后: X=%d, Y=%d, Z=%d cm\n", sensorData.pos_x, sensorData.pos_y, sensorData.pos_z); } break; default: Serial.printf("❓未知的0x80命令字: 0x%02X\n", cmdByte); break; } break; case CTRL_BREATH: switch(cmdByte) { case 0x00: case 0x80: if(dataLen >= 1) { if(frame[6] == 0x01) Serial.println("🔄 呼吸监测功能已开启"); else Serial.println("🔄 呼吸监测功能已关闭"); } break; case 0x01: if(dataLen >= 1) { sensorData.breath_status = frame[6]; const char* info_str[] = {"", "正常", "呼吸过高(>25)", "呼吸过低(<10)", "无"}; if(sensorData.breath_status >= 1 && sensorData.breath_status <= 4) { Serial.printf("🔍 呼吸信息: %s\n", info_str[sensorData.breath_status]); } else { Serial.printf("🔍 呼吸信息: 未知状态(0x%02X)\n", sensorData.breath_status); } } break; case 0x02: if(dataLen >= 1) { sensorData.breath_rate = (float)frame[6]; sensorData.breath_valid = (sensorData.breath_rate >= 0.0f && sensorData.breath_rate <= 35.0f); Serial.printf("💨 呼吸率: %.1f 次/分\n", sensorData.breath_rate); } break; case 0x05: if(dataLen >= 5) { for(int i = 0; i < 5 && i < dataLen; i++) { sensorData.breath_waveform[i] = (int8_t)(frame[6+i] - 128); } Serial.printf("📈 呼吸波形: %d\n", sensorData.breath_waveform[0]); } break; default: Serial.printf("❓未知的0x81命令字: 0x%02X\n", cmdByte); break; } break; case CTRL_HEARTRATE: switch(cmdByte) { case 0x00: case 0x80: if(dataLen >= 1) { if(frame[6] == 0x01) Serial.println("🔄 心率监测功能已开启"); else Serial.println("🔄 心率监测功能已关闭"); } break; case 0x02: if(dataLen >= 1) { sensorData.heart_rate = (float)frame[6]; sensorData.heart_valid = (sensorData.heart_rate >= 60.0f && sensorData.heart_rate <= 120.0f); Serial.printf("❤️ 心率: %.1f 次/分\n", sensorData.heart_rate); } break; case 0x05: if(dataLen >= 5) { for(int i = 0; i < 5 && i < dataLen; i++) { sensorData.heart_waveform[i] = (int8_t)(frame[6+i] - 128); } Serial.printf("📈 心率波形: %d\n", sensorData.heart_waveform[0]); } break; default: Serial.printf("❓未知的0x85命令字: 0x%02X\n", cmdByte); break; } break; case CTRL_SLEEP: switch(cmdByte) { case 0x00: case 0x80: if(dataLen >= 1) { if(frame[6] == 0x01) Serial.println("🔄 睡眠监测功能已开启"); else Serial.println("🔄 睡眠监测功能已关闭"); } break; case 0x01: case 0x81: if(dataLen >= 1) { sensorData.bed_status = frame[6]; const char* status_str[] = {"离床", "入床", "无"}; Serial.printf("🛏️ 床状态: %s\n", status_str[sensorData.bed_status]); } break; case 0x03: case 0x83: if(dataLen >= 2) { sensorData.awake_time = ((uint16_t)frame[6] << 8) | (uint16_t)frame[7]; Serial.printf("⏰ 清醒时长: %d 分钟\n", sensorData.awake_time); } break; case 0x04: case 0x84: if(dataLen >= 2) { sensorData.light_sleep_time = ((uint16_t)frame[6] << 8) | (uint16_t)frame[7]; Serial.printf("😪 浅睡时长: %d 分钟\n", sensorData.light_sleep_time); } break; case 0x05: case 0x85: if(dataLen >= 2) { sensorData.deep_sleep_time = ((uint16_t)frame[6] << 8) | (uint16_t)frame[7]; Serial.printf("💤 深睡时长: %d 分钟\n", sensorData.deep_sleep_time); } break; case 0x06: if(dataLen >= 1) { sensorData.sleep_score = frame[6]; Serial.printf("⭐ 睡眠质量评分: %d 分\n", sensorData.sleep_score); } break; case 0x86: if(dataLen >= 2) { sensorData.sleep_score = frame[6]; Serial.printf("⭐ 睡眠质量评分: %d 分\n", sensorData.sleep_score); } break; case 0x0C: case 0x8D: if(dataLen >= 8) { sensorData.presence = frame[6]; sensorData.sleep_state = frame[7]; sensorData.avg_breath_rate = frame[8]; sensorData.avg_heart_rate = frame[9]; sensorData.turnover_count = frame[10]; sensorData.large_move_ratio = frame[11]; sensorData.small_move_ratio = frame[12]; sensorData.apnea_count = frame[13]; Serial.printf("📊 睡眠综合状态 - 存在:%d, 睡眠状态:%d, 睡眠平均呼吸:%d, 睡眠平均心率:%d, 翻身次数:%d, 大动占比:%d%%, 小动占比:%d%%, 呼吸暂停次数:%d\n", sensorData.presence, sensorData.sleep_state, sensorData.avg_breath_rate, sensorData.avg_heart_rate, sensorData.turnover_count, sensorData.large_move_ratio, sensorData.small_move_ratio, sensorData.apnea_count); } break; case 0x0D: case 0x8F: if(dataLen >= 12) { sensorData.sleep_score = frame[6]; sensorData.sleep_total_time = ((uint16_t)frame[7] << 8) | (uint16_t)frame[8]; sensorData.awake_ratio = frame[9]; sensorData.light_sleep_ratio = frame[10]; sensorData.deep_sleep_ratio = frame[11]; sensorData.bed_Out_Time = frame[12]; sensorData.turn_count = frame[13]; sensorData.turnover_count = frame[14]; sensorData.avg_breath_rate = frame[15]; sensorData.avg_heart_rate = frame[16]; sensorData.apnea_count = frame[17]; Serial.printf("📈 睡眠分析报告 - 评分:%d, 总时长:%d分, 清醒占比:%d%%, 浅睡占比:%d%%, 深睡占比:%d%%, 离床时长:%d, 离床次数:%d, 翻身:%d次, 平均呼吸:%d, 平均心跳:%d\n", sensorData.sleep_score, sensorData.sleep_total_time, sensorData.awake_ratio, sensorData.light_sleep_ratio, sensorData.deep_sleep_ratio, sensorData.bed_Out_Time, sensorData.turn_count, sensorData.turnover_count, sensorData.avg_breath_rate, sensorData.avg_heart_rate); } break; case 0x0E: case 0x8E: if(dataLen >= 1) { sensorData.abnormal_state = frame[6]; const char* abnormal_str[] = { "睡眠时长不足4小时", "睡眠时长大于12小时", "长时间异常无人" }; if(sensorData.abnormal_state < 3) { Serial.printf("⚠️ 睡眠异常: %s\n", abnormal_str[sensorData.abnormal_state]); } } break; case 0x10: case 0x90: if(dataLen >= 1) { sensorData.sleep_grade = frame[6]; const char* rating_str[] = {"无", "睡眠质量良好", "睡眠质量一般", "睡眠质量较差"}; if(sensorData.sleep_grade < 4) { Serial.printf("🏆 睡眠质量评级: %s\n", rating_str[sensorData.sleep_grade]); } } break; case 0x11: case 0x91: if(dataLen >= 1) { sensorData.struggle_alert = frame[6]; const char* struggle_str[] = {"无", "正常", "异常挣扎"}; if(sensorData.struggle_alert < 3) { Serial.printf("⚠️ 挣扎状态: %s\n", struggle_str[sensorData.struggle_alert]); } } break; case 0x12: case 0x92: if(dataLen >= 1) { sensorData.no_one_alert = frame[6]; const char* no_one_str[] = {"无", "正常", "异常"}; if(sensorData.no_one_alert < 3) { Serial.printf("⏰ 无人计时状态: %s\n", no_one_str[sensorData.no_one_alert]); } } break; default: Serial.printf("❓未知的0x84命令字: 0x%02X\n", cmdByte); break; } break; case 0x07: if(dataLen >= 1) { if(frame[6] == 0x00) Serial.println("雷达探测范围外"); else Serial.println("雷达探测范围内"); } break; default: Serial.printf("❓未知控制字: 0x%02X\n", ctrlByte); break; } lastSensorUpdate = millis(); sensorData.heart_valid = (sensorData.heart_rate > 0 && sensorData.heart_rate < 200); sensorData.breath_valid = (sensorData.breath_rate >= 0.1f && sensorData.breath_rate <= 60.0f); if( sensorData.heart_valid ==1 && sensorData.heart_valid == 1 && presence_Bit == 1 ) { sensorData.presence = 1; presence_Bit = 0; } return true; } int16_t parseSignedCoordinate(uint16_t raw_value) { bool is_negative = (raw_value & 0x8000) != 0; uint16_t magnitude = raw_value & 0x7FFF; int16_t result = (int16_t)magnitude; if (is_negative) { result = -result; } return result; } /** * @brief 发送雷达命令 * 构造并发送控制命令到雷达模组 * @param ctrl 控制字节 * @param cmd 命令字节 * @param value 值字节 */ void sendRadarCommand(uint8_t ctrl, uint8_t cmd, uint8_t value) { uint8_t command[10]; command[0] = 0x53; command[1] = 0x59; command[2] = ctrl; command[3] = cmd; command[4] = 0x00; command[5] = 0x01; command[6] = value; uint8_t checksum = 0; for(int i = 0; i < 7; i++) { checksum += command[i]; } command[7] = checksum; command[8] = 0x54; command[9] = 0x43; mySerial1.write(command, 10); Serial.printf("📤 发送: "); for(int i = 0; i < 10; i++) { Serial.printf("%02X ", command[i]); } Serial.println(); Serial.printf(" 控制字=0x%02X, 命令字=0x%02X, 值=0x%02X, 校验和=0x%02X\n", ctrl, cmd, value, checksum); } void IRAM_ATTR serialRxCallback() { if (uartQueue != NULL) { while(mySerial1.available()) { char c = mySerial1.read(); BaseType_t xHigherPriorityTaskWoken = pdFALSE; xQueueSendFromISR(uartQueue, &c, &xHigherPriorityTaskWoken); if(xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(); } } } } /** * @brief 检查数据是否发生变化 * 比较当前传感器数据与上次发送的数据,判断是否需要发送更新 * @return 是否发生变化 */ bool isDataChanged() { // 心率变化阈值:0.5 if (fabs(sensorData.heart_rate - lastSentData.heart_rate) > 0.5) { return true; } // 呼吸率变化阈值:0.5 if (fabs(sensorData.breath_rate - lastSentData.breath_rate) > 0.5) { return true; } // 存在状态变化 if (sensorData.presence != lastSentData.presence) { return true; } // 运动状态变化 if (sensorData.motion != lastSentData.motion) { return true; } // 睡眠状态变化 if (sensorData.sleep_state != lastSentData.sleep_state) { return true; } return false; } /** * @brief BLE数据发送任务 * 实现基于数据变化和定时检测的发送机制 * 1. 定时检测数据变化(基于continuousSendInterval) * 2. 检测到变化时立即发送数据 * 3. 发送后更新lastSentData为当前数据 * @param parameter 任务参数(未使用) */ void bleSendTask(void *parameter) { Serial.println("🔁 R60ABD1蓝牙数据发送任务启动"); while (1) { esp_task_wdt_reset(); // 检查是否需要进行数据检测 if (continuousSendEnabled && deviceConnected) { unsigned long currentTime = millis(); // 按照设定的时间间隔进行检测 if (currentTime - lastCheckTime >= continuousSendInterval) { lastCheckTime = currentTime; // 检查数据是否发生变化 if (isDataChanged()) { // 构建雷达数据字符串 String radarDataCore; if (sensorData.presence > 0) { radarDataCore = String(sensorData.heart_rate, 1) + String("|") + String(sensorData.breath_rate, 1) + String("|") + String((int)sensorData.heart_waveform[0]) + String("|") + String((int)sensorData.breath_waveform[0]) + String("|") + String(sensorData.presence) + String("|") + String(sensorData.motion) + String("|") + String(sensorData.sleep_state); } else { radarDataCore = String("0.0") + String("|") + String("0.0") + String("|") + String("0") + String("|") + String("0") + String("|") + String("0") + String("|") + String("0") + String("|") + String("0"); } // 计算CRC校验 unsigned int crc = 0xFFFF; for (int i = 0; i < radarDataCore.length(); i++) { crc ^= (unsigned int)radarDataCore.charAt(i); for (int j = 0; j < 8; j++) { if (crc & 0x0001) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } String radarDataMsg = radarDataCore + String("|") + String(crc, HEX); Serial.printf("📤 通过蓝牙发送R60ABD1雷达数据: %s\n", radarDataMsg.c_str()); const int MAX_BLE_PACKET_SIZE = 20; if (radarDataMsg.length() <= MAX_BLE_PACKET_SIZE) { pCharacteristic->setValue(radarDataMsg.c_str()); pCharacteristic->notify(); Serial.println("✅ R60ABD1雷达数据蓝牙发送成功"); } else { Serial.println("🔄 R60ABD1雷达数据较长,使用分包发送"); sendDataInChunks(radarDataMsg); } // 更新上次发送的数据 lastSentData.heart_rate = sensorData.heart_rate; lastSentData.breath_rate = sensorData.breath_rate; lastSentData.presence = sensorData.presence; lastSentData.motion = sensorData.motion; lastSentData.sleep_state = sensorData.sleep_state; Serial.println("📊 数据已更新,上次发送数据已保存"); } } } vTaskDelay(10 / portTICK_PERIOD_MS); esp_task_wdt_reset(); } } /** * @brief 生命体征数据发送任务 * 从队列中获取生命体征数据并发送到InfluxDB数据库 * @param parameter 任务参数(未使用) */ void vitalSendTask(void *parameter) { Serial.println("🔁🔁 生命体征数据发送任务启动(WiFi数据库传输)"); unsigned long lastSleepDataTime = 0; const unsigned long SLEEP_DATA_INTERVAL = 5000; while (1) { VitalData vitalData; if (xQueueReceive(vitalDataQueue, &vitalData, portMAX_DELAY) == pdTRUE) { esp_task_wdt_reset(); if (WiFi.status() == WL_CONNECTED) { // 检查心率和呼吸率是否都为0,如果是则跳过发送 if (vitalData.heart_rate == 0 || vitalData.breath_rate == 0) { Serial.println("⚠️ 心率和呼吸率都为0,跳过发送数据到数据库"); continue; } String dailyDataLine = "daily_data,deviceId=" + String(currentDeviceId) + ",dataType=daily "; bool firstField = true; if (vitalData.heart_rate > 0) { if (!firstField) dailyDataLine += ","; dailyDataLine += "heartRate=" + String(vitalData.heart_rate, 1); firstField = false; } if (vitalData.breath_rate > 0) { if (!firstField) dailyDataLine += ","; dailyDataLine += "breathingRate=" + String(vitalData.breath_rate, 1); firstField = false; } if (!firstField) dailyDataLine += ","; dailyDataLine += "personDetected=" + String(vitalData.presence) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "humanActivity=" + String(vitalData.motion) + "i"; firstField = false; if (vitalData.distance > 0) { if (!firstField) dailyDataLine += ","; dailyDataLine += "humanDistance=" + String(vitalData.distance) + "i"; firstField = false; } if (vitalData.sleep_state >= 0) { if (!firstField) dailyDataLine += ","; dailyDataLine += "sleepState=" + String(vitalData.sleep_state) + "i"; firstField = false; } if (!firstField) dailyDataLine += ","; dailyDataLine += "humanPositionX=" + String(vitalData.pos_x) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "humanPositionY=" + String(vitalData.pos_y) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "humanPositionZ=" + String(vitalData.pos_z) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "heartbeatWaveform=" + String((int)sensorData.heart_waveform[0]) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "breathingWaveform=" + String((int)sensorData.breath_waveform[0]) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "abnormalState=" + String(vitalData.abnormal_state) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "bedStatus=" + String(vitalData.bed_status) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "struggleAlert=" + String(vitalData.struggle_alert) + "i"; firstField = false; if (!firstField) dailyDataLine += ","; dailyDataLine += "noOneAlert=" + String(vitalData.no_one_alert) + "i"; firstField = false; if (!dailyDataLine.endsWith(" ")) { sendDailyDataToInfluxDB(dailyDataLine); esp_task_wdt_reset(); } unsigned long currentTime = millis(); if (currentTime - lastSleepDataTime >= SLEEP_DATA_INTERVAL) { sendSleepDataToInfluxDB(); lastSleepDataTime = currentTime; Serial.println("⏰ 睡眠数据定时发送完成"); } } else { Serial.println("❌❌ WiFi未连接,无法发送雷达数据到数据库"); static unsigned long lastWifiCheck = 0; if (millis() - lastWifiCheck > 10000) { Serial.printf("📶📶 WiFi状态: %d\n", WiFi.status()); lastWifiCheck = millis(); } } esp_task_wdt_reset(); } vTaskDelay(10 / portTICK_PERIOD_MS); } } /** * @brief 发送日常数据到InfluxDB数据库 * 通过HTTP协议将数据写入InfluxDB时序数据库 * @param dailyDataLine 数据行字符串 */ void sendDailyDataToInfluxDB(String dailyDataLine) { if (WiFi.status() != WL_CONNECTED) { Serial.println("❌ WiFi未连接,无法发送日常数据到数据库"); return; } HTTPClient http; http.setTimeout(2000); String url = String("http://") + String(influxDBHost) + ":" + String(influxDBPort) + "/api/v2/write?org=" + String(influxDBOrg) + "&bucket=" + String(influxDBBucket); http.begin(url); http.addHeader("Authorization", String("Token ") + String(influxDBToken)); http.addHeader("Content-Type", "text/plain; charset=utf-8"); http.setReuse(true); Serial.println(String("📊 发送日常数据到InfluxDB: ") + dailyDataLine); int httpResponseCode = http.POST(dailyDataLine); if (httpResponseCode == 204) { Serial.println("✅ 日常数据发送成功"); } else { Serial.println(String("❌ 发送日常数据失败: ") + String(httpResponseCode) + " - " + http.getString()); } http.end(); } /** * @brief 发送睡眠数据到InfluxDB数据库 * 将睡眠相关的统计数据发送到InfluxDB时序数据库 */ void sendSleepDataToInfluxDB() { if (WiFi.status() != WL_CONNECTED) { Serial.println("❌ WiFi未连接,无法发送睡眠数据到数据库"); return; } if (sensorData.sleep_total_time == 0) { Serial.println("😴 总睡眠时长为0,跳过上传睡眠数据"); return; } HTTPClient http; http.setTimeout(2000); String url = String("http://") + String(influxDBHost) + ":" + String(influxDBPort) + "/api/v2/write?org=" + String(influxDBOrg) + "&bucket=" + String(influxDBBucket); http.begin(url); http.addHeader("Authorization", String("Token ") + String(influxDBToken)); http.addHeader("Content-Type", "text/plain; charset=utf-8"); http.setReuse(true); String lineProtocol = String("sleep_data,deviceId=") + String(currentDeviceId) + ",dataType=sleep "; String fields = ""; fields += String("sleepQualityScore=") + String((int)sensorData.sleep_score) + "i"; fields += ",sleepQualityGrade=" + String((int)sensorData.sleep_grade) + "i"; fields += ",totalSleepDuration=" + String((int)sensorData.sleep_total_time) + "i"; fields += ",awakeDurationRatio=" + String((int)sensorData.awake_ratio) + "i"; fields += ",lightSleepRatio=" + String((int)sensorData.light_sleep_ratio) + "i"; fields += ",deepSleepRatio=" + String((int)sensorData.deep_sleep_ratio) + "i"; fields += ",outOfBedDuration=" + String((int)sensorData.bed_Out_Time) + "i"; fields += ",outOfBedCount=" + String((int)sensorData.turn_count) + "i"; fields += ",turnCount=" + String((int)sensorData.turnover_count) + "i"; fields += ",avgBreathingRate=" + String((int)sensorData.avg_breath_rate) + "i"; fields += ",avgHeartRate=" + String((int)sensorData.avg_heart_rate) + "i"; fields += ",apneaCount=" + String((int)sensorData.apnea_count) + "i"; fields += ",abnormalState=" + String((int)sensorData.abnormal_state) + "i"; fields += ",bodyMovement=" + String((int)sensorData.body_movement) + "i"; fields += ",breathStatus=" + String((int)sensorData.breath_status) + "i"; fields += ",sleepState=" + String((int)sensorData.sleep_state) + "i"; fields += ",largeMoveRatio=" + String((int)sensorData.large_move_ratio) + "i"; fields += ",smallMoveRatio=" + String((int)sensorData.small_move_ratio) + "i"; fields += ",struggleAlert=" + String((int)sensorData.struggle_alert) + "i"; fields += ",noOneAlert=" + String((int)sensorData.no_one_alert) + "i"; fields += ",awakeDuration=" + String((int)sensorData.awake_time) + "i"; fields += ",lightSleepDuration=" + String((int)sensorData.light_sleep_time) + "i"; fields += ",deepSleepDuration=" + String((int)sensorData.deep_sleep_time) + "i"; lineProtocol += fields; Serial.println(String("🌙 发送睡眠数据到InfluxDB: ") + lineProtocol); int httpResponseCode = http.POST(lineProtocol); if (httpResponseCode == 204) { Serial.println(String("✅ 睡眠数据已保存到InfluxDB设备") + String(currentDeviceId) + "上"); } else { Serial.println(String("❌ 保存睡眠数据到InfluxDB失败: ") + String(httpResponseCode) + " - " + http.getString()); } http.end(); } /** * @brief 雷达数据处理任务 * 处理雷达数据并分发到相应的队列 * @param parameter 任务参数(未使用) */ void radarDataTask(void *parameter) { Serial.println("🔁 雷达数据处理任务启动(最高优先级)"); while (1) { vTaskDelay(100 / portTICK_PERIOD_MS); } } /** * @brief UART数据处理任务 * 从UART队列中读取数据并解析雷达数据帧 * @param parameter 任务参数(未使用) */ void uartProcessTask(void *parameter) { uint8_t buffer[256]; int bufferIndex = 0; bool inFrame = false; uint8_t prevByte = 0; Serial.println("✅ R60ABD1串口数据处理任务启动"); while(1) { uint8_t c; if(xQueueReceive(uartQueue, &c, 10 / portTICK_PERIOD_MS) == pdTRUE) { esp_task_wdt_reset(); if(!inFrame) { if(prevByte == FRAME_HEADER1 && c == FRAME_HEADER2) { buffer[0] = FRAME_HEADER1; buffer[1] = FRAME_HEADER2; bufferIndex = 2; inFrame = true; Serial.println("🔍 检测到R60ABD1帧头"); } } else { if(bufferIndex < sizeof(buffer)) { buffer[bufferIndex++] = c; if(bufferIndex >= 8 && buffer[bufferIndex-2] == FRAME_TAIL1 && buffer[bufferIndex-1] == FRAME_TAIL2) { if(parseR60ABD1Frame(buffer, bufferIndex)) { static uint32_t frameCounter = 0; frameCounter++; lastSensorUpdate = millis(); static uint32_t phasePacketCounter = 0; static uint32_t vitalPacketCounter = 0; phasePacketCounter++; if (phasePacketCounter >= PHASE_SEND_INTERVAL) { PhaseData phaseData; phaseData.heartbeat_waveform = sensorData.heartbeat_waveform; phaseData.breathing_waveform = sensorData.breathing_waveform; if (xQueueSend(phaseDataQueue, &phaseData, 0) == pdTRUE) { } else { Serial.println("❌ 相位数据队列已满,数据丢失"); } phasePacketCounter = 0; } vitalPacketCounter++; if (vitalPacketCounter >= VITAL_SEND_INTERVAL) { VitalData vitalData; vitalData.heart_rate = sensorData.heart_rate; vitalData.breath_rate = sensorData.breath_rate; vitalData.presence = sensorData.presence; vitalData.motion = sensorData.motion; vitalData.distance = sensorData.distance; vitalData.sleep_state = sensorData.sleep_state; vitalData.sleep_score = sensorData.sleep_score; vitalData.body_movement = sensorData.body_movement; vitalData.breath_status = sensorData.breath_status; vitalData.sleep_time = sensorData.sleep_time; vitalData.bed_status = sensorData.bed_status; vitalData.abnormal_state = sensorData.abnormal_state; vitalData.avg_heart_rate = sensorData.avg_heart_rate; vitalData.avg_breath_rate = sensorData.avg_breath_rate; vitalData.turn_count = sensorData.turn_count; vitalData.large_move_ratio = sensorData.large_move_ratio; vitalData.small_move_ratio = sensorData.small_move_ratio; vitalData.pos_x = sensorData.pos_x; vitalData.pos_y = sensorData.pos_y; vitalData.pos_z = sensorData.pos_z; vitalData.deep_sleep_time = sensorData.deep_sleep_time; vitalData.light_sleep_time = sensorData.light_sleep_time; vitalData.awake_time = sensorData.awake_time; vitalData.sleep_total_time = sensorData.sleep_total_time; vitalData.deep_sleep_ratio = sensorData.deep_sleep_ratio; vitalData.light_sleep_ratio = sensorData.light_sleep_ratio; vitalData.awake_ratio = sensorData.awake_ratio; vitalData.turnover_count = sensorData.turnover_count; vitalData.struggle_alert = sensorData.struggle_alert; vitalData.no_one_alert = sensorData.no_one_alert; vitalData.apnea_count = sensorData.apnea_count; vitalData.heartbeat_waveform = sensorData.heartbeat_waveform; vitalData.breathing_waveform = sensorData.breathing_waveform; if (xQueueSend(vitalDataQueue, &vitalData, 0) == pdTRUE) { Serial.println("📤 生命体征数据已加入发送队列"); } else { Serial.println("❌ 生命体征数据队列已满,数据丢失"); } vitalPacketCounter = 0; } if(frameCounter % 100 == 0) { Serial.printf("📈 已处理 %d 个R60ABD1数据帧\n", frameCounter); } } inFrame = false; } } else { Serial.println("⚠️ R60ABD1帧缓冲区溢出,重置接收状态"); inFrame = false; } } prevByte = c; } vTaskDelay(1 / portTICK_PERIOD_MS); esp_task_wdt_reset(); } } /** * @brief 分块发送数据 * 将大数据分块发送,避免BLE MTU限制 * @param data 要发送的数据字符串 */ void sendDataInChunks(const String& data) { const int MAX_PACKET_SIZE = 20; const int HEADER_SIZE = 6; const int CHUNK_SIZE = MAX_PACKET_SIZE - HEADER_SIZE; int totalLength = data.length(); int numChunks = (totalLength + CHUNK_SIZE - 1) / CHUNK_SIZE; Serial.printf("📦 开始分包发送,总长度: %d, 分包数: %d\n", totalLength, numChunks); for(int i = 0; i < numChunks; i++) { int start = i * CHUNK_SIZE; int chunkLength = min(CHUNK_SIZE, totalLength - start); String chunk = data.substring(start, start + chunkLength); String packetHeader = String("[") + String(i+1) + String("/") + String(numChunks) + String("]"); int maxDataLength = MAX_PACKET_SIZE - packetHeader.length(); if (chunk.length() > maxDataLength) { chunk = chunk.substring(0, maxDataLength); } String packet = packetHeader + chunk; Serial.printf("📤 发送分包 %s: %s\n", packetHeader.c_str(), chunk.c_str()); if (!deviceConnected) { Serial.println("❌ BLE未连接,无法发送数据"); return; } pCharacteristic->setValue(packet.c_str()); pCharacteristic->notify(); Serial.println("✅ 分包发送成功"); if (i < numChunks - 1) { Serial.printf("⏳ 等待接收端处理第%d个包...\n", i+1); vTaskDelay(20 / portTICK_PERIOD_MS); } } Serial.println("📦 分包发送完成"); } /** * @brief 发送JSON数据到BLE * 将JSON格式数据通过BLE发送给客户端 * @param jsonData JSON格式数据字符串 */ void sendJSONDataToBLE(const String& jsonData) { Serial.printf("📤 准备发送JSON数据: %s\n", jsonData.c_str()); if (!deviceConnected) { Serial.println("❌ BLE未连接,无法发送JSON数据"); return; } const int MAX_PACKET_SIZE = 20; int totalLength = jsonData.length(); int numChunks = (totalLength + MAX_PACKET_SIZE - 1) / MAX_PACKET_SIZE; Serial.printf("📦 开始分包发送JSON,总长度: %d, 分包数: %d\n", totalLength, numChunks); for(int i = 0; i < numChunks; i++) { int start = i * MAX_PACKET_SIZE; int chunkLength = min(MAX_PACKET_SIZE, totalLength - start); String chunk = jsonData.substring(start, start + chunkLength); Serial.printf("📤 发送JSON分包 %d/%d: %s\n", i+1, numChunks, chunk.c_str()); pCharacteristic->setValue(chunk.c_str()); pCharacteristic->notify(); Serial.println("✅ JSON分包发送成功"); if (i < numChunks - 1) { Serial.printf("⏳ 等待接收端处理第%d个包...\n", i+1); vTaskDelay(10 / portTICK_PERIOD_MS); } } Serial.println("📦 JSON分包发送完成"); } /** * @brief 发送自定义JSON数据到BLE * 构造自定义JSON格式数据并通过BLE发送 * @param jsonType JSON类型 * @param jsonString JSON内容字符串 * @return 是否发送成功 */ bool sendCustomJSONData(const String& jsonType, const String& jsonString) { if (!deviceConnected) { Serial.println("❌ BLE未连接,无法发送自定义JSON数据"); return false; } String fullJSON = String("{\"type\":\"") + jsonType + String("\",") + jsonString + String("}"); Serial.printf("📤 发送自定义JSON数据类型 '%s': %s\n", jsonType.c_str(), fullJSON.c_str()); sendJSONDataToBLE(fullJSON); return true; } /** * @brief 发送雷达数据到BLE * 发送雷达传感器数据(已移至FreeRTOS任务处理) */ void sendRadarDataToBLE() { Serial.println("ℹ️ 雷达数据发送已移至FreeRTOS任务处理"); } /** * @brief 处理查询雷达数据命令 * 处理来自BLE的雷达数据查询请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processQueryRadarData(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "queryRadarData") == 0) { Serial.println("收到查询雷达数据命令"); if (deviceConnected) { String radarDataMsg = String("{\"type\":\"radarData\",\"success\":true") + String(",\"deviceId\":") + String(currentDeviceId) + String(",\"timestamp\":") + String(millis()) + String(",\"presence\":") + String(sensorData.presence) + String(",\"heartRate\":") + String(sensorData.heart_rate, 1) + String(",\"breathRate\":") + String(sensorData.breath_rate, 1) + String(",\"motion\":") + String(sensorData.motion) + String(",\"heartbeatWaveform\":") + String((int)sensorData.breath_waveform[0]) + String(",\"breathingWaveform\":") + String((int)sensorData.heart_waveform[0]) + String(",\"distance\":") + String(sensorData.distance) + String(",\"bodyMovement\":") + String(sensorData.body_movement) + String(",\"breathStatus\":") + String(sensorData.breath_status) + String(",\"sleepState\":") + String(sensorData.sleep_state) + String(",\"sleepTime\":") + String(sensorData.sleep_time) + String(",\"sleepScore\":") + String(sensorData.sleep_score) + String(",\"avgHeartRate\":") + String(sensorData.avg_heart_rate) + String(",\"avgBreathRate\":") + String(sensorData.avg_breath_rate) + String(",\"turnCount\":") + String(sensorData.turn_count) + String(",\"largeMoveRatio\":") + String(sensorData.large_move_ratio) + String(",\"smallMoveRatio\":") + String(sensorData.small_move_ratio) + String("}"); sendJSONDataToBLE(radarDataMsg); Serial.println("已发送雷达数据"); Serial.printf("发送的数据: %s\n", radarDataMsg.c_str()); } else { Serial.println("BLE未连接,无法发送雷达数据"); } return true; } return false; } /** * @brief 处理启动持续发送命令 * 处理来自BLE的启动持续发送请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processStartContinuousSend(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "startContinuousSend") == 0) { if (doc["interval"].is()) { continuousSendInterval = doc["interval"].as(); if (continuousSendInterval < 100) continuousSendInterval = 100; if (continuousSendInterval > 10000) continuousSendInterval = 10000; } continuousSendEnabled = true; bleFlow.reset(); Serial.printf("⚙️ 启动持续发送模式,间隔: %lu ms\n", continuousSendInterval); if (deviceConnected) { String confirmMsg = String("{\"type\":\"startContinuousSendResult\",\"success\":true,\"message\":\"已启动持续发送模式\",\"interval\":") + String(continuousSendInterval) + "}"; sendJSONDataToBLE(confirmMsg); Serial.println("✅ 启动确认消息发送成功"); Serial.println("🚀 已启动持续发送模式"); } else { Serial.println("❌ BLE未连接,无法发送确认消息"); } return true; } return false; } /** * @brief 处理停止持续发送命令 * 处理来自BLE的停止持续发送请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processStopContinuousSend(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "stopContinuousSend") == 0) { continuousSendEnabled = false; Serial.println("🛑 停止持续发送模式"); if (deviceConnected) { String confirmMsg = String("{\"type\":\"stopContinuousSendResult\",\"success\":true,\"message\":\"已停止持续发送模式\"}"); sendJSONDataToBLE(confirmMsg); Serial.println("✅ 停止确认消息发送成功"); Serial.println("⏹️ 已停止持续发送模式"); } else { Serial.println("❌ BLE未连接,无法发送确认消息"); } return true; } return false; } /** * @brief 处理BLE配置数据 * 处理从BLE接收到的配置数据,解析JSON命令并执行相应操作 */ void processBLEConfig() { if (completeData.length() > 0 && (millis() - lastReceiveTime > 3000)) { Serial.println("⏰ [超时] 数据接收超时3秒,自动当作接收完成"); if (receivedData.length() == 0) { Serial.println("📥 [BLE] 超时后将completeData当作接收数据进行处理"); receivedData = completeData; } completeData = ""; } if (receivedData.length() > 0) { String bleData = receivedData; receivedData = ""; bleData.trim(); Serial.printf("⚙️ [BLE] 准备解析JSON: %s\n", bleData.c_str()); if (bleData.startsWith("{") && bleData.endsWith("}")) { JsonDocument doc; DeserializationError error = deserializeJson(doc, bleData); if (error) { String errorMsg = String("❌ [BLE] JSON解析失败: ") + String(error.c_str()); Serial.println(errorMsg); if (deviceConnected) { String responseMsg = String("{\"type\":\"error\",\"message\":\"配置格式错误,请使用JSON格式\",\"originalData\":\"") + bleData + String("\"}"); sendJSONDataToBLE(responseMsg); } } else { Serial.println("✅ [BLE] JSON解析成功"); bool processed = false; if (!processed) processed = processSetDeviceId(doc); if (!processed) processed = processWiFiConfigCommand(doc); if (!processed) processed = processQueryStatus(doc); if (!processed) processed = processQueryRadarData(doc); if (!processed) processed = processStartContinuousSend(doc); if (!processed) processed = processStopContinuousSend(doc); if (!processed) processed = processScanWiFi(doc); if (!processed) processed = processGetSavedNetworks(doc); if (!processed) processed = processEchoRequest(doc); if (!processed) { Serial.println("❓[BLE] 未知命令"); if (deviceConnected) { String responseMsg = String("{\"type\":\"error\",\"message\":\"未知命令\",\"receivedData\":\"") + bleData + String("\"}"); sendJSONDataToBLE(responseMsg); } } } } else { Serial.println("📥 [BLE] 接收到非JSON数据"); } } } /** * @brief 处理设置设备ID命令 * 处理来自BLE的设置设备ID请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processSetDeviceId(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "setDeviceId") == 0) { uint16_t newDeviceId = doc["newDeviceId"]; if (newDeviceId < 1000 || newDeviceId > 1999){ Serial.printf("[错误] 设备ID超出范围,有效范围: 1000-1999\n"); if (deviceConnected) { String errorMsg = String("{\"type\":\"error\",\"message\":\"设备ID超出范围,有效范围: 1000-1999\"}"); sendJSONDataToBLE(errorMsg); } return true; } currentDeviceId = newDeviceId; Serial.printf("[设备ID] 已设置新的设备ID: %u\n", currentDeviceId); saveDeviceId(); Serial.printf("设备ID已保存到Flash: %u\n", currentDeviceId); if (deviceConnected) { String confirmMsg = String("{\"type\":\"setDeviceIdResult\",\"success\":true,\"message\":\"设备ID设置成功\",\"newDeviceId\":") + String(newDeviceId) + "}"; sendJSONDataToBLE(confirmMsg); sendStatusToBLE(); } return true; } return false; } /** * @brief 发送设备状态到BLE * 将当前设备状态信息通过BLE发送给客户端 */ void sendStatusToBLE() { if (deviceConnected) { String statusMsg = String("{\"type\":\"status\",\"wifiConfigured\":") + String(wifiManager.getSavedNetworkCount() > 0 ? "true" : "false") + String(",\"wifiConnected\":") + String(WiFi.status() == WL_CONNECTED ? "true" : "false") + String(",\"ipAddress\":\"") + (WiFi.status() == WL_CONNECTED ? WiFi.localIP().toString() : "") + "\"" + String(",\"deviceId\":") + String(currentDeviceId) + "}"; sendJSONDataToBLE(statusMsg); Serial.println("已发送连接状态信息"); } } /** * @brief 处理查询状态命令 * 处理来自BLE的查询设备状态请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processQueryStatus(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "queryStatus") == 0) { if (deviceConnected) { String statusMsg = String("{\"type\":\"deviceStatus\",\"success\":true,\"deviceId\":") + String(currentDeviceId) + String(",\"wifiConfigured\":") + String(wifiManager.getSavedNetworkCount() > 0 ? "true" : "false") + String(",\"wifiConnected\":") + String(WiFi.status() == WL_CONNECTED ? "true" : "false") + String(",\"ipAddress\":\"") + (WiFi.status() == WL_CONNECTED ? WiFi.localIP().toString() : "") + String("\"}"); sendJSONDataToBLE(statusMsg); Serial.println("已发送设备状态信息"); } return true; } return false; } /** * @brief 处理WiFi配置命令 * 处理来自BLE的WiFi配置请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processWiFiConfigCommand(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "setWiFiConfig") == 0) { Serial.println("📱 [BLE-WiFi] 收到WiFi配置命令"); const char* newSSID = doc["ssid"]; const char* newPassword = doc["password"]; if (newSSID != nullptr && newPassword != nullptr) { return wifiManager.handleConfigurationData(newSSID, newPassword); } else { Serial.println("❌ [BLE-WiFi] WiFi配置参数不完整"); if (deviceConnected) { String errorMsg = String("{\"type\":\"error\",\"message\":\"WiFi配置参数不完整,需要ssid和password字段\"}"); sendJSONDataToBLE(errorMsg); } return true; } } return false; } /** * @brief 处理扫描WiFi命令 * 处理来自BLE的WiFi扫描请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processScanWiFi(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "scanWiFi") == 0) { Serial.println("📱 [BLE-WiFi] 收到WiFi扫描命令"); wifiManager.scanAndSendResults(); return true; } return false; } bool processGetSavedNetworks(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "getSavedNetworks") == 0) { Serial.println("📱 [BLE-WiFi] 收到获取已保存WiFi网络命令"); wifiManager.getSavedNetworks(); return true; } return false; } /** * @brief 处理回显请求命令 * 处理来自BLE的回显测试请求 * @param doc JSON文档对象 * @return 是否处理成功 */ bool processEchoRequest(JsonDocument& doc) { const char* command = doc["command"]; if (command != nullptr && strcmp(command, "echo") == 0) { Serial.println("📱 [BLE] 收到回显请求"); const char* echoContent = doc["content"]; if (echoContent != nullptr) { String echoResponse = String("{\"type\":\"echoResponse\",\"originalContent\":\"") + echoContent + String("\",\"receivedSuccessfully\":true}"); if (deviceConnected) { sendJSONDataToBLE(echoResponse); Serial.printf("📤 [BLE] 回显响应已发送: %s\n", echoContent); } } else { String echoResponse = String("{\"type\":\"echoResponse\",\"receivedSuccessfully\":true,\"message\":\"Echo command received\"}"); if (deviceConnected) { sendJSONDataToBLE(echoResponse); Serial.println("📤 [BLE] 简单回显响应已发送"); } } return true; } return false; } /** * @brief 发送原始数据回显响应 * 将接收到的原始数据通过BLE回显给客户端 * @param rawData 原始数据字符串 */ void sendRawEchoResponse(const String& rawData) { if (deviceConnected) { String echoResponse = String("{\"type\":\"rawEchoResponse\",\"originalData\":\"") + rawData + String("\",\"received\":true}"); sendJSONDataToBLE(echoResponse); Serial.printf("📤 [BLE] 原始数据回显已发送: %s\n", rawData.c_str()); } }