Files
stc32g128k/App/app_manager.c

784 lines
24 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "app_manager.h"
#include "rgb.h"
#include "event.h"
#include "database.h"
#include "ui.h"
#include "system.h"
#include "../Drivers/rf.h"
#include "../Drivers/lcd.h"
#define APP_ONRUN_MAX_TICKS 5
// 定义局部静态注册表
static WristbandApp app_registry[APP_ID_MAX];
static WristbandApp *active_app = NULL;
#define DEFAULT_APP_ID APP_ID_CLOCK
// 定义菜单项定义
char *code menu_items[5] = {
"DETEC. PORTE",
"DETEC. PIR",
"DETEC. FUMEE",
"DETEC. GAZ",
"DETEC. EAU"
};
/* 回调函数前置声明 */
void ClockApp_OnStart(void);
void ClockApp_onRun(void);
void ClockApp_onClose(void);
EventResult ClockApp_onEvent(SystemEvent *evt);
void MenuApp_OnStart(void);
void MenuApp_onRun(void);
void MenuApp_onClose(void);
EventResult MenuApp_onEvent(SystemEvent *evt);
void PairApp_OnStart(void);
void PairApp_onRun(void);
void PairApp_onClose(void);
EventResult PairApp_onEvent(SystemEvent *evt);
void AlarmApp_OnStart(void);
void AlarmApp_onRun(void);
void AlarmApp_onClose(void);
EventResult AlarmApp_onEvent(SystemEvent *evt);
void SOSApp_OnStart(void);
void SOSApp_onRun(void);
void SOSApp_onClose(void);
EventResult SOSApp_onEvent(SystemEvent *evt);
/* ====== AppManager 核心接口 ====== */
void AppManager_Init(void)
{
u8 i;
/* 清零注册表 */
for (i = 0; i < APP_ID_MAX; i++) {
app_registry[i].app_id = APP_ID_MAX;
app_registry[i].app_type = APP_TYPE_FOREGROUND;
app_registry[i].app_name = "";
app_registry[i].OnStart = NULL;
app_registry[i].onRun = NULL;
app_registry[i].onClose = NULL;
app_registry[i].onEvent = NULL;
app_registry[i].is_active = 0;
app_registry[i].is_running = 0;
}
/* 注册 ClockApp */
app_registry[APP_ID_CLOCK].app_id = APP_ID_CLOCK;
app_registry[APP_ID_CLOCK].app_type = APP_TYPE_FOREGROUND;
app_registry[APP_ID_CLOCK].app_name = "Clock";
app_registry[APP_ID_CLOCK].OnStart = ClockApp_OnStart;
app_registry[APP_ID_CLOCK].onRun = ClockApp_onRun;
app_registry[APP_ID_CLOCK].onClose = ClockApp_onClose;
app_registry[APP_ID_CLOCK].onEvent = ClockApp_onEvent;
/* 注册 MenuApp */
app_registry[APP_ID_MENU].app_id = APP_ID_MENU;
app_registry[APP_ID_MENU].app_type = APP_TYPE_FOREGROUND;
app_registry[APP_ID_MENU].app_name = "Menu";
app_registry[APP_ID_MENU].OnStart = MenuApp_OnStart;
app_registry[APP_ID_MENU].onRun = MenuApp_onRun;
app_registry[APP_ID_MENU].onClose = MenuApp_onClose;
app_registry[APP_ID_MENU].onEvent = MenuApp_onEvent;
/* 注册 PairApp */
app_registry[APP_ID_PAIR].app_id = APP_ID_PAIR;
app_registry[APP_ID_PAIR].app_type = APP_TYPE_FOREGROUND;
app_registry[APP_ID_PAIR].app_name = "Pair";
app_registry[APP_ID_PAIR].OnStart = PairApp_OnStart;
app_registry[APP_ID_PAIR].onRun = PairApp_onRun;
app_registry[APP_ID_PAIR].onClose = PairApp_onClose;
app_registry[APP_ID_PAIR].onEvent = PairApp_onEvent;
/* 注册 AlarmApp */
app_registry[APP_ID_ALARM].app_id = APP_ID_ALARM;
app_registry[APP_ID_ALARM].app_type = APP_TYPE_FOREGROUND;
app_registry[APP_ID_ALARM].app_name = "Alarm";
app_registry[APP_ID_ALARM].OnStart = AlarmApp_OnStart;
app_registry[APP_ID_ALARM].onRun = AlarmApp_onRun;
app_registry[APP_ID_ALARM].onClose = AlarmApp_onClose;
app_registry[APP_ID_ALARM].onEvent = AlarmApp_onEvent;
/* 注册 SOSApp */
app_registry[APP_ID_SOS].app_id = APP_ID_SOS;
app_registry[APP_ID_SOS].app_type = APP_TYPE_FOREGROUND;
app_registry[APP_ID_SOS].app_name = "SOS";
app_registry[APP_ID_SOS].OnStart = SOSApp_OnStart;
app_registry[APP_ID_SOS].onRun = SOSApp_onRun;
app_registry[APP_ID_SOS].onClose = SOSApp_onClose;
app_registry[APP_ID_SOS].onEvent = SOSApp_onEvent;
AppManager_StartApp(DEFAULT_APP_ID);
}
void AppManager_StartApp(AppID app_id)
{
WristbandApp *target;
if (app_id >= APP_ID_MAX) return;
target = &app_registry[app_id];
if (target->OnStart == NULL) return;
if (active_app == target) return;
Uart_SendString("[APP] StartApp: ");
Uart_SendString(target->app_name);
Uart_SendString("\r\n");
/* 关闭当前活跃应用 */
if (active_app != NULL && active_app->onClose != NULL) {
active_app->is_active = 0;
active_app->onClose();
}
/* 切换并启动新应用 */
active_app = target;
if (active_app->OnStart != NULL) {
active_app->is_active = 1;
active_app->is_running = 1;
active_app->OnStart();
}
}
void AppManager_DispatchEvent(SystemEvent evt)
{
EventResult result = EVENT_IGNORED;
if (active_app != NULL && active_app->is_active && active_app->onEvent != NULL) {
result = active_app->onEvent(&evt);
if (result == EVENT_HANDLED) return;
}
}
void AppManager_RunActiveApp(void)
{
u16 start_tick;
u16 elapsed;
if (active_app == NULL || !active_app->is_active) return;
if (!active_app->is_running) return;
if (active_app->onRun == NULL) return;
start_tick = ms_tick;
active_app->onRun();
elapsed = ms_tick - start_tick;
if (elapsed > APP_ONRUN_MAX_TICKS) {
active_app->is_running = 0;
} else {
active_app->is_running = 1;
}
}
AppID AppManager_GetActiveAppID(void)
{
if (active_app == NULL) return APP_ID_MAX;
return active_app->app_id;
}
/* =========================================================================
* ClockApp 回调实现与时间编辑状态机
* ========================================================================= */
static u8 time_edit_active = 0;
static u8 time_edit_field = 1;
static u8 time_edit_blink_on = 1;
void Start_Time_Edit(void)
{
time_edit_active = 1;
time_edit_field = 1;
time_edit_blink_on = 1;
current_state = STATE_SET_TIME;
// FCOB 幻彩灯条蓝色常亮 (R=0, G=0, B=180)
RGB_Send(0, 0, 180, 0, 0, 180);
// 马达短振 50ms
MOTOR = 1;
Delay_ms(50);
MOTOR = 0;
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
}
void ClockApp_OnStart(void)
{
time_edit_active = 0;
current_state = STATE_NORMAL;
RF_SetMode(0);
UI_ShowClockPage(current_state, current_hour, current_min);
// 启动时熄灭灯条
RGB_Send(0, 0, 0, 0, 0, 0);
Uart_SendString("[ClockApp] Started\r\n");
}
void ClockApp_onRun(void)
{
u32 rx_addr;
u8 rx_data;
if (time_edit_active)
{
// 500ms 周期控制闪烁
u8 blink = (ms_tick / 500) % 2;
if (blink != time_edit_blink_on)
{
time_edit_blink_on = blink;
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, time_edit_blink_on);
}
}
else
{
if (clock_updated) {
clock_updated = 0;
UI_ShowClockPage(current_state, current_hour, current_min);
}
if (EV1527_Decode(&rx_addr, &rx_data)) {
u8 slot;
if (Check_Sensor_ID(rx_addr, &slot)) {
u8 sensor_type = sensor_list[slot].type;
if (sensor_type < 5) {
if (sensor_list[slot].zone == 0 || current_state == STATE_ARMED) {
SystemEvent rf_evt;
rf_evt.key_event = KEY_EVENT_NONE;
rf_evt.priority = EVENT_PRIORITY_HIGH;
rf_evt.extra_data = rx_addr;
rf_evt.extra_size = 4;
EventQueue_InsertFront(rf_evt);
}
}
}
}
}
}
void ClockApp_onClose(void)
{
time_edit_active = 0;
RGB_Send(0, 0, 0, 0, 0, 0);
Uart_SendString("[ClockApp] Closed\r\n");
}
EventResult ClockApp_onEvent(SystemEvent *evt)
{
if (time_edit_active)
{
if (evt->key_event == KEY_EVENT_UP_CLICK)
{
if (time_edit_field == 1) {
current_hour = (current_hour + 1) % 24;
} else {
current_min = (current_min + 1) % 60;
}
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_DOWN_CLICK)
{
if (time_edit_field == 1) {
current_hour = (current_hour == 0) ? 23 : (current_hour - 1);
} else {
current_min = (current_min == 0) ? 59 : (current_min - 1);
}
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_LONG)
{
// 长按 Confirm 键跳转字段
if (time_edit_field == 1) {
time_edit_field = 2;
} else {
time_edit_field = 1;
}
UI_ShowSetTimePage(current_hour, current_min, time_edit_field, 1);
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK)
{
// 短按 Confirm 键保存退出
time_edit_active = 0;
current_state = STATE_NORMAL;
RGB_Send(0, 0, 0, 0, 0, 0); // 熄灭
// 退出短振
MOTOR = 1; Delay_ms(50); MOTOR = 0;
UI_ShowClockPage(current_state, current_hour, current_min);
return EVENT_HANDLED;
}
return EVENT_HANDLED; // 吞掉其他按键
}
if (evt->key_event == KEY_EVENT_CONFIRM_LONG) {
AppManager_StartApp(APP_ID_MENU);
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_UP_LONG) {
if (current_state == STATE_ARMED) {
current_state = STATE_DISARMED;
} else {
current_state = STATE_ARMED;
}
// 切换状态短震确认
MOTOR = 1; Delay_ms(100); MOTOR = 0;
UI_ShowClockPage(current_state, current_hour, current_min);
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_SOS_CLICK || evt->key_event == KEY_EVENT_SOS_LONG) {
AppManager_StartApp(APP_ID_SOS);
return EVENT_HANDLED;
}
return EVENT_IGNORED;
}
/* =========================================================================
* MenuApp 回调实现
* ========================================================================= */
static u8 menu_level = 0; // 0:主菜单, 1:传感器对码二级菜单, 2:IPC绑定中
static u16 last_bind_tx_ms = 0;
void MenuApp_OnStart(void)
{
menu_level = 0;
menu_select = 0;
current_state = STATE_PAIR_MENU;
RF_SetMode(0);
UI_ShowMainMenu(menu_select);
RGB_Send(0, 0, 0, 0, 0, 0); // 熄灭灯条
Uart_SendString("[MenuApp] Started (Main Menu)\r\n");
}
void MenuApp_onRun(void)
{
if (menu_level == 2)
{
// 绑定中:控制青色呼吸灯 (周期1000ms双灯同步)
u16 breath = ms_tick % 1000;
u8 val = (breath < 500) ? (breath * 2 / 5) : ((1000 - breath) * 2 / 5); // 范围 0~200
RGB_Send(0, val, val, 0, val, val);
// 每 500ms 发射一次绑定信号 (出厂 Factory ID)
if (ms_tick - last_bind_tx_ms >= 500 || ms_tick < last_bind_tx_ms)
{
last_bind_tx_ms = ms_tick;
RF_SetMode(2);
EV1527_Transmit(CLONED_ADDR, 0x01);
RF_SetMode(0);
}
}
}
void MenuApp_onClose(void)
{
menu_level = 0;
RGB_Send(0, 0, 0, 0, 0, 0);
RF_SetMode(0);
Uart_SendString("[MenuApp] Closed\r\n");
}
EventResult MenuApp_onEvent(SystemEvent *evt)
{
if (menu_level == 0)
{
// 主菜单层 (0-HORLOGE, 1-APPAIRAGE, 2-LIAISON)
if (evt->key_event == KEY_EVENT_UP_CLICK) {
if (menu_select > 0) {
menu_select--;
UI_ShowMainMenu(menu_select);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_DOWN_CLICK) {
if (menu_select < 2) {
menu_select++;
UI_ShowMainMenu(menu_select);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK) {
if (menu_select == 0) {
// 启动时钟 App 并立即进入编辑模式
AppManager_StartApp(APP_ID_CLOCK);
Start_Time_Edit();
} else if (menu_select == 1) {
// 进入二级传感器对码菜单
menu_level = 1;
menu_select = 0;
UI_ShowPairMenuPage(menu_select);
} else if (menu_select == 2) {
// 进入摄像机绑定
menu_level = 2;
last_bind_tx_ms = ms_tick;
current_state = STATE_IPC_BIND;
UI_ShowBindingPage(CLONED_ADDR);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_LONG) {
AppManager_StartApp(APP_ID_CLOCK);
return EVENT_HANDLED;
}
}
else if (menu_level == 1)
{
// 传感器对码选择菜单 (0-门磁, 1-PIR, 2-烟感, 3-气感, 4-水浸)
if (evt->key_event == KEY_EVENT_UP_CLICK) {
if (menu_select > 0) {
menu_select--;
UI_ShowPairMenuPage(menu_select);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_DOWN_CLICK) {
if (menu_select < 4) {
menu_select++;
UI_ShowPairMenuPage(menu_select);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK) {
// 保存当前选定的类型到 captured_type短震 100ms 并跳转到 PairApp 对码搜索
captured_type = menu_select;
MOTOR = 1;
Delay_ms(100);
MOTOR = 0;
AppManager_StartApp(APP_ID_PAIR);
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_DOWN_LONG) {
// 返回主菜单
menu_level = 0;
menu_select = 1;
UI_ShowMainMenu(menu_select);
return EVENT_HANDLED;
}
}
else if (menu_level == 2)
{
// 绑定中:长按 Confirm 键 (3秒) 或 长按 DOWN 键 (2秒) 退出返回主菜单
if (evt->key_event == KEY_EVENT_CONFIRM_LONG || evt->key_event == KEY_EVENT_DOWN_LONG) {
menu_level = 0;
menu_select = 2;
current_state = STATE_PAIR_MENU;
RGB_Send(0, 0, 0, 0, 0, 0); // 熄灭
UI_ShowMainMenu(menu_select);
return EVENT_HANDLED;
}
}
return EVENT_IGNORED;
}
/* =========================================================================
* PairApp 回调实现
* ========================================================================= */
enum {
PAIR_STATE_WAIT,
PAIR_STATE_CONFIRM,
PAIR_STATE_SUCCESS,
PAIR_STATE_FAIL
};
static u8 pair_state;
static u8 last_radar_sec;
static u8 captured_zone = 1;
static u32 success_start_ms = 0;
static u32 fail_start_ms = 0;
void PairApp_OnStart(void)
{
pair_state = PAIR_STATE_WAIT;
last_radar_sec = 99;
current_state = STATE_PAIR_WAIT;
pair_timeout_ms = 0;
captured_zone = 1;
RF_SetMode(1);
// 初始化对码搜寻状态显示
UI_ShowPairWaitPage(0);
// 快闪白色 RGB (双灯)
RGB_Send(150, 150, 150, 150, 150, 150);
Uart_SendString("[PairApp] Started (WAIT)\r\n");
}
void PairApp_onRun(void)
{
u32 rx_addr;
u8 rx_data;
u8 flash;
u8 frame;
if (pair_state == PAIR_STATE_WAIT) {
// 白色 3Hz 快闪 (周期 333ms, 亮 166ms)
flash = (ms_tick / 166) % 2;
if (flash) RGB_Send(150, 150, 150, 150, 150, 150);
else RGB_Send(0, 0, 0, 0, 0, 0);
frame = (u8)((ms_tick / 250) % 3);
if (frame != last_radar_sec) {
last_radar_sec = frame;
UI_ShowPairWaitPage(frame);
}
if (pair_timeout_ms >= 30000UL) {
pair_timeout_ms = 0;
pair_state = PAIR_STATE_FAIL;
current_state = STATE_PAIR_FAIL;
fail_start_ms = ms_tick;
UI_ShowPairFailPage(1);
// 红色常亮
RGB_Send(200, 0, 0, 200, 0, 0);
Uart_SendString("[PairApp] Timeout\r\n");
return;
}
if (EV1527_Decode(&rx_addr, &rx_data)) {
// 排除 SOS 数据码 (0x08 代表 SOS 求救,不用于常规传感器配对)
if (rx_data != 0x08)
{
captured_addr = rx_addr;
pair_state = PAIR_STATE_CONFIRM;
current_state = STATE_PAIR_CONFIRM;
RF_SetMode(0);
captured_zone = 1; // 初始为防区 1
UI_ShowPairConfirmPage(captured_type, captured_zone);
Uart_SendString("[PairApp] Sensor captured\r\n");
}
}
} else if (pair_state == PAIR_STATE_CONFIRM) {
// 橙色慢闪 (1.5Hz, 周期 666ms)
u8 flash = (ms_tick / 333) % 2;
if (flash) RGB_Send(100, 180, 0, 100, 180, 0); // 橙色
else RGB_Send(0, 0, 0, 0, 0, 0);
} else if (pair_state == PAIR_STATE_SUCCESS) {
// 2 秒后自动返回二级菜单
if (ms_tick - success_start_ms >= 2000 || ms_tick < success_start_ms)
{
AppManager_StartApp(APP_ID_MENU);
}
} else if (pair_state == PAIR_STATE_FAIL) {
// 5 秒后自动返回二级菜单
if (ms_tick - fail_start_ms >= 5000 || ms_tick < fail_start_ms)
{
AppManager_StartApp(APP_ID_MENU);
}
}
}
void PairApp_onClose(void)
{
RGB_Send(0, 0, 0, 0, 0, 0); // 关闭灯光
MOTOR = 0;
RF_SetMode(0);
Uart_SendString("[PairApp] Closed\r\n");
}
EventResult PairApp_onEvent(SystemEvent *evt)
{
if (pair_state == PAIR_STATE_CONFIRM) {
if (evt->key_event == KEY_EVENT_UP_CLICK) {
if (captured_zone < 99) {
captured_zone++;
UI_ShowPairConfirmPage(captured_type, captured_zone);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_DOWN_CLICK) {
if (captured_zone > 1) {
captured_zone--;
UI_ShowPairConfirmPage(captured_type, captured_zone);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK) {
// 保存防区配对并显示成功反馈
Add_Sensor_With_Zone(captured_addr, captured_type, captured_zone);
pair_state = PAIR_STATE_SUCCESS;
current_state = STATE_PAIR_SUCCESS;
success_start_ms = ms_tick;
UI_ShowPairSuccessPage();
// 绿色常亮且马达长振 400ms
RGB_Send(0, 200, 0, 0, 200, 0);
MOTOR = 1;
Delay_ms(400);
MOTOR = 0;
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_LONG) {
// 长按 Confirm 取消返回主菜单
RGB_Send(0, 0, 0, 0, 0, 0);
AppManager_StartApp(APP_ID_MENU);
return EVENT_HANDLED;
}
}
// 搜寻状态或确认状态下长按 DOWN 退出
if (evt->key_event == KEY_EVENT_DOWN_LONG) {
RGB_Send(0, 0, 0, 0, 0, 0);
AppManager_StartApp(APP_ID_MENU);
return EVENT_HANDLED;
}
return EVENT_IGNORED;
}
/* =========================================================================
* AlarmApp 回调实现
* ========================================================================= */
void AlarmApp_OnStart(void)
{
u8 slot;
u8 type = 0;
u8 zone = 1;
current_state = STATE_ALARM;
alarm_timer_ms = 0;
alarm_flash_flag = 0;
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); // 门磁: 红色 (R=180)
else if (type == 1) RGB_Send(100, 180, 0, 100, 180, 0); // PIR: 黄色
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); // 气感: 紫色
else RGB_Send(0, 0, 180, 0, 0, 180); // 水浸: 蓝色
Uart_SendString("[AlarmApp] Started\r\n");
}
void AlarmApp_onRun(void)
{
u8 type = sensor_list[alarm_sensor_slot].type;
u8 flash = (ms_tick / 250) % 2; // 250ms 亮灭周期
// 同步控制 RGB 幻彩灯闪烁
if (flash)
{
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);
}
// 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);
}
}
void AlarmApp_onClose(void)
{
RGB_Send(0, 0, 0, 0, 0, 0); // 关闭灯条
MOTOR = 0;
current_state = STATE_NORMAL;
Uart_SendString("[AlarmApp] Closed\r\n");
}
EventResult AlarmApp_onEvent(SystemEvent *evt)
{
// 任意键按下或长按 ➔ 清除报警返回时钟
if (evt->key_event != KEY_EVENT_NONE) {
AppManager_StartApp(APP_ID_CLOCK);
return EVENT_HANDLED;
}
return EVENT_IGNORED;
}
/* =========================================================================
* SOSApp 回调实现
* ========================================================================= */
static u8 sos_last_phase;
void SOSApp_OnStart(void)
{
current_state = STATE_SOS_EMITTED;
sos_last_phase = 99;
alarm_timer_ms = 0;
UI_ShowSosPage();
// 立即启动双灯交替爆闪
RGB_Send(0, 200, 0, 0, 0, 0);
Uart_SendString("[SOSApp] Started\r\n");
}
void SOSApp_onRun(void)
{
// 每 500ms 发射一次求救射频信号 (CLONED_ADDR 伴随 SOS 数据码 0x08)
u8 sec_phase = (u8)((ms_tick / 500) % 2);
if (sec_phase != sos_last_phase) {
sos_last_phase = sec_phase;
RF_SetMode(2);
EV1527_Transmit(CLONED_ADDR, 0x08);
RF_SetMode(0);
}
// 50ms 周期控制双灯交替红色闪烁
{
u8 flash = (ms_tick / 50) % 2;
if (flash) {
RGB_Send(0, 200, 0, 0, 0, 0); // 灯1亮红灯2灭
} else {
RGB_Send(0, 0, 0, 0, 200, 0); // 灯1灭灯2亮红
}
}
// Truly AMOLED 边框闪烁 (红粗边框 + 白细边框)
if (alarm_flash_flag) {
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_RED);
LCD_DrawRectBorder(5, 5, 110, 230, COLOR_RED);
LCD_DrawRectBorder(8, 8, 104, 224, COLOR_WHITE);
} else {
LCD_DrawRectBorder(4, 4, 112, 232, COLOR_BLACK);
LCD_DrawRectBorder(5, 5, 110, 230, COLOR_BLACK);
LCD_DrawRectBorder(8, 8, 104, 224, COLOR_BLACK);
}
}
void SOSApp_onClose(void)
{
RGB_Send(0, 0, 0, 0, 0, 0); // 关闭灯条
MOTOR = 0;
current_state = STATE_NORMAL;
Uart_SendString("[SOSApp] Closed\r\n");
}
EventResult SOSApp_onEvent(SystemEvent *evt)
{
// 短按或长按任意键 ➔ 退出求救状态返回待机时钟
if (evt->key_event != KEY_EVENT_NONE) {
AppManager_StartApp(APP_ID_CLOCK);
return EVENT_HANDLED;
}
return EVENT_IGNORED;
}