189 lines
7.1 KiB
C
189 lines
7.1 KiB
C
/******************************************************************************
|
||
* @file app_function.c
|
||
* @brief CBR3 功能总装实现
|
||
* @author cyWu <1917507415@qq.com>
|
||
* @date 2026.09.02
|
||
* @version V3.0.0(规格书 V3.0.0):app_cond → app_linkage/app_runrec;
|
||
* 出厂重置改清联动 20B + 31 天运行记录(DP21,规格书第 14 章)
|
||
******************************************************************************/
|
||
|
||
#include "system/includes.h" /* 必须先于 app_main.h:u8/u16/u32 等类型由 SDK 定义 */
|
||
#include "app_function.h"
|
||
#include "app_pair.h"
|
||
#include "app_mode.h"
|
||
#include "app_fan.h"
|
||
#include "app_nvm.h"
|
||
#include "app_defer.h"
|
||
#include "app_arbiter.h"
|
||
#include "app_linkage.h"
|
||
#include "app_runrec.h"
|
||
#include "app_timer_task.h"
|
||
#include "app_th.h"
|
||
#include "app_led.h"
|
||
#include "app_main.h"
|
||
#include "usr_le_api.h"
|
||
#include "jb_product.h"
|
||
#include "board_pin.h"
|
||
#include <string.h>
|
||
|
||
#define LOG_TAG_CONST APP
|
||
#define LOG_TAG "[APP_FUNC]"
|
||
#define LOG_INFO_ENABLE
|
||
#include "debug.h"
|
||
|
||
/**
|
||
* @brief 初始化功能模块状态
|
||
* @note DP0 power 恒为开机态:规格书 0 章第 5 条"预留,不当开关",
|
||
* 协议层 DP0 写入本就忽略(jb_product.c),本产品无软关机,
|
||
* 这里写死一次即可,不需要额外状态字段
|
||
* @return 无
|
||
*/
|
||
void app_function_init(void)
|
||
{
|
||
gDevData.power = 1;
|
||
}
|
||
|
||
/**
|
||
* @brief 任务上下文周期处理(由 usr_timer_loop 500ms 调用)
|
||
* @note ⚠ 本函数是唯一允许做 VM 落盘、清绑定、OTA 启动的地方:
|
||
* usr_timer_loop 跑在 BLE 线程(sys_timer 同步接口,任务上下文,栈充足)。
|
||
* 20ms 的 usr_timer_tick 是硬件定时器中断上下文,做这些会栈溢出复位。
|
||
* @return 无
|
||
*/
|
||
void app_function_loop(void)
|
||
{
|
||
app_nvm_flush(); /* 防抖满后真正写 VM(syscfg_write 必须在任务上下文) */
|
||
|
||
/* OTA 优先于配对:按满 12s 说明用户不是想配网,放弃本次清绑定 */
|
||
if (app_defer_take(APP_DEFER_OTA)) {
|
||
app_defer_cancel(APP_DEFER_PAIR);
|
||
usr_app_ota_init(); /* BLE 侧:置 usr_goto_updata + 1s 定时器切 OTA 广播 */
|
||
app_led_request_ota(); /* 200ms 闪,优先级最高 */
|
||
log_info("key hold 12s -> ota\n");
|
||
} else if (app_defer_take(APP_DEFER_PAIR)) {
|
||
/* ⚠ 真正发起配对广播:usr_goto_pair_mode 内部会断连+清绑定(写VM)+重发绑定广播
|
||
* 必须在任务上下文调用(写 VM)。仅置 usr_var.usr_goto_pair 标志无效——
|
||
* SDK adv 模块只消费 usr_goto_updata,不消费该标志,不会开广播。 */
|
||
usr_goto_pair_mode();
|
||
app_pair_start(); /* 起 120s 配对会话,灯交由 app_led_run 接管 */
|
||
app_led_clear_pair_hint();
|
||
log_info("key hold 5s -> pair\n");
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 同步 DP(fan_gear、mode、fault_code),每个业务 tick 调用
|
||
* @note DP3/DP4 温湿度在 userHandle(500ms)填;DP0 power 不在这里同步,
|
||
* 恒为开机态,写死在 app_function_init
|
||
* @return 无
|
||
*/
|
||
void app_function_poll(void)
|
||
{
|
||
gDevData.fan_gear = app_fan_get_gear(); /* DP2 必须等于当前真实档位 */
|
||
gDevData.mode = app_mode_get_active();
|
||
/* DP18 fault_code:传感器连续失败报 1;2 预留,温湿度出范围只走显示闪烁不上报(8.2) */
|
||
gDevData.fault_code = app_th_is_fault() ? 1 : 0;
|
||
}
|
||
|
||
/**
|
||
* @brief 短按:风扇档位循环 1→2→3→0→1…(规格书 5.3)
|
||
* @note 立刻退出通风/强力改为手动档:用 app_mode_stop() 只清模式、
|
||
* 不动档位(若用 set_manual(0) 会恢复模式前快照档,导致通风 1 档
|
||
* 短按跳到旧档+1 而非 2 档);配对进行中短按仍可切档
|
||
* @return 无
|
||
*/
|
||
void usr_on_key_short(void)
|
||
{
|
||
uint8_t g;
|
||
|
||
app_arbiter_manual_intervene(); /* 手动动作:释放联动/定时占用 + 本轮联动作废(12 章) */
|
||
app_mode_stop(); /* 退模式(不动档位,下面立刻切循环下一档) */
|
||
g = app_fan_get_gear(); /* 当前实际档:手动=手动档;模式中=模式强制档(1/3) */
|
||
g = (uint8_t)((g + 1) % 4); /* 1→2→3→0→1 */
|
||
app_fan_set_gear(g);
|
||
log_info("key short gear=%d\n", g);
|
||
}
|
||
|
||
/**
|
||
* @brief 按住满 5s:切配对提示灯,提示"松手即配网,继续按到 12s 进 OTA"
|
||
* @note 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,只准动灯效事件
|
||
* (纯 RAM)。清绑定写 VM 在 app_function_loop 做。
|
||
* @return 无
|
||
*/
|
||
void usr_on_key_pair_hint(void)
|
||
{
|
||
if (app_led_is_ota()) {
|
||
return; /* OTA 灯效最高优先级,不打断 */
|
||
}
|
||
app_led_hint_pair();
|
||
log_info("key hold 5s, pair hint (release to pair, keep to 12s for ota)\n");
|
||
}
|
||
|
||
/**
|
||
* @brief 按满 5s 后松手:提交配对(只置标志)
|
||
* @note ⚠ 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,只置标志。
|
||
* 清绑定(usr_clear_pair_info_noreset 会写 VM)放到任务上下文。
|
||
* @return 无
|
||
*/
|
||
void usr_on_key_pair_start(void)
|
||
{
|
||
if (app_led_is_ota()) {
|
||
return;
|
||
}
|
||
app_defer_request(APP_DEFER_PAIR);
|
||
log_info("key hold 5s released, pair pending\n");
|
||
}
|
||
|
||
/**
|
||
* @brief 按住满 12s:进 OTA(只置标志,到点即触发不等松手)
|
||
* @note ⚠ 本回调在 usr_timer 20ms(硬件定时器中断上下文)执行,只置标志。
|
||
* usr_app_ota_init 涉及 BLE 广播切换,放到任务上下文。
|
||
* @return 无
|
||
*/
|
||
void usr_on_key_ota_start(void)
|
||
{
|
||
if (app_led_is_ota()) {
|
||
return; /* 已在 OTA,不重复发起 */
|
||
}
|
||
app_defer_request(APP_DEFER_OTA);
|
||
log_info("key hold 12s, ota pending\n");
|
||
}
|
||
|
||
/**
|
||
* @brief 出厂重置:清业务 VM 与 RAM,保留 BLE 配对(规格书第 14 章)
|
||
* @note 清联动 20B、定时 7 组、31 天运行记录(VM 由 app_nvm_reset 全清);
|
||
* RAM:mode/gear/fan 停、联动作废清掉(app_linkage_init)、
|
||
* 运行记录清零。不断开、不软复位。
|
||
* @return 无
|
||
*/
|
||
void app_function_factory_reset(void)
|
||
{
|
||
uint8_t i;
|
||
uint8_t *tm[7] = {
|
||
gDevData.time_config1, gDevData.time_config2, gDevData.time_config3,
|
||
gDevData.time_config4, gDevData.time_config5, gDevData.time_config6,
|
||
gDevData.time_config7
|
||
};
|
||
|
||
app_nvm_reset();
|
||
app_arbiter_init(); /* owner=NONE */
|
||
app_linkage_init(); /* 联动配置 RAM 清零 + 作废标志清掉(init 不清配置,这里显式清) */
|
||
memset(gDevData.linkage_config, 0, BOARD_LINKAGE_CFG_LEN);
|
||
app_runrec_reset(); /* 31 天运行记录清零(14 章) */
|
||
app_timer_init(); /* 定时引擎状态复位 */
|
||
app_mode_stop();
|
||
app_fan_set_gear(0);
|
||
gDevData.mode = 0;
|
||
gDevData.fan_gear = 0;
|
||
gDevData.linkage_delete = 0;
|
||
gDevData.time_en = 0;
|
||
gDevData.fault_en = 0;
|
||
gDevData.alarm_en = 0;
|
||
gDevData.fault_code = 0;
|
||
gDevData.alarm_code = 0;
|
||
for (i = 0; i < 7; i++) {
|
||
memset(tm[i], 0, 8);
|
||
}
|
||
log_info("factory reset: business vm cleared, pairing kept\n");
|
||
}
|