Browse Source

Stabilisinmg Bluetooth Platform implementations

frankvandenbos 4 tháng trước cách đây
mục cha
commit
534b0711d2

+ 2 - 1
InABox.Avalonia.Platform.Android/Bluetooth/Android_BluetoothDevice.cs

@@ -2,7 +2,7 @@
 
 namespace InABox.Avalonia.Platform.Android;
 
-public class Android_BluetoothDevice(ScanResult scan, Guid[] availableservices, DateTime timestamp) : IBluetoothDevice, IDisposable
+public class Android_BluetoothDevice(ScanResult scan, Guid[] availableservices, DateTime timestamp) : IBluetoothDevice
 {
     public ScanResult Scan { get; } = scan;
     public string ID { get; } = scan.Device?.Address ?? string.Empty;
@@ -12,6 +12,7 @@ public class Android_BluetoothDevice(ScanResult scan, Guid[] availableservices,
 
     public void Dispose()
     {
+        scan.Dispose();
         Scan.Dispose();
     }
 }

+ 26 - 15
InABox.Avalonia.Platform.Android/Bluetooth/Android_ConnectedBluetoothDevice.cs

@@ -3,12 +3,12 @@ using Android.Bluetooth;
 
 namespace InABox.Avalonia.Platform.Android;
 
-public class Android_ConnectedBluetoothDevice(BluetoothDevice device) : BluetoothGattCallback,IConnectedBluetoothDevice
+public class Android_ConnectedBluetoothDevice : BluetoothGattCallback,IConnectedBluetoothDevice
 {
 
-    private BluetoothDevice _device = device;
-    public string ID { get; } = device?.Address ?? string.Empty;
-    public string Name { get; } = device?.Name ?? "Unknown Device";
+    private BluetoothDevice? _device;
+    public string ID { get; }
+    public string Name { get; }
     public DateTime LastSeen { get; set; } = DateTime.Now;
 
     private Guid[] _availableServices = [];
@@ -16,15 +16,22 @@ public class Android_ConnectedBluetoothDevice(BluetoothDevice device) : Bluetoot
         
     private BluetoothGatt? _bluetoothGatt;
     
-    private TaskCompletionSource<bool> _connectionTaskCompletionSource;
-    private TaskCompletionSource<bool> _serviceDiscoveryTaskCompletionSource;
-    private TaskCompletionSource<byte[]> _readTaskCompletionSource;
-    private TaskCompletionSource<bool> _writeTaskCompletionSource;
+    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);
+        _bluetoothGatt = _device?.ConnectGatt(Application.Context, false, this);
         return await _connectionTaskCompletionSource.Task;
     }
 
@@ -88,7 +95,7 @@ public class Android_ConnectedBluetoothDevice(BluetoothDevice device) : Bluetoot
     public async Task<String?> ReadStringAsync(Guid serviceid, Guid characteristicid)
     {
         var data = await ReadBytesAsync(serviceid,characteristicid);
-        return data != null ? System.Text.Encoding.UTF8.GetString(data) : null;
+        return data != null ? Encoding.UTF8.GetString(data) : null;
     }
 
     private async Task<byte[]?> ReadCharacteristicAsync(BluetoothGattCharacteristic characteristic)
@@ -174,8 +181,9 @@ public class Android_ConnectedBluetoothDevice(BluetoothDevice device) : Bluetoot
         }
     }
     
-    public void Dispose()
+    public new void Dispose()
     {
+        base.Dispose();
         try
         {
             _bluetoothGatt?.Disconnect();
@@ -185,12 +193,15 @@ public class Android_ConnectedBluetoothDevice(BluetoothDevice device) : Bluetoot
         {
             Console.WriteLine($"Error during disposal: {ex.Message}");
         }
-        finally
-        {
-            _bluetoothGatt = null;
-        }
+        
+        _bluetoothGatt?.Dispose();
+        _bluetoothGatt = null;
+        
+        _device?.Dispose();
+        _device = null;
 
         Console.WriteLine("Resources released.");
+        
     }
     
 }

+ 29 - 10
InABox.Avalonia.Platform.Android/Bluetooth/Bluetooth.Android.cs

@@ -29,7 +29,11 @@ public class Android_Bluetooth : IBluetooth
                 var stale = Devices.ToArray().Where(x => (x == null) || (x.LastSeen < DateTime.Now.Subtract(new TimeSpan(0, 0, 5))))
                     .ToArray();
                 if (stale.Any())
+                {
                     Devices.RemoveRange(stale);
+                    Changed?.Invoke(this, EventArgs.Empty);
+                }
+                    
                 Task.Delay(500);
             }
         });
