前言
笔者在之前的文章中记录了蓝牙的基础知识、蓝牙的iOS的基本使用、iOS 的与、或运算等内容。笔者在本文中将结合之前介绍的内容,以阿里云的生活物联网平台自定义的蓝牙BLE广播规范为文档,组装简单的蓝牙广播包,注意组装简单的广播包不是发送蓝牙数据包的组包。
笔者会以下图(阿里云物联网平台自定义的蓝牙广播数据包为例)整理下组装蓝牙广播包。
上边截图中已表明阿里自定义广播格式总共由(6+n)字节组成,不同广播类型,对应不同的n值和Content,上图中的octet 就是1个字节的意思。
(6+n)中的6指的一次是1个长度字节,1个Type字节,2个公司编码字节、1个VID(协议版本号)及Subtype字节,1个Function Mash 功能使能掩码字节。
(6+n)中的n就是我们要拼接的数据内容的二进制内容。
组装蓝牙广播包
组装前 4 个字节
我们先组装这个蓝牙广播包的前4个比较简单的字节。其中1个长度字节,1个Type字节,2个公司编码字节都是占据完整1个字节及其倍数的字节。所以比较简单。
结合笔者上文中谈到的 Byte 数组和二进制数据之间的转换,我们可以组装出如下二进制数据。
Byte bytes0123[] = {0x0F, 0xFF, 0x01, 0xA8};
NSData *data0123 = [[NSData alloc] initWithBytes:bytes0123 length:sizeof(bytes0123)];
NSLog(@"data0123:%@", data0123);
输出结果如下,可以看出来 0x0fff01a8 就是这个蓝牙广播包的前4个字节的二进制数据输出内容。
2021-01-16 19:44:55.678592+0800 WDemo[7429:1728544] data0123:{length = 4, bytes = 0x0fff01a8}
组装第5个字节
组装VID(协议版本号)及Subtype。
VID 的值为5,bit3-bit0为0b0101,16进制表示为0x05;
bit7-4 分别为Subtype类型,我们可以选择使用 (0b1011:蓝牙GATT类型,接入的BLE品类设备使用此类型)
对应的16进制的值为0x0b。
bit7-4 因为是高四位的bit为,所以Subtype的值需要使用左移运算左移4位。
bit3-bit0为第5个字节的低4位比特位,所以bit3-bit0部分的VID的值不需要变动,仍未0b0101,16进制为0x05;
综上第5个字节的值为 0x0b << 4 | 0xb0。
下边的是计算第5个字节二进制数据的相关代码。
Byte byte40 = 0x05;
Byte byte41 = 0x0b << 4;
Byte byte4Result = byte40 | byte41;
Byte bytes4[] = {byte4Result};
NSData *data4 = [[NSData alloc] initWithBytes:bytes4 length:sizeof(bytes4)];
NSLog(@"data4:%@", data4);
下边是第5个字节的二进制数据输出内容。
2021-01-16 19:57:08.738494+0800 WDemo[7435:1731347] data4:{length = 1, bytes = 0xb5}
组装第6个字节FMSK
我们可以结合上图,依次使用蓝牙版本BLE5.0以上,不支持OTA,后边其他的值先使用0,来组成第6个字节。 相应的二进制格式为0b0000 0011。相应的16进制格式值为0x03。 当然咱们平时项目中一般用到的是支持OTA,会进行安全认证,一机一密可能也会是根据特定设备去选择的,配网的标识也会是变动的。 综上,我们第六个字节可以使用0x03。
组装第7-n(下标为6-n)个字节
第7-n个字节我们可以组装设备的产品ID(产品Product ID,4字节,由生活物联网平台颁发。)和MAC地址。(蓝牙设备MAC地址,6字节,唯一设备地址,由生活物联网平台颁发。) 笔者这里就直接使用提供的示例值了,ProductID为0x00ef1000,Mac地址为0xb0b448d07882。 综上ProductID和MAC拼接后的值为 0x00ef1000 b448d07882。这部分涉及16进制字符串转16进制的内容。笔者会在下篇文章分享。
组装整个蓝牙广播包数据
我们结合上边上边分析的0-n个字节的值,使用如下代码组装出来 除了最后的数据内容 的蓝牙广播包的数据。
使用如下代码进行组装。
// 0-3字节 Length Type CID
Byte bytes0123[] = {0x0F, 0xFF, 0x01, 0xA8};
NSData *data0123 = [[NSData alloc] initWithBytes:bytes0123 length:sizeof(bytes0123)];
// 第5个字节(从0开始索引的第4个字节)VID和Subtype
Byte byte40 = 0x05;
Byte byte41 = 0x0b << 4;
Byte byte4Result = byte40 | byte41;
Byte bytes4[] = {byte4Result};
NSData *data4 = [[NSData alloc] initWithBytes:bytes4 length:sizeof(bytes4)];
// 第6个字节(从0开始索引的第5个字节)FMSK
Byte byte5 = 0x03;
Byte bytes5[] = {byte5};
NSData *data5 = [[NSData alloc] initWithBytes:bytes5 length:sizeof(bytes5)];
NSMutableData *mData = [NSMutableData data];
[mData appendData:data0123];
[mData appendData:data4];
[mData appendData:data5];
NSLog(@"%@", [mData copy]);
上述代码的输出结果如下
2021-01-16 21:35:11.484692+0800 WDemo[3296:217357] {length = 6, bytes = 0x0fff01a8b503}
至于本文没有记录的ProductID、MAC的数据内容的拼接部分,笔者会在下篇文章中分享。