Sfoglia il codice sorgente

中广核104日志修改

wzl 4 mesi fa
parent
commit
3798a9b595

+ 110 - 0
README.MD

@@ -0,0 +1,110 @@
+# 能源在线数据服务系统 - 项目说明书
+
+## 1. 项目概述
+本系统是一个基于Java Spring Boot框架开发的能源数据采集与处理服务,主要实现IEC 104规约通信协议的数据接收、处理与存储功能。系统采用定时任务机制进行数据采集与文件存储,适用于能源监控领域的实时数据处理场景。
+
+## 2. 技术架构
+### 2.1 技术栈
+- **开发语言**:Java 8
+- **构建工具**:Maven
+- **核心框架**:Spring Boot
+- **通信协议**:IEC 104
+- **调度机制**:Spring Scheduled
+- **数据存储**:文件系统(CSV格式)
+
+### 2.2 项目结构
+```
+src/main/java/com/energy/online/data/
+├── OnlineDataMain.java       // 应用程序入口
+├── common/                   // 公共数据存储
+├── config/                   // 配置类
+├── crontab/                  // 定时任务
+├── dto/                      // 数据传输对象
+├── handle/                   // 协议数据处理
+└── utils/                    // 工具类
+```
+
+## 3. 核心功能模块
+
+### 3.1 主程序入口
+<mcsymbol name="OnlineDataMain" filename="OnlineDataMain.java" path="d:\project\energy-online-data-service\src\main\java\com\energy\online\data\OnlineDataMain.java" startline="2" type="class"></mcsymbol>作为系统入口点,负责:
+- 初始化Spring Boot应用
+- 创建IEC 104主站连接
+- 启动时执行设备连接
+- 发送总召唤命令获取数据
+
+关键代码片段:
+```java:/d:\project\energy-online-data-service\src\main\java\com\energy\online\data\OnlineDataMain.java
+@PostConstruct
+public void init() {
+    Line line = baseConfig.getLine();
+    runDeviceConnection(line);
+}
+
+private void runDeviceConnection(Line line) {
+    try {
+        master = new Iec104MasterBuilder(line.getIp(), line.getPort());
+        master.createByUnBlock();
+        // ... 发送总召唤命令 ...
+    } catch (Exception e) {
+        e.printStackTrace();
+    }
+}
+```
+
+### 3.2 配置管理
+<mcsymbol name="AppConfig" filename="AppConfig.java" path="d:\project\energy-online-data-service\src\main\java\com\energy\online\data\config\AppConfig.java" startline="2" type="class"></mcsymbol>负责系统配置:
+- 加载IEC 104协议配置参数
+- 创建线程池用于异步任务处理
+- 提供配置属性绑定
+
+
+### 3.3 定时任务模块
+<mcsymbol name="TimeSaveScheduled" filename="TimeSaveScheduled.java" path="d:\project\energy-online-data-service\src\main\java\com\energy\online\data\crontab\TimeSaveScheduled.java" startline="2" type="class"></mcsymbol>提供多种定时任务:
+- 数据采集(配置在${my.scheduled.cron})
+- 每2分钟发送总召唤命令
+- 每10分钟将数据保存为CSV文件
+- 每2分钟打印数据量日志
+
+## 4. 配置说明
+系统配置通过以下方式实现:
+1. 创建src/main/resources/application.properties文件
+2. 配置IEC 104协议参数:
+```properties
+# IEC 104协议配置
+iec104.line.ip=目标IP地址
+iec104.line.port=端口号
+iec104.line.coa=公共地址
+iec104.saveDir=数据保存目录
+
+# 定时任务配置
+my.scheduled.cron=0/1 * * * * *
+```
+
+## 5. 部署与运行
+### 5.1 环境要求
+- JDK 8
+- Maven 3.6+
+
+### 5.2 构建步骤
+```bash
+# 编译打包
+mvn clean package
+
+# 运行应用
+java -jar target/energy-online-data-service.jar
+```
+
+## 6. 数据流程
+1. 系统启动后通过<mcsymbol name="OnlineDataMain.init" filename="OnlineDataMain.java" path="d:\project\energy-online-data-service\src\main\java\com\energy\online\data\OnlineDataMain.java" startline="18" type="function"></mcsymbol>建立IEC 104连接
+2. 通过定时任务发送总召唤命令请求数据
+3. <mcsymbol name="HandleYX151.handleAndAnswer" filename="HandleYX151.java" path="d:\project\energy-online-data-service\src\main\java\com\energy\online\data\handle\HandleYX151.java" startline="23" type="function"></mcsymbol>处理接收到的数据
+4. 数据临时存储在<mcsymbol name="CommonData" filename="CommonData.java" path="d:\project\energy-online-data-service\src\main\java\com\energy\online\data\common\CommonData.java" startline="1" type="class"></mcsymbol>
+5. <mcsymbol name="TimeSaveScheduled.saveToFile" filename="TimeSaveScheduled.java" path="d:\project\energy-online-data-service\src\main\java\com\energy\online\data\crontab\TimeSaveScheduled.java" startline="45" type="function"></mcsymbol>定期将数据写入CSV文件
+
+## 7. 注意事项
+- 确保目标设备的IP、端口和公共地址配置正确
+- 数据保存目录需要有写入权限
+- 根据实际需求调整定时任务的执行频率
+- 系统依赖IEC 104协议库,请确保相关依赖包正确引入
+        

