dotnet-bluetooth-le icon indicating copy to clipboard operation
dotnet-bluetooth-le copied to clipboard

Gatt write characteristic FAILED

Open diegoperfeito opened this issue 4 years ago • 9 comments

Steps to reproduce

  1. I load a observable list with services list

    ObservableCollection<servicesBT100> AuxservicosBT100 = new ObservableCollection<servicesBT100>(); foreach (IService servico in _servicos) { switch (servico.Id.ToString()) { case Constants.F1: // Função F1 var aux1 = new servicesBT100(); aux1.Servico = servico.Id.ToString(); aux1.Fn = "F1"; aux1.Funcao = App.Resx.GetTraducao("F1"); aux1.DescFunc = App.Resx.GetTraducao("DescF1"); aux1.DescFuncCompleta = App.Resx.GetTraducao("DescF1Completa"); aux1.Farquivo = Application.Current.Resources["F1arquivo"].ToString(); aux1.IServico = servico; AuxservicosBT100.Add(aux1); break;

  2. After Tapped Action

    var paginaFuncao3 = new TabbedPageF3(_characteristic, _numIntervalos, _charactIntervalos); await Navigation.PushAsync(paginaFuncao3); break;

  3. The error happens when I send / submit the push feature to the next page. then the error Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException: 'Gatt write characteristic FAILED.' happens.

  4. Everything was working 60 days ago, something was updated / modified and the functionality started to give a problem only on Android. On iOS it's working fine.

Crashlog

Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException Message=Gatt write characteristic FAILED. Source=mscorlib StackTrace: at Plugin.BLE.Android.Characteristic.InternalWrite (System.Byte[] data) [0x0004a] in D:\a\xamarin-bluetooth-le\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:110 at Plugin.BLE.Android.Characteristic+<>c__DisplayClass19_0.<WriteNativeAsync>b__0 () [0x00000] in D:\a\xamarin-bluetooth-le\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:81 at Plugin.BLE.Abstractions.Utils.TaskBuilder.FromEvent[TReturn,TEventHandler,TRejectHandler] (System.Action execute, System.Func3[T1,T2,TResult] getCompleteHandler, System.Action1[T] subscribeComplete, System.Action1[T] unsubscribeComplete, System.Func2[T,TResult] getRejectHandler, System.Action1[T] subscribeReject, System.Action1[T] unsubscribeReject, System.Threading.CancellationToken token) [0x000b3] in D:\a\xamarin-bluetooth-le\xamarin-bluetooth-le\Source\Plugin.BLE.Abstractions\Utils\TaskBuilder.cs:48 at Plugin.BLE.Android.Characteristic.WriteNativeAsync (System.Byte[] data, Plugin.BLE.Abstractions.CharacteristicWriteType writeType) [0x000b2] in D:\a\xamarin-bluetooth-le\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:80 at Plugin.BLE.Abstractions.CharacteristicBase.WriteAsync (System.Byte[] data, System.Threading.CancellationToken cancellationToken) [0x00061] in D:\a\xamarin-bluetooth-le\xamarin-bluetooth-le\Source\Plugin.BLE.Abstractions\CharacteristicBase.cs:92 at BT110MC.TabbedPageF3.picIntervalo_SelectedIndexChanged (System.Object sender, System.EventArgs e) [0x000b5] in E:\app\BT110MC\BT110\BT110\TabbedPageF3.xaml.cs:312 at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021 at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in /Users/builder/azdo/_work/278/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:36 at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in /Users/builder/azdo/_work/278/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:36 at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in /Users/builder/azdo/_work/278/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-29/mcw/Java.Lang.IRunnable.cs:84 at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.1(intptr,intptr)

Configuration

**Version of the Plugin: Nuget 2.1.2

**Platform: Android 11 / Android 7

**Device: Xiaomi A3 / Moto G4 Plus

diegoperfeito avatar May 06 '21 17:05 diegoperfeito

Hi @diegoperfeito,

I'm the friendly issue checker. It seems like (62.50 %) you haven't used our issue template :cry: I think it is very frustrating for the repository owners, if you ignore them.

If you think it's fine to make an exception, just ignore this message. But if you think it was a mistake to delete the template, please close the issue and create a new one.

Thanks!

smsissuechecker avatar May 06 '21 17:05 smsissuechecker

Looks like you're writing from a different thread than the main thread.

Be aware of what's stated in the documentation:

Characteristic/Descriptor Write: make sure you call characteristic.WriteAsync(...) from the main thread, failing to do so will most probably result in a GattWriteError.

MKuckert avatar May 18 '21 06:05 MKuckert

If you are using Xamarin.Essentials, wrap the write up like this:

var success = false;
if (MainThread.IsMainThread)
{
   success  = await writer.WriteAsync(buffer);
}
else 
{
   success  = await MainThread.InvokeOnMainThreadAsync(async () =>  await writer.WriteAsync(buffer));
}

Something like that. But Android is not very good at writing a lot of data to characteristics. I implemented Reliable Writes in my fork of this library because of this. The Reliable Writes lets you write all the data in a transaction and then commit it, so that the controller can send all of the data reliably in one or more transmission windows.

memsom avatar Jun 03 '21 14:06 memsom

Hi, I return in this project, and continue in this error, but worked to more details. When share/passtrought characteristics over functions or navigation pages, but, same after instanced that characteristics, this device and service execute this command : await _characteristic.StopUpdatesAsync(); Return error 'GATT: SetCharacteristicNotification to false, FAILED.' In Android 9 and 11 _characteristic.CanWrite is false. Only Android 9 and 11 tested, but allrigh in Android 7. I had testing any implements, but not suceeded. 1 - Implemented variables/characteristics how to property 2 - Passtrought variable/characteristics how to a reference

Any Idea?

Regards.

diegoperfeito avatar Oct 21 '21 20:10 diegoperfeito

bool d0 = _characteristic.CanRead; //true bool d1 = _characteristic.CanUpdate; //true bool d2 = _characteristic.CanWrite; //false var a1 = _characteristic.Id; //{f0cba101-c838-c592-f00b-000a000a000a} var a2 = _characteristic.Name; //"Unknown characteristic" var a3 = _characteristic.Properties; //Plugin.BLE.Abstractions.CharacteristicPropertyType.Notify | Plugin.BLE.Abstractions.CharacteristicPropertyType.Read var a4 = _characteristic.Service; //{Plugin.BLE.Android.Service} var a5 = _characteristic.StringValue; //"" var a6 = _characteristic.Uuid; //f0cba101-c838-c592-f00b-000a000a000a" var a7 = _characteristic.Value; //{byte[0]} var a8 = _characteristic.WriteType; //Plugin.BLE.Abstractions.CharacteristicWriteType.Default

diegoperfeito avatar Oct 22 '21 12:10 diegoperfeito

It didn't work either way

await Xamarin.Essentials.MainThread.InvokeOnMainThreadAsync(async () => await _characteristic.StopUpdatesAsync()); or Device.BeginInvokeOnMainThread(async () => { await _characteristic.StopUpdatesAsync(); });

Same error in two ways. I had testing, when not used await the error occour instantanely

diegoperfeito avatar Oct 22 '21 14:10 diegoperfeito

Plugin.BLE.Abstractions.Exceptions.CharacteristicReadException Message=GATT: SetCharacteristicNotification to false, FAILED. Source=mscorlib StackTrace: at Plugin.BLE.Android.Characteristic.StopUpdatesNativeAsync () [0x00061] in D:\a\xamarin-bluetooth-le\xamarin-bluetooth-le\Source\Plugin.BLE.Android\Characteristic.cs:164 at BT110MC.TabbedPageF1.<Button_Clicked>b__21_0 () [0x00025] in E:\app\BT110MC\BT110\BT110\TabbedPageF1.xaml.cs:206 at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021 at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in /Users/builder/azdo/_work/1/s/xamarin-android/src/Mono.Android/Android.App/SyncContext.cs:36 at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in /Users/builder/azdo/_work/1/s/xamarin-android/src/Mono.Android/Java.Lang/Thread.cs:36 at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in /Users/builder/azdo/_work/1/s/xamarin-android/src/Mono.Android/obj/Release/monoandroid10/android-29/mcw/Java.Lang.IRunnable.cs:84 at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.1(intptr,intptr)

diegoperfeito avatar Oct 22 '21 14:10 diegoperfeito

I tryed use the xamarin-bluetooth-le project with my device and the connection loose right after connect. Prox 12 secs. I must be fast, but, Connect in device, list services, select caractheristic, details...and CONNECTION LOST DEVICE I can read services, and select characteristics, but only. After select Display a message "Connection Lost" and SetCharacteristicNotification to false, FAILED. Or when in same screen, click in START UPDATES

diegoperfeito avatar Oct 25 '21 17:10 diegoperfeito

I just ran into this issue on my app and have a solution.

  1. Use Xamarin.Essentials MainThread to ensure every WriteAsync happens on the main thread.
_mainThread.InvokeOnMainThreadAsync(async () => characteristic.WriteAsync(data))
  1. Use Gentlee's SerialQueue to ensure all of my writes happen synchronously.

It seems that ensuring the Android implementation uses the main thread and performs writes in a serial queue would be a good addition to this library. Is there any interest in adding this to the library?

Edit:

It seems ensuring I was on the main thread wasn't necessary in my scenario. (Needs more experimentation)

Hackmodford avatar May 10 '22 20:05 Hackmodford