Subscribing to Notifications/Indications



  • I'm having trouble enabling notifications. I'm getting write failures with status 128 - GATT_NO_RESOURCES.

    It seems like (based on https://stackoverflow.com/questions/41016834/ble-getting-error-code-128-while-writing-to-characterstic/41527567) this is because I haven't set the Descriptor UUID, but previously (with Sweetblue 2.x) I didn't have to do this, it just worked with the service and characteristic UUID.

    I'm creating a new BleNotify with the Service UUID and Characteristic UUID, then setting the Listener before calling enableNotify. Any ideas as to what else I need to do, or what format the descriptor UUID should be?



  • It should essentially work the same as with V2. That's one area that really didn't get changed much in V3.

    How many notifications do you have set? Most android devices have a limit on how many notifications you can have enabled at the same time. This will vary from device to device, and by OS level. This is what the GATT_NO_RESOURCES code means (but not always).



  • @ryanbis We do have something like 5 or 6 indications and/or notifications. But we had that many with v2 and it was working fine.

    We were using BleDevice.enableNotify, with the service and characteristic UUIDs and a ReadWriteListener as the arguments. In v3 that's deprecated (and the Listener has changed to a NotificationListener) so I'm trying to do it using a BleNotify which is passed in as the only argument to enableNotify.

    The BleNotify seems to need a NotificationListener and the same UUIDs to be set up before using it, but then I'm getting the GATT 128 error when trying to actually enable the notify.



  • Are you able to get any notifications enabled?

    BTW, you don't have to provide a NotificationListener. If you set a "global" listener on the device via BleDevice.setListener_Notification(), you will get all notification messages in that listener.



  • No, I've not managed to get any notifications working using sweetblue 3 so far.

    Is there a demo app or something like that I could try, just to make sure if it's something I've set up wrong or not?



  • You could use the Toolbox app https://play.google.com/store/apps/details?id=com.idevicesinc.sweetblue.toolbox.v3

    Also, is the characteristic set as a notification, or indication?



  • We've got five indicates and a notify. They all seem to work on the toolbox app - or at least it doesn't throw any errors.

    I noticed it showed a message that it was discovering services on the toolbox app, and I don't think I've seen any log lines about service discovery in our v3 app. Although that might just be I haven't set up the correct listener.



  • Service discovery is implicit in the library (unless you turn it off in the BleManageConfig), and part of the normal connection process. We had another person complain that their indications aren't working as well. However, the Toolbox app doesn't work in their case (although the V2 version DOES work). This doesn't make any sense because other than how you call the method, nothing changed for notifications/indications. Plus, I found a device which does have indications setup on a characteristic, and they seem to work fine. Is there any way you could possible send us a device for us to test on here at the office?



  • We've actually got two devices, one of which has only got one Indication, the other of which has 5 Indications and a (usually unused) Notification.

    Weirdly, they seem to behave differently - the device with one indication successfully enables the it, but doesn't get any data through (of course I may not have set up the listener for it correctly, as I don't think I'm getting any NotificationEvents for that device at all). The one with multiple indications has the REMOTE_GATT_FAILURE events with GATT_NO_RESOURCES(128).

    The device with a single indication is easier to test, and I've managed to get data out of it on SweetBlue toolbox - which I've just realised is using 2.52.17 and not 3 as I thought (I found it by searching on google play not via the link above, so that's my fault there). I'll have to check again with v3.

    I am wondering though if I'm starting the notify/indicate enables at the right point. In v2 we were waiting for an INITIALIZED state before trying to read, write or enable notifications. I didn't seem to be getting an INITIALIZED even in v3, so I tried triggering the reads and writes after a successful ConnectEvent. So is it possible I'm trying to set notifications/indications before the full service discovery is finished? Where, if anywhere, should I be listening for an INITIALIZED state?



  • You may want to look at this page https://sweetblue.io/docs/Version-3-Changes . It explains how states have changed slightly. Now you just look for the CONNECTED state (that is essentially the old INITIALIZED state). The INITIALIZED state is still there, but it's filtered out from the state events (Filtering was applied to cut down on the amount of posting to the main thread). You can of course change this behavior, by setting the option BleDeviceConfig.defaultDeviceStates (it's an array of BleDeviceState).

    I've always handled notifications/indications the same way. By turning them on in an Init transaction. This way, if the device has to reconnect because android dropped the session for whatever reason, I know the notifications will be re-enabled (plus any other operations that need to be done upon establishing a connection).

    BleManagerConfig config = new BleManagerConfig();
    config.defaultInitFactory = () -> new BleTransaction.Init()
            {
                @Override
                protected void start()
                {
                    BleNotify notify = new BleNotify(myServiceUuid, myCharUuid)
                            .setNotificationListener((notifyEvent) -> 
                            {
                               if (notifyEvent.wasSuccess())
                               {
                                   BleRead read = new BleRead(mNameRead);
                                   read.setReadWriteListener((readEvent) ->
                                   {
                                       if (readEvent.wasSuccess())
                                           succeed();
                                       else
                                           fail();
                                   });
                                   read(read);                    
                               }
                               else
                                   fail();
                            });
                    getDevice().enableNotify(notify);
                }
            };
    


  • Okay, that's a neat way of handling it. Presumably we could set a defaultInitFactory for a device config instead of a manager config if we want different default behaviour between different types of device?

    And a ConnectionEvent success should be the same as being in the state CONNECTED then?

    Interestingly though, I seem to get the same behaviour in the v3 toolbox as I do in our app - the device with one indication successfully enables it but gets no data; the other device can't enable indications at all, but can (for some reason) enable the Notify.



  • The key with transactions is to remember to call either succeed() or fail(). Otherwise it will perpetually be in the transaction forever, and nothing will seem to work. You are correct in your assumption about using BleDeviceConfig if you want different behavior from device to device.

    Yes the when the DeviceConnectListener reports a successful connection, the device will be in the CONNECTED state. These changes were made in an effort to make things more intuitive.

    Is there any way you could send us the 2 devices? It will be MUCH easier for us to figure out the problem if we could reproduce it here, and step through code between v2 and v3 to find where they are diverging from one another.



  • Potentially, although I'd like to try a couple of other things first.

    One is using another tablet to act as a peripheral, just to check if it's working.

    The other is using a development board or one of our devices as a simplified test device - something like a single indication which updates every couple of seconds with known data.

    Both of those should be easier to test than our actual devices which expect a timestamp and/or a one-time-key authentication before sending any data.



  • Ok, let me know how it goes. I know that in general, notifications do work, as we've been running V3 in our commercial app for a few months now (granted, we don't have a production case for indications working, but it's really the same process).



  • Okay, I might have something.

    I used the nrfConnect app from Nordic Semiconductor to clone our devices and act as an advertiser and GATT server. These indications work fine as far as I can tell. Still not sure why that's different.

    Going back to our devices, I had another look at the one where subscribing works but no data comes through. I noticed that in the V2 app it writes 0200 to the CCCD to enable indications, but in the V3 app it writes 0100.

    I think that (allowing for different byte order) that corresponds to enabling an indication (0x0002) or a notification (0x0001). So in the simpler one-indication device, I think we receive the value and possibly even start sending data, but android ignores it because we're sending via indicate instead of notify, and it's enabled notify. Or it doesn't match the value we're expecting so we don't start sending data, I'm not 100% sure. Then in the other device with multiple indications we're using a different radio chip, which I suspect rejects the notify enable completely and we get the GATT_NO_RESOURCES error.

    So if I can set the CCCD value for sweetblue to write, it should all work, I think.



  • Just to confirm, when I connect the V2 app to nrfConnect and enable an notifications on an indication I get an '"Indications enabled" received' message on the logger, but when I do the same for the V3 app, I get a '"Notifications enabled" received' message. However in both cases the nrfConnect app can then send an indication through to the sweetblue apps.

    So presumably for whatever reason our "real" devices behave differently and expect an "Indications enabled" instead of a "Notifications enabled" even though other than the value of 1 or 2 the messages are effectively the same.



  • Ok I'll look into it. Someone else mentioned the 1 versus 2 being sent for indications. It's strange as the logic to decide which one to send hasn't changed, but there must be a glitch in there somewhere. Thanks for digging in for more info.



  • So I found the issue. Well, the issue where the library is sending the wrong value when enabling indications. I'm prepping to release a hotfix version (3.0.1) to fix this issue. It should be release within the next 2 days.



  • Excellent news, thank you!