在蓝牙开发中,经常会遇到蓝牙
Mac地址
(
物理地址
-->唯一标记)链接的问题,
对于
安卓
来说,可以通过Mac地址来链接,因为他们
可以获取
到外设的Mac地址。
对于
苹果
而言,是不可以通过Mac地址链接的,因为我们
无法获取
外设的Mac地址。
虽然苹果给我们提供了一个
外设的UUID
,但是这个UUID是通过
外设的Mac地址
和
手机的Mac地址
进行加密计算得来的。
换言之,
不同手机链接同一外设这个值是不同的
,所以这个值并不能取代Mac地址作为唯一标记,况且安卓是没有这个UUID的。
peripheral.identifier.UUIDString;
*
@property identifier
*
@discussion The unique, persistent identifier associated with the peer.
@property(
readonly
, nonatomic) NSUUID *identifier NS_AVAILABLE(10_13, 7_0);
/* Return a string description of the UUID, such as "E621E1F8-C36C-495A-93FC-0C247A3E6E5F" */
@property (readonly, copy) NSString *UUIDString;
那i
OS如何获取Mac地址
呢?
硬件工程师将Mac地址写到
厂商数据
中,然后我们获取(
扫描阶段
就可以获取到)
方案B
:(本质就是读取固定指令获取)
读取外设的
180A服务里的2A23特征值
,再去进行剪切和拼接来获取(必须
先链接上
外设)
详情参考:
https://www.jianshu.com/p/1d6a8fc8134f
但这个方案有
大弊端
:
1、就是我必须先链接上然后再去获取这个Mac地址,
太消耗成本
,且效率不高。
假如有很多设备的话,我必须一一验证,不是再断开,远没有在扫描阶段(扫描的过程是很快的,可以在短短几秒钟内就可以找到周围的上百台设备),确认是再链接高效。
2、这样会有
莫名其妙的问题
。
3、从
链接
的角度来讲有点
本末倒置
,本来我是用Mac地址来链接的,但现在变成了,先链接再获取Mac地址,验证是否正确。
4、仅限
某些设备
,如果你的蓝牙设备不支持这样获取,你需要跟硬件工程师沟通,说白了并
不通用
那
iOS如何链接
呢?
一般我们可以通过
名称、厂商数据
来链接。
当手机蓝牙(此地将手机蓝牙作为中心设备)扫描到外设(譬如手环之类的)后,会进入这个方法
* @method centralManager:didDiscoverPeripheral:advertisementData:RSSI:
* @param central The central manager providing this update.
* @param peripheral A <code>CBPeripheral</code> object.
* @param advertisementData A dictionary containing any advertisement and scan response data.
* @param RSSI The current RSSI of <i>peripheral</i>, in dBm. A value of <code>127</code> is reserved and indicates the RSSI
* was not available.
* @discussion This method is invoked while scanning, upon the discovery of <i>peripheral</i> by <i>central</i>. A discovered peripheral must
* be retained in order to use it; otherwise, it is assumed to not be of interest and will be cleaned up by the central manager. For
* a list of <i>advertisementData</i> keys, see {@link CBAdvertisementDataLocalNameKey} and other similar constants.
* @seealso CBAdvertisementData.h
- (
void
)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,
id
> *)advertisementData RSSI:(NSNumber *)RSSI;
名称、厂商数据可以从
advertisementData
(广告数据)中读取
* @constant CBAdvertisementDataLocalNameKey
* @discussion A <code>NSString</code> containing the local name of a peripheral.
CB_EXTERN NSString
*
const
CBAdvertisementDataLocalNameKey;
* @constant CBAdvertisementDataManufacturerDataKey
* @discussion A <code>NSData</code> object containing the manufacturer data of a peripheral.
CB_EXTERN NSString *
const
CBAdvertisementDataManufacturerDataKey;
//advertisementData中可以发送的数据有约定 如下
17 /*
18 对应设置NSString类型的广播名
19 NSString *const CBAdvertisementDataLocalNameKey;
20 外设制造商的NSData数据
21 NSString *const CBAdvertisementDataManufacturerDataKey;
22 外设制造商的CBUUID数据
23 NSString *const CBAdvertisementDataServiceDataKey;
24 服务的UUID与其对应的服务数据字典数组
25 NSString *const CBAdvertisementDataServiceUUIDsKey;
26 附加服务的UUID数组
27 NSString *const CBAdvertisementDataOverflowServiceUUIDsKey;
28 外设的发送功率 NSNumber类型
29 NSString *const CBAdvertisementDataTxPowerLevelKey;
30 外设是否可以连接
31 NSString *const CBAdvertisementDataIsConnectable;
32 服务的UUID数组
33 NSString *const CBAdvertisementDataSolicitedServiceUUIDsKey;
34 */
具体如何保证
唯一性
,这个就需要和蓝牙硬件工程师约定了。
1
、如果名称是唯一的,我们就可以用名称来约定唯一性。
2
、如果名称相同,又要确定唯一性,那我们就需要通过厂商数据来约定了。
具体这个规则要怎么来约定唯一性,就靠彼此约定了,这个规则随意,只要彼此双方约定好就可以。
比较好的
链接方案
就是,
苹果、安卓、硬件
大家约定好一个
规则
,不论是通过
名称或者厂商数据
都可以确定
唯一性通用性
。