shinyorg / shiny

.NET Framework for Backgrounding & Device Hardware Services (iOS, Android, & Catalyst)

Home Page:https://shinylib.net

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Bug]: NotifyCharacteristic throws BleException "Characteristic notification descriptor not found"

gianisimone opened this issue · comments

Component/Nuget

BluetoothLE Client (Shiny.BluetoothLE)

What operating system(s) are effected?

  • iOS (13+ supported)
  • Mac Catalyst
  • Android (8+ supported)
  • Windows (.NET 7 Target - only Core is currently supported, BLE is coming)

Version(s) of Operation Systems

Android 13

Hosting Model

  • MAUI
  • Native/Classic Xamarin
  • Manual

Steps To Reproduce

  1. Connect to a BLE Device
  2. Get a known characteristic which has no descriptors
  3. Subscribe to Observable returned by Peripheral.NotifyCharacteristic method

Expected Behavior

I expected to see the Next method called properly when notification on that characteristic happens

Actual Behavior

The OnError method of the Observer is called with the error message "Characteristic notification descriptor not found".
Looking at the source code that exception is thrown when the notify descriptor is not found on that characteristic. This is fine, however in previous versions the same characteristic is able to receive notification, even if it has no descriptors for notification. Is it possible to have the same behaviour in the new version?

Exception or Log output

Characteristic notification descriptor not found

Code Sample

No response

Code of Conduct

  • I have supplied a reproducible sample that is NOT FROM THE SHINY SAMPLES!
  • I am a Sponsor OR I am using the LATEST stable/beta version from nuget (v3.0 stable - ALPHAS are not taking issues - Sponsors can still send v2 issues)
  • I am Sponsor OR My GitHub account is 30+ days old
  • I understand that if I am checking these boxes and I am not actually following what they are saying, I will be removed from this repository!

Android has always looked for a notification characteristic because it is required. This has never been any different.

@aritchie thank you for your reply. I can guarantee that with 2.7.2 subscribing to the characteristic which had no descriptor with WhenNotificationReceived actually worked. The OnNext was called perfectly even if the EnableNotifications failed to complete.

Then send a reproducible case with the issue!

@aritchie Yes, sure.
This is the code using the v3 of Shiny:

private async Task WhenConnected(IPeripheral P)
{
    var characteristics = await P.GetAllCharacteristicsAsync();
    Command = characteristics.FirstOrDefault(c => c.Uuid == BLECharacteristicCommandUuid);    

    if(Command != null) 
    {
        P.NotifyCharacteristic(Command).ObserveOn(RxApp.MainThreadScheduler).Subscribe(notification =>
        {
            Log($"COMMAND CHANGED {Encoding.UTF8.GetString(notification.Data)}");
        },
        (notifyEx) => Log($"Error while enabling notifications for COMMAND. {notifyEx.Message}"));
    }
}
// peripheral is IPeripheral
whenConnected = peripheral.WhenConnected().Subscribe(conn => _ = WhenConnected(conn));

In this example, when calling NotifyCharacteristic the error handler is called and I am not able to process any notifications in the OnNext handler.

This is the code I have for version 2.7.2

var d = await peripheral.GetAllCharacteristics();
d.FirstOrDefault(_ => _.Uuid.ToGuid() == BT_CHARACTERISTIC_COMMAND_UUID);

if(d != null)
{
    TaskCompletionSource<bool> enableCommandNotificationTask = new TaskCompletionSource<bool>();

    CommandNotifyDisposable = Command.WhenNotificationReceived().Subscribe(g =>
    {
        Log(string.Format("COMMAND CHANGED {0}", Encoding.UTF8.GetString(g.Data)));
    }, 
    err => Log("Error"));

    Command.EnableNotifications(true).Subscribe(encd =>
    {
        Log("Command notifications enabled");
    }, 
    err =>
    {
        Log(string.Format("Error while enabling notifications for command {0}", err.Message));
    });
}

The EnableNotifications calls the error method, however, when a notification is received on the characteristic which has no descriptor, the OnNext is called properly.

If you need more details let me know

Ok so really this is more of a feature request. You would like the methods NotifyCharacteristic to be EnableNotification with a separate hook method. This is something I can consider for a future release, but honestly, I don't want to support the non-standard cases. I also merged these methods because people don't understand subscribing/unsubscribing/resubscribing post reconnect. It's a support case I don't want again

Yes, I would like to be able to process any notification received on the a Characteristic even if it has no descriptor.
Is there something I could do to workaround that Exception at the moment?

Not with the current implementation that I can think of. You can always create your own implementation.