package com.zy.asrs.wcs.rcs.thread.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.zy.asrs.framework.common.DateUtils; import com.zy.asrs.framework.common.SpringUtils; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wcs.common.ExecuteSupport; import com.zy.asrs.wcs.core.domain.param.ShuttleMoveLocParam; import com.zy.asrs.wcs.core.entity.BasShuttle; import com.zy.asrs.wcs.core.entity.Loc; import com.zy.asrs.wcs.core.model.MapNode; import com.zy.asrs.wcs.core.model.NavigateNode; import com.zy.asrs.wcs.core.model.command.ShuttleCommand; import com.zy.asrs.wcs.core.model.command.ShuttleRedisCommand; import com.zy.asrs.wcs.core.model.enums.MotionCtgType; import com.zy.asrs.wcs.core.model.enums.NavigationMapType; import com.zy.asrs.wcs.core.model.enums.ShuttleCommandModeType; import com.zy.asrs.wcs.core.service.BasShuttleService; import com.zy.asrs.wcs.core.service.LocService; import com.zy.asrs.wcs.core.utils.NavigateMapData; import com.zy.asrs.wcs.core.utils.NavigatePositionConvert; import com.zy.asrs.wcs.core.utils.RedisUtil; import com.zy.asrs.wcs.core.utils.Utils; import com.zy.asrs.wcs.rcs.News; import com.zy.asrs.wcs.rcs.cache.OutputQueue; import com.zy.asrs.wcs.rcs.constant.DeviceRedisConstant; import com.zy.asrs.wcs.rcs.entity.Device; import com.zy.asrs.wcs.rcs.entity.DeviceDataLog; import com.zy.asrs.wcs.rcs.model.command.NyShuttleHttpCommand; import com.zy.asrs.wcs.rcs.model.enums.ShuttleProtocolStatusType; import com.zy.asrs.wcs.rcs.model.enums.SlaveType; import com.zy.asrs.wcs.rcs.model.protocol.ShuttleProtocol; import com.zy.asrs.wcs.rcs.service.DeviceDataLogService; import com.zy.asrs.wcs.rcs.thread.ShuttleThread; import com.zy.asrs.wcs.system.entity.Dict; import com.zy.asrs.wcs.system.service.DictService; 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 Device device; private RedisUtil redisUtil; private ShuttleProtocol shuttleProtocol; private Socket socket; private static final boolean DEBUG = false;//调试模式 private List socketResults = new ArrayList<>(); public NyShuttleThread(Device device, RedisUtil redisUtil) { this.device = device; this.redisUtil = redisUtil; } @Override public void run() { News.info("{}号四向车线程启动", device.getDeviceNo()); this.connect(); //监听消息并存储 Thread innerThread = new Thread(() -> { while (true) { listenSocketMessage(); } }); innerThread.start(); while (true) { try { read(); Thread.sleep(500); } catch (Exception e) { log.error("ShuttleThread Fail", e); } } } 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());//得到响应结果集 if (!socketResults.isEmpty() && socketResults.size() >= 5) { socketResults.remove(0);//清理头节点 } socketResults.add(result);//添加数据 } catch (Exception e) { // e.printStackTrace(); } } public JSONObject getRequestBody(String type) { 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;//响应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(); listenInit();//监听初始化事件 } catch (Exception e) { e.printStackTrace(); OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】读取四向穿梭车状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.getPort())); } } private void readStatus() { try { if (null == shuttleProtocol) { shuttleProtocol = new ShuttleProtocol(); shuttleProtocol.setShuttleNo(Integer.valueOf(device.getDeviceNo())); shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE); shuttleProtocol.setDevice(device); InnerSuhttleExtend extend = new InnerSuhttleExtend(); shuttleProtocol.setExtend(extend); } //----------读取四向穿梭车状态----------- NyShuttleHttpCommand readStatusCommand = getReadStatusCommand(Integer.parseInt(device.getDeviceNo())); JSONObject data = requestCommand(readStatusCommand); 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()), device.getId(), device.getIp(), device.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") == 1 ? true : false); //是否有托盘 shuttleProtocol.setHasPallet(data.getInteger("loadState") == 1 ? true : false); //行驶方向 shuttleProtocol.setRunDirection(data.getString("runDir") == null ? "none" : data.getString("direction")); //是否为充电状态 shuttleProtocol.setHasCharge(data.getInteger("chargState") == 1 ? true : false); //*********读取扩展字段********** InnerSuhttleExtend extend = (InnerSuhttleExtend) shuttleProtocol.getExtend(); //管制状态 extend.setSuspendState(data.getInteger("suspendState")); //当前速度 extend.setSpeed(data.getInteger("speed")); //剩余电量 extend.setSurplusQuantity(data.getInteger("surplusQuantity")); //总电量 extend.setCountQuantity(data.getInteger("countQuantity")); shuttleProtocol.setExtend(extend);//扩展字段 //最近一次在线时间 shuttleProtocol.setLastOnlineTime(System.currentTimeMillis()); ///读取四向穿梭车状态-end //小车处于运行中,将标记置为true if (shuttleProtocol.getDeviceStatus() == 1) { shuttleProtocol.setPakMk(true); } if (shuttleProtocol.getProtocolStatusType() == null && shuttleProtocol.getDeviceStatus().intValue() == 0) { //小车空闲状态、小车任务状态为未知,认定曾离线过,需要复位成空闲 shuttleProtocol.setProtocolStatusType(ShuttleProtocolStatusType.IDLE); } if (System.currentTimeMillis() - shuttleProtocol.getDeviceDataLog() > 1000 * 5) { //采集时间超过5s,保存一次数据记录 //保存数据记录 DeviceDataLogService deviceDataLogService = SpringUtils.getBean(DeviceDataLogService.class); DeviceDataLog deviceDataLog = new DeviceDataLog(); deviceDataLog.setOriginData(JSON.toJSONString(data)); deviceDataLog.setWcsData(JSON.toJSONString(shuttleProtocol)); deviceDataLog.setType(String.valueOf(SlaveType.Shuttle)); deviceDataLog.setDeviceNo(String.valueOf(shuttleProtocol.getShuttleNo())); deviceDataLog.setCreateTime(new Date()); deviceDataLog.setHostId(device.getHostId()); deviceDataLogService.save(deviceDataLog); //更新采集时间 shuttleProtocol.setDeviceDataLog(System.currentTimeMillis()); } //将四向穿梭车状态保存至数据库 BasShuttleService shuttleService = SpringUtils.getBean(BasShuttleService.class); BasShuttle basShuttle = shuttleService.getOne(new LambdaQueryWrapper() .eq(BasShuttle::getShuttleNo, device.getDeviceNo()) .eq(BasShuttle::getHostId, device.getHostId())); if (basShuttle == null) { basShuttle = new BasShuttle(); //四向穿梭车号 basShuttle.setShuttleNo(Integer.valueOf(device.getDeviceNo())); basShuttle.setStatus(1); basShuttle.setDeleted(0); basShuttle.setHostId(device.getHostId()); basShuttle.setDeviceId(device.getId().intValue()); shuttleService.save(basShuttle); } //任务号 basShuttle.setTaskNo(shuttleProtocol.getTaskNo().intValue()); //修改时间 basShuttle.setUpdateTime(new Date()); //设备状态 basShuttle.setProtocol(JSON.toJSONString(shuttleProtocol)); if (shuttleService.updateById(basShuttle)) { OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), device.getDeviceNo())); } } } catch (Exception e) { e.printStackTrace(); OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.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.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"); OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向车复位上报 ===>> [code:{1}] [ip:{2}] [port:{3}]", code, device.getId(), device.getIp(), device.getPort())); //小车复位请求 ShuttleCommand initCommand = getInitCommand(requestId, code); //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(initCommand.getBody(), NyShuttleHttpCommand.class); JSONObject requestResult = requestCommand(httpCommand); removeIdx = i;//此数据已经处理,从结果集中剔除 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 Device getDevice() { return this.device; } @Override public boolean movePath(List nodes, Integer taskNo) { return true; } @Override public boolean move(ShuttleCommand command) { try { //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class); Map body = httpCommand.getRequest().getBody(); Object pathObj = body.get("path"); 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); subList.clear(); }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); request.setBody(bodyCopy); httpCommandCopy.setRequest(request); commandList.add(httpCommandCopy);//add copy } for (NyShuttleHttpCommand requestCommand : commandList) { JSONObject result = requestCommand(requestCommand); if (result == null) { return false;//请求失败 } this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 } return true; } catch (IOException e) { return false; } } @Override public boolean lift(ShuttleCommand command) { try { //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class); JSONObject result = requestCommand(httpCommand); if (result == null) { return false;//请求失败 } this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 return true; } catch (IOException e) { return false; } } @Override public boolean charge(ShuttleCommand command) { try { //发出请求 NyShuttleHttpCommand httpCommand = JSON.parseObject(command.getBody(), NyShuttleHttpCommand.class); JSONObject result = requestCommand(httpCommand); if (result == null) { return false;//请求失败 } this.shuttleProtocol.setSendTime(System.currentTimeMillis());//指令下发时间 return true; } catch (IOException e) { return false; } } @Override public boolean reset(ShuttleCommand command) { setSyncTaskNo(0); setProtocolStatus(ShuttleProtocolStatusType.IDLE); enableMoveLoc(null, false); return true; } @Override public boolean updateLocation(ShuttleCommand param) { return true;//还没移植过来 } @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.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.getOne(new LambdaQueryWrapper().eq(BasShuttle::getDeviceId, this.device.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() == 1 && this.shuttleProtocol.getHasCharge()) { //运行中 && 充电中 return true; } return false; } @Override public boolean isChargingCompleted() { Integer maxPower = 100; DictService dictService = SpringUtils.getBean(DictService.class); if (dictService != null) { Dict chargeMaxValue = dictService.getOne(new LambdaQueryWrapper() .eq(Dict::getFlag, "chargeMaxValue") .eq(Dict::getStatus, 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 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(DeviceRedisConstant.SHUTTLE_WORK_FLAG + shuttleProtocol.getTaskNo()); if (object != null) { ShuttleRedisCommand redisCommand = null; try { redisCommand = objectMapper.readValue(String.valueOf(object), ShuttleRedisCommand.class); } catch (JsonProcessingException e) { return path; } List nodes = redisCommand.getAssignCommand().getNodes();//穿梭车预计路径 if (nodes == null) { return path; } if (!nodes.isEmpty()) { path.addAll(nodes); } //将路径锁与小车路径进行匹配 ArrayList tmp = new ArrayList<>(); //检测路径是否被锁定 int[][] map = navigateMapData.getDataFromRedis(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, MotionCtgType motionCtgType) { return taskNo; } @Override public synchronized boolean setProtocolStatus(ShuttleProtocolStatusType status) { this.shuttleProtocol.setProtocolStatus(status); 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 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(Integer.parseInt(device.getDeviceNo()), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); ArrayList> path = new ArrayList<>(); HashMap body = new HashMap<>(); body.put("requestType", "move");//移动命令 body.put("taskId", getTaskId());//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); navigateMapData.setLev(startNode.getZ()); for (NavigateNode node : nodes) { HashMap data = new HashMap<>(); String codeNum = NavigatePositionConvert.xyToPosition(node.getX(), node.getY(), node.getZ(), device.getHostId()); Map nyNode = navigateNodeToNyPointNode(NavigatePositionConvert.codeToNode(codeNum, device.getHostId())); 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(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.getYBase()); data.put("y", mapNode.getXBase()); path.add(data); } httpStandard.setRequest(request); LocService locService = SpringUtils.getBean(LocService.class); Loc loc = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, distCodeNum) .eq(Loc::getHostId, this.device.getHostId())); if (loc == null) { throw new CoolException("库位信息不存在"); } ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(Integer.parseInt(this.device.getDeviceNo())); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(ShuttleCommandModeType.MOVE.id); command.setTargetLocNo(loc.getLocNo()); return command; } @Override public ShuttleCommand getLiftCommand(Integer taskNo, Boolean lift) { NyShuttleHttpCommand httpStandard = getHttpStandard(Integer.parseInt(device.getDeviceNo()), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); HashMap body = new HashMap<>(); body.put("requestType", lift ? "liftUp" : "liftDown");//顶升或下降命令 body.put("taskId", getTaskId());//TaskID需要随机 request.setBody(body); httpStandard.setRequest(request); ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(Integer.parseInt(this.device.getDeviceNo())); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(lift ? ShuttleCommandModeType.PALLET_LIFT.id : ShuttleCommandModeType.PALLET_DOWN.id); return command; } @Override public ShuttleCommand getChargeCommand(Integer taskNo, Boolean charge) { NyShuttleHttpCommand httpStandard = getHttpStandard(Integer.parseInt(device.getDeviceNo()), taskNo); NyShuttleHttpCommand.NyRequest request = httpStandard.getRequest(); HashMap body = new HashMap<>(); body.put("requestType", charge ? "charge" : "stopCharge");//充电或停止充电 body.put("taskId", getTaskId());//TaskID需要随机 request.setBody(body); httpStandard.setRequest(request); ShuttleCommand command = new ShuttleCommand(); command.setShuttleNo(Integer.parseInt(this.device.getDeviceNo())); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(charge ? ShuttleCommandModeType.CHARGE_OPEN.id : ShuttleCommandModeType.CHARGE_CLOSE.id); return command; } @Override public ShuttleCommand getUpdateLocationCommand(Integer taskNo, String locNo) { return null;//还没移植过来 } //获取小车复位响应命令 public ShuttleCommand getInitCommand(Integer taskNo, Integer code) { LocService locService = SpringUtils.getBean(LocService.class); NavigateMapData navigateMapData = SpringUtils.getBean(NavigateMapData.class); NyShuttleHttpCommand httpStandard = getHttpStandard(Integer.parseInt(device.getDeviceNo()), 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); Loc loc = locService.getOne(new LambdaQueryWrapper() .eq(Loc::getCode, mapStr) .eq(Loc::getStatus, 1) .eq(Loc::getHostId, this.device.getHostId())); if (loc == null) { throw new CoolException("地址码不存在"); } navigateMapData.setLev(lev); List> mapData = navigateMapData.getJsonData(NavigationMapType.NONE.id, null, null); List mapNodes = mapData.get(loc.getRow()); MapNode mapNode = mapNodes.get(loc.getBay()); HashMap location = new HashMap<>(); location.put("xp", row); location.put("yp", bay); location.put("z", lev); location.put("x", mapNode.getYBase()); location.put("y", mapNode.getXBase()); 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(Integer.parseInt(this.device.getDeviceNo())); command.setBody(JSON.toJSONString(httpStandard)); command.setMode(ShuttleCommandModeType.RESET.id); return command; } @Override public boolean connect() { try { Socket socket = new Socket(device.getIp(),device.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()), device.getId(), device.getIp(), device.getPort())); } catch (IOException e) { OutputQueue.SHUTTLE.offer(MessageFormat.format("【{0}】四向穿梭车Socket链接失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), device.getId(), device.getIp(), device.getPort())); } 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; try { requestType = httpCommand.getRequest().getBody().get("requestType").toString(); } catch (Exception e) { return null; } // 获取服务器响应 // 尝试10次 JSONObject result = null; for (int i = 0; i < 10; i++) { result = getRequestBody(requestType); if (result == null) { try { Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } break; } return result;//返回Body结果集 } 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; return new int[]{y1, x1, z}; } @Data private class InnerSuhttleExtend { /** * 管制状态不在管制下/被管制中 * 0/1 */ private Integer suspendState; /** * 当前速度,单位mm/s */ private Integer speed; /** * 剩余电量/10(A) */ private Integer surplusQuantity; /** * 总电量/10(A) */ private Integer countQuantity; } }