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

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

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

namespace Scanner_MAUI.Pages;

public partial class RealTimeData : ContentPage
{
   
    private SerialPort serialPort;

    public RealTimeData()
    {
        InitializeComponent();
        BindingContext = this;
        NetworkNames = new ObservableCollection<string>();
        //NetworkListView.ItemsSource = NetworkNames;

    }
    class ScannerData
    {
        public string Name { get; set; }
        //...
    }
    private void StartMenuItem_Clicked(object sender, EventArgs e)
    {
        // TODO: Connect to the LoRa scanner and start scanning
        ConnectToScanner();
    }
public void ConnectToScanner()
    {
        // Clear the NetworkNames list before connecting to the scanner
        //NetworkNames.Clear();
        try
        {
            serialPort = new SerialPort("COMx", baudrate);

            serialPort.Open();
            Debug.WriteLine("Serial Port conn created");
            Debug.WriteLine("Serial Port Is Open: " + serialPort.IsOpen);

            var data = new byte[] { (byte)'1', 13 };
            serialPort.Write(data, 0, data.Length);

            // TODO: Handle the scanner's output and display the information in your app
            serialPort.DataReceived += SerialPort_DataReceived;

            //Debug.WriteLine("test");
        }
        catch (Exception ex)
        {
            // Handle the exception
            Debug.WriteLine($"Failed to connect to the scanner: {ex.Message}");
        }
    }
public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        //NetworkNames = new ObservableCollection<string>();
        //NetworkNames.Clear();
        
        try
        {
            while (serialPort.BytesToRead > 0)
            {
            string DataIn = serialPort.ReadLine();
                //Debug.WriteLine("Data received from the scanner: " + DataIn);

                // Process the received data and extract the fields
                //ScannerData scannerData = ProcessReceivedData(DataIn);

                //Task.Delay(1000).Wait();
                foreach (string name in NetworkNames)
                {
                    Debug.WriteLine($"Name: {name}");
                }
                //ProcessReceivedData(DataIn);
                MainThread.BeginInvokeOnMainThread(() =>
                {
                    ProcessReceivedData(DataIn);
                    NetworkListView.ItemsSource = NetworkNames;
                });
            }
        }
        catch (OperationCanceledException)
        {
            // Handle the cancellation if needed
            Debug.WriteLine("Reading data from the scanner was canceled.");
        }
        catch (Exception ex)
        {
            // Handle other exceptions
            Debug.WriteLine($"Failed to read data from the scanner: {ex.Message}");
        }
        
    }
    
    public ObservableCollection<string> NetworkNames { get; set; } = new ObservableCollection<string>();

    private ScannerData ProcessReceivedData(string data)
    {
        ScannerData scannerData = new ScannerData();

        // Parse and extract relevant information from the data string
        string[] fields = data.Split(new string[] { ", " }, StringSplitOptions.None);

        Debug.WriteLine($"Received data fields count: {fields.Length}");
        //Debug.WriteLine($"Received data fields: {string.Join(", ", fields)}");

        if (fields.Length >= 8)
        {
            scannerData.Message = fields[0].Split(':')[1].Trim();
            string input = fields[1];
            string startMarker = "b'";
            string endMarker = "'";

            int startIndex = input.IndexOf(startMarker) + startMarker.Length;
            int endIndex = input.IndexOf(endMarker, startIndex);

            if (startIndex >= 0 && endIndex >= 0)
            {
                string extractedString = input.Substring(startIndex, endIndex - startIndex);
                scannerData.Name = extractedString;

                // Add non-null and non-empty names to the collection
                //if (!string.IsNullOrEmpty(scannerData.Name))
                //{
                    NetworkNames.Add(extractedString);
                //}
                //NetworkNames.Add(scannerData.Name); // Add network name to the list
            }
            ....More code 
        }
        else
        {
            Debug.WriteLine("Insufficient fields in the data string.");
        }

        return scannerData;
    }

    private double? ParseNullableDouble(string value)
    {
        if (double.TryParse(value, out double result))
            return result;

        return null;
    }

最后是xaml文件中的列表:

<ListView x:Name="NetworkListView" ItemsSource="{Binding NetworkNames}">
  <ListView.ItemTemplate>
     <DataTemplate>
        <TextCell Text="{Binding}" />
     </DataTemplate>
  </ListView.ItemTemplate>
</ListView>


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

sc4hvdpw

sc4hvdpw1#

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

public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {

        try
        {
            while (serialPort.BytesToRead > 0)
            {
            string DataIn = serialPort.ReadLine();
                //Debug.WriteLine("Data received from the scanner: " + DataIn);

               // Process the received data and extract the fields
                Network data = ProcessReceivedData(DataIn);
               MainThread.BeginInvokeOnMainThread(() =>
                {
                    // Check if the data name is not empty or null
                    if (!string.IsNullOrEmpty(data.Name))
                    {
                        // Find the existing network with the same name, if it exists
                        Network existingNetwork = NetworkNames.FirstOrDefault(network => network.Name == data.Name);

                        if (existingNetwork != null)
                        {
                          
                            existingNetwork.RSSI = data.RSSI;
                            existingNetwork.Name = data.Name;
                            
                            Debug.WriteLine("strength: " + strength);
                            Debug.WriteLine("existingNetwork: " + existingNetwork.Name + " " + existingNetwork.RSSI);
                        }
                        else
                        {
                            // Create a new network with the name and initialize its RSSIList with the current RSSI value

                            NetworkNames.Add(new Network { Name = data.Name, RSSI = data.RSSI });

                        // Print the network name and its RSSIList for debugging purposes
                        foreach (Network network in NetworkNames)
                        {
                            Debug.WriteLine("NetworkName: " + network.Name + " " + network.RSSI);
                        }
                        foreach (Network network in NetworkValues)
                        {
                            Debug.WriteLine("NetworkValues: " + network.Name + " " + network.RSSI);
                        }

                    }
                });
        }
        
    }

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

NetworkListView.ItemsSource = scannerConn.NetworkNames;


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

<ListView x:Name="NetworkListView">
  <ListView.ItemTemplate>
     <DataTemplate>
        <TextCell Text="{Binding}" />
     </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

相关问题