GJLightBlueTooth——一個輕量級的iOS藍芽開發庫

manofit發表於2019-03-03

從上家公司離職已經快半年了,與藍芽打了一年的交道,從小白一個到略知一二。最近在整理上一家公司做的一些專案,突發奇想,自己封裝一個藍芽庫,方便以後的使用。說幹就幹,如果需要專案程式碼,猛擊這裡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——一個輕量級的iOS藍芽開發庫
GJLightBlueTooth——一個輕量級的iOS藍芽開發庫

如果需要專案程式碼,猛擊這裡GJLightBlueTooth。如果有用,請賞顆小星星。

相關文章