Merge branch '滁州-烟草' of https://gitlab.hzleaper.com:81/duoji/backend-duoji-monitor into 滁州-烟草

# Conflicts:
#	web/src/main/java/com/zhehekeji/web/controller/CheckLogController.java
滁州-烟草
LAPTOP-S9HJSOEB\昊天 2 years ago
commit 165a697c7e

@ -46,6 +46,10 @@ public class ConfigProperties {
*/
private Integer serverPort;
private boolean inventorySimulationFollow = false;
private Long queueSpanTime = 5000L;
@Data
public static class CameraConfig{

@ -5,8 +5,12 @@ import com.zhehekeji.common.util.ValidatorUtil;
import com.zhehekeji.core.pojo.Result;
import com.zhehekeji.web.entity.CheckLog;
import com.zhehekeji.web.entity.StockLog;
<<<<<<< HEAD
import com.zhehekeji.web.pojo.CheckLogOne;
import com.zhehekeji.web.pojo.Obg;
=======
import com.zhehekeji.web.pojo.LocReq;
>>>>>>> d6df183a0c2207a5165c402df8fc6c0fb599b9e8
import com.zhehekeji.web.pojo.stock.CheckLogSearch;
import com.zhehekeji.web.pojo.stock.StockLogSearch;
import com.zhehekeji.web.service.CheckLogService;
@ -19,6 +23,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Api(tags = "盘点历史")
@RequestMapping("/checkLog")

@ -12,6 +12,8 @@ import java.time.LocalDateTime;
@Data
public class CheckLog {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer streetId;
@ -33,8 +35,13 @@ public class CheckLog {
private String wmsCode;
private String category;
private String taskId;
private Integer count;
private Integer wmsCount;
private String wmsCategory;
private int statusVision = 0;
private String checkNum;
@ -44,10 +51,6 @@ public class CheckLog {
@ApiModelProperty("扫描出的托盘码")
private String trayCode;
private Integer status;
private String pic;
private String lotnum;
@ -56,5 +59,10 @@ public class CheckLog {
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
private Integer status;
private String pic;
@TableField(exist=false)
private String[] pics;
}

@ -25,6 +25,7 @@ public class Stock {
@ApiModelProperty("随行任务号")
private String orderNum;
private int statusVision =0;
@ApiModelProperty("盘点任务号")
private String checkNum;
@ -91,4 +92,5 @@ public class Stock {
private String streetName;
private String pcd;//点位文件路径
}

@ -1,5 +1,6 @@
package com.zhehekeji.web.lib;
import com.zhehekeji.web.service.client.TransmissionPojo;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -15,9 +16,12 @@ public class CameraDelayTask implements Delayed {
private LocalDateTime startTime;
private TransmissionPojo transmissionPojo;
private LocalDateTime endTime;
private String path;
private String command;
/**
* 0 : mp4 1:jpeg
@ -26,10 +30,19 @@ public class CameraDelayTask implements Delayed {
private long executeTime;
private String cameraPlcId;
private long delayTime;
private Integer ptzId;
public CameraDelayTask(String cameraPlcId, String command, long delayTime,TransmissionPojo transmissionPojo) {
this.cameraPlcId = cameraPlcId;
this.command = command;
this.executeTime = System.currentTimeMillis()+delayTime;
this.delayTime = delayTime;
this.transmissionPojo = transmissionPojo;
}
public CameraDelayTask(Integer cameraId, LocalDateTime startTime, LocalDateTime endTime, String path, Integer type, long delayTime) {
this.cameraId = cameraId;
this.startTime = startTime;

@ -10,15 +10,22 @@ public class HikExceptionCallBack implements HCNetSDK.FExceptionCallBack {
@Override
public void invoke(int dwType, int lUserID, int lHandle, Pointer pUser) {
Integer cameraId =CameraConnMap.getCameraIdByLoginId(new NetSDKLib.LLong(lUserID));
if(dwType == 32768){
NetSDKLib.LLong lLong = new NetSDKLib.LLong(lUserID);
Integer cameraId =CameraConnMap.getCameraIdByLoginId(lLong);
if(dwType == 0x8000){
if(cameraId != null) {
log.error("hik disconnect,cameraId:{}", cameraId);
log.error("hik disconnect,cameraId:{}", cameraId);
}else if(dwType == 32791){
}
}else if(dwType == 0x8017){
log.info("hik reconnect,cameraId:{}", CameraConnMap.getCameraIdByLoginId(new NetSDKLib.LLong(lUserID)));
}
log.info("hik reconnect,cameraId:{}", cameraId);
if(!lLong.equals(CameraConnMap.getConnId(cameraId))) {
log.error("hik reconnect,cameraId:{},lUserId:{}", cameraId,lLong);
CameraConnMap.conn(cameraId, new NetSDKLib.LLong(lUserID));
}
}
}
}

@ -0,0 +1,16 @@
package com.zhehekeji.web.pojo;
import lombok.Data;
@Data
public class LocReq {
Integer streetId;
//货位编码
private String loc;
//时间
private String date;
//托盘标签
private String tagid;
//taskId
private String jobnum;
}

@ -13,6 +13,7 @@ import com.zhehekeji.web.lib.joyware.NetSDKLib;
import com.zhehekeji.web.mapper.CameraMapper;
import com.zhehekeji.web.mapper.SensorGunMapper;
import com.zhehekeji.web.mapper.StreetMapper;
import com.zhehekeji.web.service.client.GetPhotoDelayExecutor;
import com.zhehekeji.web.service.client.NettyServer;
import com.zhehekeji.web.service.ksec.KsecNettyClient;
import com.zhehekeji.web.service.robotic.NettyClient;
@ -87,6 +88,8 @@ public class InitService implements ApplicationRunner {
//球机登录
List<Camera> cameras = cameraMapper.selectByMap(new HashMap<>(0));
List<Street> streets = streetMapper.selectByMap(new HashMap<>());
cameras.forEach(camera -> {
LoginThread loginThread = new LoginThread(camera);
loginThread.start();
@ -96,7 +99,6 @@ public class InitService implements ApplicationRunner {
if(configProperties.getServerMode() == 0){
log.info("PLC TCP MODE");
//plc 连接状态初始化
List<Street> streets = streetMapper.selectByMap(new HashMap<>(0));
streets.forEach(street -> {
StreetConn.init(street.getId(),street.getPlcId());
@ -123,6 +125,7 @@ public class InitService implements ApplicationRunner {
}
}
TaskDelayExecutor.runMp4DownloadExecutor();
GetPhotoDelayExecutor.runExecutor(streets);
}
class LoginThread extends Thread{

@ -69,6 +69,8 @@ public class PlcCmdInfo {
private Integer times;
private String code;
private String lotnum;
private Integer streetId;

@ -11,14 +11,16 @@ import com.zhehekeji.web.lib.*;
import com.zhehekeji.web.mapper.*;
import com.zhehekeji.web.pojo.CameraPtzPojo;
import com.zhehekeji.web.pojo.OrderVO;
import com.zhehekeji.web.pojo.stock.StockStatus;
import com.zhehekeji.web.service.RFID.RFIDMap;
import com.zhehekeji.web.service.RFID.RFIDSocket;
import com.zhehekeji.web.service.RFID.RFIDSocketFactory;
import com.zhehekeji.web.service.client.ClientChanel;
import com.zhehekeji.web.service.client.SCTransmission;
import com.zhehekeji.web.service.client.*;
import com.zhehekeji.web.service.damLightSource.JYDAMEquip;
import com.zhehekeji.web.service.damLightSource.JYDamHelper;
import com.zhehekeji.web.service.hikLightSource.HikControlSocket;
import com.zhehekeji.web.service.ksec.KsecDataInfo;
import com.zhehekeji.web.service.ksec.KsecInfo;
import com.zhehekeji.web.service.ksec.KsecNettyClient;
import com.zhehekeji.web.service.sick.SickSocket;
import lombok.extern.slf4j.Slf4j;
@ -38,6 +40,9 @@ import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
import static org.aspectj.weaver.tools.cache.SimpleCacheFactory.path;
@ -642,13 +647,33 @@ public class PlcService {
}
Lock lock = new ReentrantLock();
@Resource
private LightSourceMapper lightSourceMapper;
public Boolean check(PlcCmdInfo plcCmdInfo,String cmdCode,String wmsCode,String wmsTrayCode,String wmsCatagary){
long startTime = System.currentTimeMillis();
Street street = streetService.getStreetByPlcId(plcCmdInfo.getPlcId());
//开始盘点具体货位
CheckLog checkLog = new CheckLog();
checkLog.setStreetId(street.getId());
checkLog.setLotnum(plcCmdInfo.getLotnum());
checkLog.setDirection(plcCmdInfo.getLeftRight1());
checkLog.setSide(plcCmdInfo.getSide1());
checkLog.setRow(plcCmdInfo.getRow1());
checkLog.setColumn(plcCmdInfo.getColumn1());
checkLog.setWmsCode(plcCmdInfo.getCode());
checkLog.setTaskId((plcCmdInfo.getTaskId()));
//默认未盘点
checkLog.setStatus(StockStatus.PENDING.getStatus());
checkLog.setCreateTime(LocalDateTime.now());
checkLog.setWmsCategory(plcCmdInfo.getTypeNum());
checkLog.setWmsCount(plcCmdInfo.getQuantity());
CronTab.putTime(street.getId());
List<LightSource> lightSources = lightSourceMapper.selectList(new QueryWrapper<LightSource>().eq("street_id",street.getId()));
lightSources.forEach(lightSource -> {
@ -676,76 +701,26 @@ public class PlcService {
String path = PathUtil.createFileNameByRowColumn("jpg", cameraId, plcCmdInfo.getRow1(), plcCmdInfo.getColumn1());
try {
cameraCapture(cameraId, false, null, path);
} catch (NullPointerException e) {
log.error("相机{}未连接无法拍照", cameraId);
}
checkLog.setPic(path);
checkLogMapper.insert(checkLog);
//托盘码
String trayCode = null;
Boolean trayCheck = Boolean.TRUE;
//扫托盘码
if(configProperties.getScanCodeMode().getTray() == 2) {
log.info("扫码类型:" + configProperties.getScanCodeMode().getTray());
//托盘使用sick扫码枪
SensorGun sensorGun = sensorService.getSensorByPlc(street.getId(), plcCmdInfo.getLeftRight1());
if (sensorGun == null) {
trayCode = "扫码枪未配置";
trayCheck = Boolean.FALSE;
log.error("no sensor gun config in database ,street id:{},direction:{}", street.getId(), plcCmdInfo.getLeftRight1());
} else {
trayCode = SickSocket.readOCR(sensorGun.getIp(), sensorGun.getPort());
log.info("sensor tray code:{}", trayCode);
if ("".equals(wmsTrayCode)) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
if (StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) {
trayCode = "无货物";
trayCheck = Boolean.TRUE;
} else {
trayCode = "扫码枪识别异常";
trayCheck = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
}
} else {
if (StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) {
trayCode = "扫码枪识别异常";
trayCheck = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
} else {
//扫到就认为正常
trayCheck = Boolean.TRUE;
}
}
}
}else if(configProperties.getScanCodeMode().getTray() == 3){
//扫到的码
Set<String> tags = new HashSet<>();
try {
RFIDCheck(plcCmdInfo, true);
Thread.sleep(1000 * configProperties.getRfid().getScanTime());
} catch (Exception e) {
e.printStackTrace();
} finally {
tags = RFIDStop(plcCmdInfo);
log.info("盘点rfid扫描结果" + tags);
}
if (tags !=null && tags.contains(wmsTrayCode)) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
trayCode = wmsTrayCode;
trayCheck = Boolean.TRUE;
trayCheck = scan(configProperties.getScanCodeMode().getTray(),street,plcCmdInfo,checkLog,trayCode);
} else {
trayCode = trayCode+ "扫码枪识别异常";
trayCheck = Boolean.FALSE;
log.warn("rfid error:{}", trayCode);
}
}
Boolean trayGoodCheck = Boolean.TRUE;
String trayGoodCode = null;
Boolean trayGoodCheck = scan(configProperties.getScanCodeMode().getGoods(),street,plcCmdInfo,checkLog,trayGoodCode);
OrderInfo orderInfo = new OrderInfo(street, plcCmdInfo, 1, cmdCode);
//扫货物
@ -782,7 +757,8 @@ public class PlcService {
}
}
}
}else if(configProperties.getScanCodeMode().getGoods() == 3){
}else
if(configProperties.getScanCodeMode().getGoods() == 3){
Set<String> tags = new HashSet<>();
try {
RFIDCheck(plcCmdInfo, true);
@ -805,31 +781,49 @@ public class PlcService {
log.warn("rfid error:{}", trayCode);
}
}else if (configProperties.getScanCodeMode().getGoods() == 4){
//开始盘点
String goodLocation = orderInfo.getStreetId().toString()+"_"+ plcCmdInfo.getLeftRight1().toString()+"_"+ orderInfo.getSeparation().toString()+"_"+ orderInfo.getRow().toString()+"_"+ orderInfo.getColumn();
SCTransmission scTransmission = new SCTransmission(street.getPlcId(),plcCmdInfo.getTaskId(),goodLocation,plcCmdInfo.getTypeNum(), plcCmdInfo.getQuantity(), "N");
String scTransmissionStr = scTransmission.toString();
ClientChanel.write(scTransmissionStr,street.getPlcId());
}else
if (configProperties.getScanCodeMode().getGoods() == 4){
TransmissionPojo transmissionPojo = new TransmissionPojo(checkLog, street);
if (ClientChanel.get(plcCmdInfo.getPlcId()) != null) {
ClientChanel.get(plcCmdInfo.getPlcId()).writeAndFlush(transmissionPojo.toString(TransmissionType.ST));
} else {
log.error("未找到对应plc" + transmissionPojo.toString());
}
//取货完成进行拍照
try {
Thread.sleep(500);
Thread.sleep(50L);
//不为其他状态进入队列
if (lock.tryLock()) {
//队列中没有任务,发送取图指令
//只采用队列,队列中有数据则自动发送
//模拟随行
if (configProperties.isInventorySimulationFollow() ) {
TransmissionPojo transmissionPojoFollow = new TransmissionPojo(street, transmissionPojo.getRow(),transmissionPojo.getColumn(),transmissionPojo.getDirection(), "");
String s = (transmissionPojoFollow).toString(TransmissionType.GPS);
//放置到队列中,等待取图返回后删除
GetPhotoDelayExecutor.addCameraDelayTask(street.getPlcId(), s, configProperties.getQueueSpanTime(),transmissionPojoFollow);
}
//放置到队列中,等待取图返回后删除
GetPhotoDelayExecutor.addCameraDelayTask(street.getPlcId(), transmissionPojo.toString(TransmissionType.GPS), configProperties.getQueueSpanTime(),transmissionPojo);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
log.error("取图命令 error", e);
} finally {
lock.unlock();
log.info("盘点完成");
}
//滁州开始盘点即取货到位
SCTransmission scTransmission2 = new SCTransmission(street.getPlcId(),plcCmdInfo.getTaskId());
String scTransmissionStr2 = scTransmission2.toSC02String();
ClientChanel.write(scTransmissionStr2,street.getPlcId());
}
Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(orderInfo.getStreetId(), plcCmdInfo.getLeftRight1(), orderInfo.getSeparation(), orderInfo.getRow(), orderInfo.getColumn());
String scanCode = null;
//货物使用球机扫码
checkLog.setTrayCode(trayCode);
log.info("code:{}", scanCode);
//核对异常
Integer status = 1;
@ -837,6 +831,8 @@ public class PlcService {
if (trayCheck && trayGoodCheck ) {
status = 2;
}
checkLog.setStatus(status);
checkLogMapper.updateById(checkLog);
if (stock == null) {
stock = Stock.builder()
.checkNum(plcCmdInfo.getOrderNum())
@ -870,14 +866,138 @@ public class PlcService {
checkLog(stock);
//StockCheckRunnable stockCheckRunnable = new StockCheckRunnable(street,plcCmdInfo,cmdCode,stockMapper,path,checkLogMapper,configProperties.getScanCodeMode().getGoods(),wmsCode,wmsTrayCode,trayCode,trayCheck,configProperties,sensorGun);
// threadPoolExecutor.execute(stockCheckRunnable);
//还原相机
gyrateCameraByCode(cameraId, "C5");
long end = System.currentTimeMillis();
long s = end - startTime;
log.info("time:{}millisecond", s);
long timeLong = end - startTime;
log.info("time:{}millisecond", timeLong);
return true;
}
Boolean scan(int type ,Street street, PlcCmdInfo plcCmdInfo,CheckLog checkLog ,String trayCode){
Boolean checkBoolean = true;
if(type == 2) {
checkBoolean = Boolean.FALSE;
log.info("扫码类型:" + configProperties.getScanCodeMode().getTray());
//托盘使用sick扫码枪
SensorGun sensorGun = sensorService.getSensorByPlc(street.getId(), plcCmdInfo.getLeftRight1());
if (sensorGun == null) {
trayCode = "扫码枪识别异常";
log.error("no sensor gun config in database ,street id:{},direction:{}", street.getId(), plcCmdInfo.getLeftRight1());
} else {
trayCode = SickSocket.readOCR(sensorGun.getIp(), sensorGun.getPort());
log.info("sensor tray code:{}", trayCode);
if ("".equals(plcCmdInfo.getCode())) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
if (StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) {
trayCode = "";
checkBoolean = Boolean.TRUE;
} else {
trayCode = "扫码枪识别异常";
checkBoolean = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
}
} else {
if (StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) {
trayCode = "扫码枪识别异常";
checkBoolean = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
} else {
//扫到就认为正常
checkBoolean = Boolean.TRUE;
}
}
}
}else
if(type == 3){
Set<String> tags = new HashSet<>();
try {
RFIDCheck(plcCmdInfo, true);
Thread.sleep(1000 * configProperties.getRfid().getScanTime());
} catch (Exception e) {
e.printStackTrace();
} finally {
tags = RFIDStop(plcCmdInfo);
log.info("盘点rfid扫描结果" + tags);
}
if (tags !=null && tags.contains(plcCmdInfo.getCode())) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
trayCode = plcCmdInfo.getCode();
checkBoolean = Boolean.TRUE;
} else {
trayCode = trayCode+ "扫码枪识别异常";
checkBoolean = Boolean.FALSE;
log.warn("rfid error:{}", trayCode);
}
}else
if (type == 4){
TransmissionPojo transmissionPojo = new TransmissionPojo(checkLog, street);
if (ClientChanel.get(plcCmdInfo.getPlcId()) != null) {
ClientChanel.get(plcCmdInfo.getPlcId()).writeAndFlush(transmissionPojo.toString(TransmissionType.ST));
} else {
log.error("未找到对应plc" + transmissionPojo.toString());
}
//取货完成进行拍照
try {
Thread.sleep(50L);
//不为其他状态进入队列
if (lock.tryLock()) {
//队列中没有任务,发送取图指令
//只采用队列,队列中有数据则自动发送
//模拟随行
if (configProperties.isInventorySimulationFollow() ) {
TransmissionPojo transmissionPojoFollow = new TransmissionPojo(street, transmissionPojo.getRow(),transmissionPojo.getColumn(),transmissionPojo.getDirection(), "");
String s = (transmissionPojoFollow).toString(TransmissionType.GPS);
//放置到队列中,等待取图返回后删除
GetPhotoDelayExecutor.addCameraDelayTask(street.getPlcId(), s, configProperties.getQueueSpanTime(),transmissionPojoFollow);
}
//放置到队列中,等待取图返回后删除
GetPhotoDelayExecutor.addCameraDelayTask(street.getPlcId(), transmissionPojo.toString(TransmissionType.GPS), configProperties.getQueueSpanTime(),transmissionPojo);
}
} catch (InterruptedException e) {
log.error("取图命令 error", e);
} finally {
lock.unlock();
log.info("盘点完成");
}
}
return checkBoolean;
}
public KsecInfo getKsecDataInfo(TransmissionPojo transmissionPojo, String type) {
KsecDataInfo ksecDataInfo = new KsecDataInfo();
CheckLog checkLog = checkLogMapper.selectById(transmissionPojo.getCheckId());
if(checkLog!=null) {
ksecDataInfo.setLotnum(checkLog.getLotnum());
ksecDataInfo.setSRMNumber(transmissionPojo.getStreetNumber());
ksecDataInfo.setCmdName(type);
ksecDataInfo.setTaskId(checkLog.getTaskId().toString());
ksecDataInfo.setFromDirection(checkLog.getDirection());
ksecDataInfo.setFromColumn(checkLog.getColumn());
ksecDataInfo.setFromRow(checkLog.getRow());
ksecDataInfo.setFromSide(checkLog.getSide());
ksecDataInfo.setCode(checkLog.getCode());
ksecDataInfo.setTrayCode(checkLog.getTrayCode());
ksecDataInfo.setLotnum(checkLog.getLotnum());
}
KsecInfo ksecInfo = new KsecInfo("KC", "E", ksecDataInfo);
return ksecInfo;
}
public void checkLog(Stock stock){
CheckLog checkLog = new CheckLog();
checkLog.setCheckNum(stock.getCheckNum());
@ -984,4 +1104,37 @@ public class PlcService {
}
checkLog(stock);
}
public void visualCalculationResults(TransmissionPojo transmissionPojo) {
CheckLog checkLog = checkLogMapper.selectById(transmissionPojo.getCheckId());
Stock stock = stockMapper.selectOne(new QueryWrapper<Stock>().eq("check_Num", checkLog.getId()));
Street street = streetService.getStreetByPlcId(transmissionPojo.getStreetNumber());
if (transmissionPojo.getResult() != null && transmissionPojo.getResult() == 1) {
checkLog.setStatusVision(StockStatus.SUCCESS.getStatus());
stock.setStatusVision(StockStatus.SUCCESS.getStatus());
} else {
checkLog.setStatusVision(StockStatus.ERROR.getStatus());
stock.setStatusVision(StockStatus.ERROR.getStatus());
stock.setCount(transmissionPojo.getCount());
stock.setCategory(transmissionPojo.getCategory());
}
if (transmissionPojo.getPcd() != null && !"".equals(transmissionPojo.getPcd())) {
stock.setPcd("http://" + street.getPlcIp() + ":8007" + transmissionPojo.getPcd());
}
if (transmissionPojo.getPicsPath() != null && transmissionPojo.getPicsPath().size() > 0) {
String pics = transmissionPojo.getPicsPath().stream().map(v -> {
return "http://" + street.getPlcIp() + ":8007" + v;
}).collect(Collectors.joining(";"));
checkLog.setPic(pics);
stock.setCheckPic(pics);
}
checkLogMapper.updateById(checkLog);
stockMapper.updateById(stock);
}
public void saveFollowPhoto(TransmissionPojo transmissionPojo) {
}
}

@ -1,8 +1,9 @@
package com.zhehekeji.web.service.client;
import com.zhehekeji.web.entity.Stock;
import com.zhehekeji.web.lib.CameraDelayTask;
import com.zhehekeji.web.service.PlcService;
import com.zhehekeji.web.service.ksec.*;
import com.zhehekeji.web.service.ksec.KsecInfo;
import com.zhehekeji.web.service.ksec.KsecNettyClient;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
@ -12,15 +13,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.Charset;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import static com.zhehekeji.web.service.ksec.KsecDecoder.ksecInfoMap;
import static org.aspectj.weaver.tools.cache.SimpleCacheFactory.path;
/**
*
*/
@ -29,13 +25,24 @@ public class Decoder extends DelimiterBasedFrameDecoder {
private static final Logger tcpLogger = LoggerFactory.getLogger("tcp");
public static String PT_CLIENT = "PT";
private static String WCS_CLIENT = "WCS";
private static String EMPTY_CLIENT = "EMPTY";
public static String START_CHECK = "ST";
private static String GET_PHOTO = "GP";
private static String GET_PHOTO_END = "GPE";
private static String RETURN_CHECK = "RTE";
private static String FOLLOW_GET_PHOTO_END = "SGPE";
private static String END_CHECK = "EN";
private static String HEART_BEAT = "HB";
private static String CONNECT_START = "CE";
private static String END_STRING = "$";
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,15,30, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(20000));
private PlcService plcService;
public Decoder(PlcService plcService) {
@ -76,70 +83,54 @@ public class Decoder extends DelimiterBasedFrameDecoder {
@Override
public void run() {
String body = in.toString(Charset.forName("UTF-8"));
tcpLogger.info("receive client:{}, data length:{}",body, body.length());
//视觉服务
{
if(body.startsWith(HBTransmission.getHEADER())) {
//心跳
HBTransmission hbTransmission = new HBTransmission(body);
//回复客户端心跳
ctx.channel().writeAndFlush(hbTransmission.toString());
ClientChanel.connect(hbTransmission.getSRMNumber(), ctx.channel());
//tcpLogger.info("client:{} heart", hbTransmission.getSRMNumber());
in.release();
} else if(body.startsWith(SCTransmission.getHeader())){
//盘点指令
SCTransmission scTransmission = new SCTransmission(body);
if(scTransmission.isCollectOver()){
//给普天发送数据采集完毕指令
KsecDataInfo ksecDataInfo = ksecInfoMap.get(scTransmission.getTaskNo());
ksecDataInfo.setCmdName("E2");
KsecInfo ksecInfo = new KsecInfo("KC","E",ksecDataInfo);
KsecNettyClient.write(ksecInfo);
}else {
plcService.visualInventory(scTransmission);
KsecDataInfo ksecDataInfo = ksecInfoMap.get(scTransmission.getTaskNo());
ksecDataInfo.setCmdName("E3");
ksecDataInfo.setQuantity(scTransmission.getRstCount());
ksecDataInfo.setTypeNum(scTransmission.getRstCategory());
ksecDataInfo.setCheckRlt(Integer.parseInt(scTransmission.getCheckRst()));
KsecInfo ksecInfo = new KsecInfo("KC","E",ksecDataInfo);
KsecNettyClient.write(ksecInfo);
ksecInfoMap.remove(scTransmission.getTaskNo());
//添加到实时信息里
//RealtimeCheckMap.put(scTransmission.getSRMNumber(),scTransmission.checkInfo());
//更新盤點統計
// emptyCheckService.updateCheckLastTime(tmTransmission.getTaskNo(),tmTransmission.getSRMNumber(),stock.getCode());
}
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();
tcpLogger.info("receive client:{}, data length:{}", body, body.length());
TransmissionPojo transmissionPojo = new TransmissionPojo(body);
//心跳进行连接
if(HEART_BEAT.equals(transmissionPojo.getHeader()) || CONNECT_START.equals(transmissionPojo.getHeader())){
ClientChanel.connect(transmissionPojo.getStreetNumber(),ctx.channel());
}
//获取照片后发送进行计算逻辑,并在拍照队列中取出拍照发送
else if(GET_PHOTO_END.equals(transmissionPojo.getHeader())){
if(transmissionPojo.getTaskId() != null && !"0".equals(transmissionPojo.getTaskId())) {
ClientChanel.get(transmissionPojo.getStreetNumber()).writeAndFlush(transmissionPojo.toString(TransmissionType.RTS));
// GetPhotoDelayExecutor.addCameraDelayTask(transmissionPojo.getStreetNumber(), transmissionPojo.toString(TransmissionType.RTS), 3000);
}
try {
Thread.sleep(50L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
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();
//删除队列的拍照数据
GetPhotoDelayExecutor.remove(transmissionPojo.getStreetNumber(),transmissionPojo);
//读取下一个发送
CameraDelayTask cameraDelayTask = GetPhotoDelayExecutor.nextOne(transmissionPojo.getStreetNumber(),transmissionPojo.toString(TransmissionType.GPS));
if (cameraDelayTask != null) {
TransmissionPojo pojo = new TransmissionPojo(cameraDelayTask.getCommand());
ClientChanel.get(pojo.getStreetNumber()).writeAndFlush(pojo.toString(TransmissionType.GPS));
}
// else if (body.contains("EMPTY_CLIENT")){
// ClientChanel.connect(EMPTY_CLIENT_NAME, ctx.channel());
// tcpLogger.info("client:{} connect", EMPTY_CLIENT_NAME);
// in.release();
// }
}
//照片和结果保存,并发送给上位机
else if(RETURN_CHECK.equals(transmissionPojo.getHeader())){
//保存数据
plcService.visualCalculationResults(transmissionPojo);
//发送给上位机
KsecInfo ksecInfo = plcService.getKsecDataInfo(transmissionPojo,"E");
ksecInfo.getData().setTypeNum(transmissionPojo.getCategory());
ksecInfo.getData().setQuantity(transmissionPojo.getCount());
ksecInfo.getData().setCheckRlt(transmissionPojo.getResult());
KsecNettyClient.write(ksecInfo);
GetPhotoDelayExecutor.removeTask(transmissionPojo.getStreetNumber(), transmissionPojo);
}
//照片和结果保存,并发送给上位机
else if(FOLLOW_GET_PHOTO_END.equals(transmissionPojo.getHeader())){
//保存数据
plcService.saveFollowPhoto(transmissionPojo);
}
}
}
}

@ -0,0 +1,208 @@
package com.zhehekeji.web.service.client;
import com.zhehekeji.common.util.SpringContextUtil;
import com.zhehekeji.web.entity.Street;
import com.zhehekeji.web.lib.CameraDelayTask;
import com.zhehekeji.web.service.PlcService;
import com.zhehekeji.web.service.ksec.KsecInfo;
import com.zhehekeji.web.service.ksec.KsecNettyClient;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* GetPhotoDelayExecutor
*/
@Slf4j
public class GetPhotoDelayExecutor {
// 延时队列存放CameraDelayTask任务
public static Map<String, DelayQueue<CameraDelayTask>> cameraDelayTaskMap = new ConcurrentHashMap<>();
// 线程池,用于执行延时任务
public static DelayQueue<CameraDelayTask> delayTasks = new DelayQueue<>();
private static ExecutorService exec = Executors.newFixedThreadPool(15);
/**
*
*
* @param plcId PLC
* @param getPhotoCommand
* @param time
*/
public static void addCameraDelayTask(String plcId, String getPhotoCommand, long time,TransmissionPojo transmissionPojo) {
// 如果队列为空,则直接发送命令
if(cameraDelayTaskMap.get(plcId)==null || cameraDelayTaskMap.get(plcId).size() == 0) {
if( ClientChanel.get(plcId) != null){
log.info("队列中无数据,输出"+getPhotoCommand);
ClientChanel.get(plcId).writeAndFlush(getPhotoCommand);
}else {
log.info("队列中无数据,未找到通信"+plcId);
}
}
// 创建一个CameraDelayTask对象并将其添加到队列中
CameraDelayTask cameraDelayTask = new CameraDelayTask(plcId, getPhotoCommand, time,transmissionPojo);
if(cameraDelayTaskMap.get(plcId)!=null){
cameraDelayTaskMap.get(plcId).add(cameraDelayTask);
}else {
cameraDelayTaskMap.put(plcId,new DelayQueue<>());
cameraDelayTaskMap.get(plcId).add(cameraDelayTask);
}
delayTasks.add(cameraDelayTask);
}
/**
* PLC
*
* @param plcId
*/
public static CameraDelayTask remove(String plcId, TransmissionPojo transmissionPojo) {
synchronized (plcId) {
// 将延时队列中的任务转换为数组,便于遍历和移除
Object[] objects = cameraDelayTaskMap.get(plcId).toArray();
if(objects.length > 0) {
for(Object object : objects){
CameraDelayTask cameraDelayTask = (CameraDelayTask)object;
if (cameraDelayTask != null
&& cameraDelayTask.getTransmissionPojo().getTaskId().equals(transmissionPojo.getTaskId())
&& cameraDelayTask.getTransmissionPojo().getCheckId().equals(transmissionPojo.getCheckId())
&& cameraDelayTask.getTransmissionPojo().getDirection().equals(transmissionPojo.getDirection())) {
cameraDelayTaskMap.get(plcId).remove(cameraDelayTask);
return cameraDelayTask;
}
}
}
}
return null;
}
public static CameraDelayTask removeTask(String plcId, TransmissionPojo transmissionPojo) {
synchronized (plcId){
// 将延时队列中的任务转换为数组,便于遍历和移除
Object[] objects = delayTasks.toArray();
if(objects.length > 0) {
for(Object object : objects){
CameraDelayTask cameraDelayTask = (CameraDelayTask)object;
if (cameraDelayTask != null
&& cameraDelayTask.getTransmissionPojo().getTaskId().equals(transmissionPojo.getTaskId())
&& cameraDelayTask.getTransmissionPojo().getCheckId().equals(transmissionPojo.getCheckId())
&& cameraDelayTask.getTransmissionPojo().getDirection().equals(transmissionPojo.getDirection())) {
delayTasks.remove(cameraDelayTask);
return cameraDelayTask;
}
}
}
}
return null;
}
public static CameraDelayTask nextOne(String plcId, String getPhotoCommand) {
plcId = plcId.intern();
synchronized (plcId) {
// 将延时队列中的任务转换为数组,便于遍历和移除
Object[] objects = cameraDelayTaskMap.get(plcId).toArray();
if(objects.length > 0) {
CameraDelayTask cameraDelayTask = (CameraDelayTask)objects[0];
if (cameraDelayTask != null) {
return cameraDelayTask;
}
}
}
return null;
}
/**
*
*/
public static void runExecutor(List<Street> streets ) {
for (Street street: streets){
exec.execute(new Consumer(street));
}
exec.execute(new TaskConsumer());
}
/**
* ConsumerRunnable
*/
private static class Consumer implements Runnable {
private Street street;
Consumer(Street street){
this.street = street;
}
/**
*
*/
@Override
public void run() {
while (true) {
try {
// 从Spring上下文中获取PlcService实例
PlcService plcService = SpringContextUtil.getBean(PlcService.class);
// 从延时队列中获取并移除一个任务
if (cameraDelayTaskMap.get(street.getPlcId())!=null) {
CameraDelayTask cameraDelayTask = cameraDelayTaskMap.get(street.getPlcId()).take();
// if (cameraDelayTask != null) {
// // 构造传输对象,并将任务命令等信息设置进去
// TransmissionPojo transmissionPojo = new TransmissionPojo(cameraDelayTask.getCommand());
// // 调用PLC服务模拟发送数据到上位机
// KsecInfo ksecInfo = plcService.getKsecDataInfo(transmissionPojo, "E");
// ksecInfo.getData().setTypeNum(transmissionPojo.getCategory());
// ksecInfo.getData().setQuantity(transmissionPojo.getCount());
// ksecInfo.getData().setCheckRlt(0);
// // 将信息发送给上位机
// if (!transmissionPojo.getTaskId().equals("0"))
// KsecNettyClient.write(ksecInfo);
// }
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private static class TaskConsumer implements Runnable {
/**
*
*/
@Override
public void run() {
while (true) {
try {
// 从Spring上下文中获取PlcService实例
PlcService plcService = SpringContextUtil.getBean(PlcService.class);
// 从延时队列中获取并移除一个任务
CameraDelayTask cameraDelayTask = delayTasks.take();
if (cameraDelayTask != null) {
// 构造传输对象,并将任务命令等信息设置进去
TransmissionPojo transmissionPojo = new TransmissionPojo(cameraDelayTask.getCommand());
// 调用PLC服务模拟发送数据到上位机
KsecInfo ksecInfo = plcService.getKsecDataInfo(transmissionPojo, "E");
ksecInfo.getData().setTypeNum(transmissionPojo.getCategory());
ksecInfo.getData().setQuantity(transmissionPojo.getCount());
ksecInfo.getData().setCheckRlt(0);
// 将信息发送给上位机
if (!transmissionPojo.getTaskId().equals("0"))
KsecNettyClient.write(ksecInfo);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}

@ -0,0 +1,164 @@
package com.zhehekeji.web.service.client;
import com.zhehekeji.web.entity.CheckLog;
import com.zhehekeji.web.entity.Street;
import lombok.Data;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@Data
public class TransmissionPojo {
private String data;
private String[] dataArray;
private String header;
private String streetNumber;//巷道标识符
private Integer row;//行
private Integer column;//列
private String pcd;//点位文件路径
private String taskId;
private String checkId;
private Integer direction;//左右
private Integer count = 0; //数量
private String category = ""; //品规
private Set<String> picsPath; //照片
private Integer result;
public TransmissionPojo(CheckLog checkLog , Street street){
this.checkId = checkLog.getId().toString();
this.streetNumber = street.getPlcId();
this.taskId = checkLog.getLotnum();
this.row = checkLog.getRow();
this.column = checkLog.getColumn();
this.direction = checkLog.getDirection();
this.count = checkLog.getWmsCount();
if(checkLog.getCategory() != null && checkLog.getCategory().contains("/")) {
this.category = checkLog.getWmsCategory().split("/")[0];
}else {
this.category = checkLog.getCategory();
}
}
/**
* 30
*
* @param number
* @param length 3
* @return
*/
public static String convertNumberToFixedLengthChars(int number, int length) {
if (length < 1) {
throw new IllegalArgumentException("Length must be a positive integer.");
}
String numStr = Integer.toString(number);
while (numStr.length() < length) {
numStr = "0" + numStr;
}
return numStr;
}
public TransmissionPojo( Street street,Integer row , Integer column,Integer direction,String orderId){
this.streetNumber = street.getPlcId();
this.row = row;
this.taskId = "0";
this.direction = direction;
this.column = column;
this.checkId = convertNumberToFixedLengthChars(row, 3) + convertNumberToFixedLengthChars(column, 3);
}
public String toString(TransmissionType type) {
this.header = type.toString();
if (type == TransmissionType.ST) {
return "ST&" + streetNumber + "&" + checkId + "&" + taskId + "&" + direction ;
}else if (type == TransmissionType.GPS) {
return "GPS&" + streetNumber +"/"+row +"/"+column+ "&" + checkId + "&" + taskId + "&" + direction+ "&" + category + "&" + count;
}else if (type == TransmissionType.RTS) {
return "RTS&" + streetNumber +"/"+row +"/"+column+ "&" + checkId + "&" + taskId + "&" + direction + "&" + category + "&" + count;
}
return "";
}
public TransmissionPojo(String data) {
this.data = data;
data = data.replace(">", "");
this.dataArray = data.split("&");
this.header = dataArray[0];
if(dataArray[1].contains("/")) {
String[] dataArr = dataArray[1].split("/");
this.streetNumber = dataArr[0];
this.row = Integer.valueOf(dataArr[1]);
if(dataArr.length > 2) {
this.column = Integer.valueOf(dataArr[2]);
}
}else {
this.streetNumber = dataArray[1];
}
if (dataArray.length > 2) {
this.checkId = dataArray[2];
this.taskId = (dataArray[3]);
if(dataArray[4] != null && !"".equals(dataArray[4]) && !"null".equals(dataArray[4])) {
this.direction = Integer.valueOf(dataArray[4]);
}
}
if (dataArray.length > 5) {
if(dataArray[5] != null &&!"".equals(dataArray[5]) && !"null".equals(dataArray[5]) ) {
this.category = dataArray[5];
}
if( dataArray.length > 6 && dataArray[6] != null && !"".equals(dataArray[6]) && ! "null".equals(dataArray[5])) {
this.count = Integer.valueOf(dataArray[6]);
}
}
if (dataArray.length > 7) {
this.result = Integer.parseInt(dataArray[7])==0 ?0:1;
//不记录2d图像
//String path2D = "/fileData/"+this.taskId+"/"+this.checkId+"/"+this.direction+".jpg";
String path3D ;
if((this.taskId!=null) && !"".equals(this.taskId)){
path3D = "/fileData/"+this.taskId+"/"+this.checkId+"/"+(this.direction+2)+".PNG";
}else {
path3D = "/fileData/"+this.checkId+"/"+(this.direction+2)+".PNG";
}
Set<String> strings = new HashSet<>();
//strings.add(path2D);
strings.add(path3D);
// 将数组中的元素添加到 Set 集合中
if(dataArray.length > 8 && dataArray[8].split(";").length>0) {
String[] s = dataArray[8].split(";");
for (int i = 0; i < s.length; i++) {
s[i] = s[i].replace("\\\\","/");
s[i] = s[i].replace("\\","/");
if(s[i].startsWith(".")) {
s[i] = s[i].replaceFirst(".", ""); // 移除单个字符
}
// 或者
// stringArray[i] = stringArray[i].replaceAll(regexToRemove, ""); // 使用正则表达式移除字符类别
}
Collections.addAll(strings,s);
strings.remove("");
}
this.picsPath = strings;
}
if(this.taskId != null && !"".equals(this.taskId) && this.checkId != null && !"".equals(this.checkId))
this.pcd = "/fileData/"+this.taskId+"/"+this.checkId+"/"+(this.direction+2)+".pcd";
}
public static void main(String[] args) {
//2024-05-31 17:52:07,909 INFO (Decoder.java:96)- receive client:RTE&001/1/9&2812&&2&0341&30&1&.\fileData\\2812\4.PNG;\fileData\\2812\2_0341_rlt.jpg&.\fileData\\2812\4.pcd, data length:106
TransmissionPojo transmissionPojo = new TransmissionPojo("RTE&001/1/9&2812&&2&0341&30&1&.\\fileData\\\\2812\\4.PNG;\\fileData\\\\2812\\2_0341_rlt.jpg&.\\fileData\\\\2812\\4.pcd>");
System.out.println(transmissionPojo);
}
}

@ -0,0 +1,14 @@
package com.zhehekeji.web.service.client;
public enum TransmissionType {
ST ,
GPS ,
GPE ,
SGPS ,
SGPE ,
RTS ,
RTE ,
EN ,
ZHB ;
}

@ -103,6 +103,12 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder {
plcCmdInfo.setQuantity(dataInfo.getQuantity());
srmNumber = dataInfo.getSRMNumber();
cmdName = dataInfo.getCmdName();
if(dataInfo.getCode()!=null && !"".equals(dataInfo.getCode())){
plcCmdInfo.setCode(dataInfo.getCode());
}else if(dataInfo.getTrayCode()!=null && !"".equals(dataInfo.getTrayCode())){
plcCmdInfo.setCode(dataInfo.getTrayCode());
}
}
if (Cmd.A.name().equals(ksecInfo.getType())) {
//心跳
@ -193,7 +199,7 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder {
plcCmdInfo.setTimes(1);
ksecInfoMap.put(dataInfo.getTaskId(),dataInfo);
Boolean ok = plcService.check(plcCmdInfo,ksecInfo.getData().getCmdName(), dataInfo.getCode(), dataInfo.getTrayCode(), dataInfo.getLotnum());
Boolean ok = plcService.check(plcCmdInfo,ksecInfo.getData().getCmdName(), plcCmdInfo.getCode(), plcCmdInfo.getCode(), dataInfo.getLotnum());
// Boolean ok = true;
if(ok){
ksecInfo.getData().setAckStatus(1);

@ -31,7 +31,6 @@ cameraConfig:
cameraPassword: a1234567
cameraUser: admin
cameraPort: 8000
videoServer: 127.0.0.1:8083
#相机抓图延迟 毫秒,这个延迟是等待球机球机转动到位,然后拍照的
delayCaptureTime: 3500
#随行模式下的相机抓图延迟 毫秒,这个延迟是等待球机球机转动到位,然后拍照的
@ -87,7 +86,7 @@ lightSource:
# -----goods 货物
# 扫码模式 0:此处不盘点 1球机扫码 2sick扫码枪 3:南北达RFID 4.南京视觉客户端(只支持货物盘点)
scanCodeMode:
tray: 3
tray: 2
goods: 4
goodsCodeTypes:
- 14

Loading…
Cancel
Save