前言
笔者在上一篇文章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的值的解析,笔者将在后续文章中进行分享。