增加http协议到master

master
yiming 3 years ago
parent d518e5fbcc
commit 5867b06535

@ -8,6 +8,10 @@
***
* 罗伯泰克协议编解码在com.leaper.web.service.robotic下面
* 罗伯泰克协议见doc文件夹下两张图片罗伯泰克plc通讯协议1——2.jpg
***
* HTTP通讯协议在com.leaper.web.controller.MonitorController类
* 目前是宁福多氟多项目上使用不推荐使用http因为http协议的时延比tcp要高
* 文档见doc文件夹下 宁福迦南HTTP通信协议文档12.2.doc
***
## SDK:
### 1.调用sdk的代码在 com.leaper.web.lib下面

@ -0,0 +1,25 @@
package com.leaper.web.controller;
import com.leaper.web.service.CommandHandler;
import com.leaper.web.service.ksec.KsecInfo;
import com.zhehekeji.core.pojo.Result;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(value = "monitor",tags = "监控接口 HTTP协议")
@RestController
@RequestMapping("/monitor")
@Slf4j
public class MonitorController {
@PostMapping("/task")
public Result monitorTask(@RequestBody KsecInfo ksecInfo){
CommandHandler.exec(ksecInfo);
return Result.success();
}
}

@ -0,0 +1,36 @@
package com.leaper.web.service;
import com.leaper.common.util.FileUtil;
import com.leaper.web.service.ksec.KsecDecoder;
import com.leaper.web.service.ksec.KsecInfo;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
public class CommandHandler {
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(7,21,30, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<>(20000));
static {
String lotnum = FileUtil.getText("lastLotnum");
if(lotnum != null){
CommandRunnable.setLastLotnum(lotnum);
}
log.info("read lastLotnum:{}",lotnum);
}
public static void exec(ChannelHandlerContext ctx, ByteBuf in){
CommandRunnable commandRunnable = new CommandRunnable(in,ctx);
threadPoolExecutor.execute(commandRunnable);
}
public static void exec(KsecInfo ksecInfo){
CommandRunnable commandRunnable = new CommandRunnable(ksecInfo);
threadPoolExecutor.execute(commandRunnable);
}
}

@ -0,0 +1,190 @@
package com.leaper.web.service;
import com.alibaba.fastjson.JSONObject;
import com.leaper.common.util.FileUtil;
import com.leaper.common.util.SpringContextUtil;
import com.leaper.web.pojo.Cmd;
import com.leaper.web.service.ksec.KsecDataInfo;
import com.leaper.web.service.ksec.KsecInfo;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.nio.charset.Charset;
@Slf4j
public class CommandRunnable implements Runnable{
private static final Logger tcpLogger = LoggerFactory.getLogger("tcp");
public static void setLastLotnum(String lotnum){
lastLotnum = lotnum;
}
private static String lastLotnum;
private PlcService plcService;
private ByteBuf in;
private ChannelHandlerContext ctx;
private KsecInfo ksecInfo;
private String content;
/**
* TCP
* @param body
* @param ctx
*/
public CommandRunnable(ByteBuf body, ChannelHandlerContext ctx){
this.in = body;
this.ctx = ctx;
this.plcService = SpringContextUtil.getBean(PlcService.class);
content = body.toString(Charset.forName("UTF-8"));
if(content.startsWith("<")){
content = content.substring(1, content.length());
ksecInfo = JSONObject.parseObject(content, KsecInfo.class);
}
tcpLogger.info("{}",content);
}
/**
* HTTP
* @param ksecInfo
*/
public CommandRunnable(KsecInfo ksecInfo){
this.ksecInfo = ksecInfo;
this.plcService = SpringContextUtil.getBean(PlcService.class);
tcpLogger.info("{}",JSONObject.toJSONString(ksecInfo));
}
@Override
public void run() {
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())) {
//任务
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();
}
}
plcService.gyrateCamera(plcCmdInfo,Cmd.C5.name());
plcService.orderStop(plcCmdInfo);
}
} else if (Cmd.C.name().equals(ksecInfo.getType())) {
//动作
String code = dataInfo.getCmdName();
log.info("action code,{},orderInfo:{}", code, plcCmdInfo.toString());
if (Cmd.isBaseAction(code)) {
//执行动作,需要保存执行到第几步了
Integer times = GoodsActionTimes.put(plcCmdInfo.getOrderNum());
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())) {
//盘点
//转球机到盘点位 然后拍照
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;
}
plcCmdInfo.setTimes(1);
Boolean ok = plcService.check(plcCmdInfo,ksecInfo.getData().getCmdName(), dataInfo.getCode(), dataInfo.getTrayCode());
if(ok){
ksecInfo.getData().setAckStatus(1);
}else {
ksecInfo.getData().setAckStatus(0);
}
if(ctx != null){
ctx.channel().writeAndFlush(ksecInfo);
}
}
if(in != null){
in.release();
}
}
}

