package wei.yigulu.iec104.util; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import wei.yigulu.iec104.apdumodel.Apdu; import wei.yigulu.iec104.container.Iec104Link; import wei.yigulu.iec104.container.LinkContainer; import wei.yigulu.utils.DataConvertor; /** * 用以处理接收和发送序列号的处理类 * * @author 修唯xiuwei * @version 3.0 */ public class SendAndReceiveNumUtil { private static Logger log = LoggerFactory.getLogger(SendAndReceiveNumUtil.class); private static final String INTERVALPROPNAME = "sFrameInterval"; private static final int INTERVALDEFVAL = 5; private static final int INTERVAL = PropertiesReader.getInstance().getIntProp(INTERVALPROPNAME, INTERVALDEFVAL); /** * 为发送的i帧组装接收和发送序号 * * @param apdu apdu * @param channelId channel id */ public static void setSendAndReceiveNum(Apdu apdu, ChannelId channelId) { Iec104Link link = LinkContainer.getInstance().getLink(channelId); int send = link.getISend(); int receive = link.getIReceive(); apdu.setSendSeqNum(send++); apdu.setReceiveSeqNum(receive); link.setISend(send); LinkContainer.getInstance().getLinks().put(channelId, link); } /** * 组装i帧的发送和接收序号 后发出 * * @param apdu apdu * @param channel channel * @throws Exception exception */ public static void sendIFrame(Apdu apdu, Channel channel) throws Exception { setSendAndReceiveNum(apdu, channel.id()); byte[] bb = apdu.encode(); //TODO 改变日志模式 log.debug("向104对端发出数据帧:" + DataConvertor.Byte2String(bb)); channel.writeAndFlush(Unpooled.copiedBuffer(bb)); } /** * 组装i帧的发送和接收序号 后发出 * * @param apdu apdu * @param channel channel * @throws Exception exception */ public static void sendIFrame(Apdu apdu, Channel channel, Logger log) throws Exception { setSendAndReceiveNum(apdu, channel.id()); byte[] bb = apdu.encode(); //TODO 改变日志模式 if (log != null) { log.debug("向104对端发出数据帧:" + DataConvertor.Byte2String(bb)); } else { SendAndReceiveNumUtil.log.debug("向104对端发出数据帧:" + DataConvertor.Byte2String(bb)); } channel.writeAndFlush(Unpooled.copiedBuffer(bb)); } /** * 接收到i帧,处理接收和发送序号 * * @param apdu apdu * @param channelId channel id */ public static void receiveIFrame(Apdu apdu, ChannelId channelId) { Iec104Link link = LinkContainer.getInstance().getLink(channelId); int send = link.getISend(); int receive = link.getIReceive(); int send1 = apdu.getSendSeqNum(); int receive1 = apdu.getReceiveSeqNum(); link.setLinkState(Iec104Link.LinkState.NORMAL); if (receive < send1) { /** * 我方丢失 通道对方放出的 i帧 */ apdu.loseReceive(); link.setLinkState(Iec104Link.LinkState.LOSEREC); } if (send < receive1) { /** * 通道对方丢失 我方发出的i帧 */ apdu.loseSend(); link.setLinkState(Iec104Link.LinkState.LOSESEND); } link.setIReceive(++send1); link.setISend(receive1); sendSFrame(link); LinkContainer.getInstance().getLinks().put(channelId, link); } /** * 向通道内发送s帧 * * @param link link */ public static void sendSFrame(Iec104Link link) { if (link.getIReceive() != 0 && link.getIReceive() % INTERVAL == 0) { Apdu apdu1 = new Apdu(); apdu1.setReceiveSeqNum(link.getIReceive()); apdu1.setApciType(Apdu.ApciType.S_FORMAT); try { byte[] bs = apdu1.encode(); //TODO 改变日志模式 link.getLog().debug("发送s帧:" + DataConvertor.Byte2String(bs)); link.getChannel().writeAndFlush(Unpooled.copiedBuffer(bs)); } catch (Exception e) { e.printStackTrace(); } } } }