2017-02-24 46 views
1

我正在開發一個C#Windows窗體應用程序,通過藍牙連接與Raspberry Pi Model 3進行通信。此連接通過客戶機上的虛擬串行端口進行模擬。我可以在C#程序中啓動藍牙連接,但無法接收程序中的任何數據。當我使用Putty程序時,我可以看到數據按照我希望的方式在COM端口上傳輸。C#應用程序將不會收到串行數據流

我還發現了一個怪異的C#程序故障。如果我在Putty上打開COM端口,然後啓動C#程序,則由於端口被保留,因此port.open()命令會發生錯誤。那麼如果我關閉Putty並繼續C#應用程序,數據將完全流向程序。有沒有人遇到過這個問題?我幾天來一直處於虧損狀態。我在程序的代碼如下所示:

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

更新:我剛剛發現我的聲明藍牙端點,客戶端和設備與閱讀過我的串行端口的干擾。由於藍牙連接以前已經初始化,所以我能夠在端口上看到數據。現在爲什麼它這樣做?

+0

如果有人沒有達到這個目標,請稍後在今天晚些時候給我一個答案。 – Snoopy

+1

那太棒了。非常感謝你! – Frankn

回答

0

好吧,看起來你沒有做錯什麼。 .NET本身不能處理同一端口的多個所有權。當您聲明您的SerialPort實例並連接說... COM11 ...您已將COM11的所有權完全轉讓給您的SerialPort實例。要訪問COM11,您現在需要提供對具有COM11的所有權的特定SerialPort對象的引用。

在你的情況下,你打開PuTTY,然後運行你的程序。一旦PuTTY獲得訪問端口,您的程序將無法完成此操作。這在.NET框架中是完全標準的。現在,還有其他方法可以獲得對COM端口的多次訪問,但我認爲這超出了這個問題的範圍。這裏有一個軟件,可以讓你運行一個應用程序,同時在端口上嗅探流量...... Free Serial Port Monitor。你可以免費得到這個,並有一個更好的購買版本,可以做各種魔術。

這是確保你的端口一點算法正確打開,你可能想借此...修改一點點... ...並把它作爲你的BluetoothClientConnect方法。

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

除了這一切,你可能想要看你Bluetooth類不自稱端口的所有權時,你需要閱讀它。這可能是干擾閱讀港口的原因。你真的應該創建一個單獨的課程,並稱之爲BluetoothClient或其他什麼東西,並且該單一課程負責與SerialPort引用的所有交互。通過這種方式,您可以確保您是否希望在端口上發送/接收,您始終擁有所有權。

+0

對不起所有的編輯,意外地發佈了錯誤的東西,不得不改變它... – Snoopy

+0

@Frankn這個答案可以幫助你嗎?或者可以以某種方式改進? – Snoopy

相關問題