невозможно распаковать информацию между пользовательской Преамбулой в Python и telnetlib - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть промышленный датчик, который предоставляет мне информацию через telnet через порт 10001.

. Он имеет формат данных следующим образом:

Table Data Format

Также руководство:

Все измеренные значения передаются в int32 или uint32 или плавают в зависимости от датчиков

Код

import telnetlib
import struct
import time

# IP Address, Port, timeout for Telnet
tn = telnetlib.Telnet("169.254.168.150", 10001, 10)


while True:
    op = tn.read_eager() # currently read information limit this till preamble
    print(op[::-1]) # make little-endian
    if not len(op[::-1]) == 0: # initially an empty bit starts (b'')
        data = struct.unpack('!4c', op[::-1]) # unpacking `MEAS`
    time.sleep(0.1)

моя первоначальная попытка:

  1. Подключение к датчику

  2. чтение данных

  3. сделать это в порядке байтов

ВЫХОД

b''
b'MEAS\x85\x8c\x8c\x07\xa7\x9d\x01\x0c\x15\x04\xf6MEAS'
b'\x04\xf6MEAS\x86\x8c\x8c\x07\xa7\x9e\x01\x0c\x15\x04\xf6'
b'\x15\x04\xf6MEAS\x85\x8c\x8c\x07\xa7\x9f\x01\x0c\x15'
b'\x15\x04\xf6MEAS\x87\x8c\x8c\x07\xa7\xa0\x01\x0c'
b'\xa7\xa2\x01\x0c\x15\x04\xf6MEAS\x87\x8c\x8c\x07\xa7\xa1\x01\x0c'
b'\x8c\x07\xa7\xa3\x01\x0c\x15\x04\xf6MEAS\x87\x8c\x8c\x07'
b'\x88\x8c\x8c\x07\xa7\xa4\x01\x0c\x15\x04\xf6MEAS\x88\x8c'
b'MEAS\x8b\x8c\x8c\x07\xa7\xa5\x01\x0c\x15\x04\xf6MEAS'
b'\x04\xf6MEAS\x8b\x8c\x8c\x07\xa7\xa6\x01\x0c\x15\x04\xf6'
b'\x15\x04\xf6MEAS\x8a\x8c\x8c\x07\xa7\xa7\x01\x0c\x15'
b'\x15\x04\xf6MEAS\x88\x8c\x8c\x07\xa7\xa8\x01\x0c'
b'\x01\x0c\x15\x04\xf6MEAS\x88\x8c\x8c\x07\xa7\xa9\x01\x0c'
b'\x8c\x07\xa7\xab\x01\x0c\x15\x04\xf6MEAS\x8b\x8c\x8c\x07\xa7\xaa'
b'\x8c\x8c\x07\xa7\xac\x01\x0c\x15\x04\xf6MEAS\x8c\x8c'
b'AS\x89\x8c\x8c\x07\xa7\xad\x01\x0c\x15\x04\xf6MEAS\x8a'
b'MEAS\x88\x8c\x8c\x07\xa7\xae\x01\x0c\x15\x04\xf6ME'
b'\x15\x04\xf6MEAS\x87\x8c\x8c\x07\xa7\xaf\x01\x0c\x15\x04\xf6'
b'\x15\x04\xf6MEAS\x8a\x8c\x8c\x07\xa7\xb0\x01\x0c'
b'\x0c\x15\x04\xf6MEAS\x8a\x8c\x8c\x07\xa7\xb1\x01\x0c'
b'\x07\xa7\xb3\x01\x0c\x15\x04\xf6MEAS\x89\x8c\x8c\x07\xa7\xb2\x01'
b'\x8c\x8c\x07\xa7\xb4\x01\x0c\x15\x04\xf6MEAS\x89\x8c\x8c'
b'\x85\x8c\x8c\x07\xa7\xb5\x01\x0c\x15\x04\xf6MEAS\x84'
b'MEAS\x87\x8c\x8c\x07\xa7\xb6\x01\x0c\x15\x04\xf6MEAS'
b'\x04\xf6MEAS\x8b\x8c\x8c\x07\xa7\xb7\x01\x0c\x15\x04\xf6'
b'\x15\x04\xf6MEAS\x8b\x8c\x8c\x07\xa7\xb8\x01\x0c\x15'
b'\x15\x04\xf6MEAS\x8a\x8c\x8c\x07\xa7\xb9\x01\x0c'
b'\xa7\xbb\x01\x0c\x15\x04\xf6MEAS\x87\x8c\x8c\x07\xa7\xba\x01\x0c'
попытаться распаковать преамбулу!?

Как прочитать информацию, такую ​​как Article number, Serial number, Channel, Status, Measuring Value между преамбулой?

Размер полезной нагрузки здесь фиксирован для 22 байт (через Wireshark)

Wireshark Picture

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Мне удалось вообще избежать TelnetLib и я создал tcp клиента, используя python3.У меня уже был размер полезной нагрузки из моей свалки Wireshark (22 байта), поэтому я продолжаю получать 22 байта информации. Очевидно, что модуль отправляет две различные полезные данные по 22 байта

  1. Первая (фрейм) полезная нагрузка имеет информацию preamble, serial, article, channel
  2. Вторая (фрейм) полезная нагрузка имеет такую ​​информацию, как bytes per frame, measuring value counter, measuring value Channel 1, measuring value Channel 2, measuring value Channel 3

Информация находится в int32 и поэтому нуждается вформула для преобразования в реальные показания (упомянутые в руководстве по эксплуатации)

(как упомянуто @J_H, распаковка была, как он упомянул в своем ответе с небольшими изменениями)

Код

import socket
import time
import struct

DRANGEMIN = 3261
DRANGEMAX = 15853
MEASRANGE = 50
OFFSET = 35

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_address = ('169.254.168.150', 10001)
print('connecting to %s port %s' % server_address)
sock.connect(server_address)


def value_mm(raw_val):

    return (((raw_val - DRANGEMIN) * MEASRANGE) / (DRANGEMAX - DRANGEMIN) + OFFSET)


if __name__ == '__main__':
    while True:
        Laser_Value = 0
        data = sock.recv(22)
        preamble, article, serial, x1, x2 = struct.unpack('<4sIIQH', data)
        if not preamble == b'SAEM':
            status, bpf, mValCounter, CH1, CH2, CH3 = struct.unpack('<hIIIII',data)
            #print(CH1, CH2, CH3)
            Laser_Value = CH3
            print(str(value_mm(Laser_Value)) + " mm")

        #print('RAW: ' + str(len(data)))
        print('\n')
        #time.sleep(0.1)

Конечно, это дает мне необходимую информацию, и я сравнил информацию с помощью программного обеспечения, которое компания предоставляет.

0 голосов
/ 23 ноября 2018

Разбор обращенного буфера - просто странно ;пожалуйста используйте поддержку struct для endianess.Использование big-endian '!'в контексте с прямым порядком байтов также нечетно.

Первые четыре байта являются текстовой константой.Хорошо, хорошо, возможно, вам нужно будет поменять ихНо просто те, пожалуйста.

После этого используйте struct.unpack, чтобы разобрать 'IIQI'.До сих пор это работало нормально с вашим подходом, поскольку все поля занимают 4 байта или пару из 4 байтов.Но найти длину кадра M - это ложка дегтя, поскольку она составляет всего 2 байта, поэтому проанализируйте ее с помощью 'H', что даст вам в совокупности 'IIQIH'.После этого вам нужно продвинуться только на такое количество байтов, а затем ожидать еще одну текстовую константу 'MEAS', когда вы исчерпали этот набор измерений.

...