+ 74 - 0
iec104_zf_1.sys

@@ -0,0 +1,74 @@
+//	config_func_alias	config_func_val		desc
+//	变量别名		变量值(十进制)		描述
+	NEED_FIRST_CALL         1       是否需要总招
+	PLAN_VALUE_COEF         1       计划值的系数,最终的计划值是通过将报文中的原码值乘以此系数得到的
+	PROTOCOL_BYTE_ORDER		0		规约报文的字节顺序:0,低字节在前;1,高字节在前
+	FRONT_MAIN_BACK			0		表示主前置进行正常收发而备前置只进行通道报文测试
+
+	LINK_ENABLE_FLAG		1		等待连接超时是否向主站发停止帧
+	TEST_ACK_FLAG			0		没有初始化时(进程重启)是否响应主站发出的测试帧:0,响应;1:不响应
+	
+	LINK_TIME_OUT			20		等待建立连接超时时间(秒)           
+	TEST_TIME_OUT			10		发送或测试APDU的超时时间(秒〕
+	COMM_TIME_OUT			50		通讯中断的时间间隔(秒〕
+
+	TIME_ENABLE_FLAG		1		是否需要接收主站对时
+	TIME_UTC_FLAG			0   	对时是否使用UTC时间: 0 使用本地时间  1 使用UTC时间(多时区时使用)
+	DIN_ENABLE_FLAG			1		是否需要遥信
+	AIN_ENABLE_FLAG			1		是否需要遥测
+	PIN_ENABLE_FLAG			1		是否需要遥脉
+	SOE_ENABLE_FLAG			1		是否需要SOE
+	SOEEX_ENABLE_FLAG		1		是否需要SOE EX
+	COM_ENABLE_FLAG			1		是否需要变化遥测
+	COS_ENABLE_FLAG			1		是否需要变化遥信
+	SOM_ENABLE_FLAG			0		是否需要SOM
+	CTL_ENABLE_FLAG			1		是否需要遥控
+	SEQ_ENABLE_FLAG			0		是否需要程序化控制
+	SET_ENABLE_FLAG			0		是否需要设定值
+	PERIOD_ENABLE_FLAG		0		是否需要周期上送遥测
+	PERIOD_AIN_TM_OUT		60		遥测上送周期,在PERIOD_ENABLE_FLAG为1的时候生效,单位为秒
+	
+	CURVE_ENABLE_FLAG		0		是否需要计划曲线
+	ELANGUAGE_FLAG			0		是否需要E语言传输文件
+	OTHER_NODE_FLAG			0		E语言传输文件时是否需要指定地址
+	OTHER_NODE_ADDR			3		E语言传输文件时指定地址
+	ALLOCATE_CURVE_FLAG		0		是否需要分配曲线
+	CURVE_NUM			1		计划曲线条数
+	DAY_CURVE_POINT_NUM		289		日计划曲线点数
+
+	MSG_HEAD_LEN			2		IEC104报文头长度
+	ASDU_ADDR_LEN			2		ASDU公共地址字结数(1,2)
+	OBJ_ADDR_LEN			3		信息对象地址字结数(1,2,3)
+	TRAN_CAUSE_LEN			2		传送原因字结数(1,2)
+	
+	FIRST_ENABLE			1		是否送一次值:1,是;0:否
+	ASDU_COMMON_ADDR		1		ASDU低位公共地址
+	ASDU_ADDR_HIGH          0       ASDU高位字节
+	K_VALUE				12		K值
+	W_VALUE				8		W值
+	K_ENABLE			0		是否判断K值
+	YC_QDS				1		遥测是否带品质字节:1,带;0,不带
+
+	CTRL_TYPE			0		遥控命令类型:0,单点;1,双点		
+	PIN_TIME_TYPE			0		电度帧类别:0,不带时标;1,带时标(7字节长时标)
+	YC_ASDU_TYPE			13		遥测ASDU类型:9,归一化值;11,标度化值;13,短浮点数;21,归一化值,无品质描述
+	YX_ASDU_TYPE			1		遥信ASDU类型:1,标准类型单点  3 标准类型双点;151 ENVISION定义
+	YC_CAUSE_TYPE     3       遥测上送原因:3,突变上送;1,周期循环上送;
+	DIN_MAX_NUM			127		单帧遥信最大个数
+	AIN_MAX_NUM1			120		单帧遥测最大个数(ASDU21)
+	AIN_MAX_NUM2			80		单帧遥测最大个数(ASDU9,ASDU11)
+	AIN_MAX_NUM3			48		单帧遥测最大个数(ASDU13)
+	PIN_MAX_NUM1			48		单帧电度最大个数(无时标时〕
+	PIN_MAX_NUM2			30		单帧电度最大个数(短时标时〕
+	PIN_MAX_NUM3			20		单帧电度最大个数(长时标时〕
+
+	DIN_ADDR_START			1		DIN起始地址(默认0x0001)
+	AIN_ADDR_START			16385		AIN起始地址(默认0x4001)
+	CTL_ADDR_START			24577		CTL起始地址(默认0x6001)
+	PIN_ADDR_START			25601		PIN起始地址(默认0x6401)
+	SEQ_ADDR_START			24577		SEQ起始地址(默认0x6001)
+	SET_ADDR_START			25089		设定值起始地址(默认0x6201)
+	CURVE_ADDR_START		28673		计划曲线起始地址(默认0x7001)
+	IEC104_START_YEAR		2000		报文年的起始时间
+	
+	WRITE_AODO_LOG_FILE_ENABLE		0		是否将AODO写入log文件

+ 9 - 5
src/main/java/com/energy/online/data/crontab/TimeSaveScheduled.java

@@ -35,11 +35,11 @@ public class TimeSaveScheduled {
         CommonData.addList();
     }
 
-    @Scheduled(cron = "0 0/2 * * * *")
-    public void sendTotal() throws Exception {
-        log.info(baseConfig.getLine().getPort() + "发送总召");
-        SendDataFrameHelper.sendTotalSummonFrame(OnlineDataMain.master.getFuture().channel(), baseConfig.getLine().getCoa(), 6, OnlineDataMain.master.getLog());
-    }
+    // @Scheduled(cron = "0 0/2 * * * *")
+    // public void sendTotal() throws Exception {
+    //     log.info(baseConfig.getLine().getPort() + "发送总召");
+    //     SendDataFrameHelper.sendTotalSummonFrame(OnlineDataMain.master.getFuture().channel(), baseConfig.getLine().getCoa(), 6, OnlineDataMain.master.getLog());
+    // }
 
 
     @SneakyThrows
@@ -69,6 +69,10 @@ public class TimeSaveScheduled {
                     }
                 });
             }
+
+            log.info(baseConfig.getLine().getPort() + "发送总召");
+            CommonData.map.clear();
+            SendDataFrameHelper.sendTotalSummonFrame(OnlineDataMain.master.getFuture().channel(), baseConfig.getLine().getCoa(), 6, OnlineDataMain.master.getLog());
         }
     }
 

