2017-02-24 4 views
1

Ich entwickle eine C# Windows Forms-Anwendung, um über eine Bluetooth-Verbindung mit einem Raspberry Pi Model 3 zu kommunizieren. Diese Verbindung wird über eine virtuelle serielle Schnittstelle auf dem Clientcomputer simuliert. Ich bin in der Lage, eine Bluetooth Verbindung innerhalb des C# Programms zu beginnen, aber ich kann keine Daten vom Programm empfangen. Wenn ich das Programm Putty benutze, kann ich sehen, dass die Daten auf dem COM Port so übertragen werden, wie ich es möchte.C# -Anwendung empfängt keine seriellen Datenströme

Ich entdeckte auch eine seltsame Art von Glitch mit dem C# -Programm. Wenn ich den COM-Port auf Putty öffnen und dann das C# -Programm starten, wird mit dem Befehl port.open() ein Fehler auftreten, da der Port reserviert ist. Wenn ich also Putty schließe und die C# -Anwendung fortsetze, strömen die Daten perfekt zum Programm. Ist jemand schon einmal auf dieses Problem gestoßen? Ich habe jetzt ein paar Tage verloren. Der Kodex in meinem Programm ist unten dargestellt:

using System; 
using System.IO.Ports; 
using System.IO; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using InTheHand.Net; 
using InTheHand.Net.Sockets; 
using InTheHand.Net.Bluetooth; 
using System.Threading; 

namespace GUIfromPI 
{ 

    static class Program 
    { 
     //PC BT USB adapter 
     private static BluetoothEndPoint EP = new BluetoothEndPoint(BluetoothAddress.Parse("##:##:##:##:##:##"), BluetoothService.BluetoothBase); //addressing the usb adapter used on the PC (endpoint) 
     private static BluetoothClient BC = new BluetoothClient(EP); 

     //Pi BT Adapter 
     private static BluetoothDeviceInfo BTDevice = new BluetoothDeviceInfo(BluetoothAddress.Parse("##:##:##:##:##:##")); //addressing the BT adapter on the Rasperry Pi 
     // private static NetworkStream stream = null; 
     public static SerialPort mySerialPort = new SerialPort(); //Bluetooth module mimics serial protocol by streaming data through the COM5 port in the host80 computer 
     /// <summary> 
     /// The main entry point for the application. 
     /// </summary> 
     [STAThread] 
     public static void Main(string[] args) 
     { 
      Console.WriteLine("Executing Program..."); 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      if (BluetoothSecurity.PairRequest(BTDevice.DeviceAddress, "1234"))//MY_PAIRING_CODE)) 
      { 
       Console.WriteLine("PairRequest: OK"); 

       if (BTDevice.Authenticated) 
       { 
        Console.WriteLine("Authenticated: OK"); 
        BC.SetPin("1234");//pairing code 
        //BC.BeginConnect(BTDevice.DeviceAddress, BluetoothService.SerialPort, new AsyncCallback(Connect), BTDevice); 
       } 
       else 
       { 
        Console.WriteLine("Authenticated:No"); 
       } 
      } 
      else 
      { 
       Console.WriteLine("PairRequest: No"); 
      } 
      //mySerialPort = new SerialPort("COM5"); 

      SerialThreadFunction(); 
     } 


     public static void SerialThreadFunction() 
     { 
      mySerialPort.PortName = "COM10"; 
      mySerialPort.BaudRate = 9600; 
      mySerialPort.Parity = Parity.None; 
      mySerialPort.StopBits = StopBits.One; 
      mySerialPort.DataBits = 8; 
      mySerialPort.Handshake = Handshake.None; 
      mySerialPort.DtrEnable = true; 
      mySerialPort.RtsEnable = true; 
      mySerialPort.ReadTimeout = 100000; 
      mySerialPort.Open(); 
      //mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); 
      string mydata = "hello"; 
      while (true) 
      { 
       Console.WriteLine(mySerialPort.ReadLine()); 
       mydata = mySerialPort.ReadLine(); 
      } 
      mySerialPort.Close(); 
     } 


