Files
stc32g128k/App/app_pair.c

232 lines
7.9 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 "xtell.h"
#include "ui.h"
#include "rgb.h"
#include "event.h"
#include "system.h"
#include "database.h"
#include "../Drivers/rf.h"
// 外部全局变量引用
extern SystemState current_state;
extern u8 current_sec;
extern u8 captured_type;
extern u32 captured_addr;
extern volatile u16 ms_tick;
// 对码状态机定义
enum {
PAIR_STATE_WAIT, // 等待射频探测器触发 (扩散雷达页面)
PAIR_STATE_CONFIRM, // 已捕获,进入分配防区确认页面
PAIR_STATE_SUCCESS, // 对码绑定成功界面 (SUCCESS)
PAIR_STATE_FAIL // 超时或失败界面 (FAIL)
};
// 本地私有变量
static u8 pair_state; // 当前的对码阶段状态
static u8 last_radar_sec; // 备份上一次雷达动画的帧索引
static u8 captured_zone = 1; // 准备分配的防区号 (1~99)
static u8 success_start_sec = 0;// 对码成功时的起始秒数 (延迟退场)
static u8 fail_start_sec = 0; // 对码失败时的起始秒数
static u32 pair_timeout_ms = 0; // 对码超时毫秒计数器
static u16 last_run_tick = 0; // 上一次执行 onRun 时的毫秒滴答数
// 声明本应用的生命周期回调函数
static void PairApp_OnStart(void);
static void PairApp_onRun(void);
static void PairApp_onClose(void);
static EventResult PairApp_onEvent(SystemEvent *evt);
// 实体化定义对码应用控制块
WristbandApp pair_app = {
APP_ID_PAIR,
"Pair",
PairApp_OnStart,
PairApp_onRun,
PairApp_onClose,
PairApp_onEvent
};
/**
* @brief PairApp 启动回调
*/
static void PairApp_OnStart(void)
{
// 1. 为了防止后台射频监听与对码射频接收冲突,将后台射频监听应用暂时卸载
AppManager_DetachFromBackground(&rf_monitor_app);
pair_state = PAIR_STATE_WAIT;
last_radar_sec = 99; // 强制刷写
current_state = STATE_PAIR_WAIT;
pair_timeout_ms = 0;
last_run_tick = ms_tick;
captured_zone = 1;
RF_SetMode(1); // 开启无线接收模式
// 初始化对码搜索页面绘制
UI_ShowPairWaitPage(0);
// 开启白色幻彩双灯珠常亮 (R=150, G=150, B=150),作为对码状态视觉指示
RGB_Send(150, 150, 150, 150, 150, 150);
XTELL_LOG("[PairApp] Started (WAIT)\r\n");
}
/**
* @brief PairApp 轮询主回调
*/
static void PairApp_onRun(void)
{
u32 rx_addr;
u8 rx_data;
u8 flash;
u8 frame;
u16 tick_diff;
// 计算非阻塞的毫秒时间增量
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;
if (pair_state == PAIR_STATE_WAIT) {
// ====== 等待射频数据期间,白光 3Hz 高频闪烁 (周期 333ms) ======
flash = (ms_tick / 166) % 2;
if (flash) RGB_Send(150, 150, 150, 150, 150, 150);
else RGB_Send(0, 0, 0, 0, 0, 0);
// 每隔 250ms滚动绘制雷达搜索的 3 帧图片,构成动效
frame = (u8)((ms_tick / 250) % 3);
if (frame != last_radar_sec) {
last_radar_sec = frame;
UI_ShowPairWaitPage(frame);
}
// 累加计算 30 秒的对码时间上限
pair_timeout_ms += tick_diff;
if (pair_timeout_ms >= 30000UL) {
pair_timeout_ms = 0;
pair_state = PAIR_STATE_FAIL;
current_state = STATE_PAIR_FAIL;
fail_start_sec = current_sec;
UI_ShowPairFailPage(1); // 绘制超时大红叉页
// 红色双灯常亮警告
RGB_Send(200, 0, 0, 200, 0, 0);
XTELL_LOG("[PairApp] Timeout fail!\r\n");
return;
}
// ====== 物理射频包解调接收监听 ======
if (EV1527_Decode(&rx_addr, &rx_data)) {
// 保护机制:排除 SOS 码 (0x08)
if (rx_data != 0x08) {
captured_addr = rx_addr; // 缓存捕获的物理 ID 地址 (含数据码)
pair_state = PAIR_STATE_CONFIRM; // 进入防区微调确认模式
current_state = STATE_PAIR_CONFIRM;
RF_SetMode(0); // 暂时关闭物理射频,防止再次覆盖
captured_zone = 1;
UI_ShowPairConfirmPage(captured_type, captured_zone);
XTELL_LOG("[PairApp] Sensor captured. Addr=");
XTELL_LOG_HEX32(rx_addr);
XTELL_LOG("\r\n");
}
}
}
else if (pair_state == PAIR_STATE_CONFIRM) {
// ====== 确认状态:橙色慢闪 (1.5Hz,周期 666ms) ======
u8 flash_orange = (ms_tick / 333) % 2;
if (flash_orange) RGB_Send(100, 180, 0, 100, 180, 0); // 橙色 (G=180, R=100)
else RGB_Send(0, 0, 0, 0, 0, 0);
}
else if (pair_state == PAIR_STATE_SUCCESS) {
// ====== 成功展示状态:延时 2 秒自动返回二级设置菜单 ======
u8 elapsed = (current_sec >= success_start_sec) ? (current_sec - success_start_sec) : (60 + current_sec - success_start_sec);
if (elapsed >= 2) {
AppManager_SwitchToForeground(&menu_app);
}
}
else if (pair_state == PAIR_STATE_FAIL) {
// ====== 失败展示状态:延时 5 秒自动返回二级设置菜单 ======
u8 elapsed = (current_sec >= fail_start_sec) ? (current_sec - fail_start_sec) : (60 + current_sec - fail_start_sec);
if (elapsed >= 5) {
AppManager_SwitchToForeground(&menu_app);
}
}
}
/**
* @brief PairApp 退出清理
*/
static void PairApp_onClose(void)
{
RGB_Send(0, 0, 0, 0, 0, 0); // 关闭 RGB
MOTOR = 0; // 停震
RF_SetMode(1); // 开启无线接收
// 重新挂载后台射频监控应用,以便回到时钟状态下能继续捕获报警
AppManager_AttachToBackground(&rf_monitor_app);
XTELL_LOG("[PairApp] Closed\r\n");
}
/**
* @brief PairApp 事件拦截处理回调
*/
static EventResult PairApp_onEvent(SystemEvent *evt)
{
if (pair_state == PAIR_STATE_CONFIRM) {
if (evt->key_event == KEY_EVENT_UP_CLICK) {
// 短按 ▲ 键增加目标分配防区号 (上限 99)
if (captured_zone < 99) {
captured_zone++;
UI_ShowPairConfirmPage(captured_type, captured_zone);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_DOWN_CLICK) {
// 短按 ▼ 键减小目标分配防区号 (下限 1)
if (captured_zone > 1) {
captured_zone--;
UI_ShowPairConfirmPage(captured_type, captured_zone);
}
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_CLICK) {
// 短按 ■ 确认键,写入 EEPROM 传感器数据库并保存
Add_Sensor_With_Zone(captured_addr, captured_type, captured_zone);
pair_state = PAIR_STATE_SUCCESS;
current_state = STATE_PAIR_SUCCESS;
success_start_sec = current_sec;
UI_ShowPairSuccessPage(); // 绘制打勾页
// 绿色双灯珠常亮,震动马达长震 400ms 反馈
RGB_Send(0, 200, 0, 0, 200, 0);
MOTOR = 1;
Delay_ms(400);
MOTOR = 0;
XTELL_LOG("[PairApp] Sensor saved successfully.\r\n");
return EVENT_HANDLED;
}
if (evt->key_event == KEY_EVENT_CONFIRM_LONG) {
// 长按 ■ 确认键放弃本次捕获,直接返回二级主菜单
RGB_Send(0, 0, 0, 0, 0, 0);
AppManager_SwitchToForeground(&menu_app);
return EVENT_HANDLED;
}
}
// 在对码搜寻或确认防区期间,长按 ▼ 键均代表强行取消对码直接退回菜单页
if (evt->key_event == KEY_EVENT_DOWN_LONG) {
RGB_Send(0, 0, 0, 0, 0, 0);
AppManager_SwitchToForeground(&menu_app);
return EVENT_HANDLED;
}
return EVENT_IGNORED;
}