+ 4 - 4
src/main/java/com/energy/online/data/handle/HandleNormalizedIntegerType.java → src/main/java/com/energy/online/data/handle/HandleNormalizedInteger.java

@@ -13,7 +13,7 @@ import java.util.Map;
 
 @Slf4j
 @AsduType(typeId = 9)
-public class HandleNormalizedIntegerType extends NormalizedIntegerType {
+public class HandleNormalizedInteger extends NormalizedIntegerType {
 
     /**
      * 处理短整型数据
@@ -24,9 +24,9 @@ public class HandleNormalizedIntegerType extends NormalizedIntegerType {
     @Override
     public byte[][] handleAndAnswer(Apdu apdu) {
         log.debug("----------处理NormalizedIntegerType型数据---------");
-        HandleShortInteger handleShortFloat = (HandleShortInteger) apdu.getAsdu().getDataFrame();
-        List<InformationBodyAddress> address = handleShortFloat.getAddresses();
-        Map<IeMeasuredQuality, Integer> datas = handleShortFloat.getDatas();
+        HandleNormalizedInteger handleNormalizedInteger = (HandleNormalizedInteger) apdu.getAsdu().getDataFrame();
+        List<InformationBodyAddress> address = handleNormalizedInteger.getAddresses();
+        Map<IeMeasuredQuality, Integer> datas = handleNormalizedInteger.getDatas();
         int i = 0;
         //存入共享服务端
 //        log.info("获取到数据{}个", address.size());

+ 3 - 3
src/main/java/com/energy/online/data/handle/HandleShortInteger.java

@@ -23,7 +23,7 @@ public class HandleShortInteger extends ShortIntegerType {
      */
     @Override
     public byte[][] handleAndAnswer(Apdu apdu) {
-        log.debug("----------处理短整型数据---------");
+        log.debug("----------处理HandleShortInteger数据---------");
         HandleShortInteger handleShortFloat = (HandleShortInteger) apdu.getAsdu().getDataFrame();
         List<InformationBodyAddress> address = handleShortFloat.getAddresses();
         Map<IeMeasuredQuality, Integer> datas = handleShortFloat.getDatas();
@@ -31,12 +31,12 @@ public class HandleShortInteger extends ShortIntegerType {
         //存入共享服务端
 //        log.info("获取到数据{}个", address.size());
         if (apdu.getAsdu().getVsq().getSq() == 0) {
-            log.debug("------处理短整型单一寻址-----");
+            log.debug("------处理HandleShortInteger单一寻址-----");
             for (Map.Entry<IeMeasuredQuality, Integer> e : datas.entrySet()) {
                 CommonData.put(address.get(i++).getAddress(), e.getValue());
             }
         } else if (apdu.getAsdu().getVsq().getSq() == 1) {
-            log.debug("------处理短整型连续寻址-----");
+            log.debug("------处理HandleShortInteger连续寻址-----");
             i = address.get(0).getAddress();
             for (Map.Entry<IeMeasuredQuality, Integer> e : datas.entrySet()) {
                 CommonData.put(i++, e.getValue());

+ 3 - 3
src/main/java/com/energy/online/data/handle/HandleShortIntegerWithTimeType.java

@@ -23,7 +23,7 @@ public class HandleShortIntegerWithTimeType extends ShortIntegerWithTimeType {
      */
     @Override
     public byte[][] handleAndAnswer(Apdu apdu) {
-        log.debug("----------处理短整型带时间数据---------");
+        log.debug("----------处理HandleShortIntegerWithTimeType带时间数据---------");
         HandleShortInteger handleShortFloat = (HandleShortInteger) apdu.getAsdu().getDataFrame();
         List<InformationBodyAddress> address = handleShortFloat.getAddresses();
         Map<IeMeasuredQuality, Integer> datas = handleShortFloat.getDatas();
@@ -31,12 +31,12 @@ public class HandleShortIntegerWithTimeType extends ShortIntegerWithTimeType {
         //存入共享服务端
 //        log.info("获取到数据{}个", address.size());
         if (apdu.getAsdu().getVsq().getSq() == 0) {
-            log.debug("------处理短整型单一寻址-----");
+            log.debug("------处理HandleShortIntegerWithTimeType单一寻址-----");
             for (Map.Entry<IeMeasuredQuality, Integer> e : datas.entrySet()) {
                 CommonData.put(address.get(i++).getAddress(), e.getValue());
             }
         } else if (apdu.getAsdu().getVsq().getSq() == 1) {
-            log.debug("------处理短整型连续寻址-----");
+            log.debug("------处理HandleShortIntegerWithTimeType连续寻址-----");
             i = address.get(0).getAddress();
             for (Map.Entry<IeMeasuredQuality, Integer> e : datas.entrySet()) {
                 CommonData.put(i++, e.getValue());

+ 49 - 0
src/main/java/com/energy/online/data/handle/HandleYX151.java

@@ -0,0 +1,49 @@
+package com.energy.online.data.handle;
+
+import com.energy.online.data.common.CommonData;
+import lombok.extern.slf4j.Slf4j;
+import wei.yigulu.iec104.annotation.AsduType;
+import wei.yigulu.iec104.apdumodel.Apdu;
+import wei.yigulu.iec104.asdudataframe.Yx151IntegerType;
+import wei.yigulu.iec104.asdudataframe.qualitydescription.IeMeasuredQuality;
+import wei.yigulu.iec104.asdudataframe.typemodel.InformationBodyAddress;
+
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@AsduType(typeId = 151)
+public class HandleYX151 extends Yx151IntegerType {
+
+    /**
+     * 处理短整型数据
+     *
+     * @param apdu
+     * @return
+     */
+    @Override
+    public byte[][] handleAndAnswer(Apdu apdu) {
+        log.debug("----------处理HandleShortInteger数据---------");
+        HandleYX151 handleShortFloat = (HandleYX151) apdu.getAsdu().getDataFrame();
+        List<InformationBodyAddress> address = handleShortFloat.getAddresses();
+        Map<IeMeasuredQuality, Long> datas = handleShortFloat.getDatas();
+        int i = 0;
+        //存入共享服务端
+//        log.info("获取到数据{}个", address.size());
+        if (apdu.getAsdu().getVsq().getSq() == 0) {
+            log.debug("------处理HandleShortInteger单一寻址-----");
+            for (Map.Entry<IeMeasuredQuality, Long> e : datas.entrySet()) {
+                CommonData.put(address.get(i++).getAddress(), e.getValue());
+            }
+        } else if (apdu.getAsdu().getVsq().getSq() == 1) {
+            log.debug("------处理HandleShortInteger连续寻址-----");
+            i = address.get(0).getAddress();
+            for (Map.Entry<IeMeasuredQuality, Long> e : datas.entrySet()) {
+                CommonData.put(i++, e.getValue());
+            }
+        }
+
+        //如果有需要返回数据帧可以创建byte数据  向内置入要返回的数据帧encode()后的数组
+        return null;
+    }
+}

+ 5 - 1
src/main/resources/application-2404.yml

@@ -8,10 +8,14 @@ spring:
 iec104:
   saveDir: "/home/caiji/data/2404/"
   line:
-    ip: 172.21.6.36
+    #    ip: 172.21.6.36
+    #    port: 2405
+    #    coa: 1
+    ip: 192.168.50.242
     port: 2404
     coa: 1
 
+
 my:
   scheduled:
     cron: "0/10 * * * * *"

+ 1 - 1
src/main/resources/logback-spring-2404.xml

@@ -14,7 +14,7 @@
         </rollingPolicy>
     </appender>
 
-    <root level="INFO">
+    <root level="DEBUG">
         <appender-ref ref="CONSOLE"/>
         <appender-ref ref="FILE"/>
     </root>