简体   繁体   中英

Twisted serialport dataReceived() provides fragmented data

I am tyring to implement a python program, using Twisted, to communicate witha bluetooth device. The following is a sample code of what I have implemented:

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()

When I run the program, sometimes I get a response and other times I do not receive anything. And most of the times long responses are fragmented appear as part of the next message. I have through the hyperterminal to make sure that I get the appropriate response from by bluetooth device. So, the problem has to be with my code.

Is there something that I doing wrong in my code?


Additional modification/correction

When I replace dataReceived() function in the above code by stringReceived(), the program never enters this function.

I also tried to above program with the LineReceiver protocol, as the following:

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()

I have the same problem, as before, with fragmented data from the dataReceived function.

Your protocol subclasses Int16StringReceiver which implements message framing using two byte (16 bit) length prefixes. However, it overrides dataReceived which is the method that implements that framing. This disables the framing and just delivers whatever bytes happen to be read from the connection - in whatever size they happen to be read.

When you subclass Int16StringReceiver , you're meant to override stringReceived instead.

For most of my bluetooth work, I've used 8-bit integers, so I would recommend using Int8StringReceiver . The LineReceiver protocol waits for an endline sequence which defaults to '\\r\\n' (and the bluetooth radios I use return '\\r' ) so a mismatch on endline sequence would prevent the code from ever entering.

Have you tried to use a non-Twisted library for debugging? I highly recommend Twisted especially for production environments, but PySerial is a great way to poll serial data. ( easy_install pyserial should do the trick.) Try this code:

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

Make sure to use timeout=0 since that will make your read non-blocking. This will allow you to examine exactly what kind of data is being outputted by the bluetooth radio.

Finally, depending on what kind of bluetooth radio you are using, Windows might decide to move COM20 around, especially if you are using a USB-connected radio.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM