Search code examples
iosswiftarduinobluetooth-lowenergyadafruit

iOS Bluetooth Low Energy (BLE) not discovering TX characteristic


I am using an an arduino feather BLE board and trying to create an iOS app that can send data to the board over BLE. I can connect but I can't get access to the txCharacteristic

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    guard let characteristics = service.characteristics else {
        return
    }

    for characteristic in characteristics {
        if characteristic.properties.contains(.write) || characteristic.properties.contains(.writeWithoutResponse) {
            writableCharacteristic = characteristic
        }

        //            if(characteristic.uuid == CBUUID(string: "6e400002-b5a3-f393-e0a9-e50e24dcca9e"))
        //            {
        //                txCharacteristic = characteristic
        //            }

        var txUUID = CBUUID(string: "6e400002-b5a3-f393-e0a9-e50e24dcca9e")
        let temp = characteristic.uuid.uuidString;
        switch characteristic.uuid {
        case txUUID:
            txCharacteristic = characteristic;
            break;
        default:
            break;
        }

        peripheral.setNotifyValue(true, for: characteristic)
    }
}

This code works, but only discovers the following UUIDs:

temp    String  "00001532-1212-EFDE-1523-785FEABCD123"  
temp    String  "00001531-1212-EFDE-1523-785FEABCD123"  
temp    String  "00001534-1212-EFDE-1523-785FEABCD123"  

I have figured out that these UUID's are DFU UUIDs. How can I discover the txCharacteristic instead?


Added for more information how I am calling discoverCharacteristics():

extension SimpleBluetoothIO: CBPeripheralDelegate {
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    guard let services = peripheral.services else {
        return
    }

    targetService = services.first
    if let service = services.first {
        targetService = service
        peripheral.discoverCharacteristics(nil, for: service)
    }
}

Solution

  • I was able to figure this out, by reading info at this website: https://learn.adafruit.com/getting-started-with-the-nrf8001-bluefruit-le-breakout/adding-app-support

    Particularly this part (notice that UART is the service and TX and RX are characteristics of the service):

    UART Service UUID: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
    TX Characteristic UUID: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
    RX Characteristic UUID: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E
    

    So I needed to call peripheral.discoverServices() with the UART Service ID. In my example below self.serviceUUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"

    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        //peripheral.discoverServices(nil)
        //peripheral.discoverServices([CBUUID(string: "6e400001-b5a3-f393-e0a9-e50e24dcca9e")])
    
        // Disover peripheral with service UUID that was given to us during initialization (self.serviceUUID)
        peripheral.discoverServices([CBUUID(string: self.serviceUUID)])
    }
    

    Then in didDiscoverCharacteristicsFor service I needed to look for the TX Characteristic ID:

    // Did Discover Characteristics
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        guard let characteristics = service.characteristics else {
            return
        }
    
        for characteristic in characteristics {
            if characteristic.properties.contains(.write) || characteristic.properties.contains(.writeWithoutResponse) {
                writableCharacteristic = characteristic
            }
    
            // TX Characteristic UUID: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
            // https://learn.adafruit.com/getting-started-with-the-nrf8001-bluefruit-le-breakout/adding-app-support
            let txUUID = CBUUID(string: "6e400002-b5a3-f393-e0a9-e50e24dcca9e")
            switch characteristic.uuid {
            case txUUID:
                txCharacteristic = characteristic;
                break;
            default:
                break;
            }
    
            peripheral.setNotifyValue(true, for: characteristic)
        }
    }