pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/Server.java
@@ -138,6 +138,21 @@ if(ServerProperties.isLowPower == null){ ServerProperties.isLowPower = false ; } String onlyDealRtus = conf.getSetAttrTxt(doc, "config.base", "onlyDealRtus", null, true, null) ; if(onlyDealRtus == null || onlyDealRtus.trim().equals("")){ ServerProperties.onlyDealRtusTest = false ; }else{ onlyDealRtus = onlyDealRtus.replaceAll(",", ",") ; onlyDealRtus = onlyDealRtus.replaceAll(" ", "") ; ServerProperties.onlyDealRtus = onlyDealRtus.split(",") ; if(ServerProperties.onlyDealRtus != null && ServerProperties.onlyDealRtus.length > 0){ ServerProperties.onlyDealRtusTest = true ; }else{ ServerProperties.onlyDealRtusTest = false ; } } //在支持多通信协议时,只有RTU上线了,才能识别出该RTU实际用的通信协议,进而用此协议解析上行数据及构造下行命令。 //如果RTU未曾上线(通信中间件启动后该RTU未曾上线),那么在向它发送下行命令时,不能判断出其采用的协议,也不能构造命令,尤其是低功耗情况下,不上线是正常现象。 // 当只有一个协议情况下,在RTU未曾上线时,也能用此协议构造命令并缓存下来,尤其适合低功耗情况。 @@ -151,7 +166,7 @@ //针对一个RTU,下发命令的时间间隔 ServerProperties.commandSendInterval = conf.getSetAttrPlusInt(doc, "config.base", "commandSendInterval", null, 1, 40, null) * 1000L ; //命令已经发送达最大次数,仍未收到命令结果,需要在缓存继续等待,其等待最大时长 ServerProperties.cachWaitResultTimeout = conf.getSetAttrPlusInt(doc, "config.base", "cachWaitResultTimeout", null, 10, 60, null) * 1000L ; ServerProperties.cachWaitResultTimeout = conf.getSetAttrPlusInt(doc, "config.base", "cachWaitResultTimeout", null, 10, 360, null) * 1000L ; //不在线缓存的命令最大缓存时长 ServerProperties.offLineCachTimeout = conf.getSetAttrPlusInt(doc, "config.base", "offLineCachTimeout", null, 15, 172800, null) * 1000L ; //TCP上行数据时刻缓存时长,当达到时长时,TCP上行数据时刻被清空,采用TCP上行数据时刻目的是,阻止上数据同时下发数据,因为RTU处理不过来 pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/ServerProperties.java
@@ -6,6 +6,11 @@ public static String orgTag = "ym" ; //是否为低功耗 public static Boolean isLowPower = false ; //只处理指定RTU地址设备,其他设备数据丢弃,多个RTU地址用英文逗号隔开,如果配置空串(即无IMEI号),则接收全部水表数据,设置此目的是针对某个水表进行调试 public static Boolean onlyDealRtusTest = false ; public static String[] onlyDealRtus ; //在支持多通信协议时,只有RTU上线了,才能识别出该RTU实际用的通信协议,进而用此协议解析上行数据及构造下行命令。 //如果RTU未曾上线(通信中间件启动后该RTU未曾上线),那么在向它发送下行命令时,不能判断出其采用的协议,也不能构造命令,尤其是低功耗情况下,不上线是正常现象。 // 当只有一个协议情况下,在RTU未曾上线时,也能用此协议构造命令并缓存下来,尤其适合低功耗情况。 pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/forTcp/MidResultActionFromRtu.java
@@ -34,6 +34,7 @@ this.nextDealRtuData(false, resFromRtu); this.nextDealRtuComResult(resFromRtu); }else{ log.error("匹配命令失败,功能码是:" + ((MidResultFromRtu) result).upCode ); this.nextDealRtuData(false, resFromRtu); //未匹配到下发的命令,命令在缓存因超时被清除了 RtuStatusDealer.commandFail2Success(resFromRtu.rtuAddr) ; @@ -64,7 +65,9 @@ */ private void nextDealRtuComResult(MidResultFromRtu resFromRtu){ try{ log.info("开始把命令结果放入缓中"); RtuComResultCache.cacheRtuComResult(new RtuComResultNode(resFromRtu.data)); log.info("结束把命令结果放入缓中"); }catch(Exception e){ log.error(e.getMessage(), e); } pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/forTcp/MidResultActionToRtu.java
@@ -16,7 +16,7 @@ try { MidResultToRtu resToRtu = (MidResultToRtu)result ; TcpDownCommandCache.cacheCommand(resToRtu); log.info("下行命令(toRtu)" + resToRtu.downCode + "中间结果已经放入下行命令缓存中"); log.info("下行命令(toRtu,id=" + resToRtu.commandId + ")" + resToRtu.downCode + "中间数据(MidResult)已经放入下行命令缓存中"); } catch (Exception e) { log.error(e); } pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/forTcp/TcpDownCommandCache.java
@@ -62,7 +62,7 @@ obj.onceReceivedResult = true ;//标识已经收到命令结果 return res ; }else{ node = node.pre ; node = node.next ; } } pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/tasks/RtuUpTask.java
@@ -78,8 +78,22 @@ } } } if(rtuAddr != null){ boolean toDeal = true ; if(ServerProperties.onlyDealRtusTest){ boolean find = false ; for(String testRtu : ServerProperties.onlyDealRtus){ if(testRtu.equals(rtuAddr)){ find = true ; break ; } } if(!find){ //不在处理范围内 toDeal = false ; } } if(toDeal){ if(protocolName == null){ protocolName = TcpSessionCache.getTcpProtocolName(rtuAddr) ; } @@ -93,6 +107,7 @@ } } } } /** * 解析上线数据 pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/web/comResult/CommandResultDeal.java
@@ -2,7 +2,8 @@ import com.dy.common.mw.protocol.Command; import com.dy.common.mw.protocol.Data; import lombok.extern.slf4j.Slf4j; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.http.converter.StringHttpMessageConverter; @@ -18,10 +19,11 @@ * @LastEditTime 2023/12/21 20:28 * @Description */ @Slf4j @Component() public class CommandResultDeal { private static final Logger log = LogManager.getLogger(CommandResultDeal.class.getName()); private RestTemplate restTemplate; @Autowired pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/resources/config.xml
@@ -5,6 +5,7 @@ 基本配置 orgTag 机构tag(对应机构tag,和数据源后缀) isLowPower: 是否为低功耗 onlyDealRtus:只处理指定RTU地址设备,其他设备数据丢弃,多个RTU地址用英文逗号隔开, onlyOneProtocol:在支持多通信协议时,只有RTU上线了,才能识别出该RTU实际用的通信协议,进而用此协议解析上行数据及构造下行命令。 如果RTU未曾上线(通信中间件启动后该RTU未曾上线),那么在向它发送下行命令时,不能判断出其采用的协议,也不能构造命令,尤其是低功耗情况下,不上线是正常现象。 当只有一个协议情况下,在RTU未曾上线时,也能用此协议构造命令并缓存下来,尤其适合低功耗情况。 @@ -22,10 +23,11 @@ <base orgTag="ym" isLowPower="false" onlyOneProtocol="true" onlyDealRtus="532328059995" onlyOneProtocol="false" downComandMaxResendTimes="1" commandSendInterval="2" cachWaitResultTimeout="60" cachWaitResultTimeout="120" offLineCachTimeout="86400" lastUpDataTimeLive="500" dbDataIdSuffix="0" pipIrr-platform/pipIrr-web/pipIrr-mwTest-rtu/src/main/java/com/dy/pipIrrMwTestRtu/p206V1_0_0/RtuP206V1_0_0Ctrl.java
@@ -3,6 +3,7 @@ import com.dy.common.webUtil.BaseResponse; import com.dy.pipIrrMwTestRtu.tcpClient.upData.UpCd83Close; import com.dy.pipIrrMwTestRtu.tcpClient.upData.UpCd83Open; import com.dy.pipIrrMwTestRtu.tcpClient.upData.UpCd84; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,9 +23,11 @@ @GetMapping(path = "test") public BaseResponse<String> test(String com) { if(com.equals("83Open")){ this.cd83Open() ; UpCd83Open.upCd83Data(); }else if(com.equals("83Close")){ this.cd83Close() ; UpCd83Close.upCd83Data(); }else if(com.equals("84")){ UpCd84.upCd84Data(); } BaseResponse<String> rt = new BaseResponse<String>() ; rt.setCode("001") ; @@ -32,18 +35,6 @@ rt.setSuccess(true) ; return rt ; } private void cd83Open(){ UpCd83Open.upCd83Data(); } private void cd83Close(){ UpCd83Close.upCd83Data(); } } pipIrr-platform/pipIrr-web/pipIrr-mwTest-rtu/src/main/java/com/dy/pipIrrMwTestRtu/tcpClient/upData/UpCd83Close.java
@@ -2,7 +2,6 @@ import com.dy.common.mw.protocol.p206V1_0_0.parse.global.GlCreate; import com.dy.common.util.ByteUtil; import com.dy.common.util.ByteUtilUnsigned; import com.dy.pipIrrMwTestRtu.ServerProperties; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -31,13 +30,14 @@ /** * 构造心跳数据 * 构造上行数据 * * @return 字节数组 * @throws Exception 异常 */ private static byte[] createData(String rtuAddr) throws Exception { UpConstant.closeValve(); UpConstant.addValve();//调整流量 byte[] bytes = creatHead(rtuAddr, "83", (byte)0xB0); byte[] bs = new byte[1] ; pipIrr-platform/pipIrr-web/pipIrr-mwTest-rtu/src/main/java/com/dy/pipIrrMwTestRtu/tcpClient/upData/UpCd83Open.java
@@ -31,7 +31,7 @@ /** * 构造心跳数据 * 构造上行数据 * * @return 字节数组 * @throws Exception 异常 pipIrr-platform/pipIrr-web/pipIrr-mwTest-rtu/src/main/java/com/dy/pipIrrMwTestRtu/tcpClient/upData/UpCd84.java
New file @@ -0,0 +1,89 @@ package com.dy.pipIrrMwTestRtu.tcpClient.upData; import com.dy.common.mw.protocol.p206V1_0_0.parse.global.GlCreate; import com.dy.common.util.ByteUtil; import com.dy.pipIrrMwTestRtu.ServerProperties; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * @Author: liurunyu * @Date: 2024/7/16 19:32 * @Description */ public class UpCd84 extends UpData { private static final Logger log = LogManager.getLogger(UpCd84.class); public static void upCd84Data() { try { if (UpData.session != null && UpData.session.isConnected()) { byte[] bs = createData(ServerProperties.rtuAddr); UpData.upSend(bs); } else { log.error("未连接通信中间件,不能发送数据"); } } catch (Exception e) { log.error("向通信中间件发送数据产生异常", e); } } /** * 构造心跳数据 * * @return 字节数组 * @throws Exception 异常 */ private static byte[] createData(String rtuAddr) throws Exception { UpConstant.addValve();//调整流量 byte[] bytes = creatHead(rtuAddr, "84", (byte)0xB0); byte[] bs = new byte[1] ; bs[0] = (byte)0x01 ;//刷卡开阀 bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[1] ; bs[0] = (byte)0x01 ;//卡类型 用户卡 bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[4] ;//IC卡地址 ByteUtil.hex2Bytes_LE(ServerProperties.icCardAddr, bs, 0); bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[8] ;//IC卡编号 GlCreate.createIcCardNo(ServerProperties.icCardNo, bs, 0); bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[4] ;//用水户余额 ByteUtil.int2BCD_LE(UpConstant.remainMoney, bs, 0); bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[5] ;//累计流量 ByteUtil.int2BCD_LE(UpConstant.totalAmount, bs, 0); bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[5] ;//瞬时流量 ByteUtil.int2BCD_LE(UpConstant.instantAmount, bs, 0); bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[]{0x00, 0x00} ;//报警 bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[]{0x00, 0x00} ;//状态 bytes = ByteUtil.bytesMerge(bytes, bs) ; bs = new byte[6] ;//控制器时钟 GlCreate.createTp(bs, 0); bytes = ByteUtil.bytesMerge(bytes, bs) ; GlCreate.createLen(bytes);//长度放字节数组中 byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾叠加字节数组中 bytes = ByteUtil.bytesMerge(bytes, bsTail) ; return bytes ; } } pipIrr-platform/pipIrr-web/pipIrr-mwTest-rtu/src/main/java/com/dy/pipIrrMwTestRtu/tcpClient/upData/UpConstant.java
@@ -13,15 +13,16 @@ private static String openValveDt ; private static String closeValveDt ; public static Integer instantAmount = 10123;//瞬时流量10.000 public static Integer totalAmount = 1234567;//实为12345.67 public static Integer remainMoney = 56789;//实为567.89 public static Integer thisAmount = 1000;//实为10.00 public static Integer thisMoney = 1000;//实为10.00 public static Integer thisAmount = 0;// public static Integer thisMoney = 0;// public static Integer thisTime = 10;//实为10 public static Integer thisPrice = 100;//实为1.00 public static Integer perAmount = thisAmount; public static Integer perMoney = thisMoney; public static Integer perAmount = 10; public static Integer perMoney = 0; public static void clearOpenValveDt(){ @@ -40,7 +41,11 @@ return closeValveDt ; } public static void closeValve(){ public static void addValve(){ perMoney = perAmount / (thisPrice / 100) ; thisAmount += perAmount ; thisMoney += perMoney ; totalAmount = totalAmount + perAmount ; remainMoney = remainMoney - perMoney ; } pipIrr-platform/pipIrr-web/pipIrr-mwTest-web/src/main/java/com/dy/pipIrrMwTestWeb/p206V1_0_0/ComSupportP206V1_0_0.java
@@ -20,8 +20,12 @@ public class ComSupportP206V1_0_0 { protected static String mwUrlTest = "http://127.0.0.1:8070/rtuMw/com/test" ; protected static String mwUrlSendCom = "http://127.0.0.1:8070/rtuMw/com/send" ; protected static String rtuAddr = "532328059995" ; // protected static String mwUrlTest = "http://8.140.179.55:8071/rtuMw/com/test" ; // protected static String mwUrlSendCom = "http://8.140.179.55:8071/rtuMw/com/send" ; // protected static String rtuAddr = "620202000066" ; protected static String rtuResultSendWebUrl = "http://127.0.0.1:65535/test/comRes/receive" ; protected static String vsIcCardNo = "61181622830147822" ;//虚拟IC卡编号(用户虚拟卡序列号)