2026-07-17 09:08:53 +08:00
|
|
|
|
#include "app_manager.h"
|
|
|
|
|
|
#include "xtell.h"
|
|
|
|
|
|
#include "ui.h"
|
|
|
|
|
|
#include "rgb.h"
|
|
|
|
|
|
#include "event.h"
|
|
|
|
|
|
#include "system.h"
|
|
|
|
|
|
#include "database.h"
|
|
|
|
|
|
#include "../Drivers/lcd.h"
|
|
|
|
|
|
|
|
|
|
|
|
// 外部全局变量引用
|
|
|
|
|
|
extern SystemState current_state;
|
|
|
|
|
|
extern u32 captured_addr;
|
|
|
|
|
|
extern u8 alarm_sensor_slot;
|
|
|
|
|
|
extern volatile u16 ms_tick;
|
|
|
|
|
|
extern volatile bit alarm_flash_flag;
|
|
|
|
|
|
|
|
|
|
|
|
// 传感器存储列表数据库声明
|
|
|
|
|
|
extern Sensor_Slot xdata sensor_list[16];
|
|
|
|
|
|
|
|
|
|
|
|
// 本地私有变量
|
2026-07-17 09:41:29 +08:00
|
|
|
|
static u32 alarm_pulse_timer = 0; // 报警震动波形计数器
|
2026-07-17 09:08:53 +08:00
|
|
|
|
static u16 last_run_tick = 0; // 记录上一次轮询的 ticks
|
|
|
|
|
|
|
|
|
|
|
|
// 声明本应用的生命周期回调函数
|
|
|
|
|
|
static void AlarmApp_OnStart(void);
|
|
|
|
|
|
static void AlarmApp_onRun(void);
|
|
|
|
|
|
static void AlarmApp_onClose(void);
|
|
|
|
|
|
static EventResult AlarmApp_onEvent(SystemEvent *evt);
|
|
|
|
|
|
|
|
|
|
|
|
// 实体化定义警报应用控制块
|
|
|
|
|
|
WristbandApp alarm_app = {
|
|
|
|
|
|
APP_ID_ALARM,
|
|
|
|
|
|
"Alarm",
|
|
|
|
|
|
AlarmApp_OnStart,
|
|
|
|
|
|
AlarmApp_onRun,
|
|
|
|
|
|
AlarmApp_onClose,
|
|
|
|
|
|
AlarmApp_onEvent
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief AlarmApp 启动回调
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void AlarmApp_OnStart(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
u8 slot;
|
|
|
|
|
|
u8 type = 0;
|
|
|
|
|
|
u8 zone = 1;
|
|
|
|
|
|
|
|
|
|
|
|
current_state = STATE_ALARM; // 系统切入报警状态
|
2026-07-17 09:41:29 +08:00
|
|
|
|
alarm_pulse_timer = 0; // 振动计时器清零
|
2026-07-17 09:08:53 +08:00
|
|
|
|
last_run_tick = ms_tick;
|
|
|
|
|
|
|
|
|
|
|
|
// 比对查出当前触发警报的传感器在数据库中的属性
|
|
|
|
|
|
if (Check_Sensor_ID(captured_addr, &slot)) {
|
|
|
|
|
|
type = sensor_list[slot].type;
|
|
|
|
|
|
zone = sensor_list[slot].zone;
|
|
|
|
|
|
alarm_sensor_slot = slot;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染显示报警图文界面
|
|
|
|
|
|
UI_ShowAlarmPage(type, zone);
|
|
|
|
|
|
|
|
|
|
|
|
// 首次亮起防区特定的警示色彩,起到区分报警硬件的目的
|
|
|
|
|
|
if (type == 0) RGB_Send(0, 180, 0, 0, 180, 0); // 门磁: 红色 (GRB中R=180,G=0)
|
|
|
|
|
|
else if (type == 1) RGB_Send(100, 180, 0, 100, 180, 0); // 红外PIR: 黄色 (G=100, R=180)
|
|
|
|
|
|
else if (type == 2) RGB_Send(180, 0, 0, 180, 0, 0); // 烟感: 绿色 (G=180)
|
|
|
|
|
|
else if (type == 3) RGB_Send(0, 180, 180, 0, 180, 180); // 气感: 紫色 (R=180, B=180)
|
|
|
|
|
|
else RGB_Send(0, 0, 180, 0, 0, 180); // 水浸: 蓝色 (B=180)
|
|
|
|
|
|
|
|
|
|
|
|
XTELL_LOG("[AlarmApp] Started. Type=");
|
|
|
|
|
|
XTELL_LOG_HEX8(type);
|
|
|
|
|
|
XTELL_LOG("\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief AlarmApp 轮询主回调
|
|
|
|
|
|
* @details 包含同步的灯光爆闪和 Truly AMOLED 像素边框闪烁动效,
|
|
|
|
|
|
* 以及马达差异化震动波形逻辑的自处理。
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void AlarmApp_onRun(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
u8 type = sensor_list[alarm_sensor_slot].type;
|
|
|
|
|
|
u8 flash_light = (ms_tick / 250) % 2; // 250ms 周期亮灭
|
|
|
|
|
|
u16 tick_diff;
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 同步控制 RGB 幻彩灯条进行交替爆闪
|
|
|
|
|
|
if (flash_light)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (type == 0) RGB_Send(0, 180, 0, 0, 180, 0);
|
|
|
|
|
|
else if (type == 1) RGB_Send(100, 180, 0, 100, 180, 0);
|
|
|
|
|
|
else if (type == 2) RGB_Send(180, 0, 0, 180, 0, 0);
|
|
|
|
|
|
else if (type == 3) RGB_Send(0, 180, 180, 0, 180, 180);
|
|
|
|
|
|
else RGB_Send(0, 0, 180, 0, 0, 180);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 控制 Truly AMOLED 屏幕的最外围红色警告框闪烁效果
|
|
|
|
|
|
if (alarm_flash_flag) {
|
|
|
|
|
|
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED);
|
|
|
|
|
|
LCD_DrawRectBorder(6, 6, 108, 228, COLOR_RED);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK);
|
|
|
|
|
|
LCD_DrawRectBorder(6, 6, 108, 228, COLOR_BLACK);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 计算时间差并执行马达差异化震动状态机控制
|
|
|
|
|
|
if (ms_tick >= last_run_tick) {
|
|
|
|
|
|
tick_diff = ms_tick - last_run_tick;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
tick_diff = 1000 + ms_tick - last_run_tick;
|
|
|
|
|
|
}
|
|
|
|
|
|
last_run_tick = ms_tick;
|
|
|
|
|
|
|
2026-07-17 09:41:29 +08:00
|
|
|
|
alarm_pulse_timer += tick_diff;
|
|
|
|
|
|
if (alarm_pulse_timer >= 5000) {
|
|
|
|
|
|
alarm_pulse_timer = 0; // 5秒一周期
|
2026-07-17 09:08:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (type == 0) {
|
|
|
|
|
|
// 门磁警报波形:单次震动 300ms,停 4700ms
|
2026-07-17 09:41:29 +08:00
|
|
|
|
if (alarm_pulse_timer < 300) MOTOR = 1; else MOTOR = 0;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
} else if (type == 1) {
|
|
|
|
|
|
// PIR 警报波形:震动 300ms,停 200ms,再震动 300ms,停 4200ms
|
2026-07-17 09:41:29 +08:00
|
|
|
|
if (alarm_pulse_timer < 300) MOTOR = 1;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 300 && alarm_pulse_timer < 500) MOTOR = 0;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 500 && alarm_pulse_timer < 800) MOTOR = 1;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
else MOTOR = 0;
|
|
|
|
|
|
} else if (type == 2) {
|
|
|
|
|
|
// 烟感警报波形:急促短闪三下 200ms-150ms-200ms-150ms-200ms
|
2026-07-17 09:41:29 +08:00
|
|
|
|
if (alarm_pulse_timer < 200) MOTOR = 1;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 200 && alarm_pulse_timer < 350) MOTOR = 0;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 350 && alarm_pulse_timer < 550) MOTOR = 1;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 550 && alarm_pulse_timer < 700) MOTOR = 0;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 700 && alarm_pulse_timer < 900) MOTOR = 1;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
else MOTOR = 0;
|
|
|
|
|
|
} else if (type == 3) {
|
|
|
|
|
|
// 燃气报警波形:快频连续四下
|
2026-07-17 09:41:29 +08:00
|
|
|
|
if (alarm_pulse_timer < 200) MOTOR = 1;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 200 && alarm_pulse_timer < 300) MOTOR = 0;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 300 && alarm_pulse_timer < 500) MOTOR = 1;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 500 && alarm_pulse_timer < 600) MOTOR = 0;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 600 && alarm_pulse_timer < 800) MOTOR = 1;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 800 && alarm_pulse_timer < 900) MOTOR = 0;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 900 && alarm_pulse_timer < 1100) MOTOR = 1;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
else MOTOR = 0;
|
|
|
|
|
|
} else if (type == 4) {
|
|
|
|
|
|
// 水浸警报波形:慢速双长震波 600ms 和 600ms
|
2026-07-17 09:41:29 +08:00
|
|
|
|
if (alarm_pulse_timer < 600) MOTOR = 1;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 600 && alarm_pulse_timer < 900) MOTOR = 0;
|
|
|
|
|
|
else if (alarm_pulse_timer >= 900 && alarm_pulse_timer < 1500) MOTOR = 1;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
else MOTOR = 0;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 缺省状态默认单次 300ms
|
2026-07-17 09:41:29 +08:00
|
|
|
|
if (alarm_pulse_timer < 300) MOTOR = 1; else MOTOR = 0;
|
2026-07-17 09:08:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief AlarmApp 退出清理
|
|
|
|
|
|
*/
|
|
|
|
|
|
static void AlarmApp_onClose(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
RGB_Send(0, 0, 0, 0, 0, 0); // 关闭灯条
|
|
|
|
|
|
MOTOR = 0; // 停震
|
|
|
|
|
|
current_state = STATE_NORMAL;
|
|
|
|
|
|
XTELL_LOG("[AlarmApp] Closed\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief AlarmApp 事件拦截处理 (按任意键退出报警)
|
|
|
|
|
|
*/
|
|
|
|
|
|
static EventResult AlarmApp_onEvent(SystemEvent *evt)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (evt->key_event != KEY_EVENT_NONE) {
|
|
|
|
|
|
AppManager_SwitchToForeground(&clock_app); // 清除报警并切回时钟待机页
|
|
|
|
|
|
return EVENT_HANDLED;
|
|
|
|
|
|
}
|
|
|
|
|
|
return EVENT_IGNORED;
|
|
|
|
|
|
}
|