using System; using System.Text; using System.Threading.Tasks; using Plugin.BLE.Abstractions; namespace InABox.Avalonia.Platform.iOS; public class iOS_ConnectedBluetoothDevice(IBluetoothDevice device) : IConnectedBluetoothDevice { public void Dispose() { Device.Dispose(); } public iOS_BluetoothDevice Device { get; } = (iOS_BluetoothDevice)device; public string ID => Device.ID; public string Name => Device.Name; public Guid[] AvailableServices => Device.AvailableServices; public DateTime LastSeen { get => Device.LastSeen; set => device.LastSeen = value; } public byte[]? ManufacturerData { get => Device.ManufacturerData; set => Device.ManufacturerData = value; } public async Task WriteBytesAsync(Guid serviceid, Guid characteristicid, byte[] data) { System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} WriteBytesAsync::Getting Service {serviceid}..."); using (var service = await Device.Native.GetServiceAsync(serviceid)) { if (service == null) { System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} WriteBytesAsync::Failed to find service"); return false; } System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} WriteBytesAsync::Getting Characteritsic {characteristicid}..."); var characteristic = await service.GetCharacteristicAsync(characteristicid); if (characteristic == null) { System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} WriteBytesAsync::Failed to find characteristic"); return false; } System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} WriteBytesAsync::Writing [{string.Join(" ",data.Select(x=>$"{x:X2}"))}]..."); // for some reason the async call fails randomly //var result = await characteristic.WriteAsync(data); // So lets hack in a one-second timeout... var writeTask = characteristic.WriteAsync(data); var waitTask = Task.Delay(1000); await Task.WhenAny(writeTask, waitTask); if (writeTask.Status == TaskStatus.RanToCompletion) { System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} WriteBytesAsync::Wrote {writeTask.Result} bytes."); return writeTask.Result == data.Length; } System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} WriteBytesAsync::Timeout while writing!"); return false; } } public async Task WriteStringAsync(Guid serviceid, Guid characteristicid, string data) { var encoded = Encoding.UTF8.GetBytes(data); return await WriteBytesAsync(serviceid, characteristicid, encoded); } public async Task ReadBytesAsync(Guid serviceid, Guid characteristicid) { System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} ReadBytesAsync::Getting Service {serviceid}..."); using (var service = await Device.Native.GetServiceAsync(serviceid)) { if (service == null) { System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} ReadBytesAsync::Failed to find service"); return []; } System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} ReadBytesAsync::Getting Characteritsic {characteristicid}..."); var characteristic = await service.GetCharacteristicAsync(characteristicid); if (characteristic == null) { System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} ReadBytesAsync::Failed to find characteristic"); return []; } System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} ReadBytesAsync::Reading data..."); var result = await characteristic.ReadAsync(); System.Diagnostics.Debug.WriteLine($"{DateTime.Now:O} ReadBytesAsync:: [{result.resultCode}] => [{string.Join(" ",result.data.Select(x=>$"{x:X2}"))}]."); return result.data; } } public async Task ReadStringAsync(Guid serviceid, Guid characteristicid) { var data = await ReadBytesAsync(serviceid,characteristicid); return data != null ? Encoding.UTF8.GetString(data) : null; } }