CoreBluetooth開發簡單藍牙通訊發送十六進制指令

基於CoreBluetooth與藍牙4.0設備通訊非常方便,一句話總結就是中心-設備-服務-特徵,對應的關鍵API爲CBCentralManager-CBPeripheral-CBService-CBCharacteristic

可以通過LightBlue查看你的藍牙設備相關信息,也可以發送簡單指令。

CBCentralManager scanForPeripherals時需要注意兩點:

  1. APP需要後臺掃描withServices必須指定要掃描的服務的UUID,不傳系統會忽略不執行後臺掃描;
  2. 指定服務UUID無法找到設備,可能是芯片不支持在沒有連接的情況下掃描服務。如果確實需要就找芯片開發溝通,非必要就掃描所有設備再通過設備名稱等過濾連接後再找到服務。

設定特徵uuid爲:

private let Characteristic_UUID: String = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"

一、使用中心對象查找設備

centralManager = CBCentralManager.init(delegate: self, queue: .main)
func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .unknown:
            print("unknown")
        case .resetting:
            print("resetting")
        case .unsupported:
            print("unsupported")
        case .unauthorized:
            print("unauthorized")
        case .poweredOff:
            print("poweredOff")
        case .poweredOn:
            print("ok")
            central.scanForPeripherals(withServices: [], options: nil)
        }
    }

二、連接設備並查找服務

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        self.peripheral = peripheral
        // 根據設備名稱來過濾
        if ((peripheral.name != nil) && (peripheral.name?.hasPrefix("XXX"))!) {
            central.connect(peripheral, options: nil)
            central.stopScan();
        }
    }

三、獲取指定服務,查詢指定特徵

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        for service: CBService in peripheral.services! {
            print("設備中的服務有:\(service)")
        }
        //假設外設中只有一個服務
        let service = peripheral.services?.last
        //根據UUID尋找服務中的特徵
        peripheral.discoverCharacteristics([CBUUID.init(string: Characteristic_UUID)], for: service!)
    }

四、發現指定特徵

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        for characteristic: CBCharacteristic in service.characteristics! {
            print("外設中的特徵有:\(characteristic)")
        }
        self.characteristic = service.characteristics?.last
    }

五、向特徵發送十六進制指令

此特徵必須是約定的可寫入特徵(是否可寫入與設備的通訊協議一般都會定好,也可以通過LightBlue查看),指令通訊一般是十六進制指令,假設指令爲打開(0x2601),爲方便操作封裝一個十六進制字符串轉data的方法:

func dataWithHexString(hex: String) -> Data {
        var hex = hex
        var data = Data()
        while(hex.count > 0) {
            let subIndex = hex.index(hex.startIndex, offsetBy: 2)
            let c = String(hex[..<subIndex])
            hex = String(hex[subIndex...])
            var ch: UInt32 = 0
            Scanner(string: c).scanHexInt32(&ch)
            var char = UInt8(ch)
            data.append(&char, count: 1)
        }
        return data
    }

調用此方法:

if peripheral == nil || characteristic == nil {
    print("no peripheral connected")
    return;
}
let data = dataWithHexString(hex: "2601")
peripheral?.writeValue(data, for: characteristic!, type: CBCharacteristicWriteType.withoutResponse)

這裏需要注意,一般的寫入操作CBCharacteristicWriteType的類型是withResponse需要設備有響應,但是具體設備要看芯片設計,如果發現沒有成功嘗試使用withoutResponse

寫入有響應會回調:

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        print("寫入數據")
}

簡單的基於CoreBluetooth發送指令就介紹這些,如果涉及與藍牙設備大數據傳輸代碼和通訊協議相對較複雜,另外還需要注意發送數據的間隔,因爲限於載波大小如果單次數據較大可能會沒有響應,間隔參考值:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章