feat: 按钮去抖+配网界面美化+水浸离线+LED独立任务+报警全拓展(人身优先)+有人才检测
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
/**
|
||||
* @file alarm_manager.h
|
||||
* @brief 报警管理器 - 双模式 (本地判定 + 服务端指令)
|
||||
* @brief 报警管理器 - 多类型分优先级报警 (本地判定 + 服务端指令)
|
||||
*
|
||||
* 本地模式: 离线也能用, 跌倒/水浸/心率异常/呼吸异常 本地判定触发
|
||||
* 优先级: 跌倒 > 水浸 > 心率异常 > 呼吸异常 > 温湿度异常 > 传感器故障
|
||||
*
|
||||
* 本地模式: 离线也能用, 全部类型本地判定触发
|
||||
* 服务端模式: 收到 cmd/{gateid}/alarm, alarm/restore 执行联动
|
||||
* 防抖: 传感器故障需连续 N 次确认才触发, 避免误报
|
||||
*/
|
||||
|
||||
#ifndef ALARM_MANAGER_H
|
||||
@@ -12,16 +15,23 @@
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
|
||||
// 报警回调 — 通知外部 (如 MQTT 上报)
|
||||
typedef void (*AlarmCallback)(uint8_t type, bool triggered, const char* desc);
|
||||
|
||||
class AlarmManager {
|
||||
public:
|
||||
// 告警类型 (本地 + 服务端共用)
|
||||
enum AlarmType {
|
||||
// 告警类型 (按优先级从高到低)
|
||||
enum AlarmType : uint8_t {
|
||||
ALARM_NONE = 0,
|
||||
ALARM_FALL, // 跌倒 (本地 + 服务端)
|
||||
ALARM_WATER_LEAK, // 水浸 (本地 + 服务端)
|
||||
ALARM_HEART_ABNORMAL, // 心率异常 (本地)
|
||||
ALARM_BREATH_ABNORMAL, // 呼吸异常 (本地)
|
||||
ALARM_SERVER, // 服务端下发 (通用)
|
||||
ALARM_FALL, // 跌倒 (本地 + 服务端) ★★★★★
|
||||
ALARM_WATER_LEAK, // 水浸 (本地 + 服务端) ★★★★
|
||||
ALARM_HEART_ABNORMAL, // 心率异常 (本地) ★★★
|
||||
ALARM_BREATH_ABNORMAL, // 呼吸异常 (本地) ★★★
|
||||
ALARM_TEMP_ABNORMAL, // 温度异常 (本地) ★★
|
||||
ALARM_HUMI_ABNORMAL, // 湿度异常 (本地) ★★
|
||||
ALARM_SENSOR_FAULT, // 传感器故障 (本地) ★
|
||||
ALARM_SERVER, // 服务端下发 (通用)
|
||||
ALARM_COUNT
|
||||
};
|
||||
|
||||
AlarmManager();
|
||||
@@ -34,11 +44,11 @@ public:
|
||||
// 本地报警接口 (离线可用)
|
||||
// ============================================================
|
||||
|
||||
/** 触发本地报警 */
|
||||
void triggerLocal(AlarmType type);
|
||||
/** 触发本地报警 (防抖由调用方处理) */
|
||||
void triggerLocal(AlarmType type, const char* detail = nullptr);
|
||||
/** 清除本地报警 */
|
||||
void clearLocal(AlarmType type);
|
||||
/** 清除所有本地报警 */
|
||||
/** 清除所有本地报警 (含防抖计数器) */
|
||||
void clearAllLocal();
|
||||
|
||||
// ============================================================
|
||||
@@ -53,33 +63,58 @@ public:
|
||||
void buzzerTest(uint32_t durationSec);
|
||||
|
||||
// ============================================================
|
||||
// 状态查询 (上报用)
|
||||
// 回调注册
|
||||
// ============================================================
|
||||
|
||||
bool isBuzzerOn() const { return _buzzerOn; }
|
||||
bool hasActiveAlarm() const { return _activeCount > 0; }
|
||||
const char* getActiveAlarmType() const;
|
||||
/** 报警状态变化回调 (触发/清除时调用, 用于MQTT上报) */
|
||||
void onAlarmChange(AlarmCallback cb) { _alarmCb = cb; }
|
||||
|
||||
// ============================================================
|
||||
// 状态查询
|
||||
// ============================================================
|
||||
|
||||
bool isBuzzerOn() const { return _buzzerOn; }
|
||||
bool hasActiveAlarm() const { return _activeCount > 0; }
|
||||
uint8_t getActiveCount() const { return _activeCount; }
|
||||
AlarmType getHighestAlarm() const;
|
||||
const char* getAlarmName(AlarmType type) const;
|
||||
const char* getActiveAlarmStr() const;
|
||||
|
||||
private:
|
||||
// 报警优先级 (越小越紧急)
|
||||
static uint8_t _priority(AlarmType t);
|
||||
|
||||
void _setBuzzer(bool on);
|
||||
void _setLED(bool on);
|
||||
void _updateBuzzer();
|
||||
void _updateLED();
|
||||
uint32_t _buzzerIntervalFor(AlarmType type);
|
||||
|
||||
// 蜂鸣器/LED 状态
|
||||
bool _buzzerOn;
|
||||
bool _ledOn;
|
||||
uint32_t _buzzerOffTime; // 定时关闭时刻 (0=手动关)
|
||||
uint32_t _buzzerOffTime; // 定时关闭时刻 (0=手动/无限)
|
||||
uint32_t _buzzerToggleTime; // 间歇切换时刻
|
||||
bool _buzzerBeepState; // 间歇状态 (响/停)
|
||||
uint8_t _beepCount; // 当前周期哔了几声
|
||||
uint8_t _beepsPerCycle; // 当前报警类型每周期几声
|
||||
uint32_t _beepOnMs; // 每声持续 ms
|
||||
uint32_t _beepOffMs; // 每声间隔 ms
|
||||
uint32_t _cyclePauseMs; // 周期间停顿 ms
|
||||
|
||||
// 活动报警列表 (最多 4 个同时)
|
||||
AlarmType _activeAlarms[4];
|
||||
// 活动报警列表 (最多 5 个同时)
|
||||
static const uint8_t MAX_ACTIVE = 5;
|
||||
AlarmType _activeAlarms[MAX_ACTIVE];
|
||||
uint8_t _activeCount;
|
||||
|
||||
// 当前详情 (用于上报)
|
||||
char _activeDetail[64];
|
||||
|
||||
// LED 闪烁
|
||||
uint32_t _lastLEDToggle;
|
||||
|
||||
// 回调
|
||||
AlarmCallback _alarmCb;
|
||||
};
|
||||
|
||||
#endif // ALARM_MANAGER_H
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/**
|
||||
* @file button_manager.h
|
||||
* @brief 三按钮管理器 - 去抖 + 长按/短按识别
|
||||
* @brief 三按钮管理器 - 双向去抖 + 长按/短按识别 + 超时自愈
|
||||
*
|
||||
* 按钮1 (GPIO14): 长按3秒 → 配网
|
||||
* 按钮2 (GPIO15): 短按 → 解除报警
|
||||
* 按钮3 (GPIO16): 短按 → 翻页
|
||||
* 按钮1 (GPIO14): 长按1.5秒 → 配网
|
||||
* 按钮2 (GPIO13): 短按 → 解除报警
|
||||
* 按钮3 (GPIO46): 短按 → 翻页
|
||||
*
|
||||
* 去抖策略: 状态变化需持续稳定 BTN_DEBOUNCE_MS 才确认
|
||||
* 自愈策略: 按钮按下超过 10 秒强制复位,防止卡死
|
||||
*/
|
||||
|
||||
#ifndef BUTTON_MANAGER_H
|
||||
@@ -13,6 +16,8 @@
|
||||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
|
||||
#define BTN_STUCK_TIMEOUT_MS 10000 // 按钮卡死超时 (10秒强制复位)
|
||||
|
||||
typedef void (*ButtonCallback)(void);
|
||||
|
||||
class ButtonManager {
|
||||
@@ -31,17 +36,32 @@ public:
|
||||
void onPageSwitch(ButtonCallback cb) { _cbPage = cb; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* 按钮状态机 (基于稳定读数而非边沿)
|
||||
*
|
||||
* 状态转换:
|
||||
* IDLE ──[raw稳定LOW×BTN_DEBOUNCE_MS]──→ PRESSED (记录pressTime)
|
||||
* PRESSED ──[hold≥BTN_LONG_PRESS_MS]──→ 触发长按回调 (仅限hasLong)
|
||||
* PRESSED ──[raw稳定HIGH×BTN_DEBOUNCE_MS]──→ 检查hold时长触发短按 → IDLE
|
||||
* PRESSED ──[hold≥BTN_STUCK_TIMEOUT_MS]──→ 强制复位 → IDLE (防卡死)
|
||||
*/
|
||||
struct ButtonState {
|
||||
uint8_t pin;
|
||||
bool pressed; // 当前是否在按下状态
|
||||
uint32_t pressTime; // 按下时刻 (ms)
|
||||
bool longTriggered; // 防止长按时重复触发短按
|
||||
bool stableState; // 当前确认的稳定状态 (true=按下)
|
||||
bool rawState; // 上一次 raw 读值
|
||||
uint32_t changeTime; // raw 状态变化时刻
|
||||
uint32_t pressTime; // 稳定按下时刻 (ms)
|
||||
bool longTriggered; // 长按已触发
|
||||
bool shortPending; // 等待释放以判定短按
|
||||
};
|
||||
|
||||
/** 处理单个按钮的状态机 */
|
||||
/** 处理单个按钮 (基于稳定状态而非瞬时边沿) */
|
||||
void _processButton(ButtonState& btn, bool hasShort, bool hasLong);
|
||||
bool _readPin(uint8_t pin);
|
||||
|
||||
/** 强制复位单个按钮 */
|
||||
void _resetButton(ButtonState& btn);
|
||||
|
||||
ButtonState _btnProvision;
|
||||
ButtonState _btnDismiss;
|
||||
ButtonState _btnPage;
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
#define DHT11_PIN 4 // 温湿度传感器
|
||||
|
||||
// --- 水浸传感器 ---
|
||||
#define WATER_SENSOR_PIN 6 // 数字输入, 低电平=有水
|
||||
#define WATER_SENSOR_PIN 45 // 数字输入, 低电平=有水
|
||||
|
||||
// --- 蜂鸣器 (PWM) ---
|
||||
#define BUZZER_PIN 7
|
||||
#define BUZZER_PIN 21
|
||||
#define BUZZER_PWM_CHANNEL 0
|
||||
#define BUZZER_PWM_FREQ 2000
|
||||
#define BUZZER_PWM_RESOLUTION 8
|
||||
@@ -47,15 +47,15 @@
|
||||
#define LED_ALARM_PIN 9 // 红色 - 报警指示
|
||||
|
||||
// --- OLED 显示屏 (SSD1306 128x64 I2C) ---
|
||||
#define OLED_SDA_PIN 14 // I2C 数据线
|
||||
#define OLED_SCL_PIN 15 // I2C 时钟线
|
||||
#define OLED_SDA_PIN 15 // I2C 数据线
|
||||
#define OLED_SCL_PIN 16 // I2C 时钟线
|
||||
|
||||
// --- 交互按钮 ---
|
||||
#define BTN_PROVISION_PIN 16 // 擦除WiFi配网按钮 (长按3秒)
|
||||
#define BTN_PROVISION_PIN 14 // 擦除WiFi配网按钮 (长按3秒)
|
||||
#define BTN_ALARM_DISMISS_PIN 13 // 解除报警按钮
|
||||
#define BTN_PAGE_SWITCH_PIN 10 // 翻页按钮
|
||||
#define BTN_PAGE_SWITCH_PIN 46 // 翻页按钮
|
||||
#define BTN_DEBOUNCE_MS 50 // 去抖时间
|
||||
#define BTN_LONG_PRESS_MS 3000 // 长按判定
|
||||
#define BTN_LONG_PRESS_MS 1500 // 长按判定
|
||||
|
||||
// ============================================================
|
||||
// 2. 设备标识 (协议规范 §2)
|
||||
|
||||
@@ -26,11 +26,14 @@ public:
|
||||
|
||||
/**
|
||||
* @brief 更新显示内容 (每 5 秒调用一次即可)
|
||||
* @param data 遥测数据
|
||||
* @param wifiOk WiFi 是否已连接
|
||||
* @param buzzerOn 蜂鸣器是否在响
|
||||
* @param data 遥测数据
|
||||
* @param wifiOk WiFi 是否已连接
|
||||
* @param buzzerOn 蜂鸣器是否在响
|
||||
* @param hasAlarm 是否有活跃报警
|
||||
* @param alarmName 报警名称 (如 "跌倒"/"心率异常")
|
||||
*/
|
||||
void update(const TelemetryData& data, bool wifiOk, bool buzzerOn);
|
||||
void update(const TelemetryData& data, bool wifiOk, bool buzzerOn,
|
||||
bool hasAlarm = false, const char* alarmName = "");
|
||||
|
||||
/** 切换到下一页 (0→1→2→3→0 循环) */
|
||||
void nextPage();
|
||||
@@ -39,10 +42,11 @@ public:
|
||||
uint8_t getPage() const { return _pageIndex; }
|
||||
|
||||
private:
|
||||
void _drawPage0(const TelemetryData& data, bool wifiOk, bool buzzerOn);
|
||||
void _drawPage1(const TelemetryData& data);
|
||||
void _drawPage2(const TelemetryData& data);
|
||||
void _drawPage3(const TelemetryData& data, bool buzzerOn, bool wifiOk);
|
||||
void _drawPage0(const TelemetryData& data, bool wifiOk, bool buzzerOn, bool hasAlarm);
|
||||
void _drawPage1(const TelemetryData& data, bool hasAlarm);
|
||||
void _drawPage2(const TelemetryData& data, bool hasAlarm);
|
||||
void _drawPage3(const TelemetryData& data, bool buzzerOn, bool wifiOk, bool hasAlarm);
|
||||
void _drawAlarmBanner(const char* name);
|
||||
|
||||
/** 格式化秒数为 HH:MM:SS */
|
||||
String _fmtUptime(uint32_t secs) const;
|
||||
|
||||
@@ -80,6 +80,9 @@ public:
|
||||
const char* errorCode, const char* errorMsg,
|
||||
const char* wifiSignal = "");
|
||||
|
||||
/** 本地报警上报 status/{gateid}/alarm (§4.7 扩展) */
|
||||
void publishLocalAlarm(uint8_t alarmType, bool triggered, const char* desc);
|
||||
|
||||
// ============================================================
|
||||
// 回调注册 (协议规范 §5)
|
||||
// ============================================================
|
||||
|
||||
@@ -87,11 +87,16 @@ private:
|
||||
bool _connectWiFi();
|
||||
|
||||
/**
|
||||
* @brief 设置 LED 状态
|
||||
* @param mode 0=慢闪(未连接) 1=快闪(配网) 2=常亮(已连接)
|
||||
* @brief 设置 LED 模式 (线程安全, 无阻塞)
|
||||
* @param mode 0=灭 1=慢闪(断连1s) 2=快闪(配网300ms) 3=常亮(已连接)
|
||||
*/
|
||||
void _setLEDMode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief LED 闪烁独立任务 (FreeRTOS, 不受主循环阻塞影响)
|
||||
*/
|
||||
static void _ledTaskFunc(void* param);
|
||||
|
||||
/**
|
||||
* @brief 检测按钮长按
|
||||
*/
|
||||
@@ -116,9 +121,9 @@ private:
|
||||
uint32_t _buttonPressTime;
|
||||
bool _buttonPressed;
|
||||
|
||||
// LED 闪烁状态
|
||||
uint32_t _ledLastToggle;
|
||||
bool _ledState;
|
||||
// LED 独立任务 (不被 startConfigPortal 阻塞影响)
|
||||
TaskHandle_t _ledTaskHandle;
|
||||
volatile uint8_t _ledMode; // 0=灭 1=慢闪 2=快闪 3=常亮
|
||||
|
||||
// WiFiManager 自定义参数
|
||||
WiFiManagerParameter* _param_mqtt_server;
|
||||
|
||||
Reference in New Issue
Block a user