package com.zy.core.thread.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.core.common.DateUtils; import com.core.common.SpringUtils; import com.core.exception.CoolException; import com.fasterxml.jackson.databind.ObjectMapper; import com.zy.asrs.entity.BasShuttle; import com.zy.asrs.entity.DeviceDataLog; import com.zy.asrs.entity.LocMast; import com.zy.asrs.service.BasShuttleService; import com.zy.asrs.service.DeviceDataLogService; import com.zy.asrs.service.LocMastService; import com.zy.asrs.utils.Utils; import com.zy.common.ExecuteSupport; import com.zy.common.model.MapNode; import com.zy.common.model.NavigateNode; import com.zy.common.model.enums.NavigationMapType; import com.zy.common.utils.NavigateMapData; import com.zy.common.utils.NavigatePositionConvert; import com.zy.common.utils.RedisUtil; import com.zy.core.News; import com.zy.core.action.ShuttleAction; import com.zy.core.cache.OutputQueue; import com.zy.core.enums.*; import com.zy.core.model.CommandResponse; import com.zy.core.model.ShuttleSlave; import com.zy.core.model.command.NyShuttleHttpCommand; import com.zy.core.model.command.ShuttleCommand; import com.zy.core.model.command.ShuttleRedisCommand; import com.zy.core.model.param.ShuttleMoveLocParam; import com.zy.core.model.protocol.ShuttleProtocol; import com.zy.core.thread.ShuttleThread; import com.zy.system.entity.Config; import com.zy.system.service.ConfigService; import lombok.Data; import lombok.extern.slf4j.Slf4j; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import java.text.MessageFormat; import java.util.*; @Slf4j @SuppressWarnings("all") public class NyShuttleThread implements ShuttleThread { private ShuttleSlave slave; private RedisUtil redisUtil; private ShuttleProtocol shuttleProtocol; private Socket socket; private static final boolean DEBUG = false;//调试模式 private List socketReadResults = new ArrayList<>(); private List socketResults = new ArrayList<>(); //原始设备数据 private Object originDeviceData; public NyShuttleThread(ShuttleSlave slave, RedisUtil redisUtil) { this.slave = slave; this.redisUtil = redisUtil; } @Override public void run() { News.info("{}号四向车线程启动", slave.getId()); this.connect(); //监听消息并存储 Thread innerThread = new Thread(() -> { while (true) { try { listenSocketMessage(); listenInit();//监听初始化事件 } catch (Exception e) { e.printStackTrace(); } } }); innerThread.start(); //设备读取 Thread readThread = new Thread(() -> { while (true) { try { read(); Thread.sleep(50); } catch (Exception e) { log.error("ShuttleThread Fail", e); } } }); readThread.start(); //设备执行 Thread executeThread = new Thread(() -> { while (true) { try { ShuttleAction shuttleAction = SpringUtils.getBean(ShuttleAction.class); if (shuttleAction == null) { continue; } Object object = redisUtil.get(RedisKeyType.SHUTTLE_FLAG.key + slave.getId()); if (object == null) { continue; } Integer taskNo = Integer.valueOf(String.valueOf(object)); if (taskNo != 0) { //存在任务需要执行 boolean result = shuttleAction.executeWork(slave.getId(), taskNo); } // //小车空闲且有跑库程序 // shuttleAction.moveLoc(slave.getId()); //演示模式 shuttleAction.demo(slave.getId()); Thread.sleep(200); } catch (Exception e) { e.printStackTrace(); } } }); executeThread.start(); //其他任务 Thread otherThread = new Thread(() -> { while (true) { try { saveLog();//保存数据 } catch (Exception e) { e.printStackTrace(); } } }); otherThread.start(); } private void saveLog() { if (shuttleProtocol == null) { return; } if (System.currentTimeMillis() - shuttleProtocol.getDeviceDataLog() > 1000 * 5) { if (this.originDeviceData != null) { //采集时间超过5s,保存一次数据记录 //保存数据记录 DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class); if (deviceDataLogService == null) { return; } DeviceDataLog deviceDataLog = new DeviceDataLog(); deviceDataLog.setOriginData(JSON.toJSONString(this.originDeviceData)); deviceDataLog.setWcsData(JSON.toJSONString(shuttleProtocol)); deviceDataLog.setType(String.valueOf(SlaveType.Shuttle)); deviceDataLog.setDeviceNo(slave.getId()); deviceDataLog.setCreateTime(new Date()); deviceDataLogService.insert(deviceDataLog); //更新采集时间 shuttleProtocol.setDeviceDataLog(System.currentTimeMillis()); OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId())); } } } private void listenSocketMessage() { try { if (this.socket == null) { return; } // 获取输入流 BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); // 读取服务器的响应 StringBuffer sb = new StringBuffer(); char[] chars = new char[2048];//缓冲区 while (true) { reader.read(chars); String trim = new String(chars); sb.append(trim); if (trim.lastIndexOf("\r\n") != -1) { break; } } JSONObject result = JSON.parseObject(sb.toString());//得到响应结果集 String msgType = result.getString("msgType"); if ("responseMsg".equals(msgType)) { JSONObject response = result.getJSONObject("response"); JSONObject body = response.getJSONObject("body"); if (body.containsKey("workingMode")) { //read socketReadResults.add(body); return; } } if (!socketResults.isEmpty() && socketResults.size() >= 20) { socketResults.remove(0);//清理头节点 } socketResults.add(result);//添加数据 } catch (Exception e) { // e.printStackTrace(); } } public JSONObject getRequestBody(String type, String taskId) { try { // 获取服务器响应 JSONObject result = null; if (type.equals("readState")) { type = "state"; } for (int i = 0; i < socketResults.size(); i++) { JSONObject socketResult = socketResults.get(i); if (!socketResult.get("msgType").equals("responseMsg")) {//不是响应内容 continue; } JSONObject resultResponse = JSON.parseObject(socketResult.get("response").toString()); JSONObject resultBody = JSON.parseObject(resultResponse.get("body").toString()); String responseType = resultBody.get("responseType").toString(); if (DEBUG) { result = socketResult; break; } if (!responseType.equals(type)) { continue;//响应类型与请求类型不一致,不在调试模式下 } if (taskId != null) { String responseTaskId = resultBody.get("taskId").toString(); if (!responseTaskId.equals(taskId)) { continue;//响应ID与请求ID不一致,不在调试模式下 } } result = socketResult; break; } if (result == null) { return null;//无响应结果 } return filterBodyData(result);//返回Body结果集 } catch (Exception e) { return null; } } private void read() { try { if (this.socket == null || this.socket.isClosed()) { //链接断开重新链接 this.connect(); } readStatus(); } catch (Exception e) { e.printStackTrace(); OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】读取四向穿梭车状态信息失败 ===>> [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 ShuttleProtocol(); shuttleProtocol.setShuttleNo(slave.getId()); shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE); InnerSuhttleExtend extend = new InnerSuhttleExtend(); shuttleProtocol.setExtend(extend); } //----------读取四向穿梭车状态----------- NyShuttleHttpCommand readStatusCommand = getReadStatusCommand(slave.getId()); requestCommandAsync(readStatusCommand);//请求状态 if (this.socketReadResults.isEmpty()) { if (System.currentTimeMillis() - shuttleProtocol.getLastOnlineTime() > 1000 * 60) { //最后一次上线时间超过60s,认定离线 shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE); } return; } JSONObject data = this.socketReadResults.get(0); this.socketReadResults.remove(0); if (data == null) { if (System.currentTimeMillis() - shuttleProtocol.getLastOnlineTime() > 1000 * 60) { //最后一次上线时间超过60s,认定离线 shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.OFFLINE); } OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort())); }else { //----------读取四向穿梭车状态----------- //小车设备状态 shuttleProtocol.setDeviceStatus(data.getInteger("free")); //小车模式 shuttleProtocol.setMode(data.getInteger("workingMode")); //当前二维码 shuttleProtocol.setCurrentCode(data.getString("point")); //电池电量 shuttleProtocol.setBatteryPower(data.getString("powerPercent")); //电池电压 shuttleProtocol.setBatteryVoltage(data.getInteger("voltage")); //故障 shuttleProtocol.setErrorCode(data.getJSONArray("errCode").getString(0)); //是否顶升 shuttleProtocol.setHasLift(data.getInteger("liftPosition") == 2 ? true : false); //是否有托盘 shuttleProtocol.setHasPallet(data.getInteger("loadState") == 1 ? true : false); //行驶方向 shuttleProtocol.setRunDirection(data.getString("runDir") == null ? "none" : data.getString("runDir")); //是否为充电状态 shuttleProtocol.setHasCharge(data.getInteger("chargState") == 1 ? true : false); //运行速度 shuttleProtocol.setSpeed(data.getInteger("speed")); //*********读取扩展字段********** InnerSuhttleExtend extend = (InnerSuhttleExtend) shuttleProtocol.getExtend(); //管制状态 extend.setSuspendState(data.getInteger("suspendState")); //最高电芯电压(mV) extend.setMaxCellVoltage(data.getInteger("maxCellVoltage")); //最低电芯电压(mV) extend.setMinCellVoltage(data.getInteger("minCellVoltage")); //电池电压 extend.setVoltage(data.getInteger("voltage")); //充放电循环次数 extend.setChargeCycleTimes(data.getInteger("chargeCycleTimes")); //剩余电量 extend.setSurplusQuantity(data.getInteger("surplusQuantity")); //总电量 extend.setCountQuantity(data.getInteger("countQuantity")); shuttleProtocol.setExtend(extend);//扩展字段 //最近一次在线时间 shuttleProtocol.setLastOnlineTime(System.currentTimeMillis()); ///读取四向穿梭车状态-end //小车处于运行中,将标记置为true if (shuttleProtocol.getDeviceStatus() == 0) { shuttleProtocol.setPakMk(true); } if (shuttleProtocol.getProtocolStatusType() == null && shuttleProtocol.getDeviceStatus().intValue() == 0) { //小车空闲状态、小车任务状态为未知,认定曾离线过,需要复位成空闲 shuttleProtocol.setProtocolStatusType(ShuttleProtocolStatusType.IDLE); } if (shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.OFFLINE) && shuttleProtocol.getDeviceStatus().intValue() == 0) { shuttleProtocol.setProtocolStatusType(ShuttleProtocolStatusType.IDLE); } this.originDeviceData = data; OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), slave.getId())); } } catch (Exception e) { e.printStackTrace(); OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort())); try { this.socket.close(); this.socket = null; Thread.sleep(1000); this.connect(); } catch (IOException | InterruptedException exception) { e.printStackTrace(); } } } /** * 监听小车复位初始化信号 */ public void listenInit() { try { // 获取服务器响应 JSONObject result = null; int removeIdx = -1; for (int i = 0; i < socketResults.size(); i++) { JSONObject socketResult = socketResults.get(i); if (socketResult == null) { continue; } if (!socketResult.get("msgType").equals("requestMsg")) {//不是请求内容 continue; } JSONObject resultResponse = JSON.parseObject(socketResult.get("request").toString()); JSONObject resultHeader = JSON.parseObject(resultResponse.get("header").toString()); JSONObject resultBody = JSON.parseObject(resultResponse.get("body").toString()); String requestType = resultBody.getString("requestType"); Integer requestId = resultHeader.getInteger("requestId"); if (requestType.equals("init")) { Integer code = resultBody.getInteger("code"); //小车复位请求 ShuttleCommand initCommand = getInitCommand(requestId, code); //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(initCommand.getBody(), NyShuttleHttpCommand.class); JSONObject requestResult = requestCommand(httpCommand); removeIdx = i;//此数据已经处理,从结果集中剔除 log.info(MessageFormat.format("【{0}】四向车复位上报 ===>> [code:{1}] [ip:{2}] [port:{3}]", slave.getId(), code, slave.getIp(), slave.getPort())); OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向车复位上报 ===>> [code:{1}] [ip:{2}] [port:{3}]", slave.getId(), code, slave.getIp(), slave.getPort())); break; } } if (removeIdx != -1) { socketResults.remove(removeIdx); } } catch (Exception e) { e.printStackTrace(); } } @Override public ShuttleProtocol getStatus() { return getStatus(true); } @Override public ShuttleProtocol getStatus(boolean clone) { if (this.shuttleProtocol == null) { return null; } return clone ? this.shuttleProtocol.clone() : this.shuttleProtocol; } @Override public CommandResponse movePath(List nodes, Integer taskNo) { CommandResponse response = new CommandResponse(true); return response; } @Override public CommandResponse move(ShuttleCommand command) { CommandResponse response = new CommandResponse(false); try { //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class); Map body = httpCommand.getRequest().getBody(); Object pathObj = body.get("path"); int taskId = Integer.parseInt(body.get("taskId").toString()); List path = JSON.parseArray(JSON.toJSONString(pathObj), JSONObject.class); ArrayList commandList = new ArrayList<>(); while (!path.isEmpty()) { ArrayList> list = new ArrayList<>(); if (path.size() > 10) { List subList = path.subList(0, 10); list.addAll(subList); List tmp = new ArrayList<>(); for (int i = 10; i < path.size(); i++) { tmp.add(path.get(i)); } path = tmp; }else { list.addAll(path); path.clear(); } NyShuttleHttpCommand httpCommandCopy = JSON.parseObject(JSON.toJSONString(httpCommand), NyShuttleHttpCommand.class); JSONObject bodyCopy = JSON.parseObject(JSON.toJSONString(body)); NyShuttleHttpCommand.NyRequest request = httpCommandCopy.getRequest(); bodyCopy.put("path", list); bodyCopy.put("taskId", taskId++); request.setBody(bodyCopy); httpCommandCopy.setRequest(request); commandList.add(httpCommandCopy);//add copy } for (NyShuttleHttpCommand requestCommand : commandList) { while (true) { JSONObject result = requestCommand(requestCommand); if (result == null) { // return response;//请求失败 continue;//请求失败尝试重新请求 } this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 response.setMessage(JSON.toJSONString(result)); response.setResult(true); break; } } return response; } catch (Exception e) { e.printStackTrace(); response.setMessage(e.getMessage()); return response; } } @Override public CommandResponse lift(ShuttleCommand command) { CommandResponse response = new CommandResponse(false); try { //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class); JSONObject result = requestCommand(httpCommand); if (result == null) { return response;//请求失败 } this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 response.setMessage(JSON.toJSONString(result)); response.setResult(true); return response; } catch (Exception e) { e.printStackTrace(); return response; } } @Override public CommandResponse charge(ShuttleCommand command) { CommandResponse response = new CommandResponse(false); try { //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class); JSONObject result = requestCommand(httpCommand); if (result == null) { return response;//请求失败 } this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 response.setMessage(JSON.toJSONString(result)); response.setResult(true); return response; } catch (Exception e) { e.printStackTrace(); return response; } } @Override public CommandResponse reset(ShuttleCommand command) { setSyncTaskNo(0); setProtocolStatus(ShuttleProtocolStatusType.IDLE); enableMoveLoc(null, false); return new CommandResponse(true, JSON.toJSONString(command)); } @Override public CommandResponse updateLocation(ShuttleCommand command) { CommandResponse response = new CommandResponse(false); try { //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class); JSONObject result = requestCommand(httpCommand); if (result == null) { return response;//请求失败 } this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 response.setMessage(JSON.toJSONString(result)); response.setResult(true); return response; } catch (Exception e) { e.printStackTrace(); return response; } } @Override public boolean isIdle() { return this.isIdle(null); } @Override public boolean isIdle(ExecuteSupport support) { if (null != support) { Boolean judgement = support.judgement(); if (judgement != null && !judgement) { return true; } } if (this.shuttleProtocol.getDeviceStatus() == null || this.shuttleProtocol.getPakMk() == null || this.shuttleProtocol.getErrorCode() == null || this.shuttleProtocol.getProtocolStatus() == null || this.shuttleProtocol.getMode() == null || this.shuttleProtocol.getExtend() == null ) { return false; } InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend(); boolean res = this.shuttleProtocol.getDeviceStatus() == 1 && this.shuttleProtocol.getMode() == 1 && this.shuttleProtocol.getPakMk() && this.shuttleProtocol.getErrorCode().equals("0") && this.shuttleProtocol.getTaskNo() == 0 && (this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.IDLE.id || this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.WAITING.id || this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.CHARGING_WAITING.id) && extend.getSuspendState() == 0; return res; } @Override public boolean isDeviceIdle() { return isDeviceIdle(null); } @Override public boolean isDeviceIdle(ExecuteSupport support) { if (null != support) { Boolean judgement = support.judgement(); if (judgement != null && !judgement) { return true; } } if (this.shuttleProtocol.getDeviceStatus() == null || this.shuttleProtocol.getPakMk() == null || this.shuttleProtocol.getErrorCode() == null || this.shuttleProtocol.getMode() == null || this.shuttleProtocol.getExtend() == null ) { return false; } InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend(); boolean res = this.shuttleProtocol.getDeviceStatus() == 1 && this.shuttleProtocol.getMode() == 1 && this.shuttleProtocol.getPakMk() && this.shuttleProtocol.getErrorCode().equals("0") && extend.getSuspendState() == 0 ; return res; } @Override public boolean isRequireCharge() { if (this.shuttleProtocol.getDeviceStatus() == null || this.shuttleProtocol.getPakMk() == null || this.shuttleProtocol.getErrorCode() == null || this.shuttleProtocol.getProtocolStatus() == null || this.shuttleProtocol.getMode() == null || this.shuttleProtocol.getExtend() == null ) { return false; } InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend(); boolean res = this.shuttleProtocol.getDeviceStatus() == 1 && this.shuttleProtocol.getMode() == 1 && this.shuttleProtocol.getPakMk() && this.shuttleProtocol.getErrorCode().equals("0") && this.shuttleProtocol.getProtocolStatus() == ShuttleProtocolStatusType.IDLE.id && extend.getSuspendState() == 0 ; if (!res) { return res; } else { // 电量小于阈值需要进行充电 try { BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class); if (shuttleService == null) { return false; } BasShuttle basShuttle = shuttleService.selectOne(new EntityWrapper().eq("shuttle_no", slave.getId())); if (basShuttle == null) { return false; } Integer chargeLine = basShuttle.getChargeLine(); if (chargeLine == null) { return false; } return Integer.valueOf(this.shuttleProtocol.getBatteryPower()) < chargeLine; } catch (Exception e) { return false; } } } @Override public boolean isCharging() { if (this.shuttleProtocol.getDeviceStatus() == null || this.shuttleProtocol.getHasCharge() == null) { return false; } if (this.shuttleProtocol.getDeviceStatus() == 0 && this.shuttleProtocol.getHasCharge()) { //运行中 && 充电中 return true; } return false; } @Override public boolean isChargingCompleted() { Integer maxPower = 100; ConfigService configService = SpringUtils.getBean(ConfigService.class); if (configService != null) { Config chargeMaxValue = configService.selectOne(new EntityWrapper() .eq("code", "chargeMaxValue") .eq("status", 1)); if (chargeMaxValue != null) { maxPower = Integer.parseInt(chargeMaxValue.getValue()); } } if (this.shuttleProtocol.getHasCharge() == null) { return false; } if (this.shuttleProtocol.getBatteryPower() == null) { return false; } if (!this.shuttleProtocol.getHasCharge()) { return false; } if (Integer.valueOf(this.shuttleProtocol.getBatteryPower()) >= maxPower) { return true; } return false; } @Override public boolean isFault() { if (this.shuttleProtocol.getErrorCode() == null || this.shuttleProtocol.getMode() == null || this.shuttleProtocol.getExtend() == null ) { return false; } if (this.shuttleProtocol.getMode() == 0) { return true; } if (!this.shuttleProtocol.getErrorCode().equals("0")) { return true; } InnerSuhttleExtend extend = (InnerSuhttleExtend) this.shuttleProtocol.getExtend(); if (extend.getSuspendState() == 1) { return true; } return false; } @Override public List getMoveAdvancePath() { ObjectMapper objectMapper = SpringUtils.getBean(ObjectMapper.class); NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class); ArrayList path = new ArrayList<>(); if (shuttleProtocol.getTaskNo() != 0) { //存在任务,获取指令 Object object = redisUtil.get(RedisKeyType.SHUTTLE_WORK_FLAG.key + shuttleProtocol.getTaskNo()); if (object != null) { ShuttleRedisCommand redisCommand = null; try { redisCommand = objectMapper.readValue(String.valueOf(object), ShuttleRedisCommand.class); } catch (IOException e) { return path; } List nodes = redisCommand.getAssignCommand().getNodes();//穿梭车预计路径 if (nodes == null) { return path; } if (!nodes.isEmpty()) { path.addAll(nodes); } NavigateNode navigateNode = path.get(0); int lev = navigateNode.getZ(); //将路径锁与小车路径进行匹配 ArrayList tmp = new ArrayList<>(); //检测路径是否被锁定 int[][] map = navigateMapData.getDataFromRedis(lev, NavigationMapType.DFX.id, null, null); for (NavigateNode node : path) { if(map[node.getX()][node.getY()] == -999) { tmp.add(node); } } path = tmp; } } return path; } @Override public int generateDeviceTaskNo(int taskNo, ShuttleTaskNoType type) { return taskNo; } @Override public synchronized boolean setProtocolStatus(ShuttleProtocolStatusType status) { this.shuttleProtocol.setProtocolStatus(status); return true; } @Override public synchronized boolean setTaskNo(Integer taskNo) { this.shuttleProtocol.setTaskNo(taskNo); return true; } @Override public synchronized boolean setSyncTaskNo(Integer taskNo) { this.shuttleProtocol.setSyncTaskNo(taskNo); return true; } @Override public synchronized boolean setPakMk(boolean pakMk) { this.shuttleProtocol.setPakMk(pakMk); return true; } @Override public boolean enableMoveLoc(ShuttleMoveLocParam param, boolean enable) { if (enable) { shuttleProtocol.setMoveLoc(true);//开启跑库 shuttleProtocol.setMoveType(param.getMoveType()); shuttleProtocol.setXStart(param.getStartX()); shuttleProtocol.setXTarget(param.getTargetX()); shuttleProtocol.setXCurrent(param.getStartX()); shuttleProtocol.setYStart(param.getStartY()); shuttleProtocol.setYTarget(param.getTargetY()); shuttleProtocol.setYCurrent(param.getStartY()); }else { shuttleProtocol.setMoveLoc(false); shuttleProtocol.setMoveType(0); shuttleProtocol.setXStart(0); shuttleProtocol.setXTarget(0); shuttleProtocol.setXCurrent(0); shuttleProtocol.setYStart(0); shuttleProtocol.setYTarget(0); shuttleProtocol.setYCurrent(0); } return true; } @Override public boolean requestWaiting() { if (this.shuttleProtocol.getProtocolStatusType().equals(ShuttleProtocolStatusType.IDLE)) { this.shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.WAITING); return true; } return false; } @Override public boolean enableDemo(boolean enable) { shuttleProtocol.setDemo(enable); return true; } @Override public boolean offerSystemMsg(String format, Object... arguments) { String msg = News.replace(format, arguments); shuttleProtocol.setSystemMsg(msg); return true; } @Override public ShuttleCommand getMoveCommand(Integer taskNo, String startCodeNum, String distCodeNum, Integer allDistance, Integer runDirection, Integer runSpeed, List nodes) { NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class); NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); ArrayList> path = new ArrayList<>(); Integer taskId = getTaskId(); HashMap body = new HashMap<>(); body.put("requestType", "move");//移动命令 body.put("taskId", taskId);//TaskID需要随机 // body.put("start", navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(startCodeNum, device.getHostId())));//起点 // body.put("target", navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(distCodeNum, device.getHostId())));//终点 body.put("path", path); request.setBody(body); NavigateNode startNode = nodes.get(0); for (NavigateNode node : nodes) { HashMap data = new HashMap<>(); String codeNum = NavigatePositionConvert.xyToPosition(node.getX(), node.getY(), node.getZ()); Map nyNode = navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(codeNum)); int xp = Integer.parseInt(String.valueOf(nyNode.get("y"))); int yp = Integer.parseInt(String.valueOf(nyNode.get("x"))); int z = Integer.parseInt(String.valueOf(nyNode.get("z"))); List> mapData = navigateMapData.getJsonData(startNode.getZ(), NavigationMapType.NONE.id, null, null); List mapNodes = mapData.get(node.getX()); MapNode mapNode = mapNodes.get(node.getY()); data.put("xp", xp); data.put("yp", yp); data.put("z", z); data.put("x", mapNode.getXBase()); data.put("y", mapNode.getYBase()); path.add(data); } httpStandard.setRequest(request); LocMastService locMastService = SpringUtils.getBean(LocMastService.class); LocMast locMast = locMastService.selectOne(new EntityWrapper() .eq("qr_code_value", distCodeNum)); if (locMast == null) { throw new CoolException("库位信息不存在"); } ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(slave.getId()); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(ShuttleCommandModeType.MOVE.id); command.setTargetLocNo(locMast.getLocNo()); command.setTaskNo(taskId); return command; } @Override public ShuttleCommand getLiftCommand(Integer taskNo, Boolean lift) { NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); Integer taskId = getTaskId();//TaskID需要随机 HashMap body = new HashMap<>(); body.put("requestType", lift ? "liftUp" : "liftDown");//顶升或下降命令 body.put("taskId", taskId); request.setBody(body); httpStandard.setRequest(request); ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(slave.getId()); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(lift ? ShuttleCommandModeType.PALLET_LIFT.id : ShuttleCommandModeType.PALLET_DOWN.id); command.setTaskNo(taskId); return command; } @Override public ShuttleCommand getChargeCommand(Integer taskNo, Boolean charge) { NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); Integer taskId = getTaskId();//TaskID需要随机 HashMap body = new HashMap<>(); body.put("requestType", charge ? "charge" : "stopCharge");//充电或停止充电 body.put("taskId", taskId); request.setBody(body); httpStandard.setRequest(request); ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(slave.getId()); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(charge ? ShuttleCommandModeType.CHARGE_OPEN.id : ShuttleCommandModeType.CHARGE_CLOSE.id); command.setTaskNo(taskId); return command; } @Override public ShuttleCommand getUpdateLocationCommand(Integer taskNo, String locNo) { NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); HashMap body = new HashMap<>(); body.put("requestType", "updateFloor");//更新层Z body.put("z", Utils.getLev(locNo));//坐标Z request.setBody(body); httpStandard.setRequest(request); ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(slave.getId()); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(ShuttleCommandModeType.UPDATE_LOCATION.id); command.setTaskNo(taskNo); return command; } //获取小车复位响应命令 public ShuttleCommand getInitCommand(Integer taskNo, Integer code) { LocMastService locMastService = SpringUtils.getBean(LocMastService.class); NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class); NyShuttleHttpCommand httpStandard = getHttpStandard(slave.getId(), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); //code -> {Integer@13781} 1101101 int lev = code % 100; int bay = code / 100 % 1000; int row = code / 100000; HashMap map = new HashMap<>(); map.put("x", row); map.put("y", bay); map.put("z", lev); String mapStr = JSON.toJSONString(map); LocMast locMast = locMastService.selectOne(new EntityWrapper() .eq("qr_code_value", mapStr)); if (locMast == null) { throw new CoolException("地址码不存在"); } List> mapData = navigateMapData.getJsonData(lev, NavigationMapType.NONE.id, null, null); List mapNodes = mapData.get(locMast.getRow1()); MapNode mapNode = mapNodes.get(locMast.getBay1()); HashMap location = new HashMap<>(); location.put("xp", row); location.put("yp", bay); location.put("z", lev); location.put("x", mapNode.getXBase()); location.put("y", mapNode.getYBase()); HashMap body = new HashMap<>(); body.put("responseType", "init");//复位 body.put("location", location);//初始化坐标 body.put("devicePoints", new ArrayList<>());//提升机点位 body.put("specialPoints", new ArrayList<>());//特殊条码坐标 request.setBody(body); httpStandard.setRequest(request); ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(slave.getId()); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(ShuttleCommandModeType.RESET.id); command.setTaskNo(taskNo); return command; } @Override public boolean connect() { try { Socket socket = new Socket(slave.getIp(), slave.getPort()); socket.setSoTimeout(10000); socket.setKeepAlive(true); this.socket = socket; log.info(MessageFormat.format("【{0}】四向穿梭车Socket链接成功 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort())); } catch (IOException e) { OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket链接失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), slave.getId(), slave.getIp(), slave.getPort())); return false; } return true; } @Override public void close() { } //获取HTTP请求标准结构体 private NyShuttleHttpCommand getHttpStandard(Integer shuttleNo, Integer taskNo) { NyShuttleHttpCommand httpStandard = new NyShuttleHttpCommand(); httpStandard.setMsgType("requestMsg");//请求消息 httpStandard.setRobotId(shuttleNo);//车辆编号 httpStandard.setTaskNo(taskNo);//工作号 //设置请求消息 NyShuttleHttpCommand.NyRequest request = new NyShuttleHttpCommand.NyRequest(); NyShuttleHttpCommand.NyRequest.NyHeader header = new NyShuttleHttpCommand.NyRequest.NyHeader(); header.setVersion("1.0");//版本号 header.setRequestId(getRequestId());//消息编号 //设置请求头 request.setHeader(header); httpStandard.setRequest(request); return httpStandard; } //获取请求编号 private Integer getRequestId() { Random random = new Random(); return random.nextInt(9999999); } //获取TaskId private static Integer getTaskId() { Random random = new Random(); return random.nextInt(999999); } //获取读FAS状态信息命令 private NyShuttleHttpCommand getReadStatusCommand(Integer shuttleNo) { NyShuttleHttpCommand httpStandard = getHttpStandard(shuttleNo, 9999); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); HashMap body = new HashMap<>(); body.put("requestType", "readState");//读FAS状态信息 request.setBody(body); httpStandard.setRequest(request); return httpStandard; } //发出请求 private JSONObject requestCommand(NyShuttleHttpCommand httpCommand) throws IOException { if (this.socket == null) { return null; } //压缩数据包 JSONObject data = JSON.parseObject(JSON.toJSONString(httpCommand)); data.remove("nodes"); // 获取输出流 OutputStreamWriter writer = new OutputStreamWriter(this.socket.getOutputStream()); writer.write(JSON.toJSONString(data) + "\r\n"); writer.flush(); // System.out.println("Sent message to server: " + JSON.toJSONString(httpCommand)); String requestType = null; String taskId = null; try { requestType = httpCommand.getRequest().getBody().get("requestType").toString(); taskId = httpCommand.getRequest().getBody().get("taskId").toString(); } catch (Exception e) { // return null; //taskId可能取空,不报错,正常情况 } // 获取服务器响应 // 尝试10次 JSONObject result = null; for (int i = 0; i < 10; i++) { result = getRequestBody(requestType, taskId); if (result == null) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } }else { break; } } return result;//返回Body结果集 } private void requestCommandAsync(NyShuttleHttpCommand httpCommand) throws IOException { if (this.socket == null) { return; } //压缩数据包 JSONObject data = JSON.parseObject(JSON.toJSONString(httpCommand)); data.remove("nodes"); // 获取输出流 OutputStreamWriter writer = new OutputStreamWriter(this.socket.getOutputStream()); writer.write(JSON.toJSONString(data) + "\r\n"); writer.flush(); // System.out.println("Sent message to server: " + JSON.toJSONString(httpCommand)); } private JSONObject filterBodyData(JSONObject data) { Object response = data.get("response"); if (response == null) { return null; } JSONObject result = JSON.parseObject(response.toString()); Object body = result.get("body"); if (body == null) { return null; } JSONObject jsonBody = JSON.parseObject(body.toString()); return jsonBody; } //地图节点转换牛眼节点 private static Map navigateNodeToNyPointNode(NavigateNode node) { int[] NyPosition = WCSXyzToNyXyz(node.getX(), node.getY(), node.getZ());//WCS系统坐标转牛眼坐标 HashMap point = new HashMap<>(); point.put("x", NyPosition[0]); point.put("y", NyPosition[1]); point.put("z", NyPosition[2]); return point; } //WCS系统坐标转牛眼坐标 private static int[] WCSXyzToNyXyz(int x, int y, int z) { // //WCS系统Y轴 => 牛眼X轴转换公式 // int x1 = Math.abs(y - 61) + 11; // //WCS系统X轴 => 牛眼Y轴转换公式 // int y1 = x + 10; // int x1 = x + 10; // int y1 = y + 10; LocMastService locMastService = SpringUtils.getBean(LocMastService.class); LocMast locMast = locMastService.selectOne(new EntityWrapper() .eq("row1", x) .eq("bay1", y) .eq("lev1", z) .eq("status", 1)); if (locMast == null) { return null; } String qrCodeValue = locMast.getQrCodeValue(); JSONObject data = JSON.parseObject(qrCodeValue); return new int[]{data.getInteger("y"), data.getInteger("x"), z}; } @Data private class InnerSuhttleExtend { /** * 管制状态不在管制下/被管制中 * 0/1 */ private Integer suspendState; /** * 最高电芯电压(mV) */ private Integer maxCellVoltage; /** * 最低电芯电压(mV),低于2900mv需要立即充电 */ private Integer minCellVoltage; /** * 电池电压(mV) */ private Integer voltage; /** * 充放电循环次数 */ private Integer chargeCycleTimes; /** * 剩余电量/10(A) */ private Integer surplusQuantity; /** * 总电量/10(A) */ private Integer countQuantity; } }