
关键词:电力中心、配电柜、SNMP协议、以太网温湿度记录仪、MIB库、Trap告警、阈值配置、OID、轮询策略、配电室环境监测 标签:#物联网 #TCP/IP #UDP #POE供电 #以太网温湿度传感器 #网口温湿度变送器 #机房监控 #SNMP #配电柜监测

电力中心(变电站、配电室、开闭所、新能源升压站)的配电柜内环境监控,与机房动环、楼宇自控、产线监测存在显著差异:
维度 | 机房动环 | 产线监测 | 电力中心配电柜 |
|---|---|---|---|
电磁环境 | 中等 | 强干扰 | 极强:高压开关、变压器、电流互感器、电弧 |
空间约束 | 机柜内 | 车间区域 | 极窄:配电柜内/柜顶,空间受限 |
安装方式 | 导轨/壁挂 | 壁挂/支架 | 磁吸/卡扣/超薄,不占柜内空间 |
通信要求 | 稳定即可 | 防风暴 | 抗电磁干扰,光纤优先 |
告警要求 | 分级通知 | 快速恢复 | 联动跳闸/风机/消防,安全等级最高 |
运维方式 | 定期巡检 | 产线不停 | 带电作业,不能断电插拔 |
协议偏好 | Modbus TCP/HTTP | TCP/UDP | SNMP(电力监控网络标准协议) |
电力行业监控系统(SCADA/动环监控主机)普遍支持SNMP协议,用于统一采集网络设备、UPS、空调、环境传感器的数据。以太网温湿度记录仪支持SNMP后,可直接接入现有电力监控网络,无需额外网关或协议转换。

