feat: init

This commit is contained in:
yangzhijia
2026-07-22 11:27:37 +08:00
commit 49e3abbb34
23 changed files with 4388 additions and 0 deletions

266
src/alarm_manager.cpp Normal file
View File

@@ -0,0 +1,266 @@
/**
* @file alarm_manager.cpp
* @brief 报警管理器 - 双模式实现
*
* 本地: 跌倒/水浸/心率异常/呼吸异常 → 立即蜂鸣器+LED
* 服务端: cmd/alarm, cmd/alarm/restore → 执行联动 + 回复响应
*/
#include "alarm_manager.h"
AlarmManager::AlarmManager()
: _buzzerOn(false)
, _ledOn(false)
, _buzzerOffTime(0)
, _buzzerToggleTime(0)
, _buzzerBeepState(false)
, _beepCount(0)
, _activeCount(0)
, _lastLEDToggle(0)
{
for (int i = 0; i < 4; i++) _activeAlarms[i] = ALARM_NONE;
}
AlarmManager::~AlarmManager() {}
// ============================================================
// 初始化
// ============================================================
bool AlarmManager::begin() {
ledcSetup(BUZZER_PWM_CHANNEL, BUZZER_PWM_FREQ, BUZZER_PWM_RESOLUTION);
ledcAttachPin(BUZZER_PIN, BUZZER_PWM_CHANNEL);
ledcWrite(BUZZER_PWM_CHANNEL, 0); // 关
pinMode(LED_ALARM_PIN, OUTPUT);
digitalWrite(LED_ALARM_PIN, LOW);
_buzzerToggleTime = 0;
_buzzerBeepState = false;
_beepCount = 0;
Serial.println(F("[告警] ✅ 双模式报警 (本地+服务端)"));
return true;
}
// ============================================================
// 主循环
// ============================================================
void AlarmManager::loop() {
_updateBuzzer();
_updateLED();
}
// ============================================================
// 本地报警触发 (离线可用)
// ============================================================
void AlarmManager::triggerLocal(AlarmType type) {
// 去重
for (uint8_t i = 0; i < _activeCount; i++) {
if (_activeAlarms[i] == type) return;
}
if (_activeCount < 4) {
_activeAlarms[_activeCount++] = type;
}
const char* name = "";
switch (type) {
case ALARM_FALL: name = "跌倒"; break;
case ALARM_WATER_LEAK: name = "水浸"; break;
case ALARM_HEART_ABNORMAL: name = "心率异常"; break;
case ALARM_BREATH_ABNORMAL: name = "呼吸异常"; break;
default: name = "未知"; break;
}
Serial.printf("[告警] 🚨 本地报警触发: %s (活动报警:%d)\n", name, _activeCount);
// 立即开启蜂鸣器和 LED
_setBuzzer(true);
_setLED(true);
}
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;
}
}
Serial.printf("[告警] 本地报警清除, 剩余活动:%d\n", _activeCount);
// 没有活动报警时关闭
if (_activeCount == 0) {
_setBuzzer(false);
_setLED(false);
}
}
void AlarmManager::clearAllLocal() {
_activeCount = 0;
for (int i = 0; i < 4; i++) _activeAlarms[i] = ALARM_NONE;
_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 到本地类型
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);
if (cmd.buzzerDuration > 0) {
_buzzerOffTime = millis() + (uint32_t)cmd.buzzerDuration * 1000;
} else {
_buzzerOffTime = 0;
}
}
if (cmd.nightLight || cmd.buzzerOn) {
_setLED(true);
}
}
// ============================================================
// 服务端恢复指令 (§5.2)
// ============================================================
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;
clearLocal(localType);
if (!cmd.buzzerOn) {
_setBuzzer(false);
}
if (!cmd.nightLight) {
_setLED(false);
}
}
// ============================================================
// 蜂鸣器测试
// ============================================================
void AlarmManager::buzzerTest(uint32_t durationSec) {
Serial.printf("[告警] 🔔 蜂鸣器测试 %d秒\n", durationSec);
_setBuzzer(true);
_buzzerOffTime = millis() + durationSec * 1000;
}
// ============================================================
// 状态查询
// ============================================================
const char* AlarmManager::getActiveAlarmType() const {
if (_activeCount == 0) return "";
switch (_activeAlarms[0]) {
case ALARM_FALL: return "fall";
case ALARM_WATER_LEAK: return "water_leak";
case ALARM_HEART_ABNORMAL: return "heart_abnormal";
case ALARM_BREATH_ABNORMAL: return "breath_abnormal";
case ALARM_SERVER: return "server";
default: return "";
}
}
// ============================================================
// 内部控制
// ============================================================
void AlarmManager::_setBuzzer(bool on) {
_buzzerOn = on;
_buzzerBeepState = false;
_buzzerToggleTime = 0;
_beepCount = 0;
if (on) {
_buzzerOffTime = 0; // 本地报警=无限哔哔
} else {
ledcWrite(BUZZER_PWM_CHANNEL, 0);
_buzzerOffTime = 0;
}
}
void AlarmManager::_setLED(bool on) {
_ledOn = on;
if (!on) digitalWrite(LED_ALARM_PIN, LOW);
}
void AlarmManager::_updateBuzzer() {
// 定时关闭检查
if (_buzzerOn && _buzzerOffTime > 0 && millis() >= _buzzerOffTime) {
_buzzerOn = false;
ledcWrite(BUZZER_PWM_CHANNEL, 0);
Serial.println(F("[告警] ⏰ 蜂鸣器定时关闭"));
return;
}
// 本地报警: 三连哔 停 — 循环 (哔哔哔...哔哔哔...)
if (_buzzerOn && _buzzerOffTime == 0) {
uint32_t now = millis();
// 周期: 3声哔 (每声150ms响+100ms停) + 600ms大停顿
if (!_buzzerBeepState) {
// 在停顿中,检查是否该下一声
uint32_t pause = (_beepCount >= 3) ? 600 : 100;
if (now - _buzzerToggleTime >= pause) {
_buzzerToggleTime = now;
if (_beepCount >= 3) _beepCount = 0; // 重置周期
_buzzerBeepState = true;
ledcWrite(BUZZER_PWM_CHANNEL, 128);
_beepCount++;
}
} else {
// 在响中150ms后停下
if (now - _buzzerToggleTime >= 150) {
_buzzerToggleTime = now;
_buzzerBeepState = false;
ledcWrite(BUZZER_PWM_CHANNEL, 0);
}
}
}
// 云端定时: 持续响
else if (_buzzerOn && _buzzerOffTime > 0) {
ledcWrite(BUZZER_PWM_CHANNEL, 128);
}
}
void AlarmManager::_updateLED() {
if (!_ledOn) {
digitalWrite(LED_ALARM_PIN, LOW);
return;
}
// 根据告警类型调整闪烁频率
uint32_t interval = 500;
for (uint8_t i = 0; i < _activeCount; i++) {
if (_activeAlarms[i] == ALARM_FALL) {
interval = 200; // 跌倒快闪
break;
}
}
if (millis() - _lastLEDToggle >= interval) {
_lastLEDToggle = millis();
digitalWrite(LED_ALARM_PIN, !digitalRead(LED_ALARM_PIN));
}
}