feat:增加蓝牙配网功能

This commit is contained in:
2026-08-12 09:20:54 +08:00
parent 2ce4ac0b9c
commit 93112dcdfd
11 changed files with 1163 additions and 561 deletions
+59 -13
View File
@@ -19,6 +19,11 @@ RadarManager::RadarManager()
, _callback(nullptr)
, _frameCount(0)
, _errorCount(0)
, _lastHeartBeat(0)
, _lastBreathBeat(0)
, _stablePresence(false)
, _presenceCnt(0)
, _lastRawPresence(false)
{
memset(&_currentFrame, 0, sizeof(_currentFrame));
memset(&_data, 0, sizeof(_data));
@@ -43,6 +48,9 @@ bool RadarManager::begin() {
_resetParser();
memset(&_data, 0, sizeof(_data));
_data.lastUpdate = millis();
_stablePresence = false;
_presenceCnt = 0;
_lastRawPresence = false;
// 不给雷达发任何命令,让它自己初始化并开始自动上报
// R60ABD1 上电后通常需要 15-30 秒自检,之后自动输出数据
@@ -68,6 +76,16 @@ void RadarManager::loop() {
Serial.printf("[雷达] ✅ 开始接收数据 (首帧)\n");
}
// 心率/呼吸数据过期 (>10秒无更新 → 标记无效)
if (millis() - _lastHeartBeat > 10000) {
_data.vitalValid = false;
_data.heartRate = 0;
}
if (millis() - _lastBreathBeat > 10000) {
_data.vitalValid = false;
_data.breathRate = 0;
}
// 超时检测:如果 10 秒还没收到任何数据,打印一次
static uint32_t noDataWarn = 0;
if (_frameCount == 0 && millis() - _data.lastUpdate > 10000) {
@@ -222,6 +240,9 @@ void RadarManager::_processCompleteFrame() {
case CTRL_HEART_RATE:
_extractHeartRate(_currentFrame);
break;
case CTRL_FALL:
_extractFall(_currentFrame); // AFD1 专用跌倒
break;
case CTRL_SLEEP:
_extractSleep(_currentFrame);
break;
@@ -250,47 +271,60 @@ void RadarManager::_processCompleteFrame() {
void RadarManager::_extractPresence(const RadarFrame& frame) {
uint8_t raw = frame.data_length > 0 ? frame.data[0] : 0;
bool rawPresence = false;
// cmd 0x00 (len=1): 有人状态 (1=有人 0=无人)
if (frame.command == 0x00 && frame.data_length >= 1) {
_data.presence = (raw == 1);
rawPresence = (raw == 1);
_data.radarValid = true;
_data.lastUpdate = millis();
_notifyUpdate();
}
// cmd 0x01 (len=1): 运动状态/体动 (值越大越活跃)
else if (frame.command == 0x01 && frame.data_length >= 1) {
_data.body = raw; // 0=静止, 1+=有体动
_data.motion = (raw >= 1); // >=1 有运动
_data.body = raw;
_data.motion = (raw >= 1);
_data.radarValid = true;
_data.lastUpdate = millis();
_notifyUpdate();
return; // 运动帧不含有人信息, 跳过防抖
}
// cmd 0x03 (len=1): 有人状态备用 (非0=有人)
else if (frame.command == 0x03 && frame.data_length >= 1) {
_data.presence = (raw != 0);
rawPresence = (raw != 0);
_data.radarValid = true;
_data.lastUpdate = millis();
_notifyUpdate();
}
// cmd 0x04 (len=2): [0]=presence [1]=motion
else if (frame.command == 0x04 && frame.data_length >= 2) {
_data.presence = (frame.data[0] != 0);
_data.motion = (frame.data[1] == 0);
rawPresence = (frame.data[0] != 0);
_data.motion = (frame.data[1] == 0);
_data.radarValid = true;
_data.lastUpdate = millis();
_notifyUpdate();
}
// cmd 0x05 (len=6): 完整包
else if (frame.command == 0x05 && frame.data_length >= 6) {
_data.presence = (frame.data[0] != 0);
rawPresence = (frame.data[0] != 0);
_data.motion = (frame.data[1] == 0);
_data.distance = ((uint16_t)frame.data[2] << 8) | frame.data[3];
_data.body = frame.data[4];
_data.radarValid = true;
_data.lastUpdate = millis();
_notifyUpdate();
} else {
return; // 未知命令
}
// 防抖: 连续 PRESENCE_HYSTERESIS 次一致才更新
if (rawPresence == _lastRawPresence) {
if (_presenceCnt < PRESENCE_HYSTERESIS) _presenceCnt++;
} else {
_presenceCnt = 0;
_lastRawPresence = rawPresence;
}
if (_presenceCnt >= PRESENCE_HYSTERESIS && rawPresence != _data.presence) {
_data.presence = rawPresence;
_stablePresence = rawPresence;
}
_notifyUpdate();
}
void RadarManager::_extractBreathing(const RadarFrame& frame) {
@@ -299,8 +333,9 @@ void RadarManager::_extractBreathing(const RadarFrame& frame) {
if (rate != 0x80 && rate != 0x00 && rate <= 40) {
_data.breathRate = rate;
_data.vitalValid = true;
_data.presence = true; // 有呼吸=有人
_data.presence = true;
_data.radarValid = true;
_lastBreathBeat = millis();
}
_data.lastUpdate = millis();
_notifyUpdate();
@@ -313,14 +348,25 @@ void RadarManager::_extractHeartRate(const RadarFrame& frame) {
if (rate != 0x80 && rate != 0x00 && rate >= 40) {
_data.heartRate = rate;
_data.vitalValid = true;
_data.presence = true; // 有心跳=有人
_data.presence = true;
_data.radarValid = true;
_lastHeartBeat = millis();
}
_data.lastUpdate = millis();
_notifyUpdate();
}
}
// AFD1 专用: 跌倒检测 (控制字 0x83)
void RadarManager::_extractFall(const RadarFrame& frame) {
if (frame.data_length >= 1) {
_data.fall = (frame.data[0] != 0);
_data.radarValid = true;
_data.lastUpdate = millis();
_notifyUpdate();
}
}
void RadarManager::_extractSleep(const RadarFrame& frame) {
// 从睡眠数据提取: cmd=0x00/0x01 为入床离床状态
if (frame.data_length >= 1) {