【逗老师带你学IT】PRTG监控通过Python通过串口监控UPS运行状态,PRTG值查询功能定义

news/2024/11/30 7:53:19/

本文主要介绍,如何通过串口获取UPS主机的运行状态,并通过PRTG统计监控和告警。
不同UPS主机厂的串口通信协议不同,但是市面上有一种比较通用的协议,如果你使用的是EATON,山特等等国产UPS,大概率用的都是Q1协议。
本文涉及的知识点:

1、UPS串口通信分析
2、python中的pyserial模块使用。
3、PRTG的lookup值查询功能定义

本文最终实现效果如下:
在这里插入图片描述

目录

  • 一、UPS串口协议分析
    • 1、搭建抓包环境
    • 2、开始抓包
    • 3、分析报文内容
  • 二、python中serial模块的使用
  • 三、PRTG中的值查询功能
    • 1、新建值查询定义文件
    • 2、加载定义文件
    • 3、编辑通道,调用定义文件
  • 搞定!

一、UPS串口协议分析

原则上,每家UPS主机厂都多多少少会有一些自己的私有协议。开发文档也不一定公开。但是我们可以稍微分析一下,基本都可以分析得出每家主机厂的通信协议。
本文一一款山特的国产UPS举例,说明如何分析串口通信协议。

1、搭建抓包环境

说到网络抓包,大家都很熟悉。但是如何对串口通信进行抓包?
一种办法是通过串口抓包软件,对本机串口进行抓包。例如Device Monitoring Studio
在这里插入图片描述
软件功能比较强大,是收费软件,免费试用15天。从截图可以看出,选择了通信端口以后,可以很轻松监控串口数据。另外从界面上看它还有数据统计等很多其它功能,我没有全部试用,就不多介绍了。需要注意一点,它的启动按钮在界面右侧下方。

另一种办法是如果使用了串口转以太网盒子,可以在网络侧进行抓包。或者利用虚拟串口软件自带的抓包功能。
在这里插入图片描述

2、开始抓包

解决了抓包问题后,我们开始尝试通过厂商自带的方式与UPS尝试通信。
因为原厂的管理软件是肯定可以正常可以与UPS通信的,所以我们的思路是尝试去分析原厂软件是如何管理UPS的,并以此设计和编写我们自己的监控脚本。
首先用最正经的方式,下载原厂的UPS管理软件,安装,连接UPS。
在这里插入图片描述
当通过原厂的管理软件可以读到UPS后,我们就开始分析此时COM口上的通信内容,并以此分析主机的串口通信协议。

3、分析报文内容

