Программа Serial Test Loopback на универсальной платформе Windows - версия VB.NET не работает? - PullRequest
0 голосов
/ 07 мая 2018

У меня проблема с созданием кода перевода C # в VB.NET в тестовом примере UWP Serial UART, обнаруженном на странице Microsoft. Программа на C # работает отлично, но когда я пытаюсь запустить в VB.NET, в тот момент, когда я пытаюсь подключить порт в RaspBerry Pi 3, переменная «serialPort» вводится без значения и возвращается, как на изображении здесь serialPort без значения.

Я дизонибилизирую исходный код здесь в C # и VB.NET, чтобы сравнить, если что-то не хватает (вероятно, да) в момент, когда был сделан перевод кода.

Вот изображение C # serialPort со значением.

C # ПРИМЕР

// Copyright (c) Microsoft. All rights reserved.

using System;
using System.Collections.ObjectModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using System.Threading;
using System.Threading.Tasks;

namespace SerialSample
{    
    public sealed partial class MainPage : Page
    {
        /// <summary>
        /// Private variables
        /// </summary>
        private SerialDevice serialPort = null;
        DataWriter dataWriteObject = null;
        DataReader dataReaderObject = null;

        private ObservableCollection<DeviceInformation> listOfDevices;
        private CancellationTokenSource ReadCancellationTokenSource;

        public MainPage()
        {
            this.InitializeComponent();            
            comPortInput.IsEnabled = false;
            sendTextButton.IsEnabled = false;
            listOfDevices = new ObservableCollection<DeviceInformation>();
            ListAvailablePorts();
        }

        /// <summary>
        /// ListAvailablePorts
        /// - Use SerialDevice.GetDeviceSelector to enumerate all serial devices
        /// - Attaches the DeviceInformation to the ListBox source so that DeviceIds are displayed
        /// </summary>
        private async void ListAvailablePorts()
        {
            try
            {
                string aqs = SerialDevice.GetDeviceSelector();
                var dis = await DeviceInformation.FindAllAsync(aqs);

                status.Text = "Select a device and connect";

                for (int i = 0; i < dis.Count; i++)
                {
                    listOfDevices.Add(dis[i]);
                }

                DeviceListSource.Source = listOfDevices;
                comPortInput.IsEnabled = true;
                ConnectDevices.SelectedIndex = -1;
            }
            catch (Exception ex)
            {
                status.Text = ex.Message;
            }
        }

        /// <summary>
        /// comPortInput_Click: Action to take when 'Connect' button is clicked
        /// - Get the selected device index and use Id to create the SerialDevice object
        /// - Configure default settings for the serial port
        /// - Create the ReadCancellationTokenSource token
        /// - Start listening on the serial port input
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void comPortInput_Click(object sender, RoutedEventArgs e)
        {
            var selection = ConnectDevices.SelectedItems;

            if (selection.Count <= 0)
            {
                status.Text = "Select a device and connect";
                return;
            }

            DeviceInformation entry = (DeviceInformation)selection[0];         

            try
            {                
                serialPort = await SerialDevice.FromIdAsync(entry.Id);
                if (serialPort == null) return;

                // Disable the 'Connect' button 
                comPortInput.IsEnabled = false;

                // Configure serial settings
                serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
                serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);                
                serialPort.BaudRate = 9600;
                serialPort.Parity = SerialParity.None;
                serialPort.StopBits = SerialStopBitCount.One;
                serialPort.DataBits = 8;
                serialPort.Handshake = SerialHandshake.None;

                // Display configured settings
                status.Text = "Serial port configured successfully: ";
                status.Text += serialPort.BaudRate + "-";
                status.Text += serialPort.DataBits + "-";
                status.Text += serialPort.Parity.ToString() + "-";
                status.Text += serialPort.StopBits;

                // Set the RcvdText field to invoke the TextChanged callback
                // The callback launches an async Read task to wait for data
                rcvdText.Text = "Waiting for data...";

                // Create cancellation token object to close I/O operations when closing the device
                ReadCancellationTokenSource = new CancellationTokenSource();

                // Enable 'WRITE' button to allow sending data
                sendTextButton.IsEnabled = true;

                Listen();
            }
            catch (Exception ex)
            {
                status.Text = ex.Message;
                comPortInput.IsEnabled = true;
                sendTextButton.IsEnabled = false;
            }
        }

