Лучший подход для разбора строки буфера в Python - PullRequest
0 голосов
/ 02 мая 2018

Я работаю над встроенной системой, которая отправляет команды через Uart. Uart работает на скорости 115200 бод

На ПК я хочу прочитать эти команды, проанализировать их и выполнить соответствующее действие.

Я выбираю python в качестве языка для создания скрипта.

Это типичная команда, полученная от встроенной системы:

S;SEND;40;{"ID":"asg01","T":1,"P":{"T":180}};E

Каждое сообщение начинается с S и заканчивается на E. Команда, связанная с сообщением, - «ОТПРАВИТЬ», а длина полезной нагрузки - 40.

Моя идея - прочитать байты, поступающие из UART, и:

  • проверить, начинается ли сообщение с S
  • проверить, заканчивается ли сообщение E
  • если приведенные выше предположения верны, разделите сообщение, чтобы найти команду и полезную нагрузку.

Какой лучший способ проанализировать все байты, поступающие от асинхронного uart?

Мое беспокойство связано с потерей сообщения из-за неправильного (или медленного) анализа.

Спасибо за помощь!

BR, Федерико

Ответы [ 2 ]

0 голосов
/ 02 мая 2018

В своей повседневной работе я написал программное обеспечение для встроенной системы и ПК, связывающихся друг с другом через USB-кабель, используя протокол UART со скоростью 115 200 бод.

Я вижу, что вы пометили свой пост PySerial, так что вы уже знаете о самом популярном пакете Python для связи через последовательный порт. Я добавлю, что если вы используете PyQt, в этот пакет также входит последовательный модуль.

115 200 бод не быстры для современного настольного ПК. Я сомневаюсь, что любой анализ, который вы выполняете на стороне ПК, не будет поддерживать. Я анализирую потоки данных и строю графики своих данных в режиме реального времени, используя PyQt.

Что я заметил в своей работе со связью между встроенной системой и ПК через UART, так это то, что некоторые данные иногда бывают повреждены. Байт может быть искажен, повторен или отброшен. Кроме того, даже если ни один байт не добавлен или не удален, вы можете время от времени выполнять чтение, пока только часть пакета находится в буфере, и чтение будет прекращено досрочно. Если вы используете фиксированную длину чтения 40 байтов и уверены, что каждое чтение всегда будет совпадать с пакетом данных, как показано выше, вы часто ошибаетесь.

Чтобы решить проблемы такого рода, я написал класс FIFO на Python, который использует данные последовательного порта в начале FIFO, выдает допустимые пакеты данных в хвосте и отбрасывает недопустимые данные. Мой FIFO содержит в 3 раза больше байтов, чем мои пакеты данных, поэтому, если я ищу границы пакетов, используя определенные последовательности, у меня много указателей.

Еще несколько рекомендаций: работайте в Python 3, если у вас есть выбор, он чище. Используйте байты и объекты bytearray. Не используйте str, потому что вы обнаружите, что конвертируете назад и вперед между Unicode и ASCII.

0 голосов
/ 02 мая 2018

Этот формат почти разбирается как csv, но не совсем, потому что четвертое поле - JSON, и вы не сможете гарантировать, что JSON не содержит строк со встроенными точка с запятой. Итак, я думаю, что вы, вероятно, хотите просто использовать функции манипуляции со строками (или, скорее, байтами):

def parsemsg(buf):
    s, cmd, length, rest = buf.split(b';', 3)
    j, _, e = rest.rpartition(b';')
    if s != b'S' or e != b'E':
        raise ValueError('must start with S and end with E')
    return cmd.decode('utf-8'), int(length), json.loads(j)

Тогда:

>>> parsemsg(b'S,SEND,40,{"ID":"asg01","T":1,"P":{"T":180}},E')
('SEND', 40, {'ID': 'asg01', 'T': 1, 'P': {'T': 180}})

Фактическая часть анализа точки с запятой занимает 602 нс на моем ноутбуке, decode и int повышают это до 902 нс. json.loads, с другой стороны, занимает 10US. Так что, если вы беспокоитесь о производительности, JSON-часть действительно является единственной частью, которая имеет значение (пробуя сторонние библиотеки JSON, которые я установил, самая быстрая из них - все еще 8.1us, что не намного лучше). Вы могли бы также сделать все остальное простым и надежным.

Кроме того, учитывая, что вы читаете это со скоростью 115000 бод, вы не можете получить эти сообщения быстрее, чем примерно 6 мс, поэтому потратить 11US на их разбор даже не близко к проблеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...