rev:ndc netty

This commit is contained in:
2024-03-19 15:45:14 +08:00
parent 1bfc70d6c7
commit d7917a9d38
7 changed files with 1235 additions and 19 deletions

View File

@@ -55,25 +55,30 @@ public enum StatusEnum {
QXXL_FULL_REQ("9", "取满框请求(清洗下料)", ""),
QXXL_EMPTY_REQ("10", "叫空框请求(清洗下料)", ""),
QXXL_COMPEL_REQ("11", "强制搬出请求(清洗下料)", ""),
KZSL_EMPTY_REQ("12","取空框请求(刻字上料)",""),
KZSL_EMPTY_REQ("12", "取空框请求(刻字上料)", ""),
EMPTY_REQ("22", "补空框请求(三工位)", ""),
HAIROU_IN_REQ("13","半成品入库(海柔)",""),
HAIROU_OUT_REQ("14","半成品出库(海柔)",""),
HAIROU_INVENTORY_REQ("15","盘点(海柔)",""),
HAIROU_EMPTY_OUT_REQ("16","空载具出库(海柔)",""),
HAIROU_EMPTY_IN_REQ("17","空载具入库(海柔)",""),
HAIROU_IN_REQ("13", "半成品入库(海柔)", ""),
HAIROU_OUT_REQ("14", "半成品出库(海柔)", ""),
HAIROU_INVENTORY_REQ("15", "盘点(海柔)", ""),
HAIROU_EMPTY_OUT_REQ("16", "空载具出库(海柔)", ""),
HAIROU_EMPTY_IN_REQ("17", "空载具入库(海柔)", ""),
HAIROU_LIKU_REQ("18","半成品库任务(海柔)",""),
TWO_TASK_1("10", "双点位任务", "取放/取取放放"),
TWO_TASK_2("12", "双点位任务", "取放取放"),
THREE_TASK("11", "三点位任务", "取倒放"),
HAIROU_RELOCATION("19","移库(海柔)",""),
HAIROU_CARRY("20","搬运(海柔)",""),
HAIROU_CHECK("21","盘库(海柔)",""),
HAIROU_LIKU_REQ("18", "半成品库任务(海柔)", ""),
TOTE_INBOUND("1","容器入库","tote_inbound"),
TOTE_OUTBOUND("2","容器出库","tote_outbound"),
TOTE_RELOCATION("3","容器移库","tote_relocation"),
TOTE_CARRY("4","容器搬运","tote_carry"),
TOTE_CHECK("5","容器","tote_check"),
HAIROU_RELOCATION("19", "移库(海柔)", ""),
HAIROU_CARRY("20", "搬运(海柔)", ""),
HAIROU_CHECK("21", "盘库(海柔)", ""),
TOTE_INBOUND("1", "容器", "tote_inbound"),
TOTE_OUTBOUND("2", "容器出库", "tote_outbound"),
TOTE_RELOCATION("3", "容器移库", "tote_relocation"),
TOTE_CARRY("4", "容器搬运", "tote_carry"),
TOTE_CHECK("5", "容器盘库", "tote_check"),
//指令状态
INST_READY("0", "就绪", ""),
@@ -86,9 +91,9 @@ public enum StatusEnum {
TASK_RUNNING("1", "执行中", "6"),
TASK_FINISH("2", "完成", "7"),
TASK_CANCEL("3", "取消", "8"),
TASK_FULL_IN("4","满入",""),
TASK_EMPTY_OUT("5","空出",""),
TASK_CHECK_ANOMALY("6","盘点异常","");
TASK_FULL_IN("4", "满入", ""),
TASK_EMPTY_OUT("5", "空出", ""),
TASK_CHECK_ANOMALY("6", "盘点异常", "");
private String code;
private String desc;

View File

@@ -73,4 +73,22 @@ public interface NDCAgvService {
* @throws Exception
*/
public void sendAgvTwoInstToNDC(Instruction inst, Instruction inst2) throws Exception;
/**
* 智能三线反馈诺宝AGV
*
* @param phase
* @param index
* @param result
* @return
*/
byte[] sendInstToNuoBaoNdc(int phase, int index, int result);
/**
* 智能三线下发诺宝AGV指令
*
* @param inst
* @param inst2
*/
void sendNuoBaoAgvInst(Instruction inst, Instruction inst2);
}

View File

@@ -1,12 +1,15 @@
package org.nl.acs.agv.server.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@AllArgsConstructor
public class AgvDto implements Serializable {
/**

View File

@@ -5,9 +5,11 @@ import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.AcsConfig;
import org.nl.acs.acsEnum.StatusEnum;
import org.nl.acs.agv.server.NDCAgvService;
import org.nl.acs.agv.server.dto.AgvDto;
import org.nl.acs.auto.run.NDCSocketConnectionAutoRun;
import org.nl.acs.auto.run.NdcNettyConnectionAutoRun;
import org.nl.acs.auto.run.OneNDCSocketConnectionAutoRun;
import org.nl.acs.device.service.DeviceService;
import org.nl.acs.device.service.impl.DeviceServiceImpl;
@@ -493,7 +495,7 @@ public class NDCAgvServiceImpl implements NDCAgvService {
(byte) 0X00, (byte) 0X01,
(byte) 0X00, (byte) 0X71,
(byte) 0X00, (byte) 0X16,
(byte) 0X01, (byte) 0X80,
(byte) 0X01, (byte) prioritylow,
(byte) 0X00, (byte) 0X01,
(byte) ikeyhigh, (byte) ikeylow,
(byte) ikeyhigh, (byte) ikeylow,
@@ -512,4 +514,131 @@ public class NDCAgvServiceImpl implements NDCAgvService {
System.out.println("下发agv指令数据:" + Bytes2HexString(b));
}
@Override
public byte[] sendInstToNuoBaoNdc(int phase, int index, int result) {
log.info("反馈agv动作数据--index:" + hexToString((byte) IntToHexHigh(index) & 0xFF) + hexToString((byte) IntToHexLow(index) & 0xFF) + ",phase:" + hexToString((byte) IntToHexHigh(phase) & 0xFF) + hexToString((byte) IntToHexLow(phase) & 0xFF));
return (phase < 0 || index < 0) ? null : new byte[]{
(byte) 0X87, (byte) 0XCD,
(byte) 0X00, (byte) 0X08,
(byte) 0X00, (byte) 0X0A,
(byte) 0X00, (byte) 0X01,
(byte) 0X00, (byte) 0X6D,
(byte) 0X00, (byte) 0X06,
(byte) IntToHexHigh(index), (byte) IntToHexLow(index),
(byte) 0X01, (byte) 0X17,
(byte) IntToHexHigh(phase), (byte) IntToHexLow(phase)
};
}
@Override
public void sendNuoBaoAgvInst(Instruction inst, Instruction inst2) {
int type = 1;
if (inst2 != null && StatusEnum.TWO_TASK_1.getCode().equals(inst.getInstruction_type())) {
type = 4;
} else if (inst2 != null && StatusEnum.TWO_TASK_2.getCode().equals(inst.getInstruction_type())) {
type = 3;
} else if (inst2 != null && StatusEnum.THREE_TASK.getCode().equals(inst.getInstruction_type())) {
type = 5;
} else if (inst2 == null && StatusEnum.THREE_TASK.getCode().equals(inst.getInstruction_type())) {
type = 2;
}
String instcode = inst.getLink_num();
int priority = Integer.parseInt(inst.getPriority()) + 128;
DeviceService deviceService = SpringContextHolder.getBean(DeviceServiceImpl.class);
int startAddress1 = deviceService.queryAddressBydeviceCode(inst.getStart_point_code());
int putAddress1 = deviceService.queryAddressBydeviceCode(inst.getPut_point_code());
int nextAddress1 = deviceService.queryAddressBydeviceCode(inst.getNext_point_code());
int startAddress2 = 0;
int putAddress2 = 0;
int nextAddress2 = 0;
if (ObjectUtil.isNotEmpty(inst2)) {
startAddress2 = deviceService.queryAddressBydeviceCode(inst2.getStart_point_code());
putAddress2 = deviceService.queryAddressBydeviceCode(inst2.getPut_point_code());
nextAddress2 = deviceService.queryAddressBydeviceCode(inst2.getNext_point_code());
}
byte ikeyhigh = (byte) IntToHexHigh(Integer.parseInt(instcode));
byte ikeylow = (byte) IntToHexLow(Integer.parseInt(instcode));
byte typehigh = (byte) IntToHexHigh(type);
byte typelow = (byte) IntToHexLow(type);
byte qhd1high = (byte) IntToHexHigh(startAddress1);
byte qhd1low = (byte) IntToHexLow(startAddress1);
byte qhd2high = (type == 4 || type == 5) ? (byte) IntToHexHigh(startAddress2) : 0;
byte qhd2low = (type == 4 || type == 5) ? (byte) IntToHexLow(startAddress2) : 0;
byte dld1high = (byte) IntToHexHigh(putAddress1);
byte dld1low = (byte) IntToHexLow(putAddress1);
byte dld2high = (byte) IntToHexHigh(putAddress2);
byte dld2low = (byte) IntToHexLow(putAddress2);
byte fhd1high = (byte) IntToHexHigh(nextAddress1);
byte fhd1low = (byte) IntToHexLow(nextAddress1);
byte fhd2high = (byte) IntToHexHigh(nextAddress2);
byte fhd2low = (byte) IntToHexLow(nextAddress2);
byte qhd3high = (type == 3 || type == 6) ? (byte) IntToHexHigh(startAddress1) : 0;
byte qhd3low = (type == 3 || type == 6) ? (byte) IntToHexLow(startAddress1) : 0;
byte qhd4high = type == 6 ? (byte) IntToHexHigh(startAddress2) : 0;
byte qhd4low = type == 6 ? (byte) IntToHexLow(startAddress2) : 0;
byte fhd3high = (type == 3 || type == 6) ? (byte) IntToHexHigh(nextAddress1) : 0;
byte fhd3low = (type == 3 || type == 6) ? (byte) IntToHexLow(nextAddress1) : 0;
byte fhd4high = type == 6 ? (byte) IntToHexHigh(nextAddress2) : 0;
byte fhd4low = type == 6 ? (byte) IntToHexLow(nextAddress2) : 0;
byte prioritylow = (byte) IntToHexLow(priority);
String str = "十进制下发:";
String str1 = "十六进制下发:";
str1 += "ikey:" + hexToString(ikeyhigh & 0xFF) + hexToString(ikeylow & 0xFF);
str += "/type:" + (type);
str1 += "/type:" + hexToString(typehigh & 0xFF) + hexToString(typelow & 0xFF);
str1 += "/qhd1:" + hexToString(qhd1high & 0xFF) + hexToString(qhd1low & 0xFF);
str1 += "/qhd2:" + hexToString(qhd2high & 0xFF) + hexToString(qhd2low & 0xFF);
str1 += "/dld1:" + hexToString(dld1high & 0xFF) + hexToString(dld1low & 0xFF);
str1 += "/dld2:" + hexToString(dld2high & 0xFF) + hexToString(dld2low & 0xFF);
str1 += "/fhd1:" + hexToString(fhd1high & 0xFF) + hexToString(fhd1low & 0xFF);
str1 += "/fhd2:" + hexToString(fhd2high & 0xFF) + hexToString(fhd2low & 0xFF);
System.out.println(str);
System.out.println(str1);
byte[] b = new byte[]{(byte) 0X87, (byte) 0XCD,
(byte) 0X00, (byte) 0X08,
(byte) 0X00, (byte) 0X22,
(byte) 0X00, (byte) 0X01,
(byte) 0X00, (byte) 0X71,
(byte) 0X00, (byte) 0X1E,
(byte) 0X01, (byte) prioritylow,
(byte) 0X00, (byte) 0X01,
ikeyhigh, ikeylow,
ikeyhigh, ikeylow,
typehigh, typelow,
qhd1high, qhd1low,
qhd2high, qhd2low,
dld1high, dld1low,
dld2high, dld2low,
fhd1high, fhd1low,
fhd2high, fhd2low,
qhd3high, qhd3low,
qhd4high, qhd4low,
fhd3high, fhd3low,
fhd4high, fhd4low,
};
log.info("下发AGV作业指令--{}", str1);
NdcNettyConnectionAutoRun.write(b);
System.out.println("下发agv指令数据:" + Bytes2HexString(b));
}
}

View File

@@ -0,0 +1,143 @@
package org.nl.acs.auto.run;
import com.alibaba.fastjson.JSON;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.AcsConfig;
import org.nl.acs.device_driver.basedriver.agv.nuoBaoNdc.NuoBaoNdcDeviceDriver;
import org.nl.acs.opc.Device;
import org.nl.acs.opc.DeviceAppService;
import org.nl.config.ProtocolCodec;
import org.nl.modules.common.exception.BadRequestException;
import org.nl.modules.system.service.ParamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import static org.nl.acs.agv.server.impl.NDCAgvServiceImpl.Bytes2HexString;
/**
* @author onepiece
*/
@Slf4j
@Component
public class NdcNettyConnectionAutoRun extends AbstractAutoRunnable {
@Autowired
private ParamService paramService;
@Autowired
private DeviceAppService deviceAppService;
private static final int[] PHASES_CAR_ID = {0x67, 0x70, 0x71, 0x72, 0x73, 0x74};
private final Bootstrap bootstrap = new Bootstrap();
private static final EventLoopGroup group = new NioEventLoopGroup();
private static Channel channel;
@Override
public String getCode() {
return NdcNettyConnectionAutoRun.class.getSimpleName();
}
@Override
public String getName() {
return "智能三线诺宝NDC连接";
}
@Override
public void autoRun() {
String ip = paramService.findByCode(AcsConfig.ONEAGVURL).getValue();
int port = Integer.parseInt(paramService.findByCode(AcsConfig.ONEAGVPORT).getValue());
try {
Bootstrap bootstrap = createBootstrap();
ChannelFuture boot = bootstrap.connect(ip, port).sync();
channel = boot.channel();
channel.closeFuture().sync();
} catch (Exception e) {
log.error("agv连接出现异常: {}", JSON.toJSONString(e));
if (channel != null) {
channel.flush();
channel.close();
}
} finally {
group.shutdownGracefully();
}
}
private Bootstrap createBootstrap() {
return bootstrap.group(group)
.option(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.TCP_NODELAY, true)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new MsgHandler());
}
});
}
@Override
public void stop() {
if (channel != null) {
channel.flush();
channel.close();
}
group.shutdownGracefully();
}
public static void write(byte[] b) {
try {
log.info("下发agv数据:" + Bytes2HexString(b));
channel.writeAndFlush(Unpooled.copiedBuffer(b));
} catch (Exception e) {
try {
log.info("再次下发agv数据:" + Bytes2HexString(b));
channel.writeAndFlush(Unpooled.copiedBuffer(b));
} catch (Exception e1) {
throw new BadRequestException(e1.getMessage());
}
}
}
class MsgHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
@SneakyThrows
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
if (msg.isReadable()) {
byte[] bytes = ProtocolCodec.readBody(msg);
if (bytes.length > 0) {
//执行阶段
Integer phase = (Byte.toUnsignedInt(bytes[16]) << 8) + Byte.toUnsignedInt(bytes[17]);
//agv任务号
Integer index = (Byte.toUnsignedInt(bytes[12]) << 8) + Byte.toUnsignedInt(bytes[13]);
//任务号
Integer ikey = (Byte.toUnsignedInt(bytes[26]) << 8) + Byte.toUnsignedInt(bytes[27]);
//站点号
Integer param = (Byte.toUnsignedInt(bytes[18]) << 8) + Byte.toUnsignedInt(bytes[19]);
//车号
byte carId = bytes[20];
Device device = null;
//Phase值为这些站点号param代表小车号否则carId代表小车号
if (Arrays.stream(PHASES_CAR_ID).anyMatch(v -> v == phase)) {
device = deviceAppService.findDeviceByCode(Integer.toString(param));
} else {
device = deviceAppService.findDeviceByCode(Integer.toString(carId));
}
if (device != null && device.getDeviceDriver() instanceof NuoBaoNdcDeviceDriver) {
NuoBaoNdcDeviceDriver deviceDriver = (NuoBaoNdcDeviceDriver) device.getDeviceDriver();
deviceDriver.processSocket(bytes, phase, index, ikey, Byte.toUnsignedInt(carId), param);
}
}
}
}
}
}

