简体   繁体   中英

Writing to BLE peripheral from Swift

I am building an iOS Swift app that connects to a BLE device (Redbear Labs Duo) .

What works?

  1. I am able to initiate a scan for devices
  2. Connect to the device
  3. Collect services and characteristics of the BLE device - all good

Where is the problem?

  1. The BLE device (Redbear Labs Duo) also has a Wifi controller onboard and is capable of scanning for available networks. The documentation states that to scan for Wifi one must
    • connect to the primary service with UUID 3EC61400-89CD-49C3-A0D9-7A85669E901E
    • find the command characteristic with UUID 3EC61401-89CD-49C3-A0D9-7A85669E901E
    • send a 2 byte command [0x20, 0xA0] to the command characteristic
    • also set a 1 byte status indicator 0xB1 to the scan characteristic with UUID 3EC61402-89CD-49C3-A0D9-7A85669E901E

My code to do the above steps is as below..

func scanWifi() {
    print("[DEBUG] - Scanning for Wifi")

    let command:[UInt8] = [0x02, 0xA0]
    let commandData = NSData(bytes: command, length: command.count)
    BLE.sharedInstance.write(toCharacteristic: BLE.sharedInstance.RBL_CHAR_CMD_UUID, data: commandData, withType: .withResponse)

    let state:[UInt8] = [0xB1]
    let stateData = NSData(bytes: state, length: state.count)
    BLE.sharedInstance.write(toCharacteristic: BLE.sharedInstance.RBL_CHAR_SCN_UUID, data: stateData, withType: .withResponse)

    BLE.sharedInstance.read(fromCharacteristic: BLE.sharedInstance.RBL_CHAR_SCN_UUID)
}

Everything works... but... after writing the above data to the peripheral I was expecting the below method to get called - it never did.. what am I doing wrong?

func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil {

            print("[ERROR] Error updating value. \(error!.localizedDescription)")
            return
        }

        if characteristic.uuid.uuidString == RBL_CHAR_CMD_UUID {

            self.delegate?.bleDidReceiveData(data: characteristic.value as NSData?)
        }
    }

Update:

I set a bunch of debug statements and got the following output - from the below it is apparent that

  1. I am able to identify and connect to the right device and characteristics
  2. I am able to set the notification value appropriately

[DEBUG] Connecting to peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Connected to peripheral 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Did connect to peripheral
[DEBUG] Found service: 3EC61400-89CD-49C3-A0D9-7A85669E901E for peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Found characteristic: 3EC61401-89CD-49C3-A0D9-7A85669E901E for peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
[DEBUG] Found characteristic: 3EC61402-89CD-49C3-A0D9-7A85669E901E for peripheral: 547BC3C9-4823-431C-B888-A8F3E8C699F5
("3EC61402-89CD-49C3-A0D9-7A85669E901E", )
("3EC61401-89CD-49C3-A0D9-7A85669E901E", )
[DEBUG] didUpdateNotification state for characteristic CBCharacteristic: 0x1702a6c60, UUID = 3EC61401-89CD-49C3-A0D9-7A85669E901E, properties = 0x14, value = (null), notifying = YES on peripheral: CBPeripheral: 0x1740fba80, identifier = 547BC3C9-4823-431C-B888-A8F3E8C699F5, name = Duo-ZKBY, state = connected
[DEBUG] didUpdateNotification state for characteristic: CBCharacteristic: 0x1742a3c60, UUID = 3EC61402-89CD-49C3-A0D9-7A85669E901E, properties = 0x10, value = (null), notifying = YES on peripheral: CBPeripheral: 0x1740fba80, identifier = 547BC3C9-4823-431C-B888-A8F3E8C699F5, name = Duo-ZKBY, state = connected

Found the solution - posting here for the benefit of others.

Reading through the documentation provided by Redbear Labs, the key thing to note is that the Command characteristic only supports two types of properties - PROPERTY_WRITE_NO_RESPONSE | PROPERTY_NOTIFY PROPERTY_WRITE_NO_RESPONSE | PROPERTY_NOTIFY

Likewise the Scan characteristic only supports PROPERTY_NOTIFY

Also, to have the device scan all available Wifi - we should only write a 2 byte command [0x20, 0xA0] to the Command characteristic - code for the same is below

func scanWifi() {
        print("[DEBUG] - Scanning for Wifi")

        let command:[UInt8] = [0x02, 0xA0]
        let commandData = NSData(bytes: command, length: command.count)
        BLE.sharedInstance.writeTo(characteristic: BLE.sharedInstance.RBL_CHAR_CMD_UUID, data: commandData, withType: .withoutResponse)
}

Nothing needs to be written to the scan characteristic. When Wifi scanning begins, the Scan characteristic will send a notification with value 0xB1 to indicate start of scanning and then send a notification with value 0xB2 to indicate end of scanning.

The actual Wifi networks scanned will be sent via notifications on the command characteristic itself.

After calling

peripheral.writeValue(dataToWrite, for: char, type: .withResponse)

you need to call the read in this delegate function:

func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {

// Call your read functions here. 
     BLE.sharedInstance.read(fromCharacteristic: BLE.sharedInstance.RBL_CHAR_SCN_UUID)

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM