区域修改

昆船链接
无限重连
记录照片少两张
扫码返回非回车
视频时间可以修改
扫码,返回,拍照
清空盘点
扫码超时未返回
盘点历史,只记录一条
拍照间隔
hebei-cangzhouyancao
LAPTOP-S9HJSOEB\昊天 3 years ago
parent 6cb148ff3e
commit bba056ce43

@ -1,5 +1,6 @@
package com.leaper.web.config;
import io.swagger.models.auth.In;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ -63,6 +64,9 @@ public class ConfigProperties {
private Long B2OutDelayTime;
private Long delayDownloadMp4;
private Long rotationPhotographyInterval = 0L;
private Long originInterval = 0L;
}
@ -82,6 +86,10 @@ public class ConfigProperties {
public static class KSEC{
private String ip;
private Integer port;
private Integer reconnectNum;
private Long reconnectInterval;
private Long downloadStartMp4 = 0L ;
private Long downloadEndMp4 = 0L ;
}
@Data
@ -98,5 +106,9 @@ public class ConfigProperties {
private Integer goods;
private int [] goodsCodeTypes;
private int [] trayCodeTypes;
private Integer checkScanCodeInterval;
private Integer checkPhotographyInterval;
private Integer checkPhotographyScanCodeInterval;
}
}

