Files

386 lines
13 KiB
C
Raw Permalink 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.
/******************************************************************************
* @file usr_le_recieve.c
* @brief BLE 收包入口:bleproto 解析后分发配网 / 对时 / JB 协议 / 组应答
* @author cyWu <1917507415@qq.com>
* @date 2026.09.09
* @version V1.2.0
* @history
* - V1.0.0, 2026.08.03, cyWu, 首次发布
* - V1.1.0, 2026.08.19, cyWu, 对齐模组结构;废弃 JSON OTA;修 AUTHDELETE serviceid
* - V1.2.0, 2026.09.09, cyWu, JB 上报超 255 走 wrap_raw 自动分包;加大 txbuf
******************************************************************************/
#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 拼包缓冲。发:V2 + bleproto 多帧(单帧总长 247,与 ATT 对齐) */
#define USR_LE_RX_BUF_LEN 1024
#define USR_LE_V2_WRAP_OVERHEAD 32u /* V2 头开销 */
#define USR_LE_V2_MAX_LEN (512u + USR_LE_V2_WRAP_OVERHEAD)
#define USR_LE_APPDATA_PACKETLEN 247u /* 对齐 ATT_LOCAL_PAYLOAD_SIZE8B头+239B数据 */
#define USR_LE_APPDATA_FRAME_PAYLOAD (USR_LE_APPDATA_PACKETLEN - 8u)
#define USR_LE_TX_BUF_LEN (USR_LE_V2_MAX_LEN + \
8u * ((USR_LE_V2_MAX_LEN + USR_LE_APPDATA_FRAME_PAYLOAD - 1u) / \
USR_LE_APPDATA_FRAME_PAYLOAD))
#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[USR_LE_TX_BUF_LEN];
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), USR_LE_APPDATA_PACKETLEN, 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_V255AA 字节流转交 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), USR_LE_APPDATA_PACKETLEN,
&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);
}