无法在 Python 中的自定义序言和 telnetlib 之间解压信息

unable to unpack information between custom Preamble in Python and telnetlib

我有一个工业传感器,它通过 telnet 通过端口 10001 向我提供信息。

它有一个Data Format如下:

还有手册:

All the measuring values are transmitted int32 or uint32 or float depending on the sensors

代码

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'
  1. 尝试解压序言!?

如何在序言之间读取 Article numberSerial numberChannelStatusMeasuring Value 等信息?

负载大小似乎固定为 22 字节(通过 Wireshark)

解析反向缓冲区只是奇怪;请使用 struct's support for endianess. Using big-endian '!'在小端上下文中也是奇数。

前四个字节是文本常量。好吧,也许你需要扭转这些。但是 只是 那些,拜托了。

之后用struct.unpack解析出'IIQI'。到目前为止,您的方法可以正常工作,因为所有字段都占用 4 个字节或一对 4 个字节。但是找到帧 M 的长度是美中不足的,因为它只有 2 个字节,所以用 'H' 解析它,得到一个组合 'IIQIH'。在那之后,您只需要前进那么多字节,然后在用完那组测量值后期待另一个 'MEAS' 文本常量。

我设法完全避免了 TelnetLib,并使用 python3 创建了一个 tcp 客户端。我已经从我的 wireshark 转储中获得了有效负载大小(22 字节),因此我不断收到 22 字节的信息。 显然模块发送了两个不同的 22 字节有效负载

  1. 第一个(帧)有效载荷具有 preambleserialarticlechannel 信息
  2. 第二个(帧)有效载荷包含 bytes per framemeasuring value countermeasuring value Channel 1measuring value Channel 2measuring value Channel 3
  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)

果然,这给了我需要的信息,我通过公司提供的专有软件比对了信息。