@ -45,7 +45,7 @@ public class RealTimeController {
@ApiOperation(value = "全部库区")
//@SessionHandler
public Result<Set<String>> allAreas() {
return Result.success(realTimeService.allAreas());
return Result.success();
}
@GetMapping("/allCamerasByArea")

@ -113,7 +113,12 @@ public class StockController {
validatorUtil.validate(stockCheck);
return Result.success(stockService.stockInfo(stockCheck));
}
@ApiOperation(value = "清空所有盘点")
@RequestMapping(value = "/clearStock", method = RequestMethod.GET)
public Result<Stock> clearStock() {
stockService.clearStock();
return Result.success();
}
@ApiOperation(value = "获取盘点信息")
@RequestMapping(value = "/checkInfo", method = RequestMethod.POST)
public Result<Stock> checkInfo(@RequestBody StockCheckSearch stockCheck) {

@ -13,11 +13,13 @@ import java.time.LocalDateTime;
public class CheckLog {
@TableField("`street_Id`")
private Integer streetId;
@TableField(exist = false)
private String streetName;
@TableField("`direction`")
private Integer direction;
private Integer side;

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

@ -61,5 +61,6 @@ public class Street {
/**
*
*/
@TableField(exist = false)
private String area;
}

@ -19,6 +19,9 @@ public class OrderInfo {
private Integer row;
private Integer side;
private Integer column;
private String code;
@ -54,11 +57,13 @@ public class OrderInfo {
leftRight = plcCmdInfo.getLeftRight1();
row = plcCmdInfo.getRow1();
column = plcCmdInfo.getColumn1();
side = plcCmdInfo.getSide1();
separation = plcCmdInfo.getSeparation1();
} else if (times == 4 || times == 3) {
leftRight = plcCmdInfo.getLeftRight2();
row = plcCmdInfo.getRow2();
column = plcCmdInfo.getColumn2();
side = plcCmdInfo.getSide2();
separation = plcCmdInfo.getSeparation2();
}
streetId = street.getId();

@ -1,5 +1,7 @@
package com.leaper.web.lib.hik;
import com.leaper.common.util.SpringContextUtil;
import com.leaper.web.config.ConfigProperties;
import com.leaper.web.lib.CameraConnMap;
import com.leaper.web.lib.joyware.NetSDKLib;
import com.sun.jna.ptr.IntByReference;
@ -254,6 +256,12 @@ public class HikCameraControlModuleImpl implements CameraControlModule {
public void downloadMp4(Integer cameraId, String path, LocalDateTime start, LocalDateTime end) {
ConfigProperties configProperties = SpringContextUtil.getBean(ConfigProperties.class);
start = start.minusNanos(1000000000 * configProperties.getKsec().getDownloadStartMp4());
end = end.minusNanos(1000000000 * configProperties.getKsec().getDownloadEndMp4());
PathUtil.checkDirc(path);
HCNetSDK.NET_DVR_TIME startTime = new HCNetSDK.NET_DVR_TIME();
startTime.setTime(start.getYear(), start.getMonthValue(), start.getDayOfMonth(), start.getHour(), start.getMinute(), start.getSecond());

@ -0,0 +1,16 @@
package com.leaper.web.pojo;
import com.leaper.web.entity.Street;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class TrayCode {
Street street ;
//托盘码
String trayCode = null;
Boolean trayCheck = Boolean.TRUE;
}

@ -52,6 +52,7 @@ public class CheckLogService {
if(search.getStreetId() != null && search.getStreetId() != 0){
wrapper.eq("`street_id`",search.getStreetId());
}
wrapper.orderByDesc("create_time");
List<CheckLog>stockChecks = checkLogMapper.selectList(wrapper);
stockChecks.forEach(l->{
l.setStreetName(map.get(l.getStreetId()));

@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Description
@ -15,7 +16,7 @@ import java.util.Map;
@Slf4j
public class GoodsActionTimes {
private static Map<String, Integer> orderActions = new HashMap<>();
private static Map<String, Integer> orderActions = new ConcurrentHashMap<>();
/**
*

@ -1,21 +1,18 @@
package com.leaper.web.service;
import codeDetector.BarcodeDetector;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.leaper.web.entity.*;
import com.leaper.web.lib.CameraControlModule;
import com.leaper.web.lib.OrderInfo;
import com.leaper.web.lib.OrderRealtime;
import com.leaper.web.lib.TaskDelayExecutor;
import com.leaper.web.mapper.*;
import com.leaper.web.service.RFID.RFIDSocket;
import com.leaper.common.util.PathUtil;
import com.leaper.web.config.ConfigProperties;
import com.leaper.web.entity.*;
import com.leaper.web.lib.*;
import com.leaper.web.mapper.*;
import com.leaper.web.pojo.OrderVO;
import com.leaper.web.service.RFID.RFIDMap;
import com.leaper.web.pojo.TrayCode;
import com.leaper.web.service.RFID.RFIDSocket;
import com.leaper.web.service.hikLightSource.HikControlSocket;
import com.leaper.web.service.ksec.KsecNettyClient;
import com.leaper.web.service.sick.SickSocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
@ -25,8 +22,8 @@ import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@ -138,16 +135,16 @@ public class PlcService {
*
* @param plcCmdInfo
*/
public void orderStop(PlcCmdInfo plcCmdInfo) {
public boolean orderStop(PlcCmdInfo plcCmdInfo) {
LocalDateTime endTime = LocalDateTime.now();
Street street = streetMapper.getStreetByPlcId(plcCmdInfo.getPlcId());
if (street == null) {
return;
return false;
}
Order order = orderMapper.getOneByOrderNum(plcCmdInfo.getOrderNum());
if (order == null) {
log.error("订单结束信号订单不存在orderNum:{}", plcCmdInfo.getOrderNum());
return;
return false;
}
OrderRealtime.stopOrder(street.getId());
Order update = new Order();
@ -157,7 +154,7 @@ public class PlcService {
update.setLeftRight2(plcCmdInfo.getLeftRight2());
update.setColumn2(plcCmdInfo.getColumn2());
update.setRow2(plcCmdInfo.getRow2());
LocalDateTime endDownLoadTime = endTime.plusSeconds(10);
LocalDateTime endDownLoadTime = endTime.plusSeconds(5);
Duration duration = Duration.between(order.getStartTime(),endDownLoadTime);
if(duration.toMinutes() > 50){
@ -172,7 +169,7 @@ public class PlcService {
update.setVideoPath2(path);
}
orderMapper.updateById(update);
return true;
}
public void orderStopByWarn(String orderNum) {
@ -462,16 +459,17 @@ public class PlcService {
//update picPath in stock if code is C2/C4
if(orderInfo.getCode().startsWith("C2") || orderInfo.getCode().startsWith("C4")){
StockLog stockLog = new StockLog();
stockLog.setStreetId(orderInfo.getStreetId());
stockLog.setDirection(orderInfo.getLeftRight());
stockLog.setSide(orderInfo.getSeparation());
stockLog.setStreetId(order.getStreetId());
stockLog.setRow(orderInfo.getRow());
stockLog.setColumn(orderInfo.getColumn());
stockLog.setPic(path);
String type = orderInfo.getCode().substring(1,2);
stockLog.setType(Integer.valueOf(type));
stockLog.setOrderNum(orderInfo.getOrderNum());
stockLog.setCreateTime(LocalDateTime.now());
stockLog.setDirection(order.getLeftRight1());
stockLog.setSide(orderInfo.getSide());
stockLogMapper.insert(stockLog);
// Stock stock = stockMapper.getByShelveIdAndRowColumn(orderInfo.getShelveId(), orderInfo.getRow(), orderInfo.getColumn());
// if (stock == null) {
@ -523,6 +521,7 @@ public class PlcService {
if (street.getCamera1Id() != null && street.getCamera2Id() != null && street.getCamera1Id() != 0 && street.getCamera2Id() != 0) {
if (leftRight == 1) {
return street.getCamera2Id();
} else {
return street.getCamera1Id();
}
@ -533,12 +532,48 @@ public class PlcService {
}else {
if (street.getCamera1Id() != null && street.getCamera2Id() != null && street.getCamera1Id() != 0 && street.getCamera2Id() != 0) {
//双伸 todo 这个因项目而异,看现场的情况
//默认是 左侧返回camera2 右侧返回camera1
//默认是
if(plcCmdInfo.getTimes() <= 2){
//左侧
if(plcCmdInfo.getLeftRight1() == 1){
if(plcCmdInfo.getSeparation1() == 1){
//左侧 内货架 camera2
return street.getCamera2Id();
}else {
//左侧 外货架 camera1
return street.getCamera2Id();
}
}else {
if(plcCmdInfo.getSeparation1() == 1){
//右侧 内货架 camera1
return street.getCamera1Id();
}else {
//右侧 外货架 camera2
return street.getCamera1Id();
}
}
}else {
//左侧
if(plcCmdInfo.getLeftRight2() == 1){
if(plcCmdInfo.getSeparation2() == 1){
//左侧 内货架 camera2
return street.getCamera2Id();
}else {
//左侧 外货架 camera1
return street.getCamera2Id();
}
}else {
if(plcCmdInfo.getSeparation2() == 1){
//右侧 内货架 camera1
return street.getCamera1Id();
}else {
//右侧 外货架 camera2
return street.getCamera1Id();
}
}
}
} else {
Integer cameraId = street.getCamera1Id() != null && street.getCamera1Id() != 0 ? street.getCamera1Id() : street.getCamera2Id();
return cameraId;
@ -561,59 +596,271 @@ public class PlcService {
HikControlSocket.openLight(lightSource.getIp(),lightSource.getPort(),configProperties.getLightSource().getIndex(),1);
});
Integer cameraId = getCameraByPlcCmd(plcCmdInfo,plcCmdInfo.getLeftRight1());
log.info("taskId:{}", plcCmdInfo.getTaskId());
if(plcCmdInfo.getSeparation1() == 1 && configProperties.getScanCodeMode().getTray() == 2){
//内测
String c = cmdCode + "-" + plcCmdInfo.getLeftRightStr(1) + "-IN";
log.info("camera ptz"+c);
gyrateCameraByCode(cameraId, c);
try {
Thread.sleep(configProperties.getScanCodeMode().getCheckScanCodeInterval());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//托盘码
String trayCode = null;
Boolean trayCheck = Boolean.TRUE;
log.info("3");
//重庆项目 单伸,只用扫码枪
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 {
log.info("sensor ip:{},port:{}",sensorGun.getIp(),sensorGun.getPort());
//不确定扫码方式暂时停用
trayCode = SickSocket.readOCR(sensorGun.getIp(),sensorGun.getPort());
trayCode = trayCode.substring(trayCode.length()-4);
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 {
gyrateCameraByCode(cameraId, cmdCode);
trayCheck = wmsTrayCode.equals(trayCode);
}
}
}
try {
Thread.sleep(configProperties.getScanCodeMode().getCheckPhotographyScanCodeInterval());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
String path = PathUtil.createFileNameByRowColumn("jpg",cameraId,plcCmdInfo.getRow1(),plcCmdInfo.getColumn1());
//重庆亚士创能盘点时用同侧相机拍摄货物顶部(E1-TOP)
Integer leftRightTop = plcCmdInfo.getLeftRight1() == 1 ? 2 : 1;
Integer cameraIdTop = getCameraByPlcCmd(plcCmdInfo, leftRightTop);
String cameraCmdCode1 = cmdCode;
// if(plcCmdInfo.getSeparation1() == 1 && configProperties.getScanCodeMode().getTray() == 2){
// //内测
cameraCmdCode1 = cmdCode + "-" + "TOP";
// }
log.info("1 camera ptz:"+cameraCmdCode1);
gyrateCameraByCode(cameraIdTop, cameraCmdCode1);
cameraCapture(cameraIdTop,false,null,path);
//重庆亚士创能盘点时用对侧球机拍侧面层数(E1-SIDE)
String cameraCmdCode2 = cmdCode + "-" + "SIDE";
gyrateCameraByCode(cameraId, cameraCmdCode2);
log.info("2 camera ptz:"+cameraCmdCode2);
cameraCapture(cameraId,false,null,path+".jpg");
OrderInfo orderInfo = new OrderInfo(street,plcCmdInfo,1,cmdCode);
Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(orderInfo.getStreetId(),orderInfo.getLeftRight(),orderInfo.getSeparation(),orderInfo.getRow(),orderInfo.getColumn());
//核对异常
Integer status = 1;
//托盘和货物都正确
if(trayCheck){
status = 2;
}
if(stock == null){
stock = Stock.builder()
.checkNum(plcCmdInfo.getOrderNum())
.lotnum(plcCmdInfo.getLotnum())
.code("")
.wmsCode(wmsCode)
.wmsTrayCode(wmsTrayCode)
.trayCode("")
.streetId(orderInfo.getStreetId())
.direction(orderInfo.getLeftRight())
.side(orderInfo.getSeparation())
.row(orderInfo.getRow())
.column(orderInfo.getColumn())
.status(0)
.checkPic(path)
.exportTime(LocalDateTime.now())
.build();stockMapper.insert(stock);
}else {
stock.setStatus(status);
stock.setLotnum(plcCmdInfo.getLotnum());
stock.setExportTime(LocalDateTime.now());
stock.setCheckPic(path);
stock.setCheckNum(plcCmdInfo.getOrderNum());
stock.setTrayCode(trayCode);
stock.setWmsTrayCode(wmsTrayCode);
stockMapper.updateById(stock);
}
checkLog(stock);
long end = System.currentTimeMillis();
long s = end - startTime;
log.info("time:{}millisecond",s);
return true;
}
public TrayCode checkScanCode(PlcCmdInfo plcCmdInfo, String cmdCode, String wmsCode, String wmsTrayCode ){
try {
Thread.sleep(configProperties.getCameraConfig().getDelayCaptureTime());
Thread.sleep(configProperties.getScanCodeMode().getCheckScanCodeInterval());
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
Street street = streetService.getStreetByPlcId(plcCmdInfo.getPlcId());
//托盘码
String trayCode = null;
Boolean trayCheck = Boolean.TRUE;
//重庆项目 单伸,只用扫码枪
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 {
log.info("sensor ip:{},port:{}",sensorGun.getIp(),sensorGun.getPort());
//不确定扫码方式暂时停用
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 {
trayCode = trayCode.substring(trayCode.length()-4);
trayCheck = Long.parseLong(wmsTrayCode) == Long.parseLong(trayCode);
}
}
}
return new TrayCode(street,trayCode,trayCheck);
}
public static void main(String[] args) {
System.out.println(Long.parseLong("0999") == Long.parseLong("999"));
}
public Boolean checkPhotography(PlcCmdInfo plcCmdInfo,String cmdCode,String wmsCode,String wmsTrayCode,TrayCode trayCode){
Street street =trayCode.getStreet();
String path = PathUtil.createFileNameByRowColumn("jpg",cameraId,plcCmdInfo.getRow1(),plcCmdInfo.getColumn1());
//拍照暂停1s再拍
try {
Thread.sleep(1000l);
Thread.sleep(configProperties.getScanCodeMode().getCheckPhotographyScanCodeInterval());
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
cameraCapture(cameraId,false,null,path);
//成都蜜雪冰城 只拍照人工核对
long startTime = System.currentTimeMillis();
CronTab.putTime(street.getId());
List<LightSource> lightSources = lightSourceMapper.selectList(new QueryWrapper<LightSource>().eq("street_id",street.getId()));
lightSources.forEach(lightSource -> {
HikControlSocket.openLight(lightSource.getIp(),lightSource.getPort(),configProperties.getLightSource().getIndex(),1);
});
Integer cameraId = getCameraByPlcCmd(plcCmdInfo,plcCmdInfo.getLeftRight1());
log.info("taskId:{}", plcCmdInfo.getTaskId());
String path = PathUtil.createFileNameByRowColumn("jpg",cameraId,plcCmdInfo.getRow1(),plcCmdInfo.getColumn1());
//重庆亚士创能盘点时用同侧相机拍摄货物顶部(E1-TOP)
Integer leftRightTop = plcCmdInfo.getLeftRight1() == 1 ? 2 : 1;
Integer cameraIdTop = getCameraByPlcCmd(plcCmdInfo, leftRightTop);
String cameraCmdCode1 = cmdCode;
// if(plcCmdInfo.getSeparation1() == 1 && configProperties.getScanCodeMode().getTray() == 2){
// //内测
cameraCmdCode1 = cmdCode + "-" + "TOP";
// }
log.info("1 camera ptz:"+cameraCmdCode1);
Long delayTime =configProperties.getCameraConfig().getRotationPhotographyInterval();
gyrateCameraByCode(cameraIdTop, cameraCmdCode1);
cameraCapture(cameraIdTop,true,delayTime,path);
//重庆亚士创能盘点时用对侧球机拍侧面层数(E1-SIDE)
String cameraCmdCode2 = cmdCode + "-" + "SIDE";
gyrateCameraByCode(cameraId, cameraCmdCode2);
log.info("2 camera ptz:"+cameraCmdCode2);
cameraCapture(cameraId,true,delayTime,path+".jpg");
OrderInfo orderInfo = new OrderInfo(street,plcCmdInfo,1,cmdCode);
Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(orderInfo.getStreetId(),orderInfo.getLeftRight(),orderInfo.getSeparation(),orderInfo.getRow(),orderInfo.getColumn());
//核对异常
//默认未核对
Integer status = 0;
//托盘和货物都正确
if(trayCode.getTrayCheck()){
status = 2;
}
if(stock == null){
stock = new Stock(null,null,plcCmdInfo.getOrderNum(),plcCmdInfo.getLotnum(),"", null,null,wmsCode,null,null,wmsTrayCode,"",orderInfo.getStreetId(),orderInfo.getLeftRight(),orderInfo.getSeparation(),orderInfo.getRow(),orderInfo.getColumn(),0,null,null,path, LocalDateTime.now());
stockMapper.insert(stock);
stock = Stock.builder()
.checkNum(plcCmdInfo.getOrderNum())
.lotnum(plcCmdInfo.getLotnum())
.code("")
.wmsCode(wmsCode)
.wmsTrayCode(wmsTrayCode)
.trayCode("")
.streetId(orderInfo.getStreetId())
.direction(orderInfo.getLeftRight())
.side(orderInfo.getSeparation())
.row(orderInfo.getRow())
.column(orderInfo.getColumn())
.status(status)
.trayCode(trayCode.getTrayCode())
.checkPic(path)
.exportTime(LocalDateTime.now())
.build();stockMapper.insert(stock);
}else {
//stock.setStatus(status);
stock.setStatus(status);
stock.setLotnum(plcCmdInfo.getLotnum());
stock.setExportTime(LocalDateTime.now());
stock.setCheckPic(path);
stock.setCheckNum(plcCmdInfo.getOrderNum());
//stock.setTrayCode(trayCode);
stock.setTrayCode(trayCode.getTrayCode());
stock.setWmsTrayCode(wmsTrayCode);
//stock.setCode(scanCode);
stock.setWmsCode(wmsCode);
stockMapper.updateById(stock);
}
checkLog(stock);
// StockCheckRunnable stockCheckRunnable = new StockCheckRunnable(street,plcCmdInfo,cmdCode,stockMapper,path,checkLogMapper,configProperties.getScanCodeMode().getGoods(),wmsCode,wmsTrayCode,trayCode,trayCheck,configProperties,sensorGun);
// threadPoolExecutor.execute(stockCheckRunnable);
long end = System.currentTimeMillis();
long s = end - startTime;
log.info("time:{}millisecond",s);
if(street.getCamera2Id() != null){
gyrateCameraByCodeTimeLater(street.getCamera2Id(),"C5",delayTime+configProperties.getCameraConfig().getOriginInterval());
}
if(street.getCamera1Id() != null){
gyrateCameraByCodeTimeLater(street.getCamera1Id(),"C5",delayTime+configProperties.getCameraConfig().getOriginInterval());
}
return true;
}
public void checkLog(Stock stock){
CheckLog checkLog = new CheckLog();
checkLog.setCheckNum(stock.getCheckNum());
checkLog.setPic(stock.getCheckPic());
@ -635,36 +882,6 @@ public class PlcService {
stockMapper.truncate();
}
public void RFIDCheck(PlcCmdInfo plcCmdInfo){
Street street = streetService.getStreetByPlcId(plcCmdInfo.getPlcId());
if(street != null){
RFID rfid = rfidService.getRFIDByPlc(street.getId());
if(rfid != null){
RFIDStart(rfid.getIp(),rfid.getPort(),street.getId());
}
}
}
public void RFIDStart(String ip,Integer port,Integer streetId){
RFIDSocket rfidSocket = new RFIDSocket(ip,port);
rfidSocket.startCheck();
rfidSocket.readData();
RFIDMap.put(streetId,rfidSocket);
}
public Set<String> RFIDStop(PlcCmdInfo plcCmdInfo){
Street street = streetService.getStreetByPlcId(plcCmdInfo.getPlcId());
RFIDSocket rfidSocket = RFIDMap.get(street.getId());
Set<String> tags = null;
if(rfidSocket != null){
tags = rfidSocket.getTags();
log.info("tags:{}",tags);
rfidSocket.close();
RFIDMap.remove(street.getId());
}
return tags;
}
public ConfigProperties getConfigProperties(){
return configProperties;
}

@ -199,7 +199,7 @@ public class StockService {
Stock stock = new Stock();
stock.setColumn(j);
stock.setRow(i);
stock.setStatus(0);
stock.setStatus(-1);
//stock.setShelveId(shelveId);
readyList.add(stock);
}
@ -209,7 +209,7 @@ public class StockService {
}
//0 : 未盘点 1盘点异常 2盘点正确
//0 : 未盘点 1盘点异常 2盘点正确 3:未确认
//1>0>2 替换为
// 盘点异常 未盘点 盘点正确
// 1000 100 10
@ -219,8 +219,10 @@ public class StockService {
tabStatus.put(tab,stock.getStatus());
}else {
Integer status = tabStatus.get(tab);
if(stock.getStatus() == 1){
if(stock.getStatus() == 0){
//盘点异常为最高
tabStatus.put(tab,3);
}else if(stock.getStatus() == 1){
tabStatus.put(tab,1);
}else if(stock.getStatus() == 0 && status != 1) {
tabStatus.put(tab, 0);
@ -369,19 +371,30 @@ public class StockService {
private void checkLog(Stock stock){
CheckLog checkLog = new CheckLog();
checkLog.setRow(stock.getRow());
checkLog.setColumn(stock.getColumn());
checkLog.setCheckNum(stock.getCheckNum());
checkLog.setPic(stock.getCheckPic());
checkLog.setStreetId(stock.getStreetId());
checkLog.setDirection(stock.getDirection());
checkLog.setSide(stock.getSide());
checkLog.setStreetId(stock.getStreetId());
//checkLog.setShelveId(stock.getShelveId());
checkLog.setStatus(stock.getStatus());
checkLog.setCode(stock.getCode());
checkLog.setWmsCode(stock.getWmsCode());
checkLog.setStatus(stock.getStatus());
checkLog.setRow(stock.getRow());
checkLog.setColumn(stock.getColumn());
checkLog.setCreateTime(LocalDateTime.now());
checkLog.setTrayCode(stock.getTrayCode());
checkLog.setWmsTrayCode(stock.getWmsTrayCode());
checkLog.setLotnum(stock.getLotnum());
checkLog.setExportTime(stock.getExportTime());
checkLogMapper.insert(checkLog);
QueryWrapper<CheckLog> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("`direction`",stock.getDirection())
.eq("`street_id`",stock.getStreetId())
.eq("`lotnum`",stock.getLotnum())
.eq("`check_Num`",stock.getCheckNum())
.eq("`row`",stock.getRow())
.eq("`side`",stock.getSide())
.eq("`column`",stock.getColumn());
checkLogMapper.update(checkLog,queryWrapper);
}
/**
@ -406,6 +419,11 @@ public class StockService {
return stock;
}
public boolean clearStock() {
stockMapper.truncate();
return true;
}
// public void init(String shelveId, Integer row, Integer column){
// Map<String,Object> map = new HashMap<>();
// map.put("shelve_id",shelveId);

@ -1,6 +1,5 @@
package com.leaper.web.service.ksec;
import com.leaper.web.service.PlcService;
import com.leaper.web.service.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
@ -21,10 +20,13 @@ public class KescFilter extends ChannelInitializer<SocketChannel> {
private KsecInfo ksecInfo;
private PlcService plcService;
private KsecNettyClient nettyClient;
public KescFilter(KsecInfo ksecInfo, KsecNettyClient nettyClient){
public KescFilter(KsecInfo ksecInfo, PlcService plcService, KsecNettyClient nettyClient){
this.ksecInfo = ksecInfo;
this.plcService = plcService;
this.nettyClient = nettyClient;
}
@ -35,7 +37,7 @@ public class KescFilter extends ChannelInitializer<SocketChannel> {
//4秒发一次心跳
ph.addLast(new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS));
ByteBuf byteBuf = Unpooled.copiedBuffer(">".getBytes());
ph.addLast(new KsecDecoder(10000,byteBuf));
ph.addLast(new KsecDecoder(10000,byteBuf,plcService));
ph.addLast(new KescEncoder());
ph.addLast(new KescNettyHandler(ksecInfo,nettyClient));
}

@ -1,12 +1,12 @@
package com.leaper.web.service.ksec;
import com.alibaba.fastjson.JSONObject;
import com.leaper.web.pojo.Cmd;
import com.leaper.web.service.CommandHandler;
import com.leaper.web.service.PlcService;
import com.leaper.common.util.FileUtil;
import com.leaper.web.pojo.Cmd;
import com.leaper.web.pojo.TrayCode;
import com.leaper.web.service.GoodsActionTimes;
import com.leaper.web.service.PlcCmdInfo;
import com.leaper.web.service.PlcService;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
@ -26,8 +26,21 @@ import java.util.concurrent.TimeUnit;
@Slf4j
public class KsecDecoder extends DelimiterBasedFrameDecoder {
public KsecDecoder(int maxFrameLength, ByteBuf delimiter) {
private static final Logger tcpLogger = LoggerFactory.getLogger("tcp");
public static void setLastLotnum(String lotnum){
lastLotnum = lotnum;
}
private static String lastLotnum;
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(7,21,30, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(20000));
private PlcService plcService;
public KsecDecoder(int maxFrameLength, ByteBuf delimiter, PlcService plcService) {
super(maxFrameLength, delimiter);
this.plcService = plcService;
}
@Override
@ -37,7 +50,162 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder {
log.debug("no data");
return null;
}
CommandHandler.exec(ctx, in);
KescRunnable kescRunnable = new KescRunnable(in,ctx,plcService);
threadPoolExecutor.execute(kescRunnable);
return null;
}
public static class KescRunnable implements Runnable{
private ByteBuf in;
private ChannelHandlerContext ctx;
private PlcService plcService;
public KescRunnable(ByteBuf body,ChannelHandlerContext ctx,PlcService plcService){
this.in = body;
this.ctx = ctx;
this.plcService = plcService;
}
@Override
public void run() {
String body = in.toString(Charset.forName("UTF-8"));
if (body.startsWith("<")){
// 去掉首尾标识符
body = body.substring(1, body.length());
KsecInfo ksecInfo = JSONObject.parseObject(body, KsecInfo.class);
if (Cmd.A.name().equals(ksecInfo.getType())) {
in.release();
return ;
}
KsecDataInfo dataInfo = ksecInfo.getData();
String lotnum = dataInfo.getLotnum();
PlcCmdInfo plcCmdInfo = null;
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);
srmNumber = dataInfo.getSRMNumber();
cmdName = dataInfo.getCmdName();
}
if (Cmd.A.name().equals(ksecInfo.getType())) {
//心跳
log.debug("receieve heart ");
} else if (Cmd.B.name().equals(ksecInfo.getType())) {
tcpLogger.info(body);
//任务
if (Cmd.B1.name().equals(cmdName)) {
//昆船盘点模式下也会发B1 ,但是不会发送B2
//这里判断下,是否存在盘点批次号 若存在既是盘点的B1,无需处理若不存在lotnum则是随行的B1
if(StringUtils.isEmpty(dataInfo.getLotnum())){
//任务开始 旋转到原点位
plcService.gyrateCamera(plcCmdInfo,Cmd.C5.name());
plcService.orderStart(plcCmdInfo);
}else {
log.info("check move");
}
} else if (Cmd.B2.name().equals(cmdName)) {
//B2 C4 一起发的需要停止等B2
//这里判断是不是双伸
if(plcCmdInfo.getSeparation2() == 2){
//深测货架延迟
try {
Thread.sleep(plcService.getConfigProperties().getCameraConfig().getB2OutDelayTime());
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
//浅侧延迟
try {
Thread.sleep(plcService.getConfigProperties().getCameraConfig().getB2DelayTime());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(plcService.orderStop(plcCmdInfo)) {
plcService.gyrateCamera(plcCmdInfo, Cmd.C5.name());
}
}
} else if (Cmd.C.name().equals(ksecInfo.getType())) {
tcpLogger.info(body);
//动作
String code = dataInfo.getCmdName();
log.info("action code,{},orderInfo:{}", code, plcCmdInfo.toString());
if (Cmd.isBaseAction(code)) {
//执行动作,需要保存执行到第几步了
Integer times = GoodsActionTimes.put(plcCmdInfo.getOrderNum());
if(!code.endsWith(times.toString())){
in.release();
return;
}
plcCmdInfo.setTimes(times);
code = code + "-" + plcCmdInfo.getLeftRightStr(times) + plcCmdInfo.getInOutStr(times);
//执行动作
try {
plcService.action(plcCmdInfo, times, code);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
log.info("other C code :{}",code);
}
} else if (Cmd.D.name().equals(ksecInfo.getType())) {
String code = dataInfo.getCmdName();
if(code.equals(Cmd.D1.name())){
log.info("plcId:{},warn start",plcCmdInfo.getPlcId());
//根据告警code转动camera
String warnCode = dataInfo.getWarnCode();
if(!StringUtils.isEmpty(warnCode)){
String warnCode0 = Cmd.D1.name()+"-"+warnCode.split(",")[0];
plcService.warnAction(plcCmdInfo,warnCode0);
}
plcService.warnStart(plcCmdInfo.getPlcId(),dataInfo.getWarnCode());
}else if(code.equals(Cmd.D2.name())){
log.info("plcId:{},warn stop",plcCmdInfo.getPlcId());
plcService.warnStop(plcCmdInfo.getPlcId());
}else {
log.info("other D code :{}",code);
}
} else if (Cmd.E.name().equals(ksecInfo.getType())) {
//盘点
//转球机到盘点位 然后拍照
tcpLogger.info(body);
if(!StringUtils.isEmpty(lotnum) && !lotnum.equals(lastLotnum)){
//需要把stock表truncate
FileUtil.save(lotnum,"lastLotnum");
tcpLogger.info("truncate table ,last lotnum:{},new lotnum:{}",lastLotnum,lotnum);
plcService.truncateStock();
lastLotnum = lotnum;
}
log.info("orderInfo:{}", plcCmdInfo.toString());
plcCmdInfo.setTimes(1);
//Boolean ok = plcService.check(plcCmdInfo,ksecInfo.getData().getCmdName(), dataInfo.getCode(), dataInfo.getTrayCode());
//扫码
TrayCode trayCode = plcService.checkScanCode(plcCmdInfo,ksecInfo.getData().getCmdName(), dataInfo.getCode(), dataInfo.getTrayCode());
//返回值
ctx.channel().writeAndFlush(ksecInfo);
//拍照
Boolean ok = plcService.checkPhotography(plcCmdInfo,ksecInfo.getData().getCmdName(), dataInfo.getCode(), dataInfo.getTrayCode(),trayCode);
if(ok){
ksecInfo.getData().setAckStatus(1);
}else {
ksecInfo.getData().setAckStatus(0);
}
}
//找到该货位的最后一张照片与现在的照片比照
//plcService.recordStock(plcCmdInfo, dataInfo.getCode(), 0, 0);
}
in.release();
}
}
}

@ -41,13 +41,15 @@ public class KsecNettyClient {
client.group(group);
client.channel(NioSocketChannel.class);
KsecInfo heart = KsecInfo.heart();
client.handler(new KescFilter(heart,this));
client.handler(new KescFilter(heart,plcService,this));
// 连接服务端
channel = client.connect(ksec.getIp(), ksec.getPort()).sync().channel();
}
/**
* 线 RECONNECT_NUM
* 线
*
* @param upId
*/
@ -64,13 +66,21 @@ 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) {
}
//没连上 继续
catch (Exception e) {
//关闭当前链接
channel.close();
log.error("reconnect error num:{}", num);
num++;
try{
Thread.sleep(ksec.getReconnectInterval());
}catch (Exception ex){
throw new RuntimeException(ex);
}
continue;
}
isConnected = true;

@ -8,6 +8,7 @@ import java.io.*;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.*;
/**
* sick
@ -16,8 +17,9 @@ import java.nio.charset.StandardCharsets;
public class SickSocket {
private static final Logger tcpLogger = LoggerFactory.getLogger("sick");
public static void main(String[] args) {
String code = readOCR("192.168.8.236", 2002);
String code = readOCR("127.0.0.1", 2003);
System.out.println(code);
}
@ -28,12 +30,16 @@ public class SickSocket {
InputStream is = null;
try {
socket.connect(new InetSocketAddress(ip, port), 3000);
System.out.println("start connect");
os = socket.getOutputStream();
is = socket.getInputStream();
int i = 0;
while ("NoRead".equals(code) && i <= 4) {
System.out.println("intend connect sand start");
writeCmd(os);
code = read(is);
System.out.println("sand start");
code = read(is, ip);
System.out.println(code);
tcpLogger.info("count:{},ip:{},code:{}", i, ip, code);
if (code != null) {
code = code.replace("\\n", "");
@ -76,9 +82,31 @@ public class SickSocket {
os.write(bytes);
}
private static String read(InputStream inStream) throws IOException {
private static String read(InputStream inStream,String ip) throws IOException {
BufferedReader bd = new BufferedReader(new InputStreamReader(inStream));
return bd.readLine();
StringBuilder stringBuilder = new StringBuilder();
FutureTask<StringBuilder> future = new FutureTask <>(()->{
StringBuilder bdString = new StringBuilder();
while (true) {
try {
bdString.append((char) bd.read());
} catch (IOException exc) {
throw new RuntimeException(exc);
}
if (bdString.toString().contains("\\n") || bdString.toString().contains("\n")) {
break;
}
}
return bdString;
});
try {
new Thread(future).start();
stringBuilder = future.get(1000,TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
tcpLogger.error("sick 可以连接但发送返回存在问题,ip:{},info:{}", ip, e);
log.error("sick 可以连接但发送返回存在问题,ip:{},info:{}", ip, e);
throw new RuntimeException(e);
}
return stringBuilder.toString();
}
}

@ -58,6 +58,12 @@ serverMode: 1
ksec:
ip: 192.168.168.11
port: 8001
#断点重连的次数:-1->不断重连
reconnectNum: -1
#断点重连的时间间隔(单位ms)
reconnectInterval: 10000
# ------------ 实时视频流 全部页面的格式 行列数量
videoStyleConfig:
videoStyleRow: 4

@ -7,7 +7,7 @@ spring:
maxWait: 60000
minEvictableIdleTimeMillis: 300000
minIdle: 15
password: Leaper@123
password: root
poolPreparedStatements: true
testOnBorrow: true
testOnReturn: false
@ -22,17 +22,35 @@ spring:
# ----默认摄像头的连接信息
cameraConfig:
# ------------球機選擇--- 0:利珀 1海康
cameraType: 0
cameraType: 1
cameraPassword: a1234567
cameraUser: admin
cameraPort: 8000
videoServer: 127.0.0.1:8083
#相机抓图延迟 毫秒,这个延迟是等待球机球机转动到位,然后拍照的
delayCaptureTime: 3500
#随行模式下的相机抓图延迟 毫秒,这个延迟是等待球机球机转动到位,然后拍照的
# 发了C1之后多久拍照
C1DelayCaptureTime: 1500
# 内侧货架 发了C2 之后多久拍照
C2DelayCaptureTime: 1500
# 外侧货架 发了C2 之后多久拍照
C2OutDelayCaptureTime: 2500
# 发了C3之后多久拍照
C3DelayCaptureTime: 1500
C4DelayCaptureTime: 1500
C4OutDelayCaptureTime: 1500
# 发了B2之后多久转原点位
B2DelayTime: 2000
# 外侧货架发了B2多久转原点位
B2OutDelayTime: 2000
# 下载mp4延迟 海康的下载mp4需要2分钟
# 利珀延迟10s就可
# 单位毫秒
delayDownloadMp4: 120000
delayDownloadMp4: 10000
rotationPhotographyInterval: 1500
#拍照返回原点间隔/ms
originInterval: 1500
# ------------
# -----图片 mp4下载地址
savePath:
@ -43,6 +61,14 @@ serverMode: 1
ksec:
ip: 127.0.0.1
port: 3000
#断点重连的次数:-1->不断重连
reconnectNum: -1
#断点重连的时间间隔(单位ms)
reconnectInterval: 10000
#视频下载开始时间后延秒数,可以负数
downloadStartMp4: 10
#视频下载结束时间后延秒数,可以负数
downloadEndMp4: 20
# ------------ 实时视频流 全部页面的格式 行列数量
videoStyleConfig:
videoStyleRow: 2
@ -65,5 +91,9 @@ scanCodeMode:
- 14
trayCodeTypes:
- 14
#盘点指令后多少毫秒扫码
checkScanCodeInterval: 1000
#盘点指令并扫码后多少毫秒拍照
checkPhotographyScanCodeInterval: 1000
# 照片 視頻保存多久
deleteFileDays: 365
Loading…
Cancel
Save