如何在.NET MAUI xaml文件(UI)中显示SerialPort缓冲区数据(真实的)?

gwo2fgha  于 2023-08-01  发布在  .NET
关注(0)|答案(1)|浏览(231)

我正在使用.NET MAUI构建Windows桌面应用程序。该应用程序使用SerialPort连接到LoRa扫描仪。扫描仪扫描LoRa网络,并每秒从虚拟LoRa发射器获取数据约8次。扫描仪读取传输的数据,其中包含网络名称,信号强度,经度,纬度等。在我的UI中,我有一个专门用于网络名称的部分,我一直试图用SerialPort缓冲区数据中的网络名称填充列表。
我面临的问题是,网络名称只显示一次或有时根本不出现,而事实上,当我运行扫描时,它必须显示约8次。在我的情况下,现在它是一个具有相同网络名称的网络。但是,如果我有多个虚拟LoRa发射器,只有一个或没有将显示在UI中。
我目前正在UI后面的代码中建立连接(计划在我让它工作时将其移动到一个单独的文件中)。我还使用MainThread.BeingInvokeOnMainThread来显示xaml列表中的名称(不工作)。以下是我在myPage.xaml.cs中所做的:

  1. namespace Scanner_MAUI.Pages;
  2. public partial class RealTimeData : ContentPage
  3. {
  4. private SerialPort serialPort;
  5. public RealTimeData()
  6. {
  7. InitializeComponent();
  8. BindingContext = this;
  9. NetworkNames = new ObservableCollection<string>();
  10. //NetworkListView.ItemsSource = NetworkNames;
  11. }
  12. class ScannerData
  13. {
  14. public string Name { get; set; }
  15. //...
  16. }
  17. private void StartMenuItem_Clicked(object sender, EventArgs e)
  18. {
  19. // TODO: Connect to the LoRa scanner and start scanning
  20. ConnectToScanner();
  21. }
  1. public void ConnectToScanner()
  2. {
  3. // Clear the NetworkNames list before connecting to the scanner
  4. //NetworkNames.Clear();
  5. try
  6. {
  7. serialPort = new SerialPort("COMx", baudrate);
  8. serialPort.Open();
  9. Debug.WriteLine("Serial Port conn created");
  10. Debug.WriteLine("Serial Port Is Open: " + serialPort.IsOpen);
  11. var data = new byte[] { (byte)'1', 13 };
  12. serialPort.Write(data, 0, data.Length);
  13. // TODO: Handle the scanner's output and display the information in your app
  14. serialPort.DataReceived += SerialPort_DataReceived;
  15. //Debug.WriteLine("test");
  16. }
  17. catch (Exception ex)
  18. {
  19. // Handle the exception
  20. Debug.WriteLine($"Failed to connect to the scanner: {ex.Message}");
  21. }
  22. }
  1. public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
  2. {
  3. //NetworkNames = new ObservableCollection<string>();
  4. //NetworkNames.Clear();
  5. try
  6. {
  7. while (serialPort.BytesToRead > 0)
  8. {
  9. string DataIn = serialPort.ReadLine();
  10. //Debug.WriteLine("Data received from the scanner: " + DataIn);
  11. // Process the received data and extract the fields
  12. //ScannerData scannerData = ProcessReceivedData(DataIn);
  13. //Task.Delay(1000).Wait();
  14. foreach (string name in NetworkNames)
  15. {
  16. Debug.WriteLine($"Name: {name}");
  17. }
  18. //ProcessReceivedData(DataIn);
  19. MainThread.BeginInvokeOnMainThread(() =>
  20. {
  21. ProcessReceivedData(DataIn);
  22. NetworkListView.ItemsSource = NetworkNames;
  23. });
  24. }
  25. }
  26. catch (OperationCanceledException)
  27. {
  28. // Handle the cancellation if needed
  29. Debug.WriteLine("Reading data from the scanner was canceled.");
  30. }
  31. catch (Exception ex)
  32. {
  33. // Handle other exceptions
  34. Debug.WriteLine($"Failed to read data from the scanner: {ex.Message}");
  35. }
  36. }
  37. public ObservableCollection<string> NetworkNames { get; set; } = new ObservableCollection<string>();
  38. private ScannerData ProcessReceivedData(string data)
  39. {
  40. ScannerData scannerData = new ScannerData();
  41. // Parse and extract relevant information from the data string
  42. string[] fields = data.Split(new string[] { ", " }, StringSplitOptions.None);
  43. Debug.WriteLine($"Received data fields count: {fields.Length}");
  44. //Debug.WriteLine($"Received data fields: {string.Join(", ", fields)}");
  45. if (fields.Length >= 8)
  46. {
  47. scannerData.Message = fields[0].Split(':')[1].Trim();
  48. string input = fields[1];
  49. string startMarker = "b'";
  50. string endMarker = "'";
  51. int startIndex = input.IndexOf(startMarker) + startMarker.Length;
  52. int endIndex = input.IndexOf(endMarker, startIndex);
  53. if (startIndex >= 0 && endIndex >= 0)
  54. {
  55. string extractedString = input.Substring(startIndex, endIndex - startIndex);
  56. scannerData.Name = extractedString;
  57. // Add non-null and non-empty names to the collection
  58. //if (!string.IsNullOrEmpty(scannerData.Name))
  59. //{
  60. NetworkNames.Add(extractedString);
  61. //}
  62. //NetworkNames.Add(scannerData.Name); // Add network name to the list
  63. }
  64. ....More code
  65. }
  66. else
  67. {
  68. Debug.WriteLine("Insufficient fields in the data string.");
  69. }
  70. return scannerData;
  71. }
  72. private double? ParseNullableDouble(string value)
  73. {
  74. if (double.TryParse(value, out double result))
  75. return result;
  76. return null;
  77. }

最后是xaml文件中的列表:

  1. <ListView x:Name="NetworkListView" ItemsSource="{Binding NetworkNames}">
  2. <ListView.ItemTemplate>
  3. <DataTemplate>
  4. <TextCell Text="{Binding}" />
  5. </DataTemplate>
  6. </ListView.ItemTemplate>
  7. </ListView>


下面是我在下面的图像中得到的结果:x1c 0d1x在本图中,网络名称应显示在左列中。在控制台中,名称显示得很好。
由于某些原因,有时一个名字显示在左栏中。
我应该采取什么方法,使它能够显示网络名称,而扫描?我做错了什么!
请注意,我是初学者。非常感谢您的帮助!

sc4hvdpw

sc4hvdpw1#

回答晚了。谢谢大家的帮助。
我做了以下更改,现在预期的行为工作。
在SerialPortConn文件中,我添加了一个ObservableCollection,并在SerialPort_DataReceived(位于同一文件中)函数中添加了MainThread的名称:

  1. public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
  2. {
  3. try
  4. {
  5. while (serialPort.BytesToRead > 0)
  6. {
  7. string DataIn = serialPort.ReadLine();
  8. //Debug.WriteLine("Data received from the scanner: " + DataIn);
  9. // Process the received data and extract the fields
  10. Network data = ProcessReceivedData(DataIn);
  11. MainThread.BeginInvokeOnMainThread(() =>
  12. {
  13. // Check if the data name is not empty or null
  14. if (!string.IsNullOrEmpty(data.Name))
  15. {
  16. // Find the existing network with the same name, if it exists
  17. Network existingNetwork = NetworkNames.FirstOrDefault(network => network.Name == data.Name);
  18. if (existingNetwork != null)
  19. {
  20. existingNetwork.RSSI = data.RSSI;
  21. existingNetwork.Name = data.Name;
  22. Debug.WriteLine("strength: " + strength);
  23. Debug.WriteLine("existingNetwork: " + existingNetwork.Name + " " + existingNetwork.RSSI);
  24. }
  25. else
  26. {
  27. // Create a new network with the name and initialize its RSSIList with the current RSSI value
  28. NetworkNames.Add(new Network { Name = data.Name, RSSI = data.RSSI });
  29. // Print the network name and its RSSIList for debugging purposes
  30. foreach (Network network in NetworkNames)
  31. {
  32. Debug.WriteLine("NetworkName: " + network.Name + " " + network.RSSI);
  33. }
  34. foreach (Network network in NetworkValues)
  35. {
  36. Debug.WriteLine("NetworkValues: " + network.Name + " " + network.RSSI);
  37. }
  38. }
  39. });
  40. }
  41. }

字符串
在Content页面中,我添加了以下行,将NetworkNamesObservableCollection分配给xaml文件中的listView

  1. NetworkListView.ItemsSource = scannerConn.NetworkNames;


最后,在xaml文件中,我去掉了ItemsSource,因为它已经在后面的代码中定义了:

  1. <ListView x:Name="NetworkListView">
  2. <ListView.ItemTemplate>
  3. <DataTemplate>
  4. <TextCell Text="{Binding}" />
  5. </DataTemplate>
  6. </ListView.ItemTemplate>
  7. </ListView>

展开查看全部

相关问题