diff --git a/src/main.cpp b/src/main.cpp index 29da683..f7a647c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,14 +56,18 @@ bool g_humiDismissed = false; uint8_t g_tempAbnCnt = 0; uint8_t g_humiAbnCnt = 0; uint8_t g_radarTimeoutCnt = 0; -uint8_t g_heartAbnCnt = 0; // 心率异常防抖 -uint8_t g_breathAbnCnt = 0; // 呼吸异常防抖 +uint32_t g_heartAbnMs = 0; // 心率异常持续计时 (ms) +uint32_t g_heartNormalMs = 0; // 心率正常持续计时 (ms) +uint32_t g_breathAbnMs = 0; // 呼吸异常持续计时 (ms) +uint32_t g_breathNormalMs = 0; // 呼吸正常持续计时 (ms) uint32_t g_fallDetectMs = 0; // 跌倒检测计时 (ms) uint32_t g_fallClearMs = 0; // 跌倒清除计时 (ms) bool g_fallDismissed = false; // 已手动解除, 不重复报警 #define ALARM_HYSTERESIS 3 // 连续3次确认才触发 -#define FALL_DETECT_MS 2000 // 跌倒持续2秒才触发 (房顶安装, 过滤坐下) -#define FALL_CLEAR_MS 5000 // 跌倒消失5秒后才清除 (防误消) +#define FALL_DETECT_MS 10000 // 跌倒持续10秒才触发 (房顶安装, 过滤坐下) +#define FALL_CLEAR_MS 18000 // 跌倒消失18秒后才清除 (防误消) +#define VITAL_DETECT_MS 20000 // 心率/呼吸持续异常20秒才触发 +#define VITAL_CLEAR_MS 15000 // 心率/呼吸持续正常15秒才恢复 // ============================================================ // 时间同步 @@ -115,8 +119,10 @@ void handleAlarmCommand(const AlarmCommand& cmd) { g_tempAbnCnt = 0; g_humiAbnCnt = 0; g_radarTimeoutCnt = 0; - g_heartAbnCnt = 0; - g_breathAbnCnt = 0; + g_heartAbnMs = 0; + g_heartNormalMs = 0; + g_breathAbnMs = 0; + g_breathNormalMs = 0; g_fallDetectMs = 0; g_fallClearMs = 0; g_fallDismissed = false; @@ -335,55 +341,85 @@ void checkLocalAlarms(const RadarRawData& radar) { g_fallClearMs = 0; // 仍在跌倒, 重置消失计时 } - // ─── ★★★★★ 人身安全: 心率异常 (仅卧室+ABD1, 防抖3次, 30s) ─── + // ─── ★★★★★ 人身安全: 心率异常 (仅卧室+ABD1, 持续异常20s触发/正常15s恢复, 30s) ─── #if RADAR_TYPE != RADAR_TYPE_AFD1 if (enVital && millis() > 30000 && humanPresent && radar.vitalValid && radar.heartRate > 0) { bool heartAbn = (radar.heartRate < HEART_RATE_MIN || radar.heartRate > HEART_RATE_MAX); if (heartAbn) { - if (!g_heartDismissed && ++g_heartAbnCnt >= ALARM_HYSTERESIS && !g_localHeartAbnActive) { - g_localHeartAbnActive = true; - char buf[32]; - snprintf(buf, sizeof(buf), "心率异常: %d bpm", radar.heartRate); - g_alarm.triggerLocal(AlarmManager::ALARM_HEART_ABNORMAL, buf); + // 持续异常: 累积时长, 满 VITAL_DETECT_MS 触发 + if (!g_heartDismissed && !g_localHeartAbnActive) { + if (g_heartAbnMs == 0) { + g_heartAbnMs = millis(); + } else if (millis() - g_heartAbnMs >= VITAL_DETECT_MS) { + g_localHeartAbnActive = true; + char buf[32]; + snprintf(buf, sizeof(buf), "心率异常: %d bpm", radar.heartRate); + g_alarm.triggerLocal(AlarmManager::ALARM_HEART_ABNORMAL, buf); + } } + g_heartNormalMs = 0; // 仍异常, 重置正常计时 } else { - g_heartAbnCnt = 0; - g_heartDismissed = false; - if (g_localHeartAbnActive) { - g_localHeartAbnActive = false; - g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL); + // 持续正常: 累积时长, 满 VITAL_CLEAR_MS 清除 + 重新武装 + g_heartAbnMs = 0; // 正常了, 重置异常计时 + if (g_heartNormalMs == 0) { + g_heartNormalMs = millis(); + } + if (millis() - g_heartNormalMs >= VITAL_CLEAR_MS) { + if (g_localHeartAbnActive) { + g_localHeartAbnActive = false; + g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL); + } + if (g_heartDismissed) { + g_heartDismissed = false; // 持续正常后重新武装 + } } } } else if (!humanPresent && g_localHeartAbnActive) { g_localHeartAbnActive = false; - g_heartAbnCnt = 0; + g_heartAbnMs = 0; + g_heartNormalMs = 0; g_heartDismissed = false; g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL); } #endif // RADAR_TYPE != AFD1 - // ─── ★★★★★ 人身安全: 呼吸异常 (仅卧室+ABD1, 防抖3次, 30秒后生效) ─── + // ─── ★★★★★ 人身安全: 呼吸异常 (仅卧室+ABD1, 持续异常20s触发/正常15s恢复, 30秒后生效) ─── #if RADAR_TYPE != RADAR_TYPE_AFD1 if (enVital && millis() > 30000 && humanPresent && radar.vitalValid && radar.breathRate > 0) { bool breathAbn = (radar.breathRate < BREATH_RATE_MIN || radar.breathRate > BREATH_RATE_MAX); if (breathAbn) { - if (!g_breathDismissed && ++g_breathAbnCnt >= ALARM_HYSTERESIS && !g_localBreathAbnActive) { - g_localBreathAbnActive = true; - char buf[32]; - snprintf(buf, sizeof(buf), "呼吸异常: %d 次/分", radar.breathRate); - g_alarm.triggerLocal(AlarmManager::ALARM_BREATH_ABNORMAL, buf); + // 持续异常: 累积时长, 满 VITAL_DETECT_MS 触发 + if (!g_breathDismissed && !g_localBreathAbnActive) { + if (g_breathAbnMs == 0) { + g_breathAbnMs = millis(); + } else if (millis() - g_breathAbnMs >= VITAL_DETECT_MS) { + g_localBreathAbnActive = true; + char buf[32]; + snprintf(buf, sizeof(buf), "呼吸异常: %d 次/分", radar.breathRate); + g_alarm.triggerLocal(AlarmManager::ALARM_BREATH_ABNORMAL, buf); + } } + g_breathNormalMs = 0; // 仍异常, 重置正常计时 } else { - g_breathAbnCnt = 0; - g_breathDismissed = false; - if (g_localBreathAbnActive) { - g_localBreathAbnActive = false; - g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL); + // 持续正常: 累积时长, 满 VITAL_CLEAR_MS 清除 + 重新武装 + g_breathAbnMs = 0; // 正常了, 重置异常计时 + if (g_breathNormalMs == 0) { + g_breathNormalMs = millis(); + } + if (millis() - g_breathNormalMs >= VITAL_CLEAR_MS) { + if (g_localBreathAbnActive) { + g_localBreathAbnActive = false; + g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL); + } + if (g_breathDismissed) { + g_breathDismissed = false; // 持续正常后重新武装 + } } } } else if (!humanPresent && g_localBreathAbnActive) { g_localBreathAbnActive = false; - g_breathAbnCnt = 0; + g_breathAbnMs = 0; + g_breathNormalMs = 0; g_breathDismissed = false; g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL); } @@ -551,8 +587,10 @@ void setup() { g_localDhtFaultActive = false; g_tempAbnCnt = 0; g_humiAbnCnt = 0; - g_heartAbnCnt = 0; - g_breathAbnCnt = 0; + g_heartAbnMs = 0; + g_heartNormalMs = 0; + g_breathAbnMs = 0; + g_breathNormalMs = 0; g_radarTimeoutCnt = 0; g_fallClearMs = 0; g_fallDismissed = true; // 抑制重复报警, 等跌倒信号消了再恢复