        /// <summary>
        /// sendTextButton_Click: Action to take when 'WRITE' button is clicked
        /// - Create a DataWriter object with the OutputStream of the SerialDevice
        /// - Create an async task that performs the write operation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void sendTextButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {                
                if (serialPort != null)
                {
                    // Create the DataWriter object and attach to OutputStream
                    dataWriteObject = new DataWriter(serialPort.OutputStream);

                    //Launch the WriteAsync task to perform the write
                    await WriteAsync();
                }
                else
                {
                    status.Text = "Select a device and connect";                
                }
            }
            catch (Exception ex)
            {
                status.Text = "sendTextButton_Click: " + ex.Message;
            }
            finally
            {
                // Cleanup once complete
                if (dataWriteObject != null)
                {
                    dataWriteObject.DetachStream();
                    dataWriteObject = null;
                }
            }
        }

        /// <summary>
        /// WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream 
        /// </summary>
        /// <returns></returns>
        private async Task WriteAsync()
        {
            Task<UInt32> storeAsyncTask;

            if (sendText.Text.Length != 0)
            {
                // Load the text from the sendText input text box to the dataWriter object
                dataWriteObject.WriteString(sendText.Text);                

                // Launch an async task to complete the write operation
                storeAsyncTask = dataWriteObject.StoreAsync().AsTask();

                UInt32 bytesWritten = await storeAsyncTask;
                if (bytesWritten > 0)
                {                    
                    status.Text = sendText.Text + ", ";
                    status.Text += "bytes written successfully!";
                }
                sendText.Text = "";
            }
            else
            {
                status.Text = "Enter the text you want to write and then click on 'WRITE'";
            }
        }

        /// <summary>
        /// - Create a DataReader object
        /// - Create an async task to read from the SerialDevice InputStream
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Listen()
        {
            try
            {
                if (serialPort != null)
                {
                    dataReaderObject = new DataReader(serialPort.InputStream);

                    // keep reading the serial input
                    while (true)
                    {
                        await ReadAsync(ReadCancellationTokenSource.Token);
                    }
                }
            }
            catch (TaskCanceledException tce) 
            {
                status.Text = "Reading task was cancelled, closing device and cleaning up";
                CloseDevice();            
            }
            catch (Exception ex)
            {
                status.Text = ex.Message;
            }
            finally
            {
                // Cleanup once complete
                if (dataReaderObject != null)
                {
                    dataReaderObject.DetachStream();
                    dataReaderObject = null;
                }
            }
        }

        /// <summary>
        /// ReadAsync: Task that waits on data and reads asynchronously from the serial device InputStream
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        private async Task ReadAsync(CancellationToken cancellationToken)
        {
            Task<UInt32> loadAsyncTask;

            uint ReadBufferLength = 1024;

            // If task cancellation was requested, comply
            cancellationToken.ThrowIfCancellationRequested();

            // Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available
            dataReaderObject.InputStreamOptions = InputStreamOptions.Partial;

            using (var childCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
            {
                // Create a task object to wait for data on the serialPort.InputStream
                loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(childCancellationTokenSource.Token);

                // Launch the task and wait
                UInt32 bytesRead = await loadAsyncTask;
                if (bytesRead > 0)
                {
                    rcvdText.Text = dataReaderObject.ReadString(bytesRead);
                    status.Text = "bytes read successfully!";
                }
            }
        }

        /// <summary>
        /// CancelReadTask:
        /// - Uses the ReadCancellationTokenSource to cancel read operations
        /// </summary>
        private void CancelReadTask()
        {         
            if (ReadCancellationTokenSource != null)
            {
                if (!ReadCancellationTokenSource.IsCancellationRequested)
                {
                    ReadCancellationTokenSource.Cancel();
                }
            }         
        }

        /// <summary>
        /// CloseDevice:
        /// - Disposes SerialDevice object
        /// - Clears the enumerated device Id list
        /// </summary>
        private void CloseDevice()
        {            
            if (serialPort != null)
            {
                serialPort.Dispose();
            }
            serialPort = null;

            comPortInput.IsEnabled = true;
            sendTextButton.IsEnabled = false;            
            rcvdText.Text = "";
            listOfDevices.Clear();               
        }

        /// <summary>
        /// closeDevice_Click: Action to take when 'Disconnect and Refresh List' is clicked on
        /// - Cancel all read operations
        /// - Close and dispose the SerialDevice object
        /// - Enumerate connected devices
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void closeDevice_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                status.Text = "";
                CancelReadTask();
                CloseDevice();
                ListAvailablePorts();
            }
            catch (Exception ex)
            {
                status.Text = ex.Message;
            }          
        }             
    }
}

