fix:修复 MQTT 断线重连,修改报警阈值,减少误报
This commit is contained in:
+43
-1
@@ -63,11 +63,15 @@ uint32_t g_breathNormalMs = 0; // 呼吸正常持续计时 (ms)
|
||||
uint32_t g_fallDetectMs = 0; // 跌倒检测计时 (ms)
|
||||
uint32_t g_fallClearMs = 0; // 跌倒清除计时 (ms)
|
||||
bool g_fallDismissed = false; // 已手动解除, 不重复报警
|
||||
uint32_t g_vitalLostMs = 0; // 生命体征丢失持续计时 (ms)
|
||||
bool g_vitalLostActive = false; // 生命体征丢失报警激活
|
||||
bool g_vitalLostDismissed = false; // 生命体征丢失解除抑制
|
||||
#define ALARM_HYSTERESIS 3 // 连续3次确认才触发
|
||||
#define FALL_DETECT_MS 10000 // 跌倒持续10秒才触发 (房顶安装, 过滤坐下)
|
||||
#define FALL_CLEAR_MS 18000 // 跌倒消失18秒后才清除 (防误消)
|
||||
#define VITAL_DETECT_MS 20000 // 心率/呼吸持续异常20秒才触发
|
||||
#define VITAL_CLEAR_MS 15000 // 心率/呼吸持续正常15秒才恢复
|
||||
#define VITAL_LOST_MS 60000 // 在床但心率呼吸持续为0达60秒 → 疑似骤停
|
||||
|
||||
// ============================================================
|
||||
// 时间同步
|
||||
@@ -126,6 +130,8 @@ void handleAlarmCommand(const AlarmCommand& cmd) {
|
||||
g_fallDetectMs = 0;
|
||||
g_fallClearMs = 0;
|
||||
g_fallDismissed = false;
|
||||
g_vitalLostMs = 0;
|
||||
g_vitalLostActive = false;
|
||||
|
||||
// 解除抑制标志也复位 (远程恢复后重新武装)
|
||||
g_waterDismissed = false;
|
||||
@@ -133,6 +139,7 @@ void handleAlarmCommand(const AlarmCommand& cmd) {
|
||||
g_breathDismissed = false;
|
||||
g_tempDismissed = false;
|
||||
g_humiDismissed = false;
|
||||
g_vitalLostDismissed = false;
|
||||
} else {
|
||||
// 告警触发
|
||||
g_alarm.executeAlarm(cmd);
|
||||
@@ -263,7 +270,8 @@ TelemetryData buildTelemetry(const RadarRawData& radar) {
|
||||
t.breathRate = radar.breathRate;
|
||||
t.body = radar.body;
|
||||
t.sleepState = radar.sleepState;
|
||||
t.sleepScore = radar.sleepScore;
|
||||
// 清醒时不报睡眠评分 (雷达此时的值是残留/无意义), 避免误导
|
||||
t.sleepScore = (radar.resident && radar.sleepState != 0) ? radar.sleepScore : 0;
|
||||
t.radarValid = radar.radarValid;
|
||||
t.vitalValid = radar.vitalValid;
|
||||
|
||||
@@ -425,6 +433,37 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
}
|
||||
#endif // RADAR_TYPE != AFD1
|
||||
|
||||
// ─── ★★★★★ 人身安全: 生命体征丢失 (在床但心率呼吸持续为0 → 疑似骤停/死亡) ───
|
||||
// 用 resident(在床) 而非 presence(有人): 人离房时 presence 有保持时间会误报,
|
||||
// 而 resident 离床即清, 精准区分"人离开"和"人死在床上"。复用 心率+呼吸异常 类型。
|
||||
#if RADAR_TYPE != RADAR_TYPE_AFD1
|
||||
if (enVital && millis() > 30000) {
|
||||
bool vitalLost = radar.resident && radar.heartRate == 0 && radar.breathRate == 0;
|
||||
if (vitalLost) {
|
||||
if (!g_vitalLostActive && !g_vitalLostDismissed) {
|
||||
if (g_vitalLostMs == 0) {
|
||||
g_vitalLostMs = millis();
|
||||
} else if (millis() - g_vitalLostMs >= VITAL_LOST_MS) {
|
||||
g_vitalLostActive = true;
|
||||
g_vitalLostMs = 0;
|
||||
g_alarm.triggerLocal(AlarmManager::ALARM_HEART_ABNORMAL, "生命体征丢失(疑似骤停)");
|
||||
g_alarm.triggerLocal(AlarmManager::ALARM_BREATH_ABNORMAL, "生命体征丢失(疑似骤停)");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g_vitalLostMs = 0;
|
||||
if (g_vitalLostActive) {
|
||||
g_vitalLostActive = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL);
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL);
|
||||
}
|
||||
if (g_vitalLostDismissed) {
|
||||
g_vitalLostDismissed = false; // 体征恢复或离床后重新武装
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // RADAR_TYPE != AFD1
|
||||
|
||||
// ─── ★★★ 环境安全: 水浸 (仅浴室) ───
|
||||
if (enWater) {
|
||||
bool waterLeak = !g_sensor.getRainDO() && g_sensor.isRainValid();
|
||||
@@ -594,12 +633,15 @@ void setup() {
|
||||
g_radarTimeoutCnt = 0;
|
||||
g_fallClearMs = 0;
|
||||
g_fallDismissed = true; // 抑制重复报警, 等跌倒信号消了再恢复
|
||||
g_vitalLostMs = 0;
|
||||
g_vitalLostActive = false;
|
||||
// 其余类型同样抑制, 条件恢复正常后才重新武装
|
||||
g_waterDismissed = true;
|
||||
g_heartDismissed = true;
|
||||
g_breathDismissed = true;
|
||||
g_tempDismissed = true;
|
||||
g_humiDismissed = true;
|
||||
g_vitalLostDismissed = true;
|
||||
});
|
||||
g_buttons.onProvisionLongPress([]() {
|
||||
g_wifi.startConfigPortal();
|
||||
|
||||
@@ -145,6 +145,16 @@ bool MQTTManager::isConnected() {
|
||||
// ============================================================
|
||||
|
||||
void MQTTManager::loop() {
|
||||
// 连接实际已断开 (网络抖动/broker重启/心跳超时), 复位标志触发重连
|
||||
// 否则 _connected 永远为 true, 下面 else 分支只调 _mqtt.loop() 却不重连,
|
||||
// 设备会卡在"WiFi通/MQTT死"的僵尸状态 (小程序显示离线)
|
||||
if (_connected && !_mqtt.connected()) {
|
||||
Serial.println("[MQTT] ⚠️ 连接断开, 触发重连...");
|
||||
_connected = false;
|
||||
_reconnectInterval = MQTT_RECONNECT_MIN;
|
||||
_lastReconnectAttempt = 0;
|
||||
}
|
||||
|
||||
if (!_connected) {
|
||||
uint32_t now = millis();
|
||||
if (now - _lastReconnectAttempt >= _reconnectInterval) {
|
||||
|
||||
Reference in New Issue
Block a user