###### 本工具是本人基于工作所需开发的针对于IEC104通讯的辅助工具 该工具针对U帧和S帧已经做好了收发逻辑,但是I帧的具体处理逻辑需要使用者自己实现 本工具基于netty框架。建议有netty使用经验和对104通讯规约的人使用。如果不了解104通讯规约,理解本工具的工作流程可能会有些麻烦。 # 使用方式 ## Matser的创建 以及数据的接收处理: ### Matser的创建 ```java SimpleMasterBuilder simpleMasterBuilder=new SimpleMasterBuilder("127.0.0.1",2404); simpleMasterBuilder.create(); ``` 上面 这种master仅支持一个ip和端口号,与之相对的是HSMasterBuilder 支持主备链接 ,主动切换。 ```java HSMasterBuilder masterBuilder=new HSMasterBuilder("127.0.0.1",2404).setSpareIp("127.0.0.2"); masterBuilder.create(); ``` create() 方法会阻塞线程,如果不希望阻塞线程可以使用createByUnBlock(),以工具内的单线程池执行。 ### 数据的接收 首先向slave端发送总召唤 ```java //创建总召唤类型I帧 TotalSummonType totalSummonType=new TotalSummonType(); //反向生成asdu Asdu asdu = totalSummonType.generateBack(); //配置总召唤发送原因 asdu.setNot(6); //配置公共地址位 asdu.setCommonAddress(1); Apdu apdu=new Apdu().setAsdu(asdu); masterBuilder.sendFrame(apdu); ``` 实现对应数据类型的数据接收后的处理,以数据类型为13的浮点数为例 ```java @Slf4j @AsduType(typeId=13) public class HandleShortFloat extends ShortFloatType { /** * 处理短浮点数据 * * @param apdu * @return */ @Override public byte[][] handleAndAnswer(Apdu apdu) { log.info("----------处理短浮点数据---------"); Map map = new HashMap<>(); HandleShortFloat handleShortFloat = (HandleShortFloat) apdu.getAsdu().getDataFrame(); List address = handleShortFloat.getAddresses(); Map datas = handleShortFloat.getDatas(); int i = 0; //存入共享服务端 if (apdu.getAsdu().getVsq().getSq() == 0) { log.warn("------处理短浮点单一寻址-----"); for (Map.Entry e : datas.entrySet()) { map.put(address.get(i++).getAddress(), e.getValue()); } } else if (apdu.getAsdu().getVsq().getSq() == 1) { log.warn("------处理短浮点连续寻址-----"); i = address.get(0).getAddress(); for (Map.Entry e : datas.entrySet()) { map.put(i++, e.getValue()); } } //将map 储起来 //TODO //如果有需要返回数据帧可以创建byte数据 向内置入要返回的数据帧encode()后的数组 return null; } } ``` ## Slave端的创建及数据的发送 ### Slave端的创建 ```java SlaverBuilder slaverBuilder=new SlaverBuilder(); slaverBuilder.create(); ``` 数据响应 响应总召唤 ```java @AsduType(typeId = 100) @Slf4j public class HandleTotalSummonType extends TotalSummonType { @Override public byte[][] handleAndAnswer(Apdu apdu) throws Exception { TotalSummonType dataFrameType = (TotalSummonType) (apdu.getAsdu().getDataFrame()); Channel channel = apdu.getChannel(); int commonAddress = apdu.getAsdu().getCommonAddress(); if (dataFrameType.getValue() == 20 && apdu.getAsdu().getCot().getNot() == 6) { //1.回应激活确认总召唤 SendDataFrameHelper.sendTotalSummonFrame(channel, commonAddress, 7); //2.回应连续寻址短浮点i帧 SendDataFrameHelper.sendYcDataFrame(channel, //TODO 传入类型的数据map , commonAddress, 20); //3.回应激活终止总召唤总召唤 SendDataFrameHelper.sendTotalSummonFrame(channel, commonAddress, 8); } return null; } ``` 突发上送数据 向所有接入的master突发上送map中的数据 ```java for (Channel channel : slaverBuilder.getChannels()) { try { SendDataFrameHelper.sendYcDataFrameDiscontinuity(channel, //TODO 传入类型的数据map , 1, 3); } catch (Exception e) { e.printStackTrace(); } } ``` ##### 更加深入的应用请研究代码 apdu asdu 和各个类型的报文帧 都支持重写,包括拆包工具也支持重写,如果有疑问可以向 weiyigulu524710549@gmail.com 邮箱留言