package com.zy.core.thread;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.core.common.DateUtils;
|
import com.core.common.SpringUtils;
|
import com.zy.asrs.entity.*;
|
import com.zy.asrs.service.*;
|
|
import com.zy.common.utils.*;
|
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.cache.SlaveConnection;
|
import com.zy.core.enums.*;
|
import com.zy.core.model.ShuttleSlave;
|
import com.zy.core.model.Task;
|
import com.zy.core.model.command.NyShuttleHttpCommand;
|
import com.zy.core.model.command.ShuttleAssignCommand;
|
import com.zy.core.model.command.ShuttleCommand;
|
import com.zy.core.model.command.ShuttleRedisCommand;
|
import com.zy.core.model.protocol.LiftProtocol;
|
import com.zy.core.model.protocol.NyShuttleProtocol;
|
import lombok.Data;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.text.MessageFormat;
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
|
/**
|
* 牛眼四向穿梭车线程
|
*/
|
@Data
|
@Slf4j
|
public class NyShuttleThread implements Runnable, ThreadHandler {
|
|
private ShuttleSlave slave;
|
private NyShuttleProtocol shuttleProtocol;
|
private RedisUtil redisUtil;
|
|
public NyShuttleThread(ShuttleSlave slave,RedisUtil redisUtil) {
|
this.slave = slave;
|
this.redisUtil = redisUtil;
|
}
|
|
@Override
|
public void run() {
|
this.connect();
|
while (true) {
|
try {
|
int step = 1;
|
Task task = MessageQueue.poll(SlaveType.Shuttle, slave.getId());
|
if (task != null) {
|
step = task.getStep();
|
}
|
switch (step) {
|
// 读数据
|
case 1:
|
read();
|
break;
|
// 写入数据
|
case 2:
|
write((NyShuttleHttpCommand) task.getData());
|
break;
|
//下发任务
|
case 3:
|
assignWork((ShuttleAssignCommand) task.getData());
|
break;
|
default:
|
break;
|
}
|
Thread.sleep(500);
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
|
private void read() {
|
try {
|
readStatus();
|
//四向穿梭车空闲、有任务、标记为true、存在任务指令,需要执行任务的下一条指令
|
if (shuttleProtocol.getFree() == ShuttleStatusType.IDLE.id
|
&& shuttleProtocol.getTaskNo() != 0
|
&& shuttleProtocol.getPakMk()) {
|
//执行下一步指令
|
executeWork(shuttleProtocol.getTaskNo().shortValue());
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
}
|
}
|
|
private void readStatus() {
|
try {
|
if (null == shuttleProtocol) {
|
shuttleProtocol = new NyShuttleProtocol();
|
shuttleProtocol.setShuttleNo(slave.getId().shortValue());
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);
|
}
|
|
//----------读取四向穿梭车状态-----------
|
NyShuttleHttpCommand readStatusCommand = NyHttpUtils.getReadStatusCommand(slave.getId());
|
JSONObject jsonObject = NyHttpUtils.requestCommand(readStatusCommand);
|
if (jsonObject == null) {
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
}else {
|
//手动状态/自动状态
|
shuttleProtocol.setWorkingMode(jsonObject.getInteger("workingMode"));
|
//允许状态 0:运行中1:空闲
|
shuttleProtocol.setFree(jsonObject.getInteger("free"));
|
//当前速度
|
shuttleProtocol.setSpeed(jsonObject.getInteger("speed"));
|
//负载状态
|
shuttleProtocol.setLoadState(jsonObject.getInteger("loadState"));
|
//管制状态
|
shuttleProtocol.setSuspendState(jsonObject.getInteger("suspendState"));
|
//顶升位置
|
shuttleProtocol.setLiftPosition(jsonObject.getInteger("liftPosition"));
|
//运行方向
|
shuttleProtocol.setRunDir(jsonObject.getInteger("runDir"));
|
//运行方向
|
shuttleProtocol.setRunDir2(jsonObject.getInteger("runDir2"));
|
//充电状态
|
shuttleProtocol.setChargState(jsonObject.getInteger("chargState"));
|
//电池电量
|
shuttleProtocol.setPowerPercent(jsonObject.getInteger("powerPercent"));
|
//最高电芯电压(mV)
|
shuttleProtocol.setMaxCellVoltage(jsonObject.getInteger("maxCellVoltage"));
|
//最低电芯电压(mV)
|
shuttleProtocol.setMinCellVoltage(jsonObject.getInteger("minCellVoltage"));
|
//电池电压
|
shuttleProtocol.setVoltage(jsonObject.getInteger("voltage"));
|
//充放电循环次数
|
shuttleProtocol.setChargeCycleTimes(jsonObject.getInteger("chargeCycleTimes"));
|
//剩余电量
|
shuttleProtocol.setSurplusQuantity(jsonObject.getInteger("surplusQuantity"));
|
//总电量
|
shuttleProtocol.setCountQuantity(jsonObject.getInteger("countQuantity"));
|
//实际库位xyz
|
shuttleProtocol.setPoint(jsonObject.getObject("point", NyShuttleProtocol.NyShuttlePointClass.class));
|
//实际坐标xyz
|
shuttleProtocol.setCoord(jsonObject.getObject("coord", NyShuttleProtocol.NyShuttlePointClass.class));
|
//任务目的库位
|
shuttleProtocol.setTask(jsonObject.getObject("task", NyShuttleProtocol.TaskClass.class));
|
//任务状态
|
shuttleProtocol.setTaskState(jsonObject.getInteger("taskState"));
|
//故障状态
|
shuttleProtocol.setErrState(jsonObject.getInteger("errState"));
|
ArrayList<Integer> errCode = new ArrayList<>();
|
for (Object o : jsonObject.getJSONArray("errCode")) {
|
errCode.add(Integer.parseInt(o.toString()));
|
}
|
//故障码
|
shuttleProtocol.setErrCode(errCode);
|
//总里程数
|
shuttleProtocol.setStatusSum(jsonObject.getObject("statusSum", NyShuttleProtocol.StatusSumClass.class));
|
//非自动状态时间计时
|
shuttleProtocol.setErrTime(jsonObject.getInteger("errTime"));
|
|
//小车处于运行中,将标记置为true
|
if (shuttleProtocol.getFree() == 0) {
|
shuttleProtocol.setPakMk(true);
|
}
|
|
//将四向穿梭车状态保存至数据库
|
BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
|
BasShuttle basShuttle = shuttleService.selectById(slave.getId());
|
if (basShuttle == null) {
|
basShuttle = new BasShuttle();
|
//四向穿梭车号
|
basShuttle.setShuttleNo(slave.getId());
|
shuttleService.insert(basShuttle);
|
}
|
//工作模式
|
basShuttle.setWorkingMode(shuttleProtocol.getWorkingMode());
|
//运行状态
|
basShuttle.setFree(shuttleProtocol.getFree());
|
//当前速度
|
basShuttle.setSpeed(shuttleProtocol.getSpeed());
|
//负载状态
|
basShuttle.setLoadState(shuttleProtocol.getLoadState());
|
//管制状态
|
basShuttle.setSuspendState(shuttleProtocol.getSuspendState());
|
//顶升位置
|
basShuttle.setLiftPosition(shuttleProtocol.getLiftPosition());
|
//运行方向
|
basShuttle.setRunDir(shuttleProtocol.getRunDir());
|
//运行方向
|
basShuttle.setRunDir2(shuttleProtocol.getRunDir2());
|
//充电状态
|
basShuttle.setChargState(shuttleProtocol.getChargState());
|
//电池电量
|
basShuttle.setPowerPercent(shuttleProtocol.getPowerPercent());
|
//最高电芯电压
|
basShuttle.setMaxCellVoltage(shuttleProtocol.getMaxCellVoltage());
|
//电池电压
|
basShuttle.setVoltage(shuttleProtocol.getVoltage());
|
//充放电循环次数
|
basShuttle.setChargeCycleTimes(shuttleProtocol.getChargeCycleTimes());
|
//剩余电量
|
basShuttle.setSurplusQuantity(shuttleProtocol.getSurplusQuantity());
|
//总电量
|
basShuttle.setCountQuantity(shuttleProtocol.getCountQuantity());
|
//实际库位
|
basShuttle.setPoint(JSONObject.toJSONString(shuttleProtocol.getPoint()));
|
//实际坐标
|
basShuttle.setCoord(JSONObject.toJSONString(shuttleProtocol.getCoord()));
|
//任务目的库位
|
basShuttle.setTask(JSONObject.toJSONString(shuttleProtocol.getTask()));
|
//任务状态
|
basShuttle.setTaskState(shuttleProtocol.getTaskState());
|
//故障状态
|
basShuttle.setErrState(shuttleProtocol.getErrState());
|
//总里程数
|
basShuttle.setStatusSum(JSONObject.toJSONString(shuttleProtocol.getStatusSum()));
|
//非自动状态时间计时
|
basShuttle.setErrTime(shuttleProtocol.getErrTime());
|
//任务号
|
basShuttle.setWrkNo(shuttleProtocol.getTaskNo().intValue());
|
//修改时间
|
basShuttle.setUpdateTime(new Date());
|
//作业标记
|
basShuttle.setPakMk(shuttleProtocol.getPakMk());
|
if (shuttleService.updateById(basShuttle)) {
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
|
// log.info(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId()));
|
}
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort()));
|
}
|
}
|
|
@Override
|
public boolean connect() {
|
return true;
|
}
|
|
@Override
|
public void close() {
|
|
}
|
|
private boolean write(NyShuttleHttpCommand command){
|
if (null == command) {
|
News.error("四向穿梭车写入命令为空");
|
return false;
|
}
|
BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class);
|
if (shuttleService == null) {
|
News.error("系统错误");
|
return false;
|
}
|
|
BasShuttle basShuttle = shuttleService.selectById(slave.getId().shortValue());
|
if (basShuttle == null) {
|
News.error("四向穿梭车不存在");
|
return false;
|
}
|
|
//发出请求
|
JSONObject result = NyHttpUtils.requestCommand(command);
|
if (result == null) {
|
return false;//请求失败
|
}
|
|
return true;
|
}
|
|
//分配任务
|
private void assignWork(ShuttleAssignCommand assignCommand) {
|
ShuttleRedisCommand redisCommand = new ShuttleRedisCommand();
|
redisCommand.setShuttleNo(assignCommand.getShuttleNo());//四向穿梭车号
|
redisCommand.setWrkNo(assignCommand.getTaskNo());//工作号
|
redisCommand.setCommandStep(0);//命令执行步序
|
redisCommand.setAssignCommand(assignCommand);//命令
|
shuttleProtocol.setTaskNo(assignCommand.getTaskNo().intValue());
|
shuttleProtocol.setAssignCommand(assignCommand);
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WORKING);
|
//任务数据保存到redis
|
redisUtil.set("shuttle_wrk_no_" + assignCommand.getTaskNo(), JSON.toJSONString(redisCommand));
|
//执行下发任务
|
executeWork(assignCommand.getTaskNo());
|
}
|
|
//执行下发的指令
|
private boolean executeWork(Short wrkNo) {
|
//读取redis数据
|
if (wrkNo == null) {
|
return false;
|
}
|
|
WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class);
|
|
Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
|
if (o == null) {
|
return false;
|
}
|
ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
|
List<NyShuttleHttpCommand> commands = redisCommand.getAssignCommand().getCommands();
|
ShuttleAssignCommand assignCommand = redisCommand.getAssignCommand();
|
//当前步序
|
int commandStep = redisCommand.getCommandStep();
|
if (commands.size() == 0) {
|
return false;
|
}
|
//取出命令
|
NyShuttleHttpCommand command = commands.get(commandStep);
|
|
if (shuttleProtocol.getFree() == ShuttleStatusType.BUSY.id) {
|
return false;//小车状态忙,禁止执行命令
|
}
|
|
//检测小车是否要进提升机,如需要进提升机则调度提升机
|
if (!checkLiftStation(wrkNo)) {
|
return false;
|
}
|
|
//检查路径是否可行走(检查路径锁定状态,检测路径是否有其他小车)
|
|
|
//可执行命令
|
if (!write(command)) {
|
News.error("四向穿梭车命令下发失败,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
return false;
|
}
|
|
News.info("四向穿梭车命令下发成功,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
//将标记置为false(防止重发)
|
shuttleProtocol.setPakMk(false);
|
|
//保存数据到数据库做流水
|
BasShuttleOptService shuttleOptService = SpringUtils.getBean(BasShuttleOptService.class);
|
if (shuttleOptService != null) {
|
BasShuttleOpt opt = new BasShuttleOpt(
|
assignCommand.getTaskNo().intValue(),
|
assignCommand.getShuttleNo().intValue(),
|
new Date(),
|
ShuttleTaskModeType.get(assignCommand.getTaskMode()).desc,
|
assignCommand.getSourceLocNo(),
|
assignCommand.getLocNo(),
|
null,
|
null,
|
null,
|
JSON.toJSONString(command),
|
null
|
);
|
shuttleOptService.insert(opt);
|
}
|
|
//判断数据是否执行完成
|
if (commandStep < commands.size() - 1) {
|
//更新redis数据
|
//步序增加
|
commandStep++;
|
redisCommand.setCommandStep(commandStep);
|
//任务数据保存到redis
|
redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand));
|
}else {
|
//已执行完成
|
|
// if (redisCommand.getLiftSecurityMk()) {
|
// //曾锁定过提升机,需要进行解锁
|
// if (liftProtocol != null) {
|
// liftProtocol.setSecurityMk(false);
|
// }
|
// }
|
|
// String locNo = shuttleProtocol.getLocNo() == null ? shuttleProtocol.getSourceLocNo() : shuttleProtocol.getLocNo();
|
// if (locNo != null) {
|
// //解除锁定的库位路径
|
// NavigateMapData navigateMapData = new NavigateMapData(Utils.getLev(locNo));
|
// navigateMapData.writeNavigateNodeToRedisMap(redisCommand.getAssignCommand().getNodes(), false);
|
// }
|
|
//删除redis
|
redisUtil.del("shuttle_wrk_no_" + redisCommand.getWrkNo());
|
|
if (!assignCommand.getCharge()) {
|
//对主线程抛出等待确认状态waiting
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING);
|
}else {
|
shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.CHARGING_WAITING);
|
}
|
News.info("四向穿梭车任务执行下发完成等待执行结束,穿梭车号={},任务数据={}", shuttleProtocol.getShuttleNo(), JSON.toJSON(command));
|
}
|
|
return true;
|
}
|
|
//检测小车是否要进提升机,如需要进提升机则调度提升机
|
private boolean checkLiftStation(Short wrkNo) {
|
//读取redis数据
|
if (wrkNo == null) {
|
return false;
|
}
|
|
Object o = redisUtil.get("shuttle_wrk_no_" + wrkNo);
|
if (o == null) {
|
return false;
|
}
|
|
//拿到提升机线程
|
LiftThread liftThread = (LiftThread) SlaveConnection.get(SlaveType.Lift, 1);
|
if (liftThread == null) {
|
return false;
|
}
|
LiftProtocol liftProtocol = liftThread.getLiftProtocol();
|
if (liftProtocol == null) {
|
return false;
|
}
|
|
ShuttleRedisCommand redisCommand = JSON.parseObject(o.toString(), ShuttleRedisCommand.class);
|
//当前步序
|
int commandStep = redisCommand.getCommandStep();
|
|
//检测是否存在提升机口的指令
|
List<NyShuttleHttpCommand> commands = redisCommand.getAssignCommand().getCommands();
|
if (commands.size() == 0) {
|
return false;
|
}
|
|
if (!commands.get(commandStep).getMsgType().equals("move")) {
|
return true;//不是行走命令,直接放行
|
}
|
|
|
return false;//默认不放行
|
}
|
|
}
|