前文【逗老师带你学IT】PRTG监控通过Python+TCP Modbus获取温湿度传感器数据中我们讲了如何通过Python读取支持TCP Modbus的传感器数据。本章我们讲解下如何读取Modbus RTU传感器的数据。
目录
一、Modbus TCP和RTU的区别
Modbus协议包括ASCII、RTU、TCP等,并没有规定物理层。
1、接口区别
Modbus rtu和Modbus tcp两个协议的本质都是Modbus总线协议,都是靠Modbus寄存器地址来交换数据。
但二者所用的硬件接口不一样,Modbus RTU一般采用串口RS232C或RS485/422,而Modbus TCP一般采用以太网口。现在市场上有很多协议转换器,可以轻松的将这些不同的协议相互转换。
2、数据帧区别
2.1、请求帧区别举例
TCP请求帧:00 4b 00 00 00 06 01 03 00 00 00 02
事务处理标识符 | 协议标识符 | 数据长度 | 从机地址 | 功能码 | 寄存器起始地址 | 读取寄存器个数 |
---|---|---|---|---|---|---|
00 4b | 00 00为modbus协议 | 00 06 | 01 | 03(读) | 0000 | 0002 |
RTU请求帧:01 03 00 00 00 02 C4 0B
从机地址 | 功能码 | 寄存器起始地址 | 读取寄存器个数 | CRC校验 |
---|---|---|---|---|
01 | 03(读) | 0000 | 0002 | C40B |
2.2、应答帧区别举例
TCP应答帧:00 4b 00 00 00 07 01 03 04 01 b6 01 00
事务处理标识符 | 协议标识符 | 数据长度 | 从机地址 | 功能码 | 返回字节个数 | 寄存器40001数据 | 寄存器40002数据 |
---|---|---|---|---|---|---|---|
00 4B | 00 00 | 00 07 | 01 | 03 | 04 | 01 B6 | 01 00 |
RTU应答帧:01 03 04 01 94 00 E2 3A 6A
从机地址 | 功能码 | 返回字节个数 | 寄存器40001数据 | 寄存器40002数据 | CRC校验 |
---|---|---|---|---|---|
01 | 03 | 04 | 01 94 | 00 E2 | 3A 6A |
对比来看,请求帧中TCP比RTU异步串口增加了协议标识符和数据长度,这是符合TCP设计思路的。同时TCP比RTU取消了CRC校验,因为在TCP/IP层会自带CRC校验
二、Python的Modbus RTU客户端
1、Python modbus_tk第三方库
Python中提供了支持Modbus协议的第三方库——modbus_tk,简单的通过pip install modbus_tk
即可安装
2、确认温度传感器寄存器地址
对于你购买的支持TCP Modbus协议的温湿度传感器,请查阅说明书确认温度、湿度两个数据的寄存器地址。
比如,我这个温度传感器,很简单的就是第1、2两个寄存器内存储着湿度、温度。
三、数据整合展示到PRTG监控系统
1、串口服务器配置
如果你的温湿度传感器直接通过串口连接到监控服务器,可以跳过本小节。
如果你的问温湿度服务器通过串口转以太网映射到监控服务器,可以查阅说明书,我们在这用有人科技的一款转换器,举例配置如下:
1.1、服务端配置
1.2、客户端配置
通过服务端的IP地址+端口,为本地添加映射的虚拟串口。
2、代码部分
import json
import threading
from multiprocessing import Process,Manager,freeze_support
import time
import serial
import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
PORT = '/dev/cu.usbserial-AK08ROD4'
#PORT = 'COM6'
#修改为实际的串口编号
process_list = []
slave_num_list={
"1":"AL-SZ-8F-G5",
"2":"AL-SZ-10F-MDF"
}
#提前写入从站号和从站名称
def print_json(value_list):
try:
data={
"prtg": {
"result": []
}
}
result_data=[]
for i in value_list:
Temperature_data={
"Channel": "%s Temperature"%value_list[i][2],
"Unit": "Temperature",
"Mode":"Absolute",
"DecimalMode":"All",
"Float":1,
"LimitMode":1,
"LimitMaxWarning":35,
"LimitMinWarning":18,
"Value":int(value_list[i][1])/10
}
Humidity_data={
"Channel": "%s Humidity"%value_list[i][2],
"Unit": "Percent",
"Mode":"Absolute",
"DecimalMode":"All",
"Float":1,
"LimitMode":1,
"LimitMaxWarning":70,
"LimitMinWarning":10,
"Value":int(value_list[i][0])/10
}
data['prtg']['result'].append(Temperature_data)
data['prtg']['result'].append(Humidity_data)
print (json.dumps(data, sort_keys=True, indent=2))
except Exception as err:
raise err
def get_value(slave_num,value_list):
try:
master = modbus_rtu.RtuMaster(serial.Serial(port=PORT, baudrate=4800, bytesize=8, parity='N', stopbits=1, xonxoff=0))
master.set_timeout(5.0)
master.set_verbose(True)
Hold_value=master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 2)
Hold_value=list(Hold_value)
Hold_value.append(slave_num_list[slave_num])
except Exception as err:
#print([0,0,host_list[host_ip]])
value_list[slave_num]=[0,0,slave_num_list[slave_num]]
else:
value_list[slave_num]=Hold_value
#print(value_list)
def main():
try:
manager=Manager()
value_list=manager.dict()
for slave_num in slave_num_list:
p = Process(target=get_value, args=(slave_num,value_list))
process_list.append(p)
p.start()
for p in process_list:
p.join()
#print(value_list)
print_json(value_list)
except Exception as err:
data={
"prtg": {
"error": 1,
"text": str(err)
}
}
print (json.dumps(data, sort_keys=True, indent=2))
if __name__ == "__main__":
freeze_support()
main()
运行后给出的符合PRTG要求的json结构格式数据
{
"prtg": {
"result": [
{
"Channel": "AL-SZ-8F-G5 Temperature",
"DecimalMode": "All",
"Float": 1,
"LimitMaxWarning": 35,
"LimitMinWarning": 18,
"LimitMode": 1,
"Mode": "Absolute",
"Unit": "Temperature",
"Value": 22.3
},
{
"Channel": "AL-SZ-8F-G5 Humidity",
"DecimalMode": "All",
"Float": 1,
"LimitMaxWarning": 70,
"LimitMinWarning": 10,
"LimitMode": 1,
"Mode": "Absolute",
"Unit": "Percent",
"Value": 34.6
},
{
"Channel": "AL-SZ-10F-MDF Temperature",
"DecimalMode": "All",
"Float": 1,
"LimitMaxWarning": 35,
"LimitMinWarning": 18,
"LimitMode": 1,
"Mode": "Absolute",
"Unit": "Temperature",
"Value": 23.2
},
{
"Channel": "AL-SZ-10F-MDF Humidity",
"DecimalMode": "All",
"Float": 1,
"LimitMaxWarning": 70,
"LimitMinWarning": 10,
"LimitMode": 1,
"Mode": "Absolute",
"Unit": "Percent",
"Value": 37.1
}
]
}
}
Program ended with exit code: 0
往期回顾:
【逗老师带你学IT】HUAWEI华为防火墙自动化运维Python ssh管理网络设备
【逗老师带你学IT】PRTG获取HUAWEI FusionServer iBMC传感器状态
【逗老师带你学IT】PRTG自定义脚本ssh登录网络设备获负载均衡链路状态
【逗老师带你学IT】Django+IIS+Python构建微软AD域控API管理中心
【逗老师带你学IT】通过企业微信推送AD域密码即将到期提醒
【逗老师带你学IT】AD域控 Dsquery 查询命令实例汇总
【逗老师带你学IT】Google Admin服务账号+API管理G suit内所有网域用户
【逗老师带你学IT】PRTG监控系统通过企业微信推送图文混排告警消息
【逗老师带你学IT】PRTG HTTP API获取指定传感器流量图表图片
【逗老师带你学IT】PRTG监控系统合并多个传感器通道数据
【逗老师带你学IT】PRTG监控系统通过企业微信推送告警消息
【逗老师带你学IT】PRTG监控系统配合树莓派采集企业内部无线网络质量
【逗老师带你学IT】vMware ESXi 6.7合并第三方硬件驱动
【逗老师带你学IT】Kiwi Syslog Server安装和配置教程
【逗老师带你学IT】Kiwi Syslog Web Access与Active Directory集成认证
【逗老师带你学IT】vMware ESXi 6.7合并第三方硬件驱动
【逗老师带你学IT】Windows Server Network Policy Service(NPS)记账与审计
【逗老师带你学IT】Windows Server NPS服务构建基于AD域控的radius认证
【逗老师带你学IT】AD域控和freeradius集成认证环境,PAP,MSCHAPV2
【逗老师带你学IT】深信服SSL远程接入与深信服行为审计同步登陆用户信息