该工具针对U帧和S帧已经做好了收发逻辑,但是I帧的具体处理逻辑需要使用者自己实现
本工具基于netty框架。建议有netty使用经验和对104通讯规约的人使用。如果不了解104通讯规约,理解本工具的工作流程可能会有些麻烦。
SimpleMasterBuilder simpleMasterBuilder=new SimpleMasterBuilder("127.0.0.1",2404);
simpleMasterBuilder.create();
上面 这种master仅支持一个ip和端口号,与之相对的是HSMasterBuilder 支持主备链接 ,主动切换。
HSMasterBuilder masterBuilder=new HSMasterBuilder("127.0.0.1",2404).setSpareIp("127.0.0.2");
masterBuilder.create();
create() 方法会阻塞线程,如果不希望阻塞线程可以使用createByUnBlock(),以工具内的单线程池执行。
首先向slave端发送总召唤
//创建总召唤类型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的浮点数为例
@Slf4j
@AsduType(typeId=13)
public class HandleShortFloat extends ShortFloatType {
/**
* 处理短浮点数据
*
* @param apdu
* @return
*/
@Override
public byte[][] handleAndAnswer(Apdu apdu) {
log.info("----------处理短浮点数据---------");
Map<Integer, Float> map = new HashMap<>();
HandleShortFloat handleShortFloat = (HandleShortFloat) apdu.getAsdu().getDataFrame();
List<InformationBodyAddress> address = handleShortFloat.getAddresses();
Map<IeMeasuredQuality, Float> datas = handleShortFloat.getDatas();
int i = 0;
//存入共享服务端
if (apdu.getAsdu().getVsq().getSq() == 0) {
log.warn("------处理短浮点单一寻址-----");
for (Map.Entry<IeMeasuredQuality, Float> 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<IeMeasuredQuality, Float> e : datas.entrySet()) {
map.put(i++, e.getValue());
}
}
//将map 储起来
//TODO
//如果有需要返回数据帧可以创建byte数据 向内置入要返回的数据帧encode()后的数组
return null;
}
}
SlaverBuilder slaverBuilder=new SlaverBuilder();
slaverBuilder.create();
数据响应 响应总召唤
@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 传入<Integer,Number>类型的数据map
, commonAddress, 20);
//3.回应激活终止总召唤总召唤
SendDataFrameHelper.sendTotalSummonFrame(channel, commonAddress, 8);
}
return null;
}
突发上送数据 向所有接入的master突发上送map中的数据
for (Channel channel : slaverBuilder.getChannels()) {
try {
SendDataFrameHelper.sendYcDataFrameDiscontinuity(channel, //TODO 传入<Integer,Number>类型的数据map
, 1, 3);
} catch (Exception e) {
e.printStackTrace();
}
}