C 语言示例
用于解析形如:
+SCN:{macAddr},{rssi},{advDataHex}
的蓝牙广播包字符串,并支持按指定类型提取广播数据(如设备名、厂商数据、UUID 等)。
一、输入格式说明
假设串口/协议收到的字符串为:
+SCN:AABBCCDDEEFF,-65,0201060A094C6564546573743031
含义:
macAddr:AABBCCDDEEFF
rssi:-65
advDataHex:0201060A094C6564546573743031(十六进制)
二、广播数据类型定义(BLE AD Type)
typedef enum {
BLE_AD_TYPE_FLAGS = 0x01,
BLE_AD_TYPE_NAME_SHORT = 0x08,
BLE_AD_TYPE_NAME_COMPLETE = 0x09,
BLE_AD_TYPE_MANUFACTURER_DATA = 0xFF,
BLE_AD_TYPE_SERVICE_UUID_16 = 0x02,
BLE_AD_TYPE_SERVICE_UUID_128 = 0x06,
} ble_ad_type_t;
三、解析结构体
typedef struct {
char mac[18];
int rssi;
uint8_t adv_data[31];
uint8_t adv_len;
} ble_adv_packet_t;
四、主解析函数
1️⃣ 解析 +SCN: 字符串
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
int parse_ble_scan_rsp(const char *str, ble_adv_packet_t *pkt)
{
if (!str || !pkt) return -1;
const char *prefix = "+SCN:";
if (strncmp(str, prefix, strlen(prefix)) != 0)
return -1;
str += strlen(prefix);
// MAC
if (sscanf(str, "%17[^,],%d,", pkt->mac, &pkt->rssi) != 2)
return -1;
// 跳过 MAC 和 RSSI
const char *hex = strchr(str, ',');
if (!hex) return -1;
hex++; // 指向 advDataHex
// Hex -> bin
pkt->adv_len = 0;
for (int i = 0; hex[i] && hex[i + 1]; i += 2) {
char byte[3] = { hex[i], hex[i + 1], '\0' };
pkt->adv_data[pkt->adv_len++] = (uint8_t)strtol(byte, NULL, 16);
}
return 0;
}
2️⃣ 按类型解析广播数据(AD Structure)
int ble_get_adv_field(
const ble_adv_packet_t *pkt,
ble_ad_type_t type,
uint8_t *out_buf,
uint8_t out_buf_len)
{
if (!pkt || !out_buf) return -1;
uint8_t i = 0;
while (i < pkt->adv_len) {
uint8_t len = pkt->adv_data[i];
if (len == 0 || i + len >= pkt->adv_len)
break;
uint8_t ad_type = pkt->adv_data[i + 1];
if (ad_type == type) {
uint8_t data_len = len - 1;
if (data_len > out_buf_len)
data_len = out_buf_len;
memcpy(out_buf, &pkt->adv_data[i + 2], data_len);
return data_len;
}
i += len + 1;
}
return -1;
}
五、使用示例
int main(void)
{
const char *rx = "+SCN:AABBCCDDEEFF,-65,0201060A094C6564546573743031";
ble_adv_packet_t pkt;
if (parse_ble_scan_rsp(rx, &pkt) != 0) {
printf("Parse failed\n");
return -1;
}
printf("MAC: %s\n", pkt.mac);
printf("RSSI: %d\n", pkt.rssi);
uint8_t name[32] = {0};
int ret = ble_get_adv_field(&pkt, BLE_AD_TYPE_NAME_COMPLETE, name, sizeof(name));
if (ret > 0) {
printf("Device Name: %s\n", name);
}
return 0;
}
六、输出结果
MAC: AABBCCDDEEFF
RSSI: -65
Device Name: LedTest01