View File

@@ -0,0 +1,49 @@
package org.nl.acs.device_driver.basedriver.agv.nuoBaoNdc;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.DeviceDriverDefination;
import org.nl.acs.opc.Device;
import org.nl.acs.opc.DeviceType;
import org.springframework.stereotype.Service;
import java.util.LinkedList;
import java.util.List;
/**
* 智能三线诺宝AGV
*/
@Service
public class NuoBaoNdcDefination implements DeviceDriverDefination {
@Override
public String getDriverCode() {
return "nuo_bao_ndc";
}
@Override
public String getDriverName() {
return "智能三线诺宝AGV";
}
@Override
public String getDriverDescription() {
return "智能三线诺宝AGV";
}
@Override
public DeviceDriver getDriverInstance(Device device) {
return (new NuoBaoNdcDeviceDriver()).setDevice(device).setDriverDefination(this);
}
@Override
public Class<? extends DeviceDriver> getDeviceDriverType() {
return NuoBaoNdcDeviceDriver.class;
}
@Override
public List<DeviceType> getFitDeviceTypes() {
List<DeviceType> types = new LinkedList();
types.add(DeviceType.agv);
return types;
}
}

View File

@@ -0,0 +1,869 @@
package org.nl.acs.device_driver.basedriver.agv.nuoBaoNdc;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.acsEnum.StatusEnum;
import org.nl.acs.agv.server.NDCAgvService;
import org.nl.acs.agv.server.dto.AgvDto;
import org.nl.acs.agv.server.impl.NDCAgvServiceImpl;
import org.nl.acs.auto.run.NdcNettyConnectionAutoRun;
import org.nl.acs.device.service.DeviceService;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.basedriver.hailiang_one.hailiang_cleaning_put_line.HailiangCleaningPutLineDeviceDriver;
import org.nl.acs.device_driver.basedriver.hailiang_one.hailiang_engraving_cache.HailiangEngravingCacheDeviceDriver;
import org.nl.acs.device_driver.basedriver.hailiang_one.hailiang_engraving_in.HailiangEngravingInDeviceDriver;
import org.nl.acs.device_driver.basedriver.hailiang_one.hailiang_engraving_machine.HailiangEngravingMachineDeviceDriver;
import org.nl.acs.device_driver.basedriver.hailiang_one.hailiang_packer_station.HailiangPackerStationDeviceDriver;
import org.nl.acs.device_driver.basedriver.standard_ordinary_site.StandardOrdinarySiteDeviceDriver;
import org.nl.acs.device_driver.basedriver.standard_storage.StandardStorageDeviceDriver;
import org.nl.acs.device_driver.driver.AbstractDeviceDriver;
import org.nl.acs.instruction.service.InstructionService;
import org.nl.acs.instruction.service.dto.Instruction;
import org.nl.acs.instruction.service.impl.InstructionServiceImpl;
import org.nl.acs.opc.Device;
import org.nl.acs.opc.DeviceAppService;
import org.nl.acs.task.service.TaskService;
import org.nl.acs.task.service.dto.TaskDto;
import org.nl.acs.task.service.impl.TaskServiceImpl;
import org.nl.modules.wql.util.SpringContextHolder;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* 智能三线诺宝AGV
*
* @author onepiece
*/
@Slf4j
@Data
@RequiredArgsConstructor
public class NuoBaoNdcDeviceDriver extends AbstractDeviceDriver implements DeviceDriver {
private final InstructionService instructionService = SpringContextHolder.getBean(InstructionServiceImpl.class);
private final NDCAgvService ndcAgvService = SpringContextHolder.getBean(NDCAgvServiceImpl.class);
private final DeviceAppService deviceAppService = SpringContextHolder.getBean(DeviceAppService.class);
private final DeviceService deviceService = SpringContextHolder.getBean(DeviceService.class);
private final TaskService taskService = SpringContextHolder.getBean(TaskServiceImpl.class);
/**
* 当前AGV正在执行的指令信息
*/
private List<Instruction> instructions = null;
/**
* AGV设备编码
*/
private String device_code;
/**
* AGV上报站点值
*/
private int agv_address = 0;
private int agv_address_copy = 0;
/**
* AGV上报当前phase值
*/
private int currentPhase = 0;
/**
* 存放AGV状态信息
*/
private final AgvDto agvInfo = AgvDto.builder()
.name(this.getDevice().getDevice_code())
.state("UNKNOWN")
.energyLevel("0")
.transportOrder(null)
.positionX("0")
.positionY("0")
.positionAngle("0")
.build();
/**
* 当AGV上报这些phase值时,param代表小车Id,此时carId无实际用途
*/
private static final int[] PHASES_CAR_ID = {0x67, 0x70, 0x71, 0x72, 0x73, 0x74};
/**
* 取货点phase值
*/
private static final int[] GET_PHASES = {0x03, 0x05, 0x07, 0x09, 0x1B, 0x1D, 0x1F, 0x21};
/**
* 倒料点phase值
*/
private static final int[] FALL_PHASES = {0x0B, 0x0D, 0x0F, 0x11};
/**
* 放货点phase值
*/
private static final int[] PUT_PHASES = {0x13, 0x15, 0x17, 0x19, 0x23, 0x25, 0x27, 0x29};
/**
* 开始任务
*/
private static final int PHASE_01 = 0x01;
/**
* 分配车ID
*/
private static final int PHASE_02 = 0x02;
/**
* 到达取货点1
*/
private static final int PHASE_03 = 0x03;
/**
* 取货完毕
*/
private static final int PHASE_05 = 0x05;
/**
* 到达取货点2
*/
private static final int PHASE_07 = 0x07;
/**
* 取货完毕
*/
private static final int PHASE_09 = 0x09;
/**
* 到达倒料点1
*/
private static final int PHASE_0B = 0x0B;
/**
* 倒料完毕
*/
private static final int PHASE_0D = 0x0D;
/**
* 到达倒料点2
*/
private static final int PHASE_0F = 0x0F;
/**
* 倒料完毕
*/
private static final int PHASE_11 = 0x11;
/**
* 到达放货点1
*/
private static final int PHASE_13 = 0x13;
/**
* 放货完毕
*/
private static final int PHASE_15 = 0x15;
/**
* 到达放货点2
*/
private static final int PHASE_17 = 0x17;
/**
* 放货完毕
*/
private static final int PHASE_19 = 0x19;
/**
* 到达取货点3
*/
private static final int PHASE_1B = 0x1B;
/**
* 取货完毕
*/
private static final int PHASE_1D = 0x1D;
/**
* 到达取货点4
*/
private static final int PHASE_1F = 0x1F;
/**
* 取货完毕
*/
private static final int PHASE_21 = 0x21;
/**
* 到达放货点3
*/
private static final int PHASE_23 = 0x23;
/**
* 放货完毕
*/
private static final int PHASE_25 = 0x25;
/**
* 到达放货点4
*/
private static final int PHASE_27 = 0x27;
/**
* 放货完毕
*/
private static final int PHASE_29 = 0x29;
/**
* 任务完毕
*/
private static final int PHASE_2A = 0x2A;
/**
* 请求删除任务
*/
private static final int PHASE_30 = 0x30;
/**
* 任务删除确认
*/
private static final int PHASE_FF = 0xFF;
/**
* 进入交通灯区域
*/
private static final int PHASE_50 = 0x50;
/**
* 离开交通灯区域
*/
private static final int PHASE_51 = 0x51;
/**
* 到达位置点
*/
private static final int PHASE_64 = 0x64;
/**
* 称重就绪
*/
private static final int PHASE_65 = 0x65;
/**
* 上报异常信息
*/
private static final int PHASE_67 = 0x67;
/**
* 上报X坐标
*/
private static final int PHASE_70 = 0x70;
/**
* 上报Y坐标
*/
private static final int PHASE_71 = 0x71;
/**
* 上报车辆角度
*/
private static final int PHASE_72 = 0x72;
/**
* 上报车辆电量
*/
private static final int PHASE_73 = 0x73;
/**
* 上报三色灯状态
*/
private static final int PHASE_74 = 0x74;
/**
* 处理NDC交互逻辑
*
* @param arr NDC上报报文信息
* @param phase phase值,AGV执行阶段
* @param index NDC调度系统的任务号
* @param ikey phase值不在phasesCarsId中代表ACS指令号或关联编号否则代表phase值对应的上报的信息异常、X坐标、Y坐标、角度、电量、三色灯状态等信息
* @param carId phase值不在phasesCarsId中代表小车Id否则暂无实际作用
* @param param phase值在phasesCarsId中代表小车Id,否则代表站点号-即AGV地址
*/
public synchronized void processSocket(byte[] arr, Integer phase, Integer index, Integer ikey, Integer carId, Integer param) {
this.device_code = this.getDevice_code();
byte[] data = null;
this.setTaskCodeToAgvInfo(ikey, phase);
this.currentPhase = phase;
switch (phase) {
//开始任务
case PHASE_01:
data = this.handleStartTask(ikey, index);
break;
//分配车Id
case PHASE_02:
this.assignCarId(ikey, carId);
break;
//到达取货点1、2、3、4
case PHASE_03:
case PHASE_07:
case PHASE_1B:
case PHASE_1F:
data = this.toGetPoint(ikey, index);
break;
//取货完闭1、2、3、4
case PHASE_05:
case PHASE_09:
case PHASE_1D:
case PHASE_21:
data = this.getFinish(ikey, index);
break;
//到达倒料点1、2
case PHASE_0B:
case PHASE_0F:
data = this.toFallPoint(ikey, index);
break;
//倒料完毕1、2
case PHASE_0D:
case PHASE_11:
data = this.fallFinish(ikey, index);
break;
//到达放货点1、2、3、4
case PHASE_13:
case PHASE_17:
case PHASE_23:
case PHASE_27:
data = this.toPutPoint(ikey, index);
break;
//放货完毕1、2、3、4
case PHASE_15:
case PHASE_19:
case PHASE_25:
case PHASE_29:
data = this.putFinish(ikey, index);
break;
//任务完成
case PHASE_2A:
data = this.taskFinish(ikey, index);
break;
//删除任务
case PHASE_30:
data = this.delTask(ikey, index);
break;
//删除任务确认
case PHASE_FF:
data = this.delTaskConfirm(ikey, index);
break;
//进入交通灯区域
case PHASE_50:
data = this.inLightArea();
break;
//离开交通灯区域
case PHASE_51:
data = this.outLightArea();
break;
//到达位置点
case PHASE_64:
data = this.arrivedPoint(param, index);
break;
//开始称重
case PHASE_65:
data = this.startWeighing(phase, ikey, index, param);
break;
//上报异常信息
case PHASE_67:
this.reportExceptionInfo();
break;
//上报车辆X坐标
case PHASE_70:
this.reportXCoordinate(ikey);
break;
//上报车辆Y坐标
case PHASE_71:
this.reportYCoordinate(ikey);
break;
//上报车辆角度
case PHASE_72:
this.reportAngle(ikey);
break;
//上报车辆电量
case PHASE_73:
this.reportElectric(ikey);
break;
//上报三色灯状态
case PHASE_74:
this.reportThreeColorStatus(ikey);
break;
default:
break;
}
if (data != null) {
NdcNettyConnectionAutoRun.write(data);
}
}
/**
* 开始任务
*
* @param ikey 指令号或关联编号
* @param index NDC的任务号
*/
private byte[] handleStartTask(Integer ikey, Integer index) {
List<Instruction> instructions = this.getInstructions(ikey);
if (ObjectUtil.isNotEmpty(instructions)) {
boolean flag = false;
Instruction instruction = instructions.get(0);
TaskDto taskDto = taskService.findByTaskCode(instruction.getTask_code());
if (taskDto != null) {
List<TaskDto> taskDtos = taskService.findByLinkNumFromCache(taskDto.getLink_num());
if (taskDtos != null) {
if (taskDtos.size() == 1) {
for (Instruction inst : instructions) {
inst.setInstruction_status(StatusEnum.INST_RUNNING.getCode());
inst.setAgv_jobno(String.valueOf(index));
inst.setSend_status(StatusEnum.YES.getCode());
instructionService.update(inst);
log.info("修改指令执行信息成功,指令号:{}", inst.getInstruction_code());
flag = true;
}
} else if (taskDtos.size() == 2) {
for (int i = 0; i < instructions.size(); i++) {
Instruction inst = instructions.get(i);
inst.setInstruction_status(StatusEnum.INST_RUNNING.getCode());
inst.setAgv_jobno(String.valueOf(index));
inst.setSend_status(StatusEnum.YES.getCode());
instructionService.update(inst);
if (i == 1) {
flag = true;
}
log.info("修改指令执行信息成功,指令号:{}", inst.getInstruction_code());
}
}
}
if (flag) {
return ndcAgvService.sendInstToNuoBaoNdc(currentPhase, index, 0);
}
}
}
return null;
}
/**
* 上报车号
*
* @param ikey 指令号或关联编号
* @param carId 车辆Id
*/
private void assignCarId(Integer ikey, Integer carId) {
List<Instruction> instructions = this.getInstructions(ikey);
for (Instruction inst : instructions) {
inst.setCarno(String.valueOf(carId));
instructionService.update(inst);
}
}
/**
* 到达取货点1、2、3、4
*
* @param ikey 指令号或关联编号
* @param index AGV任务号
*/
private byte[] toGetPoint(Integer ikey, Integer index) {
return processInstruction(ikey, index, currentPhase, new int[]{PHASE_03, PHASE_07, PHASE_1B, PHASE_1F});
}
/**
* 取货完成1、2、3、4
*
* @param ikey 指令号或关联编号
* @param index AGV任务号
*/
private byte[] getFinish(Integer ikey, Integer index) {
return processInstruction(ikey, index, currentPhase, new int[]{PHASE_05, PHASE_09, PHASE_1D, PHASE_21});
}
/**
* 到达倒料点1、2
*
* @param ikey
* @param index
* @return
*/
private byte[] fallFinish(Integer ikey, Integer index) {
return processInstruction(ikey, index, currentPhase, new int[]{PHASE_0D, PHASE_11});
}
/**
* 倒料完毕1、2
*
* @param ikey
* @param index
* @return
*/
private byte[] toFallPoint(Integer ikey, Integer index) {
return processInstruction(ikey, index, currentPhase, new int[]{PHASE_0B, PHASE_0F});
}
/**
* 到达放货点1、2、3、4
*
* @param ikey 指令号或关联编号
* @param index AGV任务号
*/
private byte[] toPutPoint(Integer ikey, Integer index) {
return processInstruction(ikey, index, currentPhase, new int[]{PHASE_13, PHASE_17, PHASE_23, PHASE_27});
}
/**
* 放货完毕1、2、3、4
*
* @param ikey 指令号或关联编号
* @param index AGV任务号
*/
private byte[] putFinish(Integer ikey, Integer index) {
return processInstruction(ikey, index, currentPhase, new int[]{PHASE_15, PHASE_19, PHASE_25, PHASE_29});
}
/**
* 处理取、倒、放货逻辑
*
* @param ikey
* @param index
* @param currentPhase
* @param phases
* @return
*/
private byte[] processInstruction(Integer ikey, Integer index, int currentPhase, int[] phases) {
Device device = this.getDeviceCodeByAgvAddress(agv_address);
if (device == null) {
log.info("AGV上报站点信息:{},根据站点信息查询设备为空!", agv_address);
return null;
}
List<Instruction> insts = this.getInstructions(ikey);
if (insts == null) {
log.info("AGV上报指令关联编号:{},根据指令关联编号查询指令信息为空!", ikey);
return null;
}
// 排序
insts.sort(Comparator.comparing(Instruction::getCreate_time));
Instruction inst = null;
// 根据当前阶段获取指令
for (int i = 0; i < phases.length; i++) {
if (currentPhase == (phases[i])) {
inst = getInstructionAtIndex(insts, i);
break;
}
}
// 校验指令和设备起始点
if (ObjectUtil.isEmpty(inst)) {
log.info("AGV上报phase值:{},获取指令信息为空!", currentPhase);
return null;
}
boolean isValidPhase = false;
//如果当前Phase值与取货点Phase值相同比较AGV上报站点与起点是否一致
//如果当前Phase值与倒料点Phase值相同比较AGV上报站点与倒料点是否一致
//如果当前Phase值与放货点Phase值相同比较AGV上报站点与放货点是否一致
if (Arrays.asList(GET_PHASES).contains(currentPhase)) {
isValidPhase = StrUtil.equals(inst.getStart_device_code(), device.getDevice_code());
} else if (Arrays.asList(FALL_PHASES).contains(currentPhase)) {
isValidPhase = StrUtil.equals(inst.getPut_device_code(), device.getDevice_code());
} else if (Arrays.asList(PUT_PHASES).contains(currentPhase)) {
isValidPhase = StrUtil.equals(inst.getNext_device_code(), device.getDevice_code());
}
if (isValidPhase) {
this.setPhaseToDriver(device, currentPhase, index, inst);
if (device.getDeviceDriver() instanceof StandardStorageDeviceDriver) {
return ndcAgvService.sendInstToNuoBaoNdc(currentPhase, index, 0);
}
} else {
log.info("AGV上报站点:{},上报phase值:{},与查询到的指令信息:{},中的取、倒、放点位信息不一致!", agv_address, currentPhase, inst.getInstruction_code());
}
return null;
}
/**
* 获取指定索引处的指令,如果索引超出范围,返回 null
*
* @param insts
* @param index
* @return
*/
private Instruction getInstructionAtIndex(List<Instruction> insts, int index) {
if (index < 0 || index >= insts.size()) {
return null;
}
return insts.get(index);
}
/**
* 任务完成
*
* @param ikey 指令号或关联编号
*/
private byte[] taskFinish(Integer ikey, Integer index) {
instructionService.finishByLinkNum(String.valueOf(ikey));
this.instructions = null;
this.agvInfo.setTransportOrder(null);
return ndcAgvService.sendInstToNuoBaoNdc(currentPhase, index, 0);
}
/**
* 删除任务
*
* @param ikey 指令号或关联编号
*/
private byte[] delTask(Integer ikey, Integer index) {
this.instructions = null;
this.agvInfo.setTransportOrder(null);
return ndcAgvService.sendInstToNuoBaoNdc(143, index, 0);
}
/**
* 删除任务确认
*
* @param ikey 指令号或关联编号
*/
private byte[] delTaskConfirm(Integer ikey, Integer index) {
try {
instructionService.forceCancelByLinkNum(String.valueOf(ikey));
this.instructions = null;
this.agvInfo.setTransportOrder(null);
} catch (Exception e) {
e.printStackTrace();
}
return ndcAgvService.sendInstToNuoBaoNdc(currentPhase, index, 0);
}
/**
* 到达位置点
*
* @param param AGV站点
*/
private byte[] arrivedPoint(Integer param, Integer index) {
agv_address = param;
agv_address_copy = agv_address;
return ndcAgvService.sendInstToNuoBaoNdc(currentPhase, index, 0);
}
/**
* 开始称重
*
* @param param AGV称重信息
*/
private byte[] startWeighing(Integer phase, Integer ikey, Integer index, Integer param) {
if (agv_address < 1) {
log.info("AGV开始称重,上报站点信息有误:{}", agv_address);
return null;
}
agv_address = agv_address_copy;
String device_code = deviceService.queryDeviceCodeByAddress(agv_address);
if (ObjectUtil.isEmpty(device_code)) {
log.info("AGV上报重量时站点:" + agv_address + ",对应设备号为空!");
return null;
}
//1、得到重量信息
int weight = param * 10;
if (weight < 0) {
log.info("AGV上报重量小于0不反馈AGV信息,指令号:{}", ikey);
return null;
}
List<Instruction> insts = this.getInstructions(ikey);
if (insts == null) {
log.info("AGV上报重量时根据ikey:{},查询指令信息为空!", ikey);
return null;
}
insts.sort(Comparator.comparing(Instruction::getCreate_time));
Instruction instruction = insts.stream()
.filter(inst -> StrUtil.isEmpty(inst.getWeight()))
.limit(1)
.findFirst()
.orElse(null);
if (instruction == null) {
log.info("未找到关联编号{}对应的指令", ikey);
return null;
}
if (StrUtil.equals(instruction.getStart_device_code(), device_code)) {
String now = DateUtil.now();
instruction.setWeight(String.valueOf(weight));
instruction.setUpdate_time(now);
instructionService.update(instruction);
TaskDto taskDto = taskService.findByCodeFromCache(instruction.getTask_code());
if (taskDto != null) {
taskDto.setWeight(String.valueOf(weight));
taskDto.setUpdate_time(now);
taskService.update(taskDto);
}
}
return ndcAgvService.sendAgvTwoModeInst(phase, index, 0);
}
private void reportExceptionInfo() {
}
private byte[] inLightArea() {
return null;
}
private byte[] outLightArea() {
return null;
}
/**
* 上报x坐标
*
* @param ikey x坐标
*/
private void reportXCoordinate(Integer ikey) {
this.agvInfo.setPositionX(String.valueOf(ikey));
}
/**
* 上报y坐标
*
* @param ikey y坐标
*/
private void reportYCoordinate(Integer ikey) {
this.agvInfo.setPositionY(String.valueOf(ikey));
}
/**
* 上报AGV角度
*
* @param ikey 角度
*/
private void reportAngle(Integer ikey) {
this.agvInfo.setPositionAngle(String.valueOf(ikey));
}
/**
* 上报AGV电量
*
* @param ikey 电量
*/
private void reportElectric(Integer ikey) {
this.agvInfo.setEnergyLevel(String.valueOf(ikey));
}
/**
* 上报三色灯状态
*
* @param ikey 三色灯状态
*/
private void reportThreeColorStatus(Integer ikey) {
this.agvInfo.setState("");
}
/**
* 向AGV设置任务号
*
* @param ikey 指令号或者关联编号
* @param phase 执行阶段
*/
private void setTaskCodeToAgvInfo(Integer ikey, Integer phase) {
if (ikey != 0 && ikey != null) {
if (!Arrays.asList(PHASES_CAR_ID).contains(phase)) {
if (this.instructions == null) {
this.instructions = this.getInstructions(ikey);
for (Instruction inst : this.instructions) {
this.agvInfo.setTransportOrder(inst.getTask_code());
}
}
}
}
}
/**
* 根据ikey查询指令信息
*
* @param ikey 指令编号或者关联编号
* @return
*/
private List<Instruction> getInstructions(Integer ikey) {
return instructionService.findByLinkNum(String.valueOf(ikey));
}
/**
* 抽取取放货公共逻辑
* 根据AGV上报的地址值获取设备信息
*
* @param agvAddress
* @return
*/
private Device getDeviceCodeByAgvAddress(Integer agvAddress) {
this.agv_address = this.agv_address == 0 ? this.agv_address_copy : this.agv_address;
if (agv_address < 1) {
//打日志
return null;
}
String device_code = deviceService.queryDeviceCodeByAddress(agvAddress);
if (agvAddress != 0) {
String old_device_code = deviceService.queryDeviceCodeByAddress(agvAddress);
if (StrUtil.contains(old_device_code, "-")) {
String[] point = old_device_code.split("-");
device_code = point[0];
} else if (StrUtil.contains(old_device_code, ".")) {
String[] point = old_device_code.split("\\.");
device_code = point[0];
} else {
device_code = old_device_code;
}
}
return deviceAppService.findDeviceByCode(device_code);
}
private void setPhaseToDriver(Device device, Integer phase, Integer index, Instruction inst) {
//刻字缓存位
HailiangEngravingCacheDeviceDriver hailiangEngravingCacheDeviceDriver;
//刻字机工位
HailiangEngravingMachineDeviceDriver hailiangEngravingMachineDeviceDriver;
//包装机工位
HailiangPackerStationDeviceDriver hailiangPackerStationDeviceDriver;
//普通站点
StandardOrdinarySiteDeviceDriver standardOrdinarySiteDeviceDriver;
//货架
StandardStorageDeviceDriver standardStorageDeviceDriver;
//刻字上料线体
HailiangEngravingInDeviceDriver hailiangEngravingInDeviceDriver;
//
HailiangCleaningPutLineDeviceDriver hailiangCleaningPutLineDeviceDriver;
if (device.getDeviceDriver() instanceof HailiangEngravingMachineDeviceDriver) {
hailiangEngravingMachineDeviceDriver = (HailiangEngravingMachineDeviceDriver) device.getDeviceDriver();
hailiangEngravingMachineDeviceDriver.set(phase, index, inst);
}
if (device.getDeviceDriver() instanceof HailiangEngravingCacheDeviceDriver) {
hailiangEngravingCacheDeviceDriver = (HailiangEngravingCacheDeviceDriver) device.getDeviceDriver();
hailiangEngravingCacheDeviceDriver.set(phase, index, inst);
}
if (device.getDeviceDriver() instanceof StandardOrdinarySiteDeviceDriver) {
standardOrdinarySiteDeviceDriver = (StandardOrdinarySiteDeviceDriver) device.getDeviceDriver();
standardOrdinarySiteDeviceDriver.set(phase, index, inst);
}
if (device.getDeviceDriver() instanceof HailiangPackerStationDeviceDriver) {
hailiangPackerStationDeviceDriver = (HailiangPackerStationDeviceDriver) device.getDeviceDriver();
hailiangPackerStationDeviceDriver.set(phase, index, inst);
}
if (device.getDeviceDriver() instanceof HailiangEngravingInDeviceDriver) {
hailiangEngravingInDeviceDriver = (HailiangEngravingInDeviceDriver) device.getDeviceDriver();
hailiangEngravingInDeviceDriver.set(phase, index, inst);
}
if (device.getDeviceDriver() instanceof HailiangCleaningPutLineDeviceDriver) {
hailiangCleaningPutLineDeviceDriver = (HailiangCleaningPutLineDeviceDriver) device.getDeviceDriver();
hailiangCleaningPutLineDeviceDriver.set(phase, index, inst);
}
}
}