蓝牙通讯中有两个重要角色:中心设备和外围设备。外围设备提供中心设备需要的数据(某米手环记录的步数),中心设备读取数据并处理(某米运动显示步数)。
中心设备和外围设备
直接点就是外围设备提供数据(手环记录步数)给中心设备处理数据(app拿到数据后进行显示)-
外围设备数据结构
一个设备包含一个以上服务(service),一个服务又可以包含一个以上的特征(characteristic)。- 服务:完成一项功能所需相关数据的集合。
- 特征:记录具体的某一项数据。
手环记录步数就是手环提供的一个服务,但该服务也不仅是记录步数,还有时间或运动距离等,这些就分别是一个特征。
如何连接
外围设备会发送广告包,广告包中包含一小部分服务,其中就有包含外围设备信息的服务,根据设备信息确定我们需要的外围设备。中心设备扫描到需要的外围设备后发起连接,成功后即可对数据进行读写。
UUID
- 通常不会由我们自定义,一般通过查询后读取。
- 一般在编写外围设备角色时,定义设备(NSUUID)、服务(CBUUID)或特征(CBUUID)的唯一标识符时用到。
- 编写中心设备角色时,需要根据指定搜索设备(NSUUID)或服务(CBUUID)时也会用到。
- UUID 每个字符用的是16进制(0 ~ 9和A ~ F,4位二进制)表示。
NSUUID
NSUUID
采用RFC 4122 version 4
协议形成的128位唯一标识字符串。这里用于唯一标识蓝牙设备,意味着每个蓝牙模块都是唯一的。
// 一般用法
// 生成一个随机128位唯一标识
NSUUID *uu = [NSUUID UUID];
// 读取该UUID
NSString *str = uu.UUIDString;
// 两个UUID的比较
// 使用 == 不能保证一定相同
if UUID1 isEqueal: UUID2 {}
CBUUID
CBUUID
也是一个128位唯一标识,用于唯一标识蓝牙的服务、特征或特征的描述符(descriptor)。这里使用的是蓝牙技术联盟(Bluetooth SIG)
制定的规范。
UUID表现为16位或32位的短整型,它和128位长整型标识的转换关系如下:
/*
* Bluetooth_Base_UUID = 0x00000000—0000—1000—8000—00805F9B34FB
* 左移
* 128位UUID = 16位UUID * 2^96 + Bluetooth_Base_UUID
* 结果:0x 0000xxxx—0000—1000—8000—00805F9B34FB
* 128位UUID = 32位UUID * 2^96 + BIuetooth_Base_UUID
* 结果:0x xxxxxxxx—0000—1000—8000—00805F9B34FB
*/
蓝牙技术联盟已经定义好了许多服务的16位标识,比如0x180A
表示设备信息服务,它的descriptor
为Device Information
。CBUUID
类提供了转换方法:
// 参数为符合规范的16位,32位或128位字符串
CBUUID *uu = [CBUUID UUIDWithString:@"0x180A"];
NSString *str = uu.UUIDString;
如果需要生成自定义的UUID,可以传入长度为4或8的字符串。必须长度一定否则UUID为nil。
CBUUID *uu = [CBUUID UUIDWithString:@"abcd"];
或者可以通过终端命令uuidgen
生成一个128位的字符串。
CBUUID *uu = [CBUUID UUIDWithString:@"45376F2E-F9E3-4B91-A297-005BDF2FBB91"];
常用服务的UUID:
http://blog.csdn.net/zjy323520/article/details/52164025
http://blog.csdn.net/zf_c_cqupt/article/details/52177723
开发中出现的一些常量
CBManagerState
蓝牙状态信息
创建设备对象后的回调,确定设备是否支持蓝牙以及是否可用
适用CBCentralManager和CBPeripheralManager
* @enum CBManagerState
*
* @constant CBManagerStateUnknown 未知状态,立即更新.
* @constant CBManagerStateResetting 重置蓝牙,链接暂时断开,立即更新.
* @constant CBManagerStateUnsupported 设备不支持蓝牙4.0 .
* @constant CBManagerStateUnauthorized 应用尚未被授权.
* @constant CBManagerStatePoweredOff 蓝牙处于关闭状态.
* @constant CBManagerStatePoweredOn 蓝牙处于开启可用状态.
CBCharacteristicProperties特征属性
告知如何使用特征的值(value)或如何访问描述符(descriptor)。
Specifying the read and write properties for a characteristic’s value lets the client (a central) know what read and write permissions of the characteristic’s value are set. --- Apple Developer Documentation
设定特征的值的读写**属性**是为了**告知**中心设备特征有哪些读写属性。
* @enum CBCharacteristicProperties
*
* @constant CBCharacteristicPropertyBroadcast
"特征的值通过特征的描述符被广播出去,但是使用init初始化的特征不能使用"
* @constant CBCharacteristicPropertyRead
"可读"
* @constant CBCharacteristicPropertyWriteWithoutResponse
"可写,外围设备不会回传写入是否成功"
* @constant CBCharacteristicPropertyWrite
"可写,如写入失败,CBPeripheral调用相应代理返回错误"
* @constant CBCharacteristicPropertyNotify
"可订阅,如中心设备未收到通知不会将error告知外围设备"
* @constant CBCharacteristicPropertyIndicate
"可订阅,中心设备未收到通知会告知外围设备,然后CBCentral调用相应代理"
* @constant CBCharacteristicPropertyAuthenticatedSignedWrites
"受信任设备可写,写入不成功时不会回传错误"
* @constant CBCharacteristicPropertyExtendedProperties
"可以在特征的属性描述符中添加额外的特征属性,但是使用init初始化的特征不能使用"
* @constant CBCharacteristicPropertyNotifyEncryptionRequired
"只能订阅受信任设备广播的特征的值,如中心设备未收到通知不会将error告知外围设备"
* @constant CBCharacteristicPropertyIndicateEncryptionRequired
"只能订阅受信任设备广播的特征的值,会告知外围设备是否收到通知"
CBAttributePermissions
决定特征的值得读写和加密权限
Specifying the read and write permissions for a characteristic’s value actually sets the permissions for the server (the peripheral) to allow the type of read or write specified by the characteristic’s properties --- Apple Developer Documentation
设定特征的值的读写**权限**才决定了能否进行读写操作。
* @enum CBAttributePermissions
*
* CBAttributePermissionsReadable 只读.
* CBAttributePermissionsWriteable 只写.
* CBAttributePermissionsReadEncryptionRequired 受信任设备可读
* CBAttributePermissionsWriteEncryptionRequired 受信任设备可写