0

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?

2
  • Have you checked that this characteristic is readable? I would expect that you get the data via Notification. Commented Feb 14 at 11:12
  • @Risto do you mean that Notification is another mechanism compared to just read characteritics ? Do you have a code snippet at hand with the correct way to do it ? Commented Feb 14 at 12:39

1 Answer 1

0

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")
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.