一、背景
公司有个项目,是要按照IEC104协议采集电力数据。考虑到要带没有开发基础的同学,所以写这篇文章,尽量详细一点。代码仅仅是简单学习之用,不足之处请见谅。
二、名词
1. IEC104
IEC104(IEC 60870-5-104)是电力系统主流远动通信协议,基于 TCP/IP(默认端口 2404),由 IEC 制定,是 IEC101 的网络扩展版。它采用主从架构,支持遥测、遥信、遥控、遥调等核心功能,通过 I/S/U 帧机制保障可靠传输与实时交互。广泛用于电网调度、变电站自动化与工业电力监控,具备长连接、毫秒级时标、数据主动上送等特点,是电力 SCADA 系统的标准通信方案。
2.maven
Maven 是 Java 生态主流的项目构建与依赖管理工具,由 Apache 基金会开发。它通过统一的pom.xml配置文件,自动管理第三方库(jar 包)的下载、版本控制与依赖传递,省去手动导包的繁琐。Maven 提供标准化项目结构、编译、测试、打包、发布等一站式构建生命周期,支持多模块项目管理(一般口语说的父子工程)、私服仓库与插件扩展,极大提升 Java 项目开发效率与协作规范性,是企业级 Java、SpringBoot 开发必备工具。背后我们还创建了依赖的私库(nexus),私库没有的才到互联网库下载,这里就过多描述了。
3.j60870
j60870 是纯 Java 实现的IEC104(IEC 60870-5-104)协议客户端 / 服务端开发库,由 OpenMUC 开源社区维护,适配 TCP/IP(默认 2404 端口)。支持主站(客户端)、从站(服务端)双向通信,完整实现遥测、遥信、遥控、遥调、总召唤、对时等核心功能。提供 Maven 依赖引入,API 简洁,可快速集成到 SpringBoot 等 Java 项目,广泛用于电网调度、变电站自动化、SCADA 系统等电力物联网场景。maven的依赖配置如下:
<dependency> <groupId>org.openmuc</groupId> <artifactId>j60870</artifactId> <version>1.7.2</version> </dependency>4.oceanbase
OceanBase 是蚂蚁集团完全自研的国产原生分布式数据库,2010 年起步于支付宝核心,历经十余年 “双 11” 高并发验证。采用一体化分布式架构,兼顾分布式扩展性与集中式性能,一套引擎同时支撑 OLTP/OLAP 混合负载(HTAP)。金融级高可用,首创 “三地五中心” 容灾,满足 RPO=0、RTO<8s;高度兼容 MySQL/Oracle,迁移成本低;支持在线水平扩展,单集群可达数千节点、PB 级数据;基于 LSM-Tree 高压缩引擎,存储成本显著降低,广泛用于金融、政务、运营商、工业物联网等核心场景。我们用的是公司技术部门在内网搭建的OB。
5.IEC104主站
主站(Client,主动读数据),就是你写的代码运行的机器。
6.IEC104从站
从站(Server,设备端,端口2404),就是你程序监听的地址,现实中,这个地址可以是一个汇聚的机器,也可以是一个网关设备。
7.IEC104总召唤
主站发总召唤(C_IC_NA_1),请求全量数据。从站回:总召唤确认 → 上送所有遥信 / 遥测 → 总召唤结束。简单说,就你的主程序向电表要一次全量数据。
8.IEC104数据类型
遥信(DI):开关状态(单点 / 双点)。
遥测(AI):电压、电流、功率等模拟量(浮点数 / 归一化值)。
电度(PI):累计电能。
控制(DO/AO):遥控、遥调(写操作)
三、上手
1.gitcode创建项目
(1)创建项目
(2)输入新建项目相关的信息
(3).gitignore文件
不希望提交一堆代码无关的文件信息到代码库,按照eclipse的常见文件,编写了忽略的文件及文件夹。建议的内容(可以在gitcode中打开文件点击编辑后提交)
target/ *.classpath *.project .settings/ logs/(4)复制你项目的git地址
(5)在eclipse中打开GitRepositories创建并克隆项目
这里应该有个默认的向导,没有就自己去安装eclipse的插件。
(6)导入到eclipse作为工程
(7)把工程转化为maven项目
因为开始我们在代码仓库创建的就是一个空壳,并没有maven的pom等文件,eclipse并不知道是一个maven工程。
(8)输入maven工程的关键信息
主要就是GroupId(我一般认为是你团队或者个人的标识),ArtifactId(一般就是工程的名称)。
(9)给主项目的pom文件加入parent和properties
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.18</version> <relativePath /> </parent> <groupId>cn.potato</groupId> <artifactId>iec104-master</artifactId> <version>1.0.0</version> <packaging>pom</packaging> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> </project>2.创建子工程
(1)子工程规划
我问AI:
我准备用maven的母子工程来做,我的想法就是有多个从站,我作为主站,读取数据,然后存储到OB数据库。当然未来我可能存储到不同的地方。基于这个考虑,你觉得我应该创建哪几个子模块好一些?我的主站名称是iec104-master,子模块参考这个命名方式
AI的核心回答:
iec104-master (父工程)
├── iec104-master-common # 公共工具、常量、模型
├── iec104-master-core # IEC104 协议核心:连接、采集、解析
├── iec104-master-storage # 存储抽象层 + 各种存储实现(OB/MySQL...)
├── iec104-master-service # 业务逻辑:调度、任务、多从站管理
└── iec104-master-boot # 启动入口、配置、SpringBoot 主程序
(2)依次创建5个子工程
打开主pom文件,点击modules中的Create
过程简单,勾选简单创建,输入模块名称就好了。
3.代码实现
(1)AI生成代码
我问AI:
我用的eclipse,配置文件使用application.properties 你按照刚刚沟通的工程结构,重新帮我生成相关的代码吧
AI回答的内容,我这里就不一一罗列了。问题还是很多的,主要是我也是第一次做IEC104数据采集,很不熟悉,给AI提出的要求太少。
4.AI代码生成过程中的一些问题
(1)代码编译错误
主要的问题应该还是j60870版本不同,出现了一些编译错误。在eclipse中,按住ctrl,鼠标点击对应的对象,包括第三方包中的对象,一般都可以看到对象的源代码。直接复制给AI,再复制编译错误行的代码,告诉AI编译错误,一般都能找到具体替代的方法。
(2)配置文件中iec104.slave.list读取失败
一个是utf-8的问题,我修改了这个文件的字符集,也修改了eclipse的默认字符集。具体修改方法自己问AI,这里就不多说了。
还有个怪问题是编译问题,暂时没有解决,应该是我eclipse插件安装多了的一些问题。现象是iec104-master-boot/target目录classes文件夹下面没有iec104-master-boot/src/main/resources下面的application.properties文件。通过mvn命令是正常的,在eclipse下面点击子项目iec104-master-boot,选择maven的update project是正常的,但是点击父工程iec104-master,选择maven的update project就不能把application.properties文件编译到对应的目录下。
(3)IEC104总召唤报文构造错误
因为没有详细去读和理解协议的文件,直接用的第三方的包(j60870),所以AI生成的代码的时候,没有考虑清楚。导致我运行的时候,刚连接就断开了。
// ============================================== // 正确总召唤(带 20 询问限定词,104 标准!) // ============================================== ASdu asdu = new ASdu( ASduType.C_IC_NA_1, false, CauseOfTransmission.ACTIVATION, false, false, 0, commonAddr, new InformationObject(0, new IeQualifierOfInterrogation(20)) // 关键! ); connection.send(asdu);(4)多线程
我们作为主站,跟从站之间,一般都是1个从站就是1个连接(实际中可能一个从站有多个,IP:端口:主地址,可能有多个主地址)。我写代码时,要给AI强调,我们是一个地址就产生1个连接,需要考虑多线程,不要做成单线程了。
(5)断网重连
我默认是没有要求断网重连的,实际生产环境必须具备的,后面我跟AI对话让她添加了断网重连的功能。实际中断网重连还有一套规则,这里就简单的5S一次了。
(6)一部分从站仅支持1个连接的问题
因为特殊原因,我们网络架构使用到了happynet这个工具。我这边出现了1个现象,就是开发的时候,我们2个同事同时运行程序,有的从站可以,有的从站只能同时只有1个人连接。原因还没有找到,先这样吧!
四、最终代码库
1.公开代码库主页
iec104-master_demo
2.公开代码库的git地址,可直接克隆代码库
https://gitcode.com/qq_37372909/iec104-master_demo.git
五、总结
整个过程耗时4个小时左右,主要还是得益于跟AI合作,和同事的支持。我们要继续坚持体系化的去使用AI,而不是上来就让AI写代码。最好是先了解业务知识,业界一般的架构。写代码是最简单的,核心还是业务知识与设计。
本次代码仅供参考,实际应用中很多需要考虑的,后续逐步完善。