@@ -88,19 +92,34 @@ public class Android_Bluetooth : IBluetooth
     private void DoDeviceFound(ScanResult device, Guid configServiceId)
     {
 
-        var abd = Devices.FirstOrDefault(x => x.ID == device.Device?.Address);
-        if (abd == null)
+        var isTarget = device.ScanRecord?.ServiceUuids?
+            .Any(x=>string.Equals(x.ToString(),configServiceId.ToString(), StringComparison.OrdinalIgnoreCase)) 
+                       ?? false;
+        if (isTarget)
         {
-            var services = device.ScanRecord?.ServiceUuids?
-                .Select(x => Guid.Parse(x.ToString()))
-                .Where(x => !x.ToString().ToUpper().EndsWith("-0000-1000-8000-00805F9B34FB") && configServiceId != x)
-                .ToArray() ?? [];
+            var abd = Devices.FirstOrDefault(x => x.ID == device.Device?.Address);
+            if (abd == null)
+            {
+
+                if (isTarget)
+                {
+                    var services = device.ScanRecord?.ServiceUuids?
+                        .Select(x => Guid.Parse(x.ToString()))
+                        .Where(x => !x.ToString().ToUpper().EndsWith("-0000-1000-8000-00805F9B34FB") &&
+                                    configServiceId != x)
+                        .ToArray() ?? [];
 
-            abd = new Android_BluetoothDevice(device, services, DateTime.Now);
-            Devices.Add(abd);
+                    if (services.Any())
+                    {
+                        abd = new Android_BluetoothDevice(device, services, DateTime.Now);
+                        Devices.Add(abd);
+                        Changed?.Invoke(this, EventArgs.Empty);
+                    }
+                }
+            }
+            else
+                abd.LastSeen = DateTime.Now;
         }
-        else
-            abd.LastSeen = DateTime.Now;
 
     }
 

+ 1 - 1
InABox.Avalonia.Platform.Android/InABox.Avalonia.Platform.Android.csproj

@@ -25,7 +25,7 @@
     <ItemGroup>
       <PackageReference Include="Avalonia" Version="11.2.3" />
       <PackageReference Include="bblanchon.PDFium.Android" Version="135.0.7009" />
-      <PackageReference Include="Microsoft.Maui.Essentials" Version="9.0.40" />
+      <PackageReference Include="Microsoft.Maui.Essentials" Version="8.0.93" />
       <PackageReference Include="PDFtoImage" Version="5.0.0" />
     </ItemGroup>
 

+ 11 - 2
InABox.Avalonia.Platform.Desktop/Bluetooth/Desktop_Bluetooth.cs

@@ -3,7 +3,7 @@ using InABox.Core;
 
 namespace InABox.Avalonia.Platform.Desktop;
 
-public class Desktop_Bluetooth : IBluetooth
+public class Desktop_Bluetooth : IBluetooth, IDisposable
 {
     public Logger? Logger { get; set; }
 
@@ -71,9 +71,18 @@ public class Desktop_Bluetooth : IBluetooth
     {
         if (await IsAvailable())
         {
-            if (device is Desktop_BluetoothDevice d)
+            if (device is Desktop_BluetoothDevice { Device: not null } d)
+            {
                 _adapter.Disconnect(d.Device);
+            }
         }
         return true;
     }
+
+    public void Dispose()
+    {
+        foreach (var device in Devices)
+            device.Dispose();
+        Devices.Clear();
+    }
 }

+ 15 - 3
InABox.Avalonia.Platform.Desktop/Bluetooth/Desktop_BluetoothDevice.cs

@@ -2,11 +2,23 @@
 
 namespace InABox.Avalonia.Platform.Desktop;
 
-public class Desktop_BluetoothDevice(BLEDevice device) : IBluetoothDevice
+public class Desktop_BluetoothDevice : IBluetoothDevice
 {
-    public BLEDevice? Device { get; } = device;
+    public Desktop_BluetoothDevice(BLEDevice device)
+    {
+        Device = device;
+        LastSeen = device.LastSeen;
+    }
+
+    public BLEDevice? Device { get; private set; }
     public string ID => Device?.MacAddress ?? string.Empty;
     public string Name => Device?.Native?.Name ?? "Unknown Device";
     public Guid[] AvailableServices  => Device?.AvailableServices ?? [];
-    public DateTime LastSeen { get; set; } = device.LastSeen;
+    public DateTime LastSeen { get; set; }
+
+    public void Dispose()
+    {
+        Device?.Dispose();
+        Device = null;
+    }
 }

+ 9 - 6
InABox.Avalonia.Platform.Desktop/Bluetooth/Desktop_ConnectedBluetoothDevice.cs

