| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 | using InABox.Core;using Plugin.BLE;using Plugin.BLE.Abstractions;using Plugin.BLE.Abstractions.Contracts;using Plugin.BLE.Abstractions.EventArgs;using System;using System.Linq;using System.Threading.Tasks;namespace InABox.Avalonia.Platform.iOS;public class iOS_Bluetooth : IBluetooth{    public Logger? Logger { get; set; }    public event EventHandler? Changed;    public CoreObservableCollection<IBluetoothDevice> Devices { get; } = new ();        private IBluetoothLE _ble;    private IAdapter _adapter;    private ScanFilterOptions _scanoptions = new ScanFilterOptions();    private StaleItemMonitor<IBluetoothDevice> _staleItemMonitor;    public iOS_Bluetooth()    {                _staleItemMonitor = new StaleItemMonitor<IBluetoothDevice>(            Devices,            x=>x.LastSeen,            x =>x.ID,            TimeSpan.FromSeconds(10),             TimeSpan.FromMilliseconds(500)        );                _ble = CrossBluetoothLE.Current;         _adapter = CrossBluetoothLE.Current.Adapter;        _adapter.ScanTimeout = 5000;        _adapter.ScanTimeoutElapsed += async (sender, args) => { await _adapter.StartScanningForDevicesAsync(_scanoptions); };        _adapter.DeviceDiscovered += AdapterOnDeviceDiscovered;        //_adapter.ScanMatchMode = ScanMatchMode.AGRESSIVE;        //_adapter.ScanMode = ScanMode.LowLatency;                // Task.Run(() =>        // {        //     while (true)        //     {        //         var stale = Devices.ToArray().Where(x => (x == null) || (x.LastSeen < DateTime.Now.Subtract(new TimeSpan(0, 0, 10))))        //             .ToArray();        //         if (stale.Any())        //         {        //             Devices.RemoveRange(stale);        //             Changed?.Invoke(this, EventArgs.Empty);        //         }        //                     //         Task.Delay(500);        //     }        // });    }        // public static async Task<bool> IsPermitted<TPermission>() where TPermission : Permissions.BasePermission, new()    // {    //     try    //     {    //         PermissionStatus status = await Permissions.CheckStatusAsync<TPermission>();    //         if (status == PermissionStatus.Granted)    //             return true;    //         var request = await Permissions.RequestAsync<TPermission>();    //         return request == PermissionStatus.Granted;    //    //     }    //     catch (TaskCanceledException ex)    //     {    //         return false;    //     }    // }        public async Task<bool> IsAvailable()    {        //if (await IsPermitted<Permissions.Bluetooth>())        //{        //}        return _adapter != null;    }    public async Task<bool> StartScanningAsync(Guid configServiceId)    {                _scanoptions.ServiceUuids = [configServiceId];        return await StartScanningAsync();    }    private async Task<bool> StartScanningAsync()    {        System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Starting Bluetooth Scanning...");        await _staleItemMonitor.StartAsync();        await _adapter.StartScanningForDevicesAsync(_scanoptions);        System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Bluetooth Scanning Started.");        return true;    }    private void AdapterOnDeviceDiscovered(object? sender, DeviceEventArgs e)    {        System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Found device {e.Device.Name}...");        var device = Devices.FirstOrDefault(x => string.Equals(x.ID, e.Device.Id.ToString()));        if (device == null)        {            System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Adding device {e.Device.Id}...");            device = new iOS_BluetoothDevice(e.Device);            Devices.Add(device);            System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Added device {device.ID}.");        }        device.LastSeen = DateTime.Now;        device.ManufacturerData = e.Device.AdvertisementRecords            .FirstOrDefault(x => x.Type == AdvertisementRecordType.ManufacturerSpecificData)?.Data ?? [];                System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Notifying Changes...");        Changed?.Invoke(this, EventArgs.Empty);        System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Changes Notified.");    }        public async Task<bool> StopScanningAsync()    {        System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Stopping Bluetooth Scanning...");        await _staleItemMonitor.StopAsync();        await _adapter.StopScanningForDevicesAsync();        System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Bluetooth Scanning Stopped.");        return true;    }    public async Task<IConnectedBluetoothDevice?> Connect(IBluetoothDevice device)    {        if (Guid.TryParse(device.ID, out var deviceid))        {            System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Connecting Bluetooth Device {device.ID}...");            await StopScanningAsync();            var connected = await _adapter.ConnectToKnownDeviceAsync(deviceid);            if (connected != null)            {                var result = new iOS_ConnectedBluetoothDevice(device);                System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Bluetooth Device {device.ID} connected.");                return result;            }            await StartScanningAsync();            System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Connection to {device.ID} failed.");        }        System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Device has invalid ID.");        return null;    }    public async Task<bool> Disconnect(IConnectedBluetoothDevice device)    {        if (device is iOS_ConnectedBluetoothDevice connected)        {            System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Disconnecting Bluetooth Device {device.ID}...");            await _adapter.DisconnectDeviceAsync(connected.Device.Native);            await StartScanningAsync();            System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} Bluetooth Device {device.ID} disconnected.");        }        return true;    }}
 |