Я работаю над проектом, в котором данные игровой телеметрии из F1 2012 интерпретируются Python и отправляются в Arduino для отображения в виде физической панели.

F1 2012 отправляет данные через UDP-пакеты по адресу 127.0.0.1, порт 20777.

У меня есть простая программа на Python, которая читает входящие пакеты:

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 20777

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)
    print ("Message:" data)

Это выводит такие сообщения, как:

b'\xce\xb3T@\x00\x00\x00\x001K\xa7E\xa0\xf1\xf0\xbc\xa1\xc6\x13\xc4OY\x0b\xc3\xd5\xbf.D\xca\xe2\xc2;\xb0\x9109\xf0\x19\xbd\xbb\xdd8\xbb:q\x19M\xbf\x81t.933\x19\xbf\x1e,\x19\xbf\xc2\x82\x9d\xbc\x9c\x0fM?\xa2#H\xbc\xd6\x16x\xbe\x92hr\xba:\xa8\x88=X\xd7&?q$\xc7>\x82w#><\xe9\x1d>w\xc9\xb8\xa7Bh\x010\x00\x00\x00\x00kr\xb7\xaf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80?\x00\x00\x80?\x96z\x98\xb9!f\x849\x00\x00\x00\x00\x8d\x8b5C'

Я знаю, что это довольно длинный вывод, но он содержит 38 параметров об автомобиле, которые обновляются 60 раз в секунду. Они описаны в этот веб-сайт кем-то, кто работает над аналогичным проектом.

Я искал похожие вопросы о stackeoverflow с выходами из UDP, аналогичными моему, и мне сообщили, что данные необходимо распаковать в подходящем формате.

Читая этот веб-сайт, кажется, что все данные в пакетах Типы float в C, поэтому я изменил свой исходный код на Python.

import socket
import struct

UDP_IP = "127.0.0.1"
UDP_PORT = 20777

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)
    output = struct.unpack('f', data)
    print ("Message:", output)

Unpack имеет формат 'f', чтобы назначить формат входящих данных на основе информации с этой страницы: docs.python.org/3.2/library/struct.html#format-characters

Теперь это вызывает ошибку:

struct.error: unpack requires a bytes object of length 4

Теперь я считаю, что зашел в тупик и не знаю, что делать дальше.

Пожалуйста помоги.

0
jai_ 12 Авг 2014 в 21:38
Неродной размер устранит заполнение, т. Е. =<>! перед строкой формата, например =f. Предполагается, что ваши данные меньше 4 байтов.
 – 
keyser
12 Авг 2014 в 21:46
Также похоже, что вы распаковываете сразу несколько значений, которые занимают более 4 байтов и поэтому не помещаются в структуру C.
 – 
keyser
12 Авг 2014 в 21:52

1 ответ

Лучший ответ

Как говорится в сообщении об ошибке: struct.error: unpack requires a bytes object of length 4, вам необходимо передать 4 байта за раз.

Измените свой код, чтобы отправлять 4 байта за раз

while True:
    data, addr = sock.recvfrom(1024)
    # data is 1024 length bytearray, break into 4 bytes and get the output
    output = struct.unpack('f', data[0:4]) # 4 bytes at a time
    print ("Message:", output)
0
sk11 12 Авг 2014 в 21:55
Большое спасибо, это очень хорошо работает. Ваше решение способно вывести первый параметр, указанный во второй ссылке, который является «время» (т.е. время, прошедшее с момента начала сеанса телеметрии). Теперь я знаю, что каждый параметр составляет четыре байта. Я могу настроить значения так, чтобы части прочитанные данные можно распаковать для тех параметров, которые я хочу использовать. Например, чтобы прочитать значение текущей передачи, которая является 34-м параметром, я бы использовал данные [136: 140].
 – 
jai_
12 Авг 2014 в 22:39