iOS 解析蓝牙广播包基础

3,275 阅读2分钟

前言

笔者在上一篇文章iOS 组装蓝牙广播包基础记录了蓝牙组装蓝牙广播包的的基础内容。笔者在本文中将继续补充上篇提到的组装ProductID及MAC部分广播包及解析蓝牙广播包的内容。

组装蓝牙广播包

组装第7-n(下标为6-n)个字节

第7-n个字节我们可以组装设备的产品ID(产品Product ID,4字节,由生活物联网平台颁发。)和MAC地址。(蓝牙设备MAC地址,6字节,唯一设备地址,由生活物联网平台颁发。) 笔者这里就直接使用提供的示例值了,ProductID为0x00ef1000,Mac地址为0xb0b448d07882。 综上ProductID和MAC拼接后的值为 0x00ef1000 b448d07882。这部分涉及16进制字符串转16进制的内容。笔者这里学习的iOS NSData 和十六进制字符串之间的相互转换写了如下的一个16进制字符串转16进制二进制的方法。

//! 16进制字符串转的16进制NSData
- (NSData *)dataOfHexString:(NSString *)hexStr {
    
    NSInteger hexLength = [hexStr length];
    if (!hexStr || hexLength == 0) {
        return [NSData data];
    }
    
    hexLength = [hexStr length];
    
    NSMutableData *mHexData = [NSMutableData data];
    NSRange range;
    
    if (hexLength % 2 == 0) {
        range = NSMakeRange(0, 2);
    } else {
        // 奇数情况 给低位数值预留出2的倍数
        range = NSMakeRange(0, 1);
    }
    
    for (NSInteger i = range.location; i < hexLength; i += 2) {
        unsigned int anInt;
        NSString *hexCharStr = [hexStr substringWithRange:range];
        if ([hexCharStr isEqualToString:@"0x"]) {
            // 去除0x
            range.location += range.length;
            range.length = 2;
            continue;
        }
        NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
        // Scans for an unsigned value from a hexadecimal representation, returning a found value by reference.
        [scanner scanHexInt:&anInt];
        NSData *data = [[NSData alloc] initWithBytes:&anInt length:1];
        [mHexData appendData:data];
        range.location += range.length;
        range.length = 2;
    }
    
    return [mHexData copy];
}

使用上述方法,我们可以调用如下代码ProductID和MAC的16进制形式的NSData值。

    NSData *productIDData = [self dataOfHexString:@"0x00ef1000"];
    NSData *macData = [self dataOfHexString:@"0xb448d07882"];

结合笔者上篇iOS 组装蓝牙广播包基础 记录的内容,我们可以封装出来蓝牙广播包为:

2021-01-17 21:15:33.602065+0800 WDemo[9420:919097] {length = 15, bytes = 0x0fff01a8b50300ef1000b448d07882}

解析蓝牙广播包

解析长度的值
	// 0字节 Length
    NSData *data0 = [data subdataWithRange:NSMakeRange(0, 1)];
    Byte *byte0 = (Byte *)data0.bytes;
    UInt8 length = (UInt8)byte0[0];
    NSLog(@"length:%hhu", length);

笔者会取出蓝牙广播包的第1个字节,然后取到相应的Byte值,最终得到Length的值为15。上述代码的输出内容为

2021-01-17 21:36:51.526314+0800 WDemo[9919:967052] length:15
解析Type的值
	// 1字节 Type
    NSData *data1 = [data subdataWithRange:NSMakeRange(1, 1)];
    Byte *byte1 = (Byte *)data1.bytes;
    UInt8 type = (UInt8)byte1[0];
    NSLog(@"type:%hhu", type);

笔者会取出蓝牙广播包的第2个字节,然后取到相应的Byte值,最终得到Type的值为255。

上述代码的输出内容为

2021-01-17 21:36:51.526583+0800 WDemo[9919:967052] type:255
解析CID值
// 2、3 字节 CID 
这部分内容是16进制转16进制字符串的内容,笔者会和后边的ProductID即MAC部分一起放在后续文章分享。
解析VID及subType的值

笔者会取出蓝牙广播包的第5个字节,然后取到相应的Byte值,结合使用与操作符、及vid需要右移操作,得到vid的值为11,并且得到subType的值为5。

	 // 第5个字节(从0开始索引的第4个字节)VID和Subtype
    NSData *data5 = [data subdataWithRange:NSMakeRange(4, 1)];
    Byte *byte5 = (Byte *)data5.bytes;
    UInt8 vid = byte5[0] & 0xF0;
    vid = vid >> 4;
    UInt8 subType = byte5[0] & 0x0F;
    NSLog(@"vid:%hhu", vid);
    NSLog(@"subType:%hhu", subType);

上述代码的输出内容为

2021-01-17 21:36:54.057641+0800 WDemo[9919:967052] vid:11
2021-01-17 21:36:54.057827+0800 WDemo[9919:967052] subType:5

剩余的第6个字节FMSK及CID、ProductID、MAC的值的解析,笔者将在后续文章中进行分享。

参考学习网址

Core Bluetooth Programming Guide
阿里云的生活物联网平台自定义的蓝牙BLE广播规范