Dmitry
Dmitry

Reputation: 2168

Core Bluetooth usage for HM-10 arduino : failure reading data

I have set a basic Arduino project with HM-10 BLE module for sending some data as String (actually some temperature mesurements) and I see it works if I use an iOS app like BluetoothForArduino. I want to get this data using macOs : for this I've implemented the following snippet based on AsyncBluetooth library:

func test() async throws {
    let centralManager = CentralManager()

    try await centralManager.waitUntilReady()

    let serviceUUID = CBUUID(string: "FFE0")
    let characteristicsUUID = CBUUID(string: "FFE1")
    let deviceName = "HMSoft"
    

    let scanDataStream = try await centralManager.scanForPeripherals(withServices: [serviceUUID])
    if let foundDevice = await scanDataStream.first(
        where: { $0.peripheral.name?.hasPrefix(deviceName) == true }
    ) {
        await centralManager.stopScan()
        let peripheral = foundDevice.peripheral
        
        print("Found device : \(peripheral.name ?? "no name"), RSSI = \(foundDevice.rssi)")

        print("Connecting...")
        try await centralManager.connect(peripheral)
        print("Ok")
        
        try await peripheral.discoverServices(nil)
        
        if let service = peripheral.discoveredServices?.first {
            try await peripheral.discoverCharacteristics(nil, for: service)
            service.discoveredCharacteristics?.forEach{
                print($0)
            }
            
            print("Services UUIDs discovered : \(service.uuid)")
            if let characteristics = service.discoveredCharacteristics?
                .first(where: { $0.uuid == characteristicsUUID }) {
                    print("Characteristics UUIDs discovered : \(characteristics.uuid)")
                
                    try await peripheral.setNotifyValue(
                        true,
                        forCharacteristicWithCBUUID: characteristicsUUID,
                        ofServiceWithCBUUID : serviceUUID
                    )
                    print("Notifications enabled")

                
//                    try await peripheral.writeValue(
//                        "s".data(using: .ascii)!,
//                        for: characteristics,
//                        type: .withoutResponse
//                    )
                                    
                    if let data: Data = try await peripheral.readValue(
                        forCharacteristicWithCBUUID: characteristicsUUID,
                        ofServiceWithCBUUID: serviceUUID
                    ) {
                        data.forEach {
                            print($0)
                        }
                    }
                }
        }
                        
        print("Disconnecting...")
        try await centralManager.cancelPeripheralConnection(foundDevice.peripheral)
        print("Ok")
    }
}

try await test()

The issue is that I always get the same 6 bytes from the device (at the same time I get the service and it's characteristics in the right way). What am I doing wrong? Can anybody share a snippet to establish a simple echo example with Core Bluetooth?

Upvotes: 0

Views: 37

Answers (1)

Dmitry
Dmitry

Reputation: 2168

The final solution looks as follows :

func test() async throws {
    let centralManager = CentralManager()

    try await centralManager.waitUntilReady()

    let serviceUUID = CBUUID(string: "FFE0")
    let characteristicsUUID = CBUUID(string: "FFE1")
    let deviceName = "HMSoft"
    
    var cancellables = Set<AnyCancellable>()
    
    let scanDataStream = try await centralManager.scanForPeripherals(withServices: [serviceUUID])
    if let foundDevice = await scanDataStream.first(
        where: { $0.peripheral.name?.hasPrefix(deviceName) == true }
    ) {
        await centralManager.stopScan()
        let peripheral = foundDevice.peripheral
        
        print("Found device : \(peripheral.name ?? "no name"), RSSI = \(foundDevice.rssi)")

        print("Connecting...")
        try await centralManager.connect(peripheral)
        print("Ok")
        
        
        try await peripheral.discoverServices(nil)
        
        if let service = peripheral.discoveredServices?.first {
            try await peripheral.discoverCharacteristics(nil, for: service)
            service.discoveredCharacteristics?.forEach{
                print($0)
            }
            
            print("Services UUIDs discovered : \(service.uuid)")
            if let characteristics = service.discoveredCharacteristics?
                .first(where: { $0.uuid == characteristicsUUID }) {
                    print("Characteristics UUIDs discovered : \(characteristics.uuid)")
                
                    try await peripheral.setNotifyValue(
                        true,
                        forCharacteristicWithCBUUID: characteristicsUUID,
                        ofServiceWithCBUUID : serviceUUID
                    )
                    print("Notifications enabled")
                
                    try await peripheral.writeValue(
                        "s".data(using: .ascii)!,
                        for: characteristics,
                        type: .withoutResponse
                    )

                    print("Value updater establishing...")
                    peripheral.characteristicValueUpdatedPublisher
                        .filter { $0.characteristic.uuid == characteristicsUUID }
                        .map { try? $0.parsedValue() as String? }
                        .sink { value in
                            print(value ?? "no data")
                        }
                    .store(in: &cancellables)
                    print("done. Waiting for packets...")
                
                    try await Task.sleep(for: .seconds(20))
                
                    cancellables.forEach { $0.cancel() }
                }
        }
                        
        print("Disconnecting...")
        try await centralManager.cancelPeripheralConnection(foundDevice.peripheral)
        print("Ok")
    }
}

Upvotes: 0

Related Questions