@ -21,13 +21,10 @@ public class KescFilter extends ChannelInitializer<SocketChannel> {
private KsecInfo ksecInfo;
private PlcService plcService;
private KsecNettyClient nettyClient;
public KescFilter(KsecInfo ksecInfo, PlcService plcService, KsecNettyClient nettyClient){
public KescFilter(KsecInfo ksecInfo, KsecNettyClient nettyClient){
this.ksecInfo = ksecInfo;
this.plcService = plcService;
this.nettyClient = nettyClient;
}
@ -38,7 +35,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,plcService));
ph.addLast(new KsecDecoder(10000,byteBuf));
ph.addLast(new KescEncoder());
ph.addLast(new KescNettyHandler(ksecInfo,nettyClient));
}

@ -2,6 +2,7 @@ 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.service.GoodsActionTimes;
@ -25,21 +26,8 @@ import java.util.concurrent.TimeUnit;
@Slf4j
public class KsecDecoder extends DelimiterBasedFrameDecoder {
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) {
public KsecDecoder(int maxFrameLength, ByteBuf delimiter) {
super(maxFrameLength, delimiter);
this.plcService = plcService;
}
@Override
@ -49,153 +37,7 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder {
log.debug("no data");
return null;
}
KescRunnable kescRunnable = new KescRunnable(in,ctx,plcService);
threadPoolExecutor.execute(kescRunnable);
CommandHandler.exec(ctx, in);
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"));
tcpLogger.info(body);
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())) {
//任务
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();
}
}
plcService.gyrateCamera(plcCmdInfo,Cmd.C5.name());
plcService.orderStop(plcCmdInfo);
}
} else if (Cmd.C.name().equals(ksecInfo.getType())) {
//动作
String code = dataInfo.getCmdName();
log.info("action code,{},orderInfo:{}", code, plcCmdInfo.toString());
if (Cmd.isBaseAction(code)) {
//执行动作,需要保存执行到第几步了
Integer times = GoodsActionTimes.put(plcCmdInfo.getOrderNum());
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())) {
//盘点
//转球机到盘点位 然后拍照
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;
}
plcCmdInfo.setTimes(1);
Boolean ok = plcService.check(plcCmdInfo,ksecInfo.getData().getCmdName(), dataInfo.getCode(), dataInfo.getTrayCode());
if(ok){
ksecInfo.getData().setAckStatus(1);
}else {
ksecInfo.getData().setAckStatus(0);
}
ctx.channel().writeAndFlush(ksecInfo);
}
//找到该货位的最后一张照片与现在的照片比照
//plcService.recordStock(plcCmdInfo, dataInfo.getCode(), 0, 0);
}
in.release();
}
}
}

@ -33,10 +33,7 @@ public class KsecNettyClient {
private static Channel channel;
public void createClient(ConfigProperties.KSEC ksec) throws InterruptedException {
String lotnum = FileUtil.getText("lastLotnum");
if(lotnum != null){
KsecDecoder.setLastLotnum(lotnum);
}
if (StringUtils.isEmpty(ksec.getIp()) || ksec.getPort() == null) {
return;
}
@ -44,7 +41,7 @@ public class KsecNettyClient {
client.group(group);
client.channel(NioSocketChannel.class);
KsecInfo heart = KsecInfo.heart();
client.handler(new KescFilter(heart, plcService,this));
client.handler(new KescFilter(heart,this));
// 连接服务端
channel = client.connect(ksec.getIp(), ksec.getPort()).sync().channel();
}

@ -17,18 +17,16 @@ spring:
url: jdbc:mysql://115.236.65.98:12004/lia_duoji_test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
validationQuery: SELECT 1 FROM DUAL
# --------本服务端口号
server:
port: 8099
#--------------
# -----------
# ----默认摄像头的连接信息
cameraConfig:
# ------------球機選擇--- 0:利珀 1海康
cameraType: 0
cameraType: 1
cameraPassword: a1234567
cameraUser: admin
cameraPort: 37777
cameraPort: 8000
videoServer: 127.0.0.1:8083
#相机抓图延迟 毫秒,这个延迟是等待球机球机转动到位,然后拍照的
delayCaptureTime: 3500

@ -17,9 +17,6 @@ spring:
url: jdbc:mysql://127.0.0.1:3306/lia_duoji?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
validationQuery: SELECT 1 FROM DUAL
# --------本服务端口号
server:
port: 8099
#--------------
# -----------
# ----默认摄像头的连接信息

@ -17,9 +17,6 @@ spring:
url: jdbc:mysql://127.0.0.1:3306/lia_duoji?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
username: root
validationQuery: SELECT 1 FROM DUAL
# --------本服务端口号
server:
port: 8099
#--------------
# -----------
# ----默认摄像头的连接信息

@ -1,3 +1,6 @@
server:
# --------本服务端口号
port: 8099
spring:
profiles:
active: @profileActive@

Loading…
Cancel
Save