3000 lines
87 KiB
C
3000 lines
87 KiB
C
/****************************************************************************/
|
|
/* bleproto_packer.c
|
|
*
|
|
* Copyright (C) 2024 四川迈科创智科技有限公司
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/* Included Files */
|
|
/****************************************************************************/
|
|
|
|
#include "bleproto.h"
|
|
#include "system/includes.h"
|
|
#include "inttypes.h"
|
|
/****************************************************************************/
|
|
/* Trace Definitions */
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/* Pre-processor Definitions */
|
|
/****************************************************************************/
|
|
/**
|
|
* @def UTILS_BITFIELD_GET
|
|
* @brief get bitfield value.
|
|
*
|
|
* @note MUSTBE `s`<=`e`.
|
|
*
|
|
* @param[in] v - The value to get.
|
|
* @param[in] e - The end-bit number.
|
|
* @param[in] s - The start-bit number.
|
|
*
|
|
* @code
|
|
* uint8_t ctrl;
|
|
* - bit7-2: type
|
|
* - bit1-0: id
|
|
* type = UTILS_BITFIELD_GET(ctrl, 7, 2);
|
|
* id = UTILS_BITFIELD_GET(ctrl, 1, 0);
|
|
* @endcode
|
|
*/
|
|
/**
|
|
* @def UTILS_BITFIELD_SET
|
|
* @brief set bitfield value.
|
|
*
|
|
* @note MUSTBE `s`<=`e`.
|
|
*
|
|
* @param[in] v - The value to set.
|
|
* @param[in] e - The end-bit number.
|
|
* @param[in] s - The start-bit number.
|
|
*
|
|
* @code
|
|
* uint8_t ctrl;
|
|
* - bit7-2: type
|
|
* - bit1-0: id
|
|
* ctrl = UTILS_BITFIELD_SET(type, 7, 2) | UTILS_BITFIELD_SET(id, 1, 0);
|
|
* @endcode
|
|
*/
|
|
/* Helper bitfield encode/decode macros */
|
|
#define UTILS_STATIC_ASSERT_OR_ZERO(cond) (sizeof(char[1 - 2 * !(cond)]) - 1)
|
|
#define UTILS_BITFILED_CHECK(e, s) UTILS_STATIC_ASSERT_OR_ZERO((e) >= (s))
|
|
#define UTILS_BITFIELD_MASK(e, s) \
|
|
(UTILS_BITFILED_CHECK(e, s) + (((1UL << ((e) - (s) + 1)) - 1UL) << (s)))
|
|
#define UTILS_BITFIELD_GET(v, e, s) \
|
|
(UTILS_BITFILED_CHECK(e, s) + \
|
|
(((v) >> (s)) & UTILS_BITFIELD_MASK(((e) - (s)), 0)))
|
|
#define UTILS_BITFIELD_SET(v, e, s) \
|
|
(UTILS_BITFILED_CHECK(e, s) + \
|
|
(((v)&UTILS_BITFIELD_MASK(((e) - (s)), 0)) << (s)))
|
|
#define UTILS_BITFIELD_CLR(v, e, s) \
|
|
(UTILS_BITFILED_CHECK(e, s) + ((v) & (~(UTILS_BITFIELD_MASK(e, s)))))
|
|
#define UTILS_BITFIELD_UPD(oldv, e, s, newv) \
|
|
(UTILS_BITFILED_CHECK(e, s) + \
|
|
(UTILS_BITFIELD_CLR(oldv, e, s) | UTILS_BITFIELD_SET(newv, e, s)))
|
|
|
|
/**
|
|
* @def UTILS_MIN
|
|
* @brief Calculates the minimum of x and y.
|
|
*/
|
|
#define UTILS_MIN(x, y) ((x) < (y) ? (x) : (y))
|
|
|
|
/****************************************************************************/
|
|
/* Private Types */
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/* Private Function Prototypes */
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/* Private Data */
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/* Public Data */
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
/* Private Functions */
|
|
/****************************************************************************/
|
|
|
|
static uint8_t hex_char_to_int(char c)
|
|
{
|
|
// 将十六进制字符转换为对应的数值
|
|
if (c >= '0' && c <= '9') {
|
|
return c - '0';
|
|
} else if (c >= 'A' && c <= 'F') {
|
|
return c - 'A' + 10;
|
|
} else if (c >= 'a' && c <= 'f') {
|
|
return c - 'a' + 10;
|
|
}
|
|
// 非十六进制字符,返回无效值
|
|
return 0xFF;
|
|
}
|
|
|
|
/* utils */
|
|
static void proto_bytes_put_le16(uint8_t dst[2], uint16_t val)
|
|
{
|
|
dst[0] = val;
|
|
dst[1] = val >> 8;
|
|
}
|
|
|
|
static uint16_t proto_bytes_get_le16(const uint8_t src[2])
|
|
{
|
|
return ((uint16_t)src[1] << 8) | src[0];
|
|
}
|
|
|
|
static int proto_strhex_to_byte(const char *str, uint8_t *bytes, size_t size)
|
|
{
|
|
// string转bytes
|
|
if (str == NULL || bytes == NULL) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
size_t str_len = strlen(str);
|
|
if (str_len % 2 != 0 || str_len / 2 > size) {
|
|
BLEPROTO_T_E("Invalid string length or buffer size");
|
|
return -1;
|
|
}
|
|
|
|
for (size_t i = 0; i < str_len; i += 2) {
|
|
uint8_t high = hex_char_to_int(str[i]);
|
|
uint8_t low = hex_char_to_int(str[i + 1]);
|
|
if (high == 0xFF || low == 0xFF) {
|
|
BLEPROTO_T_E("Invalid hex character");
|
|
return -1;
|
|
}
|
|
bytes[i / 2] = (high << 4) | low;
|
|
}
|
|
|
|
return (int)(str_len / 2);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* Public Functions */
|
|
/****************************************************************************/
|
|
|
|
int bleproto_advdata_serialize(bleproto_adv_t *adv,
|
|
uint8_t * data,
|
|
uint8_t size)
|
|
{
|
|
uint8_t offset = 0;
|
|
|
|
/* check params */
|
|
if (!adv || !data || size < BLEPROTO_ADV_MAX_SZ) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return (-1);
|
|
}
|
|
|
|
/* check adv2 type */
|
|
if (adv->adv2.ad_type != BLEPROTO_ADV_TYPE_SVC_DATA_UUID16 &&
|
|
adv->adv2.ad_type != BLEPROTO_ADV_TYPE_MFG_DATA) {
|
|
BLEPROTO_T_E("Invalid adv2.adv_type");
|
|
return (-1);
|
|
}
|
|
|
|
/* clear */
|
|
memset(data, 0, size);
|
|
|
|
/* adv1 */
|
|
{
|
|
/* rewrite member */
|
|
adv->adv1.length = 0x02;
|
|
adv->adv1.ad_type = BLEPROTO_ADV_TYPE_FLAGS;
|
|
adv->adv1.ad_data = 0x06;
|
|
|
|
data[offset++] = adv->adv1.length;
|
|
data[offset++] = adv->adv1.ad_type;
|
|
data[offset++] = adv->adv1.ad_data;
|
|
}
|
|
|
|
/* adv2 */
|
|
adv->adv2.length = BLEPROTO_ADV_MAX_SZ - 3 - 1;
|
|
{
|
|
/* adv2 length */
|
|
data[offset++] = adv->adv2.length;
|
|
/* adv2 type */
|
|
data[offset++] = adv->adv2.ad_type;
|
|
}
|
|
if (adv->adv2.ad_type == BLEPROTO_ADV_TYPE_SVC_DATA_UUID16) {
|
|
/* uuid, little endian */
|
|
proto_bytes_put_le16(&data[offset],
|
|
adv->adv2.ad_data.service_data.uuid);
|
|
offset += 2;
|
|
/////////////////////////////////////////
|
|
// spec_data
|
|
/////////////////////////////////////////
|
|
bleproto_adv_specdata_t *spec_data =
|
|
&adv->adv2.ad_data.service_data.spec_data;
|
|
/* version */
|
|
data[offset++] = spec_data->version;
|
|
/* business */
|
|
data[offset++] = spec_data->business;
|
|
/* rfu */
|
|
data[offset++] = 0;
|
|
data[offset++] = 0;
|
|
/* txpower */
|
|
data[offset++] = (uint8_t)spec_data->txpower;
|
|
/* manucode */
|
|
{
|
|
spec_data->manucode.type = BLEPROTO_ADV_TLV_TYPE_MANUCODE;
|
|
spec_data->manucode.length = BLEPROTO_ADV_TLV_LENGTH_MANUCODE;
|
|
|
|
data[offset++] = spec_data->manucode.type;
|
|
data[offset++] = spec_data->manucode.length;
|
|
memcpy(&data[offset],
|
|
spec_data->manucode.value,
|
|
BLEPROTO_ADV_TLV_LENGTH_MANUCODE);
|
|
offset += BLEPROTO_ADV_TLV_LENGTH_MANUCODE;
|
|
}
|
|
/* prodcode */
|
|
{
|
|
spec_data->prodcode.type = BLEPROTO_ADV_TLV_TYPE_PRODCODE;
|
|
spec_data->prodcode.length = BLEPROTO_ADV_TLV_LENGTH_PRODCODE;
|
|
|
|
data[offset++] = spec_data->prodcode.type;
|
|
data[offset++] = spec_data->prodcode.length;
|
|
memcpy(&data[offset],
|
|
spec_data->prodcode.value,
|
|
BLEPROTO_ADV_TLV_LENGTH_PRODCODE);
|
|
offset += BLEPROTO_ADV_TLV_LENGTH_PRODCODE;
|
|
}
|
|
/* separator */
|
|
{
|
|
spec_data->separator = 0xFF;
|
|
|
|
data[offset++] = spec_data->separator;
|
|
}
|
|
/* selfdata */
|
|
{
|
|
memcpy(&data[offset],
|
|
spec_data->selfdata,
|
|
sizeof(spec_data->selfdata));
|
|
offset += (uint8_t)sizeof(spec_data->selfdata);
|
|
}
|
|
} else if (adv->adv2.ad_type == BLEPROTO_ADV_TYPE_MFG_DATA) {
|
|
bleproto_advdata_mfg_t *mfg_data = &adv->adv2.ad_data.mfg_data;
|
|
/* siot */
|
|
data[offset++] = mfg_data->siot[0];
|
|
data[offset++] = mfg_data->siot[1];
|
|
data[offset++] = mfg_data->siot[2];
|
|
data[offset++] = mfg_data->siot[3];
|
|
data[offset++] = mfg_data->siot[4];
|
|
data[offset++] = mfg_data->siot[5];
|
|
/* flag */
|
|
data[offset++] = mfg_data->flag;
|
|
/* txpower */
|
|
data[offset++] = (uint8_t)mfg_data->txpower;
|
|
/* gwmac */
|
|
data[offset++] = mfg_data->gwmac[0];
|
|
data[offset++] = mfg_data->gwmac[1];
|
|
data[offset++] = mfg_data->gwmac[2];
|
|
data[offset++] = mfg_data->gwmac[3];
|
|
data[offset++] = mfg_data->gwmac[4];
|
|
data[offset++] = mfg_data->gwmac[5];
|
|
/* manucode */
|
|
{
|
|
mfg_data->manucode.type = BLEPROTO_ADV_TLV_TYPE_MANUCODE;
|
|
mfg_data->manucode.length = BLEPROTO_ADV_TLV_LENGTH_MANUCODE;
|
|
|
|
data[offset++] = mfg_data->manucode.type;
|
|
data[offset++] = mfg_data->manucode.length;
|
|
memcpy(&data[offset],
|
|
mfg_data->manucode.value,
|
|
BLEPROTO_ADV_TLV_LENGTH_MANUCODE);
|
|
offset += BLEPROTO_ADV_TLV_LENGTH_MANUCODE;
|
|
}
|
|
/* prodcode */
|
|
{
|
|
mfg_data->prodcode.type = BLEPROTO_ADV_TLV_TYPE_PRODCODE;
|
|
mfg_data->prodcode.length = BLEPROTO_ADV_TLV_LENGTH_PRODCODE;
|
|
|
|
data[offset++] = mfg_data->prodcode.type;
|
|
data[offset++] = mfg_data->prodcode.length;
|
|
memcpy(&data[offset],
|
|
mfg_data->prodcode.value,
|
|
BLEPROTO_ADV_TLV_LENGTH_PRODCODE);
|
|
offset += BLEPROTO_ADV_TLV_LENGTH_PRODCODE;
|
|
}
|
|
}
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_advdata_deserialize(const uint8_t * data,
|
|
uint8_t len,
|
|
bleproto_adv_t *adv)
|
|
{
|
|
int rc;
|
|
uint8_t offset = 0;
|
|
|
|
/* check parameters */
|
|
if (!data || !adv) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return (-1);
|
|
}
|
|
|
|
/* check len */
|
|
if (len != BLEPROTO_ADV_MAX_SZ) {
|
|
BLEPROTO_T_E("Invalid len");
|
|
return (-1);
|
|
}
|
|
|
|
do {
|
|
/* clear */
|
|
memset(adv, 0, sizeof(*adv));
|
|
|
|
/* adv1 */
|
|
adv->adv1.length = data[offset++];
|
|
adv->adv1.ad_type = data[offset++];
|
|
adv->adv1.ad_data = data[offset++];
|
|
if (adv->adv1.length != 0x02 ||
|
|
adv->adv1.ad_type != BLEPROTO_ADV_TYPE_FLAGS ||
|
|
adv->adv1.ad_data != 0x06) {
|
|
BLEPROTO_T_E("Invalid adv1 data");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
|
|
adv->adv2.length = data[offset++];
|
|
adv->adv2.ad_type = data[offset++];
|
|
if (adv->adv2.length != BLEPROTO_ADV_MAX_SZ - 3 - 1) {
|
|
BLEPROTO_T_E("Invalid adv2 len");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
|
|
/* adv2 */
|
|
if (adv->adv2.ad_type == BLEPROTO_ADV_TYPE_SVC_DATA_UUID16) {
|
|
/* uuid, little endian */
|
|
adv->adv2.ad_data.service_data.uuid =
|
|
proto_bytes_get_le16(&data[offset]);
|
|
offset += 2;
|
|
/////////////////////////////////////////
|
|
// spec_data
|
|
/////////////////////////////////////////
|
|
bleproto_adv_specdata_t *spec_data =
|
|
&adv->adv2.ad_data.service_data.spec_data;
|
|
/* version */
|
|
spec_data->version = data[offset++];
|
|
/* business */
|
|
spec_data->business = data[offset++];
|
|
/* rfu */
|
|
spec_data->rfu[0] = data[offset++];
|
|
spec_data->rfu[1] = data[offset++];
|
|
/* txpower */
|
|
spec_data->txpower = (int8_t)data[offset++];
|
|
/* manucode */
|
|
{
|
|
spec_data->manucode.type = data[offset++];
|
|
if (spec_data->manucode.type !=
|
|
BLEPROTO_ADV_TLV_TYPE_MANUCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 service_data.manucode.type");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
spec_data->manucode.length = data[offset++];
|
|
if (spec_data->manucode.length !=
|
|
BLEPROTO_ADV_TLV_LENGTH_MANUCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 service_data.manucode.length");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
memcpy(spec_data->manucode.value,
|
|
&data[offset],
|
|
spec_data->manucode.length);
|
|
offset += spec_data->manucode.length;
|
|
}
|
|
/* prodcode */
|
|
{
|
|
spec_data->prodcode.type = data[offset++];
|
|
if (spec_data->prodcode.type !=
|
|
BLEPROTO_ADV_TLV_TYPE_PRODCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 service_data.prodcode.type");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
spec_data->prodcode.length = data[offset++];
|
|
if (spec_data->prodcode.length !=
|
|
BLEPROTO_ADV_TLV_LENGTH_PRODCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 service_data.prodcode.length");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
memcpy(spec_data->prodcode.value,
|
|
&data[offset],
|
|
spec_data->prodcode.length);
|
|
offset += spec_data->prodcode.length;
|
|
}
|
|
/* separator */
|
|
{
|
|
spec_data->separator = data[offset++];
|
|
if (spec_data->separator != 0xff) {
|
|
BLEPROTO_T_E("Invalid adv2 service_data.separator");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
}
|
|
/* selfdata */
|
|
{
|
|
memcpy(spec_data->selfdata,
|
|
&data[offset],
|
|
sizeof(spec_data->selfdata));
|
|
offset += (uint8_t)sizeof(spec_data->selfdata);
|
|
}
|
|
} else if (adv->adv2.ad_type == BLEPROTO_ADV_TYPE_MFG_DATA) {
|
|
bleproto_advdata_mfg_t *mfg_data = &adv->adv2.ad_data.mfg_data;
|
|
/* fix "SIOT-1" */
|
|
memcpy(mfg_data->siot, &data[offset], 6);
|
|
// if (mfg_data->siot[0] != 'S' || mfg_data->siot[1] != 'I' ||
|
|
// mfg_data->siot[2] != 'O' || mfg_data->siot[3] != 'T' ||
|
|
// mfg_data->siot[4] != '-') {
|
|
// BLEPROTO_T_E("Invalid adv2 mfg_data.siot");
|
|
// rc = -1;
|
|
// break;
|
|
// }
|
|
offset += 6;
|
|
|
|
/* flag */
|
|
mfg_data->flag = data[offset++];
|
|
/* txpower */
|
|
mfg_data->txpower = (int8_t)data[offset++];
|
|
/* gwmac */
|
|
memcpy(mfg_data->gwmac, &data[offset], 6);
|
|
offset += 6;
|
|
/* manucode */
|
|
{
|
|
mfg_data->manucode.type = data[offset++];
|
|
if (mfg_data->manucode.type !=
|
|
BLEPROTO_ADV_TLV_TYPE_MANUCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 mfg_data.manucode.type");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
mfg_data->manucode.length = data[offset++];
|
|
if (mfg_data->manucode.length !=
|
|
BLEPROTO_ADV_TLV_LENGTH_MANUCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 mfg_data.manucode.length");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
memcpy(mfg_data->manucode.value,
|
|
&data[offset],
|
|
mfg_data->manucode.length);
|
|
offset += mfg_data->manucode.length;
|
|
}
|
|
/* prodcode */
|
|
{
|
|
mfg_data->prodcode.type = data[offset++];
|
|
if (mfg_data->prodcode.type !=
|
|
BLEPROTO_ADV_TLV_TYPE_PRODCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 mfg_data.prodcode.type");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
mfg_data->prodcode.length = data[offset++];
|
|
if (mfg_data->prodcode.length !=
|
|
BLEPROTO_ADV_TLV_LENGTH_PRODCODE) {
|
|
BLEPROTO_T_E("Invalid adv2 mfg_data.prodcode.length");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
memcpy(mfg_data->prodcode.value,
|
|
&data[offset],
|
|
mfg_data->prodcode.length);
|
|
offset += mfg_data->prodcode.length;
|
|
}
|
|
} else {
|
|
BLEPROTO_T_E("Invalid adv2 adv_type");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
|
|
/* check offset */
|
|
if (offset != 31) {
|
|
BLEPROTO_T_E("Invalid offset");
|
|
rc = -1;
|
|
break;
|
|
}
|
|
rc = offset;
|
|
} while (0);
|
|
|
|
return (rc);
|
|
}
|
|
|
|
int bleproto_appdata_serialize_len(bleproto_appdata_t *appdata,
|
|
uint8_t packetlen,
|
|
uint16_t * outlen)
|
|
{
|
|
/* check param */
|
|
if (!appdata || packetlen <= BLEPROTO_APPDATA_HEADR_LEN) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* data total len */
|
|
uint16_t datalen = appdata->header.datalen;
|
|
|
|
/* each frame max payload length */
|
|
uint8_t frame_max_payload = packetlen - BLEPROTO_APPDATA_HEADR_LEN;
|
|
|
|
/* calculate total frames needed */
|
|
uint16_t totalframe;
|
|
if (datalen == 0) {
|
|
/* even with no data, we need at least one frame for the header */
|
|
totalframe = 1;
|
|
} else {
|
|
/* calculate frames needed for the data */
|
|
totalframe = (datalen + frame_max_payload - 1) / frame_max_payload;
|
|
}
|
|
if (totalframe > 255) {
|
|
BLEPROTO_T_E("Invalid appdata.datalen too long >(%u)",
|
|
(uint16_t)frame_max_payload * 255);
|
|
return -1;
|
|
}
|
|
|
|
/* calculate total buffer size needed */
|
|
if (totalframe <= 1) {
|
|
/* at least one frame is needed */
|
|
if (outlen) {
|
|
*outlen = datalen + BLEPROTO_APPDATA_HEADR_LEN;
|
|
}
|
|
} else {
|
|
/* calculate size of full frames */
|
|
uint16_t full_frames_size = (uint16_t)(totalframe - 1) * packetlen;
|
|
|
|
// clang-format off
|
|
/* calculate size of last frame */
|
|
uint16_t last_frame_size =
|
|
/* header */ BLEPROTO_APPDATA_HEADR_LEN +
|
|
/* payload */ datalen - (uint16_t)((totalframe - 1) * frame_max_payload);
|
|
// clang-format on
|
|
|
|
/* total size is sum of full frames and last frame */
|
|
if (outlen) {
|
|
*outlen = full_frames_size + last_frame_size;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int bleproto_appdata_serialize(bleproto_appdata_t *appdata,
|
|
uint8_t packetlen,
|
|
uint8_t * buf,
|
|
uint16_t size)
|
|
|
|
{
|
|
int rc, offset = 0;
|
|
uint16_t data_offset = 0;
|
|
|
|
/* check param */
|
|
if (!appdata || packetlen <= BLEPROTO_APPDATA_HEADR_LEN) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* totoal len */
|
|
uint16_t total_len;
|
|
rc = bleproto_appdata_serialize_len(appdata, packetlen, &total_len);
|
|
if (rc < 0) {
|
|
return -1;
|
|
}
|
|
if (size < total_len) {
|
|
BLEPROTO_T_E("Invalid datalen:%u, buf too short(%u<%u)",
|
|
appdata->header.datalen,
|
|
size,
|
|
total_len);
|
|
return -1;
|
|
}
|
|
|
|
/* data total len */
|
|
uint16_t datalen = appdata->header.datalen;
|
|
|
|
/* each frame max payload length */
|
|
uint8_t frame_max_payload = packetlen - BLEPROTO_APPDATA_HEADR_LEN;
|
|
|
|
/* calculate total frames needed */
|
|
uint16_t totalframe;
|
|
if (datalen == 0) {
|
|
/* even with no data, we need at least one frame for the header */
|
|
totalframe = 1;
|
|
} else {
|
|
/* calculate frames needed for the data */
|
|
totalframe = (datalen + frame_max_payload - 1) / frame_max_payload;
|
|
}
|
|
if (totalframe > 255) {
|
|
BLEPROTO_T_E("Invalid appdata.datalen too long");
|
|
return -1;
|
|
}
|
|
|
|
for (uint8_t i = 0; i < (uint8_t)totalframe; i++) {
|
|
/* pthis_frame_len */
|
|
uint8_t pthis_frame_len = 0;
|
|
if (totalframe == 1) {
|
|
/* only one frame */
|
|
pthis_frame_len = (uint8_t)datalen;
|
|
} else if (i + 1 < totalframe) {
|
|
/* full size frames */
|
|
pthis_frame_len = frame_max_payload;
|
|
} else {
|
|
/* last frame */
|
|
pthis_frame_len = (uint8_t)(datalen - data_offset);
|
|
}
|
|
|
|
/* header */
|
|
bleproto_appdata_header_t hdr = appdata->header;
|
|
{
|
|
hdr.totalframe = totalframe;
|
|
if (totalframe == 1) {
|
|
hdr.frameseq = 0;
|
|
} else {
|
|
hdr.frameseq = i + 1;
|
|
}
|
|
}
|
|
/* serialize_header */
|
|
{
|
|
/* buf[0]: version[2:0] | datafmt[3:3] | msgtype[7:4] */
|
|
buf[offset + 0] = UTILS_BITFIELD_SET(hdr.version, 2, 0) |
|
|
UTILS_BITFIELD_SET(hdr.datafmt, 3, 3) |
|
|
UTILS_BITFIELD_SET(hdr.msgtype, 7, 4);
|
|
/* buf[1]: msgid[3:0] | encrypt[4:4] | reserve[7:5] */
|
|
buf[offset + 1] = UTILS_BITFIELD_SET(hdr.msgid, 3, 0) |
|
|
UTILS_BITFIELD_SET(hdr.encrypt, 4, 4) |
|
|
UTILS_BITFIELD_SET(hdr.reserve, 7, 5);
|
|
|
|
buf[offset + 2] = hdr.totalframe;
|
|
buf[offset + 3] = hdr.frameseq;
|
|
buf[offset + 4] = pthis_frame_len;
|
|
buf[offset + 5] = hdr.serviceid;
|
|
|
|
/* datalen in little endian */
|
|
proto_bytes_put_le16(&buf[offset + 6], hdr.datalen);
|
|
}
|
|
offset += BLEPROTO_APPDATA_HEADR_LEN;
|
|
|
|
/* payload */
|
|
if (pthis_frame_len != 0) {
|
|
memcpy(
|
|
&buf[offset], &appdata->data[data_offset], pthis_frame_len);
|
|
/* offset */
|
|
offset += pthis_frame_len;
|
|
/* data_offset */
|
|
data_offset += pthis_frame_len;
|
|
}
|
|
}
|
|
if (offset != total_len) {
|
|
BLEPROTO_T_E("Error calc appdata total_len");
|
|
return -1;
|
|
}
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_appdata_deserialize(uint8_t * buf,
|
|
uint16_t len,
|
|
bleproto_appdata_t *appdata)
|
|
{
|
|
/* check parameters */
|
|
if (!buf || !appdata) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* 检查是否至少有一个完整的包头 */
|
|
if (len < BLEPROTO_APPDATA_HEADR_LEN) {
|
|
// 数据不够,需要更多数据
|
|
return 0;
|
|
}
|
|
|
|
int offset = 0;
|
|
uint8_t msgid;
|
|
uint8_t totalframe;
|
|
uint8_t frameseq;
|
|
uint16_t datalen;
|
|
uint8_t frame_payload_len;
|
|
uint8_t max_payload = 0;
|
|
uint8_t recv_frames = 0;
|
|
|
|
/* 第一轮: 扫描所有数据,验证分包的完整性和一致性 */
|
|
{
|
|
int scan_offset = 0;
|
|
bool first_frame = true;
|
|
|
|
while (scan_offset < len) {
|
|
/* 解析header中的关键字段 */
|
|
msgid = UTILS_BITFIELD_GET(buf[scan_offset + 1], 3, 0);
|
|
totalframe = buf[scan_offset + 2];
|
|
frameseq = buf[scan_offset + 3];
|
|
frame_payload_len = buf[scan_offset + 4];
|
|
datalen = proto_bytes_get_le16(&buf[scan_offset + 6]);
|
|
BLEPROTO_T_S("[%u/%u]=0x%02X(%u),msgid:%u,datalen:0x%02X(%u)",
|
|
frameseq,
|
|
totalframe,
|
|
frame_payload_len,
|
|
frame_payload_len,
|
|
msgid,
|
|
datalen,
|
|
datalen);
|
|
|
|
/* 基本参数检查 */
|
|
if (totalframe == 0) {
|
|
BLEPROTO_T_E("Invalid totalframe");
|
|
return -1;
|
|
}
|
|
if (frameseq > totalframe) {
|
|
BLEPROTO_T_E("Invalid frameseq");
|
|
return -1;
|
|
}
|
|
if (datalen > BLEPROTO_APPDATA_DATA_MAX_SZ) {
|
|
BLEPROTO_T_E("Invalid datalen");
|
|
return -1;
|
|
}
|
|
|
|
/* 分包一致性检查 */
|
|
if (first_frame) {
|
|
first_frame = false;
|
|
// 使用第一帧的payload长度作为最大payload
|
|
max_payload = frame_payload_len;
|
|
} else {
|
|
/* 检查msgid一致性 */
|
|
if (msgid != UTILS_BITFIELD_GET(buf[1], 3, 0)) {
|
|
BLEPROTO_T_E("Inconsistent msgid");
|
|
return -1;
|
|
}
|
|
/* 检查totalframe一致性 */
|
|
if (totalframe != buf[2]) {
|
|
BLEPROTO_T_E("Inconsistent totalframe");
|
|
return -1;
|
|
}
|
|
/* 检查frameseq连续性 */
|
|
uint8_t last_frameseq =
|
|
buf[scan_offset -
|
|
(BLEPROTO_APPDATA_HEADR_LEN + max_payload) + 3];
|
|
if (frameseq != (last_frameseq + 1)) {
|
|
BLEPROTO_T_E("Non-sequential frameseq:%u!=%u",
|
|
frameseq,
|
|
(last_frameseq + 1));
|
|
return -1;
|
|
}
|
|
/* 检查非最后一帧的payload长度是否与第一帧相同 */
|
|
if (frameseq < (totalframe - 1) &&
|
|
frame_payload_len != max_payload) {
|
|
BLEPROTO_T_E("Inconsistent frame payload length");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* 检查payload长度 */
|
|
if ((len - scan_offset) <
|
|
(BLEPROTO_APPDATA_HEADR_LEN + frame_payload_len)) {
|
|
return 0; // 需要更多数据
|
|
}
|
|
|
|
/* 验证frame_payload_len */
|
|
if (totalframe == 1) {
|
|
if (frame_payload_len != datalen) {
|
|
BLEPROTO_T_E(
|
|
"Invalid frame_payload_len for single frame");
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (frameseq < totalframe) {
|
|
/* 非最后一帧必须是满包 */
|
|
if (frame_payload_len != max_payload) {
|
|
BLEPROTO_T_E(
|
|
"Invalid frame_payload_len for non-last frame");
|
|
return -1;
|
|
}
|
|
} else {
|
|
/* 最后一帧的长度计算 */
|
|
uint16_t last_frame_payload = datalen % max_payload;
|
|
if (last_frame_payload == 0) {
|
|
last_frame_payload = max_payload;
|
|
}
|
|
if (frame_payload_len != last_frame_payload) {
|
|
BLEPROTO_T_E(
|
|
"Invalid frame_payload_len for last frame(%u!=%u)",
|
|
frame_payload_len,
|
|
last_frame_payload);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* recv_frames */
|
|
recv_frames++;
|
|
|
|
scan_offset += BLEPROTO_APPDATA_HEADR_LEN + frame_payload_len;
|
|
}
|
|
|
|
/* 检查是否收到了完整的包 */
|
|
if (recv_frames != totalframe) {
|
|
// 还没收到所有分包
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* 第二轮: 解析数据并填充到appdata结构中 */
|
|
{
|
|
/* 解析第一帧header */
|
|
bleproto_appdata_header_t *hdr = &appdata->header;
|
|
|
|
/* buf[0]: version[2:0] | datafmt[3:3] | msgtype[7:4] */
|
|
hdr->version = UTILS_BITFIELD_GET(buf[0], 2, 0);
|
|
hdr->datafmt = UTILS_BITFIELD_GET(buf[0], 3, 3);
|
|
hdr->msgtype = UTILS_BITFIELD_GET(buf[0], 7, 4);
|
|
|
|
/* buf[1]: msgid[3:0] | encrypt[4:4] | reserve[7:5] */
|
|
hdr->msgid = UTILS_BITFIELD_GET(buf[1], 3, 0);
|
|
hdr->encrypt = UTILS_BITFIELD_GET(buf[1], 4, 4);
|
|
hdr->reserve = UTILS_BITFIELD_GET(buf[1], 7, 5);
|
|
|
|
hdr->totalframe = buf[2];
|
|
hdr->frameseq = buf[3];
|
|
hdr->framelen = buf[4];
|
|
hdr->serviceid = buf[5];
|
|
hdr->datalen = proto_bytes_get_le16(&buf[6]);
|
|
|
|
/* 复制所有payload数据 */
|
|
uint16_t data_offset = 0;
|
|
uint8_t frames_processed = 0;
|
|
|
|
/* clear offset */
|
|
offset = 0;
|
|
while (frames_processed < hdr->totalframe) {
|
|
/* this frame payload length */
|
|
frame_payload_len = buf[offset + 4];
|
|
|
|
if (frame_payload_len > 0) {
|
|
uint8_t curr_frameseq = buf[offset + 3];
|
|
if (curr_frameseq == 0) {
|
|
data_offset = 0;
|
|
} else {
|
|
data_offset = (curr_frameseq - 1) * max_payload;
|
|
}
|
|
|
|
/* copy payload data */
|
|
memcpy(&appdata->data[data_offset],
|
|
&buf[offset + BLEPROTO_APPDATA_HEADR_LEN],
|
|
frame_payload_len);
|
|
}
|
|
|
|
offset += BLEPROTO_APPDATA_HEADR_LEN + frame_payload_len;
|
|
frames_processed++;
|
|
}
|
|
}
|
|
|
|
/* 返回处理的字节数 */
|
|
return offset;
|
|
}
|
|
|
|
int bleproto_encjson_ycmd(const bleproto_ycmd_t *ycmd,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
uint16_t i;
|
|
|
|
/* check param */
|
|
if (!ycmd || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
if (ycmd->arg_int32_count > YCMD_INT32_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_int32_count");
|
|
return -1;
|
|
}
|
|
if (ycmd->arg_string_count > YCMD_STRING_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_string_count");
|
|
return -1;
|
|
}
|
|
for (i = 0; i < ycmd->arg_string_count; i++) {
|
|
if (strlen(ycmd->arg_string[i]) == 0) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_string[%u]", i);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (ycmd->arg_bytes_count > YCMD_BYTES_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_bytes_count");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx" }
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// cmd_id
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%" PRId32 ",",
|
|
"cmd_id",
|
|
(int)ycmd->cmd_id);
|
|
}
|
|
|
|
// arg_int32
|
|
if (ycmd->arg_int32_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_int32");
|
|
for (i = 0; i < ycmd->arg_int32_count; i++) {
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"%" PRId32 "",
|
|
ycmd->arg_int32[i]);
|
|
if (i != ycmd->arg_int32_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_string
|
|
if (ycmd->arg_string_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_string");
|
|
for (i = 0; i < ycmd->arg_string_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\"", ycmd->arg_string[i]);
|
|
if (i != ycmd->arg_string_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_bytes
|
|
if (ycmd->arg_bytes_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":\"", "arg_bytes");
|
|
for (i = 0; i < ycmd->arg_bytes_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "%02X", ycmd->arg_bytes[i]);
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "\",");
|
|
}
|
|
|
|
// t
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%" PRIu64 "\"",
|
|
"t",
|
|
ycmd->t);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("ycmd:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_decjson_ycmd(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_ycmd_t *ycmd)
|
|
{
|
|
int rc, i;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !ycmd) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("ycmd:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(ycmd, 0, sizeof(*ycmd));
|
|
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx" }
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// cmd_id
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.cmd_id",
|
|
/* v */ &v);
|
|
if (rc > 0) {
|
|
ycmd->cmd_id = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse cmd_id");
|
|
return -1;
|
|
}
|
|
|
|
// arg_int32
|
|
for (i = 0; i < YCMD_INT32_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_int32[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_int32[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_NUMBER) {
|
|
char vstr[32] = { 0 };
|
|
memcpy(vstr, ptr, UTILS_MIN(n, 31));
|
|
ycmd->arg_int32[ycmd->arg_int32_count] =
|
|
(int32_t)strtol(vstr, NULL, 10);
|
|
ycmd->arg_int32_count++;
|
|
}
|
|
}
|
|
|
|
// arg_string
|
|
for (i = 0; i < YCMD_STRING_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_string[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_string[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_STRING) {
|
|
if (n >= 2 && ptr[0] == '"' && ptr[n - 1] == '"') {
|
|
ptr++; // 跳过首引号
|
|
n -= 2; // 去掉首尾引号的长度
|
|
} else {
|
|
BLEPROTO_T_E("Error parse arg_string");
|
|
return -1;
|
|
}
|
|
memcpy(ycmd->arg_string[ycmd->arg_string_count],
|
|
ptr,
|
|
UTILS_MIN(n, YCMD_STRING_MAX_SIZE));
|
|
ycmd->arg_string_count++;
|
|
}
|
|
}
|
|
|
|
// arg_bytes
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.arg_bytes",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
// strhex to byte
|
|
rc = proto_strhex_to_byte(
|
|
value_str, ycmd->arg_bytes, sizeof(ycmd->arg_bytes));
|
|
if (rc >= 0) {
|
|
ycmd->arg_bytes_count = (uint16_t)rc;
|
|
}
|
|
}
|
|
|
|
// t
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.t",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
ycmd->t = (uint64_t)strtoull(value_str, NULL, 10);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse t");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_encjson_deviceinfo_req(const bleproto_deviceinfo_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
//{"t":"xxxxxxxx",gmtoff:%d}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// t
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"t\":\"%" PRIu64 "\",", p->t);
|
|
}
|
|
|
|
// gmtoff
|
|
{
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"gmtoff\":%d", p->gmtoff);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_deviceinfo_rsp(const bleproto_deviceinfo_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* check params */
|
|
if (strlen(p->hwv) == 0) {
|
|
BLEPROTO_T_E("Invalid deviceinfo.rsp.hwv");
|
|
return -1;
|
|
}
|
|
if (strlen(p->swv) == 0) {
|
|
BLEPROTO_T_E("Invalid deviceinfo.rsp.swv");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"hwv":"%s","swv":"%s","prototype":%u,"hbcycle":%u,"longcon":%u}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// hwv
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":\"%s\",", "hwv", p->hwv);
|
|
}
|
|
// swv
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":\"%s\",", "swv", p->swv);
|
|
}
|
|
// prototype
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%u,",
|
|
"prototype",
|
|
p->prototype);
|
|
}
|
|
// hbcycle
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":%u,", "hbcycle", p->hbcycle);
|
|
}
|
|
// longcon
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":%u", "longcon", p->longcon);
|
|
}
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_authsetup_req(const bleproto_authsetup_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* check params */
|
|
if (strlen(p->devid) == 0) {
|
|
BLEPROTO_T_E("Invalid authsetup.req.devid");
|
|
return -1;
|
|
}
|
|
if (strlen(p->authcode) == 0) {
|
|
BLEPROTO_T_E("Invalid authsetup.req.authcode");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"gwmac":"xxxx","devid":"xxxx","authcode":"xxxx"}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// gwmac
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%02X%02X%02X%02X%02X%02X\",",
|
|
"gwmac",
|
|
p->gwmac[0],
|
|
p->gwmac[1],
|
|
p->gwmac[2],
|
|
p->gwmac[3],
|
|
p->gwmac[4],
|
|
p->gwmac[5]);
|
|
}
|
|
|
|
// devid
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":\"%s\",", "devid", p->devid);
|
|
}
|
|
|
|
// authcode
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%s\"",
|
|
"authcode",
|
|
p->authcode);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_authsetup_rsp(const bleproto_authsetup_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"errcode":xxx}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// errcode
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%d",
|
|
"errcode",
|
|
(int)p->errcode);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_authdelete_req(const bleproto_authdelete_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* check params */
|
|
if (strlen(p->authcode) == 0) {
|
|
BLEPROTO_T_E("Invalid authdelete.req.authcode");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// { "authcode": "xxxx"}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// authcode
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%s\"",
|
|
"authcode",
|
|
p->authcode);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_authdelete_rsp(const bleproto_authdelete_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"gwmac": "xxxx","errcode":xxx}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// gwmac
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%02X%02X%02X%02X%02X%02X\",",
|
|
"gwmac",
|
|
p->gwmac[0],
|
|
p->gwmac[1],
|
|
p->gwmac[2],
|
|
p->gwmac[3],
|
|
p->gwmac[4],
|
|
p->gwmac[5]);
|
|
}
|
|
|
|
// errcode
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%d",
|
|
"errcode",
|
|
(int)p->errcode);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_runcmd_req(const bleproto_runcmd_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
uint16_t i;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
if (p->ycmd.arg_int32_count > YCMD_INT32_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_int32_count");
|
|
return -1;
|
|
}
|
|
if (p->ycmd.arg_string_count > YCMD_STRING_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_string_count");
|
|
return -1;
|
|
}
|
|
for (i = 0; i < p->ycmd.arg_string_count; i++) {
|
|
if (strlen(p->ycmd.arg_string[i]) == 0) {
|
|
BLEPROTO_T_E("Invalid runcmd.req.arg_string[%u]", i);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (p->ycmd.arg_bytes_count > YCMD_BYTES_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_bytes_count");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx" }
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// cmd_id
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%" PRId32 ",",
|
|
"cmd_id",
|
|
(int)p->ycmd.cmd_id);
|
|
}
|
|
|
|
// arg_int32
|
|
if (p->ycmd.arg_int32_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_int32");
|
|
for (i = 0; i < p->ycmd.arg_int32_count; i++) {
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"%" PRId32 "",
|
|
p->ycmd.arg_int32[i]);
|
|
if (i != p->ycmd.arg_int32_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_string
|
|
if (p->ycmd.arg_string_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_string");
|
|
for (i = 0; i < p->ycmd.arg_string_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\"", p->ycmd.arg_string[i]);
|
|
if (i != p->ycmd.arg_string_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_bytes
|
|
if (p->ycmd.arg_bytes_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":\"", "arg_bytes");
|
|
for (i = 0; i < p->ycmd.arg_bytes_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "%02X", p->ycmd.arg_bytes[i]);
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "\",");
|
|
}
|
|
|
|
// t
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%" PRIu64 "\"",
|
|
"t",
|
|
p->ycmd.t);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_runcmd_rsp(const bleproto_runcmd_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
uint16_t i;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
if (p->ycmd.arg_int32_count > YCMD_INT32_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_int32_count");
|
|
return -1;
|
|
}
|
|
if (p->ycmd.arg_string_count > YCMD_STRING_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_string_count");
|
|
return -1;
|
|
}
|
|
for (i = 0; i < p->ycmd.arg_string_count; i++) {
|
|
if (strlen(p->ycmd.arg_string[i]) == 0) {
|
|
BLEPROTO_T_E("Invalid runcmd.rsp.arg_string[%u]", i);
|
|
return -1;
|
|
}
|
|
}
|
|
if (p->ycmd.arg_bytes_count > YCMD_BYTES_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_bytes_count");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx" }
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// cmd_id
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%" PRId32 ",",
|
|
"cmd_id",
|
|
(int)p->ycmd.cmd_id);
|
|
}
|
|
|
|
// arg_int32
|
|
if (p->ycmd.arg_int32_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_int32");
|
|
for (i = 0; i < p->ycmd.arg_int32_count; i++) {
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"%" PRId32 "",
|
|
p->ycmd.arg_int32[i]);
|
|
if (i != p->ycmd.arg_int32_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_string
|
|
if (p->ycmd.arg_string_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_string");
|
|
for (i = 0; i < p->ycmd.arg_string_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\"", p->ycmd.arg_string[i]);
|
|
if (i != p->ycmd.arg_string_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_bytes
|
|
if (p->ycmd.arg_bytes_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":\"", "arg_bytes");
|
|
for (i = 0; i < p->ycmd.arg_bytes_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "%02X", p->ycmd.arg_bytes[i]);
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "\",");
|
|
}
|
|
|
|
// t
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%" PRIu64 "\"",
|
|
"t",
|
|
p->ycmd.t);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_reportcmd_req(const bleproto_reportcmd_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
uint16_t i;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
if (p->ycmd.arg_int32_count > YCMD_INT32_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_int32_count");
|
|
return -1;
|
|
}
|
|
if (p->ycmd.arg_string_count > YCMD_STRING_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_string_count");
|
|
return -1;
|
|
}
|
|
for (i = 0; i < p->ycmd.arg_string_count; i++) {
|
|
if (strlen(p->ycmd.arg_string[i]) == 0) {
|
|
BLEPROTO_T_E("Invalid reportcmd.req.arg_string[%u]", i);
|
|
return -1;
|
|
}
|
|
}
|
|
if (p->ycmd.arg_bytes_count > YCMD_BYTES_MAX_COUNT) {
|
|
BLEPROTO_T_E("Invalid ycmd.arg_bytes_count");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx"}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// cmd_id
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%" PRId32 ",",
|
|
"cmd_id",
|
|
(int)p->ycmd.cmd_id);
|
|
}
|
|
|
|
// arg_int32
|
|
if (p->ycmd.arg_int32_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_int32");
|
|
for (i = 0; i < p->ycmd.arg_int32_count; i++) {
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"%" PRId32 "",
|
|
p->ycmd.arg_int32[i]);
|
|
if (i != p->ycmd.arg_int32_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_string
|
|
if (p->ycmd.arg_string_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":[", "arg_string");
|
|
for (i = 0; i < p->ycmd.arg_string_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\"", p->ycmd.arg_string[i]);
|
|
if (i != p->ycmd.arg_string_count - 1) {
|
|
offset += snprintf(&str[offset], size - offset, "%s", ",");
|
|
}
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "],");
|
|
}
|
|
|
|
// arg_bytes
|
|
if (p->ycmd.arg_bytes_count > 0) {
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":\"", "arg_bytes");
|
|
for (i = 0; i < p->ycmd.arg_bytes_count; i++) {
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "%02X", p->ycmd.arg_bytes[i]);
|
|
}
|
|
offset += snprintf(&str[offset], size - offset, "%s", "\",");
|
|
}
|
|
|
|
// t
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":\"%" PRIu64 "\"",
|
|
"t",
|
|
p->ycmd.t);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_reportcmd_rsp(const bleproto_reportcmd_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"errcode":xxx}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// errcode
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%d",
|
|
"errcode",
|
|
(int)p->errcode);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_doaction_req(const bleproto_doaction_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"action":%d}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// action
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":%d", "action", p->action);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_doaction_rsp(const bleproto_doaction_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"errcode":xxx}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// errcode
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%d",
|
|
"errcode",
|
|
(int)p->errcode);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_otanotify_req(const bleproto_otanotify_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"id": %d, "ver":"xxxx", "size":%d, "md5":"xxxxxxx"}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// id
|
|
{
|
|
offset +=
|
|
snprintf(&str[offset], size - offset, "\"%s\":%d,", "id", p->id);
|
|
}
|
|
// ver
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":\"%s\",", "ver", p->version);
|
|
}
|
|
// size
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":%u,", "size", p->size);
|
|
}
|
|
// md5
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":\"%s\",", "md5", p->md5);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_otanotify_rsp(const bleproto_otanotify_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"errcode":xxx}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// errcode
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%d",
|
|
"errcode",
|
|
(int)p->errcode);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encjson_otadata_req(const bleproto_otadata_req_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
char *str = (char *)data;
|
|
// {"id": %d, "offset":%d, "maxsize":%d}
|
|
|
|
// {
|
|
offset = snprintf(str, size, "%s", "{");
|
|
|
|
// id
|
|
{
|
|
offset += snprintf(
|
|
&str[offset], size - offset, "\"%s\":%d, ", "id", (int)p->id);
|
|
}
|
|
// offset
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%d, ",
|
|
"offset",
|
|
(int)p->offset);
|
|
}
|
|
// maxsize
|
|
{
|
|
offset += snprintf(&str[offset],
|
|
size - offset,
|
|
"\"%s\":%d",
|
|
"maxsize",
|
|
(int)p->maxsize);
|
|
}
|
|
|
|
// }
|
|
offset += snprintf((&str[offset]), size - offset, "%s", "}");
|
|
|
|
/* dump output data */
|
|
BLEPROTO_T_D("data:%.*s", (int)offset, str);
|
|
|
|
return (offset);
|
|
}
|
|
|
|
int bleproto_encbin_otadata_rsp(const bleproto_otadata_rsp_t *p,
|
|
uint8_t data[BLEPROTO_APPDATA_DATA_MAX_SZ])
|
|
{
|
|
int offset = 0, size = BLEPROTO_APPDATA_DATA_MAX_SZ;
|
|
|
|
/* check param */
|
|
if (!p || !data) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* check buffer size */
|
|
if ((size_t)size < (sizeof(p->errcode) + sizeof(p->id) +
|
|
sizeof(p->offset) + sizeof(p->len) + p->len)) {
|
|
BLEPROTO_T_E("Buffer too small");
|
|
return -1;
|
|
}
|
|
|
|
/* serialize errcode (little-endian) */
|
|
data[offset++] = (uint8_t)(p->errcode & 0xFF);
|
|
data[offset++] = (uint8_t)((p->errcode >> 8) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->errcode >> 16) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->errcode >> 24) & 0xFF);
|
|
|
|
/* serialize id (little-endian) */
|
|
data[offset++] = (uint8_t)(p->id & 0xFF);
|
|
data[offset++] = (uint8_t)((p->id >> 8) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->id >> 16) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->id >> 24) & 0xFF);
|
|
|
|
/* serialize offset (little-endian) */
|
|
data[offset++] = (uint8_t)(p->offset & 0xFF);
|
|
data[offset++] = (uint8_t)((p->offset >> 8) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->offset >> 16) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->offset >> 24) & 0xFF);
|
|
|
|
/* serialize len (little-endian) */
|
|
data[offset++] = (uint8_t)(p->len & 0xFF);
|
|
data[offset++] = (uint8_t)((p->len >> 8) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->len >> 16) & 0xFF);
|
|
data[offset++] = (uint8_t)((p->len >> 24) & 0xFF);
|
|
|
|
/* serialize data */
|
|
if (p->len > 0 && p->len <= BLEPROTO_APPDATA_OTADATA_SZ) {
|
|
memcpy(&data[offset], p->data, p->len);
|
|
offset += p->len;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
|
|
int bleproto_decjson_deviceinfo_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_deviceinfo_req_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
//{"t":"xxxxxxxx",gmtoff:%d}
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// t
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.t",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
p->t = (uint64_t)strtoull(value_str, NULL, 10);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse t");
|
|
return -1;
|
|
}
|
|
|
|
// gmtoff
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.gmtoff",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->gmtoff = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse gmtoff");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_deviceinfo_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_deviceinfo_rsp_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"hwv":"%s","swv":"%s","prototype":%u, "hbcycle":%u,"longcon":%u}
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// hwv
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.hwv",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
snprintf(p->hwv, sizeof(p->hwv), "%s", value_str);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse hwv");
|
|
return -1;
|
|
}
|
|
|
|
// swv
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.swv",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
snprintf(p->swv, sizeof(p->swv), "%s", value_str);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse swv");
|
|
return -1;
|
|
}
|
|
|
|
// prototype
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.prototype",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->prototype = (uint8_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse prototype");
|
|
return -1;
|
|
}
|
|
|
|
// hbcycle
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.hbcycle",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->hbcycle = (uint32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse hbcycle");
|
|
return -1;
|
|
}
|
|
|
|
// longcon
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.longcon",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->longcon = (uint8_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse longcon");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_authsetup_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_authsetup_req_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"gwmac":"xxxx","devid":"xxxx","authcode":"xxxx"}
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
|
|
// gwmac
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.gwmac",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
int nr = proto_strhex_to_byte(value_str, p->gwmac, sizeof(p->gwmac));
|
|
if (nr != (int)sizeof(p->gwmac)) {
|
|
BLEPROTO_T_E("Error parse gwmac");
|
|
return -1;
|
|
}
|
|
} else {
|
|
BLEPROTO_T_E("Error parse gwmac");
|
|
return -1;
|
|
}
|
|
|
|
// devid
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.devid",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
snprintf(p->devid, sizeof(p->devid), "%s", value_str);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse devid");
|
|
return -1;
|
|
}
|
|
|
|
// authcode
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.authcode",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
snprintf(p->authcode, sizeof(p->authcode), "%s", value_str);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse authcode");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_authsetup_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_authsetup_rsp_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"errcode":xxx}
|
|
double v;
|
|
|
|
// errcode
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.errcode",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->errcode = (int32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_authdelete_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_authdelete_req_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"authcode": "xxxx"}
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
|
|
// authcode
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.authcode",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
snprintf(p->authcode, sizeof(p->authcode), "%s", value_str);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse authcode");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_authdelete_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_authdelete_rsp_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"gwmac":"xxxx","errcode":xxx}
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// gwmac
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.gwmac",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
int nr = proto_strhex_to_byte(value_str, p->gwmac, sizeof(p->gwmac));
|
|
if (nr != (int)sizeof(p->gwmac)) {
|
|
BLEPROTO_T_E("Error parse gwmac");
|
|
return -1;
|
|
}
|
|
} else {
|
|
BLEPROTO_T_E("Error parse gwmac");
|
|
return -1;
|
|
}
|
|
|
|
// errcode
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.errcode",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->errcode = (int32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_runcmd_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_runcmd_req_t *p)
|
|
{
|
|
int rc, i;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx" }
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// cmd_id
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.cmd_id",
|
|
/* v */ &v);
|
|
if (rc > 0) {
|
|
p->ycmd.cmd_id = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse cmd_id");
|
|
return -1;
|
|
}
|
|
|
|
// arg_int32
|
|
for (i = 0; i < YCMD_INT32_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_int32[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_int32[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_NUMBER) {
|
|
char vstr[32] = { 0 };
|
|
memcpy(vstr, ptr, UTILS_MIN(n, 31));
|
|
p->ycmd.arg_int32[p->ycmd.arg_int32_count] =
|
|
(int32_t)strtol(vstr, NULL, 10);
|
|
p->ycmd.arg_int32_count++;
|
|
}
|
|
}
|
|
|
|
// arg_string
|
|
for (i = 0; i < YCMD_STRING_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_string[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_string[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_STRING) {
|
|
if (n >= 2 && ptr[0] == '"' && ptr[n - 1] == '"') {
|
|
ptr++; // 跳过首引号
|
|
n -= 2; // 去掉首尾引号的长度
|
|
} else {
|
|
BLEPROTO_T_E("Error parse arg_string");
|
|
return -1;
|
|
}
|
|
memcpy(p->ycmd.arg_string[p->ycmd.arg_string_count],
|
|
ptr,
|
|
UTILS_MIN(n, YCMD_STRING_MAX_SIZE));
|
|
p->ycmd.arg_string_count++;
|
|
}
|
|
}
|
|
|
|
// arg_bytes
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.arg_bytes",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
// strhex to byte
|
|
rc = proto_strhex_to_byte(
|
|
value_str, p->ycmd.arg_bytes, sizeof(p->ycmd.arg_bytes));
|
|
if (rc >= 0) {
|
|
p->ycmd.arg_bytes_count = (uint16_t)rc;
|
|
}
|
|
}
|
|
|
|
// t
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.t",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
p->ycmd.t = (uint64_t)strtoull(value_str, NULL, 10);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse t");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_runcmd_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_runcmd_rsp_t *p)
|
|
{
|
|
int rc, i;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx" }
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// cmd_id
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.cmd_id",
|
|
/* v */ &v);
|
|
if (rc > 0) {
|
|
p->ycmd.cmd_id = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse cmd_id");
|
|
return -1;
|
|
}
|
|
|
|
// arg_int32
|
|
for (i = 0; i < YCMD_INT32_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_int32[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_int32[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_NUMBER) {
|
|
char vstr[32] = { 0 };
|
|
memcpy(vstr, ptr, UTILS_MIN(n, 31));
|
|
p->ycmd.arg_int32[p->ycmd.arg_int32_count] =
|
|
(int32_t)strtol(vstr, NULL, 10);
|
|
p->ycmd.arg_int32_count++;
|
|
}
|
|
}
|
|
|
|
// arg_string
|
|
for (i = 0; i < YCMD_STRING_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_string[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_string[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_STRING) {
|
|
if (n >= 2 && ptr[0] == '"' && ptr[n - 1] == '"') {
|
|
ptr++; // 跳过首引号
|
|
n -= 2; // 去掉首尾引号的长度
|
|
} else {
|
|
BLEPROTO_T_E("Error parse arg_string");
|
|
return -1;
|
|
}
|
|
memcpy(p->ycmd.arg_string[p->ycmd.arg_string_count],
|
|
ptr,
|
|
UTILS_MIN(n, YCMD_STRING_MAX_SIZE));
|
|
p->ycmd.arg_string_count++;
|
|
}
|
|
}
|
|
|
|
// arg_bytes
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.arg_bytes",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
// strhex to byte
|
|
rc = proto_strhex_to_byte(
|
|
value_str, p->ycmd.arg_bytes, sizeof(p->ycmd.arg_bytes));
|
|
if (rc >= 0) {
|
|
p->ycmd.arg_bytes_count = (uint16_t)rc;
|
|
}
|
|
}
|
|
|
|
// t
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.t",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
p->ycmd.t = (uint64_t)strtoull(value_str, NULL, 10);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse t");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_reportcmd_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_reportcmd_req_t *p)
|
|
{
|
|
int rc, i;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"cmd_id":xxxx,"arg_int32":[],"arg_string":[],"arg_bytes":"xxxx","t":"xxxxxxxx" }
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// cmd_id
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.cmd_id",
|
|
/* v */ &v);
|
|
if (rc > 0) {
|
|
p->ycmd.cmd_id = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse cmd_id");
|
|
return -1;
|
|
}
|
|
|
|
// arg_int32
|
|
for (i = 0; i < YCMD_INT32_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_int32[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_int32[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_NUMBER) {
|
|
char vstr[32] = { 0 };
|
|
memcpy(vstr, ptr, UTILS_MIN(n, 31));
|
|
p->ycmd.arg_int32[p->ycmd.arg_int32_count] =
|
|
(int32_t)strtol(vstr, NULL, 10);
|
|
p->ycmd.arg_int32_count++;
|
|
}
|
|
}
|
|
|
|
// arg_string
|
|
for (i = 0; i < YCMD_STRING_MAX_COUNT; i++) {
|
|
const char *ptr = NULL;
|
|
int n;
|
|
char key[sizeof("$.arg_string[65535]") + 1] = { 0 };
|
|
snprintf(key, sizeof(key), "$.arg_string[%d]", i);
|
|
if (mjson_find(str, (int)len, key, &ptr, &n) == MJSON_TOK_STRING) {
|
|
if (n >= 2 && ptr[0] == '"' && ptr[n - 1] == '"') {
|
|
ptr++; // 跳过首引号
|
|
n -= 2; // 去掉首尾引号的长度
|
|
} else {
|
|
BLEPROTO_T_E("Error parse arg_string");
|
|
return -1;
|
|
}
|
|
memcpy(p->ycmd.arg_string[p->ycmd.arg_string_count],
|
|
ptr,
|
|
UTILS_MIN(n, YCMD_STRING_MAX_SIZE));
|
|
p->ycmd.arg_string_count++;
|
|
}
|
|
}
|
|
|
|
// arg_bytes
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.arg_bytes",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
// strhex to byte
|
|
rc = proto_strhex_to_byte(
|
|
value_str, p->ycmd.arg_bytes, sizeof(p->ycmd.arg_bytes));
|
|
if (rc >= 0) {
|
|
p->ycmd.arg_bytes_count = (uint16_t)rc;
|
|
}
|
|
}
|
|
|
|
// t
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.t",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
p->ycmd.t = (uint64_t)strtoull(value_str, NULL, 10);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse t");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_reportcmd_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_reportcmd_rsp_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"errcode":xxx}
|
|
double v;
|
|
|
|
// errcode
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.errcode",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->errcode = (int32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_doaction_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_doaction_req_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"action":%d}
|
|
double v;
|
|
|
|
// action
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.action",
|
|
/* v */ &v);
|
|
if (rc > 0) {
|
|
p->action = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse action");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_doaction_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_doaction_rsp_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"errcode":xxx}
|
|
double v;
|
|
|
|
// errcode
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.errcode",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->errcode = (int32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_otanotify_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_otanotify_req_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"id": %d, "ver":"xxxx", "size":%d, "md5":"xxxxxxx"}
|
|
char value_str[BLEPROTO_APPDATA_DATA_MAX_SZ] = { 0 };
|
|
double v;
|
|
|
|
// id
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.id",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->id = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
// ver
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.ver",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
snprintf(p->version, sizeof(p->version), "%s", value_str);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse version");
|
|
return -1;
|
|
}
|
|
|
|
// size
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.size",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->size = (uint32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
// md5
|
|
rc = mjson_get_string(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.md5",
|
|
/* to */ value_str,
|
|
/* n */ (int)sizeof(value_str));
|
|
if (rc > 0) {
|
|
snprintf(p->md5, sizeof(p->md5), "%s", value_str);
|
|
} else {
|
|
BLEPROTO_T_E("Error parse md5");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_otanotify_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_otanotify_rsp_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"errcode":xxx}
|
|
double v;
|
|
|
|
// errcode
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.errcode",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->errcode = (int32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_decjson_otadata_req(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_otadata_req_t *p)
|
|
{
|
|
int rc;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !p) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
const char *str = (const char *)data;
|
|
/* dump input data */
|
|
BLEPROTO_T_D("data:%.*s", (int)len, str);
|
|
|
|
/* clear */
|
|
memset(p, 0, sizeof(*p));
|
|
|
|
// {"id": %d, "offset":%d, "maxsize":%d}
|
|
double v;
|
|
|
|
// id
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.id",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->id = (int)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse errcode");
|
|
return -1;
|
|
}
|
|
|
|
// offset
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.offset",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->offset = (int32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse offset");
|
|
return -1;
|
|
}
|
|
|
|
// maxsize
|
|
rc = mjson_get_number(
|
|
/* s */ str,
|
|
/* len */ (int)len,
|
|
/* path */ "$.maxsize",
|
|
/* result */ &v);
|
|
if (rc > 0) {
|
|
p->maxsize = (uint32_t)v;
|
|
} else {
|
|
BLEPROTO_T_E("Error parse maxsize");
|
|
return -1;
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
int bleproto_debin_otadata_rsp(const uint8_t * data,
|
|
uint16_t len,
|
|
bleproto_otadata_rsp_t *rsp)
|
|
{
|
|
int offset = 0;
|
|
|
|
/* check param */
|
|
if (!data || len == 0 || !rsp) {
|
|
BLEPROTO_T_E("Invalid parameters");
|
|
return -1;
|
|
}
|
|
|
|
/* check minimum buffer size (errcode + id + offset + len = 16 bytes) */
|
|
if (len < 16) {
|
|
BLEPROTO_T_E("Buffer too small");
|
|
return -1;
|
|
}
|
|
|
|
/* deserialize errcode (little-endian) */
|
|
rsp->errcode =
|
|
((int32_t)data[offset]) | ((int32_t)data[offset + 1] << 8) |
|
|
((int32_t)data[offset + 2] << 16) | ((int32_t)data[offset + 3] << 24);
|
|
offset += 4;
|
|
|
|
/* deserialize id (little-endian) */
|
|
rsp->id = ((uint32_t)data[offset]) | ((uint32_t)data[offset + 1] << 8) |
|
|
((uint32_t)data[offset + 2] << 16) |
|
|
((uint32_t)data[offset + 3] << 24);
|
|
offset += 4;
|
|
|
|
/* deserialize offset (little-endian) */
|
|
rsp->offset = ((uint32_t)data[offset]) |
|
|
((uint32_t)data[offset + 1] << 8) |
|
|
((uint32_t)data[offset + 2] << 16) |
|
|
((uint32_t)data[offset + 3] << 24);
|
|
offset += 4;
|
|
|
|
/* deserialize len (little-endian) */
|
|
rsp->len = ((uint32_t)data[offset]) | ((uint32_t)data[offset + 1] << 8) |
|
|
((uint32_t)data[offset + 2] << 16) |
|
|
((uint32_t)data[offset + 3] << 24);
|
|
offset += 4;
|
|
|
|
/* check data length validity */
|
|
if (rsp->len > BLEPROTO_APPDATA_OTADATA_SZ) {
|
|
BLEPROTO_T_E("Data length too large: %u", rsp->len);
|
|
return -1;
|
|
}
|
|
|
|
/* check remaining buffer size */
|
|
if (len < (offset + rsp->len)) {
|
|
BLEPROTO_T_E("Insufficient data for payload");
|
|
return -1;
|
|
}
|
|
|
|
/* deserialize data */
|
|
if (rsp->len > 0) {
|
|
memcpy(rsp->data, &data[offset], rsp->len);
|
|
offset += rsp->len;
|
|
}
|
|
|
|
return offset;
|
|
}
|
|
/****************************************************************************/
|
|
/* */
|
|
/* End of file. */
|
|
/* */
|
|
/****************************************************************************/
|