diff --git a/web/src/main/java/com/zhehekeji/web/controller/ClientTestController.java b/web/src/main/java/com/zhehekeji/web/controller/ClientTestController.java new file mode 100644 index 0000000..56a8a30 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/controller/ClientTestController.java @@ -0,0 +1,55 @@ +package com.zhehekeji.web.controller; + +import com.github.pagehelper.PageInfo; +import com.zhehekeji.core.pojo.Result; +import com.zhehekeji.web.entity.CheckLog; +import com.zhehekeji.web.pojo.stock.CheckLogSearch; +import com.zhehekeji.web.service.EmptyCheckService; +import com.zhehekeji.web.service.client.ClientChanel; +import com.zhehekeji.web.service.client.ECTransmission; +import com.zhehekeji.web.service.client.TMTransmission; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import org.apache.poi.ss.formula.functions.T; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; + +@Api(tags = "客户端通讯测试") +@RequestMapping("/clientTest") +@RestController +public class ClientTestController { + + @Resource + private EmptyCheckService emptyCheckService; + + @ApiOperation("空货位盘点【发起】") + @GetMapping("/emptyCheck/start") + public Result startEmptyCheck(@ApiParam("巷道标识") String SRMNumber,@ApiParam("盘点批次ID") String taskId, @ApiParam("检测第几行") Integer row){ + + ClientChanel.write(ECTransmission.toEmptyCheckStartString(SRMNumber),SRMNumber); + + return Result.success(); + } + + @ApiOperation("空货位盘点 【结束】") + @GetMapping("/emptyCheck/stop") + public Result stopEmptyCheck(@ApiParam("巷道标识") String SRMNumber,@ApiParam("盘点批次ID") String taskId, @ApiParam("检测第几行") Integer row){ + emptyCheckService.emptyCheckStart(SRMNumber,taskId,row); + ClientChanel.write(ECTransmission.toEmptyCheckEndString(SRMNumber),SRMNumber); + return Result.success(); + } + + @ApiOperation("盘点具体货位 第一步 【开始】") + @GetMapping("/stockCheck/start") + public Result startStockCheck(@ApiParam("巷道标识") String SRMNumber,@ApiParam("盘点批次ID") String taskId, + @ApiParam("货位号,如L0100010002 ,R/L表示左右,01是浅货位(02深),0001是X,0002是Y") String goodsLocation, + @ApiParam("是否是虚拟检测 Y:是 N:不是")String V){ + TMTransmission tmTransmission = new TMTransmission(); + + ClientChanel.write(ECTransmission.toEmptyCheckEndString(SRMNumber),SRMNumber); + return Result.success(); + } + +} diff --git a/web/src/main/java/com/zhehekeji/web/service/EmptyCheckService.java b/web/src/main/java/com/zhehekeji/web/service/EmptyCheckService.java index 167636e..f897845 100644 --- a/web/src/main/java/com/zhehekeji/web/service/EmptyCheckService.java +++ b/web/src/main/java/com/zhehekeji/web/service/EmptyCheckService.java @@ -21,6 +21,7 @@ import java.time.LocalDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; @Service @Slf4j @@ -106,24 +107,57 @@ public class EmptyCheckService { } /** - * 空托盘检测开始 - * @param ecTransmission + * 空托盘检测 按行开始 + * @param */ - public void emptyCheckStart(ECTransmission ecTransmission){ - Street street = streetService.getStreetByPlcId(ecTransmission.getSRMNumber()); + public void emptyCheckStart(String SRMNUmber,String taskId,Integer row){ + log.info("空托盘检测 按行开始,SRMNUmber:{},taskNo:{},row:{}",SRMNUmber,taskId,row); + Street street = streetService.getStreetByPlcId(SRMNUmber); if(street == null){ - log.error(" no SRMNumer:{}",ecTransmission.getSRMNumber()); + log.error(" no SRMNumer:{}",SRMNUmber); return; } Map map = new HashMap<>(); map.put("street_id",street.getId()); +// map.put("direction",leftRight); +// map.put("side",side); + map.put("row",row); stockMapper.deleteByMap(map); //新增空的盘点统计 - CheckStreetSummary checkStreetSummary = new CheckStreetSummary(); - checkStreetSummary.setTaskId(ecTransmission.getTaskId()); - checkStreetSummary.setStartTime(LocalDateTime.now()); - checkStreetSummary.setStreetId(street.getId()); - checkStreetSummaryMapper.insert(checkStreetSummary); + List checkStreetSummaries = checkStreetSummaryMapper.selectList(new QueryWrapper().eq("street_id",street.getId()).eq("task_id",taskId)); + if(checkStreetSummaries.size() == 0){ + log.info("新增盘点统计,SRMNUmber:{},taskNo:{},row:{}",SRMNUmber,taskId,row); + CheckStreetSummary checkStreetSummary = new CheckStreetSummary(); + checkStreetSummary.setTaskId(taskId); + checkStreetSummary.setStartTime(LocalDateTime.now()); + checkStreetSummary.setStreetId(street.getId()); + checkStreetSummaryMapper.insert(checkStreetSummary); + } + + } + + public String getEmptyStatus(String SRMNUmber,String taskId,Integer side,Integer leftRight,Integer row){ + Street street = streetService.getStreetByPlcId(SRMNUmber); + if(street == null){ + log.error(" no SRMNumer:{}",SRMNUmber); + return null; + } + List stockList = stockMapper.selectList(new QueryWrapper().eq("`row`",row).eq("street_id",street.getId()).eq("direction",leftRight).eq("side",side)); + Map stockMap = new HashMap<>(stockList.size()*2); + stockList.forEach(stock -> { + stockMap.put(stock.getColumn(),stock); + }); + int columns = side == 1?street.getLeftColumn():street.getRightColumn(); + StringBuffer sb = new StringBuffer(); + for(int i = 1;i<=columns;i++){ + if(stockMap.get(i) != null && stockMap.get(i).getEmptyStatus() == 1){ + sb.append(1); + }else { + sb.append(0); + } + } + return sb.toString(); + } public void emptyCheckLog(ECTransmission ecTransmission){ @@ -138,6 +172,8 @@ public class EmptyCheckService { stock.setDirection(ecTransmission.getDirection()); if(ecTransmission.getIsEmpty().equals("N")){ stock.setEmptyStatus(3); + }else { + stock.setEmptyStatus(1); } stock.setRow(ecTransmission.getRow()); stock.setColumn(ecTransmission.getColumn()); diff --git a/web/src/main/java/com/zhehekeji/web/service/client/Decoder.java b/web/src/main/java/com/zhehekeji/web/service/client/Decoder.java index f36d8f3..d26cb39 100644 --- a/web/src/main/java/com/zhehekeji/web/service/client/Decoder.java +++ b/web/src/main/java/com/zhehekeji/web/service/client/Decoder.java @@ -1,5 +1,6 @@ package com.zhehekeji.web.service.client; +import com.zhehekeji.web.service.EmptyCheckService; import com.zhehekeji.web.service.PlcService; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -19,6 +20,8 @@ public class Decoder extends DelimiterBasedFrameDecoder { private static final Logger tcpLogger = LoggerFactory.getLogger("tcp"); + private EmptyCheckService emptyCheckService; + private PlcService plcService; public Decoder(PlcService plcService) { super(200,true,false, Unpooled.copiedBuffer(";".getBytes())); @@ -33,6 +36,7 @@ public class Decoder extends DelimiterBasedFrameDecoder { return null; } String body = in.toString(Charset.forName("UTF-8")); + tcpLogger.info("client rece:{}",body); if(body.startsWith(HBTransmission.getHEADER())) { //心跳 HBTransmission hbTransmission = new HBTransmission(body); @@ -56,6 +60,8 @@ public class Decoder extends DelimiterBasedFrameDecoder { }else if(body.startsWith(ECTransmission.getHEADER())){ //空货位盘点 ECTransmission ecTransmission = new ECTransmission(body); + //保存空货位信息 + emptyCheckService.emptyCheckLog(ecTransmission); }else if(body.startsWith("DC")){ //客户端断开连接 diff --git a/web/src/main/java/com/zhehekeji/web/service/client/ECTransmission.java b/web/src/main/java/com/zhehekeji/web/service/client/ECTransmission.java index 7a26964..7ee449d 100644 --- a/web/src/main/java/com/zhehekeji/web/service/client/ECTransmission.java +++ b/web/src/main/java/com/zhehekeji/web/service/client/ECTransmission.java @@ -67,7 +67,7 @@ public class ECTransmission { * 空托盘检测开始信息 * @return */ - public String toEmptyCheckStartString(){ + public static String toEmptyCheckStartString(String SRMNumber){ StringBuffer sb = new StringBuffer(HEADER); sb.append(Split).append(SRMNumber).append(Split).append("START"); return sb.toString(); @@ -77,7 +77,7 @@ public class ECTransmission { * 空托盘检测 结束信号 * @return */ - public String toEmptyCheckEndString(){ + public static String toEmptyCheckEndString(String SRMNumber){ StringBuffer sb = new StringBuffer(HEADER); sb.append(Split).append(SRMNumber).append(Split).append("END"); return sb.toString(); diff --git a/web/src/main/java/com/zhehekeji/web/service/client/TMTransmission.java b/web/src/main/java/com/zhehekeji/web/service/client/TMTransmission.java index c48f384..20ccdb1 100644 --- a/web/src/main/java/com/zhehekeji/web/service/client/TMTransmission.java +++ b/web/src/main/java/com/zhehekeji/web/service/client/TMTransmission.java @@ -36,7 +36,6 @@ public class TMTransmission { private Integer count; - private String visualTest; private String isDisConnect; @@ -61,8 +60,6 @@ public class TMTransmission { return sb.toString(); } - - public static String getHeader(){ return header; } diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PTData.java b/web/src/main/java/com/zhehekeji/web/service/putian/PTData.java new file mode 100644 index 0000000..56d8d45 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTData.java @@ -0,0 +1,70 @@ +package com.zhehekeji.web.service.putian; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class PTData { + + protected static String SPLIT = "#"; + + private static String END_STRING = "\n"; + + public static String HEART_TYPE = "HB"; + + /** + * 1.空货位盘点开始(EmptyCheck01): EC01 + * 2.空货位盘点结束(EmptyCheck02): EC02 + * 3.盘点系统返回普天所有货位的有无情况(EmptyCheck03): EC03 由我们发送 + * 4.盘点具体货位(StockCheck01): SC01 + * 5.取货完成(StockCheck02): SC02 + * 6.具体货位盘点 数据采集完成(StockCheck03): SC03 由我们发送 + * 7.盘点信息返回(StockCheck04): SC04 由我们发送 + * 8.入库指令 取货到载货台拍顶部照片(IntoStock01) : IS01 + * 9.入库指令 顶部拍照完成(IntoStock02): IS02 由我们发送 + * 10.入库指令 放货完成,拍照、扫码触发指令(IntoStock03): IS03 + * 11.入库指令 放货完成后拍照片扫码完成(IntoStock04) :IS04 由我们发送 + * 12.心跳(HeartBeat) : HB + */ + public static String EMPTY_CHECK_01 = "EC01"; + public static String EMPTY_CHECK_02 = "EC02"; + public static String EMPTY_CHECK_03 = "EC03"; + public static String STOCK_CHECK_01 = "SC01"; + public static String STOCK_CHECK_02 = "SC02"; + public static String STOCK_CHECK_03 = "SC03"; + public static String STOCK_CHECK_04 = "SC04"; + public static String Into_Stock_01 = "IS01"; + public static String Into_Stock_02 = "IS02"; + public static String Into_Stock_03 = "IS03"; + public static String Into_Stock_04 = "IS04"; + + private String FlowControl; + + private String Type; + + private String Content; + + public String toString(){ + return FlowControl + SPLIT + Type + SPLIT + Content + END_STRING; + } + + public PTData(String data){ + String[] strings = data.split(SPLIT); + FlowControl = strings[0]; + Type = strings[1]; + Content = strings[2]; + } + + public static PTData HeartBeat(){ + PTData ptData = new PTData(); + ptData.setFlowControl("."); + ptData.setType(HEART_TYPE); + ptData.setContent("HeartBeat"); + return ptData; + } + + + + +} diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PTDecoder.java b/web/src/main/java/com/zhehekeji/web/service/putian/PTDecoder.java new file mode 100644 index 0000000..de156db --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTDecoder.java @@ -0,0 +1,78 @@ +package com.zhehekeji.web.service.putian; + +import com.zhehekeji.web.service.EmptyCheckService; +import com.zhehekeji.web.service.client.ClientChanel; +import com.zhehekeji.web.service.client.ECTransmission; +import com.zhehekeji.web.service.ksec.KsecDecoder; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.LineBasedFrameDecoder; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.Charset; + +@Slf4j +public class PTDecoder extends LineBasedFrameDecoder { + + private static final Logger tcpLogger = LoggerFactory.getLogger("tcp"); + + private EmptyCheckService emptyCheckService; + + + /** + * failFast 与 maxLength 需要搭配使用,通过设置 failFast 可以控制抛出 TooLongFrameException 的时机, + * 可以说 Netty 在细节上考虑得面面俱到。如果 failFast=true,那么在超出 maxLength 会立即抛出 TooLongFrameException,不再继续进行解码。 + * 如果 failFast=false,那么会等到解码出一个完整的消息后才会抛出 TooLongFrameException。 + * @param maxLength + * @param stripDelimiter true:解析出的数据包不带换行符 + * @param failFast + */ + public PTDecoder(int maxLength, boolean stripDelimiter, boolean failFast) { + super(maxLength, stripDelimiter, failFast); + } + + protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { + in = (ByteBuf) super.decode(ctx, in); + if(in != null){ + String body = in.toString(Charset.forName("UTF-8")); + tcpLogger.info(body); + PTData ptData = new PTData(body); + + if(ptData.getType().equals(PTData.HEART_TYPE)){ + //心跳 什么都不处理,因为netty长链接,断开会感知 + }else if(ptData.getType().equals(PTData.EMPTY_CHECK_01)){ + log.info("空货位检测开始"); + + PTEmptyCheckContent checkContent = PTEmptyCheckContent.EmptyCheck(body); + emptyCheckService.emptyCheckStart(checkContent.getSRMNUmber(), checkContent.getTaskNo(), checkContent.getRow()); + String startEmptyCheckStr = ECTransmission.toEmptyCheckStartString(checkContent.getSRMNUmber()); + //通知客户端开始检测 + ClientChanel.write(startEmptyCheckStr,checkContent.getSRMNUmber()); + }else if(ptData.getType().equals(PTData.EMPTY_CHECK_02)){ + log.info("空货位检测结束"); + PTEmptyCheckContent checkContent = PTEmptyCheckContent.EmptyCheck(body); + String endEmptyCheckStr = ECTransmission.toEmptyCheckEndString(checkContent.getSRMNUmber()); + //通知客户端结束检测 + ClientChanel.write(endEmptyCheckStr,checkContent.getSRMNUmber()); + //等待3s把空货位盘点的结果发给普天 + //todo + emptyCheckService.getEmptyStatus(checkContent.getSRMNUmber(),checkContent.getTaskNo(),1,1,checkContent.getRow()); + + }else if(ptData.getType().equals(PTData.STOCK_CHECK_01)){ + log.info("盘点具体货位"); + + }else if(ptData.getType().equals(PTData.STOCK_CHECK_02)){ + log.info("盘点具体货位 ,货物已取到载货台"); + + }else { + log.info("未知的盘点指令:{}",ptData.getType()); + } + } + return null; + + } + + +} diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PTEmptyCheckContent.java b/web/src/main/java/com/zhehekeji/web/service/putian/PTEmptyCheckContent.java new file mode 100644 index 0000000..6c865fd --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTEmptyCheckContent.java @@ -0,0 +1,52 @@ +package com.zhehekeji.web.service.putian; + +import lombok.Data; + +/** + * 空货位盘点开始(EC01)报文内容(普天发送): + * 巷道标识,盘点批次号,层数,开始列,结束列,START + * 举例:SRM001,202209081122,1,1,5,START + * 空货位盘点结束(EC02)报文内容(普天发送): + * 巷道标识,盘点批次号,层数,开始列,结束列,END + * 举例:SRM001,202209081122,1,1,5,END + * 返回是否空货位(EC03)(易高发送): + * 巷道标识,盘点批次号,层数,开始列,结束列,货架,开始列到结束列按顺序的有无情况(1:有,0:无) + * 货架:{左右}{深浅} 例如L01表示左侧浅货位,R02表示右侧深货位 + * 举例:SRM001,202209081122,1,1,5,L01,10111 + * @return + */ +@Data +public class PTEmptyCheckContent { + + private String SRMNUmber; + + private String goodsLocation; + + private String taskNo; + + private Integer num; + + private Integer row; + + private Integer startColumn; + + private Integer endColumn; + + /** + * Start OR END + */ + private String type; + + + public static PTEmptyCheckContent EmptyCheck(String data){ + PTEmptyCheckContent ptContent = new PTEmptyCheckContent(); + String [] strings = data.split(","); + ptContent.setSRMNUmber(strings[0]); + ptContent.setTaskNo(strings[1]); + ptContent.setRow(Integer.valueOf(strings[2])); + ptContent.setStartColumn(Integer.valueOf(strings[3])); + ptContent.setEndColumn(Integer.valueOf(strings[4])); + ptContent.setType(strings[5]); + return ptContent; + } +} diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PTFilter.java b/web/src/main/java/com/zhehekeji/web/service/putian/PTFilter.java new file mode 100644 index 0000000..80cbc15 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTFilter.java @@ -0,0 +1,41 @@ +package com.zhehekeji.web.service.putian; + +import com.zhehekeji.web.service.PlcService; +import com.zhehekeji.web.service.ksec.*; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.timeout.IdleStateHandler; + +import java.util.concurrent.TimeUnit; + +/** + * 普天编解码和心跳的设置 + * + * @author Administrator + * + */ +public class PTFilter extends ChannelInitializer { + + private PlcService plcService; + + private PuTianNettyClient nettyClient; + + public PTFilter(PlcService plcService, PuTianNettyClient nettyClient){ + this.plcService = plcService; + this.nettyClient = nettyClient; + } + + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline ph = ch.pipeline(); + //30秒发一次心跳 + ph.addLast(new IdleStateHandler(0, 30, 0, TimeUnit.SECONDS)); + ByteBuf byteBuf = Unpooled.copiedBuffer(">".getBytes()); + ph.addLast(new PTDecoder(1000,false,true)); + ph.addLast(new PtEncoder()); + ph.addLast(new PTNettyHandler(nettyClient)); + } +} diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PTNettyHandler.java b/web/src/main/java/com/zhehekeji/web/service/putian/PTNettyHandler.java new file mode 100644 index 0000000..16a24a9 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTNettyHandler.java @@ -0,0 +1,65 @@ +package com.zhehekeji.web.service.putian; + +import com.zhehekeji.web.service.StreetConn; +import com.zhehekeji.web.service.ksec.KsecInfo; +import com.zhehekeji.web.service.ksec.KsecNettyClient; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.timeout.IdleStateEvent; +import lombok.extern.slf4j.Slf4j; + +/** + * 与PLC心跳 处理 + * + * @author Administrator + * + */ +@Slf4j +public class PTNettyHandler extends ChannelInboundHandlerAdapter { + /** 客户端请求的心跳命令 */ + private PTData heart; + + private PuTianNettyClient nettyClient; + + public PTNettyHandler(PuTianNettyClient nettyClient){ + this.nettyClient = nettyClient; +// this.heart = new PTData(); +// this.heart.setContent(""); + } + + /** + * 建立连接时 + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + log.info("upPc connected "); + StreetConn.conn(1); + ctx.fireChannelActive(); + } + + /** + * 关闭连接时 + */ + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + log.info("upPc closed"); + StreetConn.disConn(1); + log.info(" streetId reconnect......"); + nettyClient.reconnect(1); + } + + /** + * 心跳请求处理,每4秒发送一次心跳请求; + * + */ + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception { + if (obj instanceof IdleStateEvent) { + log.debug("upPc send heart"); + ctx.channel().writeAndFlush(heart); + } + + } + + +} diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PtEncoder.java b/web/src/main/java/com/zhehekeji/web/service/putian/PtEncoder.java new file mode 100644 index 0000000..f05eae6 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PtEncoder.java @@ -0,0 +1,19 @@ +package com.zhehekeji.web.service.putian; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +import java.nio.charset.StandardCharsets; + +/** + * 普天发送TCP数据 + */ +public class PtEncoder extends MessageToByteEncoder { + + @Override + protected void encode(ChannelHandlerContext channelHandlerContext, PTData data, ByteBuf byteBuf) throws Exception { + String body = data.toString(); + byteBuf.writeBytes(body.getBytes(StandardCharsets.UTF_8)); + } +} diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PuTianNettyClient.java b/web/src/main/java/com/zhehekeji/web/service/putian/PuTianNettyClient.java new file mode 100644 index 0000000..ee4b2da --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PuTianNettyClient.java @@ -0,0 +1,95 @@ +package com.zhehekeji.web.service.putian; + +import com.zhehekeji.web.config.ConfigProperties; +import com.zhehekeji.web.service.PlcService; +import com.zhehekeji.web.service.client.Decoder; +import com.zhehekeji.web.service.client.Encoder; +import com.zhehekeji.web.service.ksec.KescFilter; +import com.zhehekeji.web.service.ksec.KsecInfo; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.annotation.Resource; + +@Slf4j +@Component +public class PuTianNettyClient { + + private static EventLoopGroup group = new NioEventLoopGroup(); + @Resource + private PlcService plcService; + @Resource + private ConfigProperties configProperties; + + /** + * 重连最大次数 + */ + private static int RECONNECT_NUM = 10; + + private static Channel channel; + + public void createClient(ConfigProperties.KSEC ksec) throws InterruptedException { + if (StringUtils.isEmpty(ksec.getIp()) || ksec.getPort() == null) { + return; + } + Bootstrap client = new Bootstrap(); + client.group(group); + client.channel(NioSocketChannel.class); + client.handler(new PTNettyHandler(this)); + // 连接服务端 + channel = client.connect(ksec.getIp(), ksec.getPort()).sync().channel(); + } + + /** + * 断线重连 尝试 RECONNECT_NUM 次 + * + * @param upId + */ + public void reconnect(Integer upId) { + Boolean isConnected = false; + int num = 0; + ConfigProperties.KSEC ksec = configProperties.getKsec(); + if (ksec == null) { + log.error("reconnect ,upPc is null ,id:{}", upId); + return; + } + try { + Thread.sleep(1500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + while (num < RECONNECT_NUM && !isConnected) { + try { + createClient(ksec); + } catch (Exception e) { + //没连上 继续 + log.error("reconnect error num:{}", num); + num++; + continue; + } + isConnected = true; + } + if (isConnected) { + log.info("plc reconnect success"); + } else { + log.error("plc reconnect error .upPcId:{},reconnect num:{},ip:{},port:{}", upId, num, ksec.getIp(), ksec.getPort()); + } + } + + public static void write(KsecInfo ksecInfo){ + if(channel != null){ + channel.writeAndFlush(ksecInfo); + }else { + log.error(" no connected upPc"); + } + + } +}