From 66a86d3e14182b2081c57476675416652fbb040a Mon Sep 17 00:00:00 2001 From: Paul-Winpenny <92634321+Paul-Winpenny@users.noreply.github.com> Date: Wed, 23 Oct 2024 17:44:02 +0100 Subject: [PATCH] At this point the sending and receiving messages is working --- App/RobobinApp/Interfaces/BLEInterfaces.cs | 20 ++ .../ViewModels/ConnectionPageViewModel.cs | 245 +++++++----------- App/RobobinApp/Views/ConnectionPage.xaml | 17 ++ 3 files changed, 137 insertions(+), 145 deletions(-) create mode 100644 App/RobobinApp/Interfaces/BLEInterfaces.cs diff --git a/App/RobobinApp/Interfaces/BLEInterfaces.cs b/App/RobobinApp/Interfaces/BLEInterfaces.cs new file mode 100644 index 00000000..181124d9 --- /dev/null +++ b/App/RobobinApp/Interfaces/BLEInterfaces.cs @@ -0,0 +1,20 @@ +using Plugin.BLE.Abstractions.Contracts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Robobin.Interfaces +{ + public interface IBluetoothLEService + { + IBluetoothLE Current { get; } + } + + public interface IAdapterService + { + IAdapter Adapter { get; } + } + +} diff --git a/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs b/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs index 3cd816e9..14acad7d 100644 --- a/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs +++ b/App/RobobinApp/ViewModels/ConnectionPageViewModel.cs @@ -18,6 +18,7 @@ using Windows.Devices.WiFi; using System.Reflection.PortableExecutable; using Plugin.BLE.Windows; using System.Text; +using System.Windows.Documents; namespace RobobinApp.ViewModels { @@ -32,6 +33,9 @@ namespace RobobinApp.ViewModels public ICommand ConnectCommand { get; } public ICommand SendWifiInfoCommand { get; } public ICommand DisconnectCommand { get; } + public ICommand TestReadOperation { get; } + public ICommand TestWriteOperation { get; } + private bool _isConnected; private string ssid; private string password; @@ -39,6 +43,7 @@ namespace RobobinApp.ViewModels public const string SendReceiveServiceUUID = "00000001-710e-4a5b-8d75-3e5b444bc3cf"; public const string rxUUID = "00000002-710e-4a5b-8d75-3e5b444bc3cf"; public const string wxUUID = "00000003-710e-4a5b-8d75-3e5b444bc3cf"; + public string tempUnit = "C"; public bool IsConnected { @@ -50,17 +55,31 @@ namespace RobobinApp.ViewModels OnPropertyChanged(nameof(ConnectButtonText)); // Update button text when connection state changes } } + private ICharacteristic _readCharacteristic; + private ICharacteristic _writeCharacteristic; + + public ICharacteristic ReadCharacteristic + { + get => _readCharacteristic; + set + { + _readCharacteristic = value; + OnPropertyChanged(); + } + } - public string SSID + public ICharacteristic WriteCharacteristic { - get => ssid; + get => _writeCharacteristic; set { - ssid = value; - OnPropertyChanged(nameof(SSID)); + _writeCharacteristic = value; + OnPropertyChanged(); } } + + public string Password { get => password; @@ -76,7 +95,7 @@ namespace RobobinApp.ViewModels public string ConnectButtonText => IsConnected ? "Disconnect" : "Connect"; private bool _isWifiNetworkSelectionVisible; private WifiNetwork _selectedWifiNetwork; - + public bool IsWifiNetworkSelectionVisible { get => _isWifiNetworkSelectionVisible; @@ -94,9 +113,12 @@ namespace RobobinApp.ViewModels WifiNetworks = new ObservableCollection<WifiNetwork>(); ConnectCommand = new Command(OnConnect); DisconnectCommand = new Command(OnDisconnect); - SendWifiInfoCommand = new Command(OnSendWifiInfo); GoHomeCommand = new Command(async () => await OnGoHome()); ConnectCommand = new Command(OnToggleConnection); + TestReadOperation = new Command(async () => await ReadOperationAsync()); + SendWifiInfoCommand = new Command(OnSendWifiInfo); + + TestWriteOperation = new Command(async() => await PingPiASync()); _bluetoothLE = CrossBluetoothLE.Current; _adapter = _bluetoothLE.Adapter; _adapter.DeviceDiscovered += OnDeviceDiscovered; @@ -104,36 +126,53 @@ namespace RobobinApp.ViewModels Debug.WriteLine("Checking and requesting Bluetooth permissions."); CheckAndRequestBluetoothPermissions(); - //ScanForWifiNetworks(); } - private async void ScanForWifiNetworks() + + private void OnSendWifiInfo(object obj) { - WifiNetworks.Clear(); - Debug.WriteLine("Scanning for Wi-Fi networks..."); + var SSID = SelectedWifiNetwork.SSID; + var result = WriteOperationAsync("CONNECT", SSID + "," + password); + Debug.WriteLine($"Result: {result}"); + } - var wifiAdapter = await GetWifiAdapterAsync(); - if (wifiAdapter == null) + private async Task PingPiASync() + { + if (tempUnit.Equals("C")) { - Debug.WriteLine("Wi-Fi adapter not found."); - return; + tempUnit = "F"; + } else + { + tempUnit = "C"; } + WriteOperationAsync(tempUnit); + + } - await wifiAdapter.ScanAsync(); - Debug.Write("Scanning for networks"); - var networks = wifiAdapter.NetworkReport.AvailableNetworks; + private async void ScanForWifiNetworks() + { + WifiNetworks.Clear(); + Debug.WriteLine("Retrieving Wifi networks from readCharacteristic"); - var addedSsids = new HashSet<string>(); // To keep track of added SSIDs + //Delay 5 seconds + await Task.Delay(5000); - foreach (var network in networks) + //var networks = await ReadOperationAsync(); + var networks = "Network1\nNetwork2\nNetwork3"; // For testing + Debug.WriteLine(networks); + var delimiter = "\n"; + var networkList = networks.Split(delimiter); + var addedSsids = new HashSet<string>(); + + foreach (var network in networkList) { - Debug.Write("This network exists: " + network.Ssid); + Debug.Write("This network exists: " + network); - if (addedSsids.Add(network.Ssid)) + if (addedSsids.Add(network)) { var wifiNetwork = new WifiNetwork { - SSID = network.Ssid, - SignalStrength = network.NetworkRssiInDecibelMilliwatts + SSID = network, + SignalStrength = 0.0 }; Microsoft.Maui.Controls.Device.BeginInvokeOnMainThread(() => WifiNetworks.Add(wifiNetwork)); @@ -143,67 +182,6 @@ namespace RobobinApp.ViewModels } - private async Task<WiFiAdapter> GetWifiAdapterAsync() - { - var result = await WiFiAdapter.FindAllAdaptersAsync(); - return result.FirstOrDefault(); // Get the first available Wi-Fi adapter - } - - private async void OnSendWifiInfo(object obj) - { - if (SelectedWifiNetwork != null) - { - Debug.WriteLine("Wifi been selected"); - Debug.WriteLine($"Selected Network {SelectedWifiNetwork.SSID}"); - } - if (!_isConnected || _connectedDevice == null) - { - Debug.WriteLine("Cannot send WiFi information: No device is connected."); - await Application.Current.MainPage.DisplayAlert("Error", "No device is connected.", "OK"); - return; - } - - try - { - Debug.WriteLine($"Sending WiFi information to {_connectedDevice.Name}..."); - - - var services = await _connectedDevice.GetServicesAsync(); - var uartService = services.FirstOrDefault(s => s.Id == Guid.Parse("6e400001-b5a3-f393-e0a9-e50e24dcca9e")); - - if (uartService == null) - { - Debug.WriteLine("UART service not found."); - await Application.Current.MainPage.DisplayAlert("Error", "UART service not found on the device.", "OK"); - return; - } - - var characteristics = await uartService.GetCharacteristicsAsync(); - var rxCharacteristic = characteristics.FirstOrDefault(c => c.Id == Guid.Parse(rxUUID)); - - if (rxCharacteristic == null) - { - Debug.WriteLine("RX characteristic not found."); - await Application.Current.MainPage.DisplayAlert("Error", "RX characteristic not found on the device.", "OK"); - return; - } - - string wifiInfo = $"{SSID},{Password}"; - byte[] data = System.Text.Encoding.UTF8.GetBytes(wifiInfo); - - await rxCharacteristic.WriteAsync(data); - - Debug.WriteLine("WiFi information sent successfully."); - await Application.Current.MainPage.DisplayAlert("Success", "WiFi information sent successfully.", "OK"); - } - catch (Exception ex) - { - Debug.WriteLine($"Error sending WiFi information: {ex.Message}"); - await Application.Current.MainPage.DisplayAlert("Error", $"Failed to send WiFi information: {ex.Message}", "OK"); - } - } - - public BluetoothDevice SelectedDevice { get => _selectedDevice; @@ -351,29 +329,38 @@ namespace RobobinApp.ViewModels if (_connectedDevice != null) { Debug.WriteLine($"Successfully connected to {SelectedDevice.Name}."); + // var services = await _connectedDevice.GetServicesAsync(); + Debug.WriteLine("Services gotten"); IsWifiNetworkSelectionVisible = true; // Iterate through the discovered services + //var service = await _connectedDevice.GetServiceAsync(Guid.Parse("00000001-710e-4a5b-8d75-3e5b444bc3cf")); foreach (var service in services) + { Debug.WriteLine($"Service: ID={service.Id}, Name={service.Name}"); if (service.Id.Equals(Guid.Parse("00000001-710e-4a5b-8d75-3e5b444bc3cf")) ) { + Debug.WriteLine("Found RW service"); var characteristics = await service.GetCharacteristicsAsync(); foreach (var characteristic in characteristics) { - Debug.WriteLine($"{characteristic.Uuid} | {characteristic.Name}"); + var descriptor = await characteristic.GetDescriptorsAsync(); + Debug.WriteLine($"{characteristic.Uuid} | {characteristic.Name} | {descriptor}"); if (characteristic.Uuid.Equals(rxUUID)) { - var result = await ReadOperationAsync(characteristic); + ReadCharacteristic = characteristic; + var result = await ReadOperationAsync(); } else if (characteristic.Uuid.Equals(wxUUID)) { - const string data = "C"; - await WriteOperationAsync(characteristic,data); + WriteCharacteristic = characteristic; + const string command = "SCAN"; + await WriteOperationAsync(command); + ScanForWifiNetworks(); } } @@ -382,7 +369,7 @@ namespace RobobinApp.ViewModels var transmissionService = services.FirstOrDefault(s => s.Id == Guid.Parse(SendReceiveServiceUUID)); var readCharacteristic = await transmissionService.GetCharacteristicAsync(Guid.Parse(rxUUID)); - var result2 = await ReadOperationAsync(readCharacteristic); + var result2 = await ReadOperationAsync(); } else @@ -415,14 +402,20 @@ namespace RobobinApp.ViewModels - private async Task<string> ReadOperationAsync(ICharacteristic characteristic, int retryCount = 3) + private async Task<string> ReadOperationAsync(int retryCount = 3) { + if (ReadCharacteristic == null) + { + Debug.WriteLine("Read characteristic is not set."); + return "Failure"; + } + Debug.WriteLine($"READ COMMAND : {ReadCharacteristic.Uuid}"); for (int attempt = 1; attempt <= retryCount; attempt++) { try { - Debug.WriteLine($"Attempt {attempt}: Reading from characteristic {characteristic.Uuid}"); - var temperatureData = await characteristic.ReadAsync(); + Debug.WriteLine($"Attempt {attempt}: Reading from characteristic {ReadCharacteristic.Uuid}"); + var temperatureData = await ReadCharacteristic.ReadAsync(); var temperatureValue = System.Text.Encoding.UTF8.GetString(temperatureData.data); Debug.WriteLine($"Temperature Value: {temperatureValue}"); return temperatureValue; @@ -440,21 +433,27 @@ namespace RobobinApp.ViewModels } } } - return null; + return "Failure"; } - private async Task WriteOperationAsync(ICharacteristic characteristic,string sendData, int retryCount = 3) + private async Task<string> WriteOperationAsync(string command, string arguments="", int retryCount = 3) { - byte[] data = System.Text.Encoding.UTF8.GetBytes(sendData); + if (WriteCharacteristic == null) + { + Debug.WriteLine("Write characteristic is not set."); + return "Failure"; + } + string joinedData = command + ":" + arguments; + Debug.WriteLine($"WRITE COMMAND {joinedData}, UUID: {WriteCharacteristic}"); + byte[] data = System.Text.Encoding.UTF8.GetBytes(joinedData); for (int attempt = 1; attempt <= retryCount; attempt++) { try - { - Debug.WriteLine($"Attempt {attempt}: Writing to characteristic {characteristic.Uuid}"); - await characteristic.WriteAsync(data); + { + await WriteCharacteristic.WriteAsync(data); Debug.WriteLine("Write operation succeeded."); - return; + return "Success"; } catch (Exception ex) { @@ -469,6 +468,8 @@ namespace RobobinApp.ViewModels } } } + return "Failure"; + } @@ -505,50 +506,4 @@ namespace RobobinApp.ViewModels } - - /** - * - var transmitService = services.FirstOrDefault(s => s.Id == Guid.Parse(SendReceiveServiceUUID)); - Debug.WriteLine("Transmit service was accessed"); - Debug.WriteLine($"{transmitService.Name} : {transmitService.Id}"); - if (transmitService == null) - { - Debug.WriteLine("Transmit service wasn't found"); - } - var characteristics = await transmitService.GetCharacteristicsAsync(); - - foreach (var characteristic in characteristics) - { - Debug.WriteLine($"{characteristic.Uuid} | {characteristic.Name}"); - if (characteristic.Uuid.Equals(rxUUID)) - { - var result = await ReadOperationAsync(characteristic); - - } - else if (characteristic.Uuid.Equals(wxUUID)) - { - //await WriteOperationAsync(characteristic); - - } - } - - } - catch (DeviceConnectionException ex) - { - Debug.WriteLine($"Connection error: {ex.Message}"); - await Application.Current.MainPage.DisplayAlert("Connection Error", $"Failed to connect: {ex.Message}", "OK"); - } - catch (TaskCanceledException ex) - { - Debug.WriteLine($"TaskCanceledException: {ex.Message}"); - await Application.Current.MainPage.DisplayAlert("Connection Error", "Connection timed out.", "OK"); - _connectedDevice = null; - IsConnected = false; - } - catch (Exception ex) - { - Debug.WriteLine($"General connection error: {ex.Message}"); - await Application.Current.MainPage.DisplayAlert("Connection Error", $"An error occurred: {ex.Message}", "OK"); - } - } **/ } diff --git a/App/RobobinApp/Views/ConnectionPage.xaml b/App/RobobinApp/Views/ConnectionPage.xaml index a7df6ffa..42521cba 100644 --- a/App/RobobinApp/Views/ConnectionPage.xaml +++ b/App/RobobinApp/Views/ConnectionPage.xaml @@ -121,5 +121,22 @@ VerticalOptions="End" /> </StackLayout> </StackLayout> + <StackLayout Padding="10" + BackgroundColor="Black" + HorizontalOptions="FillAndExpand" + VerticalOptions="Start"> + <Label Text="Admin Panel:" + FontSize="Medium" + HorizontalOptions="Start" /> + + <Button Text= "Test Read Operation" + Command="{Binding TestReadOperation}" + HorizontalOptions="Center" + VerticalOptions="End" /> + <Button Text="Test Write Operation" + Command="{Binding TestWriteOperation}" + HorizontalOptions="Center" + VerticalOptions="End" /> + </StackLayout> </StackLayout> </ContentPage> -- GitLab