/****************************************************************************/ /* 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. */ /* */ /****************************************************************************/