我有一个工业传感器,它通过接口模块提供原始值telnet
。
为了连接到它:
telnet 169.254.168.150 10001
我只能从中看到垃圾值。
信息
我所掌握的信息来自接口模块的数据表。
该传感器是模拟传感器,因此Status
标志不相关。
我有一些该公司的专有软件,可以可视化传感器的信息。该软件也使用上面提到的telnet协议来获取信息。我通过 WireShark 交叉检查了它。数据包大小为 22 字节,采用小端字节序。
我无法以编程方式获取我的信息SE查询我希望获取该值,可以将传入的值直接存储在某处(在数据库或文件中)。
有什么方法可以通过命令行提取这些信息吗?
答案1
从 Pastebin 中提取:
00000050 2e 0a 53 41 45 4d 00 00 00 00 f6 04 00 00 15 00 |..SAEM..........|
00000060 00 00 00 00 00 00 00 00 00 00 0c 00 01 00 fa 94 |................|
00000070 00 00 8c 00 00 00 8c 00 00 00 0a 23 00 00 53 41 |...........#..SA|
00000080 45 4d 00 00 00 00 f6 04 00 00 15 00 00 00 00 00 |EM..............|
所以这表明信息都在那里,它是小尾数,你只需要阅读和解析它们。任何您熟悉的工具都可以;一个C程序,一个perl
程序,任何你喜欢的东西。您可能必须跳过telnet
开头的输出,或使用其他内容代替telnet
(例如nc
, netcat
, socat
)。
为了演示perl
,解码一个数据包,你会做类似的事情
cat ... | perl -nle "print join(':',unpack 'a4 (L2 Q L S2 l4)<')"
在转储中的数据包的命令行上,并获得输出
SAEM:0:1270:21:0:12:1:38138:140:140
这只适用于给定数量的通道(并且掩码表示四个测量值之一不应出现,但它有一个值;我不明白那部分)。
如果您根据其他信息获得可变数量的通道,则需要更智能的解析。
答案2
所以显然我的想法是相反的。由于我在 Wireshark 上捕获数据,因此所有数据包都是(会话启动信息),tcp
并且只有最初的几个数据包。telnet
我决定使用 python 创建一个tcp
套接字并读取 22 个字节的数据(大小可从 Wireshark Dump 获得)
我使用struct
模块来获取unpack
信息。有趣的是发现有用的传感器信息总是作为备用 TCP 有效负载,即第一个数据包仅包含以下信息:前言,文章编号,序列号等等,下一个有效负载包含所有信息Counter
,通道1值,通道2值,通道3值
这里获得的信息需要使用int32
模块使用手册中提到的公式转换为适当的值
代码
import socket
import struct
# CONSTANTS for Formula
# ....
# 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):
""" Formula for conversion """
return (((raw_val - DRANGEMIN) * MEASRANGE) / (DRANGEMAX - DRANGEMIN) + OFFSET)
if __name__ == '__main__':
while True:
Laser_Value = 0
data = sock.recv(22)
# First frame
preamble, article, serial, x1, x2 = struct.unpack('<4sIIQH', data)
# if this payload is not the preamble, it must be information payload
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('\n')