Files
wuchuyuan 2260768167 1、新增Dengle定时参数下发功能,支持最多10条配置,断电保存到Flash,COM打开时暂停发送、关闭后恢复
2、新增USB查询产品码(0x66)和查询Dengle配置(0x74)命令
3、修复bleproto组包栈溢出导致设置Dengle后复位的问题,并完善CDC的DTR状态判断
2026-07-31 14:54:26 +08:00

488 lines
20 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.
/****************************************************************************/
/* bleproto.c
*
* Copyright (C) 2024 四川迈科创智科技有限公司
*
****************************************************************************/
/****************************************************************************/
/* Included Files */
/****************************************************************************/
#include "bleproto.h"
#include "ble_proto.h"
/****************************************************************************/
/* Trace Definitions */
/****************************************************************************/
/****************************************************************************/
/* Pre-processor Definitions */
/****************************************************************************/
/****************************************************************************/
/* Private Types */
/****************************************************************************/
/****************************************************************************/
/* Private Function Prototypes */
/****************************************************************************/
/****************************************************************************/
/* Private Data */
/****************************************************************************/
/****************************************************************************/
/* Public Data */
/****************************************************************************/
/****************************************************************************/
/* Private Functions */
/****************************************************************************/
/****************************************************************************/
/* Public Functions */
/****************************************************************************/
const char *libbleproto_version(void)
{
return BLEPROTO_API_VERSION;
}
uint8_t bleproto_advdata_encode4bind(
uint8_t data[31],
int8_t txpower,
uint8_t manucode[BLEPROTO_ADV_TLV_LENGTH_MANUCODE],
uint8_t pcode[BLE_PROTO_ADV_LENGTH_PCODE],
uint8_t prodcode[BLEPROTO_ADV_TLV_LENGTH_PRODCODE])
{
bleproto_adv_t adv = { 0 };
/* adv1 */
{
adv.adv1.length = 0x02;
adv.adv1.ad_type = BLEPROTO_ADV_TYPE_FLAGS;
adv.adv1.ad_data = 0x06;
}
/* adv2 */
// clang-format off
{
adv.adv2.length = 0x1B;
adv.adv2.ad_type = BLEPROTO_ADV_TYPE_SVC_DATA_UUID16;
adv.adv2.ad_data.service_data.uuid = BLEPROTO_ADV_SERVICE_UUID_TOBIND;
/* spec_data */
bleproto_adv_specdata_t *spec_data =
&adv.adv2.ad_data.service_data.spec_data;
spec_data->version = BLEPORTO_ADV_SERVICE_SPEC_DATA_VER;
spec_data->business = BELPROTO_ADV_SERVICE_SPEC_DATA_BUSINESS_NEARFIND;
spec_data->rfu[0] = 0;
spec_data->rfu[1] = 0;
spec_data->txpower = txpower;
spec_data->manucode.type = BLEPROTO_ADV_TLV_TYPE_MANUCODE;
spec_data->manucode.length = BLEPROTO_ADV_TLV_LENGTH_MANUCODE;
memcpy(spec_data->manucode.value, manucode, BLEPROTO_ADV_TLV_LENGTH_MANUCODE);
spec_data->prodcode.type = BLEPROTO_ADV_TLV_TYPE_PRODCODE;
spec_data->prodcode.length = BLEPROTO_ADV_TLV_LENGTH_PRODCODE;
memcpy(spec_data->prodcode.value, prodcode, BLEPROTO_ADV_TLV_LENGTH_PRODCODE);
spec_data->separator = 0xFF;
memcpy(spec_data->selfdata, pcode, BLE_PROTO_ADV_LENGTH_PCODE);
// spec_data->selfdata[0] = 0X30;
// spec_data->selfdata[1] = 0X30;
// spec_data->selfdata[2] = 0X30;
// spec_data->selfdata[3] = 0X30;
// spec_data->selfdata[4] = 0X30;
// spec_data->selfdata[5] = 0X30;
}
// clang-format on
return bleproto_advdata_serialize(&adv, data, 31);
}
void bleproto_advdata_encode4heartbeat(
uint8_t data[31],
int8_t txpower,
uint8_t gwmac[6],
uint8_t manucode[BLEPROTO_ADV_TLV_LENGTH_MANUCODE],
uint8_t pcode[BLE_PROTO_ADV_LENGTH_PCODE],
uint8_t prodcode[BLEPROTO_ADV_TLV_LENGTH_PRODCODE])
{
bleproto_adv_t adv = { 0 };
/* adv1 */
{
adv.adv1.length = 0x02;
adv.adv1.ad_type = BLEPROTO_ADV_TYPE_FLAGS;
adv.adv1.ad_data = 0x06;
}
/* adv2 */
// clang-format off
{
adv.adv2.length = 0x1B;
adv.adv2.ad_type = BLEPROTO_ADV_TYPE_MFG_DATA;
/* mfg_data */
bleproto_advdata_mfg_t *mfg_data = &adv.adv2.ad_data.mfg_data;
memcpy(mfg_data->siot, pcode, BLE_PROTO_ADV_LENGTH_PCODE);
#if 0
mfg_data->siot[0] = 'S';
mfg_data->siot[1] = 'I';
mfg_data->siot[2] = 'O';
mfg_data->siot[3] = 'T';
mfg_data->siot[4] = '-';
mfg_data->siot[5] = '1';
#endif
/* HEARTBEAT */
mfg_data->flag = BLEPROTO_ADV_FLAG_HEARTBEAT;
mfg_data->txpower = txpower;
memcpy(mfg_data->gwmac, gwmac, 6);
mfg_data->manucode.type = BLEPROTO_ADV_TLV_TYPE_MANUCODE;
mfg_data->manucode.length = BLEPROTO_ADV_TLV_LENGTH_MANUCODE;
memcpy(mfg_data->manucode.value, manucode, BLEPROTO_ADV_TLV_LENGTH_MANUCODE);
mfg_data->prodcode.type = BLEPROTO_ADV_TLV_TYPE_PRODCODE;
mfg_data->prodcode.length = BLEPROTO_ADV_TLV_LENGTH_PRODCODE;
memcpy(mfg_data->prodcode.value, prodcode, BLEPROTO_ADV_TLV_LENGTH_PRODCODE);
}
// clang-format on
(void)bleproto_advdata_serialize(&adv, data, 31);
}
uint8_t bleproto_advdata_encode4reconn(
uint8_t data[31],
int8_t txpower,
uint8_t gwmac[6],
uint8_t manucode[BLEPROTO_ADV_TLV_LENGTH_MANUCODE],
uint8_t pcode[BLE_PROTO_ADV_LENGTH_PCODE],
uint8_t prodcode[BLEPROTO_ADV_TLV_LENGTH_PRODCODE])
{
bleproto_adv_t adv = { 0 };
/* adv1 */
{
adv.adv1.length = 0x02;
adv.adv1.ad_type = BLEPROTO_ADV_TYPE_FLAGS;
adv.adv1.ad_data = 0x06;
}
/* adv2 */
// clang-format off
{
adv.adv2.length = 0x1B;
adv.adv2.ad_type = BLEPROTO_ADV_TYPE_MFG_DATA;
/* mfg_data */
bleproto_advdata_mfg_t *mfg_data = &adv.adv2.ad_data.mfg_data;
memcpy(mfg_data->siot, pcode, BLE_PROTO_ADV_LENGTH_PCODE);
#if 0
mfg_data->siot[0] = 'S';
mfg_data->siot[1] = 'I';
mfg_data->siot[2] = 'O';
mfg_data->siot[3] = 'T';
mfg_data->siot[4] = '-';
mfg_data->siot[5] = '1';
#endif
/* RECONNECT */
mfg_data->flag = BLEPROTO_ADV_FLAG_RECONNECT;
mfg_data->txpower = txpower;
memcpy(mfg_data->gwmac, gwmac, 6);
mfg_data->manucode.type = BLEPROTO_ADV_TLV_TYPE_MANUCODE;
mfg_data->manucode.length = BLEPROTO_ADV_TLV_LENGTH_MANUCODE;
memcpy(mfg_data->manucode.value, manucode, BLEPROTO_ADV_TLV_LENGTH_MANUCODE);
mfg_data->prodcode.type = BLEPROTO_ADV_TLV_TYPE_PRODCODE;
mfg_data->prodcode.length = BLEPROTO_ADV_TLV_LENGTH_PRODCODE;
memcpy(mfg_data->prodcode.value, prodcode, BLEPROTO_ADV_TLV_LENGTH_PRODCODE);
}
// clang-format on
return bleproto_advdata_serialize(&adv, data, 31);
}
int bleproto_advdata_decode(const uint8_t * data,
uint8_t len,
bleproto_adv_t *adv)
{
return bleproto_advdata_deserialize(data, len, adv);
}
int bleproto_appdata_encode(uint8_t * txbuf,
uint16_t size,
uint8_t packetlen,
bleproto_appdata_desc_t *desc)
{
int rc;
uint16_t txbuf_size = size;
/* 原栈上 appdata 约 2KB+,在 USB/定时器回调里极易栈溢出复位,改为静态 */
static bleproto_appdata_t s_enc_appdata;
bleproto_appdata_t *appdata = &s_enc_appdata;
/* header */
{
appdata->header = desc->header;
}
/* data */
if (appdata->header.msgtype == BLEPROTO_APPDATA_MSGTYPE_REQ) {
switch (appdata->header.serviceid) {
case E_BLEPROTO_SERVICE_ID_DEVICEINFO:
rc = bleproto_encjson_deviceinfo_req(&desc->datast.deviceinfo_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHSETUP:
rc = bleproto_encjson_authsetup_req(&desc->datast.authsetup_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHDELETE:
rc = bleproto_encjson_authdelete_req(&desc->datast.authdelete_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_RUNCMD:
rc = bleproto_encjson_runcmd_req(&desc->datast.runcmd_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD:
rc = bleproto_encjson_reportcmd_req(&desc->datast.reportcmd_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_DOACTION:
rc = bleproto_encjson_doaction_req(&desc->datast.doaction_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTANOTIFY:
rc = bleproto_encjson_otanotify_req(&desc->datast.otanotify_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTADATA:
rc = bleproto_encjson_otadata_req(&desc->datast.otadata_req,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD_V2:
rc = ble_proto_pack(&desc->datast.runcmd_v2_req, appdata->data, sizeof(appdata->data));
break;
default:
/* unkown serviceid */
return (-1);
}
} else if (appdata->header.msgtype == BLEPROTO_APPDATA_MSGTYPE_RSP) {
switch (appdata->header.serviceid) {
case E_BLEPROTO_SERVICE_ID_DEVICEINFO:
rc = bleproto_encjson_deviceinfo_rsp(&desc->datast.deviceinfo_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHSETUP:
rc = bleproto_encjson_authsetup_rsp(&desc->datast.authsetup_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_AUTHDELETE:
rc = bleproto_encjson_authdelete_rsp(&desc->datast.authdelete_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_RUNCMD:
rc = bleproto_encjson_runcmd_rsp(&desc->datast.runcmd_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD:
rc = bleproto_encjson_reportcmd_rsp(&desc->datast.reportcmd_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_DOACTION:
rc = bleproto_encjson_doaction_rsp(&desc->datast.doaction_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTANOTIFY:
rc = bleproto_encjson_otanotify_rsp(&desc->datast.otanotify_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_OTADATA:
rc = bleproto_encbin_otadata_rsp(&desc->datast.otadata_rsp,
appdata->data);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD_V2:
case E_BLEPROTO_SERVICE_ID_RUNCMD_V2:
rc = ble_proto_pack(&desc->datast.runcmd_v2_rsp, appdata->data, sizeof(appdata->data));
break;
default:
/* unkown serviceid */
return (-1);
}
} else {
/* unkown msgtype */
return (-1);
}
/* failed to encjson struct */
if (rc <= 0) {
return (-1);
}
/* datalen */
appdata->header.datalen = (uint16_t)rc;
/* appdata_serialize */
return bleproto_appdata_serialize(appdata, packetlen, txbuf, txbuf_size);
}
int bleproto_appdata_decode(uint8_t* rxbuf,
uint16_t len,
bleproto_appdata_desc_t *desc)
{
int rc, rlen;
bleproto_appdata_t appdata;
/* appdata_deserialize */
rlen = bleproto_appdata_deserialize(rxbuf, len, &appdata);
if (rlen <= 0) {
return (rlen);
}
/* header */
{
desc->header = appdata.header;
}
/* data */
if (appdata.header.msgtype == BLEPROTO_APPDATA_MSGTYPE_REQ) {
switch (appdata.header.serviceid) {
case E_BLEPROTO_SERVICE_ID_DEVICEINFO:
rc =
bleproto_decjson_deviceinfo_req(appdata.data,
appdata.header.datalen,
&desc->datast.deviceinfo_req);
break;
case E_BLEPROTO_SERVICE_ID_AUTHSETUP:
rc = bleproto_decjson_authsetup_req(appdata.data,
appdata.header.datalen,
&desc->datast.authsetup_req);
break;
case E_BLEPROTO_SERVICE_ID_AUTHDELETE:
rc =
bleproto_decjson_authdelete_req(appdata.data,
appdata.header.datalen,
&desc->datast.authdelete_req);
break;
case E_BLEPROTO_SERVICE_ID_RUNCMD:
rc = bleproto_decjson_runcmd_req(appdata.data,
appdata.header.datalen,
&desc->datast.runcmd_req);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD:
rc = bleproto_decjson_reportcmd_req(appdata.data,
appdata.header.datalen,
&desc->datast.reportcmd_req);
break;
case E_BLEPROTO_SERVICE_ID_DOACTION:
rc = bleproto_decjson_doaction_req(appdata.data,
appdata.header.datalen,
&desc->datast.doaction_req);
break;
case E_BLEPROTO_SERVICE_ID_OTANOTIFY:
rc = bleproto_decjson_otanotify_req(appdata.data,
appdata.header.datalen,
&desc->datast.otanotify_req);
break;
case E_BLEPROTO_SERVICE_ID_OTADATA:
rc = bleproto_decjson_otadata_req(appdata.data,
appdata.header.datalen,
&desc->datast.otadata_req);
break;
case E_BLEPROTO_SERVICE_ID_RUNCMD_V2:
/* ble_proto_unpack 零拷贝指向 appdata.dataappdata 是栈变量,
* 函数返回后指针会悬空。先拷到静态缓冲再 unpack,保证 desc 可用。 */
{
static uint8_t s_runcmd_v2_raw[BLEPROTO_APPDATA_DATA_MAX_SZ];
uint16_t raw_len = appdata.header.datalen;
if (raw_len > sizeof(s_runcmd_v2_raw)) {
return (-1);
}
memcpy(s_runcmd_v2_raw, appdata.data, raw_len);
printf("runcmd_v2_req");
rc = ble_proto_unpack(s_runcmd_v2_raw, raw_len, &desc->datast.runcmd_v2_req);
printf("runcmd_v2_req rc = %d", rc);
}
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD_V2:
break;
case E_BLEPROTO_SERVICE_ID_OTADATA_V2:
break;
default:
/* unkown serviceid */
return (-1);
}
} else if (appdata.header.msgtype == BLEPROTO_APPDATA_MSGTYPE_RSP) {
switch (appdata.header.serviceid) {
case E_BLEPROTO_SERVICE_ID_DEVICEINFO:
rc =
bleproto_decjson_deviceinfo_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.deviceinfo_rsp);
break;
case E_BLEPROTO_SERVICE_ID_AUTHSETUP:
rc = bleproto_decjson_authsetup_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.authsetup_rsp);
break;
case E_BLEPROTO_SERVICE_ID_AUTHDELETE:
rc =
bleproto_decjson_authdelete_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.authdelete_rsp);
break;
case E_BLEPROTO_SERVICE_ID_RUNCMD:
rc = bleproto_decjson_runcmd_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.runcmd_rsp);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD:
rc = bleproto_decjson_reportcmd_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.reportcmd_rsp);
break;
case E_BLEPROTO_SERVICE_ID_DOACTION:
rc = bleproto_decjson_doaction_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.doaction_rsp);
break;
case E_BLEPROTO_SERVICE_ID_OTANOTIFY:
rc = bleproto_decjson_otanotify_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.otanotify_rsp);
break;
case E_BLEPROTO_SERVICE_ID_OTADATA:
rc = bleproto_debin_otadata_rsp(appdata.data,
appdata.header.datalen,
&desc->datast.otadata_rsp);
break;
case E_BLEPROTO_SERVICE_ID_REPORTCMD_V2:
printf("reportcmd_v2_rsp");
rc = ble_proto_unpack(appdata.data, appdata.header.datalen, &desc->datast.reportcmd_v2_rsp);
printf("reportcmd_v2_rsp rc = %d", rc);
break;
default:
/* unkown serviceid */
return (-1);
}
} else {
/* unkown msgtype */
return (-1);
}
/* failed to decjson struct */
if (rc < 0) {
return (-1);
}
return (rlen);
}
/****************************************************************************/
/* */
/* End of file. */
/* */
/****************************************************************************/