2015-12-08 3 views
6

Ich versuche, serielle Ports in einer universellen Windows-Anwendung zu verwenden. Ich habe die serielle Beispielanwendung von Microsoft als Vorlage verwendet, aber ich habe ein ziemlich seltsames Problem festgestellt.Serial Ports von Windows Universal App werden nicht geöffnet, SerialDevice.FromIdAsync immer null

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

Dies ist ein Schnipsel, der fehlschlägt. Es ist leicht von dem ursprünglichen Beispiel geändert, da es sich mit dem ersten Gerät mit einem bestimmten Anbieter verbindet. Nun, wenn ich dieses Snippet nehme und es in die von Microsoft erstellte Beispielanwendung einlege, öffnet sich der serielle Port und alles ist gut. Wenn ich diesen Code jedoch in mein eigenes Projekt verschiebe, gibt er immer null aus der Methode zurück.

Hier ist die vollständige MainPage.xaml.cs aus dem Microsoft-Beispiel mit meinen alerations: Dies funktioniert !!

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

Dieser nächste Block, wenn von meinem Code. Die ersten beiden Zeilen in der ConnectToSerialPort() sind die gleichen wie zuvor zum Testen, aber SerialDevice.FromIdAsync(dis[0].id); ist immer Null. Das geht nicht !!

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

Ich habe alle offensichtlichen Berechtigungen geprüft, um sie anzupassen und überprüft Sachen wie referenzierten DLL-Versionen und alles sieht gleich aus. Habe auch Sachen wie VS als Admin laufen lassen und ich habe nicht beide Anwendungen zur selben Zeit geöffnet, also sollte man nicht den Port offen halten oder irgendwas ...

Hat jemand irgendwelche Ideen?

Antwort

17

Also Microsoft nicht erwähnen, dass Sie etwas zum App-Manifest für die serielle Kommunikation hinzufügen müssen, noch gibt es ein Häkchen im App Manifest GUI für die serielle Kommunikation.

Folgende Anforderungen Ihrer App-Manifest (erstellen Sie den <Capabilities> Abschnitt, wenn sie nicht existiert) hinzugefügt werden:

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

UPDATE 10/2016

Microsoft ihre Dokumentation aktualisiert haben spiegeln diese Anforderung wider.

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

+1

Dank - ich auch viel Zeit auf diese und Ihre Antwort hat mich gerettet verschwendet. –

+3

Glauben Sie mir, ich verschwendet mehr :) –

+0

Sie meinen [diese Dokumentation] (https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.aspx), die von der [ SerialDevice msdn Dokumentation] (https://msdn.microsoft.com/en-us/library/windows/apps/windows.devices.serialcommunication.serialdevice.aspx) –

Verwandte Themen