從上家公司離職已經快半年了,與藍芽打了一年的交道,從小白一個到略知一二。最近在整理上一家公司做的一些專案,突發奇想,自己封裝一個藍芽庫,方便以後的使用。說幹就幹,如果需要專案程式碼,猛擊這裡GJLightBlueTooth。如果有用,請賞顆小星星。
GJLightBlueTooth架構
當初為了不在一個類裡面同時處理髮送與接收邏輯,也本著對外封閉的原則,為了給使用庫的人一個簡單的類,就設計了:
使用者 ——> GJLightBlueTooth ——> CoreBlueTooth ——> GJLightBlueTooth ——> 使用者
複製程式碼
這樣的架構
其中:
- GJLightBlueTooth:相當於一箇中介,架起來自頁面使用者的指令和系統CoreBlueTooth互動的橋樑,這裡的互動包括向藍芽裝置傳送指令和設定回撥。
- GJLBTCentralManager:所有與系統CoreBlueTooth的溝通都在這裡進行,這裡將指令發出去,也在這裡獲取回撥,通過block回傳。
另外,在Demo中,你還會看到MyBLETool這個類,這是為了將Demo專案中頁面與業務分離而單獨出來的一個類,可以理解為裝置類。為了我們不需要在具體的頁面中去設定回傳的block。
使用
在建立頁面後,你應該初始化GJLightBlueTooth藍芽工具:self.BLE = [[GJLightBlueTooth alloc] init]。
在獲取到Characteristic後,你應該根據實際讀寫的Characteristic匹配出裝置上的CBCharacteristic,儲存在本地,用於後面的寫與讀。
[self.BLE setBlockWhenDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
strongify(self);
for (CBCharacteristic *cha in service.characteristics){
if ([cha.UUID.UUIDString isEqualToString:CharacteristicUUIDWrite]){
self.writeCharacter = cha;
}
}
//[[NSNotificationCenter defaultCenter] postNotificationName:@"DiscoverCharacteristics" object:service];
}];
複製程式碼
掃描
[self.BLE scan]
複製程式碼
停止掃描
[self.BLE stopScan]
複製程式碼
連線裝置
[self.BLE connectWithPeripheral:peri]
複製程式碼
斷開連線
[self.BLE cancelConnectWithPeripheral:peri]
複製程式碼
讀取訊號量
[self.BLE readRSSIWithPeriperal:peri]
複製程式碼
傳送資料
[self.BLE sendDataToPeriperal:peri WriteCharacteristic:self.writeCharacter Command:command NSEncoding:encoding]
複製程式碼
這裡針對現在很多公司提出需要手機與裝置有心跳的要求,開啟了一個執行緒佇列。該佇列設定能夠同時存在的指令數為3。
NSData *cmdData = [[NSString stringWithFormat:@"%@",command] dataUsingEncoding:encoding];
NSOperation *opration = [NSBlockOperation blockOperationWithBlock:^{
[peripheral writeValue:cmdData
forCharacteristic:writeCharacteristics
type:CBCharacteristicWriteWithoutResponse];
/*
* you can set thread time interval.but the order while delay when there are a lot of orders.
*/
//[NSThread sleepForTimeInterval:SleepTimeGap];
}];
[self.writeQueue addOperation:opration];
複製程式碼
你也可以設定指令間隔時間,但是這樣會造成因心跳重新整理過快造成的延遲傳送。
注意
- 在新版本的iOS中,已經不允許通過peripheral.RSSI來獲取裝置的訊號量,必須在用[peripheral readRSSI]後,使用回撥來獲取。這就會造成在掃描到裝置時候無法顯示訊號量。所以專門建立了一個分類CBPeripheral+RSSI,利用Runtime來動態給peripheral建立了一個rssi屬性。
char nameKey;
- (void)setRssi:(NSNumber *)rssi{
objc_setAssociatedObject(self, &nameKey, rssi, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSNumber *)rssi{
return objc_getAssociatedObject(self, &nameKey);
}
複製程式碼
- 在MyBLETool中,需要設定GJLBTCentralManager回撥流,這裡為了防止迴圈引用,需要進行weak-strong dance。
weakify(self);
[self.BLE setBlockWhenDiscoverCharacteristics:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
strongify(self);
for (CBCharacteristic *cha in service.characteristics){
if ([cha.UUID.UUIDString isEqualToString:CharacteristicUUIDWrite]){
self.writeCharacter = cha;
}
}
//[[NSNotificationCenter defaultCenter] postNotificationName:@"DiscoverCharacteristics" object:service];
}];
複製程式碼
最後是兩張demo的效果
如果需要專案程式碼,猛擊這裡GJLightBlueTooth。如果有用,請賞顆小星星。