diff --git a/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_api.h b/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_api.h index b08156c..a8cffb3 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_api.h +++ b/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_api.h @@ -2,13 +2,14 @@ * @file usr_le_api.h * @brief usr_le_code 对外 API(广播 / 收发 / 配网 / MCU 帧转发) * @author cyWu <1917507415@qq.com> - * @date 2026.08.15 - * @version V1.3.0 + * @date 2026.09.11 + * @version V1.4.0 * @history * - V1.0.0, 2026.08.03, cyWu, 首次发布 * - V1.1.0, 2026.08.06, cyWu, 增加 MCU 帧 BLE 发送接口,解耦模组桥 * - V1.2.0, 2026.08.13, cyWu, P1:复位前断连停广播;0x41 走 cmd100 上报 * - V1.3.0, 2026.08.15, cyWu, 连接查询/写配对/BLE 发送收口到本头文件 + * - V1.4.0, 2026.09.11, cyWu, 增加强制 RUNCMD_V2 应答发送,供 APP 0x40 回 0x41 ******************************************************************************/ #ifndef __USR_LE_API_H__ @@ -46,6 +47,14 @@ void usr_le_data_recieve(uint8_t *data, uint16_t len); */ uint8_t usr_le_send_mcu_frame(uint8_t *data, uint16_t len); +/** + * @brief 将 55AA 帧作为 RUNCMD_V2 应答发出(不走 REPORTCMD_V2) + * @param data 完整 55AA 帧 + * @param len 帧长度 + * @note APP 主动 0x40 问版本时,0x41 必须对上这次 RUNCMD,不能走网关上报 + */ +uint8_t usr_le_send_mcu_frame_rsp(uint8_t *data, uint16_t len); + /** * @brief 进入配对/配网模式 * @note 清配对信息,置 usr_goto_pair=1,发绑定广播(非回连) diff --git a/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_recieve.c b/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_recieve.c index c57f6b2..852ec6a 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_recieve.c +++ b/JBao_JL7016_MOD_FW/apps/usr_le_code/usr_le_recieve.c @@ -2,11 +2,12 @@ * @file usr_le_recieve.c * @brief BLE 收包入口:bleproto 解析后转交 mcu_bridge / 组应答 * @author cyWu <1917507415@qq.com> - * @date 2026.08.15 - * @version V1.1.0 + * @date 2026.09.11 + * @version V1.2.0 * @history * - V1.0.0, 2026.08.03, cyWu, 首次发布 * - V1.1.0, 2026.08.15, cyWu, 只经 mcu_bridge.h 访问桥;JSON OTA 废弃 + * - V1.2.0, 2026.09.11, cyWu, 增加 usr_le_send_mcu_frame_rsp,APP 0x40 回 0x41 ******************************************************************************/ #include "system/includes.h" @@ -292,18 +293,17 @@ static void usr_run_cmd_code_v2(ble_proto_packet_t *runcmd_par, u8 usr_msg_id) /** * @brief 将 MCU 协议帧封装为 bleproto V2 后通过 BLE 发送 - * @param data 55AA 完整帧 - * @param len 帧长度 - * @note 主动上报(0x07/0x34/0x38/0x41) → REPORTCMD_V2;其余 → RUNCMD_V2 应答 + * @param data 55AA 完整帧 + * @param len 帧长度 + * @param as_report 1=REPORTCMD_V2 主动上报,0=RUNCMD_V2 应答 * @return 1=已交给协议栈,0=参数非法/超长/CCC 未就绪/组包失败 */ -uint8_t usr_le_send_mcu_frame(u8 *data, u16 len) +static uint8_t usr_le_send_mcu_frame_ex(u8 *data, u16 len, u8 as_report) { ble_proto_packet_t pkt; bleproto_appdata_header_t hdr; u8 v2_buf[MCU_FRAME_MAX_LEN + USR_LE_V2_WRAP_OVERHEAD]; u8 mcu_cmd; - u8 is_active_send; int plen; int elen; @@ -324,7 +324,6 @@ uint8_t usr_le_send_mcu_frame(u8 *data, u16 len) } mcu_cmd = data[MCU_FRAME_OFF_CMD]; - is_active_send = usr_le_is_gateway_report_cmd(mcu_cmd); memset(&pkt, 0, sizeof(pkt)); memset(&hdr, 0, sizeof(hdr)); @@ -332,7 +331,7 @@ uint8_t usr_le_send_mcu_frame(u8 *data, u16 len) hdr.datafmt = BLEPROTO_APPDATA_DATAFMT_JSON; hdr.encrypt = 0; - if (is_active_send) + if (as_report) { hdr.msgtype = BLEPROTO_APPDATA_MSGTYPE_REQ; hdr.msgid = 0; @@ -363,7 +362,7 @@ uint8_t usr_le_send_mcu_frame(u8 *data, u16 len) elen = bleproto_appdata_wrap_raw(txbuf, sizeof(txbuf), &hdr, v2_buf, (uint16_t)plen); printf("usr_le_send_mcu_frame cmd=0x%02X active=%d encode_len=%d msgid=%d\n", - mcu_cmd, is_active_send, elen, hdr.msgid); + mcu_cmd, as_report, elen, hdr.msgid); if (elen <= 0) { return 0; @@ -373,3 +372,31 @@ uint8_t usr_le_send_mcu_frame(u8 *data, u16 len) printf_buf(txbuf, elen); return 1; } + +/** + * @brief 按命令字选择上报或应答通道 + * @param data 55AA 完整帧 + * @param len 帧长度 + * @return 1=已交给协议栈,0=失败 + */ +uint8_t usr_le_send_mcu_frame(u8 *data, u16 len) +{ + u8 as_report = 0; + + if (data && len >= MCU_FRAME_OVERHEAD) + { + as_report = usr_le_is_gateway_report_cmd(data[MCU_FRAME_OFF_CMD]); + } + return usr_le_send_mcu_frame_ex(data, len, as_report); +} + +/** + * @brief 强制走 RUNCMD_V2 应答(APP 0x40 回 0x41) + * @param data 55AA 完整帧 + * @param len 帧长度 + * @return 1=已交给协议栈,0=失败 + */ +uint8_t usr_le_send_mcu_frame_rsp(u8 *data, u16 len) +{ + return usr_le_send_mcu_frame_ex(data, len, 0); +} diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c index 3f66a13..1f7f4a7 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c +++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.c @@ -2,12 +2,13 @@ * @file mcu_business.c * @brief 业务门面实现 * @author cyWu <1917507415@qq.com> - * @date 2026.08.13 - * @version V1.1.0 + * @date 2026.09.11 + * @version V1.3.0 * @history * - V1.0.0, 2026.08.12, cyWu, 取代原 mcu_link,编排三个业务子模块 * - V1.1.0, 2026.08.13, cyWu, 编排 P1 管理/对时/版本 * - V1.2.0, 2026.08.15, cyWu, 编排 P2 OTA;版本周期在 OTA 时让路 + * - V1.3.0, 2026.09.11, cyWu, APP 0x40 查询版本转 mcu_version ******************************************************************************/ #include "system/includes.h" @@ -186,6 +187,15 @@ void mcu_business_on_mcu_info_ack(const uint8_t *frame, uint16_t len) mcu_version_on_mcu_info_ack(frame, len); } +/** + * @brief APP 0x40 + * @param sn 序列号 + */ +void mcu_business_on_app_get_mcu_info(uint8_t sn) +{ + mcu_version_on_app_query(sn); +} + /** * @brief 网关 ACK * @param success 成功 diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h index e6508e6..0434cb0 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h +++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_business.h @@ -2,13 +2,14 @@ * @file mcu_business.h * @brief 业务门面:协调身份 / 配网 / 连接 / 管理 / 对时 / 版本 * @author cyWu <1917507415@qq.com> - * @date 2026.08.13 - * @version V1.2.0 + * @date 2026.09.11 + * @version V1.3.0 * @history * - V1.0.0, 2026.08.12, cyWu, 取代原 mcu_link,供协议层(mcu_protocol) * 单点调用;协议层不直接依赖 identity/pairing/link_status 三个子模块 * - V1.1.0, 2026.08.13, cyWu, 接入 P1 管理/对时/版本子模块 * - V1.2.0, 2026.08.15, cyWu, 接入 P2 OTA;协议层只经本门面访问 OTA + * - V1.3.0, 2026.09.11, cyWu, APP 主动 0x40 查询版本走门面,不转 UART ******************************************************************************/ #ifndef __MCU_BUSINESS_H__ @@ -114,6 +115,12 @@ void mcu_business_on_network_time(uint64_t unix_s, int32_t gmtoff_s); */ void mcu_business_on_mcu_info_ack(const uint8_t *frame, uint16_t len); +/** + * @brief APP 主动 0x40 查询版本(不转 UART) + * @param sn APP 请求序列号 + */ +void mcu_business_on_app_get_mcu_info(uint8_t sn); + /** * @brief 网关 REPORTCMD_V2 应答 * @param success 1=成功 diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_ota.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_ota.c index 4afb90a..4cb94a2 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_ota.c +++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_ota.c @@ -337,12 +337,12 @@ static void mcu_ota_handle_notify(const uint8_t *frame, uint16_t len) return; } - if (mcu_ota_ble_ver_low(s_ota.ver)) - { - mcu_ota_reply_app_result(MCU_CMD_OTA_NOTIFY_ACK, sn, - MCU_RESULT_OTA_VER_LOW); - return; - } + // if (mcu_ota_ble_ver_low(s_ota.ver)) + // { + // mcu_ota_reply_app_result(MCU_CMD_OTA_NOTIFY_ACK, sn, + // MCU_RESULT_OTA_VER_LOW); + // return; + // } ret = usr_ota_start(s_ota.file_size, s_ota.file_crc32); if (ret == USR_OTA_ERR_SPACE) diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.c index 8b362fb..51a9821 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.c +++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.c @@ -2,10 +2,11 @@ * @file mcu_version.c * @brief 版本业务实现:拉 MCU 信息并按 SOC 0x41 上报网关 * @author cyWu <1917507415@qq.com> - * @date 2026.08.13 - * @version V1.0.0 + * @date 2026.09.11 + * @version V1.1.0 * @history * - V1.0.0, 2026.08.13, cyWu, 首次发布 + * - V1.1.0, 2026.09.11, cyWu, APP 主动 0x40:缓存组 SOC 0x41 走 RUNCMD 应答 ******************************************************************************/ #include "system/includes.h" @@ -88,6 +89,29 @@ static uint8_t mcu_version_tx_fetch(void) return 1; } +/** + * @brief 组 SOC 0x41 载荷 + * @param payload 输出 10 字节 + * @param result Result + */ +static void mcu_version_fill_soc_payload(uint8_t payload[MCU_VER_SOC_PAYLOAD_LEN], + uint8_t result) +{ + payload[0] = result; + payload[1] = MCU_BLE_FW_VER_MAJOR; + payload[2] = MCU_BLE_FW_VER_MINOR; + payload[3] = MCU_BLE_FW_VER_PATCH; + if (s_ver.cached) + { + memcpy(&payload[4], s_ver.mcu_ver, 3); + memcpy(&payload[7], s_ver.hw_ver, 3); + } + else + { + memset(&payload[4], 0, 6); + } +} + /** * @brief 组 SOC 0x41 并走 cmd 100 上报 * @return 1=已发出,0=失败 @@ -110,12 +134,7 @@ static uint8_t mcu_version_tx_report(void) return 0; } - payload[0] = MCU_RESULT_OK; - payload[1] = MCU_BLE_FW_VER_MAJOR; - payload[2] = MCU_BLE_FW_VER_MINOR; - payload[3] = MCU_BLE_FW_VER_PATCH; - memcpy(&payload[4], s_ver.mcu_ver, 3); - memcpy(&payload[7], s_ver.hw_ver, 3); + mcu_version_fill_soc_payload(payload, MCU_RESULT_OK); s_ver.report_sn++; total = mcu_frame_pack(frame, sizeof(frame), MCU_CMD_GET_MCU_INFO_ACK, @@ -286,6 +305,41 @@ void mcu_version_on_mcu_info_ack(const uint8_t *frame, uint16_t len) (void)mcu_version_tx_report(); } +/** + * @brief APP 主动 0x40:用缓存回 SOC 0x41(RUNCMD 应答,不改上报状态机) + * @param sn APP 请求序列号 + */ +void mcu_version_on_app_query(uint8_t sn) +{ + uint8_t payload[MCU_VER_SOC_PAYLOAD_LEN]; + uint8_t frame[MCU_FRAME_MAX_LEN]; + int32_t total; + uint8_t result; + + result = s_ver.cached ? MCU_RESULT_OK : MCU_RESULT_FAIL; + mcu_version_fill_soc_payload(payload, result); + + total = mcu_frame_pack(frame, sizeof(frame), MCU_CMD_GET_MCU_INFO_ACK, + sn, payload, MCU_VER_SOC_PAYLOAD_LEN); + if (total <= 0) + { + log_error("APP 0x40 pack 0x41 fail"); + return; + } + + if (usr_le_send_mcu_frame_rsp(frame, (uint16_t)total) == 0) + { + log_error("APP 0x40 send 0x41 fail"); + return; + } + + log_info("APP 0x40 -> 0x41 sn=%u result=0x%02X ble=%u.%u.%u mcu=%u.%u.%u hw=%u.%u.%u", + sn, result, + payload[1], payload[2], payload[3], + payload[4], payload[5], payload[6], + payload[7], payload[8], payload[9]); +} + /** * @brief 网关 ACK:MCU 0x07 优先消费,版本上报绝不回 MCU 0x08 * @param success 成功 diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.h b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.h index a89b462..ce63ad3 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.h +++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/business/mcu_version.h @@ -2,10 +2,11 @@ * @file mcu_version.h * @brief 版本业务:UART 0x40/0x41 拉 MCU 信息,SOC 0x41 上报网关 * @author cyWu <1917507415@qq.com> - * @date 2026.08.13 - * @version V1.0.0 + * @date 2026.09.11 + * @version V1.1.0 * @history * - V1.0.0, 2026.08.13, cyWu, 首次发布(P1:0x40/0x41 + SOC 0x41) + * - V1.1.0, 2026.09.11, cyWu, APP 主动 0x40:用缓存组 SOC 0x41 应答 ******************************************************************************/ #ifndef __MCU_VERSION_H__ @@ -36,6 +37,13 @@ void mcu_version_periodic(void); */ void mcu_version_on_mcu_info_ack(const uint8_t *frame, uint16_t len); +/** + * @brief APP 主动 0x40:用缓存组 SOC 0x41,按请求 SN 应答 + * @param sn APP 请求序列号 + * @note 有缓存 Result=0;无缓存仍填 BLE 版本,MCU/HW 填 0,Result=失败 + */ +void mcu_version_on_app_query(uint8_t sn); + /** * @brief 网关对 REPORTCMD_V2 的应答 * @param success 1=网关成功 ACK diff --git a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c index db56380..5bdb308 100644 --- a/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c +++ b/JBao_JL7016_MOD_FW/apps/usr_mcu_bridge/protocol/mcu_protocol.c @@ -2,8 +2,8 @@ * @file mcu_protocol.c * @brief MCU 接入协议引擎实现 * @author cyWu <1917507415@qq.com> - * @date 2026.08.13 - * @version V1.2.0 + * @date 2026.09.11 + * @version V1.3.0 * @history * - V1.0.0, 2026.08.12, cyWu, 从 mcu_bridge.c 拆出(历史版本见原文件): * 事件队列 + 独立任务驱动、LP target、心跳/透传重传均原样保留 @@ -11,6 +11,7 @@ * MCU 自身已有超时重发机制,模组侧只记 SN 转发+等 ACK 回 0x08, * 去掉 report_pending 整包缓存与 mcu_protocol_check_report_pending() * - V1.2.0, 2026.08.13, cyWu, P1 管理命令分发、pending 发送、网络时间入队 + * - V1.3.0, 2026.09.11, cyWu, APP 0x40 本地回 0x41,禁止透传到 UART ******************************************************************************/ #include "system/includes.h" @@ -705,6 +706,11 @@ static void mcu_protocol_handle_app_frame(const uint8_t *data, uint16_t len) log_info("ignore APP OTA dir cmd=0x%02X", cmd); return; + case MCU_CMD_GET_MCU_INFO: + /* APP 问版本:模组用缓存回 SOC 0x41,不要把 0x40 转给 MCU */ + mcu_business_on_app_get_mcu_info(sn); + return; + case MCU_CMD_CONTROL: if (mcu_business_ota_is_active()) { mcu_protocol_reply_app_result(MCU_CMD_CONTROL_ACK, sn, MCU_RESULT_BUSY);