1.开启线程池

2.websocket后台实现
3.下一个盘点信息
4.暂时关闭获取光源状态(会报错)
5.巷道名由后端获取,保证前段通用性
6.盘点历史倒序
7.盘点左右方向错误
8.stock使用builder建造器增加可视化
9.断续重连增加不断重连
10.天线固定,不再两个方向同时扫描
11.增加rfidlog和rfidlive,保证后续深货位可以逻辑rfid扫描(待测试)
nanjing-yancao-rfid
LAPTOP-S9HJSOEB\昊天 3 years ago
parent 314fe5e8c7
commit 1e7c3cd274

@ -18,7 +18,12 @@
</properties>
<dependencies>
<!--websocket支持包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.zhehekeji</groupId>
<artifactId>base-assembly</artifactId>

@ -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

@ -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;
}
}

@ -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 {
/**
* 使SpringboottomcatServerEndpointbean
* 使webServerEndpointExporter
*/
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}

@ -114,6 +114,13 @@ public class StockController {
return Result.success(stockService.stockInfo(stockCheck));
}
@ApiOperation(value = "下一个盘点信息")
@RequestMapping(value = "/nextOne", method = RequestMethod.POST)
public Result<Stock> nextOne(@RequestBody Stock stock) {
return Result.success(stockService.nextOne(stock.getId()));
}
@ApiOperation(value = "获取盘点信息")
@RequestMapping(value = "/checkInfo", method = RequestMethod.POST)
public Result<Stock> checkInfo(@RequestBody StockCheckSearch stockCheck) {

@ -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){

@ -12,8 +12,6 @@ import java.time.LocalDateTime;
@Data
public class CheckLog {
@TableId(type = IdType.AUTO)
private Long id;
private Integer streetId;

@ -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;
}

@ -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;
}

@ -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;

@ -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<RfidLive> {
}

@ -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<RfidLog> {
}

@ -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<T> {
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;
}

@ -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");
List<CheckLog>stockChecks = checkLogMapper.selectList(wrapper);
return new PageInfo<>(stockChecks);

@ -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;

@ -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<PlcCmdInfo> 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<String> 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<String> 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);
}

@ -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();

@ -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<RFID> list = rfidMapper.selectList(new QueryWrapper<RFID>().eq("street_id",streetId));
public RFID getRFIDByPlc(Integer streetId, Integer direction){
List<RFID> list = rfidMapper.selectList(new QueryWrapper<RFID>().eq("street_id",streetId).eq(ToolUtil.isNotEmpty(direction),"direction",direction));
if(list.size() > 0){
return list.get(0);
}

@ -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);

@ -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<StockLog> stockLogs = stockLogMapper.selectList(new QueryWrapper<StockLog>().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<Stock> 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<StockLog> stockLogs = stockLogMapper.selectList(new QueryWrapper<StockLog>()
.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<String,Object> map = new HashMap<>();
// map.put("shelve_id",shelveId);

@ -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<RfidLiveMapper,RfidLive> 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<RFID>().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<String> 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<RfidLive>()
.eq("street_Id" ,street.getId())
.eq("direction" ,plcCmdInfo.getFromDirection())
.eq("side" ,plcCmdInfo.getSide1())
.eq("row" ,plcCmdInfo.getRow1())
.eq("column" ,plcCmdInfo.getRow1()));
}
}
}
}

@ -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<RfidLogMapper,RfidLog> implements RfidLogService {
}

@ -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<RfidLive> {
void rfidOrderStock(PlcCmdInfo plcCmdInfo, Integer times, String code,String wmsTrayCode);
}

@ -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<RfidLog> {
}

@ -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();
}

@ -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;

@ -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<SocketChannel>() {
@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();
}
}
}

@ -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));
}
}

@ -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<SocketChannel>() {
@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);
}
}
}

@ -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;
/**
* HandlerNettyHandlerAdapter
* NettySpringMVC
**/
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();
}
}

@ -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);
}
}

@ -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<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//新使用map对象优化便于根据sid来获取对应的WebSocket
private static ConcurrentHashMap<String,WebSocketServer> 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--;
}
}

@ -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
scanTime: 1
asyncExecutorThread:
corePoolSize: 5
maxPoolSize: 70
queueCapacity: 99999
namePrefix: "Thread_Pool_Task_Executor"
Loading…
Cancel
Save