     private static void DataReceivedHandler(
          object sender, 
          SerialDataReceivedEventArgs e) 
     { 
      SerialPort sp = (SerialPort)sender; 
      string indata = sp.ReadExisting(); 
      Console.WriteLine("Data Received: "); 
      Console.Write(indata); 
     } 
    } 
} 

UPDATE: ich, dass gerade entdeckt, erklärt mein Bluetooth Endpoint, Client und Gerät stört mit dem Lesen von meiner seriellen Schnittstelle. Da die Bluetooth-Verbindung bereits zuvor initialisiert wurde, konnte ich die Daten auf dem Port sehen. Nun, warum tut es das?

+0

Wenn jemand nicht dazu kommt, halten Sie sich für eine Antwort von mir später heute fest. – Snoopy

+1

Das wäre erstaunlich. Vielen Dank! – Frankn

Antwort

0

Okay, es scheint, dass Sie nichts falsch machen. Inhärent .NET kann nicht mehrere Eigentümer desselben Ports behandeln. Wenn Sie Ihre SerialPort Instanz deklarieren und verbinden, um zu sagen ... COM11 ... Sie haben das Eigentum von COM11 nur Ihrer SerialPort Instanz gegeben. Um Zugriff auf COM11 zu haben, müssen Sie nun einen Verweis auf das spezifische SerialPort Objekt bereitstellen, das Eigentümer der COM11 ist.

In Ihrem Fall öffnen Sie PuTTY und starten dann Ihr Programm. Sobald PuTTY Zugriff auf den Port erhält, kann Ihr Programm dies nicht mehr tun. Dies ist im .NET-Framework vollständig Standard. Jetzt gibt es andere Möglichkeiten, wie Sie mehrere Zugriffe auf einen COM-Port erhalten können, aber ich denke, das liegt außerhalb des Umfangs dieser Frage. Hier ist eine Software, die es Ihnen ermöglicht, eine Anwendung auszuführen und gleichzeitig Datenverkehr über den Port zu schnüffeln ... Free Serial Port Monitor. Du kannst das kostenlos bekommen, und es gibt eine bessere Version zum Kaufen, die alle Arten von Magie macht.

Hier ist ein kleiner Algorithmus um sicherzustellen, dass Ihr Port richtig geöffnet ist. Vielleicht möchten Sie dies ... nehmen Sie es ein wenig ändern ... und verwenden Sie es als Connect Methode auf Ihre BluetoothClient Klasse.

SerialPort port = null; 
string error = string.Empty; 
bool success = false; 
int tries = 5; 

foreach(var name in System.IO.Ports.SerialPort.GetPortNames()) 
{ 
    // try each port until you find an open one 
    port.Name = name; 

    // there is always a chance that the port is open 
    // if trying some operations back-to-back 
    // give it a few extra tries if necessary 
    for (int i = tries; i > 0; --i) 
    { 
     try 
     { 
      // avoid the exception by testing if open first 
      if (!port.IsOpen) 
      { 
       port.Open(); 
       success = true; 
       return; 
      } 
     } 
     catch (UnauthorizedAccessException e) 
     { 
      // sometimes the exception happens anyway, especially 
      // if you have multiple threads/processes banging on the 
      // ports 
      error += e.Message; 
     } 
    } 
} 

Neben all dies können Sie sehen möchten, dass Ihre Bluetooth Klassen nicht Eigentum des Hafens behauptet werden, wenn Sie es lesen müssen. Das kann sein, was das Lesen des Ports behindert. Sie sollten wirklich eine einzige Klasse erstellen und sie say BluetoothClient oder so nennen, und diese einzige Klasse muss für alle Interaktionen mit der SerialPort-Referenz verantwortlich sein. Auf diese Weise stellen Sie sicher, dass Sie unabhängig davon, ob Sie auf dem Port senden/empfangen möchten, immer Eigentümer sind.

+0

Sorry über alle Änderungen, versehentlich etwas falsch gepostet und musste es ändern ... – Snoopy

+0

@Frankn hilft Ihnen diese Antwort überhaupt? Oder kann es irgendwie verbessert werden? – Snoopy