378 lines
12 KiB
C
378 lines
12 KiB
C
/******************************************************************************
|
||
* @file usr_le_recieve.c
|
||
* @brief BLE 收包入口:bleproto 解析后分发配网 / 对时 / JB 协议 / 组应答
|
||
* @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, 对齐模组结构;废弃 JSON OTA;修 AUTHDELETE serviceid
|
||
******************************************************************************/
|
||
|
||
#include "system/includes.h"
|
||
#include "app_config.h"
|
||
#include "app_main.h"
|
||
#include "vm.h"
|
||
#include "bleproto.h"
|
||
#include "bleproto_api.h"
|
||
#include "ble_proto.h"
|
||
#include "usr_rtc.h"
|
||
#include "usr_le_api.h"
|
||
#include "jb_protocol.h"
|
||
|
||
#define LOG_TAG_CONST APP
|
||
#define LOG_TAG "[USR_LE]"
|
||
#define LOG_ERROR_ENABLE
|
||
#define LOG_DEBUG_ENABLE
|
||
#define LOG_INFO_ENABLE
|
||
#include "debug.h"
|
||
|
||
/* 拼 GATT 分包:业务包 ≈ bleproto头 + V2 开销 + JB 帧(<=128),1024 足够 */
|
||
#define USR_LE_RX_BUF_LEN 1024
|
||
#define USR_LE_V2_WRAP_OVERHEAD 32u /* V2 头开销,JB 帧最大 128 → 约 160 */
|
||
#define USR_LE_V2_CMD_REPORT 100u /* REPORTCMD_V2 内层 cmd */
|
||
#define USR_LE_V2_CMD_RUN 110u /* RUNCMD_V2 内层 cmd */
|
||
#define USR_LE_JB_CMD_OFF 4u /* 55 AA | LEN_H LEN_L | CMD */
|
||
|
||
static int encode_len = 0;
|
||
static u8 txbuf[384] = {0};
|
||
static u8 rxbuf[USR_LE_RX_BUF_LEN] = {0};
|
||
static u8 s_last_runcmd_msgid = 0; /* RUNCMD_V2 应答须回填最近 msgid */
|
||
|
||
bleproto_authsetup_req_t usr_auth_data;
|
||
|
||
extern void usr_ble_send_data(u8 *data, u16 len);
|
||
extern u8 usr_ble_is_notify_ready(void);
|
||
extern void usr_write_pair_info(void);
|
||
extern void usr_clear_pair_info(void);
|
||
extern void usr_jb_le_recieve_data(u8 *data, u16 len);
|
||
extern int8_t jbReportAckCheck(u16 cmd, u8 gateway_int_cnt, int32_t gateway_int0);
|
||
|
||
static void usr_data_ana(bleproto_appdata_desc_t *desc);
|
||
static void usr_run_cmd_code_v2(ble_proto_packet_t *runcmd_par, u8 usr_msg_id);
|
||
|
||
/**
|
||
* @brief 填 bleproto 应答头
|
||
* @param out 输出 desc
|
||
* @param in 请求 desc(取 msgid)
|
||
* @param serviceid 服务号
|
||
*/
|
||
static void usr_le_fill_rsp_header(bleproto_appdata_desc_t *out,
|
||
const bleproto_appdata_desc_t *in,
|
||
uint8_t serviceid)
|
||
{
|
||
out->header.version = 0;
|
||
out->header.datafmt = BLEPROTO_APPDATA_DATAFMT_JSON;
|
||
out->header.msgtype = BLEPROTO_APPDATA_MSGTYPE_RSP;
|
||
out->header.msgid = in->header.msgid;
|
||
out->header.encrypt = 0;
|
||
out->header.serviceid = serviceid;
|
||
}
|
||
|
||
/**
|
||
* @brief 编码并经 BLE 发出
|
||
* @param desc 已填好的应答
|
||
*/
|
||
static void usr_le_encode_and_send(bleproto_appdata_desc_t *desc)
|
||
{
|
||
encode_len = bleproto_appdata_encode(txbuf, sizeof(txbuf), sizeof(txbuf), desc);
|
||
if (encode_len > 0)
|
||
{
|
||
printf("encode_len = %d\n", encode_len);
|
||
usr_ble_send_data(txbuf, encode_len);
|
||
}
|
||
else
|
||
{
|
||
printf("encode_len fail %d\n", encode_len);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 是否走网关主动上报(REPORTCMD_V2)
|
||
* @param jb_cmd 55AA 命令字
|
||
* @return 1=主动上报,0=RUNCMD 应答
|
||
*/
|
||
static uint8_t usr_le_is_gateway_report_cmd(uint8_t jb_cmd)
|
||
{
|
||
return (jb_cmd == CMD_REPORT ||
|
||
jb_cmd == CMD_OTA_COMPLETE ||
|
||
jb_cmd == CMD_OTA_STOP_MCU)
|
||
? 1u
|
||
: 0u;
|
||
}
|
||
|
||
/**
|
||
* @brief BLE 收包入口
|
||
* @param data 收包数据
|
||
* @param len 数据长度
|
||
*/
|
||
void usr_le_data_recieve(u8 *data, u16 len)
|
||
{
|
||
static u16 usr_len = 0;
|
||
/* desc 含 ycmd 等 union,放 static,避免每次收包在栈上开大块 */
|
||
static bleproto_appdata_desc_t s_rx_desc;
|
||
int rc_result = 0;
|
||
|
||
if (!data || len == 0)
|
||
{
|
||
return;
|
||
}
|
||
if ((u32)usr_len + len > sizeof(rxbuf))
|
||
{
|
||
printf("### rxbuf overflow, usr_len=%u len=%u, reset\n", usr_len, len);
|
||
usr_len = 0;
|
||
return;
|
||
}
|
||
|
||
memcpy(&rxbuf[usr_len], data, len);
|
||
usr_len += len;
|
||
rc_result = bleproto_appdata_decode(rxbuf, usr_len, &s_rx_desc);
|
||
if (rc_result < 0)
|
||
{
|
||
printf("### invild pack\n");
|
||
usr_len = 0;
|
||
}
|
||
else if (rc_result == 0)
|
||
{
|
||
printf("### keep recieving\n");
|
||
}
|
||
else
|
||
{
|
||
printf("### pack recieved ok\n");
|
||
usr_len = 0;
|
||
usr_data_ana(&s_rx_desc);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 解析 bleproto 服务并分发
|
||
* @param desc 已 decode 的包
|
||
*/
|
||
static void usr_data_ana(bleproto_appdata_desc_t *desc)
|
||
{
|
||
static bleproto_appdata_desc_t s_encode_desc;
|
||
|
||
memset(&s_encode_desc, 0, sizeof(s_encode_desc));
|
||
printf("desc serviceid=%d msgtype=%d\n",
|
||
desc->header.serviceid, desc->header.msgtype);
|
||
|
||
if (desc->header.msgtype == BLEPROTO_APPDATA_MSGTYPE_REQ)
|
||
{
|
||
switch (desc->header.serviceid)
|
||
{
|
||
case E_BLEPROTO_SERVICE_ID_DEVICEINFO: {
|
||
bleproto_deviceinfo_req_t *req = &desc->datast.deviceinfo_req;
|
||
bleproto_deviceinfo_rsp_t *rsp = &s_encode_desc.datast.deviceinfo_rsp;
|
||
|
||
/* 网关从子设备连上开始计时,每 12 小时经 DEVICEINFO 同步一次 */
|
||
usr_rtc_set_from_unix(req->t, (int32_t)req->gmtoff);
|
||
|
||
usr_le_fill_rsp_header(&s_encode_desc, desc, E_BLEPROTO_SERVICE_ID_DEVICEINFO);
|
||
rsp->hbcycle = 1000;
|
||
strcpy(rsp->swv, "V1.0.0.00");
|
||
strcpy(rsp->hwv, "V1.0.0.00");
|
||
rsp->longcon = 1;
|
||
rsp->prototype = 4;
|
||
usr_le_encode_and_send(&s_encode_desc);
|
||
break;
|
||
}
|
||
case E_BLEPROTO_SERVICE_ID_AUTHSETUP: {
|
||
bleproto_authsetup_rsp_t *au_rsp = &s_encode_desc.datast.authsetup_rsp;
|
||
|
||
printf("E_BLEPROTO_SERVICE_ID_AUTHSETUP\n");
|
||
usr_le_fill_rsp_header(&s_encode_desc, desc, E_BLEPROTO_SERVICE_ID_AUTHSETUP);
|
||
au_rsp->errcode = 0;
|
||
memcpy(&usr_auth_data, &desc->datast.authsetup_req, sizeof(usr_auth_data));
|
||
if (usr_auth_data.paired_flag == 0)
|
||
{
|
||
usr_write_pair_info();
|
||
usr_var.usr_goto_pair = 0; // 新增:退出强制配网
|
||
printf("usr_auth_data %s %s ", usr_auth_data.authcode, usr_auth_data.devid);
|
||
printf_buf(usr_auth_data.gwmac, 6);
|
||
}
|
||
usr_le_encode_and_send(&s_encode_desc);
|
||
break;
|
||
}
|
||
case E_BLEPROTO_SERVICE_ID_AUTHDELETE: {
|
||
bleproto_authdelete_rsp_t *aude_rsp = &s_encode_desc.datast.authdelete_rsp;
|
||
|
||
printf("E_BLEPROTO_SERVICE_ID_AUTHDELETE\n");
|
||
usr_le_fill_rsp_header(&s_encode_desc, desc, E_BLEPROTO_SERVICE_ID_AUTHDELETE);
|
||
memcpy(aude_rsp->gwmac, usr_auth_data.gwmac, 6);
|
||
if (!memcmp(usr_auth_data.authcode, desc->datast.authdelete_req.authcode, 32))
|
||
{
|
||
aude_rsp->errcode = 0;
|
||
usr_clear_pair_info();
|
||
}
|
||
else
|
||
{
|
||
aude_rsp->errcode = 501;
|
||
}
|
||
usr_le_encode_and_send(&s_encode_desc);
|
||
break;
|
||
}
|
||
case E_BLEPROTO_SERVICE_ID_RUNCMD:
|
||
printf("E_BLEPROTO_SERVICE_ID_RUNCMD\n");
|
||
break;
|
||
case E_BLEPROTO_SERVICE_ID_RUNCMD_V2:
|
||
printf("E_BLEPROTO_SERVICE_ID_RUNCMD_V2\n");
|
||
usr_run_cmd_code_v2(&desc->datast.runcmd_v2_req, desc->header.msgid);
|
||
break;
|
||
case E_BLEPROTO_SERVICE_ID_OTANOTIFY:
|
||
case E_BLEPROTO_SERVICE_ID_OTADATA:
|
||
case E_BLEPROTO_SERVICE_ID_OTADATA_V2:
|
||
/* JSON OTA 已废弃,SOC 走 JB 0x30/0x32 */
|
||
printf("JSON OTA deprecated, use JB 0x30/0x32\n");
|
||
break;
|
||
default:
|
||
printf("err !!! default event desc->header.serviceid =%d\n",
|
||
desc->header.serviceid);
|
||
break;
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (desc->header.msgtype == BLEPROTO_APPDATA_MSGTYPE_RSP)
|
||
{
|
||
switch (desc->header.serviceid)
|
||
{
|
||
case E_BLEPROTO_SERVICE_ID_REPORTCMD:
|
||
printf("E_BLEPROTO_SERVICE_ID_REPORTCMD errcode=%d\n",
|
||
desc->datast.reportcmd_rsp.errcode);
|
||
break;
|
||
case E_BLEPROTO_SERVICE_ID_REPORTCMD_V2: {
|
||
ble_proto_packet_t *rpt_ack = &desc->datast.reportcmd_v2_rsp;
|
||
|
||
printf("REPORTCMD_V2 cmd=%u cnt=%u int0=%ld\n",
|
||
(unsigned)rpt_ack->cmd,
|
||
(unsigned)rpt_ack->gateway_int_cnt,
|
||
(long)((rpt_ack->gateway_int_cnt > 0) ? rpt_ack->gateway_int[0] : 0));
|
||
jbReportAckCheck(rpt_ack->cmd,
|
||
rpt_ack->gateway_int_cnt,
|
||
(rpt_ack->gateway_int_cnt > 0) ? rpt_ack->gateway_int[0] : -1);
|
||
break;
|
||
}
|
||
case E_BLEPROTO_SERVICE_ID_OTADATA:
|
||
printf("JSON OTA deprecated, use JB 0x32\n");
|
||
break;
|
||
default:
|
||
printf("unhandled RSP serviceid=%d\n", desc->header.serviceid);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief APP RUNCMD_V2:55AA 字节流转交 JB 协议层
|
||
* @param runcmd_par 内层包
|
||
* @param usr_msg_id bleproto msgid
|
||
*/
|
||
static void usr_run_cmd_code_v2(ble_proto_packet_t *runcmd_par, u8 usr_msg_id)
|
||
{
|
||
u8 jb_frame[MAX_PACKAGE_LEN];
|
||
u16 copy_len;
|
||
|
||
if (!runcmd_par || !runcmd_par->bytes_data || runcmd_par->device_bytes_len == 0)
|
||
{
|
||
printf("usr_run_cmd_code_v2 invalid bytes, len=%u\n",
|
||
runcmd_par ? runcmd_par->device_bytes_len : 0);
|
||
return;
|
||
}
|
||
|
||
printf("runcmd_par id = %d, bytes_len = %u\n",
|
||
runcmd_par->cmd, runcmd_par->device_bytes_len);
|
||
|
||
copy_len = runcmd_par->device_bytes_len;
|
||
if (copy_len > sizeof(jb_frame))
|
||
{
|
||
printf("usr_run_cmd_code_v2 bytes too long %u\n", copy_len);
|
||
return;
|
||
}
|
||
memcpy(jb_frame, runcmd_par->bytes_data, copy_len);
|
||
|
||
s_last_runcmd_msgid = usr_msg_id;
|
||
usr_jb_le_recieve_data(jb_frame, copy_len);
|
||
}
|
||
|
||
/**
|
||
* @brief 将 JB 协议帧封装为 bleproto V2 后通过 BLE 发送
|
||
* @param data JB 协议原始帧(55 AA | LEN | CMD | ...)
|
||
* @param len 帧长度
|
||
* @note 主动上报(0x07/0x34/0x38) → REPORTCMD_V2;其余 → RUNCMD_V2 应答
|
||
* 对外符号名保持 ble_send_data,供 jb_protocol 调用
|
||
*/
|
||
void ble_send_data(u8 *data, u16 len)
|
||
{
|
||
ble_proto_packet_t pkt;
|
||
bleproto_appdata_header_t hdr;
|
||
u8 v2_buf[MAX_PACKAGE_LEN + USR_LE_V2_WRAP_OVERHEAD];
|
||
u8 jb_cmd;
|
||
u8 is_active_send;
|
||
int plen;
|
||
int elen;
|
||
|
||
if (!data || len < 5)
|
||
{
|
||
printf("ble_send_data invalid param, len=%d\n", len);
|
||
return;
|
||
}
|
||
// if (len > MAX_PACKAGE_LEN)
|
||
// {
|
||
// printf("ble_send_data frame too long %u\n", len);
|
||
// return;
|
||
// }
|
||
if (!usr_ble_is_notify_ready())
|
||
{
|
||
printf("ble_send_data wait CCC cmd=0x%02X\n", data[USR_LE_JB_CMD_OFF]);
|
||
return;
|
||
}
|
||
|
||
jb_cmd = data[USR_LE_JB_CMD_OFF];
|
||
is_active_send = usr_le_is_gateway_report_cmd(jb_cmd);
|
||
|
||
memset(&pkt, 0, sizeof(pkt));
|
||
memset(&hdr, 0, sizeof(hdr));
|
||
hdr.version = 0;
|
||
hdr.datafmt = BLEPROTO_APPDATA_DATAFMT_JSON;
|
||
hdr.encrypt = 0;
|
||
|
||
if (is_active_send)
|
||
{
|
||
hdr.msgtype = BLEPROTO_APPDATA_MSGTYPE_REQ;
|
||
hdr.msgid = 0;
|
||
hdr.serviceid = E_BLEPROTO_SERVICE_ID_REPORTCMD_V2;
|
||
pkt.cmd = USR_LE_V2_CMD_REPORT;
|
||
pkt.gateway_int_cnt = 0;
|
||
}
|
||
else
|
||
{
|
||
hdr.msgtype = BLEPROTO_APPDATA_MSGTYPE_RSP;
|
||
hdr.msgid = s_last_runcmd_msgid;
|
||
hdr.serviceid = E_BLEPROTO_SERVICE_ID_RUNCMD_V2;
|
||
pkt.cmd = USR_LE_V2_CMD_RUN;
|
||
pkt.gateway_int_cnt = 2;
|
||
pkt.gateway_int[0] = 0;
|
||
pkt.gateway_int[1] = 0;
|
||
}
|
||
|
||
pkt.device_bytes_len = len;
|
||
pkt.bytes_data = data;
|
||
|
||
plen = ble_proto_pack(&pkt, v2_buf, sizeof(v2_buf));
|
||
if (plen <= 0)
|
||
{
|
||
printf("ble_send_data pack fail %d\n", plen);
|
||
return;
|
||
}
|
||
|
||
elen = bleproto_appdata_wrap_raw(txbuf, sizeof(txbuf), &hdr, v2_buf, (uint16_t)plen);
|
||
printf("ble_send_data jb_cmd=0x%02X active=%d encode_len=%d msgid=%d\n",
|
||
jb_cmd, is_active_send, elen, hdr.msgid);
|
||
if (elen <= 0)
|
||
{
|
||
return;
|
||
}
|
||
usr_ble_send_data(txbuf, elen);
|
||
printf_buf(txbuf, elen);
|
||
}
|