From 1e7c3cd274472f824368c71ce99e32c916969106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?LAPTOP-S9HJSOEB=5C=E6=98=8A=E5=A4=A9?= Date: Tue, 18 Apr 2023 10:48:36 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=BC=80=E5=90=AF=E7=BA=BF=E7=A8=8B=E6=B1=A0?= =?UTF-8?q?=202.websocket=E5=90=8E=E5=8F=B0=E5=AE=9E=E7=8E=B0=203.?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E4=B8=AA=E7=9B=98=E7=82=B9=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=204.=E6=9A=82=E6=97=B6=E5=85=B3=E9=97=AD=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E5=85=89=E6=BA=90=E7=8A=B6=E6=80=81=EF=BC=88=E4=BC=9A=E6=8A=A5?= =?UTF-8?q?=E9=94=99=EF=BC=89=205.=E5=B7=B7=E9=81=93=E5=90=8D=E7=94=B1?= =?UTF-8?q?=E5=90=8E=E7=AB=AF=E8=8E=B7=E5=8F=96=EF=BC=8C=E4=BF=9D=E8=AF=81?= =?UTF-8?q?=E5=89=8D=E6=AE=B5=E9=80=9A=E7=94=A8=E6=80=A7=206.=E7=9B=98?= =?UTF-8?q?=E7=82=B9=E5=8E=86=E5=8F=B2=E5=80=92=E5=BA=8F=207.=E7=9B=98?= =?UTF-8?q?=E7=82=B9=E5=B7=A6=E5=8F=B3=E6=96=B9=E5=90=91=E9=94=99=E8=AF=AF?= =?UTF-8?q?=208.stock=E4=BD=BF=E7=94=A8builder=E5=BB=BA=E9=80=A0=E5=99=A8?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=AF=E8=A7=86=E5=8C=96=209.=E6=96=AD?= =?UTF-8?q?=E7=BB=AD=E9=87=8D=E8=BF=9E=E5=A2=9E=E5=8A=A0=E4=B8=8D=E6=96=AD?= =?UTF-8?q?=E9=87=8D=E8=BF=9E=2010.=E5=A4=A9=E7=BA=BF=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=EF=BC=8C=E4=B8=8D=E5=86=8D=E4=B8=A4=E4=B8=AA=E6=96=B9=E5=90=91?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E6=89=AB=E6=8F=8F=2011.=E5=A2=9E=E5=8A=A0rfi?= =?UTF-8?q?dlog=E5=92=8Crfidlive=EF=BC=8C=E4=BF=9D=E8=AF=81=E5=90=8E?= =?UTF-8?q?=E7=BB=AD=E6=B7=B1=E8=B4=A7=E4=BD=8D=E5=8F=AF=E4=BB=A5=E9=80=BB?= =?UTF-8?q?=E8=BE=91rfid=E6=89=AB=E6=8F=8F(=E5=BE=85=E6=B5=8B=E8=AF=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/pom.xml | 7 +- .../web/config/ConfigProperties.java | 18 +++ .../zhehekeji/web/config/ExecutorConfig.java | 41 +++++ .../zhehekeji/web/config/WebSocketConfig.java | 17 ++ .../web/controller/StockController.java | 7 + .../web/controller/StreetController.java | 5 +- .../com/zhehekeji/web/entity/CheckLog.java | 2 - .../com/zhehekeji/web/entity/RfidLive.java | 27 ++++ .../com/zhehekeji/web/entity/RfidLog.java | 30 ++++ .../java/com/zhehekeji/web/entity/Stock.java | 5 + .../zhehekeji/web/mapper/RfidLiveMapper.java | 8 + .../zhehekeji/web/mapper/RfidLogMapper.java | 8 + .../web/pojo/websocket/WebSocketVo.java | 18 +++ .../web/service/CheckLogService.java | 9 +- .../com/zhehekeji/web/service/PlcCmdInfo.java | 3 + .../com/zhehekeji/web/service/PlcService.java | 70 ++++++-- .../web/service/RFID/RFIDSocket.java | 8 +- .../zhehekeji/web/service/RFIDService.java | 6 +- .../web/service/StockCheckRunnable.java | 17 +- .../zhehekeji/web/service/StockService.java | 38 ++++- .../web/service/impl/RfidLiveServiceImpl.java | 108 +++++++++++++ .../web/service/impl/RfidLogServiceImpl.java | 11 ++ .../service/interfaces/RfidLiveService.java | 10 ++ .../service/interfaces/RfidLogService.java | 7 + .../web/service/ksec/KsecDecoder.java | 12 +- .../web/service/ksec/KsecNettyClient.java | 13 +- .../zhehekeji/web/test/client/MyClient.java | 40 +++++ .../web/test/client/MyClientHandler.java | 23 +++ .../zhehekeji/web/test/server/MyServer.java | 44 +++++ .../web/test/server/MyServerHandler.java | 39 +++++ .../java/com/zhehekeji/web/util/ToolUtil.java | 35 ++++ .../com/zhehekeji/web/ws/WebSocketServer.java | 151 ++++++++++++++++++ web/src/main/resources/application-test.yml | 12 +- 33 files changed, 810 insertions(+), 39 deletions(-) create mode 100644 web/src/main/java/com/zhehekeji/web/config/ExecutorConfig.java create mode 100644 web/src/main/java/com/zhehekeji/web/config/WebSocketConfig.java create mode 100644 web/src/main/java/com/zhehekeji/web/entity/RfidLive.java create mode 100644 web/src/main/java/com/zhehekeji/web/entity/RfidLog.java create mode 100644 web/src/main/java/com/zhehekeji/web/mapper/RfidLiveMapper.java create mode 100644 web/src/main/java/com/zhehekeji/web/mapper/RfidLogMapper.java create mode 100644 web/src/main/java/com/zhehekeji/web/pojo/websocket/WebSocketVo.java create mode 100644 web/src/main/java/com/zhehekeji/web/service/impl/RfidLiveServiceImpl.java create mode 100644 web/src/main/java/com/zhehekeji/web/service/impl/RfidLogServiceImpl.java create mode 100644 web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLiveService.java create mode 100644 web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLogService.java create mode 100644 web/src/main/java/com/zhehekeji/web/test/client/MyClient.java create mode 100644 web/src/main/java/com/zhehekeji/web/test/client/MyClientHandler.java create mode 100644 web/src/main/java/com/zhehekeji/web/test/server/MyServer.java create mode 100644 web/src/main/java/com/zhehekeji/web/test/server/MyServerHandler.java create mode 100644 web/src/main/java/com/zhehekeji/web/util/ToolUtil.java create mode 100644 web/src/main/java/com/zhehekeji/web/ws/WebSocketServer.java diff --git a/web/pom.xml b/web/pom.xml index 90169b6..899155c 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -18,7 +18,12 @@ - + + + org.springframework.boot + spring-boot-starter-websocket + 2.3.1.RELEASE + com.zhehekeji base-assembly diff --git a/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java b/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java index 62dc9fb..bd89652 100644 --- a/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java +++ b/web/src/main/java/com/zhehekeji/web/config/ConfigProperties.java @@ -1,5 +1,6 @@ package com.zhehekeji.web.config; +import io.lettuce.core.dynamic.annotation.Value; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -38,6 +39,21 @@ public class ConfigProperties { private ScanCodeMode scanCodeMode; private Rfid rfid; + private AsyncExecutorThread asyncExecutorThread; + + @Data + public static class AsyncExecutorThread{ + //# 异步线程配置 + //# 配置核心线程数 + private int corePoolSize = 5; + //# 配置最大线程数 + private int maxPoolSize = 70; + //# 配置队列大小 + private int queueCapacity = 99999; + //# 配置线程池中的线程的名称前缀 + private String namePrefix = "Thread_Pool_Task_Executor"; + } + @Data public static class Rfid { @@ -90,6 +106,8 @@ public class ConfigProperties { public static class KSEC{ private String ip; private Integer port; + private Integer reconnectNum = 10; + private Integer reconnectInterval = 10; } @Data diff --git a/web/src/main/java/com/zhehekeji/web/config/ExecutorConfig.java b/web/src/main/java/com/zhehekeji/web/config/ExecutorConfig.java new file mode 100644 index 0000000..e770b4a --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/config/ExecutorConfig.java @@ -0,0 +1,41 @@ +package com.zhehekeji.web.config; + +import io.lettuce.core.dynamic.annotation.Value; +import org.mybatis.logging.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import javax.annotation.Resource; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.logging.Logger; + +@Configuration +@EnableAsync +public class ExecutorConfig { + @Resource + ConfigProperties configProperties; + + + @Bean(name = "threadPoolTaskExecutor") + public ThreadPoolTaskExecutor threadPoolTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + //配置核心线程数 + executor.setCorePoolSize(configProperties.getAsyncExecutorThread().getCorePoolSize()); + //配置最大线程数 + executor.setMaxPoolSize(configProperties.getAsyncExecutorThread().getMaxPoolSize()); + //配置队列大小 + executor.setQueueCapacity(configProperties.getAsyncExecutorThread().getQueueCapacity()); + //配置线程池中的线程的名称前缀 + executor.setThreadNamePrefix(configProperties.getAsyncExecutorThread().getNamePrefix()); + + // rejection-policy:当pool已经达到max size的时候,如何处理新任务 + // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + //执行初始化 + executor.initialize(); + return executor; + } +} \ No newline at end of file diff --git a/web/src/main/java/com/zhehekeji/web/config/WebSocketConfig.java b/web/src/main/java/com/zhehekeji/web/config/WebSocketConfig.java new file mode 100644 index 0000000..da266fc --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/config/WebSocketConfig.java @@ -0,0 +1,17 @@ +package com.zhehekeji.web.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +@Configuration +public class WebSocketConfig { + /** + * 如果使用Springboot默认内置的tomcat容器,则必须注入ServerEndpoint的bean; + * 如果使用外置的web容器,则不需要提供ServerEndpointExporter,下面的注入可以注解掉 + */ + @Bean + public ServerEndpointExporter serverEndpointExporter(){ + return new ServerEndpointExporter(); + } +} 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..876a40c 100644 --- a/web/src/main/java/com/zhehekeji/web/controller/StockController.java +++ b/web/src/main/java/com/zhehekeji/web/controller/StockController.java @@ -114,6 +114,13 @@ public class StockController { return Result.success(stockService.stockInfo(stockCheck)); } + @ApiOperation(value = "下一个盘点信息") + @RequestMapping(value = "/nextOne", method = RequestMethod.POST) + public Result nextOne(@RequestBody Stock stock) { + return Result.success(stockService.nextOne(stock.getId())); + } + + @ApiOperation(value = "获取盘点信息") @RequestMapping(value = "/checkInfo", method = RequestMethod.POST) public Result checkInfo(@RequestBody StockCheckSearch stockCheck) { diff --git a/web/src/main/java/com/zhehekeji/web/controller/StreetController.java b/web/src/main/java/com/zhehekeji/web/controller/StreetController.java index aa1e52b..e3dbe9d 100644 --- a/web/src/main/java/com/zhehekeji/web/controller/StreetController.java +++ b/web/src/main/java/com/zhehekeji/web/controller/StreetController.java @@ -89,8 +89,9 @@ public class StreetController { JYDAMEquip equip = JYDamHelper.Connect(lightSource.getIp(),lightSource.getPort()); JYDamHelper.openDO(equip,configProperties.getLightSource().getIndex()); - Integer status = JYDamHelper.ReadStatus(equip,configProperties.getLightSource().getNum(),configProperties.getLightSource().getIndex()); - log.info("ip:{},status:{}",lightSource.getIp(),status); + //暂时关闭灯源状态查询 + /*Integer status = JYDamHelper.ReadStatus(equip,configProperties.getLightSource().getNum(),configProperties.getLightSource().getIndex()); + log.info("ip:{},status:{}",lightSource.getIp(),status);*/ equip.DisConnect(); }else if(configProperties.getLightSource().getType() == 2){ diff --git a/web/src/main/java/com/zhehekeji/web/entity/CheckLog.java b/web/src/main/java/com/zhehekeji/web/entity/CheckLog.java index 3e0fc3a..b72a074 100644 --- a/web/src/main/java/com/zhehekeji/web/entity/CheckLog.java +++ b/web/src/main/java/com/zhehekeji/web/entity/CheckLog.java @@ -12,8 +12,6 @@ import java.time.LocalDateTime; @Data public class CheckLog { - @TableId(type = IdType.AUTO) - private Long id; private Integer streetId; diff --git a/web/src/main/java/com/zhehekeji/web/entity/RfidLive.java b/web/src/main/java/com/zhehekeji/web/entity/RfidLive.java new file mode 100644 index 0000000..03f374c --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/entity/RfidLive.java @@ -0,0 +1,27 @@ +package com.zhehekeji.web.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName("rfid_live") +public class RfidLive { + + private String id; + private String wmsTrayCode; + private Integer streetId; + private Integer direction; + private Integer side; + private Integer row; + private Integer column; + private String rfidTrayCode; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + private Integer rfidId; + private String taskId; + +} diff --git a/web/src/main/java/com/zhehekeji/web/entity/RfidLog.java b/web/src/main/java/com/zhehekeji/web/entity/RfidLog.java new file mode 100644 index 0000000..5292404 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/entity/RfidLog.java @@ -0,0 +1,30 @@ +package com.zhehekeji.web.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.models.auth.In; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName("rfid_live") +public class RfidLog { + + + private String id; + private String wmsTrayCode; + private Integer street_id; + private Integer direction; + private Integer side; + private Integer row; + private Integer column; + private String rfidTrayCode; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime createTime; + private Integer rfidId; + private String taskId; + private Integer movement; + +} \ No newline at end of file diff --git a/web/src/main/java/com/zhehekeji/web/entity/Stock.java b/web/src/main/java/com/zhehekeji/web/entity/Stock.java index 9d53521..7a080f7 100644 --- a/web/src/main/java/com/zhehekeji/web/entity/Stock.java +++ b/web/src/main/java/com/zhehekeji/web/entity/Stock.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -16,6 +17,7 @@ import java.time.LocalDateTime; @TableName("`stock`") @NoArgsConstructor @AllArgsConstructor +@Builder public class Stock { @TableId(type = IdType.AUTO) @@ -55,6 +57,9 @@ public class Stock { private Integer streetId; + @TableField(exist = false) + private String streetName; + private Integer direction; private Integer side; diff --git a/web/src/main/java/com/zhehekeji/web/mapper/RfidLiveMapper.java b/web/src/main/java/com/zhehekeji/web/mapper/RfidLiveMapper.java new file mode 100644 index 0000000..5c9bdaf --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/mapper/RfidLiveMapper.java @@ -0,0 +1,8 @@ +package com.zhehekeji.web.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zhehekeji.web.entity.Order; +import com.zhehekeji.web.entity.RfidLive; + +public interface RfidLiveMapper extends BaseMapper { +} diff --git a/web/src/main/java/com/zhehekeji/web/mapper/RfidLogMapper.java b/web/src/main/java/com/zhehekeji/web/mapper/RfidLogMapper.java new file mode 100644 index 0000000..099c1f2 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/mapper/RfidLogMapper.java @@ -0,0 +1,8 @@ +package com.zhehekeji.web.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.zhehekeji.web.entity.RfidLive; +import com.zhehekeji.web.entity.RfidLog; + +public interface RfidLogMapper extends BaseMapper { +} diff --git a/web/src/main/java/com/zhehekeji/web/pojo/websocket/WebSocketVo.java b/web/src/main/java/com/zhehekeji/web/pojo/websocket/WebSocketVo.java new file mode 100644 index 0000000..5ea58f0 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/pojo/websocket/WebSocketVo.java @@ -0,0 +1,18 @@ +package com.zhehekeji.web.pojo.websocket; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class WebSocketVo { + private String type; + + @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") + private LocalDateTime time; + private T message; + private String data; + private String messageType; + private String info; +} diff --git a/web/src/main/java/com/zhehekeji/web/service/CheckLogService.java b/web/src/main/java/com/zhehekeji/web/service/CheckLogService.java index d3226e3..8f97a3f 100644 --- a/web/src/main/java/com/zhehekeji/web/service/CheckLogService.java +++ b/web/src/main/java/com/zhehekeji/web/service/CheckLogService.java @@ -28,18 +28,19 @@ public class CheckLogService { if(search.getStartTimestamp() != null && search.getEndTimestamp() != null){ wrapper.ge("create_time",search.getStartTimestamp()).le("create_time",search.getEndTimestamp()); } - if(search.getLeftRight() != null && search.getLeftRight() != 0){ + if(search.getLeftRight() != null &&( search.getLeftRight() != 0 || search.getLeftRight() != -1)){ wrapper.eq("`direction`",search.getLeftRight()); } - if(search.getSide() != null && search.getSide() != 0){ + if(search.getSide() != null &&( search.getSide() != 0 || search.getSide() != -1)){ wrapper.eq("`side`",search.getSide()); } - if(search.getRow() != null && search.getRow() != 0){ + if(search.getRow() != null &&( search.getRow() != 0 || search.getRow() != -1)){ wrapper.eq("`row`",search.getRow()); } - if(search.getColumn() != null && search.getColumn() != 0){ + if(search.getColumn() != null &&( search.getColumn() != 0 || search.getColumn() != -1)){ wrapper.eq("`column`",search.getColumn()); } + wrapper.orderByDesc("create_time"); ListstockChecks = checkLogMapper.selectList(wrapper); return new PageInfo<>(stockChecks); diff --git a/web/src/main/java/com/zhehekeji/web/service/PlcCmdInfo.java b/web/src/main/java/com/zhehekeji/web/service/PlcCmdInfo.java index c77aa6b..597a3de 100644 --- a/web/src/main/java/com/zhehekeji/web/service/PlcCmdInfo.java +++ b/web/src/main/java/com/zhehekeji/web/service/PlcCmdInfo.java @@ -70,6 +70,9 @@ public class PlcCmdInfo { private String lotnum; + private Integer fromDirection; + private Integer toDirection; + public PlcCmdInfo(String plcId, String taskId, Integer side1, Integer leftRight1, Integer column1, Integer row1, Integer separation1, Integer side2, Integer leftRight2, Integer column2, Integer row2, Integer separation2,String lotnum) { this.taskId = taskId; this.side1 = side1; 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 14b3396..9b07e0f 100644 --- a/web/src/main/java/com/zhehekeji/web/service/PlcService.java +++ b/web/src/main/java/com/zhehekeji/web/service/PlcService.java @@ -1,18 +1,25 @@ package com.zhehekeji.web.service; import codeDetector.BarcodeDetector; +import com.alibaba.druid.support.json.JSONUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.zhehekeji.common.util.PathUtil; import com.zhehekeji.web.config.ConfigProperties; +import com.zhehekeji.web.config.WebSocketConfig; import com.zhehekeji.web.entity.*; import com.zhehekeji.web.lib.*; import com.zhehekeji.web.mapper.*; import com.zhehekeji.web.pojo.OrderVO; +import com.zhehekeji.web.pojo.websocket.WebSocketVo; import com.zhehekeji.web.service.RFID.RFIDMap; import com.zhehekeji.web.service.RFID.RFIDSocket; import com.zhehekeji.web.service.hikLightSource.HikControlSocket; import com.zhehekeji.web.service.ksec.KsecNettyClient; import com.zhehekeji.web.service.sick.SickSocket; +import com.zhehekeji.web.ws.WebSocketServer; +import io.swagger.models.auth.In; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.SetUtils; import org.apache.poi.util.ArrayUtil; @@ -23,6 +30,7 @@ import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.io.File; import java.io.FileWriter; +import java.io.IOException; import java.time.Duration; import java.time.LocalDateTime; import java.util.Arrays; @@ -44,6 +52,9 @@ import java.util.concurrent.TimeUnit; @Slf4j public class PlcService { + @Resource + WebSocketServer webSocketServer; + @Resource private OrderMapper orderMapper; @Resource @@ -555,6 +566,15 @@ public class PlcService { @Resource private LightSourceMapper lightSourceMapper; + + public void webSocketSendInfo(PlcCmdInfo plcCmdInfo,String cmdCode) throws IOException { + WebSocketVo webSocketVo = new WebSocketVo<>(); + webSocketVo.setMessage(plcCmdInfo); + webSocketVo.setType("wmsCmdCode-"+cmdCode); + webSocketVo.setMessageType("object"); + WebSocketServer.sendInfo(JSONObject.toJSONString(webSocketVo),null); + } + public Boolean check(PlcCmdInfo plcCmdInfo,String cmdCode,String wmsCode,String wmsTrayCode){ long startTime = System.currentTimeMillis(); @@ -572,6 +592,7 @@ public class PlcService { log.info("camera ptz"+c); gyrateCameraByCode(cameraId, c); }else { + String c = cmdCode+"1"; gyrateCameraByCode(cameraId, cmdCode); try { Thread.sleep(configProperties.getCameraConfig().getDelayCaptureTime()); @@ -621,11 +642,9 @@ public class PlcService { } }else if(configProperties.getScanCodeMode().getTray() == 3){ - //RFID - RFID rfid = rfidService.getRFIDByPlc(street.getId()); - +// //RFID +// RFID rfid = rfidService.getRFIDByPlc(street.getId(),plcCmdInfo.getLeftRight1()); try{ - RFIDCheck(plcCmdInfo); Thread.sleep(1000*configProperties.getRfid().getScanTime()); Set tags = RFIDStop(plcCmdInfo); @@ -640,11 +659,9 @@ public class PlcService { }catch (Exception e){ e.printStackTrace(); } - - } OrderInfo orderInfo = new OrderInfo(street,plcCmdInfo,1,cmdCode); - Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(orderInfo.getStreetId(),orderInfo.getLeftRight(),orderInfo.getSeparation(),orderInfo.getRow(),orderInfo.getColumn()); + Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(orderInfo.getStreetId(),plcCmdInfo.getFromDirection(),orderInfo.getSeparation(),orderInfo.getRow(),orderInfo.getColumn()); String scanCode = null; Boolean codeCheck = Boolean.TRUE; Boolean trayCodeCheck = Boolean.TRUE; @@ -684,7 +701,21 @@ public class PlcService { status = 2; } if(stock == null){ - stock = new Stock(null,null,plcCmdInfo.getOrderNum(),plcCmdInfo.getLotnum(),scanCode, null,null,wmsCode,null,null,wmsTrayCode,trayCode,orderInfo.getStreetId(),orderInfo.getLeftRight(),orderInfo.getSeparation(),orderInfo.getRow(),orderInfo.getColumn(),status,null,null,path, LocalDateTime.now()); + stock = Stock.builder() + .checkNum(plcCmdInfo.getOrderNum()) + .lotnum(plcCmdInfo.getLotnum()) + .code(scanCode) + .wmsCode(wmsCode) + .wmsTrayCode(wmsTrayCode) + .trayCode(trayCode) + .streetId(orderInfo.getStreetId()) + .direction(plcCmdInfo.getFromDirection()) + .side(orderInfo.getSeparation()) + .row(orderInfo.getRow()) + .column(orderInfo.getColumn()) + .status(status) + .checkPic(path) + .exportTime(LocalDateTime.now()).build(); stockMapper.insert(stock); }else { stock.setStatus(status); @@ -707,6 +738,20 @@ public class PlcService { log.info("time:{}millisecond",s); return true; } + public Boolean checkRfid(PlcCmdInfo plcCmdInfo,String wmsTrayCode){ + RFIDCheck(plcCmdInfo); + try { + Thread.sleep(1000*configProperties.getRfid().getScanTime()); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + Set tags = RFIDStop(plcCmdInfo); + if(tags!= null && tags.size()>0 && tags.contains(wmsTrayCode)){ + return Boolean.TRUE; + }else { + return Boolean.FALSE; + } + } public void checkLog(Stock stock){ CheckLog checkLog = new CheckLog(); checkLog.setCheckNum(stock.getCheckNum()); @@ -732,16 +777,17 @@ public class PlcService { public void RFIDCheck(PlcCmdInfo plcCmdInfo){ Street street = streetService.getStreetByPlcId(plcCmdInfo.getPlcId()); if(street != null){ - RFID rfid = rfidService.getRFIDByPlc(street.getId()); + //rfid不分左右,rfid使用同一ip和端口,依靠传递字符调整方向 + RFID rfid = rfidService.getRFIDByPlc(street.getId(),null); if(rfid != null){ - RFIDStart(rfid.getIp(),rfid.getPort(),street.getId()); + RFIDStart(rfid.getIp(),rfid.getPort(),street.getId(), plcCmdInfo.getFromDirection()); } } } - public void RFIDStart(String ip,Integer port,Integer streetId){ + public void RFIDStart(String ip, Integer port, Integer streetId, Integer direction){ RFIDSocket rfidSocket = new RFIDSocket(ip,port); - rfidSocket.startCheck(); + rfidSocket.startCheck(direction); rfidSocket.readData(); RFIDMap.put(streetId,rfidSocket); } diff --git a/web/src/main/java/com/zhehekeji/web/service/RFID/RFIDSocket.java b/web/src/main/java/com/zhehekeji/web/service/RFID/RFIDSocket.java index ba2f0c7..716a812 100644 --- a/web/src/main/java/com/zhehekeji/web/service/RFID/RFIDSocket.java +++ b/web/src/main/java/com/zhehekeji/web/service/RFID/RFIDSocket.java @@ -189,11 +189,10 @@ public class RFIDSocket { } - public void startCheck(){ + public void startCheck(Integer direction){ Thread thread = new Thread(new Runnable() { @Override public void run() { - int i = 0; while (true){ if(!running){ break; @@ -203,7 +202,7 @@ public class RFIDSocket { antChanges[1] = (byte)0x04; antChanges[2] = (byte)0x01; antChanges[3] = (byte)0x74; - if(i % 2 == 0){ + if(1 == direction ){ //切换天线 使用天线0 antChanges[4] = (byte)0x00; antChanges[5] = (byte)0xe7; @@ -212,7 +211,6 @@ public class RFIDSocket { antChanges[4] = (byte)0x01; antChanges[5] = (byte)0xe6; } - i++; try { os.write(antChanges); Thread.sleep(10); @@ -244,7 +242,7 @@ public class RFIDSocket { file.createNewFile(); fw = new FileWriter(file, true); fw.write("\n"); - rfid.startCheck(); + rfid.startCheck(1); rfid.readData(); Thread.sleep(1000*30000); rfid.close(); diff --git a/web/src/main/java/com/zhehekeji/web/service/RFIDService.java b/web/src/main/java/com/zhehekeji/web/service/RFIDService.java index c5d60ff..7c23825 100644 --- a/web/src/main/java/com/zhehekeji/web/service/RFIDService.java +++ b/web/src/main/java/com/zhehekeji/web/service/RFIDService.java @@ -5,6 +5,8 @@ import com.zhehekeji.web.entity.RFID; import com.zhehekeji.web.entity.SensorGun; import com.zhehekeji.web.mapper.RFIDMapper; import com.zhehekeji.web.mapper.SensorGunMapper; +import com.zhehekeji.web.util.ToolUtil; +import io.swagger.models.auth.In; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -16,8 +18,8 @@ public class RFIDService { @Resource private RFIDMapper rfidMapper; - public RFID getRFIDByPlc(Integer streetId){ - List list = rfidMapper.selectList(new QueryWrapper().eq("street_id",streetId)); + public RFID getRFIDByPlc(Integer streetId, Integer direction){ + List list = rfidMapper.selectList(new QueryWrapper().eq("street_id",streetId).eq(ToolUtil.isNotEmpty(direction),"direction",direction)); if(list.size() > 0){ return list.get(0); } diff --git a/web/src/main/java/com/zhehekeji/web/service/StockCheckRunnable.java b/web/src/main/java/com/zhehekeji/web/service/StockCheckRunnable.java index b588608..da83c20 100644 --- a/web/src/main/java/com/zhehekeji/web/service/StockCheckRunnable.java +++ b/web/src/main/java/com/zhehekeji/web/service/StockCheckRunnable.java @@ -97,7 +97,22 @@ public class StockCheckRunnable implements Runnable { status = 2; } if(stock == null){ - stock = new Stock(null,null,plcCmdInfo.getOrderNum(),plcCmdInfo.getLotnum(),scanCode, null,null,wmsCode,null,null,wmsTrayCode,trayCode,orderInfo.getStreetId(),orderInfo.getLeftRight(),orderInfo.getSeparation(),orderInfo.getRow(),orderInfo.getColumn(),status,null,null,path, LocalDateTime.now()); + stock = Stock.builder() + .orderNum(plcCmdInfo.getOrderNum()) + .lotnum(plcCmdInfo.getLotnum()) + .code(scanCode) + .wmsCode(wmsCode) + .wmsTrayCode(wmsTrayCode) + .trayCode(trayCode) + .streetId(orderInfo.getStreetId()) + .direction(orderInfo.getLeftRight()) + .side(orderInfo.getSeparation()) + .row(orderInfo.getRow()) + .column(orderInfo.getColumn()) + .status(status) + .checkPic(path) + .exportTime(LocalDateTime.now()) + .build(); stockMapper.insert(stock); }else { stock.setStatus(status); diff --git a/web/src/main/java/com/zhehekeji/web/service/StockService.java b/web/src/main/java/com/zhehekeji/web/service/StockService.java index 59eee8e..7f757e6 100644 --- a/web/src/main/java/com/zhehekeji/web/service/StockService.java +++ b/web/src/main/java/com/zhehekeji/web/service/StockService.java @@ -16,6 +16,7 @@ import com.zhehekeji.web.mapper.StockMapper; import com.zhehekeji.web.mapper.StreetMapper; import com.zhehekeji.web.pojo.category.PageSearch; import com.zhehekeji.web.pojo.stock.*; +import com.zhehekeji.web.util.ToolUtil; import io.swagger.models.auth.In; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; @@ -317,7 +318,8 @@ public class StockService { * @param stockCheck * @return */ - public Stock stockInfo(StockCheck stockCheck) { + public Stock + stockInfo(StockCheck stockCheck) { Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(stockCheck.getStreetId(),stockCheck.getDirection(),stockCheck.getSide(), stockCheck.getRow(), stockCheck.getColumn()); if(stock == null){ @@ -326,7 +328,13 @@ public class StockService { stock.setRow(stockCheck.getRow()); //stock.setShelveId(stockCheck.getShelveId()); stock.setStatus(0); + Street street = streetMapper.selectById(stockCheck.getStreetId()); + stock.setStreetName(street.getName()); + }else { + Street street = streetMapper.selectById(stock.getStreetId()); + stock.setStreetName(street.getName()); } + //不再需要操作照片 List stockLogs = stockLogMapper.selectList(new QueryWrapper().eq("`row`",stockCheck.getRow()).eq("`column`",stockCheck.getColumn()).eq("street_id",stockCheck.getStreetId()).eq("direction",stockCheck.getDirection()).eq("side",stockCheck.getSide()).orderByDesc("create_time").last(" limit 2")); if(stockLogs.size() == 1){ stock.setOveroperationPic(stockLogs.get(0).getPic()); @@ -402,6 +410,34 @@ public class StockService { return stock; } + public Stock nextOne(Long id) { + QueryWrapper stockQueryWrapper = new QueryWrapper<>(); + + stockQueryWrapper.eq("status","0") + .ne(ToolUtil.isNotEmpty(id),"id",id) + .orderByDesc("export_time").last("limit 1"); + Stock stock =stockMapper.selectOne(stockQueryWrapper); + if (stock != null) { + Street street = streetMapper.selectById(stock.getStreetId()); + stock.setStreetName(street.getName()); + List stockLogs = stockLogMapper.selectList(new QueryWrapper() + .eq("`row`",stock.getRow()) + .eq("`column`",stock.getColumn()) + .eq("street_id",stock.getStreetId()) + .eq("direction",stock.getDirection()) + .eq("side",stock.getSide()) + .orderByDesc("create_time").last(" limit 2")); + if(stockLogs.size() == 1){ + stock.setOveroperationPic(stockLogs.get(0).getPic()); + }else if(stockLogs.size() == 2){ + stock.setOveroperationPic(stockLogs.get(0).getPic()); + stock.setPreoperationPic(stockLogs.get(1).getPic()); + } + } + + return stock; + } + // public void init(String shelveId, Integer row, Integer column){ // Map map = new HashMap<>(); // map.put("shelve_id",shelveId); diff --git a/web/src/main/java/com/zhehekeji/web/service/impl/RfidLiveServiceImpl.java b/web/src/main/java/com/zhehekeji/web/service/impl/RfidLiveServiceImpl.java new file mode 100644 index 0000000..5e826a4 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/impl/RfidLiveServiceImpl.java @@ -0,0 +1,108 @@ +package com.zhehekeji.web.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zhehekeji.web.config.ConfigProperties; +import com.zhehekeji.web.entity.RFID; +import com.zhehekeji.web.entity.RfidLive; +import com.zhehekeji.web.entity.RfidLog; +import com.zhehekeji.web.entity.Street; +import com.zhehekeji.web.mapper.RFIDMapper; +import com.zhehekeji.web.mapper.RfidLiveMapper; +import com.zhehekeji.web.mapper.RfidLogMapper; +import com.zhehekeji.web.service.PlcCmdInfo; +import com.zhehekeji.web.service.PlcService; +import com.zhehekeji.web.service.StreetService; +import com.zhehekeji.web.service.interfaces.RfidLiveService; +import com.zhehekeji.web.service.interfaces.RfidLogService; +import com.zhehekeji.web.util.ToolUtil; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.time.LocalDateTime; +import java.util.Set; + +@Service +public class RfidLiveServiceImpl extends ServiceImpl implements RfidLiveService { + + @Resource + RfidLogService rfidLogService; + + @Resource + PlcService plcService; + + @Resource + ConfigProperties configProperties; + @Resource + StreetService streetService; + + @Resource + RFIDMapper rfidMapper; + + + @Override + @Async("threadPoolTaskExecutor") + public void rfidOrderStock(PlcCmdInfo plcCmdInfo, Integer times, String code,String wmsTrayCode) { + + Street street = streetService.getStreetByPlcId(plcCmdInfo.getPlcId()); + RFID rfid = rfidMapper.selectOne(new QueryWrapper().eq("street_id",street.getId())); + //wms传递了wmsTrayCode + if(ToolUtil.isNotEmpty(wmsTrayCode)){ + //放货到位的时候,去触发rfid拿到值,判断是否相同,是则记录 + if(times ==3){ + plcService.RFIDCheck(plcCmdInfo); + try { + Thread.sleep(1000*configProperties.getRfid().getScanTime()); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + Set tags = plcService.RFIDStop(plcCmdInfo); + + RfidLog rfidLog = new RfidLog(); + RfidLive rfidLive = new RfidLive(); + if(tags!= null && tags.size()>0 && tags.contains(wmsTrayCode)){ + rfidLog.setRfidTrayCode(wmsTrayCode); + rfidLive.setRfidId(rfid.getId()); + rfidLive.setWmsTrayCode(wmsTrayCode); + rfidLive.setRfidTrayCode(wmsTrayCode); + rfidLive.setStreetId(street.getId()); + rfidLive.setDirection(plcCmdInfo.getToDirection()); + rfidLive.setSide(plcCmdInfo.getSide1()); + rfidLive.setRow(plcCmdInfo.getRow1()); + rfidLive.setColumn(plcCmdInfo.getColumn1()); + rfidLive.setRfidTrayCode(null); + rfidLive.setCreateTime(LocalDateTime.now()); + rfidLive.setRfidId(rfid.getId()); + rfidLive.setTaskId(plcCmdInfo.getTaskId()); + save(rfidLive); + } + rfidLog.setRfidId(rfid.getId()); + rfidLog.setWmsTrayCode(wmsTrayCode); + rfidLog.setStreet_id(street.getId()); + rfidLog.setDirection(plcCmdInfo.getToDirection()); + rfidLog.setSide(plcCmdInfo.getSide1()); + rfidLog.setRow(plcCmdInfo.getRow1()); + rfidLog.setColumn(plcCmdInfo.getColumn1()); + rfidLog.setRfidTrayCode(null); + rfidLog.setCreateTime(LocalDateTime.now()); + rfidLog.setRfidId(rfid.getId()); + rfidLog.setTaskId(plcCmdInfo.getTaskId()); + rfidLog.setMovement(1); + rfidLogService.save(rfidLog); + + } + + //取货完成删除live + + if(times ==2){ + remove(new QueryWrapper() + .eq("street_Id" ,street.getId()) + .eq("direction" ,plcCmdInfo.getFromDirection()) + .eq("side" ,plcCmdInfo.getSide1()) + .eq("row" ,plcCmdInfo.getRow1()) + .eq("column" ,plcCmdInfo.getRow1())); + } + } + } +} diff --git a/web/src/main/java/com/zhehekeji/web/service/impl/RfidLogServiceImpl.java b/web/src/main/java/com/zhehekeji/web/service/impl/RfidLogServiceImpl.java new file mode 100644 index 0000000..936970f --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/impl/RfidLogServiceImpl.java @@ -0,0 +1,11 @@ +package com.zhehekeji.web.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.zhehekeji.web.entity.RfidLog; +import com.zhehekeji.web.mapper.RfidLogMapper; +import com.zhehekeji.web.service.interfaces.RfidLogService; +import org.springframework.stereotype.Service; + +@Service +public class RfidLogServiceImpl extends ServiceImpl implements RfidLogService { +} diff --git a/web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLiveService.java b/web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLiveService.java new file mode 100644 index 0000000..46794d6 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLiveService.java @@ -0,0 +1,10 @@ +package com.zhehekeji.web.service.interfaces; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.zhehekeji.web.entity.RfidLive; +import com.zhehekeji.web.entity.RfidLog; +import com.zhehekeji.web.service.PlcCmdInfo; + +public interface RfidLiveService extends IService { + void rfidOrderStock(PlcCmdInfo plcCmdInfo, Integer times, String code,String wmsTrayCode); +} diff --git a/web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLogService.java b/web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLogService.java new file mode 100644 index 0000000..e94b735 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/service/interfaces/RfidLogService.java @@ -0,0 +1,7 @@ +package com.zhehekeji.web.service.interfaces; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.zhehekeji.web.entity.RfidLog; + +public interface RfidLogService extends IService { +} diff --git a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java index 7e7f299..6a88274 100644 --- a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java +++ b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecDecoder.java @@ -2,6 +2,7 @@ package com.zhehekeji.web.service.ksec; import com.alibaba.fastjson.JSONObject; import com.zhehekeji.common.util.FileUtil; +import com.zhehekeji.web.entity.Street; import com.zhehekeji.web.pojo.Cmd; import com.zhehekeji.web.service.GoodsActionTimes; import com.zhehekeji.web.service.PlcCmdInfo; @@ -86,19 +87,26 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder { String srmNumber = null; String cmdName = null; if(dataInfo != null){ + + plcCmdInfo = new PlcCmdInfo(dataInfo.getSRMNumber(), dataInfo.getTaskId(), dataInfo.getFromSide(), dataInfo.getFromDirection(), dataInfo.getFromColumn(), dataInfo.getFromRow(), dataInfo.getFromSeparation(),dataInfo.getToSide(), dataInfo.getToDirection(), dataInfo.getToColumn(), dataInfo.getToRow(),dataInfo.getToSeparation(),lotnum); + plcCmdInfo.setFromDirection(dataInfo.getFromDirection()); + plcCmdInfo.setToDirection(dataInfo.getToDirection()); + //左右换过来 if(dataInfo.getFromDirection() == 1){ dataInfo.setFromDirection(2); + plcCmdInfo.setLeftRight1(dataInfo.getFromDirection()); }else { dataInfo.setFromDirection(1); + plcCmdInfo.setLeftRight1(dataInfo.getFromDirection()); } if(dataInfo.getToDirection() != null && dataInfo.getToDirection() == 1){ dataInfo.setToDirection(2); + plcCmdInfo.setLeftRight2(dataInfo.getToDirection()); }else { dataInfo.setToDirection(1); + plcCmdInfo.setLeftRight2(dataInfo.getToDirection()); } - plcCmdInfo = new PlcCmdInfo(dataInfo.getSRMNumber(), dataInfo.getTaskId(), dataInfo.getFromSide(), dataInfo.getFromDirection(), dataInfo.getFromColumn(), dataInfo.getFromRow(), dataInfo.getFromSeparation(),dataInfo.getToSide(), dataInfo.getToDirection(), dataInfo.getToColumn(), dataInfo.getToRow(),dataInfo.getToSeparation(),lotnum); - srmNumber = dataInfo.getSRMNumber(); cmdName = dataInfo.getCmdName(); } diff --git a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java index e5e3b25..487e4ab 100644 --- a/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java +++ b/web/src/main/java/com/zhehekeji/web/service/ksec/KsecNettyClient.java @@ -25,11 +25,6 @@ public class KsecNettyClient { @Resource private ConfigProperties configProperties; - /** - * 重连最大次数 - */ - private static int RECONNECT_NUM = 10; - private static Channel channel; public void createClient(ConfigProperties.KSEC ksec) throws InterruptedException { @@ -67,13 +62,19 @@ public class KsecNettyClient { } catch (InterruptedException e) { e.printStackTrace(); } - while (num < RECONNECT_NUM && !isConnected) { + while ((ksec.getReconnectNum() == -1 || num < ksec.getReconnectNum() ) && !isConnected) { try { createClient(ksec); } catch (Exception e) { //没连上 继续 log.error("reconnect error num:{}", num); + channel.close(); num++; + try { + Thread.sleep(ksec.getReconnectInterval()*1000); + } catch (InterruptedException ex) { + throw new RuntimeException(ex); + } continue; } isConnected = true; diff --git a/web/src/main/java/com/zhehekeji/web/test/client/MyClient.java b/web/src/main/java/com/zhehekeji/web/test/client/MyClient.java new file mode 100644 index 0000000..71c6f52 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/test/client/MyClient.java @@ -0,0 +1,40 @@ +package com.zhehekeji.web.test.client; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +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; + +public class MyClient { + + public static void main(String[] args) throws Exception { + NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); + try { + //创建bootstrap对象,配置参数 + Bootstrap bootstrap = new Bootstrap(); + //设置线程组 + bootstrap.group(eventExecutors) + //设置客户端的通道实现类型 + .channel(NioSocketChannel.class) + //使用匿名内部类初始化通道 + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + //添加客户端通道的处理器 + ch.pipeline().addLast(new MyClientHandler()); + } + }); + System.out.println("客户端准备就绪,随时可以起飞~"); + //连接服务端 + ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6666).sync(); + //对通道关闭进行监听 + channelFuture.channel().closeFuture().sync(); + } finally { + //关闭线程组 + eventExecutors.shutdownGracefully(); + } + } +} diff --git a/web/src/main/java/com/zhehekeji/web/test/client/MyClientHandler.java b/web/src/main/java/com/zhehekeji/web/test/client/MyClientHandler.java new file mode 100644 index 0000000..e7102f2 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/test/client/MyClientHandler.java @@ -0,0 +1,23 @@ +package com.zhehekeji.web.test.client; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.util.CharsetUtil; + +public class MyClientHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + //发送消息到服务端 + ctx.writeAndFlush(Unpooled.copiedBuffer("歪比巴卜~茉莉~Are you good~马来西亚~", CharsetUtil.UTF_8)); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //接收服务端发送过来的消息 + ByteBuf byteBuf = (ByteBuf) msg; + System.out.println("收到服务端" + ctx.channel().remoteAddress() + "的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); + } +} diff --git a/web/src/main/java/com/zhehekeji/web/test/server/MyServer.java b/web/src/main/java/com/zhehekeji/web/test/server/MyServer.java new file mode 100644 index 0000000..0070cf6 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/test/server/MyServer.java @@ -0,0 +1,44 @@ +package com.zhehekeji.web.test.server; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.bootstrap.ServerBootstrapConfig; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; + +public class MyServer { + public static void main(String[] args) { + + + //创建服务端的启动对象,设置参数 + ServerBootstrap bootstrap = new ServerBootstrap(); + bootstrap.group(new NioEventLoopGroup(),new NioEventLoopGroup())//设置服务端通道实现类型 + .channel(NioServerSocketChannel.class) + //设置线程队列得到连接个数 + .option(ChannelOption.SO_BACKLOG, 128) + //设置保持活动连接状态 + .childOption(ChannelOption.SO_KEEPALIVE, true) + //使用匿名内部类的形式初始化通道对象 + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + //给pipeline管道设置处理器 + socketChannel.pipeline().addLast(new MyServerHandler()); + } + });//给workerGroup的EventLoop对应的管道设置处理器 + + System.out.println("java技术爱好者的服务端已经准备就绪..."); + //绑定端口号,启动服务端 + try { + ChannelFuture channelFuture = bootstrap.bind(6666).sync(); + channelFuture.channel().closeFuture().sync(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + + } + } +} diff --git a/web/src/main/java/com/zhehekeji/web/test/server/MyServerHandler.java b/web/src/main/java/com/zhehekeji/web/test/server/MyServerHandler.java new file mode 100644 index 0000000..a4145c6 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/test/server/MyServerHandler.java @@ -0,0 +1,39 @@ +package com.zhehekeji.web.test.server; + +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.util.CharsetUtil; + +/** + * 自定义的Handler需要继承Netty规定好的HandlerAdapter + * 才能被Netty框架所关联,有点类似SpringMVC的适配器模式 + **/ +public class MyServerHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + //获取客户端发送过来的消息 + ByteBuf byteBuf = (ByteBuf) msg; + System.out.println("收到客户端" + ctx.channel().remoteAddress() + "发送的消息:" + byteBuf.toString(CharsetUtil.UTF_8)); + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + //发送消息给客户端 + ctx.writeAndFlush(Unpooled.copiedBuffer("服务端已收到消息,并给你发送一个问号?", CharsetUtil.UTF_8)); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + //发生异常,关闭通道 + ctx.close(); + } +} diff --git a/web/src/main/java/com/zhehekeji/web/util/ToolUtil.java b/web/src/main/java/com/zhehekeji/web/util/ToolUtil.java new file mode 100644 index 0000000..09c6b55 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/util/ToolUtil.java @@ -0,0 +1,35 @@ +package com.zhehekeji.web.util; + +import com.alibaba.excel.util.CollectionUtils; +import org.apache.poi.util.ArrayUtil; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class ToolUtil { + public static boolean isEmpty(Object o) { + if (o == null) { + return true; + } + if (o instanceof String) { + return ((String) o).isEmpty(); + } + if (o instanceof Collection) { + return ((Collection) o).isEmpty(); + } + if (o instanceof Map) { + return ((Map) o).isEmpty(); + } + if (o.getClass().isArray()) { + return Array.getLength(o) == 0; + } + return "".equals(o.toString()); + } + + public static boolean isNotEmpty(Object o) { + return !isEmpty(o); + } +} diff --git a/web/src/main/java/com/zhehekeji/web/ws/WebSocketServer.java b/web/src/main/java/com/zhehekeji/web/ws/WebSocketServer.java new file mode 100644 index 0000000..ac7536e --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/ws/WebSocketServer.java @@ -0,0 +1,151 @@ +package com.zhehekeji.web.ws; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; + +@ServerEndpoint(value = "/ws/{sid}") +@Component +public class WebSocketServer { + + private final static Logger log = LoggerFactory.getLogger(WebSocketServer.class); + //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 + private static int onlineCount = 0; + //与某个客户端的连接会话,需要通过它来给客户端发送数据 + private Session session; + //旧:concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。由于遍历set费时,改用map优化 + //private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet(); + //新:使用map对象优化,便于根据sid来获取对应的WebSocket + private static ConcurrentHashMap websocketMap = new ConcurrentHashMap<>(); + //接收用户的sid,指定需要推送的用户 + private String sid; + + /** + * 连接成功后调用的方法 + */ + @OnOpen + public void onOpen(Session session,@PathParam("sid") String sid) { + this.session = session; + //webSocketSet.add(this); //加入set中 + websocketMap.put(sid,this); //加入map中 + addOnlineCount(); //在线数加1 + log.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount()); + this.sid=sid; + try { + sendMessage("连接成功"); + } catch (IOException e) { + log.error("websocket IO异常"); + } + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose() { + if(websocketMap.get(this.sid)!=null){ + //webSocketSet.remove(this); //从set中删除 + websocketMap.remove(this.sid); //从map中删除 + subOnlineCount(); //在线数减1 + log.info("有一连接关闭!当前在线人数为" + getOnlineCount()); + } + } + + /** + * 收到客户端消息后调用的方法,根据业务要求进行处理,这里就简单地将收到的消息直接群发推送出去 + * @param message 客户端发送过来的消息 + */ + @OnMessage + public void onMessage(String message, Session session) { + log.info("收到来自窗口"+sid+"的信息:"+message); + if(StringUtils.isNotBlank(message)){ + for(WebSocketServer server:websocketMap.values()) { + try { + server.sendMessage(message); + } catch (IOException e) { + e.printStackTrace(); + continue; + } + } + } + } + + /** + * 发生错误时的回调函数 + * @param session + * @param error + */ + @OnError + public void onError(Session session, Throwable error) { + log.error("发生错误"); + error.printStackTrace(); + } + + /** + * 实现服务器主动推送消息 + */ + public void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + + + /** + * 群发自定义消息(用set会方便些) + * */ + public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException { + log.info("推送消息到窗口"+sid+",推送内容:"+message); + /*for (WebSocketServer item : webSocketSet) { + try { + //这里可以设定只推送给这个sid的,为null则全部推送 + if(sid==null) { + item.sendMessage(message); + }else if(item.sid.equals(sid)){ + item.sendMessage(message); + } + } catch (IOException e) { + continue; + } + }*/ + if(StringUtils.isNotBlank(message)){ + for(WebSocketServer server:websocketMap.values()) { + try { + // sid为null时群发,不为null则只发一个 + if (sid == null) { + server.sendMessage(message); + } else if (server.sid.equals(sid)) { + server.sendMessage(message); + } + } catch (IOException e) { + e.printStackTrace(); + continue; + } + } + } + } + + public static synchronized int getOnlineCount() { + return onlineCount; + } + public static synchronized void addOnlineCount() { + WebSocketServer.onlineCount++; + } + public static synchronized void subOnlineCount() { + WebSocketServer.onlineCount--; + } +} diff --git a/web/src/main/resources/application-test.yml b/web/src/main/resources/application-test.yml index 6be8148..16af868 100644 --- a/web/src/main/resources/application-test.yml +++ b/web/src/main/resources/application-test.yml @@ -48,6 +48,10 @@ serverMode: 1 ksec: ip: 127.0.0.1 port: 3000 + #重连次数 默认10次 + reconnectNum: -1 + #重连间隔 默认10s + reconnectInterval: 10 # ------------ 实时视频流 全部页面的格式 行列数量 videoStyleConfig: videoStyleRow: 2 @@ -76,4 +80,10 @@ deleteFileDays: 365 #rfid rfid: #rfid连续扫描时间,默认5s 单位s - scanTime: 1 \ No newline at end of file + scanTime: 1 + +asyncExecutorThread: + corePoolSize: 5 + maxPoolSize: 70 + queueCapacity: 99999 + namePrefix: "Thread_Pool_Task_Executor" \ No newline at end of file