I develop a data field to connect the Garmin watches to a treadmill series of a specific manufacturer.
The transmitted data and commands are the same for all models, but the service UUIDs differs, and while the most models are using notifications, atleast one model, with a different Bluetooth controller is using indications.
Sending data to the treadmill works without problem, but receiving data doesn't work - onCharacteristicChanged is never called.
I don't own this model by myself, which makes debugging a bit harder. Fortunately, a user is very nice and helps me testing - unfortunately with little success.
I've created a testing website using Web Bluetooth API and here, everything works perfect. So maybe I missed something in my Monkey C code, which is done automatically by the browser.
I've implemented some logging, it would be nice if a Bluetooth API expert could tell me if there is something wrong or missing.
These are the BLE related functions which I call, and the comments are the events which are called by the system:
(to focus on the important parts, I've removed null-checks/error handling etc.)
BluetoothLowEnergy.setScanState(BluetoothLowEnergy.SCAN_STATE_SCANNING); // onScanStateChange(1, STATUS_SUCCESS) // onScanResults() // -> Device found BluetoothLowEnergy.setScanState(BluetoothLowEnergy.SCAN_STATE_OFF); var profile = { :uuid => serviceUuid, :characteristics => [ { :uuid => readCharacteristicUuid, :descriptors => [BluetoothLowEnergy.cccdUuid()] }, { :uuid => writeCharacteristicUuid } ] }; BluetoothLowEnergy.registerProfile(profile); BluetoothLowEnergy.pairDevice(scanResult); // onProfileRegister(0000FEE7-0000-1000-8000-00805F9B34FB, STATUS_SUCCESS) // onScanStateChange(0, STATUS_SUCCESS) // onConnectedStateChanged({ isConnected: true }, CONNECTION_STATE_CONNECTED) var service = device.getService(serviceUuid); var readCharacteristic = service.getCharacteristic(readCharacteristicUuid); var descriptor = readCharacteristic.getDescriptor(BluetoothLowEnergy.cccdUuid()); descriptor.requestWrite([0x02, 0x00]b); // onDescriptorWrite(00002902-0000-1000-8000-00805F9B34FB, STATUS_SUCCESS) var service = device.getService(serviceUuid); var writeCharacteristic = service.getCharacteristic(writeCharacteristicUuid); writeCharacteristic.requestWrite(self.prepareDataRequest(), { :writeType => BluetoothLowEnergy.WRITE_TYPE_DEFAULT }); // onCharacteristicWrite(0000FE02-0000-1000-8000-00805F9B34FB, STATUS_SUCCESS)
The prepareDataRequest method prepares a ByteArray which tells the treadmill to send status data.
That's it ... the data field is now waiting for data but onCharacteristicChanged is never called.
The same code with notifications on another treadmill model (and descriptor.requestWrite([0x01, 0x00]b);) works without problems.
I've also tried writeType => BluetoothLowEnergy.WRITE_TYPE_WITH_RESPONSE, and while this works for my model, it fails with onCharacteristicWrite(0000FE02-0000-1000-8000-00805F9B34FB, STATUS_WRITE_FAIL)on the users model.
As far as I understand, if I set the CCCD flag for "indicate", the watch will take care about the rest and onCharacteristicChanged should be called. From the documentation:
After enabling notifications or indications on a characteristic by enabling the appropriate bit of the CCCD of the characteristic this function will be called after every change to the characteristic.
Is there anything else I missed?
I've been trying to solve this for several days now, but documentation on this is very scarce,so I'm lost.
Thank you for reading this far and many regards,
Jens