Files
Rader_Success_5/src/radar_manager.cpp

1722 lines
66 KiB
C++
Raw Normal View History

#include "radar_manager.h"
#include "wifi_manager.h"
#include <Preferences.h>
#include <esp_task_wdt.h>
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<uint32_t>()) {
continuousSendInterval = doc["interval"].as<uint32_t>();
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());
}
}