在藍牙開發中,經常會遇到藍牙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;
那iOS如何獲取Mac地址呢?
方案A:
硬件工程師將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、如果名稱相同,又要確定唯一性,那我們就需要通過廠商數據來約定了。
具體這個規則要怎么來約定唯一性,就靠彼此約定了,這個規則隨意,只要彼此雙方約定好就可以。
綜上:
比較好的鏈接方案就是,蘋果、安卓、硬件大家約定好一個規則,不論是通過名稱或者廠商數據都可以確定唯一性通用性。