Skip to content

IEC 104 驱动

dc3-driver-iec104 把 IEC 60870-5-104 远动设备接入 IoT DC3:它作为 104 客户端连到变电站/调度自动化设备,按** 信息对象地址(IOA)**采集遥测遥信,并支持下发遥控命令。读完本页你能看懂 104 的寻址方式、给设备和位号填对协议属性,并清楚这个驱动当前的实现边界。

你在这里:现场设备的"电力远动 / SCADA"接入侧。要理解工业协议为什么各家私有、IEC 104 在网络层处于什么位置,先读 工业总线与协议

协议背景

IEC 60870-5-104(简称 IEC 104)是电力系统调度自动化领域的国际标准远动协议,把 IEC 60870-5-101 的应用层架在标准 TCP/IP 之上。它广泛用于变电站综合自动化、配电终端(DTU/FTU)、远动机(RTU)与主站之间的**"四遥"通信** ——遥测(telemetry)、遥信(telesignaling)、遥控(telecontrol)、遥调(telesetpoint)。在电力调度领域,它和楼宇自控的 BACnet、公用事业计量的 DLMS/COSEM 一样,属于"按行业需求立标准"的协议阵营。

IEC 104 与 Modbus 这类协议的寻址模型不同,它用两个概念定位与解释一个数据点:

  • 信息对象地址 IOA(Information Object Address) 唯一定位远动设备里的一个数据点(一个遥测量、一个遥信状态)。
  • ASDU 类型 描述这条报文的数据语义,例如 M_ME_NC_1(短浮点遥测)、M_SP_NA_1(单点遥信)——同一个 IOA 配不同的 ASDU 类型,解出来的数据含义就不同。

104 报文里没有字段分隔符,公共地址、传送原因、信息对象地址各占几个字节,全靠主站与远动设备在工程组态时约定(典型 2/2/3 )。这套"靠字节宽度切分 + 靠 IOA 定位"的模型,使得字节长度配置必须与对端一字不差。

在物联网四层架构里,IEC 104 属于网络层的工业有线侧:它解决"现场远动设备如何在 TCP/IP 上把一个遥测遥信送出去、把一个遥控接进来"的问题,位于感知层(互感器/变送器)之上、平台层(IoT DC3 数据汇聚)之下。下面这张图给出 104 客户端在一次采集里的位置:

网络层 (IEC 60870-5-104)按 IOA + asduType 读/写采集值远动设备 RTUIOA 16385 = 220.5TCP Socket端口 2404ASDU 报文M_ME_NC_1 短浮点遥测dc3-driver-iec104code=Iec104DriverIoT DC3位号值 PointValue

驱动作为客户端(client)主动连一个 104 服务端,按位号配置的 ioa 定位读哪个点、按 asduType 解释字节,统一为 位号值 上送平台。

属性配置

IEC 104 的接入参数分两层:驱动属性(driver-attribute) 描述"连哪台远动设备、用什么端口、各字段几个字节" ,填在 设备 上;位号属性(point-attribute) 描述"读哪个 IOA、按什么 ASDU 类型解释" ,填在每个 位号 上。可写位号再加一项命令属性(command-attribute)。这些属性的默认值都来自驱动的 application.yml,三层来历见 属性与配置

