init
This commit is contained in:
@@ -256,8 +256,13 @@ void AlarmManager::executeAlarm(const AlarmCommand& cmd) {
|
||||
cmd.alarmType, cmd.alarmLevel, cmd.buzzerOn);
|
||||
|
||||
AlarmType localType = ALARM_SERVER;
|
||||
if (strcmp(cmd.alarmType, "fall") == 0) localType = ALARM_FALL;
|
||||
else if (strcmp(cmd.alarmType, "water_leak") == 0) localType = ALARM_WATER_LEAK;
|
||||
if (strcmp(cmd.alarmType, "fall") == 0) localType = ALARM_FALL;
|
||||
else if (strcmp(cmd.alarmType, "water_leak") == 0) localType = ALARM_WATER_LEAK;
|
||||
else if (strcmp(cmd.alarmType, "heart_abnormal") == 0) localType = ALARM_HEART_ABNORMAL;
|
||||
else if (strcmp(cmd.alarmType, "breath_abnormal") == 0) localType = ALARM_BREATH_ABNORMAL;
|
||||
else if (strcmp(cmd.alarmType, "temp_abnormal") == 0) localType = ALARM_TEMP_ABNORMAL;
|
||||
else if (strcmp(cmd.alarmType, "humi_abnormal") == 0) localType = ALARM_HUMI_ABNORMAL;
|
||||
else if (strcmp(cmd.alarmType, "sensor_fault") == 0) localType = ALARM_SENSOR_FAULT;
|
||||
|
||||
if (cmd.buzzerOn) {
|
||||
triggerLocal(localType, cmd.alarmDesc);
|
||||
|
||||
+59
-27
@@ -45,6 +45,13 @@ bool g_localHumiAbnActive = false;
|
||||
bool g_localRadarFaultActive = false;
|
||||
bool g_localDhtFaultActive = false;
|
||||
|
||||
// 手动解除抑制 — dismiss 后不重复报警, 条件恢复正常才重新武装
|
||||
bool g_waterDismissed = false;
|
||||
bool g_heartDismissed = false;
|
||||
bool g_breathDismissed = false;
|
||||
bool g_tempDismissed = false;
|
||||
bool g_humiDismissed = false;
|
||||
|
||||
// 报警防抖计数器 (连续N次确认才触发)
|
||||
uint8_t g_tempAbnCnt = 0;
|
||||
uint8_t g_humiAbnCnt = 0;
|
||||
@@ -113,6 +120,13 @@ void handleAlarmCommand(const AlarmCommand& cmd) {
|
||||
g_fallDetectMs = 0;
|
||||
g_fallClearMs = 0;
|
||||
g_fallDismissed = false;
|
||||
|
||||
// 解除抑制标志也复位 (远程恢复后重新武装)
|
||||
g_waterDismissed = false;
|
||||
g_heartDismissed = false;
|
||||
g_breathDismissed = false;
|
||||
g_tempDismissed = false;
|
||||
g_humiDismissed = false;
|
||||
} else {
|
||||
// 告警触发
|
||||
g_alarm.executeAlarm(cmd);
|
||||
@@ -286,40 +300,39 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
bool humanPresent = radar.presence && radar.radarValid;
|
||||
|
||||
// ─── ★★★★★ 人身安全: 跌倒 (仅浴室/走廊/客厅) ───
|
||||
if (enFall && radar.fall && humanPresent && !g_fallDismissed && millis() > 30000) {
|
||||
bool fallNow = enFall && radar.fall && humanPresent; // 当前是否处于跌倒状态
|
||||
|
||||
if (fallNow && !g_fallDismissed && millis() > 30000) {
|
||||
// 跌倒中且未解除 → 累积时长, 满 FALL_DETECT_MS 触发
|
||||
if (!g_localFallActive) {
|
||||
// 持续检测中: 必须满 FALL_DETECT_MS 才报警
|
||||
if (g_fallDetectMs == 0) {
|
||||
g_fallDetectMs = millis();
|
||||
} else if (millis() - g_fallDetectMs >= FALL_DETECT_MS) {
|
||||
g_localFallActive = true;
|
||||
g_fallDetectMs = 0;
|
||||
g_fallClearMs = 0;
|
||||
g_alarm.triggerLocal(AlarmManager::ALARM_FALL, "雷达检测到跌倒");
|
||||
}
|
||||
} else {
|
||||
g_fallClearMs = 0; // 还在跌倒, 重置清除计时
|
||||
}
|
||||
} else {
|
||||
g_fallDetectMs = 0;
|
||||
// 解除抑制需要 fall 持续消失 FALL_CLEAR_MS (防 AFD1 频繁跳变)
|
||||
if (g_fallDismissed && g_fallClearMs == 0) {
|
||||
}
|
||||
|
||||
// 跌倒信号真正消失后: 延迟清除报警 + 重新武装解除抑制 (防 AFD1 频繁跳变)
|
||||
if (!fallNow) {
|
||||
if (g_fallClearMs == 0) {
|
||||
g_fallClearMs = millis();
|
||||
}
|
||||
if (!g_fallDismissed || millis() - g_fallClearMs >= FALL_CLEAR_MS) {
|
||||
g_fallDismissed = false;
|
||||
g_fallClearMs = 0;
|
||||
}
|
||||
if (g_localFallActive) {
|
||||
// 跌倒已消失 → 延迟清除
|
||||
if (g_fallClearMs == 0) {
|
||||
g_fallClearMs = millis();
|
||||
} else if (millis() - g_fallClearMs >= FALL_CLEAR_MS) {
|
||||
if (millis() - g_fallClearMs >= FALL_CLEAR_MS) {
|
||||
if (g_localFallActive) {
|
||||
g_localFallActive = false;
|
||||
g_fallClearMs = 0;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_FALL);
|
||||
}
|
||||
if (g_fallDismissed) {
|
||||
g_fallDismissed = false; // 跌倒真正消失才重新武装
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g_fallClearMs = 0; // 仍在跌倒, 重置消失计时
|
||||
}
|
||||
|
||||
// ─── ★★★★★ 人身安全: 心率异常 (仅卧室+ABD1, 防抖3次, 30s) ───
|
||||
@@ -327,7 +340,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
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_heartAbnCnt >= ALARM_HYSTERESIS && !g_localHeartAbnActive) {
|
||||
if (!g_heartDismissed && ++g_heartAbnCnt >= ALARM_HYSTERESIS && !g_localHeartAbnActive) {
|
||||
g_localHeartAbnActive = true;
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "心率异常: %d bpm", radar.heartRate);
|
||||
@@ -335,6 +348,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
}
|
||||
} else {
|
||||
g_heartAbnCnt = 0;
|
||||
g_heartDismissed = false;
|
||||
if (g_localHeartAbnActive) {
|
||||
g_localHeartAbnActive = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL);
|
||||
@@ -343,6 +357,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
} else if (!humanPresent && g_localHeartAbnActive) {
|
||||
g_localHeartAbnActive = false;
|
||||
g_heartAbnCnt = 0;
|
||||
g_heartDismissed = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_HEART_ABNORMAL);
|
||||
}
|
||||
#endif // RADAR_TYPE != AFD1
|
||||
@@ -352,7 +367,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
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_breathAbnCnt >= ALARM_HYSTERESIS && !g_localBreathAbnActive) {
|
||||
if (!g_breathDismissed && ++g_breathAbnCnt >= ALARM_HYSTERESIS && !g_localBreathAbnActive) {
|
||||
g_localBreathAbnActive = true;
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "呼吸异常: %d 次/分", radar.breathRate);
|
||||
@@ -360,6 +375,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
}
|
||||
} else {
|
||||
g_breathAbnCnt = 0;
|
||||
g_breathDismissed = false;
|
||||
if (g_localBreathAbnActive) {
|
||||
g_localBreathAbnActive = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL);
|
||||
@@ -368,6 +384,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
} else if (!humanPresent && g_localBreathAbnActive) {
|
||||
g_localBreathAbnActive = false;
|
||||
g_breathAbnCnt = 0;
|
||||
g_breathDismissed = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_BREATH_ABNORMAL);
|
||||
}
|
||||
#endif // RADAR_TYPE != AFD1
|
||||
@@ -375,12 +392,17 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
// ─── ★★★ 环境安全: 水浸 (仅浴室) ───
|
||||
if (enWater) {
|
||||
bool waterLeak = !g_sensor.getRainDO() && g_sensor.isRainValid();
|
||||
if (waterLeak && !g_localWaterActive) {
|
||||
g_localWaterActive = true;
|
||||
g_alarm.triggerLocal(AlarmManager::ALARM_WATER_LEAK, "水浸传感器触发");
|
||||
} else if (!waterLeak && g_localWaterActive) {
|
||||
g_localWaterActive = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_WATER_LEAK);
|
||||
if (waterLeak) {
|
||||
if (!g_waterDismissed && !g_localWaterActive) {
|
||||
g_localWaterActive = true;
|
||||
g_alarm.triggerLocal(AlarmManager::ALARM_WATER_LEAK, "水浸传感器触发");
|
||||
}
|
||||
} else {
|
||||
g_waterDismissed = false;
|
||||
if (g_localWaterActive) {
|
||||
g_localWaterActive = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_WATER_LEAK);
|
||||
}
|
||||
}
|
||||
} // enWater
|
||||
|
||||
@@ -389,7 +411,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
float temp = g_sensor.getTemp();
|
||||
bool tempAbn = (temp < TEMP_LOW || temp > TEMP_HIGH);
|
||||
if (tempAbn) {
|
||||
if (++g_tempAbnCnt >= ALARM_HYSTERESIS && !g_localTempAbnActive) {
|
||||
if (!g_tempDismissed && ++g_tempAbnCnt >= ALARM_HYSTERESIS && !g_localTempAbnActive) {
|
||||
g_localTempAbnActive = true;
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "温度%.1f°C 超出范围", temp);
|
||||
@@ -397,6 +419,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
}
|
||||
} else {
|
||||
g_tempAbnCnt = 0;
|
||||
g_tempDismissed = false;
|
||||
if (g_localTempAbnActive) {
|
||||
g_localTempAbnActive = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_TEMP_ABNORMAL);
|
||||
@@ -407,7 +430,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
float humi = g_sensor.getHumi();
|
||||
bool humiAbn = (humi < HUMI_LOW || humi > HUMI_HIGH);
|
||||
if (humiAbn) {
|
||||
if (++g_humiAbnCnt >= ALARM_HYSTERESIS && !g_localHumiAbnActive) {
|
||||
if (!g_humiDismissed && ++g_humiAbnCnt >= ALARM_HYSTERESIS && !g_localHumiAbnActive) {
|
||||
g_localHumiAbnActive = true;
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "湿度%.1f%% 超出范围", humi);
|
||||
@@ -415,6 +438,7 @@ void checkLocalAlarms(const RadarRawData& radar) {
|
||||
}
|
||||
} else {
|
||||
g_humiAbnCnt = 0;
|
||||
g_humiDismissed = false;
|
||||
if (g_localHumiAbnActive) {
|
||||
g_localHumiAbnActive = false;
|
||||
g_alarm.clearLocal(AlarmManager::ALARM_HUMI_ABNORMAL);
|
||||
@@ -527,9 +551,17 @@ void setup() {
|
||||
g_localDhtFaultActive = false;
|
||||
g_tempAbnCnt = 0;
|
||||
g_humiAbnCnt = 0;
|
||||
g_heartAbnCnt = 0;
|
||||
g_breathAbnCnt = 0;
|
||||
g_radarTimeoutCnt = 0;
|
||||
g_fallClearMs = 0;
|
||||
g_fallDismissed = true; // 抑制重复报警, 等跌倒信号消了再恢复
|
||||
// 其余类型同样抑制, 条件恢复正常后才重新武装
|
||||
g_waterDismissed = true;
|
||||
g_heartDismissed = true;
|
||||
g_breathDismissed = true;
|
||||
g_tempDismissed = true;
|
||||
g_humiDismissed = true;
|
||||
});
|
||||
g_buttons.onProvisionLongPress([]() {
|
||||
g_wifi.startConfigPortal();
|
||||
|
||||
Reference in New Issue
Block a user