2. 能源数据采集架构设计
能源管理系统的数据质量,从第一米线缆、第一次寄存器读取就已经决定了。很多项目后期出现“能耗曲线跳变”“峰谷电量对不上”“水表读数回退”等问题,根源往往不在上层算法,而在采集架构与协议选型阶段。本节围绕电表、水表、气表到PLC的完整采集链路,讲清分层结构、协议取舍,以及源码中驱动层如何落地。
一、采集链路的四层结构
一个可维护的能源采集架构,通常分为四层:现场设备层(电表、水表、气表、PLC)、采集接入层(网关/采集器/边缘程序)、协议驱动层(Modbus、IEC 104、OPC UA 等驱动实例)、数据服务层(点位映射、质量码、时序入库)。现场设备层负责产生原始计量数据;采集接入层负责物理连接与轮询调度;协议驱动层负责把字节流翻译成带工程单位的点位值;数据服务层负责统一时标、质量码与存储。
关键设计原则是:协议驱动层与业务逻辑解耦。驱动只负责“读到一个值”,不负责判断这个值是否合理、属于哪个支路、要不要报警。这样更换协议或新增表计时,只需新增驱动实例和点位映射,不必改动上层业务。
二、协议选型:Modbus、IEC 104、OPC UA 的适用边界
三种协议不是替代关系,而是各有适用场景。选型时先看设备侧支持什么,再看数据实时性、点位数和网络条件。
| 对比项 | Modbus RTU/TCP | IEC 60870-5-104 | OPC UA |
|---|---|---|---|
| 典型设备 | 电表、水表、气表、小型PLC | 电力保护装置、RTU、变电站 | 中大型PLC、DCS、SCADA服务器 |
| 数据模型 | 寄存器地址,无自描述 | 信息对象地址(IOA)+ 类型标识 | 地址空间 + 节点ID,自描述 |
| 实时性 | 轮询,秒级 | 变化上送,百毫秒级 | 订阅发布,百毫秒级 |
| 点位数 | 适合数百点以内 | 适合数千点 | 适合数万点 |
| 配置复杂度 | 低,需手工映射 | 中,需点表与总召 | 高,需建模与安全配置 |
实际项目中常见的组合是:电表、水表、气表走 Modbus RTU 经串口服务器汇聚;电力回路保护装置走 IEC 104;主控 PLC 走 OPC UA 或 S7 协议。采集程序内部为每种协议实现独立驱动,统一向上输出 TagValue 结构。
三、源码中的驱动实现
驱动层的核心接口应保持极简。以下是一个可扩展的驱动抽象(以 Python 风格示意,实际项目可用 C#/Java 实现):
class ProtocolDriver:
def connect(self) -> bool: ...
def read(self, points: list[Point]) -> list[TagValue]: ...
def disconnect(self) -> None: ...
class TagValue:
tag: str # 统一点位名,如 "METER_A_EP"
value: float # 工程值
quality: str # "Good" / "Bad" / "Uncertain"
timestamp: float # UTC 秒
unit: str # "kWh" / "m3" / "kPa"
Modbus 驱动的关键实现细节:读取保持寄存器使用功能码 03,读取输入寄存器使用 04。对于 32 位电量,需明确字序。例如某电表有功电能寄存器 0x0000-0x0001,高字在前,则:
raw = client.read_holding_registers(0x0000, 2)
value = (raw[0] << 16) | raw[1] # 高字在前
kwh = value * 0.01 # 变比 0.01 kWh/字
若字序相反,则交换 raw[0] 与 raw[1]。这个细节必须在点表中标注,否则会出现“电量突然跳变 65536 倍”的典型故障。
IEC 104 驱动需要处理总召(C_IC_NA_1)与变化上送。启动后先发总召,等待激活确认与激活结束,再进入监听。遥测值通常为归一化值或标度化值,需按点表系数还原:
# 标度化值 SVA,16位有符号,系数 0.01
raw_sva = frame.value
engineering = raw_sva * 0.01
OPC UA 驱动推荐使用订阅模式而非轮询。创建 Subscription,设置发布间隔 1000ms,对每个需要采集的 NodeId 建立 MonitoredItem,并设置死区过滤,避免微小波动频繁上报:
sub = client.create_subscription(1000, handler)
for node_id in node_list:
sub.subscribe_data_change(node_id, deadband=0.5)
四、点位映射与质量码
无论哪种协议,最终都要落到统一点位表。点位表至少包含:Tag 名、协议类型、连接参数、设备地址/IOA/NodeId、寄存器/对象地址、数据类型、字序、变比、工程单位、采集周期、死区。质量码用于标记数据可信度:通信成功且值在合理范围为 Good;超时或校验失败为 Bad;值超出量程但通信正常为 Uncertain。上层能耗计算只使用 Good 数据,Bad 数据进入补采队列。
采集架构设计完成后,下一步才是数据入库与能耗计算。但请记住:驱动层的稳定性、点位映射的准确性、质量码的完整性,决定了整个能源管理系统能走多远。在源码实现中,把驱动做成可插拔组件,把点位表做成配置驱动,是后续扩展和排障成本最低的做法。