VB.NET - How to make a Serial Test Loopback program on Universal Windows Platform?

1

I have a problem while doing the translation of C # code to VB.NET on the UWP platform doing a Serial UART Test Example made available by the Microsoft website. The program in C # is working perfectly, but when I try to run in VB.NET, the moment I try to connect the port in RaspBerry Pi 3, the variable "serialPort" goes invalid and returns, like the image here worthless SerialPort.

I make the source code available here in C # and VB.NET, to compare if something is missing (probably yes) at the time the code was translated.

This image is the C # serialPort with value.

C # EXAMPLE

// 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 EXAMPLE

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

In XAML Source, both are the same except for the 'Disconnect Button' with different names, but it does not affect my current problem, I've been standing in this part of the project for almost two weeks, and I really appreciate any help on how to solve that issue.

    
asked by anonymous 07.05.2018 / 20:18

0 answers