简体   繁体   English

Windows Universal App串行端口无法打开,SerialDevice.FromIdAsync始终为null

[英]Windows Universal App Serial Ports won't open, SerialDevice.FromIdAsync always null

I am trying to use serial ports in a Windows Universal Application. 我试图在Windows通用应用程序中使用串行端口。 I have been using Microsoft's Serial Sample application as a template however I have hit a rather strange issue. 我一直在使用Microsoft的Serial Sample应用程序作为模板,但是我遇到了一个相当奇怪的问题。

var dis = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A));
var sp = await SerialDevice.FromIdAsync(dis[0].Id);

This is a the snippet that is failing. 这是一个失败的片段。 It is slightly altered from the original sample as it connects to the first device with a specific vendor. 它与原始样本略有不同,因为它连接到具有特定供应商的第一个设备。 Now if I take this snippet and put it in the sample application produced by Microsoft the serial port opens and all is good. 现在,如果我把这个片段放在Microsoft生成的示例应用程序中,串口就打开了,一切都很好。 However when I move this code into my own project it always returns null from the method. 但是,当我将此代码移动到我自己的项目中时,它始终从该方法返回null

Here is the full MainPage.xaml.cs from the Microsoft sample with my alerations: This Works!! 以下是来自Microsoft示例的完整MainPage.xaml.cs以及我的操作: 这个Works !!

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

using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
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(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A));
            serialPort = await SerialDevice.FromIdAsync(dis[0].Id);

            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;

            try
            {


                // 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;
            }
        }
        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);

            // 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 (Exception ex)
        {
            if (ex.GetType().Name == "TaskCanceledException")
            {
                status.Text = "Reading task was cancelled, closing device and cleaning up";
                CloseDevice();
            }
            else
            {
                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;

        // Create a task object to wait for data on the serialPort.InputStream
        loadAsyncTask = dataReaderObject.LoadAsync(ReadBufferLength).AsTask(cancellationToken);

        // 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;
        }          
    }        
  }
}

This next block if from my code. 从我的代码中获取下一个块。 Those first 2 lines in the ConnectToSerialPort() are the same as before for testing however SerialDevice.FromIdAsync(dis[0].id); ConnectToSerialPort()中的前两行与之前的测试相同,但是SerialDevice.FromIdAsync(dis[0].id); is always null. 永远是空的。 This does not work!! 这不行!!

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Windows.Devices.Enumeration;
using Windows.Devices.SerialCommunication;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;

namespace OpenLab.Kitchen.Receiver
{
public sealed partial class MainPage : Page
{
    private List<byte> Bytes { get; set; }

    public MainPage()
    {
        this.InitializeComponent();
        Bytes = new List<byte>();
        ConnectToSerialPort();
    }

    private async void ConnectToSerialPort()
    {
        var dis = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A));
        var sp = await SerialDevice.FromIdAsync(dis[0].Id);

        Debug.WriteLine(sp.UsbVendorId);

        DeviceInformationCollection serialDevices;

        while ((serialDevices = await DeviceInformation.FindAllAsync(SerialDevice.GetDeviceSelectorFromUsbVidPid(0x04D8, 0x000A))).Count < 1)
        {
            Debug.WriteLine("Unable to locate...");
        }

        SerialDevice serialPort;

        while ((serialPort = await SerialDevice.FromIdAsync(serialDevices[0].Id)) == null)
        {
            Debug.WriteLine("Failed to open serial port...");
        }

        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;

        var dataReader = new DataReader(serialPort.InputStream);
        var buffer = new byte[1024];

        while (true)
        {
            var bytesRead = await dataReader.LoadAsync((uint)buffer.Length);
            dataReader.ReadBytes(buffer);
            Bytes.AddRange(buffer.Take((int)bytesRead));

            byte[] slipPacket;
            while ((slipPacket = Slip.ExtractSlipPacket(Bytes)) != null)
            {
                var waxPacket = WaxPacketConverter.FromBinary(slipPacket, DateTime.Now);
                if (waxPacket != null)
                {
                    Debug.WriteLine(waxPacket);
                }
            }
        }
    }
  }
}

I have checked all the manifest permissions to match them up and checked stuff like referenced DLL versions and everything looks the same. 我检查了所有清单权限以匹配它们并检查引用的DLL版本之类的东西,一切看起来都一样。 Also checked things like running VS as admin and I haven't got both applications open at the same time so its not that one should be holding the port open or anything... 还检查了运行VS作为管理员的事情,我没有同时打开这两个应用程序所以它不是那个应该保持端口打开或任何...

Does anyone have any ideas? 有没有人有任何想法?

So Microsoft do not mention that you need to add something to the app manifest for serial communication nor is there a tick box in the app manifest GUI for serial communication. 因此,Microsoft没有提到您需要在应用程序清单中添加一些内容以进行串行通信,也不会在应用程序清单GUI中添加用于串行通信的复选框。

The following needs to be added to your app manifest (create the <Capabilities> section if it doesn't exist): 需要将以下内容添加到您的应用清单中(如果不存在,则创建<Capabilities>部分):

<Capabilities>
  <DeviceCapability Name="serialcommunication">
    <Device Id="any">
      <Function Type="name:serialPort" />
    </Device>
  </DeviceCapability>
</Capabilities>

UPDATE 10/2016 更新10/2016

Microsoft have updated their documentation to reflect this requirement. Microsoft已更新其文档以反映此要求。

https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.aspx https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SerialDevice.FromIdAsync() 产生一个空串口 - SerialDevice.FromIdAsync() yields a null serial port SerialDevice.FromIdAsync()返回null - SerialDevice.FromIdAsync() returns null UWP SerialDevice.FromIdAsync 在 Windows 10 上抛出“找不到元素”(来自 HRESULT 的异常:0x80070490) - UWP SerialDevice.FromIdAsync throws “Element not found” (Exception from HRESULT: 0x80070490) on Windows 10 UWP,第二个调用SerialDevice.FromIdAsync中的设备COM端口号为NULL - UWP , Device COM port number is NULL in 2nd call SerialDevice.FromIdAsync 为什么应该从UI线程打开SerialDevice.FromIdAsync? - Why SerialDevice.FromIdAsync should be opened from the UI thread? 为什么我的异步方法不等待“ serialPort =等待SerialDevice.FromIdAsync()”? - Why does my async method not wait on “serialPort = await SerialDevice.FromIdAsync()”? Windows 8.1应用商店应用HidDevice.FromIdAsync返回null - Windows 8.1 Store App HidDevice.FromIdAsync returns null Windows 10 Universal App:PropertyChanged事件始终为null ListView - Windows 10 Universal App:PropertyChanged Event is always null ListView 如何使用通用Windows应用程序将串行数据写入COM端口? - How to write serial data to COM ports with Universal Windows Application? UWP 应用找不到 USB 设备。 总是从 UsbDevice.FromIdAsync() 获取 null - UWP app cannot find the USB device. Always getting null from UsbDevice.FromIdAsync()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM