我正在使用Twisted来实现一个python程序,用蓝牙设备进行通信。以下是我实施的示例代码:
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()
当我运行程序时,有时我得到回复,有时我没有收到任何回复。并且大多数时候长的响应都是碎片化的,这些都是下一条消息的一部分。我通过超级终端来确保我从蓝牙设备得到适当的响应。所以,问题必须出在我的代码上。
我的代码中有什么问题吗?
其他修改/更正
当我用stringReceived()替换上面代码中的dataReceived()函数时,程序永远不会进入这个函数。
我还尝试使用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函数中的碎片数据相同的问题。
答案 0 :(得分:1)
您的协议子类Int16StringReceiver
,它使用两个字节(16位)长度前缀实现消息帧。但是,它会覆盖dataReceived
,这是实现该框架的方法。这会禁用成帧并只提供从连接中读取的任何字节 - 无论它们恰好被读取的大小。
当您继承Int16StringReceiver
时,您的意思是覆盖stringReceived
。
答案 1 :(得分:1)
对于我的大多数蓝牙工作,我使用了8位整数,所以我建议使用Int8StringReceiver
。 LineReceiver
协议等待默认为'\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连接的无线电时。