问题
I have a working connection with my serial device via PySerial, but I also want to transfer files via the xmodem protocol as part of my program.
Which would be the most platform-neutral way to do this? Worst case, I could close()
my serial.Serial
object in Python and use subprocess
to call upon /usr/bin/sb
, but that seems inelegant.
I'm currently on Ubuntu 9.10 and am using a USB-TTY adapter.
Any ideas?
回答1:
There is xmodem module on PyPi. It takes two functions in constructor for reading and writing data, implement them to work with your opened serial port. Below is simple sample of its usage:
import serial
try:
from cStringIO import StringIO
except:
from StringIO import StringIO
from xmodem import XMODEM, CRC
from time import sleep
def readUntil(char = None):
def serialPortReader():
while True:
tmp = port.read(1)
if not tmp or (char and char == tmp):
break
yield tmp
return ''.join(serialPortReader())
def getc(size, timeout=1):
return port.read(size)
def putc(data, timeout=1):
port.write(data)
sleep(0.001) # give device time to send ACK
port = serial.Serial(port='COM5',parity=serial.PARITY_NONE,bytesize=serial.EIGHTBITS,stopbits=serial.STOPBITS_ONE,timeout=0,xonxoff=0,rtscts=0,dsrdtr=0,baudrate=115200)
port.write("command that loads data via xmodem\r\n")
sleep(0.02) # give device time to handle command
readUntil(CRC)
buffer = StringIO('data to send')
XMODEM(getc, putc).send(buffer, quiet = 1)
buffer.close()
readUntil()
回答2:
It is super simple to use the XMODEM protocol implementation found on PyPi. A few things to note about the example above is there are some things that are not needed. (Maybe this worked for the author or with a previous version of the module?)
The documentation found here is extremely helpful, so don't let it scare you. You will need a sender and a receiver obviously, and since I do not know which one the Python script will be, here are two examples I have tested and are working below. (basically copied and pasted from the examples on PyPi)
import serial
from xmodem import XMODEM
ser = serial.Serial(port='COM56')
def getc(size, timeout=8):
gbytes = ser.read(size)
print(f'Read Byte: {gbytes}')
return gbytes or None
def putc(data, timeout=8):
pbytes = ser.write(data)
print(f'Put Byte: {pbytes}')
return pbytes or None
if __name__ == '__main__':
modem = XMODEM(getc, putc)
To receive from the serial device:
stream = open('output', 'wb')
modem.recv(stream, crc_mode=0)
To send to the serial device:
stream = open('input', 'rb')
modem.send(stream)
The key here is to be sure the baud rate is set on both sides (defaulting here). Do NOT add any delay or sleep as this is not time based, but transaction based. the prints will allow you to see the transaction real time as the data flows in or out of the file/serial port.
回答3:
I'm not familiar with the details of the xmodem protocol, but one person answering the xmodem-for-python question appears to be, and has even provided what looks like a crude implementation of xmodem in Python. Perhaps you could use that, or ideas from other the answers there.
来源:https://stackoverflow.com/questions/1834247/can-i-use-the-xmodem-protocol-with-pyserial