/****************************************************************************** * @file usr_le_adv.c * @brief BLE 广播 / 配对 / OTA 广播切换 * @author cyWu <1917507415@qq.com> * @date 2026.08.19 * @version V1.1.0 * @history * - V1.0.0, 2026.08.03, cyWu, 首次发布 * - V1.1.0, 2026.08.19, cyWu, 对齐模组注释与助手;保留 SOC 上电绑广播策略 ******************************************************************************/ #include "system/includes.h" #include "app_config.h" #include "app_main.h" #include "vm.h" #include "bleproto.h" #include "bleproto_api.h" #include "usr_le_product.h" #define LOG_TAG_CONST APP #define LOG_TAG "[LE_ADV]" #define LOG_ERROR_ENABLE #define LOG_DEBUG_ENABLE #define LOG_INFO_ENABLE #include "debug.h" /****************************************************************************** * 广播相关三个标志(务必区分): * * 1) usr_auth_data.paired_flag —— 配网结果(存 VM,掉电保持) * - 0:未配网 * - 1:已配网(三元组已保存) * * 2) usr_var.usr_goto_pair —— 是否主动进入配网流程(RAM,掉电丢失) * - 0:非配网流程 * - 1:app_main 上电 / usr_goto_pair_mode() 触发,发【绑定广播】 * * 3) usr_var.usr_adv_flag —— 广播内容是否需要刷新到协议栈(一次性) * - 1:usr_ble_adv_updata() 会重新 set adv data 并 enable * - 0:本周期不刷新 * * SOC 决策表(与模组不同:未配网也发绑定广播,便于上电配网): * usr_goto_pair==1 → 绑定广播 * paired_flag==0 → 绑定广播 * paired_flag==1 → 回连广播 ******************************************************************************/ extern u8 muti_adv_data[31]; extern u8 muti_adv_data_len; /* 定义在 usr_le_recieve.c,库内共用,不对外导出 */ extern bleproto_authsetup_req_t usr_auth_data; extern u16 usr_get_conn_service(void); extern int muti_make_set_adv_data(u8 *data, u8 data_len); extern int muti_make_set_adv_data_updata(void); extern void usr_set_adv_interval(u16 val); extern u16 usr_get_adv_interval(void); extern void ble_multi_trans_disconnect(void); extern void ble_trans_module_enable(u8 flag); extern void usr_timer_loop(void); extern u8 usr_get_ota_status(void); extern void usr_ota_exit(void); void usr_ble_adv_init(void); void usr_ble_adv_updata(void); static int le_timer_handle = 0; /** * @brief BLE 是否已连接 * @return 1=已连接,0=未连接 */ uint8_t usr_ble_is_connected(void) { return (usr_get_conn_service() != 0) ? 1u : 0u; } /** * @brief 从 VM 读取配对信息到 usr_auth_data * @note 失败则清零,并将 paired_flag 置 0 写回 */ void usr_get_pair_info(void) { int ret; ret = syscfg_read(CFG_USER_PAIR_INFO, (u8 *)&usr_auth_data, sizeof(usr_auth_data)); if (ret <= 0) { memset(&usr_auth_data, 0x00, sizeof(usr_auth_data)); usr_auth_data.paired_flag = 0; syscfg_write(CFG_USER_PAIR_INFO, (u8 *)&usr_auth_data, sizeof(usr_auth_data)); } } /** * @brief 标记已配网并保存三元组到 VM * @note AUTHSETUP 成功后调用,paired_flag = 1 */ void usr_write_pair_info(void) { usr_auth_data.paired_flag = 1; syscfg_write(CFG_USER_PAIR_INFO, (u8 *)&usr_auth_data, sizeof(usr_auth_data)); } /** * @brief 清除配对信息并延时复位 */ void usr_clear_pair_info(void) { printf("usr_clear_pair_info_reset\n"); memset(&usr_auth_data, 0x00, sizeof(usr_auth_data)); usr_auth_data.paired_flag = 0; syscfg_write(CFG_USER_PAIR_INFO, (u8 *)&usr_auth_data, sizeof(usr_auth_data)); sys_timeout_add(NULL, cpu_reset, 600); } /** * @brief 清除配对信息但不复位(用于重新配网) */ void usr_clear_pair_info_noreset(void) { printf("usr_clear_pair_info_noreset\n"); memset(&usr_auth_data, 0x00, sizeof(usr_auth_data)); usr_auth_data.paired_flag = 0; syscfg_write(CFG_USER_PAIR_INFO, (u8 *)&usr_auth_data, sizeof(usr_auth_data)); } /** * @brief 进入配网模式:清配对 + 置 usr_goto_pair + 发绑定广播 */ void usr_goto_pair_mode(void) { ble_multi_trans_disconnect(); usr_clear_pair_info_noreset(); usr_var.usr_goto_pair = 1; os_time_dly(5); usr_ble_adv_init(); } /** * @brief 断开 BLE 并停止广播(复位/重启前) */ void usr_ble_disconnect_and_stop_adv(void) { printf("usr_ble_disconnect_and_stop_adv\n"); ble_multi_trans_disconnect(); usr_var.usr_goto_pair = 0; usr_var.usr_adv_flag = 0; ble_trans_module_enable(0); } /** * @brief 按当前标志刷新广播策略并启动周期更新 * @note 见文件头「三个标志」;SOC 未配网也发绑定广播 */ void usr_ble_adv_init(void) { int8_t txpower = 0; uint8_t manucode[BLEPROTO_ADV_TLV_LENGTH_MANUCODE] = {0}; uint8_t prodcode[BLEPROTO_ADV_TLV_LENGTH_PRODCODE]; uint8_t gmac[6] = {0}; uint8_t pcode[BLE_PROTO_ADV_LENGTH_PCODE]; /* 产品身份由应用层 g_usr_le_* 提供(见 usr_jb_main.c) */ memcpy(prodcode, g_usr_le_prodcode, BLEPROTO_ADV_TLV_LENGTH_PRODCODE); memcpy(pcode, g_usr_le_pcode, BLE_PROTO_ADV_LENGTH_PCODE); usr_set_adv_interval(80); if (usr_var.usr_ota_succ_flag) { return; } if (usr_var.usr_goto_pair) { /* app_main 上电已置 usr_goto_pair=1 并清配对信息,此处发绑定广播供网关配网 */ usr_clear_pair_info_noreset(); printf("goto pair bind adv, paired_flag=%d\n", usr_auth_data.paired_flag); muti_adv_data_len = bleproto_advdata_encode4bind(muti_adv_data, txpower, manucode, pcode, prodcode); usr_var.usr_adv_flag = 1; } else { usr_get_pair_info(); if (usr_auth_data.paired_flag == 0) { /* SOC:未配网也发绑定广播(模组此处为不广播) */ muti_adv_data_len = bleproto_advdata_encode4bind(muti_adv_data, txpower, manucode, pcode, prodcode); usr_var.usr_adv_flag = 0; } else { memcpy(gmac, usr_auth_data.gwmac, 6); muti_adv_data_len = bleproto_advdata_encode4reconn(muti_adv_data, txpower, gmac, manucode, pcode, prodcode); usr_var.usr_adv_flag = 1; } } usr_ble_adv_updata(); if (le_timer_handle == 0) { le_timer_handle = sys_timer_add(NULL, usr_ble_adv_updata, 500); } } /** * @brief 获取是否已配网 * @return 1=已配网,0=未配网 */ u8 usr_get_pair_flag(void) { return usr_auth_data.paired_flag; } /** * @brief 周期处理广播刷新(由 500ms 定时器调用) * @note 仅当 usr_adv_flag==1 时:停广播 → 写入 muti_adv_data → 再开广播 */ void usr_ble_adv_updata(void) { static u16 usr_goto_slow_adv = 0; if (usr_var.usr_adv_flag) { ble_trans_module_enable(0); usr_var.usr_adv_flag = 0; muti_make_set_adv_data(muti_adv_data, muti_adv_data_len); printf("###muti_adv_data = "); printf_buf(muti_adv_data, muti_adv_data_len); ble_trans_module_enable(1); } if (!usr_ble_is_connected()) { /* 未连接:回连快广播(80)持续约 60s(500ms×120)后切慢广播 */ if (usr_get_adv_interval() == 80) { if ((usr_var.usr_goto_pair == 0) && usr_auth_data.paired_flag) { if (usr_var.usr_ota_succ_flag == 0) { usr_goto_slow_adv++; printf("usr_goto_slow_adv = %d\n", usr_goto_slow_adv); } if (usr_goto_slow_adv >= 120) { usr_goto_slow_adv = 0; usr_set_adv_interval(80 * 10); usr_var.usr_adv_flag = 1; } } } else { usr_goto_slow_adv = 0; } } else { usr_goto_slow_adv = 0; } if (usr_get_ota_status() == 0) { if (!usr_ble_is_connected()) { if (usr_var.usr_ota_succ_flag == 0) { usr_ota_exit(); } } } /* 协议层周期处理(上报/应答) */ usr_timer_loop(); } void usr_soft_off(void) { sys_enter_soft_poweroff(NULL); } void usr_ble_adv_updata_OTA(void) { ble_trans_module_enable(0); usr_var.usr_adv_flag = 0; extern u8 usr_mac_addr[6]; extern int le_controller_set_mac(void *addr); usr_mac_addr[0] = usr_mac_addr[0] + 1; le_controller_set_mac(usr_mac_addr); muti_make_set_adv_data_updata(); printf("###muti_adv_data = "); printf_buf(muti_adv_data, muti_adv_data_len); ble_trans_module_enable(1); } void usr_ota_process(void) { static u8 cnt = 0; if (cnt == 0) { ble_multi_trans_disconnect(); } if (!usr_ble_is_connected()) { cnt++; if (cnt == 2) { usr_ble_adv_updata_OTA(); } if (cnt >= 60) { cnt = 0; cpu_reset(); } } else { cnt = 1; } } /** * @brief 旧版 RCSP/JSON OTA 入口;产品 JB 0x30/0x32 路径不要调用 */ void usr_app_ota_init(void) { usr_var.usr_goto_updata = 1; if (usr_var.ota_timer == 0) { usr_var.ota_timer = sys_timer_add(NULL, usr_ota_process, 1000); } }