版本 | 安全性 | 复杂度 | 电力场景适用性 |
|---|---|---|---|
SNMPv1 | 无认证,明文 | 最低 | 不推荐 |
SNMPv2c | 社区字符串(明文) | 低 | 内网隔离场景可用 |
SNMPv3 | 用户认证+加密(AES/DES) | 中 | 电力监控首选 |
配电柜环境数据涉及电力设施运行状态,建议启用SNMPv3的authPriv模式(认证+加密),防止数据被窃听或篡改。
以太网温湿度记录仪通常提供私有MIB文件(.mib),定义设备的OID树。典型结构:
.iso.org.dod.internet.private.enterprises.{enterpriseID}.{productID}
├── system (1) 系统信息:设备名、位置、描述
├── sensor (2) 传感器数据
│ ├── temperature (1) 温度
│ │ ├── current (1) 当前值(0.1℃精度)
│ │ ├── min (2) 最小值
│ │ ├── max (3) 最大值
│ │ └── avg (4) 平均值
│ ├── humidity (2) 湿度
│ │ ├── current (1)
│ │ ├── min (2)
│ │ ├── max (3)
│ │ └── avg (4)
│ └── dewpoint (3) 露点
├── config (3) 配置参数
│ ├── tempHigh (1) 温度上限阈值
│ ├── tempLow (2) 温度下限阈值
│ ├── humHigh (3) 湿度上限阈值
│ ├── humLow (4) 湿度下限阈值
│ └── pollInterval(5) 采集周期
├── status (4) 设备状态
│ ├── alarmStatus (1) 告警状态位
│ ├── powerStatus (2) 供电状态
│ └── networkStatus(3) 网络状态
└── trap (5) Trap配置
├── trapEnable (1)
├── trapServer (2) Trap目标IP
└── trapPort (3) Trap目标端口# 使用snmpwalk读取设备所有可用数据
snmpwalk -v2c -c public 192.168.200.101 .1.3.6.1.4.1.12345.1
# 读取当前温度
snmpget -v2c -c public 192.168.200.101 .1.3.6.1.4.1.12345.1.2.1.1.0
# 使用SNMPv3(推荐)
snmpget -v3 -u monitor -l authPriv -a SHA -A authpass -x AES -X privpass \
192.168.200.101 .1.3.6.1.4.1.12345.1.2.1.1.0Python批量读取示例:
"""
snmp_poller.py - SNMP批量轮询配电柜温湿度记录仪
"""
from pysnmp.hlapi import *
from pysnmp.entity import config
import asyncio
from dataclasses import dataclass
@dataclass
class SNMPDevice:
ip: str
version: str = "v3"
user: str = "monitor"
auth_key: str = "authpass"
priv_key: str = "privpass"
community: str = "public"
oid_tree: str = ".1.3.6.1.4.1.12345.1"
class SNMPTempHumidPoller:
def __init__(self, devices: list[SNMPDevice], poll_interval=30):
self.devices = devices
self.poll_interval = poll_interval
self.cache = {}
def _build_auth(self, dev: SNMPDevice):
"""构建SNMP认证参数"""
if dev.version == "v3":
return UsmUserData(
dev.user,
dev.auth_key,
dev.priv_key,
authProtocol=config.usmHMACSHAAuthProtocol,
privProtocol=config.usmAesCfb128Protocol
)
else:
return CommunityData(dev.community, mpModel=1 if dev.version == "v2c" else 0)
async def poll_device(self, dev: SNMPDevice):
"""轮询单台设备"""
auth = self._build_auth(dev)
transport = UdpTransportTarget((dev.ip, 161), timeout=2, retries=2)
oids = {
"temperature": ObjectIdentity(dev.oid_tree + ".2.1.1.0"),
"humidity": ObjectIdentity(dev.oid_tree + ".2.2.1.0"),
"dewpoint": ObjectIdentity(dev.oid_tree + ".2.3.1.0"),
"alarm_status": ObjectIdentity(dev.oid_tree + ".4.1.1.0"),
}
results = {}
for name, oid in oids.items():
iterator = getCmd(
SnmpEngine(),
auth,
transport,
ContextData(),
oid
)
errorIndication, errorStatus, errorIndex, varBinds = next(iterator)
if errorIndication:
print(f"{dev.ip} {name}: {errorIndication}")
results[name] = None
elif errorStatus:
print(f"{dev.ip} {name}: {errorStatus.prettyPrint()}")
results[name] = None
else:
for varBind in varBinds:
value = varBind[1]
# 温度值通常×10存储
if name == "temperature":
results[name] = float(value) / 10.0
elif name == "humidity":
results[name] = float(value) / 10.0
elif name == "dewpoint":
results[name] = float(value) / 10.0
else:
results[name] = int(value)
results["_online"] = all(v is not None for v in results.values())
self.cache[dev.ip] = results
return results
async def run(self):
"""主轮询循环"""
while True:
for dev in self.devices:
asyncio.create_task(self.poll_device(dev))
await asyncio.sleep(self.poll_interval)配电柜环境告警应分层级,与电力监控系统告警级别对齐:
级别 | 名称 | 触发条件 | 响应要求 | 联动动作 |
|---|---|---|---|---|
Level 1 | 提示 | 温度>30℃或湿度>60%RH | 记录日志,可忽略 | 无 |
Level 2 | 一般告警 | 温度>35℃或湿度>70%RH | 24h内处理 | 启动柜顶风机 |
Level 3 | 严重告警 | 温度>40℃或湿度>80%RH | 立即处理 | 启动风机+声光报警+通知运维 |
Level 4 | 紧急告警 | 温度>50℃或湿度>90%RH | 立即停电检查 | 联动跳闸+消防联动+短信通知 |
通过SNMP SET命令配置记录仪本地阈值:
"""
snmp_config.py - 通过SNMP配置记录仪告警阈值
"""
from pysnmp.hlapi import *
def set_threshold(dev_ip, oid_base, temp_high, temp_low, hum_high, hum_low):
"""设置温湿度告警阈值"""
auth = UsmUserData("admin", "admin_auth", "admin_priv",
authProtocol=config.usmHMACSHAAuthProtocol,
privProtocol=config.usmAesCfb128Protocol)
transport = UdpTransportTarget((dev_ip, 161), timeout=3, retries=3)
# 阈值×10后写入(设备内部精度0.1)
thresholds = [
(oid_base + ".3.1.1.0", temp_high * 10), # tempHigh
(oid_base + ".3.1.2.0", temp_low * 10), # tempLow
(oid_base + ".3.1.3.0", hum_high * 10), # humHigh
(oid_base + ".3.1.4.0", hum_low * 10), # humLow
]
for oid, value in thresholds:
setCmd(
SnmpEngine(),
auth,
transport,
ContextData(),
ObjectType(ObjectIdentity(oid), Integer(value))
)
print(f"{dev_ip}: Set {oid} = {value}")
# 配置所有配电柜记录仪
devices = [
{"ip": "192.168.200.101", "cabinet": "10kV进线柜A"},
{"ip": "192.168.200.102", "cabinet": "10kV进线柜B"},
{"ip": "192.168.200.103", "cabinet": "变压器柜A"},
{"ip": "192.168.200.104", "cabinet": "变压器柜B"},
{"ip": "192.168.200.105", "cabinet": "低压出线柜A"},
]
oid_base = ".1.3.6.1.4.1.12345.1"
for dev in devices:
set_threshold(dev["ip"], oid_base, temp_high=40, temp_low=5, hum_high=80, hum_low=20)
print(f"Configured {dev['cabinet']} ({dev['ip']})")记录仪在阈值越限时主动发送SNMP Trap,无需轮询:
"""
snmp_trap_receiver.py - 接收并处理记录仪Trap
"""
from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.proto import api
from pysnmp.entity import config as snmp_config
import datetime
class TrapReceiver:
def __init__(self, listen_ip="0.0.0.0", listen_port=162):
self.listen_ip = listen_ip
self.listen_port = listen_port
self.trap_handlers = []
def add_handler(self, handler):
"""添加Trap处理函数"""
self.trap_handlers.append(handler)
def _handle_trap(self, transportDispatcher, transportDomain, data):
"""解析Trap"""
msg = api.v1.decodeMessage(data)
pdu = msg.getPDU()
trap_info = {
"timestamp": datetime.datetime.now().isoformat(),
"source_ip": transportDomain[1][0],
"trap_type": pdu.getComponentByName("generic-trap"),
"specific_trap": pdu.getComponentByName("specific-trap"),
"variables": {}
}
# 解析VarBinds
for oid, value in pdu.getComponentByName("variable-bindings"):
oid_str = str(oid.getComponent())
trap_info["variables"][oid_str] = str(value.getComponent())
# 调用所有处理函数
for handler in self.trap_handlers:
handler(trap_info)
def start(self):
"""启动Trap接收器"""
dispatcher = AsyncoreDispatcher()
dispatcher.registerRecvCbFun(self._handle_trap)
dispatcher.registerTransport(
udp.domainName + (1,),
udp.UdpTransport().openServerMode((self.listen_ip, self.listen_port))
)
print(f"Trap receiver listening on {self.listen_ip}:{self.listen_port}")
dispatcher.runDispatcher()
# 告警处理函数
def alert_handler(trap_info):
"""处理告警Trap"""
source_ip = trap_info["source_ip"]
variables = trap_info["variables"]
# 解析告警信息
temp = variables.get(".1.3.6.1.4.1.12345.1.2.1.1.0", "N/A")
hum = variables.get(".1.3.6.1.4.1.12345.1.2.2.1.0", "N/A")
alarm_status = variables.get(".1.3.6.1.4.1.12345.1.4.1.1.0", "0")
print(f"[{trap_info['timestamp']}] ALERT from {source_ip}")
print(f" Temperature: {temp}°C, Humidity: {hum}%RH")
print(f" Alarm Status: {alarm_status}")
# 根据告警状态执行联动
if int(alarm_status) & 0x01: # 温度高告警
print(" Action: Start exhaust fan, notify maintenance")
if int(alarm_status) & 0x02: # 温度低告警
print(" Action: Start heater")
if int(alarm_status) & 0x04: # 湿度高告警
print(" Action: Start dehumidifier")
if int(alarm_status) & 0x08: # 湿度低告警
print(" Action: Start humidifier")
# 启动Trap接收
receiver = TrapReceiver(listen_port=162)
receiver.add_handler(alert_handler)
receiver.start()"""
alarm_engine.py - 告警规则引擎
"""
from enum import IntEnum
from dataclasses import dataclass
from typing import Callable, List
import time
class AlarmLevel(IntEnum):
INFO = 1
WARNING = 2
CRITICAL = 3
EMERGENCY = 4
@dataclass
class AlarmRule:
name: str
condition: Callable[[dict], bool]
level: AlarmLevel
actions: List[Callable]
debounce_seconds: float = 60.0 # 防抖时间
auto_clear: bool = True
class AlarmEngine:
def __init__(self):
self.rules: List[AlarmRule] = []
self.active_alarms = {} # (rule_name, device_id) -> trigger_time
def add_rule(self, rule: AlarmRule):
self.rules.append(rule)
def evaluate(self, device_id: str, readings: dict):
"""评估所有规则"""
for rule in self.rules:
key = (rule.name, device_id)
triggered = rule.condition(readings)
if triggered:
if key not in self.active_alarms:
self.active_alarms[key] = time.time()
# 检查防抖
if time.time() - self.active_alarms[key] >= rule.debounce_seconds:
self._fire_alarm(rule, device_id, readings)
else:
if key in self.active_alarms and rule.auto_clear:
del self.active_alarms[key]
self._clear_alarm(rule, device_id)
def _fire_alarm(self, rule: AlarmRule, device_id: str, readings: dict):
"""触发告警"""
print(f"[ALARM-{rule.level.name}] {rule.name} on {device_id}")
print(f" Readings: {readings}")
for action in rule.actions:
action(device_id, readings, rule.level)
def _clear_alarm(self, rule: AlarmRule, device_id: str):
"""清除告警"""
print(f"[CLEARED] {rule.name} on {device_id}")
# 联动动作定义
def start_exhaust_fan(device_id, readings, level):
print(f" -> Starting exhaust fan for {device_id}")
def start_dehumidifier(device_id, readings, level):
print(f" -> Starting dehumidifier for {device_id}")
def send_sms_alert(device_id, readings, level):
print(f" -> Sending SMS alert for {device_id}")
def trigger_power_off(device_id, readings, level):
print(f" -> TRIGGERING POWER OFF for {device_id}")
# 配置告警规则
engine = AlarmEngine()
# 温度高告警
engine.add_rule(AlarmRule(
name="HighTemperature",
condition=lambda r: r.get("temperature", 0) > 40,
level=AlarmLevel.CRITICAL,
actions=[start_exhaust_fan, send_sms_alert],
debounce_seconds=30
))
# 湿度高告警
engine.add_rule(AlarmRule(
name="HighHumidity",
condition=lambda r: r.get("humidity", 0) > 80,
level=AlarmLevel.WARNING,
actions=[start_dehumidifier],
debounce_seconds=60
))
# 紧急温度告警
engine.add_rule(AlarmRule(
name="EmergencyTemperature",
condition=lambda r: r.get("temperature", 0) > 50,
level=AlarmLevel.EMERGENCY,
actions=[trigger_power_off, send_sms_alert],
debounce_seconds=10
))电力中心配电柜监测中,SNMP协议读取以太网温湿度记录仪并配置告警规则,是电力监控系统集成的关键环节。通过SNMPv3保障数据安全,合理设计告警层级和联动规则,实现从数据采集到告警响应的完整闭环。配置本地阈值确保设备独立告警能力,同时接收SNMP Trap实现实时告警推送。告警规则引擎支持灵活配置和防抖处理,避免误报。配电柜环境恶劣,设备选型和安装需考虑电磁兼容性和空间约束,确保长期稳定运行。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。