蓝牙模块主机扫描数据解析

Viewed 22

python环境

正则表达式

pattern = r'^\+SCN:([A-F0-9]{12}),(-?\d+),([0-9A-F]+)\r\n\0$'
        """
        解析以+SCN:开头,以\r\n\0结尾的字符串,提取三个参数
        
        参数:
            input_string (str): 要解析的字符串
            
        返回:
            tuple: 包含三个提取参数的元组 (param1, param2, param3)
            如果解析失败,返回 (None, None, None)
        """
        # 定义正则表达式模式
        pattern = r'^\+SCN:([A-F0-9]{12}),(-?\d+),([0-9A-F]+)\r\n\0$'
        
        # 尝试匹配模式
        match = re.match(pattern, input_string)
        if match:
            # 提取三个参数
            param1 = match.group(1)  # 12位大写字母和数字组合
            param2 = int(match.group(2))  # 整数(可能为负数)
            param3 = match.group(3)  # 十六进制字符串
            return param1, param2, param3
        else:
            return None, None, None
1 Answers

C 语言示例

用于解析形如:

+SCN:{macAddr},{rssi},{advDataHex}

的蓝牙广播包字符串,并支持按指定类型提取广播数据(如设备名、厂商数据、UUID 等)。


一、输入格式说明

假设串口/协议收到的字符串为:

+SCN:AABBCCDDEEFF,-65,0201060A094C6564546573743031

含义:

  • macAddrAABBCCDDEEFF
  • rssi-65
  • advDataHex0201060A094C6564546573743031(十六进制)

二、广播数据类型定义(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

Related