<commit_before>using System;
using System.Linq;
using System.Threading;
using System.Reactive.Linq;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using Android.Bluetooth;
using Java.Util;
using Plugin.BluetoothLE.Internals;
using Observable = System.Reactive.Linq.Observable;


namespace Plugin.BluetoothLE
{
    public class GattCharacteristic : AbstractGattCharacteristic
    {
        static readonly UUID NotifyDescriptorId = UUID.FromString("00002902-0000-1000-8000-00805f9b34fb");
        readonly BluetoothGattCharacteristic native;
        readonly GattContext context;


        public GattCharacteristic(IGattService service, GattContext context, BluetoothGattCharacteristic native)
            : base(service, native.Uuid.ToGuid(), (CharacteristicProperties)(int)native.Properties)
        {
            this.context = context;
            this.native = native;
        }


        public override void WriteWithoutResponse(byte[] value)
        {
            this.AssertWrite(false);

            this.RawWriteNoResponse(null, value);
        }


        public override IObservable<CharacteristicResult> Write(byte[] value)
        {
            this.AssertWrite(false);

            return Observable.Create<CharacteristicResult>(async ob =>
            {
                CancellationTokenSource cancelSrc = null;

                var handler = new EventHandler<GattCharacteristicEventArgs>((sender, args) =>
                {
                    if (this.NativeEquals(args))
                    {
                        if (cancelSrc != null)
                            this.context.Semaphore.Release();

                        Log.Write("Incoming Characteristic Write Event - " + args.Characteristic.Uuid);

                        if (!args.IsSuccessful)
                        {
                            ob.OnError(new ArgumentException($"Failed to write characteristic - {args.Status}"));
                        }
                        else
                        {
                            this.Value = value;
                            var result = new CharacteristicResult(this, CharacteristicEvent.Write, this.Value);
                            ob.Respond(result);
                            this.WriteSubject.OnNext(result);
                        }
                    }
                });

                if (this.Properties.HasFlag(CharacteristicProperties.Write))
                {
                    cancelSrc = new CancellationTokenSource();

                    Log.Write("Hooking for write response - " + this.Uuid);

                    await this.context.Semaphore.WaitAsync(cancelSrc.Token);
                    this.context.Callbacks.CharacteristicWrite += handler;
                    this.RawWriteWithResponse(value);
                }
                else
                {
                    Log.Write("Write with No Response - " + this.Uuid);
                    this.RawWriteNoResponse(ob, value);
                }
                return () =>
                {
                    cancelSrc?.Dispose();
                    this.context.Callbacks.CharacteristicWrite -= handler;
                };
            });
        }


        public override IObservable<CharacteristicResult> Read()
        {
            this.AssertRead();

            return Observable.Create<CharacteristicResult>(async ob =>
            {
                var cancelSrc = new CancellationTokenSource();

                var handler = new EventHandler<GattCharacteristicEventArgs>((sender, args) =>
                {
                    if (this.NativeEquals(args))
                    {
                        this.context.Semaphore.Release();

                        if (!args.IsSuccessful)
                        {
                            ob.OnError(new ArgumentException($"Failed to read characteristic - {args.Status}"));
                        }
                        else
                        {
                            this.Value = args.Characteristic.GetValue();

                            var result = new CharacteristicResult(this, CharacteristicEvent.Read, this.Value);
                            ob.Respond(result);
                            this.ReadSubject.OnNext(result);
                        }
                    }
                });
                this.context.Callbacks.CharacteristicRead += handler;
                await this.context.Semaphore.WaitAsync(cancelSrc.Token);

                this.context.Marshall(() =>
                {
                    try
                    {
                        this.context.Gatt.ReadCharacteristic(this.native);
                    }
                    catch (Exception ex)
                    {
                        ob.OnError(ex);
                    }
                });

                return () => this.context.Callbacks.CharacteristicRead -= handler;
            });
        }


        public override IObservable<bool> EnableNotifications(bool useIndicationsIfAvailable)
            => Observable.FromAsync(async ct =>
            {
                var descriptor = this.native.GetDescriptor(NotifyDescriptorId);
                if (descriptor == null)
                    throw new ArgumentException("Characteristic Client Configuration Descriptor not found");

                var wrap = new GattDescriptor(this, this.context, descriptor);
                var success = this.context.Gatt.SetCharacteristicNotification(this.native, true);
                await Task.Delay(250, ct);

                if (success)
                {
                    var bytes = useIndicationsIfAvailable && this.CanIndicate()
                        ? BluetoothGattDescriptor.EnableNotificationValue.ToArray()
                        : BluetoothGattDescriptor.EnableIndicationValue.ToArray();

                    await wrap.Write(bytes);
                    this.IsNotifying = true;
                }
                return success;
            });


