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 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 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 commands = redisCommand.getAssignCommand().getCommands(); if (commands.size() == 0) { return false; } if (!commands.get(commandStep).getMsgType().equals("move")) { return true;//不是行走命令,直接放行 } return false;//默认不放行 } }