驱动属性(设备级 driver-attribute

接入一台 IEC 104 设备时,先在设备上指明它的网络位置与报文字段约定。host / port 决定 TCP 连到哪里;asduAddress (公共地址,又称站地址)区分同一连接下的多个逻辑站;cotLength / caLength / ioaLength 是 104 报文中传送原因、公共地址、信息对象地址三个字段各占的字节宽度;connectTimeout 限制建连等待时长。

属性code类型默认值说明
HosthostSTRINGlocalhost104 服务端 IP(远动设备地址)
PortportINT2404104 TCP 端口(标准 2404)
ASDU AddressasduAddressINT1公共地址(站地址),区分逻辑站
COT LengthcotLengthINT2传送原因字段字节数
CA LengthcaLengthINT2公共地址字段字节数
IOA LengthioaLengthINT3信息对象地址字段字节数
Connect TimeoutconnectTimeoutINT10000连接超时(毫秒)

COT/CA/IOA 长度是站内约定,必须与对端一致

cotLength / caLength / ioaLength 是 104 报文里各字段的字节宽度,由主站与远动设备在工程组态时约定(典型 2/2/3 )。这三项必须与对端配置完全一致,否则报文按错误的字节边界切分,地址会读到错位的字节上。asduAddress(公共地址)用于在同一 host:port 连接下区分多个逻辑站。

host / port / asduAddress 为必填校验项

validate()hostportasduAddress 列为必填项;缺任一项会在校验时报 ERROR,设备配置不通过。其余字节长度项有默认值,缺省即用上表默认。

位号属性(point-attribute

每个采集位号都要指明读哪个信息对象、以及该点用什么 ASDU 类型解释——驱动不会向设备探测类型,完全按你填的 asduType 理解字节。

属性code类型默认值说明
IOAioaINT0信息对象地址,唯一定位一个数据点
ASDU TypeasduTypeSTRINGM_ME_NC_1ASDU 类型标识,决定数据语义

IOA 定位"读哪个点",ASDU 类型决定数据语义

ioa 是信息对象地址,唯一标识远动设备里的一个数据点。asduType 标明该点的数据类型,默认 M_ME_NC_1(短浮点遥测);遥信常用 M_SP_NA_1(单点遥信)。位号自身的数据类型(PointpointTypeFlag)应与 ASDU 类型携带的实际数据对得上。validatePoint()ioa 列为必填项。

命令属性(command-attribute

可写位号(下发遥控)在写命令上额外配置下发模板。

属性code类型默认值说明
Send CommandsendCommandSTRING${value}下发命令模板,用命令参数渲染

sendCommand 是模板,用命令参数占位

sendCommand${参数名} 占位,驱动 execute() 时把命令参数(如 ${value})逐个替换进去,默认 ${value} 即把命令值直接作为遥控值。注意:execute() 当前只完成模板渲染并返回,把渲染结果放进返回 Map 的 sendCommand 键,并未真正把遥控帧下发到 104 服务端(见下方实现状态)。

采集与健康

  • 采集周期:默认 read cron 0/30 * * * * ?(每 30 秒读一轮)。
  • 自定义调度schedule.custom 在 yml 中启用(cron 0/5 * * * * ?),但当前 schedule() 方法体为空,不执行任何自定义逻辑。
  • 健康/在线:设备健康检查默认 cron 0/15 * * * * ?,租约超时 45 秒 ——在线状态机制见 设备

故障排查

IEC 104 接入失败大多落在"连不上"和"报文解析错位" 两类。下面按由表及里的顺序排查。需要注意的是:本驱动的协议读写当前是骨架(见下一节),下列排查项面向接入参数与网络可达性,而非已能采到值的运行态。

端口或防火墙:2404 不通

104 标准走 TCP 2404,与 Modbus 的 502、EtherNet/IP 的 44818、DLMS 的 4059 都不同,别张冠李戴。先在驱动主机上确认 host:2404 可达(telnet <host> 2404nc -vz <host> 2404)。常见原因:远动设备未启用 104 服务、网段不通、防火墙拦了 2404。建连超时由 connectTimeout(默认 10000 毫秒)控制。

COT/CA/IOA 长度对不上 = 整条报文解析错位

104 报文没有字段分隔符,全靠约定的字节宽度切分。若 cotLength / caLength / ioaLength 与对端不一致,地址会被读到错误的字节上,导致采到的不是目标点甚至解析失败。接入前务必向运维确认对端的 2/2/3 (或其他)组态,三项一字不差地照填。

公共地址(asduAddress)选错连到错的逻辑站

一台远动机下可能挂多个逻辑站,用 asduAddress(公共地址)区分。当多个设备共用相同 host:port 时,由各自的 asduAddress 决定连/读哪个站。若 asduAddress 填错,会对端返回的总召唤里取不到预期的点。接入前向运维确认每个逻辑站的公共地址。

ASDU 类型与点的实际类型不符

驱动完全按位号填的 asduType 理解字节。把一个短浮点遥测点(M_ME_NC_1)配成单点遥信(M_SP_NA_1),解出来的值会失去意义。接入前逐个确认每个 IOA 对应的 ASDU 类型,并让位号的 pointTypeFlag 与之匹配(遥测多为 FLOAT,遥信多为 BOOLEAN)。

设备在线态不等于已采到值

设备在线/离线由租约机制(默认 45 秒 超时)维护,反映的是驱动与平台之间的心跳,而非 104 链路上真正读到了数据。判断是否采到值,应以 位号值 是否更新为准。当前驱动协议读写尚未实现(见下一节),不会有位号值更新。

在 IoT DC3 中如何落地

  • dc3.driver.codeIec104Driver(稳定路由标识,注册与消息路由都以它为准,不要随意改)。驱动名 IEC 104 Driver,类型 DRIVER_CLIENT(驱动主动连远动设备)。
  • 读能力read() 未实现——直接抛 ReadPointException 快速失败(让 SDK 记录失败并退避,而非回显缓存值或伪造成功)。
  • 写能力write() 未实现——直接抛 WritePointException 快速失败。
  • 遥控命令execute() 部分实现——只完成 sendCommand 模板的参数渲染并返回渲染结果,尚未把遥控帧真正下发到 104 服务端。
  • 订阅/上报:不涉及。本驱动按客户端模型设计,由采集周期主动读,不监听设备主动上报。

驱动能力矩阵 对齐:IEC 104 在矩阵中读/写/订阅均标记为 ,备注"电力 SCADA,骨架待补"。

当前为骨架实现(Work in progress)

本驱动是协议模板骨架:属性表、采集周期、IOA/ASDU 寻址语义已就位且可照填,但 104 协议层 I/O 尚未实现

  • read() / write() 直接抛"未实现"异常快速失败,不做任何 IOA 读取或遥控下发;
  • execute() 仅渲染 sendCommand 模板并返回,不真正发帧;
  • initial()schedule()event() 方法体为空,无自定义初始化/调度/元数据事件逻辑;
  • 已实现的只有配置校验(validate() / validatePoint())与命令模板渲染。

请将它作为接入 104 设备的起点模板,而非生产可用驱动。最终行为以 Iec104DriverCustomServiceImplread() / write() / initial() 源码为准。

把一台远动设备接进来的最小路径(用于验证配置流程,非生产采集):

  1. IEC 104 Driver 创建 设备,driver 属性填 host=192.168.1.30port=2404asduAddress=1cotLength / caLength / ioaLength 用默认 2/2/3,与对端约定一致即可)。
  2. 给设备绑定的 模板 加一个遥测 位号pointTypeFlag=FLOATREAD_ONLY),point 属性填 ioa=16385asduType=M_ME_NC_1
  3. 启动驱动观察连接与校验日志。协议层补全前,30 秒一轮的读会快速失败(异常退避);补全后即可在 位号值 看到采集值。

完整的接入操作流程见 设备接入

延伸阅读

基于 AGPL-3.0 协议发布