| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 | using System.Text;using Android.Bluetooth;namespace InABox.Avalonia.Platform.Android;public class Android_ConnectedBluetoothDevice : BluetoothGattCallback,IConnectedBluetoothDevice{    private BluetoothDevice? _device;    public string ID { get; }    public string Name { get; }    public DateTime LastSeen { get; set; } = DateTime.Now;    public byte[]? ManufacturerData { get; set; }    private Guid[] _availableServices = [];    public Guid[] AvailableServices => _availableServices;            private BluetoothGatt? _bluetoothGatt;        private TaskCompletionSource<bool>? _connectionTaskCompletionSource;    private TaskCompletionSource<bool>? _serviceDiscoveryTaskCompletionSource;    private TaskCompletionSource<byte[]>? _readTaskCompletionSource;    private TaskCompletionSource<bool>? _writeTaskCompletionSource;    public Android_ConnectedBluetoothDevice(BluetoothDevice? device)    {        _device = device;        ID = device?.Address ?? string.Empty;        Name = device?.Name ?? "Unknown Device";    }    public async Task<bool> ConnectAsync()    {        _connectionTaskCompletionSource = new TaskCompletionSource<bool>();        _bluetoothGatt = _device?.ConnectGatt(Application.Context, false, this);        return await _connectionTaskCompletionSource.Task;    }    public override void OnConnectionStateChange(BluetoothGatt? gatt, GattStatus status, ProfileState newState)    {        base.OnConnectionStateChange(gatt, status, newState);        if (newState == ProfileState.Connected && status == GattStatus.Success)        {            Console.WriteLine("Connected to GATT server.");            _connectionTaskCompletionSource?.TrySetResult(true);        }        else        {            Console.WriteLine("Failed to connect or disconnected.");            _connectionTaskCompletionSource?.TrySetResult(false);            Dispose();        }    }    public async Task<bool> DiscoverServicesAsync()    {        _serviceDiscoveryTaskCompletionSource = new TaskCompletionSource<bool>();        _bluetoothGatt?.DiscoverServices();        _availableServices = _bluetoothGatt?.Services?.Select(x => Guid.Parse(x.Uuid?.ToString() ?? Guid.Empty.ToString())).ToArray() ?? [];        return await _serviceDiscoveryTaskCompletionSource.Task;    }    public override void OnServicesDiscovered(BluetoothGatt? gatt, GattStatus status)    {        base.OnServicesDiscovered(gatt, status);        if (status == GattStatus.Success)        {            Console.WriteLine("Services discovered.");            _serviceDiscoveryTaskCompletionSource?.TrySetResult(true);        }        else        {            Console.WriteLine("Service discovery failed.");            _serviceDiscoveryTaskCompletionSource?.TrySetResult(false);        }    }        public async Task<byte[]?> ReadBytesAsync(Guid serviceid, Guid characteristicid)    {        byte[]? result = null;        if (_bluetoothGatt != null)        {            var service = _bluetoothGatt.GetService(Java.Util.UUID.FromString(serviceid.ToString()));            if (service != null)            {                var characteristic = service.GetCharacteristic(Java.Util.UUID.FromString(characteristicid.ToString()));                if (characteristic != null)                    result = await ReadCharacteristicAsync(characteristic);            }        }        return result;    }    public async Task<String?> ReadStringAsync(Guid serviceid, Guid characteristicid)    {        var data = await ReadBytesAsync(serviceid,characteristicid);        return data != null ? Encoding.UTF8.GetString(data) : null;    }    private async Task<byte[]?> ReadCharacteristicAsync(BluetoothGattCharacteristic characteristic)    {        if (_bluetoothGatt != null)        {            _readTaskCompletionSource = new TaskCompletionSource<byte[]>();            if (!_bluetoothGatt.ReadCharacteristic(characteristic))            {                _readTaskCompletionSource.TrySetException(                    new InvalidOperationException("Failed to initiate characteristic read."));            }            return await _readTaskCompletionSource.Task;        }        return null;    }    public override void OnCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] data, GattStatus status)    {        base.OnCharacteristicRead(gatt, characteristic, data, status);        if (status == GattStatus.Success)        {            Console.WriteLine("Characteristic read successfully.");            _readTaskCompletionSource?.TrySetResult(data);        }        else        {            Console.WriteLine("Failed to read characteristic.");            _readTaskCompletionSource?.TrySetException(new InvalidOperationException("Characteristic read failed."));        }    }        public async Task<bool> WriteBytesAsync(Guid serviceid, Guid characteristicid, byte[] data)    {        var result = false;        if (_bluetoothGatt != null)        {            var service = _bluetoothGatt.GetService(Java.Util.UUID.FromString(serviceid.ToString()));            if (service != null)            {                var characteristic = service.GetCharacteristic(Java.Util.UUID.FromString(characteristicid.ToString()));                if (characteristic != null)                    result = await WriteCharacteristicAsync(characteristic, data);            }        }        return result;    }        public async Task<bool> WriteStringAsync(Guid serviceid, Guid characteristicid, string data)    {        var encoded = Encoding.UTF8.GetBytes(data);        return await WriteBytesAsync(serviceid, characteristicid, encoded);    }        private async Task<bool> WriteCharacteristicAsync(BluetoothGattCharacteristic characteristic, byte[] data)    {        bool result = false;        if (_bluetoothGatt != null)        {             _writeTaskCompletionSource = new TaskCompletionSource<bool>();            _bluetoothGatt.WriteCharacteristic(characteristic, data, 2);             result = await _writeTaskCompletionSource.Task;        }        return result;    }    public override void OnCharacteristicWrite(BluetoothGatt? gatt, BluetoothGattCharacteristic? characteristic, GattStatus status)    {        base.OnCharacteristicWrite(gatt, characteristic, status);        if (status == GattStatus.Success)        {            Console.WriteLine("Characteristic written successfully.");            _writeTaskCompletionSource?.TrySetResult(true);        }        else        {            Console.WriteLine("Failed to write characteristic.");            _writeTaskCompletionSource?.TrySetException(new InvalidOperationException("Characteristic write failed."));        }    }        public new void Dispose()    {        base.Dispose();        try        {            _bluetoothGatt?.Disconnect();            _bluetoothGatt?.Close();        }        catch (Exception ex)        {            Console.WriteLine($"Error during disposal: {ex.Message}");        }                _bluetoothGatt?.Dispose();        _bluetoothGatt = null;                _device?.Dispose();        _device = null;        Console.WriteLine("Resources released.");            }    }
 |