diff --git a/web/src/main/java/com/zhehekeji/web/controller/StockController.java b/web/src/main/java/com/zhehekeji/web/controller/StockController.java index 99fb632..3953d00 100644 --- a/web/src/main/java/com/zhehekeji/web/controller/StockController.java +++ b/web/src/main/java/com/zhehekeji/web/controller/StockController.java @@ -141,14 +141,4 @@ public class StockController { return Result.success(stockService.checkByMan(checkByMan)); } - public static void main(String[] args) { - String s = "4"; - String ss = String.format("%03d", 4); - System.out.println(ss); - - String bb = "10"; - String bbb = String.format("%03d", 10); - System.out.println(bbb); - } - } diff --git a/web/src/main/java/com/zhehekeji/web/service/PlcService.java b/web/src/main/java/com/zhehekeji/web/service/PlcService.java index 271c5f7..16797af 100644 --- a/web/src/main/java/com/zhehekeji/web/service/PlcService.java +++ b/web/src/main/java/com/zhehekeji/web/service/PlcService.java @@ -10,7 +10,9 @@ import com.zhehekeji.web.pojo.OrderVO; import com.zhehekeji.web.service.RFID.RFIDMap; import com.zhehekeji.web.service.RFID.RFIDSocket; import com.zhehekeji.web.service.client.TMTransmission; +import com.zhehekeji.web.service.putian.PTCheckContent; import lombok.extern.slf4j.Slf4j; +import org.aspectj.weaver.ast.Or; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; 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 e62e61c..decf61e 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,7 +1,10 @@ package com.zhehekeji.web.service.client; +import com.zhehekeji.web.entity.Stock; import com.zhehekeji.web.service.EmptyCheckService; import com.zhehekeji.web.service.PlcService; +import com.zhehekeji.web.service.putian.PTData; +import com.zhehekeji.web.service.putian.PuTianNettyClient; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -11,6 +14,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.charset.Charset; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * 客户端解码器 连接用 @@ -20,6 +26,8 @@ public class Decoder extends DelimiterBasedFrameDecoder { private static final Logger tcpLogger = LoggerFactory.getLogger("tcp"); + private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(7,21,30, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(20000)); + private EmptyCheckService emptyCheckService; private PlcService plcService; @@ -36,55 +44,82 @@ public class Decoder extends DelimiterBasedFrameDecoder { log.debug("no data"); 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); - //回复客户端心跳 - ctx.channel().writeAndFlush(hbTransmission.toString()); - tcpLogger.info("client:{} heart", hbTransmission.getSRMNumber()); - in.release(); - } else if(body.startsWith(TMTransmission.getHeader())){ - //盘点指令 - TMTransmission tmTransmission = new TMTransmission(body); - if(tmTransmission.isCollectOver()){ - //todo 给普天发送指令 把盘点结果告诉普天 - //收到盘点结果 - plcService.checkEnd(tmTransmission); - //添加到实时信息里 - RealtimeCheckMap.put(tmTransmission.getSRMNumber(),tmTransmission.checkInfo()); - }else { - //开始盘点 - plcService.checkStart(tmTransmission); - } - in.release(); - }else if(body.startsWith(CETransmission.getHEADER())){ - //客户端建立连接 - CETransmission ceTransmission = new CETransmission(body); - //回复客户端,建立连接完成 - ctx.channel().writeAndFlush(ceTransmission.toString()); - ClientChanel.connect(ceTransmission.getSRMNumber(), ctx.channel()); - tcpLogger.info("client:{} connect", ceTransmission.getSRMNumber()); - in.release(); - }else if(body.startsWith(ECTransmission.getHEADER())){ - //空货位盘点 - ECTransmission ecTransmission = new ECTransmission(body); - //保存空货位条码 - EmptyCheckCodeInfo.addCode(ecTransmission.getSRMNumber(),ecTransmission.getRow(),ecTransmission.getStartColumn(), ecTransmission.getEndColumn(), ecTransmission.getOriginCode()); - //保存空货位信息 - emptyCheckService.emptyCheckLog(ecTransmission); - in.release(); - }else if(body.startsWith("DC")){ - //客户端断开连接 - String [] strings = body.split(","); - if(strings != null && strings.length == 2){ - tcpLogger.info("client:{} disConnect", strings[1]); - ClientChanel.disConnect(strings[1]); + ClientRunnable clientRunnable = new ClientRunnable(in,ctx,plcService,emptyCheckService); + threadPoolExecutor.execute(clientRunnable); + return null; + } + + public static class ClientRunnable implements Runnable { + + private ByteBuf in; + + private ChannelHandlerContext ctx; + + private PlcService plcService; + + private EmptyCheckService emptyCheckService; + + public ClientRunnable(ByteBuf in,ChannelHandlerContext ctx,PlcService plcService,EmptyCheckService emptyCheckService){ + this.ctx = ctx; + this.in = in; + this.plcService = plcService; + this.emptyCheckService = emptyCheckService; + } + + @Override + public void run() { + String body = in.toString(Charset.forName("UTF-8")); + tcpLogger.info("client rece:{}",body); + if(body.startsWith(HBTransmission.getHEADER())) { + //心跳 + HBTransmission hbTransmission = new HBTransmission(body); + //回复客户端心跳 + ctx.channel().writeAndFlush(hbTransmission.toString()); + tcpLogger.info("client:{} heart", hbTransmission.getSRMNumber()); + in.release(); + } else if(body.startsWith(TMTransmission.getHeader())){ + //盘点指令 + TMTransmission tmTransmission = new TMTransmission(body); + if(tmTransmission.isCollectOver()){ + //给普天发送数据采集完毕指令 + PTData ptData = PTData.StockCheck03(tmTransmission.getSRMNumber(),tmTransmission.getTaskNo(),tmTransmission.getGoodsLocation(),"Y"); + PuTianNettyClient.write(ptData); + }else { + //收到盘点结果 + Stock stock = plcService.checkEnd(tmTransmission); + //将盘点结果发给普天 + PTData ptData = PTData.StockCheck04(tmTransmission.getSRMNumber(),tmTransmission.getTaskNo(),tmTransmission.getGoodsLocation(),stock.getCode(),stock.getCount()); + PuTianNettyClient.write(ptData); + //添加到实时信息里 + RealtimeCheckMap.put(tmTransmission.getSRMNumber(),tmTransmission.checkInfo()); + } + in.release(); + }else if(body.startsWith(CETransmission.getHEADER())){ + //客户端建立连接 + CETransmission ceTransmission = new CETransmission(body); + //回复客户端,建立连接完成 + ctx.channel().writeAndFlush(ceTransmission.toString()); + ClientChanel.connect(ceTransmission.getSRMNumber(), ctx.channel()); + tcpLogger.info("client:{} connect", ceTransmission.getSRMNumber()); + in.release(); + }else if(body.startsWith(ECTransmission.getHEADER())){ + //空货位盘点 + ECTransmission ecTransmission = new ECTransmission(body); + //保存空货位条码 + EmptyCheckCodeInfo.addCode(ecTransmission.getSRMNumber(),ecTransmission.getRow(),ecTransmission.getStartColumn(), ecTransmission.getEndColumn(), ecTransmission.getOriginCode()); + //保存空货位信息 + emptyCheckService.emptyCheckLog(ecTransmission); + in.release(); + }else if(body.startsWith("DC")){ + //客户端断开连接 + String [] strings = body.split(","); + if(strings != null && strings.length == 2){ + tcpLogger.info("client:{} disConnect", strings[1]); + ClientChanel.disConnect(strings[1]); + } + in.release(); } - in.release(); } - return null; } } diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PTCheckContent.java b/web/src/main/java/com/zhehekeji/web/service/putian/PTCheckContent.java new file mode 100644 index 0000000..a206edd --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTCheckContent.java @@ -0,0 +1,45 @@ +package com.zhehekeji.web.service.putian; + +import lombok.Data; + +@Data +public class PTCheckContent { + private String SRMNUmber; + + private String goodsLocation; + + private String taskNo; + + private String code; + + private Integer count; + + /** + * 盘点具体货位(SC01) + * @param data + * @return + */ + public static PTCheckContent CheckContentSC01(String data){ + PTCheckContent ptContent = new PTCheckContent(); + String [] strings = data.split(","); + ptContent.setSRMNUmber(strings[0]); + ptContent.setTaskNo(strings[1]); + ptContent.setGoodsLocation(strings[2]); + ptContent.setCode(strings[3]); + ptContent.setCount(Integer.valueOf(strings[4])); + return ptContent; + } + + /** + * 取货完成,将货物取到载货台后 + * @param data + * @return + */ + public static PTCheckContent CheckContentSC02(String data){ + PTCheckContent ptContent = new PTCheckContent(); + String [] strings = data.split(","); + ptContent.setSRMNUmber(strings[0]); + ptContent.setTaskNo(strings[1]); + return ptContent; + } +} 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 index a2f1527..f3adb75 100644 --- a/web/src/main/java/com/zhehekeji/web/service/putian/PTData.java +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTData.java @@ -89,6 +89,29 @@ public class PTData { return ptData; } + public static PTData StockCheck03(String SRMNumber,String taskId,String goodsLocation,String YN){ + StringBuffer contentSB = new StringBuffer(); + contentSB.append(SRMNumber).append(",").append(taskId).append(",").append(goodsLocation).append(",").append(YN); + PTData ptData = new PTData(contentSB.toString(),FLOW_NO_NEED_RES,STOCK_CHECK_03); + return ptData; + } + + /** + * 盘点结果 + * @param SRMNumber + * @param taskId + * @param goodsLocation + * @param code 品规 + * @param count 数量 + * @return + */ + public static PTData StockCheck04(String SRMNumber,String taskId,String goodsLocation,String code,Integer count){ + StringBuffer contentSB = new StringBuffer(); + contentSB.append(SRMNumber).append(",").append(taskId).append(",").append(goodsLocation).append(",").append(code).append(",").append(count); + PTData ptData = new PTData(contentSB.toString(),FLOW_NO_NEED_RES,STOCK_CHECK_04); + return ptData; + } + public static PTData EmptyStatusResponse(PTEmptyCheckContent ptEmptyCheckContent){ return new PTData(ptEmptyCheckContent.toResponseString(),FLOW_NO_NEED_RES,EMPTY_CHECK_03); } 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 index 98f4067..168dfa9 100644 --- a/web/src/main/java/com/zhehekeji/web/service/putian/PTDecoder.java +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTDecoder.java @@ -1,19 +1,22 @@ 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.client.EmptyCheckCodeInfo; +import com.zhehekeji.web.service.PlcService; +import com.zhehekeji.web.service.client.*; 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.apache.poi.ss.formula.functions.T; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.charset.Charset; import java.util.Set; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; @Slf4j public class PTDecoder extends LineBasedFrameDecoder { @@ -22,6 +25,10 @@ public class PTDecoder extends LineBasedFrameDecoder { private EmptyCheckService emptyCheckService; + private PlcService plcService; + + private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(7,21,30, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(20000)); + /** * failFast 与 maxLength 需要搭配使用,通过设置 failFast 可以控制抛出 TooLongFrameException 的时机, @@ -31,14 +38,40 @@ public class PTDecoder extends LineBasedFrameDecoder { * @param stripDelimiter true:解析出的数据包不带换行符 * @param failFast */ - public PTDecoder(int maxLength, boolean stripDelimiter, boolean failFast,EmptyCheckService emptyCheckService) { + public PTDecoder(int maxLength, boolean stripDelimiter, boolean failFast,EmptyCheckService emptyCheckService,PlcService plcService) { super(maxLength, stripDelimiter, failFast); this.emptyCheckService = emptyCheckService; + this.plcService = plcService; } protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception { in = (ByteBuf) super.decode(ctx, in); - if(in != null){ + if(in == null){ + log.debug("no data"); + }else { + PTRunnable ptRunnable = new PTRunnable(ctx,in,emptyCheckService,plcService); + threadPoolExecutor.execute(ptRunnable); + } + return null; + + } + + public static class PTRunnable implements Runnable{ + + private ChannelHandlerContext ctx; + private ByteBuf in; + private EmptyCheckService emptyCheckService; + private PlcService plcService; + + public PTRunnable(ChannelHandlerContext ctx, ByteBuf in,EmptyCheckService emptyCheckService,PlcService plcService){ + this.ctx = ctx; + this.in = in; + this.emptyCheckService = emptyCheckService; + this.plcService = plcService; + } + + @Override + public void run() { String body = in.toString(Charset.forName("UTF-8")); tcpLogger.info("received from PT:{}",body); PTData ptData = new PTData(body); @@ -60,34 +93,64 @@ public class PTDecoder extends LineBasedFrameDecoder { String endEmptyCheckStr = ECTransmission.toEmptyCheckEndString(checkContent.getSRMNUmber(),checkContent.getTaskNo(),checkContent.getRow(),checkContent.getStartColumn(),checkContent.getEndColumn()); //通知客户端结束检测 ClientChanel.write(endEmptyCheckStr,checkContent.getSRMNUmber()); - //等待3s把空货位盘点的结果发给普天 - //todo - - emptyCheckService.getEmptyStatus(checkContent.getSRMNUmber(),checkContent.getTaskNo(),1,1,checkContent.getRow(),checkContent.getStartColumn(),checkContent.getEndColumn()); + //等待3s把空货位盘点的结果发给普天 + String res = emptyCheckService.getEmptyStatus(checkContent.getSRMNUmber(),checkContent.getTaskNo(),1,1,checkContent.getRow(),checkContent.getStartColumn(),checkContent.getEndColumn()); //打印空货位的所有条码 Set codes = EmptyCheckCodeInfo.getAllCode(checkContent.getSRMNUmber(),checkContent.getRow(),checkContent.getStartColumn(),checkContent.getEndColumn()); log.info("【空货位扫描到的所有条码】,SRMNumber:{},row:{},startColumn:{},endColumn:{},taskId:{},\ncodes:{}",checkContent.getSRMNUmber(),checkContent.getRow(),checkContent.getStartColumn(),checkContent.getEndColumn(),checkContent.getTaskNo(),codes); //清空所有的条码 EmptyCheckCodeInfo.stop(checkContent.getSRMNUmber(),checkContent.getRow(),checkContent.getStartColumn(),checkContent.getEndColumn()); - + //返回普天该行的盘点结果 + checkContent.setEmptyStatus(res); + PuTianNettyClient.write(PTData.EmptyStatusResponse(checkContent)); }else if(ptData.getType().equals(PTData.STOCK_CHECK_01)){ log.info("盘点具体货位"); - + //发送给客户端 + PTCheckContent ptCheckContent = PTCheckContent.CheckContentSC01(ptData.getContent()); + TMTransmission tmTransmission = new TMTransmission(ptCheckContent.getSRMNUmber(),ptCheckContent.getTaskNo(),ptCheckContent.getGoodsLocation(),ptCheckContent.getCode(), ptCheckContent.getCount(), "N"); + plcService.checkStart(tmTransmission); + String msg = tmTransmission.toString(); + ClientChanel.write(msg,ptCheckContent.getSRMNUmber()); }else if(ptData.getType().equals(PTData.STOCK_CHECK_02)){ log.info("盘点具体货位 ,货物已取到载货台"); - + PTCheckContent ptCheckContent = PTCheckContent.CheckContentSC02(ptData.getContent()); + TMTransmission tmTransmission = new TMTransmission(ptCheckContent.getSRMNUmber(),ptCheckContent.getTaskNo()); + String msg = tmTransmission.toSC02String(); + ClientChanel.write(msg,ptCheckContent.getSRMNUmber()); }else if(ptData.getType().equals(PTData.Into_Stock_01)){ log.info("入库顶部拍照"); - + //保存order标表 + PTOrderContent ptOrderContent = PTOrderContent.OrderContentIS01And03(ptData.getContent()); + String picPath = plcService.IntoStock(ptOrderContent.getSRMNUmber(), ptOrderContent.getTaskNo(), ptOrderContent.getGoodsLocation()); + //返回普天 + PTData resData = PTData.IntoStock(ptOrderContent.getSRMNUmber(), ptOrderContent.getTaskNo(), ptOrderContent.getGoodsLocation(),picPath); + PuTianNettyClient.write(resData); }else if(ptData.getType().equals(PTData.Into_Stock_02)){ log.info("入库完成拍照"); - - + PTOrderContent ptOrderContent = PTOrderContent.OrderContentIS01And03(ptData.getContent()); + String picPath = plcService.IntoStockOver(ptOrderContent.getSRMNUmber(), ptOrderContent.getTaskNo(), ptOrderContent.getGoodsLocation()); + + //向客户端发送读码指令,等待客户端返回条码 + ISTransmission isTransmission = new ISTransmission(ptOrderContent.getSRMNUmber(), ptOrderContent.getTaskNo(), ptOrderContent.getGoodsLocation()); + //为防万一,先清除code + ClientCodeMap.removeCode(ptOrderContent.getSRMNUmber()); + ClientChanel.write(isTransmission.toString(),ptOrderContent.getSRMNUmber()); + //发送结果给普天 + //若1分钟内仍为收到 则放弃 + Long start = System.currentTimeMillis(); + while (ClientCodeMap.getCode(ptOrderContent.getSRMNUmber()) == null && (System.currentTimeMillis()-start)<60000){ + try { + Thread.sleep(300l); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + String code = ClientCodeMap.getCode(ptOrderContent.getSRMNUmber()); + PTData resData = PTData.IntoStock04(ptOrderContent.getSRMNUmber(), ptOrderContent.getTaskNo(), ptOrderContent.getGoodsLocation(),picPath,code); + PuTianNettyClient.write(resData); } } - return null; - } diff --git a/web/src/main/java/com/zhehekeji/web/service/putian/PTOrderContent.java b/web/src/main/java/com/zhehekeji/web/service/putian/PTOrderContent.java new file mode 100644 index 0000000..9624f56 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/putian/PTOrderContent.java @@ -0,0 +1,34 @@ +package com.zhehekeji.web.service.putian; + +import lombok.Data; + +@Data +public class PTOrderContent { + + private String SRMNUmber; + + private String goodsLocation; + + private String taskNo; + + private String pics; + + private String scanRowAndColumn; + + /** + * 货位入库顶部拍照(IS01) + * 货位入库完成 拍照、扫码触发指令(IS03) + * @param data + * @return + */ + public static PTOrderContent OrderContentIS01And03(String data){ + PTOrderContent ptContent = new PTOrderContent(); + String [] strings = data.split(","); + ptContent.setSRMNUmber(strings[0]); + ptContent.setTaskNo(strings[1]); + ptContent.setGoodsLocation(strings[2]); + return ptContent; + } + + +}