2013-08-29 80 views
1

我打算使用Twisted實現一個Python程序來與藍牙設備進行通信。下面是什麼我實現了一個示例代碼:扭曲的串行端口dataReceived()提供零碎的數據

from twisted.internet import protocol, reactor 
from twisted.internet.serialport import SerialPort 
from twisted.protocols import basic 

class DeviceBluetooth(basic.Int16StringReceiver): 

    def connectionMade(self): 
     print 'Connection made!' 
     self.sendString('[01] help\n') 

    def dataReceived(self, data): 
     print"Response: {0}".format(data) 

     print "-----" 
     print "choose message to send: " 
     print "1. Stim on" 
     print "2. Stim off" 
     print "3. Stim status" 
     print "4. Help" 
     # user input 
     ch = input("Choose command :: ") 
     if int(ch) == 1: 
      self.sendString('[02] stim on\n') 
     elif int(ch) == 2: 
      self.sendString('[03] stim off\n') 
     elif int(ch) == 3: 
      self.sendString('[04] stim ?\n') 
     elif int(ch) == 4: 
      self.sendString('[05] help\n') 
     else: 
      reactor.stop() 

SerialPort(DeviceBluetooth(), 'COM20', reactor, baudrate=115200) 
reactor.run() 

當我運行程序時,有時我得到的迴應,其他時間我沒有收到任何東西。而且大多數時候,很長一段時間的回覆都是碎片化的,作爲下一條消息的一部分。我已經通過超級終端來確保我通過藍牙設備獲得適當的響應。所以,這個問題必須與我的代碼。

有沒有什麼我在我的代碼中做錯了?


附加修改/校正

當我替換dataReceived在上面的代碼()函數通過stringReceived(),則程序永遠不會進入該功能。

我也試圖上述程序與LineReceiver協議,如下:

from twisted.internet import protocol, reactor 
from twisted.internet.serialport import SerialPort 
from twisted.protocols import basic 

class DeviceBluetooth(basic.LineReceiver): 

    def connectionMade(self): 
     print 'Connection made!' 
     self.sendLine('[01] help') 

    def dataReceived(self, data): 
     print"Response: {0}".format(data) 

     print "-----" 
     print "choose message to send: " 
     print "1. Stim on" 
     print "2. Stim off" 
     print "3. Stim status" 
     print "4. Help" 
     # user input 
     ch = input("Choose command :: ") 
     if int(ch) == 1: 
      self.sendLine('[02] stim on') 
     elif int(ch) == 2: 
      self.sendLine('[03] stim off') 
     elif int(ch) == 3: 
      self.sendLine('[04] stim ?') 
     elif int(ch) == 4: 
      self.sendLine('[05] help') 
     else: 
      reactor.stop() 

SerialPort(DeviceBluetooth(), 'COM20', reactor, baudrate=115200) 
reactor.run() 

我有同樣的問題,如前所述,與來自dataReceived功能分段的數據。

回答

1

您的協議子類Int16StringReceiver使用兩個字節(16位)長度的前綴實現消息成幀。但是,它會覆蓋dataReceived這是實現該組幀的方法。這將禁用成幀,並只傳送從連接中讀取的任何字節 - 無論它們是以什麼大小讀取。

當您將Int16StringReceiver轉換爲子類時,您的意思是替代stringReceived

+0

我用stringReceived替換了thye的dataReceived函數,並運行了代碼。但是當我這樣做時,程序甚至不會輸入stringReceived函數。 我也嘗試了LineReceived protcol的上述程序的修改版本,在這裏我也遇到了dataReceived函數中碎片數據的相同問題。 – siva82kb

+0

你爲什麼要在Int16StringReceiver和LineReceiver之間切換?你想在這裏說什麼協議? –

+0

我試過LineReceiver協議,只是想看看它是否工作。來自藍牙設備的協議被實現爲基於線路的協議。我是Twisted的新手,所以嘗試了不同的東西。 – siva82kb

1

對於我的大多數藍牙工作,我使用了8位整數,所以我會建議使用Int8StringReceiverLineReceiver協議等待一個缺省爲'\r\n'的終止序列(以及我使用的藍牙無線電返回'\r'),因此在終止序列上的不匹配將阻止代碼進入。

您是否嘗試過使用非Twisted庫進行調試?我強烈建議Twisted特別適用於生產環境,但PySerial是查詢串行數據的好方法。 (easy_install pyserial應該做的伎倆。)試試這個代碼:

import serial 
s = serial.Serial('COM20', 115200, timeout=0) 
data = s.read(1024) 
print repr(data) 

確保使用timeout=0因爲這會讓你的read無阻塞。 這將允許您檢查藍牙無線電正在輸出什麼樣的數據。

最後,根據您使用的是哪種藍牙無線電,Windows可能會決定移動COM20,特別是在使用USB連接的無線電時。

+0

我想你可能會依賴'LineReceiver'行爲來確保你的數據看起來沒有碎片。在這種情況下,使用pyserial來查看它發送了什麼分隔符,然後通過在'class'行後面寫入'delimiter ='\ n''來設置它。 [示例](http://www.wallix.org/2011/08/30/getting-started-with-twisted/) – DrRobotNinja

+0

謝謝。我決定使用串行模塊來實現,使用單獨的線程進行讀取和寫入,因爲這將成爲具有GUI的更大應用程序的一部分。我能夠讀寫沒有任何問題。 – siva82kb

+2

從Twisted切換到線程以便修復與串行設備的交互中的成幀問題可能意味着您隱藏了該錯誤,以便在代碼部署在現實世界中時纔會顯示該錯誤,其中時間稍微不同於你的開發機器和你的代碼在各種競爭條件下開始失敗。 –