@@ -3,12 +3,15 @@ using BluetoothLENet;
 
 namespace InABox.Avalonia.Platform.Desktop;
 
-public class Desktop_ConnectedBluetoothDevice(BLEDevice device)
-    : Desktop_BluetoothDevice(device), IConnectedBluetoothDevice
+public class Desktop_ConnectedBluetoothDevice : Desktop_BluetoothDevice, IConnectedBluetoothDevice
 {
+    public Desktop_ConnectedBluetoothDevice(BLEDevice device) : base(device)
+    {
+    }
+
     public async Task<bool> WriteBytesAsync(Guid serviceid, Guid characteristicid, byte[] data)
     {
-        var service = Device.Services.FirstOrDefault(x=>x.Native.Uuid == serviceid);
+        var service = Device?.Services.FirstOrDefault(x=>x.Native.Uuid == serviceid);
         if (service != null)
         {
             var characteristic = service.Characteristics.FirstOrDefault(x=>x.Native.Uuid == characteristicid);
@@ -36,10 +39,10 @@ public class Desktop_ConnectedBluetoothDevice(BLEDevice device)
 
     public async Task<byte[]?> ReadBytesAsync(Guid serviceid, Guid characteristicid)
     {
-        var service = Device.Services.FirstOrDefault(x=>x.Native.Uuid == serviceid);
+        var service = Device?.Services.FirstOrDefault(x=>x.Native?.Uuid == serviceid);
         if (service != null)
         {
-            var characteristic = service.Characteristics.FirstOrDefault(x=>x.Native.Uuid == characteristicid);
+            var characteristic = service.Characteristics.FirstOrDefault(x=>x.Native?.Uuid == characteristicid);
             if (characteristic != null)
                 return await characteristic.ReadAsync();
         }
@@ -49,6 +52,6 @@ public class Desktop_ConnectedBluetoothDevice(BLEDevice device)
     public async Task<String?> ReadStringAsync(Guid serviceid, Guid characteristicid)
     {
         var data = await ReadBytesAsync(serviceid,characteristicid);
-        return data != null ? System.Text.Encoding.UTF8.GetString(data) : null;
+        return data != null ? Encoding.UTF8.GetString(data) : null;
     }
 }

+ 8 - 4
InABox.Avalonia.Platform.Desktop/InABox.Avalonia.Platform.Desktop.csproj

@@ -3,8 +3,10 @@
     <PropertyGroup>
         <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
         <ImplicitUsings>enable</ImplicitUsings>
+        <RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
         <Nullable>enable</Nullable>
-        <RootNamespace>InABox.Avalonia.Platform.Desktop2</RootNamespace>
+        <RootNamespace>InABox.Avalonia.Platform.Desktop</RootNamespace>
+        <EnableMsixTooling>true</EnableMsixTooling>
     </PropertyGroup>
 
     <ItemGroup>
@@ -13,8 +15,10 @@
     </ItemGroup>
 
     <ItemGroup>
-      <PackageReference Include="PDFtoImage" Version="5.0.0" />
-      <PackageReference Include="SkiaSharp" Version="3.116.1" />
+        <PackageReference Include="bblanchon.PDFium.Win32" Version="135.0.7019" />
+        <PackageReference Include="Microsoft.Maui.Essentials" Version="8.0.93" />
+        <PackageReference Include="PDFtoImage" Version="5.0.0" />
+        <PackageReference Include="SkiaSharp" Version="3.116.1" />
     </ItemGroup>
-
+    
 </Project>

+ 1 - 1
InABox.Avalonia.Platform.iOS/InABox.Avalonia.Platform.iOS.csproj

@@ -23,7 +23,7 @@
     <ItemGroup>
       <PackageReference Include="Avalonia.iOS" Version="11.2.3" />
       <PackageReference Include="bblanchon.PDFium.iOS" Version="135.0.7009" />
-      <PackageReference Include="Microsoft.Maui.Essentials" Version="9.0.40" />
+      <PackageReference Include="Microsoft.Maui.Essentials" Version="8.0.93" />
       <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
       <PackageReference Include="SkiaSharp" Version="3.116.1" />
     </ItemGroup>

+ 1 - 1
InABox.Avalonia.Platform/Bluetooth/IBluetooth.cs

@@ -4,7 +4,7 @@ using InABox.Core;
 
 namespace InABox.Avalonia.Platform;
 
-public interface IBluetoothDevice
+public interface IBluetoothDevice : IDisposable
 {
      String ID { get; }
      

+ 1 - 1
InABox.Avalonia.Platform/InABox.Avalonia.Platform.csproj

@@ -10,7 +10,7 @@
 
     <ItemGroup>
       <PackageReference Include="Autofac" Version="8.2.0" />
-      <PackageReference Include="Microsoft.Maui.Essentials" Version="9.0.40" />
+      <PackageReference Include="Microsoft.Maui.Essentials" Version="8.0.93" />
     </ItemGroup>
 
     <ItemGroup>

+ 1 - 0
InABox.Avalonia.Platform/PlatformTools.cs

@@ -1,6 +1,7 @@
 using Autofac;
 using InABox.Avalonia.Platform;
 using InABox.Core;
+using Exception = System.Exception;
 
 namespace InABox.Avalonia.Platform;
 

+ 10 - 17
InABox.Avalonia/Components/CountdownTimer/AvaloniaCountdownTimer.cs

@@ -2,22 +2,15 @@
 using Avalonia.Controls;
 using Avalonia.Media;
 using Avalonia.Threading;
-using System;
-using System.IO;
-using System.Net;
 using System.Windows.Input;
-using Avalonia.Data;
-using Avalonia.Svg.Skia;
 using InABox.Core;
-using SkiaSharp;
-using Svg.Skia;
 
 namespace InABox.Avalonia.Components;
 
 public class CircularCountdownTimer : Control
 {
-    private DispatcherTimer _timer;
-    private DateTime? _startTime = null;
+    private readonly DispatcherTimer _timer;
+    private DateTime? _startTime;
     
     public static readonly StyledProperty<IImage?> ImageProperty =
         AvaloniaProperty.Register<CircularCountdownTimer, IImage?>(nameof(Image));
@@ -37,19 +30,19 @@ public class CircularCountdownTimer : Control
         set => SetValue(IsActiveProperty, value);
     }
     
-    public static readonly StyledProperty<ICommand> StartedProperty =
-        AvaloniaProperty.Register<CircularCountdownTimer, ICommand>(nameof(Started));
+    public static readonly StyledProperty<ICommand?> StartedProperty =
+        AvaloniaProperty.Register<CircularCountdownTimer, ICommand?>(nameof(Started));
 
-    public ICommand Started
+    public ICommand? Started
     {
         get => GetValue(StartedProperty);
         set => SetValue(StartedProperty, value);
     }
     
-    public static readonly StyledProperty<ICommand> StoppedProperty =
-        AvaloniaProperty.Register<CircularCountdownTimer, ICommand>(nameof(Stopped));
+    public static readonly StyledProperty<ICommand?> StoppedProperty =
+        AvaloniaProperty.Register<CircularCountdownTimer, ICommand?>(nameof(Stopped));
 
-    public ICommand Stopped
+    public ICommand? Stopped
     {
         get => GetValue(StoppedProperty);
         set => SetValue(StoppedProperty, value);
@@ -119,9 +112,9 @@ public class CircularCountdownTimer : Control
     
     public CircularCountdownTimer()
     {
-        _timer = new DispatcherTimer
+        _timer = new DispatcherTimer(DispatcherPriority.MaxValue)
         {
-            Interval = TimeSpan.FromMilliseconds(100) // Update every 100ms
+            Interval = TimeSpan.FromMilliseconds(200),
         };
         _timer.Tick += TimerTick;
     }

+ 5 - 1
InABox.Avalonia/InABox.Avalonia.csproj

@@ -29,7 +29,7 @@
       <PackageReference Include="Material.Avalonia" Version="3.9.2" />
       <PackageReference Include="Material.Avalonia.DataGrid" Version="3.9.2" />
       <PackageReference Include="Material.Avalonia.Dialogs" Version="3.9.2" />
-      <PackageReference Include="Microsoft.Maui.Essentials" Version="9.0.40" />
+      <PackageReference Include="Microsoft.Maui.Essentials" Version="8.0.93" />
       <PackageReference Include="Serilog" Version="4.2.0" />
       <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
       <PackageReference Include="SkiaSharp" Version="3.116.1" />
@@ -68,4 +68,8 @@
       <Folder Include="Components\Modules\" />
     </ItemGroup>
 
+    <ItemGroup>
+      <UpToDateCheckInput Remove="Dialogs\TextBoxDialog\TextBoxDialogView.axaml" />
+    </ItemGroup>
+
 </Project>

+ 3 - 0
InABox.Serialization.Shared/InABox.Serialization.Shared.shproj

@@ -10,6 +10,9 @@
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
   <PropertyGroup />
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <OutputPath>bin\Debug\</OutputPath>
+  </PropertyGroup>
   <Import Project="InABox.Serialization.Shared.projitems" Label="Shared" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
 </Project>