        public override IObservable<object> DisableNotifications() => Observable.FromAsync<object>(async ct =>
        {
            var descriptor = this.native.GetDescriptor(NotifyDescriptorId);
            if (descriptor == null)<commit_msg>fix wrong attribute<commit_after>using System;
using System.Linq;
using System.Threading;
using System.Reactive.Linq;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using Android.Bluetooth;
using Java.Util;
using Plugin.BluetoothLE.Internals;
using Observable = System.Reactive.Linq.Observable;


namespace Plugin.BluetoothLE
{
    public class GattCharacteristic : AbstractGattCharacteristic
    {
        static readonly UUID NotifyDescriptorId = UUID.FromString("00002902-0000-1000-8000-00805f9b34fb");
        readonly BluetoothGattCharacteristic native;
        readonly GattContext context;


        public GattCharacteristic(IGattService service, GattContext context, BluetoothGattCharacteristic native)
            : base(service, native.Uuid.ToGuid(), (CharacteristicProperties)(int)native.Properties)
        {
            this.context = context;
            this.native = native;
        }


        public override void WriteWithoutResponse(byte[] value)
        {
            this.AssertWrite(false);

            this.RawWriteNoResponse(null, value);
        }


        public override IObservable<CharacteristicResult> Write(byte[] value)
        {
            this.AssertWrite(false);

            return Observable.Create<CharacteristicResult>(async ob =>
            {
                CancellationTokenSource cancelSrc = null;

                var handler = new EventHandler<GattCharacteristicEventArgs>((sender, args) =>
                {
                    if (this.NativeEquals(args))
                    {
                        if (cancelSrc != null)
                            this.context.Semaphore.Release();

                        Log.Write("Incoming Characteristic Write Event - " + args.Characteristic.Uuid);

                        if (!args.IsSuccessful)
                        {
                            ob.OnError(new ArgumentException($"Failed to write characteristic - {args.Status}"));
                        }
                        else
                        {
                            this.Value = value;
                            var result = new CharacteristicResult(this, CharacteristicEvent.Write, this.Value);
                            ob.Respond(result);
                            this.WriteSubject.OnNext(result);
                        }
                    }
                });

                if (this.Properties.HasFlag(CharacteristicProperties.Write))
                {
                    cancelSrc = new CancellationTokenSource();

                    Log.Write("Hooking for write response - " + this.Uuid);

                    await this.context.Semaphore.WaitAsync(cancelSrc.Token);
                    this.context.Callbacks.CharacteristicWrite += handler;
                    this.RawWriteWithResponse(value);
                }
                else
                {
                    Log.Write("Write with No Response - " + this.Uuid);
                    this.RawWriteNoResponse(ob, value);
                }
                return () =>
                {
                    cancelSrc?.Dispose();
                    this.context.Callbacks.CharacteristicWrite -= handler;
                };
            });
        }


        public override IObservable<CharacteristicResult> Read()
        {
            this.AssertRead();

            return Observable.Create<CharacteristicResult>(async ob =>
            {
                var cancelSrc = new CancellationTokenSource();

                var handler = new EventHandler<GattCharacteristicEventArgs>((sender, args) =>
                {
                    if (this.NativeEquals(args))
                    {
                        this.context.Semaphore.Release();

                        if (!args.IsSuccessful)
                        {
                            ob.OnError(new ArgumentException($"Failed to read characteristic - {args.Status}"));
                        }
                        else
                        {
                            this.Value = args.Characteristic.GetValue();

                            var result = new CharacteristicResult(this, CharacteristicEvent.Read, this.Value);
                            ob.Respond(result);
                            this.ReadSubject.OnNext(result);
                        }
                    }
                });
                this.context.Callbacks.CharacteristicRead += handler;
                await this.context.Semaphore.WaitAsync(cancelSrc.Token);

                this.context.Marshall(() =>
                {
                    try
                    {
                        this.context.Gatt.ReadCharacteristic(this.native);
                    }
                    catch (Exception ex)
                    {
                        ob.OnError(ex);
                    }
                });

                return () => this.context.Callbacks.CharacteristicRead -= handler;
            });
        }


        public override IObservable<bool> EnableNotifications(bool useIndicationsIfAvailable)
            => Observable.FromAsync(async ct =>
            {
                var descriptor = this.native.GetDescriptor(NotifyDescriptorId);
                if (descriptor == null)
                    throw new ArgumentException("Characteristic Client Configuration Descriptor not found");

                var wrap = new GattDescriptor(this, this.context, descriptor);
                var success = this.context.Gatt.SetCharacteristicNotification(this.native, true);
                await Task.Delay(250, ct);

                if (success)
                {
                    var bytes = useIndicationsIfAvailable && this.CanIndicate()
                        ? BluetoothGattDescriptor.EnableIndicationValue.ToArray()
                        : BluetoothGattDescriptor.EnableNotificationValue.ToArray();

                    await wrap.Write(bytes);
                    this.IsNotifying = true;
                }
                return success;
            });


        public override IObservable<object> DisableNotifications() => Observable.FromAsync<object>(async ct =>
        {
            var descriptor = this.native.GetDescriptor(NotifyDescriptorId);
            if (descriptor == null)
{'fraction_non_alphanumeric': 0.08206686930091185, 'fraction_numerical': 0.004959206526955687, 'mean_word_length': 1.3586115827202414, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5928882', 'n_tokens_mistral': 2907, 'n_tokens_neox': 2659, 'n_words': 495}