Is it possible to setNotifyValue for a Characteristic once you've discovered it?
KevinGAleman opened this issue · 8 comments
I'm working with a library right now from my chipset manufacturer, and trying to rewrite this and wrap it with the BlueCap framework, but I'm having trouble with the BLE messaging because I need to be able to setNotifyValue
for a characteristic once I've discovered it. For example, the manufacturer's library makes this call:
[self.connectedPeripheral.peripheral
setNotifyValue:YES
forCharacteristic:characteristic];
This call is made after the services and characteristics have been discovered, and is basically saying, "I've found this characteristic on my peripheral, and now I want to be notified of changes to it." However, the BlueCap library wraps setNotifyValue
into a private internal function, so when the characteristic is discovered, the initializer casts it to a CBCharacteristicInjectable
, and the internal cbCharacteristic.isNotifying
value is set to NO, and there's no way to change this after the fact, as far as I can tell. Am I missing something simple? Is there something more complex, like me needing to create a profile for the characteristics on my device? Or do I need to figure out a way to fix this and send a PR? Thanks for your help, and thanks for this awesome framework.
More information:
Even when I create a profile and specify [.notify, .read]
as CBCharacteristicProperties
in this profile, the propertyEnabled
function inside of Characteristic.swift still returns false, because it's only reading cbCharacteristic.properties
instead of the properties inside of the profile that I specified. I think the fix would be to also check against the properties specified in the Characteristic's profile, but I'm not sure if that would affect any other code. Thoughts?
Potential fix submitted in #48
I'm not sure if this is the solution... I'm still getting CBATT Error: Domain 6 after making the call to startNotifying
. There might be a little more work to be done here.
Is the .notify
property enabled on the discovered Characteristic? If it is not then setNotifyValue will fail.
Does the example code from the manufacturer work?
CBATT Error: Domain 6 is a CoreBluetooth error. It is not a framework error.
You can only setNotifyValue after a characteristic is discovered.
The example code from the manufacturer does work.
I do wait until the Future from service.discoverCharacteristics
returns and the characteristics have been discovered, but the .notify
property is not enabled on the Characteristic when it is initialized and isNotfying
is set to know on the CBCharacteristic
that is injected into the Characteristic class.
Maybe I'm missing a step in the process? My connection flow chain of Futures looks like this:
peripheral.connect -> .discoverServices -> .discoverCharacteristics -> .startNotifying -> .receiveNotificationUpdates
I now see that in your examples, you chain .startNotifying
after you call a .read
or .write
on a characteristic. Maybe this is the key in the process, and I'll test on Monday, but if this sounds right to you, let me know. Thanks for your input!
Weird your process flow is correct. I do not think you should have to read the characteristic before setting notify. Did you check the CBCharacteristic properties? Is notify set? The properties should be set on discovery.
Put a break point here https://github.com/troystribling/BlueCap/blob/master/BlueCapKit/Central/Peripheral.swift#L383 to check CBCharacteristic properties.
There could be a bug.
I thought that I did, but maybe I was looking in the wrong location. I'll add the break point and test again on Monday when I have access to a device. Thanks for the tip!
Can notify be set on any CBCharacteristic, or is this information that comes from the device?
The .notify property is set in the device GATT definition. It cannot be set on the client side. It is odd that it is set in the example code and not in the framework.
Just following up on this before closing it. You're right, @troystribling, the GATT definition coming from the device doesn't have notify set. After stepping through the example code, I see that the call to setNotifyValue
does return the same CBATT Error (code 6), but for some reason, the device receives this notification subscription and starts broadcasting notifications to the app. The only difference in functionality being that BlueCap takes this CBATT error seriously, while the example code from the manufacturer doesn't. :) It's strange and poorly designed (as a lot of the sample code is from this manufacturer, CSR), but it looks like to really solve this problem I'm going to have to dig into the firmware code on the device itself. Thanks for your help!