ПРИМЕР VB.NET

Imports System
Imports System.Collections.ObjectModel
Imports Windows.UI.Xaml
Imports Windows.UI.Xaml.Controls
Imports Windows.Devices.Enumeration
Imports Windows.Devices.SerialCommunication
Imports Windows.Storage.Streams
Imports System.Threading
Imports System.Threading.Tasks



Public NotInheritable Class MainPage
        Inherits Page

    ''' <summary>
    ''' Private variables
    ''' </summary>
    Private serialPort As SerialDevice = Nothing

    Private dataWriteObject As DataWriter = Nothing

        Private dataReaderObject As DataReader = Nothing

        Private listOfDevices As ObservableCollection(Of DeviceInformation)

        Private ReadCancellationTokenSource As CancellationTokenSource

        Public Sub New()
            MyBase.New
            Me.InitializeComponent
            comPortInput.IsEnabled = False
            sendTextButton.IsEnabled = False
            Me.listOfDevices = New ObservableCollection(Of DeviceInformation)
            Me.ListAvailablePorts()
        End Sub

        ''' <summary>
        ''' ListAvailablePorts
        ''' - Use SerialDevice.GetDeviceSelector to enumerate all serial devices
        ''' - Attaches the DeviceInformation to the ListBox source so that DeviceIds are displayed
        ''' </summary>
        Private Async Sub ListAvailablePorts()
            Try
                Dim aqs As String = SerialDevice.GetDeviceSelector
            Dim dis = Await DeviceInformation.FindAllAsync(aqs)
            status.Text = "Select a device and connect"
                Dim i As Integer = 0
                Do While (i < dis.Count)
                    Me.listOfDevices.Add(dis(i))
                    i = (i + 1)
                Loop

                DeviceListSource.Source = Me.listOfDevices
                comPortInput.IsEnabled = True
                ConnectDevices.SelectedIndex = -1
            Catch ex As Exception
                status.Text = ex.Message
            End Try

        End Sub

    ''' <summary>
    ''' comPortInput_Click: Action to take when 'Connect' button is clicked
    ''' - Get the selected device index and use Id to create the SerialDevice object
    ''' - Configure default settings for the serial port
    ''' - Create the ReadCancellationTokenSource token
    ''' - Start listening on the serial port input
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Async Sub comPortInput_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

        Dim selection = ConnectDevices.SelectedItems
        If (selection.Count <= 0) Then
            status.Text = "Select a device and connect"
            Return
        End If

        Dim entry As DeviceInformation = CType(selection(0), DeviceInformation)

        Try
            serialPort = Await SerialDevice.FromIdAsync(entry.Id)
            If (serialPort Is Nothing) Then
                Return
            End If

            ' Disable the 'Connect' button 
            comPortInput.IsEnabled = False
            ' Configure serial settings
            Me.serialPort.WriteTimeout = TimeSpan.FromMilliseconds(1000)
            Me.serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000)
            Me.serialPort.BaudRate = 9600
            Me.serialPort.Parity = SerialParity.None
            Me.serialPort.StopBits = SerialStopBitCount.One
            Me.serialPort.DataBits = 8
            Me.serialPort.Handshake = SerialHandshake.None
            ' Display configured settings
            status.Text = "Serial port configured successfully: "
            status.Text = (status.Text _
                            + (Me.serialPort.BaudRate + "-"))
            status.Text = (status.Text _
                            + (Me.serialPort.DataBits + "-"))
            status.Text = (status.Text _
                            + (Me.serialPort.Parity.ToString + "-"))
            status.Text = (status.Text + Me.serialPort.StopBits)
            ' Set the RcvdText field to invoke the TextChanged callback
            ' The callback launches an async Read task to wait for data
            rcvdText.Text = "Waiting for data..."
            ' Create cancellation token object to close I/O operations when closing the device
            Me.ReadCancellationTokenSource = New CancellationTokenSource
            ' Enable 'WRITE' button to allow sending data
            sendTextButton.IsEnabled = True
            Me.Listen()
        Catch ex As Exception
            status.Text = ex.Message
            comPortInput.IsEnabled = True
            sendTextButton.IsEnabled = False
        End Try

    End Sub

    ''' <summary>
    ''' sendTextButton_Click: Action to take when 'WRITE' button is clicked
    ''' - Create a DataWriter object with the OutputStream of the SerialDevice
    ''' - Create an async task that performs the write operation
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Async Sub sendTextButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Try
                If (Not (Me.serialPort) Is Nothing) Then
                    ' Create the DataWriter object and attach to OutputStream
                    Me.dataWriteObject = New DataWriter(Me.serialPort.OutputStream)
                'Launch the WriteAsync task to perform the write
                Await Me.WriteAsync()
            Else
                    status.Text = "Select a device and connect"
                End If

            Catch ex As Exception
                status.Text = ("sendTextButton_Click: " + ex.Message)
            Finally
                ' Cleanup once complete
                If (Not (Me.dataWriteObject) Is Nothing) Then
                    Me.dataWriteObject.DetachStream()
                    Me.dataWriteObject = Nothing
                End If

            End Try

        End Sub

        ''' <summary>
        ''' WriteAsync: Task that asynchronously writes data from the input text box 'sendText' to the OutputStream 
        ''' </summary>
        ''' <returns></returns>
        Private Async Function WriteAsync() As Task
            Dim storeAsyncTask As Task(Of UInt32)
            If (sendText.Text.Length <> 0) Then
                ' Load the text from the sendText input text box to the dataWriter object
                Me.dataWriteObject.WriteString(sendText.Text)
                ' Launch an async task to complete the write operation
                storeAsyncTask = Me.dataWriteObject.StoreAsync.AsTask
            Dim bytesWritten As UInt32 = Await storeAsyncTask
            If (bytesWritten > 0) Then
                status.Text = (sendText.Text + ", ")
                status.Text = (status.Text + "bytes written successfully!")
            End If

            sendText.Text = ""
            Else
                status.Text = "Enter the text you want to write and then click on 'WRITE'"
            End If

        End Function

    ''' <summary>
    ''' - Create a DataReader object
    ''' - Create an async task to read from the SerialDevice InputStream
    ''' </summary>
    Private Async Sub Listen()
        Try
            If (Not (Me.serialPort) Is Nothing) Then
                Me.dataReaderObject = New DataReader(Me.serialPort.InputStream)
                ' keep reading the serial input

                While True
                    Await Me.ReadAsync(Me.ReadCancellationTokenSource.Token)

                End While

            End If

        Catch tce As TaskCanceledException
            status.Text = "Reading task was cancelled, closing device and cleaning up"
            Me.closeDevice()
        Catch ex As Exception
            status.Text = ex.Message
        Finally
            ' Cleanup once complete
            If (Not (Me.dataReaderObject) Is Nothing) Then
                Me.dataReaderObject.DetachStream()
                Me.dataReaderObject = Nothing
            End If

        End Try

    End Sub

    ''' <summary>
    ''' ReadAsync: Task that waits on data and reads asynchronously from the serial device InputStream
    ''' </summary>
    ''' <param name="cancellationToken"></param>
    ''' <returns></returns>
    Private Async Function ReadAsync(ByVal cancellationToken As CancellationToken) As Task
            Dim loadAsyncTask As Task(Of UInt32)
            Dim ReadBufferLength As UInteger = 1024
            ' If task cancellation was requested, comply
            cancellationToken.ThrowIfCancellationRequested()
            ' Set InputStreamOptions to complete the asynchronous read operation when one or more bytes is available
            Me.dataReaderObject.InputStreamOptions = InputStreamOptions.Partial
            Dim childCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)
            ' Create a task object to wait for data on the serialPort.InputStream
            loadAsyncTask = Me.dataReaderObject.LoadAsync(ReadBufferLength).AsTask(childCancellationTokenSource.Token)
        ' Launch the task and wait
        Dim bytesRead As UInt32 = Await loadAsyncTask
        If (bytesRead > 0) Then
                rcvdText.Text = Me.dataReaderObject.ReadString(bytesRead)
                status.Text = "bytes read successfully!"
            End If

        End Function

        ''' <summary>
        ''' CancelReadTask:
        ''' - Uses the ReadCancellationTokenSource to cancel read operations
        ''' </summary>
        Private Sub CancelReadTask()
            If (Not (Me.ReadCancellationTokenSource) Is Nothing) Then
                If Not Me.ReadCancellationTokenSource.IsCancellationRequested Then
                    Me.ReadCancellationTokenSource.Cancel()
                End If

            End If

        End Sub

        ''' <summary>
        ''' CloseDevice:
        ''' - Disposes SerialDevice object
        ''' - Clears the enumerated device Id list
        ''' </summary>
        Private Sub CloseDevice()
        If (Not (serialPort) Is Nothing) Then
            Me.serialPort.Dispose()
        End If

        Me.serialPort = Nothing
            comPortInput.IsEnabled = True
            sendTextButton.IsEnabled = False
            rcvdText.Text = ""
            Me.listOfDevices.Clear()
        End Sub

    ''' <summary>
    ''' closeDevice_Click: Action to take when 'Disconnect and Refresh List' is clicked on
    ''' - Cancel all read operations
    ''' - Close and dispose the SerialDevice object
    ''' - Enumerate connected devices
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub closeConnection_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Try
            status.Text = ""
            Me.CancelReadTask()
            Me.CloseDevice()
            Me.ListAvailablePorts()
        Catch ex As Exception
            status.Text = ex.Message
        End Try

    End Sub
End Class

В источнике XAML оба равны, за исключением кнопки отключения с разными именами, но это не влияет на мою реальную проблему, ну, я застрял в этой части проекта почти на 2 недели, и я был бы очень признателен за любую помощь в этом .

1 Ответ

0 голосов
/ 10 мая 2018

Я протестировал с кодом, который вы предоставили. Вы проверили возможности устройства в манифесте пакета приложения в своем проекте VB.Net? Вам необходимо включить возможности последовательного устройства. Это сработало для меня после добавления следующего кода в файл Package.appxmanifest . Этот документ показывает Serial Communication в UWP. Если проблема все еще не может быть решена, пожалуйста, не стесняйтесь и дайте мне знать.

<DeviceCapability Name="serialcommunication">
    <Device Id="vidpid:xxxx xxxx">
      <Function Type="name:serialPort"/>
    </Device>
</DeviceCapability>
...