Twisted serialport dataReceived()提供碎片数据

时间:2013-08-29 14:40:14

标签: python bluetooth serial-port twisted

我正在使用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函数中的碎片数据相同的问题。

2 个答案:

答案 0 :(得分:1)

您的协议子类Int16StringReceiver,它使用两个字节(16位)长度前缀实现消息帧。但是,它会覆盖dataReceived,这是实现该框架的方法。这会禁用成帧并只提供从连接中读取的任何字节 - 无论它们恰好被读取的大小。

当您继承Int16StringReceiver时,您的意思是覆盖stringReceived

答案 1 :(得分: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连接的无线电时。