Могу ли я использовать протокол xmodem с PySerial?

У меня есть рабочее соединение с моим последовательным устройством через PySerial, но я также хочу передавать файлы по протоколу xmodem как часть моей программы.

Какой способ сделать это наиболее нейтральным с точки зрения платформы? В худшем случае я мог close() мой serial.Serial объект в Python и использовать subprocess призвать /usr/bin/sb, но это кажется не элегантным.

В настоящее время я использую Ubuntu 9.10 и использую адаптер USB-TTY.

Есть идеи?

3 ответа

Решение

На PyPi есть модуль xmodem. Требуется две функции в конструкторе для чтения и записи данных, реализующие их для работы с открытым последовательным портом. Ниже приведен простой пример его использования:

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

Использовать реализацию протокола XMODEM, найденную в PyPi, очень просто. Несколько вещей, которые следует отметить в приведенном выше примере: есть вещи, которые не нужны. (Может быть, это сработало для автора или с предыдущей версией модуля?)

Документация, найденная здесь, чрезвычайно полезна, поэтому не позволяйте ей пугать вас. Понятно, что вам понадобятся отправитель и получатель, и, поскольку я не знаю, каким будет скрипт Python, вот два примера, которые я протестировал и работаю ниже. (в основном скопировано и вставлено из примеров на 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)

Чтобы получить от последовательного устройства:

stream = open('output', 'wb')
modem.recv(stream, crc_mode=0)

Для отправки на последовательное устройство:

stream = open('input', 'rb')
modem.send(stream)

Главное здесь - убедиться, что скорость передачи данных установлена ​​с обеих сторон (здесь по умолчанию). НЕ добавляйте задержку или режим сна, так как это не время, а транзакция. распечатки позволят вам видеть транзакцию в режиме реального времени, когда данные поступают в / из файла / последовательного порта.

Я не знаком с деталями протокола xmodem, но один человек, отвечающий на вопрос xmodem-for-python, кажется, и даже предоставил то, что похоже на грубую реализацию xmodem в Python. Возможно, вы могли бы использовать это, или идеи из других ответов там.

Другие вопросы по тегам