/** * @file ble_proto.h * @brief BLE-网关通信协议 V1.2 序列化 / 反序列化接口 * * 数据包结构(Big Endian): * [Cmd:2][Reserved:4] * [gateway_int_cnt:1][gateway_int32[]:4*N] * [device_int_len:2][device_str_len:2][device_bytes_len:2] * [Payload: int_data | str_data | bytes_data] * [CRC16:2] * * 当前协议头(固定 6 字节):[Cmd:2][Reserved:4] * (说明:本文件早期 V1.2 草案曾在 Cmd 后加入 8 字节时间戳 t, * 现设备侧不再使用,已从线格式中彻底移除。) * * V1.1 变更(相对 V1.0): * - 删除 Magic、Version、Seq 字段 * - 新增 Reserved(uint32,固定填 0) * - Cmd 移至偏移 0 * - gateway_int_cnt 由 uint16 调整为 uint8 * - CRC 计算范围:Cmd ~ Payload 末尾(整个包除 CRC 字段本身) */ #ifndef BLE_PROTO_H #define BLE_PROTO_H #include #include #ifdef __cplusplus extern "C" { #endif /* ----------------------------------------------------------------------- * 协议常量 * --------------------------------------------------------------------- */ /** Header 固定长度:Cmd(2) + Reserved(4) = 6 Bytes */ #define BLE_PROTO_HEADER_LEN 6u /** gateway_int_cnt 字段长度(uint8) */ #define BLE_PROTO_GW_CNT_LEN 1u /** Device Parameter 固定长度:3 x uint16 = 6 Bytes */ #define BLE_PROTO_DEV_PARAM_LEN 6u /** CRC16 字段长度 */ #define BLE_PROTO_CRC_LEN 2u /** 最大 Gateway int32 参数个数(防御性上限,可按需修改) */ #define BLE_PROTO_GW_INT_MAX 16u /** 最大 Payload 总长度(按实际业务调整) */ #define BLE_PROTO_PAYLOAD_MAX 2048u /* ----------------------------------------------------------------------- * 报文数据包(解包后的逻辑结构) * --------------------------------------------------------------------- */ typedef struct { /* ----- Protocol Header ----- */ uint16_t cmd; /**< 协议命令(上报、控制、应答、OTA等) */ uint32_t reserved; /**< 保留字段,发送端固定填 0 */ /* ----- Gateway Parameter ----- */ uint8_t gateway_int_cnt; /**< Gateway int32 参数个数 */ int32_t gateway_int[BLE_PROTO_GW_INT_MAX]; /**< Gateway int32 参数列表 */ /* ----- Device Parameter ----- */ uint16_t device_int_len; /**< Payload 中 int 数据字节数(必须是 4 的整数倍) */ uint16_t device_str_len; /**< Payload 中 string 数据字节数(不含 '\0') */ uint16_t device_bytes_len; /**< Payload 中 bytes 数据字节数 */ /* ----- Payload 数据指针(指向外部 buffer,不拥有所有权) ----- */ const int32_t *int_data; /**< Device Int 数据(pack 输入为主机序 int32 数组,ble_proto_pack 内部逐元素 put_be32 转 BE;unpack 输出为 buf 内原始 BE 字节,调用方须用 get_be32 读取,不可直接解引用) */ const char *str_data; /**< Device String 数据(不含 '\0') */ const uint8_t *bytes_data; /**< Device Bytes 数据 */ } ble_proto_packet_t; /* ----------------------------------------------------------------------- * 错误码 * --------------------------------------------------------------------- */ typedef enum { BLE_PROTO_OK = 0, BLE_PROTO_ERR_NULL = -1, /**< 空指针 */ BLE_PROTO_ERR_BUF_SMALL = -2, /**< 输出缓冲区不足 */ BLE_PROTO_ERR_CRC = -3, /**< CRC16 校验失败 */ BLE_PROTO_ERR_LEN = -4, /**< 长度字段非法 / 包长不足 */ BLE_PROTO_ERR_GW_CNT = -5, /**< gateway_int_cnt 超出上限 */ BLE_PROTO_ERR_INT_ALIGN = -6, /**< device_int_len 非 4 倍数 */ } ble_proto_err_t; /* ----------------------------------------------------------------------- * 接口 * --------------------------------------------------------------------- */ /** * @brief 序列化:将逻辑数据包打包成字节流 * * @param[in] pkt 逻辑数据包(reserved 字段被忽略,固定填 0) * @param[out] buf 输出缓冲区 * @param[in] buf_size 缓冲区大小(字节) * @return 打包后实际字节数(>0),或 ble_proto_err_t 负值 */ int ble_proto_pack(const ble_proto_packet_t *pkt, uint8_t *buf, size_t buf_size); /** * @brief 反序列化:将字节流解析为逻辑数据包 * * @note pkt->int_data / str_data / bytes_data 指向 buf 内部,不复制数据。 * buf 的生命周期必须长于 pkt 的使用期。 * @note pkt->reserved 的值被读出但不做校验,接收端可直接忽略。 * * @param[in] buf 输入字节流 * @param[in] len 字节流长度 * @param[out] pkt 解析结果 * @return BLE_PROTO_OK,或 ble_proto_err_t 负值 */ int ble_proto_unpack(const uint8_t *buf, size_t len, ble_proto_packet_t *pkt); /** * @brief 计算 CRC16(MODBUS 变体,多项式 0x8005,初值 0xFFFF) * * @param[in] data 数据起始地址 * @param[in] len 数据字节数 * @return CRC16 值 */ uint16_t ble_proto_crc16(const uint8_t *data, size_t len); #ifdef __cplusplus } #endif #endif /* BLE_PROTO_H */