1、完善代码;
2、修改上行命令结果匹配命令的bug;
| | |
| | | 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未曾上线时,也能用此协议构造命令并缓存下来,尤其适合低功耗情况。 |
| | |
| | | //针对一个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处理不过来 |
| | |
| | | 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未曾上线时,也能用此协议构造命令并缓存下来,尤其适合低功耗情况。 |
| | |
| | | this.nextDealRtuData(false, resFromRtu); |
| | | this.nextDealRtuComResult(resFromRtu); |
| | | }else{ |
| | | log.error("匹配命令失败,功能码是:" + ((MidResultFromRtu) result).upCode ); |
| | | this.nextDealRtuData(false, resFromRtu); |
| | | //未匹配到下发的命令,命令在缓存因超时被清除了 |
| | | RtuStatusDealer.commandFail2Success(resFromRtu.rtuAddr) ; |
| | |
| | | */ |
| | | private void nextDealRtuComResult(MidResultFromRtu resFromRtu){ |
| | | try{ |
| | | log.info("开始把命令结果放入缓中"); |
| | | RtuComResultCache.cacheRtuComResult(new RtuComResultNode(resFromRtu.data)); |
| | | log.info("结束把命令结果放入缓中"); |
| | | }catch(Exception e){ |
| | | log.error(e.getMessage(), e); |
| | | } |
| | |
| | | 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); |
| | | } |
| | |
| | | obj.onceReceivedResult = true ;//标识已经收到命令结果 |
| | | return res ; |
| | | }else{ |
| | | node = node.pre ; |
| | | node = node.next ; |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | if(rtuAddr != null){ |
| | | if(protocolName == null){ |
| | | protocolName = TcpSessionCache.getTcpProtocolName(rtuAddr) ; |
| | | 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 ; |
| | | } |
| | | } |
| | | |
| | | //设置收到数据时刻 |
| | | TcpSessionCache.cacheUpDataTime(rtuAddr); |
| | | |
| | | if(protocolName != null){ |
| | | //对上行数据进行处理 |
| | | this.dealUpData(session, rtuAddr, protocolName, isOnLine, upBuf, upHex) ; |
| | | if(toDeal){ |
| | | if(protocolName == null){ |
| | | protocolName = TcpSessionCache.getTcpProtocolName(rtuAddr) ; |
| | | } |
| | | |
| | | //设置收到数据时刻 |
| | | TcpSessionCache.cacheUpDataTime(rtuAddr); |
| | | |
| | | if(protocolName != null){ |
| | | //对上行数据进行处理 |
| | | this.dealUpData(session, rtuAddr, protocolName, isOnLine, upBuf, upHex) ; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | 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; |
| | |
| | | * @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 |
| | |
| | | 基本配置 |
| | | orgTag 机构tag(对应机构tag,和数据源后缀) |
| | | isLowPower: 是否为低功耗 |
| | | onlyDealRtus:只处理指定RTU地址设备,其他设备数据丢弃,多个RTU地址用英文逗号隔开, |
| | | onlyOneProtocol:在支持多通信协议时,只有RTU上线了,才能识别出该RTU实际用的通信协议,进而用此协议解析上行数据及构造下行命令。 |
| | | 如果RTU未曾上线(通信中间件启动后该RTU未曾上线),那么在向它发送下行命令时,不能判断出其采用的协议,也不能构造命令,尤其是低功耗情况下,不上线是正常现象。 |
| | | 当只有一个协议情况下,在RTU未曾上线时,也能用此协议构造命令并缓存下来,尤其适合低功耗情况。 |
| | |
| | | <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" |
| | |
| | | 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; |
| | |
| | | @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") ; |
| | |
| | | rt.setSuccess(true) ; |
| | | return rt ; |
| | | } |
| | | |
| | | |
| | | private void cd83Open(){ |
| | | UpCd83Open.upCd83Data(); |
| | | } |
| | | |
| | | |
| | | private void cd83Close(){ |
| | | UpCd83Close.upCd83Data(); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | |
| | |
| | | |
| | | 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 构造心跳数据 |
| | | * 构造上行数据 |
| | | * |
| | | * @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] ; |
| | |
| | | |
| | | |
| | | /** |
| | | * 构造心跳数据 |
| | | * 构造上行数据 |
| | | * |
| | | * @return 字节数组 |
| | | * @throws Exception 异常 |
New file |
| | |
| | | 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 ; |
| | | } |
| | | } |
| | |
| | | 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(){ |
| | |
| | | return closeValveDt ; |
| | | } |
| | | |
| | | public static void closeValve(){ |
| | | public static void addValve(){ |
| | | perMoney = perAmount / (thisPrice / 100) ; |
| | | thisAmount += perAmount ; |
| | | thisMoney += perMoney ; |
| | | |
| | | totalAmount = totalAmount + perAmount ; |
| | | remainMoney = remainMoney - perMoney ; |
| | | } |
| | |
| | | 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卡编号(用户虚拟卡序列号) |
| | | |