WinPower之外的玩法:用Python脚本+串口实时监控山特UPS状态并实现自动关机
·
用Python脚本实现山特UPS状态监控与智能自动化
山特UPS作为企业级电源保护设备,其自带的WinPower软件虽然功能完善,但缺乏灵活性和可编程性。对于技术爱好者而言,通过串口直接与UPS通信,不仅能获取更丰富的实时数据,还能实现高度定制化的自动化流程。本文将带你从零开始构建一个基于Python的UPS监控系统,突破官方软件的限制。
1. 硬件准备与环境搭建
在开始编码前,我们需要确保硬件连接正确。山特C3K系列UPS配备RS-232串口,但现代计算机通常已不再配备这种传统接口。这里有几个关键注意事项:
-
USB转串口适配器选择 :建议使用FTDI芯片的转换器(如FT232RL),稳定性远优于廉价方案
-
线序确认 :必须使用直连线而非交叉线,接线方式为:
UPS端 电脑端 TX RX RX TX GND GND -
串口参数配置 :
serial_config = { 'port': 'COM3', # 根据实际端口调整 'baudrate': 2400, 'bytesize': 8, 'parity': 'N', 'stopbits': 1, 'timeout': 1 }
提示:在Linux系统下,串口设备通常为
/dev/ttyUSB0形式,需要确保用户有读写权限(可执行sudo chmod 666 /dev/ttyUSB0)
安装必要的Python库:
pip install pyserial schedule python-dotenv
2. 通讯协议解析与基础交互
通过逆向分析WinPower的通信过程,我们发现山特UPS采用基于ASCII字符的简单协议。核心命令包括:
- Q1 :获取基础状态(输入/输出电压、频率等)
- Q6 :扩展状态查询(包含电池电压和温度)
- WA :负载百分比
- WC :功率数据(有功/视在功率)
典型交互流程如下:
import serial
def query_ups(command):
with serial.Serial(**serial_config) as ser:
ser.write(f"{command}\r".encode())
response = ser.readline().decode().strip()
return response
# 示例:获取Q6数据
q6_data = query_ups("Q6")
print(f"Raw Q6 response: {q6_data}")
响应数据通常采用固定格式:
( 235.6 236.0 220.0 006 50.0 2.30 28.5 00000000
各字段含义可通过以下映射表理解:
| 位置 | 示例值 | 含义 | 单位 |
|---|---|---|---|
| 1 | 235.6 | 输入电压 | V |
| 2 | 236.0 | 输入故障电压 | V |
| 3 | 220.0 | 输出电压 | V |
| 4 | 006 | 负载百分比 | % |
| 5 | 50.0 | 市电频率 | Hz |
| 6 | 2.30 | 电池电压 | V/节 |
| 7 | 28.5 | 电池温度 | °C |
| 8 | 00000000 | 状态码 | - |
3. 构建完整的监控类
为实现更结构化的访问,我们可以创建一个 UPSMonitor 类:
class UPSMonitor:
def __init__(self, port):
self.serial_config = {
'port': port,
'baudrate': 2400,
'timeout': 1
}
def _send_command(self, cmd):
try:
with serial.Serial(**self.serial_config) as ser:
ser.write(f"{cmd}\r".encode())
return ser.readline().decode().strip()
except serial.SerialException as e:
print(f"Serial error: {e}")
return None
def get_status(self):
"""获取完整状态信息"""
q6 = self._parse_q6(self._send_command("Q6"))
wa = self._parse_wa(self._send_command("WA"))
wc = self._parse_wc(self._send_command("WC"))
return {
**q6,
'load_percentage': wa['load_percentage'],
'active_power': wc['active_power'],
'apparent_power': wc['apparent_power'],
'power_factor': round(wc['active_power'] / wc['apparent_power'], 2)
}
def _parse_q6(self, response):
# 实现Q6响应解析
pass
def _parse_wa(self, response):
# 实现WA响应解析
pass
def _parse_wc(self, response):
# 实现WC响应解析
pass
4. 高级应用场景实现
4.1 与Home Assistant集成
通过MQTT协议将UPS数据接入智能家居系统:
import paho.mqtt.client as mqtt
class UPS2MQTT(UPSMonitor):
def __init__(self, port, mqtt_config):
super().__init__(port)
self.mqtt_client = mqtt.Client()
self.mqtt_client.connect(**mqtt_config)
def publish_status(self):
status = self.get_status()
for key, value in status.items():
self.mqtt_client.publish(f"ups/{key}", value)
4.2 自动化关机保护
实现低电量自动安全关机逻辑:
import os
import time
class AutoShutdown(UPSMonitor):
def __init__(self, port, threshold=20):
super().__init__(port)
self.threshold = threshold
def run(self):
while True:
status = self.get_status()
if status['battery_voltage'] < self.threshold:
self._safe_shutdown()
time.sleep(60)
def _safe_shutdown(self):
print("Initiating safe shutdown sequence...")
# 执行应用关闭脚本
os.system("/path/to/backup_script.sh")
# 关机
os.system("shutdown -h now")
4.3 Prometheus监控集成
创建适合Prometheus拉取的metrics端点:
from prometheus_client import start_http_server, Gauge
class UPSMetrics(UPSMonitor):
def __init__(self, port, prom_port=8000):
super().__init__(port)
self.metrics = {
'input_voltage': Gauge('ups_input_voltage', 'Input voltage (V)'),
'output_voltage': Gauge('ups_output_voltage', 'Output voltage (V)'),
# 其他metrics定义...
}
start_http_server(prom_port)
def update_metrics(self):
status = self.get_status()
for name, value in status.items():
if name in self.metrics:
self.metrics[name].set(value)
5. 异常处理与优化技巧
在实际部署中,需要考虑以下关键点:
-
通信可靠性 :
- 实现命令重试机制(当收到NAK响应时)
- 添加串口连接心跳检测
- 记录通信失败日志
-
数据平滑处理 :
from collections import deque import statistics class SmoothingFilter: def __init__(self, window_size=5): self.window = deque(maxlen=window_size) def add_reading(self, value): self.window.append(value) return statistics.median(self.window) -
配置管理 : 使用
.env文件管理敏感参数:# .env SERIAL_PORT=/dev/ttyUSB0 MQTT_BROKER=homeassistant.local SHUTDOWN_THRESHOLD=20 -
系统服务化 : 创建systemd服务文件实现开机自启:
# /etc/systemd/system/ups-monitor.service [Unit] Description=UPS Monitoring Service After=network.target [Service] ExecStart=/usr/bin/python3 /opt/ups-monitor/main.py Restart=always User=root [Install] WantedBy=multi-user.target
更多推荐

所有评论(0)