/** * @file alarm_manager.cpp * @brief 报警管理器 - 多类型分优先级实现 * * 蜂鸣模式 (人身安全 > 环境 > 设备): * 跌倒: 连速哔 (60ms/60ms) — 最急 ★★★★★ * 心率/呼吸: 5连急哔 (80ms/80ms) — 次急 ★★★★★ * 水浸: 3连哔 (120ms/100ms) — 中等 ★★★ * 温湿度: 2声长停 (200ms/400ms) — 温和 ★★ * 传感器: 单声长哔 (300ms/3s) — 提示 ★ */ #include "alarm_manager.h" // ============================================================ // 优先级定义 — 人身安全 > 环境安全 > 设备故障 // ============================================================ uint8_t AlarmManager::_priority(AlarmType t) { switch (t) { // ★★★★★ 人身安全 — 直接威胁生命 case ALARM_FALL: return 0; case ALARM_HEART_ABNORMAL: return 1; case ALARM_BREATH_ABNORMAL: return 1; // ★★★ 环境安全 — 潜在危险 case ALARM_WATER_LEAK: return 2; // ★★ 环境舒适 — 非紧急 case ALARM_TEMP_ABNORMAL: return 3; case ALARM_HUMI_ABNORMAL: return 3; // ★ 设备状态 — 仅提示 case ALARM_SENSOR_FAULT: return 4; case ALARM_SERVER: return 5; default: return 9; } } // ============================================================ // 构造 & 析构 // ============================================================ AlarmManager::AlarmManager() : _buzzerOn(false) , _ledOn(false) , _buzzerOffTime(0) , _buzzerToggleTime(0) , _buzzerBeepState(false) , _beepCount(0) , _beepsPerCycle(3) , _beepOnMs(150) , _beepOffMs(100) , _cyclePauseMs(600) , _activeCount(0) , _lastLEDToggle(0) , _alarmCb(nullptr) { for (uint8_t i = 0; i < MAX_ACTIVE; i++) _activeAlarms[i] = ALARM_NONE; memset(_activeDetail, 0, sizeof(_activeDetail)); } AlarmManager::~AlarmManager() {} // ============================================================ // 初始化 // ============================================================ bool AlarmManager::begin() { // 有源蜂鸣器: 用 digitalWrite, 不用 PWM pinMode(BUZZER_PIN, OUTPUT); digitalWrite(BUZZER_PIN, LOW); pinMode(LED_ALARM_PIN, OUTPUT); digitalWrite(LED_ALARM_PIN, LOW); Serial.println(F("[告警] ✅ 多类型分优先级报警就绪 (7种类型)")); return true; } // ============================================================ // 主循环 // ============================================================ void AlarmManager::loop() { _updateBuzzer(); _updateLED(); } // ============================================================ // 报警名称映射 // ============================================================ const char* AlarmManager::getAlarmName(AlarmType type) const { switch (type) { case ALARM_FALL: return "跌倒"; case ALARM_WATER_LEAK: return "水浸"; case ALARM_HEART_ABNORMAL: return "心率异常"; case ALARM_BREATH_ABNORMAL: return "呼吸异常"; case ALARM_TEMP_ABNORMAL: return "温度异常"; case ALARM_HUMI_ABNORMAL: return "湿度异常"; case ALARM_SENSOR_FAULT: return "传感器故障"; case ALARM_SERVER: return "云端指令"; default: return "未知"; } } // ============================================================ // 最高优先级报警 // ============================================================ AlarmManager::AlarmType AlarmManager::getHighestAlarm() const { if (_activeCount == 0) return ALARM_NONE; AlarmType best = ALARM_NONE; uint8_t bestP = 99; for (uint8_t i = 0; i < _activeCount; i++) { uint8_t p = _priority(_activeAlarms[i]); if (p < bestP) { bestP = p; best = _activeAlarms[i]; } } return best; } const char* AlarmManager::getActiveAlarmStr() const { AlarmType t = getHighestAlarm(); if (t == ALARM_NONE) return ""; return getAlarmName(t); } // ============================================================ // 蜂鸣参数表 (按最高优先级报警驱动) // ============================================================ uint32_t AlarmManager::_buzzerIntervalFor(AlarmType type) { switch (type) { case ALARM_FALL: return 200; // LED 快闪 case ALARM_WATER_LEAK: return 300; case ALARM_HEART_ABNORMAL: return 500; case ALARM_BREATH_ABNORMAL: return 500; case ALARM_TEMP_ABNORMAL: return 800; case ALARM_HUMI_ABNORMAL: return 800; case ALARM_SENSOR_FAULT: return 1000; default: return 500; } } // ============================================================ // 更新蜂鸣参数 (根据当前最高优先级报警) // ============================================================ static void _calcBuzzerParams(AlarmManager::AlarmType t, uint8_t& beeps, uint32_t& onMs, uint32_t& offMs, uint32_t& pauseMs) { switch (t) { // 人身安全 — 连速急哔 case AlarmManager::ALARM_FALL: beeps = 0; onMs = 200; offMs = 200; pauseMs = 0; // 跌倒: 急促哔哔 break; case AlarmManager::ALARM_HEART_ABNORMAL: case AlarmManager::ALARM_BREATH_ABNORMAL: beeps = 5; onMs = 200; offMs = 150; pauseMs = 500; // 心率/呼吸: 5连哔 break; // 环境安全 case AlarmManager::ALARM_WATER_LEAK: beeps = 3; onMs = 250; offMs = 200; pauseMs = 600; // 水浸: 3连哔 break; // 环境舒适 case AlarmManager::ALARM_TEMP_ABNORMAL: case AlarmManager::ALARM_HUMI_ABNORMAL: beeps = 2; onMs = 300; offMs = 500; pauseMs = 1500; // 温湿度: 2声长停 break; // 设备状态 case AlarmManager::ALARM_SENSOR_FAULT: beeps = 1; onMs = 500; offMs = 3000; pauseMs = 0; // 传感器: 单声提醒 break; default: beeps = 0; onMs = 500; offMs = 500; pauseMs = 0; // 持续 break; } } // ============================================================ // 本地报警触发 // ============================================================ void AlarmManager::triggerLocal(AlarmType type, const char* detail) { // 去重 for (uint8_t i = 0; i < _activeCount; i++) { if (_activeAlarms[i] == type) return; } if (_activeCount < MAX_ACTIVE) { _activeAlarms[_activeCount++] = type; } const char* name = getAlarmName(type); Serial.printf("[告警] 🚨 触发: %s (活动:%d)", name, _activeCount); if (detail && detail[0]) Serial.printf(" | %s", detail); Serial.println(); // 更新蜂鸣参数 (按最高优先级) AlarmType highest = getHighestAlarm(); _calcBuzzerParams(highest, _beepsPerCycle, _beepOnMs, _beepOffMs, _cyclePauseMs); // 保存详情 if (detail) { strncpy(_activeDetail, detail, sizeof(_activeDetail) - 1); } _setBuzzer(true); _setLED(true); // 通知外部 if (_alarmCb) _alarmCb((uint8_t)type, true, detail ? detail : name); } void AlarmManager::clearLocal(AlarmType type) { for (uint8_t i = 0; i < _activeCount; i++) { if (_activeAlarms[i] == type) { for (uint8_t j = i; j < _activeCount - 1; j++) { _activeAlarms[j] = _activeAlarms[j + 1]; } _activeAlarms[_activeCount - 1] = ALARM_NONE; _activeCount--; break; } } const char* name = getAlarmName(type); Serial.printf("[告警] ✅ 清除: %s (剩余:%d)\n", name, _activeCount); if (_activeCount == 0) { _setBuzzer(false); _setLED(false); _activeDetail[0] = '\0'; } else { // 降级到次高优先级报警的蜂鸣参数 AlarmType highest = getHighestAlarm(); _calcBuzzerParams(highest, _beepsPerCycle, _beepOnMs, _beepOffMs, _cyclePauseMs); } if (_alarmCb) _alarmCb((uint8_t)type, false, name); } void AlarmManager::clearAllLocal() { _activeCount = 0; for (uint8_t i = 0; i < MAX_ACTIVE; i++) _activeAlarms[i] = ALARM_NONE; _activeDetail[0] = '\0'; _setBuzzer(false); _setLED(false); Serial.println(F("[告警] 清除所有报警")); } // ============================================================ // 服务端告警指令 (§5.1) // ============================================================ void AlarmManager::executeAlarm(const AlarmCommand& cmd) { Serial.printf("[告警] ☁️ 服务端: %s (等级=%s 蜂鸣=%d)\n", 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 (cmd.buzzerOn) { triggerLocal(localType, cmd.alarmDesc); if (cmd.buzzerDuration > 0) { _buzzerOffTime = millis() + (uint32_t)cmd.buzzerDuration * 1000; } else { _buzzerOffTime = 0; } } if (cmd.nightLight || cmd.buzzerOn) { _setLED(true); } } void AlarmManager::executeRestore(const AlarmCommand& cmd) { Serial.printf("[告警] ☁️ 恢复: %s\n", cmd.alarmType); 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; 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; clearLocal(localType); if (!cmd.buzzerOn) _setBuzzer(false); if (!cmd.nightLight) _setLED(false); } // ============================================================ // 蜂鸣器测试 // ============================================================ void AlarmManager::buzzerTest(uint32_t durationSec) { Serial.printf("[告警] 🔔 蜂鸣器测试 %ds\n", durationSec); _setBuzzer(true); _buzzerOffTime = millis() + durationSec * 1000; } // ============================================================ // 内部控制 // ============================================================ void AlarmManager::_setBuzzer(bool on) { _buzzerOn = on; _buzzerBeepState = false; _buzzerToggleTime = 0; _beepCount = 0; if (on) { _buzzerOffTime = 0; } else { digitalWrite(BUZZER_PIN, LOW); _buzzerOffTime = 0; } } void AlarmManager::_setLED(bool on) { _ledOn = on; if (!on) digitalWrite(LED_ALARM_PIN, LOW); } // ============================================================ // 蜂鸣器更新 (优先级驱动模式) // ============================================================ void AlarmManager::_updateBuzzer() { if (!_buzzerOn) return; // 定时关闭 if (_buzzerOffTime > 0 && millis() >= _buzzerOffTime) { _buzzerOn = false; digitalWrite(BUZZER_PIN, LOW); Serial.println(F("[告警] ⏰ 蜂鸣器定时关闭")); return; } uint32_t now = millis(); // 云端定时: 哔哔声 (500ms响/500ms停), 不是长鸣 if (_buzzerOffTime > 0) { if (now - _buzzerToggleTime >= 500) { _buzzerToggleTime = now; _buzzerBeepState = !_buzzerBeepState; digitalWrite(BUZZER_PIN, _buzzerBeepState ? HIGH : LOW); } return; } // 本地报警: 按优先级模式 — 哔声/停顿交替 if (_beepsPerCycle == 0) { // 连速哔 (跌倒): 简单翻转 if (now - _buzzerToggleTime >= (_buzzerBeepState ? _beepOnMs : _beepOffMs)) { _buzzerToggleTime = now; _buzzerBeepState = !_buzzerBeepState; digitalWrite(BUZZER_PIN, _buzzerBeepState ? HIGH : LOW); } } else { // 多声一组: N声哔 + 长停顿 if (!_buzzerBeepState) { // 停顿中 uint32_t pause = (_beepCount >= _beepsPerCycle) ? _cyclePauseMs : _beepOffMs; if (now - _buzzerToggleTime >= pause) { _buzzerToggleTime = now; if (_beepCount >= _beepsPerCycle) _beepCount = 0; _buzzerBeepState = true; digitalWrite(BUZZER_PIN, HIGH); _beepCount++; } } else { // 响声中 if (now - _buzzerToggleTime >= _beepOnMs) { _buzzerToggleTime = now; _buzzerBeepState = false; digitalWrite(BUZZER_PIN, LOW); } } } } // ============================================================ // LED 更新 (按最高优先级决定闪烁频率) // ============================================================ void AlarmManager::_updateLED() { if (!_ledOn) { digitalWrite(LED_ALARM_PIN, LOW); return; } AlarmType highest = getHighestAlarm(); uint32_t interval = _buzzerIntervalFor(highest); if (millis() - _lastLEDToggle >= interval) { _lastLEDToggle = millis(); digitalWrite(LED_ALARM_PIN, !digitalRead(LED_ALARM_PIN)); } }