482 lines
19 KiB
C
482 lines
19 KiB
C
/****************************************************************************/
|
||
/* 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;
|
||
|
||
bleproto_appdata_t 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;
|
||
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.data;appdata 是栈变量,
|
||
* 函数返回后指针会悬空。先拷到静态缓冲再 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. */
|
||
/* */
|
||
/****************************************************************************/
|