在原厂管理软件在与UPS主机通信的时候,我们抓到了以下关键内容。
在这里插入图片描述
问询帧1:
HEX:
51 31 0D
ASCII:
Q1
应答帧1:
HEX:
28 32 33 37 2E 31 20 32 33 37 2E 39 20 32 32 30 2E 30 20 30 30 36 20 34 39 2E 39 20 32 2E 32 39 20 32 38 2E 38 20 30 30 30 30 30 30 30 31 0D
ASCII:
(237.1 237.9 220.0 006 49.9 2.29 28.8 00000001

问询帧2:
HEX:
46 0D
ASCII:
F
应答帧2:
HEX:
23 32 32 30 2E 30 20 31 33 36 20 31 39 32 2E 30 20 35 30 2E 30 0D
ASCII:
#220.0 136 192.0 50.0

这其中(237.1 237.9 220.0 006 49.9 2.29 28.8 00000001的这一句,是不是看起来就很像是电压和功率等数据呢?而且,还是用ASCII编码,肉眼可见。
配合原厂的管理软件,多观察一会抓包数据和软件显示的数据,我们大致可以分析出这个应答帧中各个字段的含义。
笔者直接粘分析结果。同时对于市面上大部分用0x51 31 0D做请求帧的UPS,应答帧的解释都是差不多的。

(MMM.MNNN.NPPP.PQQQRR.RS.SSTT.TU
(237.1237.9220.000649.92.2928.800000001
起始码0x28输入电压输入故障电压输出电压负载%市电频率Hz电池电压温度状态码

关于故障输入电压:
对于在线式UPS而言,此字段保持位上一次电压瞬变前的电压。例如市电中断时,此字段保持为断电前的输入电压,并一直维持到下一次查询。

关于电池电压:
在线式UPS此电压为单体电池电压。电池组总电压请自行计算乘以电池数量乘以电池cell数量。总电池组用了16节12v铅酸蓄电池串联,每个铅酸蓄电池含6个单体电池。所以总电池组电压是2.29v * 6 * 16=219.84v

关于状态码:
Bit7 1 : Utility Fail ( Immediate )
Bit6 1 : Battery Low
Bit5 1 : Bypass/Boost Active
Bit4 1 : UPS Failed
Bit3 1 : UPS Type is Standby (0 is On-line)
Bit2 1 : Test in Progress
Bit1 1 : Shutdown Active
Bit0 1 : Speaker Config ON

二、python中serial模块的使用

有了数据和解释。接下来写代码。serial模块默认自带,一般不需要单独pip安装
本文给出一个可以用于PRTG前端展示的示例代码,详细解释看注释。

import serial
from time import sleep
import json
import re
import sys
#PORT = '/dev/cu.usbserial-AK08ROD4'
data = json.loads(sys.argv[1])
params=str(data['params']).replace("'",'"')
params = json.loads(params)
PORT = params['PORT']
#PRTG调用时,我们将COM口的编号通过['params']['PORT']字段传递进来。def get_serial_data(serial_session):try:serial_command = bytes.fromhex('51 31 0D')#16进制格式的问询指令serial_session.write(serial_command)#向UPS发送问询指令sleep(1)data =data = serial_session.read_all().decode("gbk")#读取回显serial_session.close()except Exception as err:return '(000 000 000 000 000 000 000 00000001'else:return datadef sort_serial_data(serial_data):#整理数据try:data=serial_data.split()#原始数据切片data[0]=data[0].replace('(','')data_dict={}status_flag=re.findall(r'.{1}', data[7])#状态码切片data_dict['INPUT_Voltage']=[data[0],'V']data_dict['INPUT_Fault_Vlotage']=[data[1],'V']data_dict['OUTPUT_Vlotage']=[data[2],'V']data_dict['OUTPUT_Load']=[data[3],'%']data_dict['OUTPUT_Frequency']=[data[4],'Hz']data_dict['Battery_Vlotage']=[float(data[5])*96,'V']data_dict['UPS_Temperature']=[data[6],'degress C']data_dict['Speaker_Status']=[status_flag[7],'#']data_dict['Shutdown_Active_Status']=[status_flag[6],'#']data_dict['Test_in_Progress']=[status_flag[5],'#']data_dict['UPS_Type']=[status_flag[4],'#']data_dict['UPS_System_Failed']=[status_flag[3],'#']data_dict['Bypass_Status']=[status_flag[2],'#']data_dict['Battery_Low_Alarm']=[status_flag[1],'#']data_dict['Input_Power_Status']=[status_flag[0],'#']except Exception as err:raise errelse:return data_dictdef print_json(value_list):try:data={"prtg": {"result": [{"Channel": "Run Result","CustomUnit": "#","Mode":"Absolute","Float":1,"Value":"0"}]}}for i in value_list:data_channels={"Channel": i,"CustomUnit": value_list[i][1],"Mode":"Absolute","Float":2,"Value":value_list[i][0]}data['prtg']['result'].append(data_channels)print (json.dumps(data, sort_keys=True, indent=2))except Exception as err:raise errdef main():try:serial_session=serial.Serial(port=PORT, baudrate=2400, bytesize=8, parity='N', stopbits=1, xonxoff=0)#定义串口连接参数serial_data=get_serial_data(serial_session)data=sort_serial_data(serial_data)print_json(data)except Exception as err:data={"prtg": {"error": 1,"text": str(err)}}print (json.dumps(data, sort_keys=True, indent=2))if __name__ == "__main__":main()

输出符合PRTG监控系统格式的json结构体数据

{"prtg": {"result": [{"Channel": "Run Result","CustomUnit": "#","Float": 1,"Mode": "Absolute","Value": "0"},{"Channel": "INPUT_Voltage","CustomUnit": "V","Float": 2,"Mode": "Absolute","Value": "234.9"},{"Channel": "INPUT_Fault_Vlotage","CustomUnit": "V","Float": 2,"Mode": "Absolute","Value": "234.9"},{"Channel": "OUTPUT_Vlotage","CustomUnit": "V","Float": 2,"Mode": "Absolute","Value": "220.0"},{"Channel": "OUTPUT_Load","CustomUnit": "%","Float": 2,"Mode": "Absolute","Value": "006"},{"Channel": "OUTPUT_Frequency","CustomUnit": "Hz","Float": 2,"Mode": "Absolute","Value": "50.0"},{"Channel": "Battery_Vlotage","CustomUnit": "V","Float": 2,"Mode": "Absolute","Value": 219.84},{"Channel": "UPS_Temperature","CustomUnit": "degress C","Float": 2,"Mode": "Absolute","Value": "28.9"},{"Channel": "Speaker_Status","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "1"},{"Channel": "Shutdown_Active_Status","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"},{"Channel": "Test_in_Progress","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"},{"Channel": "UPS_Type","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"},{"Channel": "UPS_System_Failed","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"},{"Channel": "Bypass_Status","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"},{"Channel": "Battery_Low_Alarm","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"},{"Channel": "Input_Power_Status","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"}]}
}
Program ended with exit code: 0

三、PRTG中的值查询功能

上面的例子中,我们将UPS的状态码传递给上层监控系统。但是监控系统如何知道状态码为0和为1时候,代表什么意思呢?

{"Channel": "Input_Power_Status","CustomUnit": "#","Float": 2,"Mode": "Absolute","Value": "0"}

例如这个通道的数据中,Value字段表示市电输入状态,为0时表示输入正常,为1时表示市电输入中断。
这时候,我们需要用PRTG的值查询功能,将不同的数值定义成不同的状态。

1、新建值查询定义文件

在PRTG核心服务器的C:\Program Files (x86)\PRTG Network Monitor\lookups\custom目录下,我们新建一个Santak_UPS_RS232_Alarm.ovl文件,并用记事本打开进行编辑,内容如下:

<?xml version="1.0" encoding="UTF-8"?><ValueLookup id="Santak_UPS_RS232_Alarm" desiredValue="1" undefinedState="Warning"><Lookups><SingleInt state="OK" value="0">Run_Status_OK</SingleInt><SingleInt state="Error" value="1">Run_Status_Error</SingleInt></Lookups></ValueLookup>

我们定义:
value=0的时候,文本显示"Run_Status_OK",状态为正常(OK)。
value=1的时候,文本显示"Run_Status_Error",状态为停机(Error)。
value等于其他值的时候,undefinedState=“Warning”,状态为告警(Warning)。

2、加载定义文件

在PRTG控制台中,进入系统->管理工具->点击加载查询和文件列表
在这里插入图片描述

3、编辑通道,调用定义文件

点击通道右侧的齿轮图标,打开通道编辑
在这里插入图片描述
在编辑通道窗口内,在“值查询”下拉菜单中选中刚才我们新建的定义文件。
在这里插入图片描述
然后,这个通道的值就不再是简单的0和1了。而是变成了带有文本描述和告警状态定义的通道状态。
在这里插入图片描述

搞定!

往期回顾:
【逗老师带你学IT】PRTG监控通过Python+Modbus RTU获取温湿度传感器数据
【逗老师带你学IT】PRTG监控通过Python+Modbus TCP获取温湿度传感器数据
【逗老师带你学IT】职场数据中心异地出口容灾,H3C的IP上一跳保持技术
【逗老师带你学IT】阿里云监控报警回调+转发企业微信+转发SnmpTrap+PRTG
【逗老师带你学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远程接入与深信服行为审计同步登陆用户信息


http://www.ppmy.cn/news/642830.html

相关文章

利用vMA在UPS市电断电时关闭ESXi主机

在上一篇介绍了如何部置vMA&#xff0c;在本篇我们利用vMA使UPS在市电断电后&#xff0c;自动关闭ESXi主机及里面的所有虚拟机。需求 现有一服务器&#xff0c;安装 ESXi55&#xff0c;里面有若干虚拟机&#xff0c;一台山特C3K UPS,市电断电后&#xff0c;要求UPS通知ESXi关机…

一篇文章,带你详细了解华为认证体系证书 (一)

一篇文章&#xff0c;带你详细了解华为认证体系证书&#xff08;2&#xff09;_PICACHU的博客-CSDN博客_华为高斯数据库证书掌握数据库的基础知识&#xff0c;openGauss数据库的基础架构和生态&#xff0c;华为云数据库GaussDB(for openGauss)的组网形态、企业特性、应用场景能…

华为UPS“内外”兼修

华为、阿里巴巴等十余家企业已经通过了IDC业务牌照审查&#xff0c;并顺利获批牌照。这对华为的数据中心和网络能源业务来说无疑是一个利好消息。华为技术有限公司企业网络能源产品领域副总经理蒋天利表示&#xff1a;“此举进一步拉近了我们与客户之间的距离&#xff0c;让我们…

步进电机保养小窍门

步进电机本身具有很多优势&#xff0c;在工作中所发挥的功能也对照富强。但是人们也知道任何配备的运行&#xff0c;想要更好发挥作用&#xff0c;都离不开同样平常保养。所以步进电机得同样平凡保养事变很重要&#xff0c;那么要如何正确保养步进电机&#xff0c;下文就往为人…

linux UPS状态,LINUX 与 UPS(转)

LINUX 与 UPS(转)[more]网上介绍的linux与ups的连接都不太实用&#xff0c;我在刚接触linux时&#xff0c;那是在4年前&#xff0c;独创一种简单有效的办法&#xff0c;就是根据网线的状态来判断是否需要关机。 原理:在掉电时&#xff0c;一般交换机不会被ups供电&#xff0c;此…

华为UPS电源最新检修方法大全

故障分析:从现象判断为蓄电池和逆变器部分故障,可按以下程序检查:      1)检查蓄电池电压,看蓄电池是否充电不足,若蓄电池充电不足,则要检查是蓄电池本身的故障还是充电电路故障。      2)若蓄电池工作电压正常,检查逆变器驱动电路工作是否正常,若驱动电路输出正常,说明…

华为UPS巡检一体化触摸屏监控方案

一、方案背景&#xff1a; 某UPS电源品牌经销商通过网络联系到我们&#xff0c;希望我们提供一套UPS电源及电池监控的方案。能与其UPS电源及电池进行整合销售&#xff0c;完善UPS电源系统的同时&#xff0c;也方便用户对UPS及其电池的监测和管理。 二、解决方案&#xff1a; …

通过Zabbix和SNMP监控华为UPS与机柜

目录 1 网络配置 1.1 网管端配置SNMP版本和团体名&#xff1a; 1.2 准备MIB 1.3 安装本地MIB浏览器 1.4 找到指定的OID 2 Zabbix配置 2.1 Zabbix 主机上安装配置SNMP监控 2.2 创建监控主机&#xff1a; 2.3 创建监控项 2.3.1 进入主机页面 2.3.2 …