BLE communication between a Garmin wearable and an iOS device

493 Views Asked by At

I would like to create a Garmin wearable app (Data Field), which would communicate with my iOS app using Bluetooth LE (BluetoothLowEnergy API on Garmin and CoreBluetooth on iOS). There's a limitation of Garmin's API - it can work only as a central device, so I configured my iPhone to act as a "virtual" peripheral (I tested it both with my own debug app and LightBlue).

I managed to establish a connection between my Garmin Vivoactive 3 Music and my iPhone, but I still have some issues to make it work.

From Garmin wearable I managed to search, find and pair a device (my iPhone virtual peripheral), so that both: self.pairedDevice = BluetoothLowEnergy.pairDevice(scanResult) and BluetoothLowEnergy.getPairedDevices().next() don't return nulls.

The problem I have is that this callback is never called on a Garmin device:

function onConnectedStateChanged(device, connectionState) {
    if (connectionState==BluetoothLowEnergy.CONNECTION_STATE_CONNECTED) {
        displayString = "Connected";
    }
    if (connectionState==BluetoothLowEnergy.CONNECTION_STATE_DISCONNECTED) {
        displayString = "Disconnected";
    }
}

Moreover, when discovering my virtual peripheral, I can see available services in advertisement data, but once the devices are paired, calling device.getServices() returns an empty iterator.

I already checked that BluetoothLowEnergy.getAvailableConnectionCount() is 3, so there should be no problem with regard to connections number limit. Is there any way to force the connection?

On iOS I do something like this:

        let service = CBMutableService(type: serviceCbuuid, primary: true)
        let writeableCharacteristic = CBMutableCharacteristic(type: characteristicCbuuid,
                                                              properties: [.write],
                                                              value: nil,
                                                              permissions: [.writeable])
        service.characteristics = [writeableCharacteristic]
        currentService = service
        peripheralManager = CBPeripheralManager(delegate: self,
                                                queue: DispatchQueue.global(qos: .userInteractive))

then I add currentService using peripheralManager?.add(currentService) and in didAdd service callback I start advertising by calling peripheral.startAdvertising(options).

Maybe I miss some setting on the iOS end to make this work?

0

There are 0 best solutions below