1

我很想用 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 函数的碎片数据。

4

2 回答 2

1

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

当您子类化时Int16StringReceiver,您应该重写stringReceived

于 2013-08-29T15:59:17.067 回答
1

对于我的大部分蓝牙工作,我使用了 8 位整数,所以我建议使用Int8StringReceiver. 该LineReceiver协议等待一个默认为'\r\n'(以及我使用的蓝牙无线电 return '\r')的 endline 序列,因此 endline 序列的不匹配将阻止代码进入。

您是否尝试过使用非 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 连接无线电的情况下。

于 2013-08-29T17:02:11.173 回答