package com.zy.core.thread;
|
|
import HslCommunication.Core.Types.OperateResult;
|
import HslCommunication.Core.Types.OperateResultExOne;
|
import HslCommunication.Profinet.Siemens.SiemensPLCS;
|
import HslCommunication.Profinet.Siemens.SiemensS7Net;
|
import com.alibaba.fastjson.JSON;
|
import com.core.common.Cools;
|
import com.core.common.DateUtils;
|
import com.core.common.SpringUtils;
|
import com.core.exception.CoolException;
|
import com.zy.asrs.entity.BasSte;
|
import com.zy.asrs.entity.BasSteOpt;
|
import com.zy.asrs.service.BasSteOptService;
|
import com.zy.asrs.service.BasSteService;
|
import com.zy.core.News;
|
import com.zy.core.ThreadHandler;
|
import com.zy.core.cache.MessageQueue;
|
import com.zy.core.cache.OutputQueue;
|
import com.zy.core.enums.SlaveType;
|
import com.zy.core.enums.SteStatusType;
|
import com.zy.core.model.SteSlave;
|
import com.zy.core.model.Task;
|
import com.zy.core.model.command.SteCommand;
|
import com.zy.core.model.protocol.SteProtocol;
|
import lombok.Data;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.text.MessageFormat;
|
import java.util.Date;
|
|
/**
|
* shuttle 穿梭车线程
|
* Created by vincent on 2020/8/4
|
* 不能有 槽号 和 机架号
|
*/
|
@Data
|
@Slf4j
|
public class SteThread implements Runnable, ThreadHandler {
|
|
private SiemensS7Net siemensS7Net;
|
private SteSlave slave;
|
private SteProtocol steProtocol;
|
private short heartBeatVal = 1;
|
private boolean resetFlag = false;
|
|
public SteThread(SteSlave slave) {
|
this.slave = slave;
|
}
|
|
@Override
|
@SuppressWarnings("InfiniteLoopStatement")
|
public void run() {
|
this.connect();
|
while (true) {
|
try {
|
int step = 1;
|
Task task = MessageQueue.poll(SlaveType.Ste, slave.getId());
|
if (task != null) {
|
step = task.getStep();
|
}
|
switch (step) {
|
// 读数据
|
case 1:
|
readStatus();
|
break;
|
// 写入数据
|
case 2:
|
write((SteCommand) task.getData());
|
break;
|
default:
|
break;
|
}
|
// 心跳
|
// heartbeat();
|
Thread.sleep(500);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
|
}
|
}
|
|
/**
|
* 初始化堆垛机状态
|
*/
|
private void initSte() {
|
if (null == steProtocol) {
|
steProtocol = new SteProtocol();
|
}
|
steProtocol.setSteNo(slave.getId().shortValue());
|
steProtocol.setMode((short) 0);
|
steProtocol.setStatus(SteStatusType.OFF_LINE);
|
steProtocol.setTaskNo((short) 0);
|
steProtocol.setExecute(false);
|
steProtocol.setWaiting(false);
|
}
|
|
@Override
|
public boolean connect() {
|
boolean result = false;
|
// 不能有 槽号 和 机架号
|
siemensS7Net = new SiemensS7Net(SiemensPLCS.S200Smart, slave.getIp());
|
// siemensS7Net.setRack(slave.getRack().byteValue());
|
// siemensS7Net.setSlot(slave.getSlot().byteValue());
|
OperateResult connect = siemensS7Net.ConnectServer();
|
if(connect.IsSuccess){
|
result = true;
|
OutputQueue.STE.offer(MessageFormat.format( "【{0}】穿梭车plc连接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
News.info("穿梭车plc连接成功 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
|
} else {
|
OutputQueue.STE.offer(MessageFormat.format("【{0}】穿梭车plc连接失败!!! ===>> [id:{1}] [ip:{2}] [port:{3}] ", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
News.error("穿梭车plc连接失败!!! ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
|
initSte();
|
}
|
// melsecMcNet.ConnectClose();
|
return result;
|
}
|
|
/**
|
* 读取状态
|
*/
|
private void readStatus(){
|
try {
|
OperateResultExOne<byte[]> result = siemensS7Net.Read("V800", (short) 70);
|
if (result.IsSuccess) {
|
if (null == steProtocol) {
|
steProtocol = new SteProtocol();
|
steProtocol.setSteNo(slave.getId().shortValue());
|
}
|
// steProtocol.setSteNo(siemensS7Net.getByteTransform().TransInt16(result.Content, 0));
|
steProtocol.setMode(siemensS7Net.getByteTransform().TransInt16(result.Content, 2));
|
steProtocol.setStatus(siemensS7Net.getByteTransform().TransInt16(result.Content, 4));
|
OperateResultExOne<Boolean> executeRes = siemensS7Net.ReadBool("V2001.0");
|
if (executeRes.IsSuccess) {
|
steProtocol.setExecute(executeRes.Content);
|
}
|
OperateResultExOne<Boolean> waitingRes = siemensS7Net.ReadBool("V2001.1");
|
if (waitingRes.IsSuccess) {
|
steProtocol.setWaiting(waitingRes.Content);
|
}
|
OperateResultExOne<Boolean> inEmptyRes = siemensS7Net.ReadBool("V2001.2");
|
if (inEmptyRes.IsSuccess) {
|
steProtocol.setInEmpty(inEmptyRes.Content);
|
}
|
OperateResultExOne<Boolean> outEmptyRes = siemensS7Net.ReadBool("V2001.3");
|
if (outEmptyRes.IsSuccess) {
|
steProtocol.setOutEmpty(outEmptyRes.Content);
|
}
|
steProtocol.setAlarm(siemensS7Net.getByteTransform().TransInt16(result.Content, 6));
|
steProtocol.setAlarm0(siemensS7Net.getByteTransform().TransInt16(result.Content, 8));
|
steProtocol.setCharge(siemensS7Net.getByteTransform().TransSingle(result.Content, 10));
|
// steProtocol.setFullCharge();
|
// steProtocol.setLowCharge();
|
steProtocol.setFeed(siemensS7Net.getByteTransform().TransInt16(result.Content, 14));
|
steProtocol.setLoca(siemensS7Net.getByteTransform().TransInt16(result.Content, 16));
|
// steProtocol.setCloser();
|
// steProtocol.setSpeed();
|
steProtocol.setPos(siemensS7Net.getByteTransform().TransInt16(result.Content, 18));
|
steProtocol.setLoad(siemensS7Net.getByteTransform().TransInt16(result.Content, 20));
|
steProtocol.setTrack(siemensS7Net.getByteTransform().TransInt16(result.Content, 22));
|
steProtocol.setTaskNo(siemensS7Net.getByteTransform().TransInt16(result.Content, 24));
|
steProtocol.setTaskType(siemensS7Net.getByteTransform().TransInt16(result.Content, 28));
|
steProtocol.setRow(siemensS7Net.getByteTransform().TransInt16(result.Content, 30));
|
steProtocol.setBay(siemensS7Net.getByteTransform().TransInt16(result.Content, 32));
|
steProtocol.setLev(siemensS7Net.getByteTransform().TransInt16(result.Content, 34));
|
|
// steProtocol.setHisTaskNo(siemensS7Net.getByteTransform().TransInt32(result.Content, 58));
|
// steProtocol.setHisTaskStatus(siemensS7Net.getByteTransform().TransInt16(result.Content, 62));
|
// steProtocol.setCheckQty(siemensS7Net.getByteTransform().TransInt16(result.Content, 64));
|
steProtocol.setReady(siemensS7Net.getByteTransform().TransInt16(result.Content, 36));
|
// steProtocol.setChargeNo(siemensS7Net.getByteTransform().TransInt16(result.Content, 68));
|
|
// steProtocol.setHeart(siemensS7Net.getByteTransform().TransInt16(result.Content, 72));
|
steProtocol.setCrnStopRun(siemensS7Net.getByteTransform().TransInt16(result.Content, 38));
|
steProtocol.setCrnStopFork(siemensS7Net.getByteTransform().TransInt16(result.Content, 40));
|
steProtocol.setCrnAllowRun(siemensS7Net.getByteTransform().TransInt16(result.Content, 42));
|
steProtocol.setChargeStatus(siemensS7Net.getByteTransform().TransInt16(result.Content, 44));
|
|
OutputQueue.STE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
|
|
//读取穿梭车设备信息,提供查询
|
OperateResultExOne<byte[]> result1 = siemensS7Net.Read("V732", (short) 16);
|
if (result1.IsSuccess) {
|
boolean[] status = siemensS7Net.getByteTransform().TransBool(result1.Content, 0, 128);
|
steProtocol.setLiftErr(status[0]);
|
steProtocol.setInFetchErr(status[2]);
|
steProtocol.setOutFetchErr(status[3]);
|
steProtocol.setAntiErr(status[4]);
|
steProtocol.setLiftSwitchErr(status[5]);
|
steProtocol.setTrackErr(status[6]);
|
steProtocol.setTimeoutErr(status[7]);
|
steProtocol.setConnectErr(status[8]);
|
steProtocol.setEmergencyErr(status[9]);
|
steProtocol.setTaskTypeErr(status[10]);
|
steProtocol.setTaskNoErr(status[11]);
|
steProtocol.setNewTaskErr(status[12]);
|
steProtocol.setErrTaskErr(status[13]);
|
steProtocol.setStopErr(status[14]);
|
steProtocol.setOfflineTaskErr(status[15]);
|
steProtocol.setStartTaskErr(status[16]);
|
steProtocol.setVoltageTaskErr(status[17]);
|
|
steProtocol.setDevpErr(status[63]);
|
|
steProtocol.setOnline(status[64]);
|
steProtocol.setNotOnTrack(status[65]);
|
steProtocol.setLowVoltage(status[66]);
|
steProtocol.setElectricityLoss(status[67]);
|
steProtocol.setForcedTravel(status[68]);
|
steProtocol.setDemoMode(status[69]);
|
steProtocol.setBrushConnect(status[70]);
|
steProtocol.setTaskManualForbid(status[71]);
|
steProtocol.setOnlineManualForbid(status[72]);
|
steProtocol.setDevpEmergency(status[73]);
|
steProtocol.setTaskInterrupt(status[74]);
|
steProtocol.setTaskClear(status[75]);
|
steProtocol.setTaskConfirmTimeout(status[76]);
|
steProtocol.setTaskWithCharge(status[77]);
|
|
steProtocol.setPakInTask(status[96]);
|
steProtocol.setPakOutTask(status[97]);
|
steProtocol.setPakMoveTask(status[98]);
|
steProtocol.setGoHpTask(status[99]);
|
steProtocol.setGoOHpTask(status[100]);
|
steProtocol.setGoHpAvoid(status[101]);
|
steProtocol.setGoOHpAvoid(status[102]);
|
steProtocol.setPakInEmpty(status[104]);
|
steProtocol.setPakInFinish(status[105]);
|
steProtocol.setPakOutEmpty(status[106]);
|
steProtocol.setPakOutFinish(status[107]);
|
steProtocol.setGoHpAvoidFinish(status[108]);
|
steProtocol.setGoOHpAvoidFinish(status[109]);
|
steProtocol.setGoHpAvoidErr(status[110]);
|
steProtocol.setGoOHpAvoidErr(status[111]);
|
|
steProtocol.setAutoMode(status[112]);
|
steProtocol.setVoltageLow(status[113]);
|
}
|
|
// 复位信号
|
if (steProtocol.getWaiting()) {
|
if (resetFlag) {
|
SteCommand steCommand = new SteCommand();
|
steCommand.setComplete(true);
|
if (write(steCommand) && confirmPos()) {
|
resetFlag = false;
|
}
|
}
|
}
|
|
// 根据实时信息更新数据库
|
BasSteService service = SpringUtils.getBean(BasSteService.class);
|
if (null != service) {
|
// 同步pakMk
|
BasSte one = service.selectById(slave.getId());
|
if (one != null) {
|
steProtocol.setPakMk(one.getPakMk());
|
}
|
|
BasSte basSte = new BasSte();
|
basSte.setSteNo(slave.getId());
|
if (!service.updateById(steProtocol.toSqlModel(basSte))){
|
News.error("穿梭车plc数据库更新失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
|
}
|
|
}
|
} else {
|
OutputQueue.STE.offer(MessageFormat.format("【{0}】{1}穿梭车plc状态信息失败",DateUtils.convert(new Date()), slave.getId()));
|
throw new CoolException(MessageFormat.format( "穿梭车plc状态信息失败 ===>> [id:{0}] [ip:{1}] [port:{2}]", slave.getId(), slave.getIp(), slave.getPort()));
|
}
|
} catch (Exception e) {
|
// e.printStackTrace();
|
OutputQueue.STE.offer(MessageFormat.format("【{0}】读取穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
// News.error("读取穿梭车plc状态信息失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
|
initSte();
|
}
|
|
}
|
|
/**
|
* 写入数据
|
*/
|
private boolean write(SteCommand command){
|
if (null == command) {
|
News.error("穿梭车写入命令为空");
|
return false;
|
}
|
command.setSteNo(slave.getId());
|
OperateResult result = null;
|
// 开始任务
|
if (!command.getComplete()) {
|
// 1.任务号
|
OperateResult result0 = siemensS7Net.Write("V998", command.getTaskNo().shortValue());
|
try {
|
Thread.sleep(200);
|
} catch (InterruptedException e) {
|
e.printStackTrace();
|
}
|
// 作业
|
if (command.getTaskMode() != 0) {
|
// 2.作业
|
OperateResult result1 = siemensS7Net.Write("V1000", command.getTaskMode());
|
// 3.确认开始任务
|
if (result0.IsSuccess && result1.IsSuccess) {
|
result = siemensS7Net.Write("V2000.0", true);
|
siemensS7Net.Write("V2000.1", false);
|
}
|
|
// 其他指令
|
} else {
|
// 控制模式
|
if (command.getControlMode() != null) {
|
result = siemensS7Net.Write("V1010", command.getControlMode());
|
// 复位信号
|
} else if (command.getReset() != null) {
|
result = siemensS7Net.Write("V2000.2", command.getReset());
|
// 删除指令
|
} else if (command.getDelete() != null) {
|
result = siemensS7Net.Write("V2000.3", command.getDelete());
|
// 无效指令
|
} else if (command.getRun() != null) {
|
result = siemensS7Net.Write("V1016", command.getRun());
|
// 无效指令
|
}else {
|
return false;
|
}
|
}
|
|
// 任务完成
|
} else {
|
siemensS7Net.Write("V2000.0", false);
|
siemensS7Net.Write("V998", (short) 0);
|
siemensS7Net.Write("V1000", (short) 0);
|
result = siemensS7Net.Write("V2000.1", true);
|
}
|
|
try {
|
// 日志记录
|
if (!command.getComplete() && command.getTaskMode() != 0) {
|
BasSteOptService bean = SpringUtils.getBean(BasSteOptService.class);
|
if (null != bean) {
|
BasSteOpt basSteOpt = new BasSteOpt(
|
command.getTaskNo(), // 任务号
|
command.getSteNo(), // 穿梭车
|
new Date(), // 下发时间
|
command.getTaskModeType().desc, // 作业
|
null, // 源排
|
null, // 源列
|
null, // 源层
|
null, // 源站
|
null, // 目标排
|
null, // 目标列
|
null, // 目标层
|
null, // 目标站
|
null, // 响应结果
|
null, // 修改时间
|
null, // 修改人员
|
null // 备注
|
);
|
bean.insert(basSteOpt);
|
}
|
}
|
|
} catch (Exception ignore) {}
|
|
if (result != null && result.IsSuccess) {
|
// 维护数据库排列层
|
if (!steProtocol.getWaiting()) {
|
if (!Cools.isEmpty(command.getRow(), command.getBay(), command.getLev())) {
|
this.modifyPos(command.getRow().intValue(), command.getBay().intValue(), command.getLev().intValue());
|
}
|
}
|
|
News.info("穿梭车命令下发[id:{}] >>>>> {}", slave.getId(), JSON.toJSON(command));
|
OutputQueue.STE.offer(MessageFormat.format("【{0}】[id:{1}] >>>>> 命令下发: {2}", DateUtils.convert(new Date()), slave.getId(), JSON.toJSON(command)));
|
return true;
|
} else {
|
OutputQueue.STE.offer(MessageFormat.format("【{0}】写入穿梭车plc数据失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
News.error("写入穿梭车plc数据失败 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
|
return false;
|
}
|
}
|
|
public void modifyPos(Integer row, Integer bay, Integer lev) {
|
BasSteService service = SpringUtils.getBean(BasSteService.class);
|
if (!service.updatePos(this.slave.getId(), row, bay, lev)) {
|
News.error("更新{}号穿梭车定位失败 ===>> 排:【{}】, 列:【{}】,层:【{}】", this.slave.getId(), row, bay, lev);
|
}
|
}
|
|
public boolean confirmPos() {
|
BasSteService service = SpringUtils.getBean(BasSteService.class);
|
BasSte basSte = service.selectById(slave.getId());
|
if (basSte != null) {
|
// 更新plc数据块
|
short[] arr = new short[] {basSte.getRow().shortValue(), basSte.getBay().shortValue(), basSte.getLev().shortValue()};
|
OperateResult result = siemensS7Net.Write("V1002", arr);
|
if (result.IsSuccess) {
|
// 更新数据库
|
if (service.updatePakMk(this.slave.getId(), "N")) {
|
return true;
|
} else {
|
News.error("{}号穿梭车修改数据库定位失败!!!", slave.getId());
|
}
|
}
|
}
|
return false;
|
}
|
|
public boolean modifyPosHandle(Integer row, Integer bay, Integer lev) {
|
short[] arr = new short[] {row.shortValue(), bay.shortValue(), lev.shortValue()};
|
OperateResult result = siemensS7Net.Write("V1002", arr);
|
if (!result.IsSuccess) {
|
News.error("更新{}号穿梭车定位失败 ===>> 排:【{}】, 列:【{}】,层:【{}】", this.slave.getId(), row, bay, lev);
|
return false;
|
}
|
BasSteService service = SpringUtils.getBean(BasSteService.class);
|
if (!service.updatePos(this.slave.getId(), row, bay, lev)) {
|
News.error("更新{}号穿梭车定位失败 ===>> 排:【{}】, 列:【{}】,层:【{}】", this.slave.getId(), row, bay, lev);
|
return false;
|
}
|
return true;
|
}
|
|
@Override
|
public void close() {
|
siemensS7Net.ConnectClose();
|
}
|
|
/**
|
* 心跳
|
*/
|
private void heartbeat(){
|
if (heartBeatVal == 1) {
|
heartBeatVal = 2;
|
} else {
|
heartBeatVal = 1;
|
}
|
OperateResult write = siemensS7Net.Write("D10", heartBeatVal);
|
if (!write.IsSuccess) {
|
News.error("输送线plc编号={} 心跳失败", slave.getId());
|
}
|
}
|
|
// public void modifyPos(int wrkNo, int row, int bay, int lev) {
|
// BasSteService service = SpringUtils.getBean(BasSteService.class);
|
// if (!service.updatePos(wrkNo,this.slave.getId(), row, bay, lev)) {
|
// News.error("更新{}号穿梭车定位失败 ===>> 排:【{}】, 列:【{}】,层:【{}】", this.slave.getId(), row, bay, lev);
|
// }
|
// }
|
|
/******************************************************************************************/
|
/**************************************** 测试专用 *****************************************/
|
/*****************************************************************************************/
|
public static void main(String[] args) throws InterruptedException {
|
SteSlave slave = new SteSlave();
|
slave.setId(1);
|
slave.setIp("192.168.2.1");
|
slave.setPort(502);
|
SteThread thread = new SteThread(slave);
|
thread.connect();
|
thread.readStatus();
|
System.out.println(JSON.toJSONString(thread.steProtocol));
|
|
// 任务作业
|
// SteCommand command = new SteCommand();
|
// command.setSteNo(1); // 堆垛机编号
|
// Random random = new Random();
|
// int taskNo = random.nextInt(9090);
|
// command.setTaskNo(taskNo); // 工作号
|
// command.setTaskMode(SteTaskModeType.MOVE_LEFT); // 任务模式
|
// thread.write(command);
|
|
// 任务完成
|
// SteCommand command = new SteCommand();
|
// command.setSteNo(1); // 堆垛机编号
|
// command.setComplete(Boolean.TRUE); // 任务模式
|
// thread.write(command);
|
|
// 控制模式
|
// SteCommand command = new SteCommand();
|
// command.setControlMode((short) 1);
|
// thread.write(command);
|
|
// 复位信号
|
// SteCommand command = new SteCommand();
|
// command.setReset(Boolean.TRUE);
|
// thread.write(command);
|
|
// 删除指令
|
// SteCommand command = new SteCommand();
|
// command.setDelete(Boolean.TRUE);
|
// thread.write(command);
|
|
// 穿梭车运行禁止
|
SteCommand command = new SteCommand();
|
command.setRun((short)0);
|
thread.write(command);
|
|
}
|
|
}
|