src/main/java/com/zy/asrs/controller/RobotController.java
@@ -2,7 +2,19 @@ import com.zy.asrs.domain.param.RobotReportActionStatusParam; import com.zy.asrs.domain.param.ReportExceptionParam; import com.zy.asrs.entity.WrkMast; import com.zy.asrs.mapper.WrkMastMapper; import com.zy.common.utils.RobotUtils; import com.zy.core.DevpThread; import com.zy.core.cache.MessageQueue; import com.zy.core.cache.SlaveConnection; import com.zy.core.enums.SlaveType; import com.zy.core.model.DevpSlave; import com.zy.core.model.Task; import com.zy.core.model.protocol.StaProtocol; import com.zy.core.properties.SlaveProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -11,6 +23,11 @@ @RestController public class RobotController { @Autowired private WrkMastMapper wrkMastMapper; @Autowired private SlaveProperties slaveProperties; //机械手向WCS回报任务结果完成 @PostMapping("/request/wcs/report_task_status") @@ -21,6 +38,17 @@ Integer pickNum = param.getPick_num(); Integer targetNum = param.getTarget_num(); String message = param.getMessage(); Integer staNo = param.getFrom_ws();//目标站 //给目标站写入出库站344 for (DevpSlave devp : slaveProperties.getDevp()) { // 获取入库站信息 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId()); StaProtocol staProtocol = devpThread.getStation().get(staNo);//机械手臂拣料站 staProtocol = staProtocol.clone(); staProtocol.setStaNo((short) 344);//空托盘出库站 boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol)); } System.out.println(param); map.put("error", 0); @@ -43,4 +71,14 @@ return map; } @GetMapping("/test") public void test() { boolean systemStatus = RobotUtils.getSystemStatus(); } @GetMapping("/test2") public void test2() { RobotUtils.sendTask("9994", 4, "317"); } } src/main/java/com/zy/asrs/controller/ShuttleController.java
@@ -338,6 +338,15 @@ shuttleProtocol.setToken(0);//令牌清空 shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE);//任务状态-空闲 shuttleProtocol.setPakMk(false);//作业标记复位 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 R.ok(); } else if (shuttleTaskModeType == ShuttleTaskModeType.SHUTTLE_CONTROL) { //小车管制 @@ -410,4 +419,40 @@ return R.ok(); } /** * 跑库程序 */ @PostMapping("/moveLoc") @ManagerAuth public R moveLoc(@RequestParam Integer shuttleNo, @RequestParam Integer moveType, @RequestParam Integer xStart, @RequestParam Integer xTarget, @RequestParam Integer yStart, @RequestParam Integer yTarget) { NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttleNo); if (shuttleThread == null) { return R.error(); } NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol(); if (shuttleProtocol == null) { return R.error(); } if (!shuttleProtocol.isIdle()) { return R.error("小车忙碌中"); } shuttleProtocol.setMoveLoc(true);//开启跑库 shuttleProtocol.setMoveType(moveType); shuttleProtocol.setXStart(xStart); shuttleProtocol.setXTarget(xTarget); shuttleProtocol.setXCurrent(xStart); shuttleProtocol.setYStart(yStart); shuttleProtocol.setYTarget(yTarget); shuttleProtocol.setYCurrent(yStart); return R.ok(); } } src/main/java/com/zy/asrs/domain/param/RobotReportActionStatusParam.java
@@ -23,4 +23,6 @@ //结果讯息 private String message; private Integer from_ws; } src/main/java/com/zy/asrs/mapper/LocMastMapper.java
@@ -39,4 +39,6 @@ LocMast queryByQrCode(String qrCodeValue); List<LocMast> selectLocByLev(Integer lev); List<LocMast> selectEmptyLocNos(@Param("locNos") List<String> locNos); } src/main/java/com/zy/asrs/service/LocMastService.java
@@ -70,4 +70,6 @@ //查询指定楼层的库位数据 List<LocMast> selectLocByLev(Integer lev); List<LocMast> selectEmptyLocNos(List<String> locNos); } src/main/java/com/zy/asrs/service/impl/LocMastServiceImpl.java
@@ -91,4 +91,9 @@ public List<LocMast> selectLocByLev(Integer lev) { return this.baseMapper.selectLocByLev(lev); } @Override public List<LocMast> selectEmptyLocNos(List<String> locNos) { return this.baseMapper.selectEmptyLocNos(locNos); } } src/main/java/com/zy/asrs/service/impl/MainServiceImpl.java
@@ -1946,6 +1946,90 @@ } /** * AGV补货 => 机械臂拣料 */ public void agvRestockByRobot() { //检测300站是否自动、有物、工作号 for (DevpSlave devp : slaveProperties.getDevp()) { // 获取入库站信息 DevpThread devpThread = (DevpThread) SlaveConnection.get(SlaveType.Devp, devp.getId()); StaProtocol staProtocol = devpThread.getStation().get(300); if (staProtocol.isAutoing() && staProtocol.isLoading() && staProtocol.getWorkNo() != 0) { //查询是否有工作档 WrkMast wrkMast = wrkMastMapper.selectByWorkNo(staProtocol.getWorkNo().intValue()); if (wrkMast == null) { continue; } if (wrkMast.getWrkSts() != 25) {//25.提升机搬运完成 continue; } if (wrkMast.getMk().equals("Y")) {//标记为Y表示需要用到机械臂拣料 Short targetSta = null;//目标站 //判断机械臂拣料站是否空闲 StaProtocol staProtocol303 = devpThread.getStation().get(303); StaProtocol staProtocol317 = devpThread.getStation().get(317); if (staProtocol303.isAutoing() && !staProtocol303.isLoading()) { //自动、无物 targetSta = (short) 303; } else if (staProtocol317.isAutoing() && !staProtocol317.isLoading()) { //自动、无物 targetSta = (short) 317; }else { continue;//没有空闲站点 } targetSta = (short) 317; //覆盖工作档目标站 wrkMast.setStaNo(targetSta.intValue()); if (wrkMastMapper.updateById(wrkMast) > 0) { //向300站写入目标站 staProtocol = staProtocol.clone(); staProtocol.setStaNo(targetSta);//移动到目标站 boolean result = MessageQueue.offer(SlaveType.Devp, devp.getId(), new Task(2, staProtocol)); try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } continue; } } } StaProtocol staProtocol303 = devpThread.getStation().get(303); StaProtocol staProtocol317 = devpThread.getStation().get(317); if (staProtocol303.isAutoing() && staProtocol303.isLoading() && staProtocol303.getWorkNo() != 0) { //调度机械臂 //查询是否有工作档 WrkMast wrkMast = wrkMastMapper.selectByWorkNo(staProtocol303.getWorkNo().intValue()); if (wrkMast == null) { continue; } WrkDetl wrkDetl = wrkDetlService.selectById(wrkMast.getWrkNo()); if (wrkDetl == null) { continue; } RobotUtils.sendTask(staProtocol303.getWorkNo().toString(), wrkDetl.getAnfme().intValue(), "303"); }else if (staProtocol317.isAutoing() && staProtocol317.isLoading() && staProtocol317.getWorkNo() != 0) { //调度机械臂 //查询是否有工作档 WrkMast wrkMast = wrkMastMapper.selectByWorkNo(staProtocol317.getWorkNo().intValue()); if (wrkMast == null) { continue; } WrkDetl wrkDetl = wrkDetlService.selectById(wrkMast.getWrkNo()); if (wrkDetl == null) { continue; } RobotUtils.sendTask(staProtocol303.getWorkNo().toString(), wrkDetl.getAnfme().intValue(), "317"); } } } /** * 出库 ===>> 工作档信息写入led显示器 */ public void ledExecute() { @@ -2240,7 +2324,7 @@ } } else if (wrkCharge.getWrkSts() == 52) { //检测小车是否满电 int maxPower = 85; int maxPower = 95; if (shuttleProtocol.getPowerPercent() < maxPower) { continue; } @@ -2257,22 +2341,32 @@ assignCommand.setSourceLocNo(shuttleProtocol.getCurrentLocNo());//源库位(小车当前位置) assignCommand.setCommands(commands);//运行命令 //下发任务 MessageQueue.offer(SlaveType.Shuttle, assignCommand.getShuttleNo().intValue(), new Task(3, assignCommand)); try { Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); } wrkCharge.setWrkSts(53L);//52.小车去充电中 => 53.小车充电完成 wrkCharge.setModiTime(new Date()); if (wrkChargeMapper.updateById(wrkCharge) > 0) { //下发任务 MessageQueue.offer(SlaveType.Shuttle, assignCommand.getShuttleNo().intValue(), new Task(3, assignCommand)); shuttleProtocol.setProtocolStatus(ShuttleProtocolStatusType.IDLE.id); shuttleProtocol.setTaskNo(0); shuttleProtocol.setPakMk(false); } } else if (wrkCharge.getWrkSts() == 53) { if (shuttleProtocol.getChargState() == 0) {//小车处于未充电状态 boolean result = Utils.searchEmptyGroupToMoveShuttle(Utils.getLev(wrkCharge.getLocNo()), shuttleThread.getSlave().getId(), shuttleThread); if (result) { wrkCharge.setWrkSts(60L);//53.小车充电完成 => 60.充电任务完成 wrkCharge.setModiTime(new Date()); if (wrkChargeMapper.updateById(wrkCharge) > 0) { shuttleProtocol.setProtocolStatusType(ShuttleProtocolStatusType.IDLE); shuttleProtocol.setTaskNo(0); } if (!result) { continue; } wrkCharge.setWrkSts(60L);//53.小车充电完成 => 60.充电任务完成 wrkCharge.setModiTime(new Date()); if (wrkChargeMapper.updateById(wrkCharge) > 0) { } } } src/main/java/com/zy/asrs/utils/Utils.java
@@ -505,11 +505,11 @@ SlaveProperties slaveProperties = SpringUtils.getBean(SlaveProperties.class); for (ShuttleSlave shuttle : slaveProperties.getShuttle()) { //获取四向穿梭车线程 ShuttleThread shuttleThread = (ShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId()); NyShuttleThread shuttleThread = (NyShuttleThread) SlaveConnection.get(SlaveType.Shuttle, shuttle.getId()); if (shuttleThread == null) { continue; } ShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol(); NyShuttleProtocol shuttleProtocol = shuttleThread.getShuttleProtocol(); if (shuttleProtocol == null) { continue; } src/main/java/com/zy/common/utils/RobotUtils.java
@@ -23,7 +23,7 @@ try { String response = new HttpHandler.Builder() .setUri(robotUrl) .setPath("/api/wcs/is_system_ready") .setPath("/adaptor/api/wcs/is_vp_ready") .setJson(JSON.toJSONString(map)) .build() .doPost(); @@ -40,9 +40,22 @@ } //WCS向机械臂下发单拆任务 public static boolean sendTask(String taskId, Map<String, Object> skuInfo, String from, String to) { public static boolean sendTask(String taskId, Integer skuNum, String from) { Environment environment = SpringUtils.getBean(Environment.class); String robotUrl = environment.getProperty("robot.url"); Map<String, Object> skuInfo = new HashMap<>(); skuInfo.put("sku_id", "1"); skuInfo.put("length", 500); skuInfo.put("width", 350); skuInfo.put("height", 200); skuInfo.put("weight", 1); skuInfo.put("sku_num", skuNum); String to = "307"; if (from.equals("317")) { to = "310"; } HashMap<String, Object> map = new HashMap<>(); map.put("task_id", taskId); @@ -52,14 +65,15 @@ try { String response = new HttpHandler.Builder() .setUri(robotUrl) .setPath("api/wcs/single_class_depal_task") .setPath("/adaptor/api/wcs/task/single_depal") .setJson(JSON.toJSONString(map)) .build() .doPost(); JSONObject data = JSON.parseObject(response); int error = Integer.parseInt(data.get("error").toString()); if (error == 0) { int code = Integer.parseInt(data.get("code").toString()); String msg = data.get("msg").toString(); if (code == 0 && msg.equals("success")) { return true;//成功 } } catch (IOException e) { src/main/java/com/zy/common/utils/ShuttleDispatchUtils.java
@@ -203,6 +203,10 @@ } } if (wrkCharge.getWrkSts() == 53) { toCharge = true;//充电结束,允许生成移库任务 } if (!toCharge) { //不是去充电桩且存在充电任务,禁止生成新的移动任务 return false; src/main/java/com/zy/core/MainProcess.java
@@ -70,6 +70,8 @@ mainService.recErr(); // 入库 ===>> 空栈板初始化入库,叉车入库站放货 mainService.storeEmptyPlt(); // AGV补货(机械臂拣料) mainService.agvRestockByRobot(); // 出库 ===>> 工作档信息写入led显示器 mainService.ledExecute(); // 其他 ===>> LED显示器复位,显示默认信息 src/main/java/com/zy/core/model/protocol/NyShuttleProtocol.java
@@ -204,6 +204,46 @@ */ private Integer token = 0; /** * 跑库状态 */ private Boolean moveLoc = false; /** * 跑库类型,0:跑轨道,1:跑库位 */ private Integer moveType = 0; /** * 跑库X起点 */ private Integer xStart = 0; /** * 跑库X终点 */ private Integer xTarget = 0; /** * 跑库X当前点位 */ private Integer xCurrent = 0; /** * 跑库Y起点 */ private Integer yStart = 0; /** * 跑库Y终点 */ private Integer yTarget = 0; /** * 跑库Y当前点位 */ private Integer yCurrent = 0; //总里程数 @Data public static class StatusSumClass { src/main/java/com/zy/core/thread/NyShuttleThread.java
@@ -11,6 +11,7 @@ import com.zy.asrs.utils.Utils; import com.zy.common.model.NavigateNode; import com.zy.common.model.NyShuttleOperaResult; import com.zy.common.service.CommonService; import com.zy.common.utils.*; import com.zy.core.News; import com.zy.core.ThreadHandler; @@ -28,6 +29,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import javax.swing.*; import java.io.IOException; import java.net.Socket; import java.text.MessageFormat; @@ -98,6 +100,11 @@ && !shuttleProtocol.getPakMk()) { //执行下一步指令 executeWork(shuttleProtocol.getTaskNo().shortValue()); } //小车空闲且有跑库程序 if (shuttleProtocol.isIdle() && shuttleProtocol.getMoveLoc()) { moveLoc(); } } catch (Exception e) { e.printStackTrace(); @@ -493,37 +500,6 @@ //任务数据保存到redis redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand)); // //判断数据是否执行完成 // if (commandStep < commands.size() - 1) { // commandStep++; // //更新redis数据 // redisCommand.setCommandStep(commandStep); // //任务数据保存到redis // redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand)); // }else { // //已执行完成 // // commandStep = commands.size(); // //更新redis数据 // redisCommand.setCommandStep(commandStep); // //任务数据保存到redis // redisUtil.set("shuttle_wrk_no_" + redisCommand.getWrkNo(), JSON.toJSONString(redisCommand)); //// //最后一段命令为移动命令,则暂缓删除redis等待清除路径时一次性删除 //// //最后一段命令为不是移动命令,则删除redis //// if (!command.getRequest().getBody().get("requestType").equals("move")) { //// //删除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; } @@ -711,4 +687,56 @@ return false;//不可行走 } /** * 跑库程序 */ private void moveLoc() { LocMastService locMastService = SpringUtils.getBean(LocMastService.class); ShuttleDispatchUtils shuttleDispatchUtils = SpringUtils.getBean(ShuttleDispatchUtils.class); CommonService commonService = SpringUtils.getBean(CommonService.class); WrkMastMapper wrkMastMapper = SpringUtils.getBean(WrkMastMapper.class); int lev = Utils.getLev(shuttleProtocol.getCurrentLocNo());//小车当前楼层 if (!shuttleProtocol.isIdle()) { return; } WrkMast wrkMast = wrkMastMapper.selectShuttleHasMoveWorking(shuttleProtocol.getShuttleNo().intValue()); if (wrkMast != null) { return; } if (shuttleProtocol.getMoveType() == 0) {//跑轨道 ArrayList<String> locs = new ArrayList<>(); for (int i = shuttleProtocol.getXCurrent(); i <= shuttleProtocol.getXTarget(); i++) { String locNo = Utils.getLocNo(i, shuttleProtocol.getYCurrent(), lev); locs.add(locNo); } List<LocMast> locMasts = locMastService.selectEmptyLocNos(locs); if (locMasts.isEmpty()) { //空库位 shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1); return; } LocMast start = locMasts.get(0); LocMast target = locMasts.get(locMasts.size() - 1); //判断小车是否在起点位置 if (!shuttleProtocol.getCurrentLocNo().equals(start.getLocNo())) {//不在起点位置,调度去起点位置 shuttleDispatchUtils.dispatchShuttle(commonService.getWorkNo(3), start.getLocNo()); }else { //在起点位置,调度去目标位置 if (shuttleProtocol.getCurrentLocNo().equals(target.getLocNo())) { shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1);//小车和目标位置一致,跳过 }else { boolean result = shuttleDispatchUtils.dispatchShuttle(commonService.getWorkNo(3), target.getLocNo()); if (result) {//调度成功 shuttleProtocol.setYCurrent(shuttleProtocol.getYCurrent() + 1); } } } }else {//跑库位 } } } src/main/resources/application.yml
@@ -8,10 +8,10 @@ name: @pom.build.finalName@ datasource: driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver url: jdbc:sqlserver://192.168.4.15:1433;databasename=tzskasrs url: jdbc:sqlserver://127.0.0.1:1433;databasename=tzskasrs username: sa # password: Zoneyung@zy56$ password: sa@123 password: sa mvc: static-path-pattern: /** redis: @@ -41,7 +41,7 @@ url: localhost:8081/tzskwms robot: url: http://127.0.0.1:9090/tzskwcs url: http://10.10.10.41:7002 erp: db: @@ -60,7 +60,7 @@ # 输送线 devp[0]: id: 1 ip: 10.10.10.100 ip: 10.10.10.51 port: 102 rack: 0 slot: 0 @@ -74,37 +74,37 @@ inSta[1]: staNo: 103 backSta: 102 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[1].id} led: ${wcs-slave.led[0].id} # 入库口3 inSta[2]: staNo: 105 backSta: 104 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[2].id} led: ${wcs-slave.led[0].id} # 入库口4 inSta[3]: staNo: 200 backSta: 201 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[3].id} led: ${wcs-slave.led[0].id} # 入库口5 inSta[4]: staNo: 203 backSta: 202 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[4].id} led: ${wcs-slave.led[0].id} # 入库口6 inSta[5]: staNo: 205 backSta: 204 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[5].id} led: ${wcs-slave.led[0].id} # 入库口7 inSta[6]: staNo: 346 backSta: 345 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[8].id} led: ${wcs-slave.led[0].id} # 空板入库口1 emptyInSta[0]: @@ -116,37 +116,37 @@ emptyInSta[1]: staNo: 103 backSta: 102 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[1].id} led: ${wcs-slave.led[0].id} # 空板入库口3 emptyInSta[2]: staNo: 105 backSta: 104 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[2].id} led: ${wcs-slave.led[0].id} # 空板入库口4 emptyInSta[3]: staNo: 200 backSta: 201 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[3].id} led: ${wcs-slave.led[0].id} # 空板入库口5 emptyInSta[4]: staNo: 203 backSta: 202 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[4].id} led: ${wcs-slave.led[0].id} # 空板入库口6 emptyInSta[5]: staNo: 205 backSta: 204 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[5].id} led: ${wcs-slave.led[0].id} # 空板入库口7 emptyInSta[6]: staNo: 346 backSta: 345 barcode: ${wcs-slave.barcode[0].id} barcode: ${wcs-slave.barcode[8].id} led: ${wcs-slave.led[0].id} # 出库口1 outSta[0]: @@ -248,6 +248,51 @@ id: 1 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[1]: id: 2 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[2]: id: 3 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[3]: id: 4 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[4]: id: 5 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[5]: id: 6 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[6]: id: 7 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[7]: id: 8 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[8]: id: 9 ip: 10.10.10.102 port: 51236 # 条码扫描仪 barcode[9]: id: 10 ip: 10.10.10.102 port: 51236 # LED1 led[0]: @@ -267,14 +312,14 @@ # 四向穿梭车1 shuttle[0]: id: 1 ip: 127.0.0.1 ip: 10.10.10.101 port: 8888 rack: 0 slot: 0 # 四向穿梭车2 shuttle[1]: id: 2 ip: 192.168.4.15 ip: 10.10.10.102 port: 8888 rack: 0 slot: 0 @@ -337,111 +382,141 @@ # 提升机1 lift[0]: id: 1 ip: 192.168.4.250 port: 502 row: 18 bay: 2 ip: 10.10.10.131 port: 102 staRow: 13 staBay: 22 sta[0]: staNo: 101 lev: 1 liftNo: ${wcs-slave.lift[0].id} sta[1]: staNo: 102 lev: 2 liftNo: ${wcs-slave.lift[0].id} sta[2]: staNo: 103 lev: 3 liftNo: ${wcs-slave.lift[0].id} sta[3]: staNo: 104 lev: 4 liftNo: ${wcs-slave.lift[0].id} sta[4]: staNo: 105 lev: 5 liftNo: ${wcs-slave.lift[0].id} sta[5]: staNo: 106 lev: 6 liftNo: ${wcs-slave.lift[0].id} sta[6]: staNo: 107 lev: 7 liftNo: ${wcs-slave.lift[0].id} sta[7]: staNo: 108 lev: 8 liftNo: ${wcs-slave.lift[0].id} sta[8]: staNo: 109 lev: 9 liftNo: ${wcs-slave.lift[0].id} sta[9]: staNo: 110 lev: 10 liftNo: ${wcs-slave.lift[0].id} # 提升机2 lift[1]: id: 2 ip: 127.0.0.1 port: 502 row: 18 bay: 2 ip: 10.10.10.132 port: 102 staRow: 13 staBay: 38 sta[0]: staNo: 201 lev: 1 liftNo: ${wcs-slave.lift[1].id} sta[1]: staNo: 202 lev: 2 liftNo: ${wcs-slave.lift[1].id} sta[2]: staNo: 203 lev: 3 liftNo: ${wcs-slave.lift[1].id} sta[3]: staNo: 204 lev: 4 liftNo: ${wcs-slave.lift[1].id} sta[4]: staNo: 205 lev: 5 liftNo: ${wcs-slave.lift[1].id} sta[5]: staNo: 206 lev: 6 liftNo: ${wcs-slave.lift[1].id} sta[6]: staNo: 207 lev: 7 liftNo: ${wcs-slave.lift[1].id} sta[7]: staNo: 208 lev: 8 liftNo: ${wcs-slave.lift[1].id} sta[8]: staNo: 209 lev: 9 liftNo: ${wcs-slave.lift[1].id} sta[9]: staNo: 210 lev: 10 liftNo: ${wcs-slave.lift[1].id} # 提升机3 lift[2]: id: 3 ip: 127.0.0.1 port: 502 row: 18 bay: 2 ip: 10.10.10.133 port: 102 staRow: 13 staBay: 57 sta[0]: staNo: 301 lev: 1 liftNo: ${wcs-slave.lift[2].id} sta[1]: staNo: 302 lev: 2 liftNo: ${wcs-slave.lift[2].id} sta[2]: staNo: 303 lev: 3 liftNo: ${wcs-slave.lift[2].id} sta[3]: staNo: 304 lev: 4 liftNo: ${wcs-slave.lift[2].id} sta[4]: staNo: 305 lev: 5 liftNo: ${wcs-slave.lift[2].id} sta[5]: staNo: 306 lev: 6 liftNo: ${wcs-slave.lift[2].id} sta[6]: staNo: 307 lev: 7 liftNo: ${wcs-slave.lift[2].id} sta[7]: staNo: 308 lev: 8 liftNo: ${wcs-slave.lift[2].id} sta[8]: staNo: 309 lev: 9 liftNo: ${wcs-slave.lift[2].id} sta[9]: staNo: 310 lev: 10 lev: 10 liftNo: ${wcs-slave.lift[2].id} src/main/resources/mapper/LocMastMapper.xml
@@ -73,4 +73,14 @@ <select id="selectLocByLev" resultMap="BaseResultMap"> SELECT * FROM asr_loc_mast WHERE lev1 = #{lev} </select> <select id="selectEmptyLocNos" resultMap="BaseResultMap"> select * from asr_loc_mast where loc_no in <foreach item="loc" collection="locNos" index="index" separator="," open="(" close=")"> #{loc} </foreach> and loc_sts = 'O' order by row1 </select> </mapper> src/main/webapp/views/shuttle2.html
New file @@ -0,0 +1,626 @@ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>四向穿梭车监控管理</title> <link rel="stylesheet" type="text/css" href="../static/css/normalize.css"> <link rel="stylesheet" type="text/css" href="../static/css/common.css"> <link rel="stylesheet" type="text/css" href="../static/layui/css/layui.css"> <link rel="stylesheet" href="../static/css/shuttle.css"> <script type="text/javascript" src="../static/js/jquery/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="../static/js/layer/layer.js"></script> <script type="text/javascript" src="../static/layui/layui.js"></script> <script type="text/javascript" src="../static/js/common.js"></script> </head> <body> <div style="padding: 10px;height: 100%;float: left;width: 6%"> <div class="button-window"></div> </div> <div style="height: 100%;padding-left: 6%"> <div style="padding: 10px;height: 100%"> <!-- 日志监控板 --> <div class="log-board"> <!-- <div class="command-log" id="commandLogId" style="width: 5%;">--> <!--<!– <div data-shuttleNo="1" class="shuttle-command-item">–>--> <!--<!– <label>1#</label>–>--> <!--<!– <button class="demoBtn pos-btn">数据维护</button>–>--> <!--<!– <button id="mode-1" class="demoBtn mode-btn" >设备信息</button>–>--> <!--<!– </div>–>--> <!-- </div>--> <!-- 堆垛机状态位信息 --> <div class="shuttle-state" style="width: 100%;"> <table id="shuttle-state-table"> <thead> <tr> <th>四向穿梭车</th> <th>任务状态</th> <th>小车状态</th> <th>工作模式</th> <th>实际库位</th> <th>实际坐标</th> <th>电量</th> <th>当前速度</th> <th>负载状态</th> <th>顶升位置</th> <th>运行方向</th> <th>运行方向2</th> <th>充电状态</th> <th>故障状态</th> <th>故障码</th> <th>管制状态</th> </tr> </thead> <tbody> </tbody> </table> </div> </div> <!-- 穿梭车状态 --> <div class="shuttle-msg"> <table id="shuttle-msg-table"> <thead> <tr> <th>四向穿梭车</th> <th>工作号</th> <th>源库位</th> <th>目标库位</th> <th>最高电芯电压</th> <th>最低电芯电压</th> <th>电池电压</th> <th>充放电循环次数</th> <th>剩余电量</th> <th>总电量</th> <th>总里程数</th> <th>作业标记</th> <th>当前库位</th> <th>令牌</th> </tr> </thead> <tbody> </tbody> </table> </div> <!-- 手动操作 --> <div class="shuttle-operation"> <!-- 遮罩层 --> <div class="shuttle-operation-shade"> <span class="shuttle-operation-shade-span"> WCS 系统运行中,请停止后操作 </span> </div> <!-- 设备任务选择 --> <div class="task-select"> <!-- 选择 --> <div id="shuttle-select" class="operator-item" style="width: 100%;"> <span class="select-title">四向穿梭车号</span> <div class="select-container" id="shuttleRadioBoxId" style="display: flex;flex-wrap: wrap;justify-content: center;align-items: center;"> <!-- <label><input type="radio" name="shuttleSelect" value="1" checked> 1号穿梭车</label>--> </div> </div> </div> <!-- 设备任务操作 --> <div class="task-operator"> <fieldset style="height: auto;padding-bottom: 20px;"> <legend>手动操作</legend> <div style="display: flex;"> <div style="width: 30%;"> <div class="operator-item" style="height: auto;width: 100%;"> <span class="select-title">源库位/目标库位</span> <div class="select-container" style="height: auto;padding: 30px 10px 20px 10px;"> <div class="select-container-item"> <span>源库位</span> <label><input id="sourceLocNo" type="text" name="sourceLocNo" /></label> </div> <div class="select-container-item"> <span>目标库位</span> <label><input id="distLocNo" type="text" name="distLocNo" /></label> </div> <div style="margin-top: 10px;"> <button class="item" onclick="shuttleOperator(18)">搬运货物</button> <button class="item" onclick="shuttleOperator(14)">移动到目标库位</button> <button class="item" onclick="shuttleOperator(23)">移动到目标库位(任务)</button> <!-- <button class="item" onclick="shuttleOperator(16)">移动到提升机</button>--> </div> </div> </div> </div> <div style="width: 40%;"> <div class="operator-item" style="height: auto;width: 100%;"> <span class="select-title">相关指令</span> <div class="select-container" style="height: auto;padding: 30px 10px 10px 10px;"> <div class="button-group"> <button class="item" onclick="shuttleOperator(3)">托盘顶升</button> <button class="item" onclick="shuttleOperator(4)">托盘下降</button> <button class="item" onclick="shuttleOperator(15)">充电开关</button> <button class="item" onclick="shuttleOperator(9)">复位</button> <button class="item" onclick="shuttleOperator(21)">管制</button> <button class="item" onclick="shuttleOperator(22)">取消管制</button> </div> </div> </div> </div> <div style="width: 30%;"> <div class="operator-item" style="height: auto;width: 100%;"> <span class="select-title">跑库系统</span> <div class="select-container" style="height: auto;padding: 30px 10px 20px 10px;"> <div class="select-container-item"> <span>X起点</span> <label><input id="xStart" type="text" name="xStart" /></label> </div> <div class="select-container-item"> <span>X终点</span> <label><input id="xTarget" type="text" name="xTarget" /></label> </div> <div class="select-container-item"> <span>Y起点</span> <label><input id="yStart" type="text" name="yStart" /></label> </div> <div class="select-container-item"> <span>Y终点</span> <label><input id="yTarget" type="text" name="yTarget" /></label> </div> <div> <label><input type="radio" name="moveType" value="0"> 跑轨道</label> <label><input type="radio" name="moveType" value="1"> 跑库位</label> </div> <div style="margin-top: 10px;"> <button class="item" onclick="moveLoc()">跑库</button> </div> </div> </div> </div> </div> </fieldset> </div> </div> <!-- 穿梭车日志输出 --> <div class="shuttle-output-board"> <textarea id="shuttle-output"></textarea> </div> </div> </div> <div id="shuttle-detl" style="display: none"> <div> <div class="form-item"> <label class="form-label">穿梭车号:</label> <div class="form-input"> <input id="shuttleNo" name="shuttleNo" class="layui-input" lay-verify="required|number" autocomplete="off" disabled="disabled"> </div> </div> <div class="form-item"> <label class="form-label">工作号:</label> <div class="form-input"> <input id="workNo" name="workNo" type="number" class="layui-input" lay-verify="number" autocomplete="off"> </div> </div> <div class="form-item"> <label class="form-label">作业标记:</label> <div class="form-input"> <input id="pakMk" name="pakMk" type="text" class="layui-input" autocomplete="off"> </div> </div> <div class="form-item"> <label class="form-label">令牌:</label> <div class="form-input"> <input id="token" name="token" type="text" class="layui-input" autocomplete="off"> </div> </div> <div class="form-item form-button-container"> <button class="form-button" id="save">保存</button> <button class="form-button" id="cancel" style="background-color: #D0D0D0">取消</button> </div> </div> </div> </body> </html> <script> // 空白行数 var shuttleStateTableBlankRows = 0; var shuttleMsgTableBlankRows = 0; // 实际行数 var shuttleStateTableFullRows = 0; var shuttleMsgTableFullRows = 0; // 初始化 var shuttleOutputDom = document.getElementById("shuttle-output"); $(document).ready(function() { initShuttleStateTable(); getShuttleStateInfo(); initShuttleMsgTable(); getShuttleMsgInfo(); operatorBlockShow(); setShuttleRadio(); }); setInterval(function () { getShuttleStateInfo() getShuttleMsgInfo(); },1000) setInterval(function () { getShuttleOutput(); operatorBlockShow(); },500); // 判断手动操作模块是否可用 function operatorBlockShow() { if (parent.systemRunning) { $('.shuttle-operation').css("opacity", "0.5"); $('.shuttle-operation-shade').show(); $('.shuttle-operation-shade-span').show(); } else { $('.shuttle-operation').css("opacity", "1"); $('.shuttle-operation-shade').hide(); $('.shuttle-operation-shade-span').hide(); } } function getColor(res,e){ $(e).val(res?"✔":"—"); if (res){ $(e).attr("style", "color: #FD482C;"); }else { $(e).attr("style", "color: #00FF00;"); } } $(document).on('click ','#save', function () { http.post(baseUrl+ "/shuttle/detl/update", { shuttleNo: $('#shuttleNo').val(), workNo: $('#workNo').val(), pakMk: $('#pakMk').val(), token: $('#token').val(), }, function (res) { layer.msg("修改成功", {icon: 1,}); layer.close(layerDetl); }) }) function setShuttleRadio() { $.ajax({ url: baseUrl+ "/shuttle/table/shuttle/state", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200){ let table = res.data; for (let i=1;i<=table.length;i++){ //渲染四向穿梭车选项html let shuttleRadioBox = '<label><input type="radio" name="shuttleSelect" '; if (i === 1) { shuttleRadioBox += 'checked ' } shuttleRadioBox += 'value="' + table[i - 1].shuttleNo + '"> ' + table[i - 1].shuttleNo + '号穿梭车</label>' $("#shuttleRadioBoxId").append(shuttleRadioBox) //渲染四向穿梭车数据维护和设备信息html let shuttleCommandLogBox = '<div class="shuttle-command-item" data-shuttleNo="' + table[i - 1].shuttleNo + '">\n' + '<label>' + table[i - 1].shuttleNo + '#</label>\n' + // '<button class="demoBtn pos-btn">数据维护</button>\n' + // '<button class="demoBtn mode-btn" id="mode-' + table[i - 1].shuttleNo + '">设备信息</button>\n' + '</div>' $("#commandLogId").append(shuttleCommandLogBox); } } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } }); } // 四向穿梭车信息表获取 ---- 表一 function getShuttleStateInfo() { let tableEl = $('#shuttle-state-table'); $.ajax({ url: baseUrl+ "/shuttle/table/shuttle/state", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200){ let table = res.data; if (table.length > shuttleStateTableBlankRows && table.length !== shuttleStateTableFullRows) { initShuttleStateTable(table.length-shuttleStateTableBlankRows); shuttleStateTableFullRows = table.length; } for (let i=1;i<=table.length;i++){ // $("#mode-"+table[i-1].shuttleNo).html(table[i-1].statusVal===0?'联机':'脱机'); let tr = tableEl.find("tr").eq(i); setVal(tr.children("td").eq(0), table[i-1].shuttleNo); setVal(tr.children("td").eq(1), table[i-1].protocolStatus$); setVal(tr.children("td").eq(2), table[i-1].free$); setVal(tr.children("td").eq(3), table[i-1].workingMode$); setVal(tr.children("td").eq(4), table[i-1].point$); setVal(tr.children("td").eq(5), table[i-1].point$$); setVal(tr.children("td").eq(6), table[i-1].powerPercent$); setVal(tr.children("td").eq(7), table[i-1].speed); setVal(tr.children("td").eq(8), table[i-1].loadState$); setVal(tr.children("td").eq(9), table[i-1].liftPosition$); setVal(tr.children("td").eq(10), table[i-1].runDir$); setVal(tr.children("td").eq(11), table[i-1].runDir2$); setVal(tr.children("td").eq(12), table[i-1].chargState$); setVal(tr.children("td").eq(13), table[i-1].errState$); setVal(tr.children("td").eq(14), table[i-1].errCode$); setVal(tr.children("td").eq(15), table[i-1].suspendState$); } } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } }); } // 四向穿梭车数据表获取 ---- 表二 function getShuttleMsgInfo() { let tableEl = $('#shuttle-msg-table'); $.ajax({ url: baseUrl+ "/shuttle/table/shuttle/state", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200){ var table = res.data; if (table.length > shuttleMsgTableBlankRows && table.length !== shuttleMsgTableFullRows) { initShuttleMsgTable(table.length-shuttleMsgTableBlankRows); shuttleMsgTableFullRows = table.length; } for (var i=1;i<=table.length;i++){ var tr = tableEl.find("tr").eq(i); setVal(tr.children("td").eq(0), table[i-1].shuttleNo); setVal(tr.children("td").eq(1), table[i-1].taskNo); setVal(tr.children("td").eq(2), table[i-1].sourceLocNo); setVal(tr.children("td").eq(3), table[i-1].locNo); setVal(tr.children("td").eq(4), table[i-1].maxCellVoltage$); setVal(tr.children("td").eq(5), table[i-1].minCellVoltage$); setVal(tr.children("td").eq(6), table[i-1].voltage$); setVal(tr.children("td").eq(7), table[i-1].chargeCycleTimes); setVal(tr.children("td").eq(8), table[i-1].surplusQuantity); setVal(tr.children("td").eq(9), table[i-1].countQuantity); setVal(tr.children("td").eq(10), table[i-1].statusSum.mileage); setVal(tr.children("td").eq(11), table[i-1].pakMk$); setVal(tr.children("td").eq(12), table[i-1].currentLocNo); setVal(tr.children("td").eq(13), table[i-1].token); if (table[i-1].shuttleNo == parseInt($('input[name="shuttleSelect"]:checked').val())) { $("#runSpeedText").text(table[i-1].runSpeed) $("#chargeLineText").text(table[i-1].chargeLine + "%") } } } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } }); } // 穿梭车日志输出 ----------------------------------------------------------------------- function getShuttleOutput() { $.ajax({ url: baseUrl + "/shuttle/output/shuttle", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200) { shuttleOutput(res.data); } else if (res.code === 403) { window.location.href = baseUrl + "/login"; } else { console.log(res.msg); } } }) } // 任务指令下发 function shuttleOperator(shuttleTaskMode) { http.post(baseUrl+"/shuttle/operator/shuttle", { shuttleNo: $('input[name="shuttleSelect"]:checked').val(), shuttleTaskMode: shuttleTaskMode, sourceLocNo: $("#sourceLocNo").val(), distLocNo: $("#distLocNo").val() }, function (res) { layer.msg(res.msg, {icon: 1}); }); } // 跑库 function moveLoc() { $.ajax({ url: baseUrl + "/shuttle/moveLoc", headers: {'token': localStorage.getItem('token')}, method: 'POST', data: { shuttleNo: $('input[name="shuttleSelect"]:checked').val(), xStart: $("#xStart").val(), xTarget: $("#xTarget").val(), yStart: $("#yStart").val(), yTarget: $("#yTarget").val(), moveType: $('input[name="moveType"]:checked').val() }, success: function (res) { if (res.code === 200) { layer.msg(res.msg, {icon: 1}); } else if (res.code === 403) { window.location.href = baseUrl + "/login"; } else { console.log(res.msg); } } }) } // ------------------------------------------------------------------------------------------------ // 四向穿梭车信息表获取 ----- 表一 function initShuttleStateTable(row) { let line; if (row === undefined){ let one = $('#shuttle-state-table thead').height(); let total = $('.shuttle-state').height(); let count = total / one; count = parseInt(count) - 1; shuttleStateTableBlankRows = count; line = count; } else { line = row; } let html = ""; for (let i = 0; i < line; i ++){ html += " <tr>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " </tr>\n"; } $('#shuttle-state-table tbody').after(html); } // 穿梭车数据表获取 ----- 表二 function initShuttleMsgTable(row) { let line; if (row === undefined){ let one = $('#shuttle-msg-table thead').height(); let total = $('.shuttle-msg').height(); let count = total / one; count = parseInt(count) - 1; shuttleMsgTableBlankRows = count; line = count; } else { line = row; } let html = ""; for (let i = 0; i < line; i ++){ html += " <tr>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " <td></td>\n" + " </tr>\n"; } $('#shuttle-msg-table tbody').after(html); } // 日志输出框 function shuttleOutput(content){ shuttleOutputDom.value += content; shuttleOutputDom.scrollTop = shuttleOutputDom.scrollHeight; } //四向穿梭车配置参数保存 function shuttleParamSave() { $.ajax({ url: baseUrl+ "/shuttle/runSpeed/" + $('input[name="shuttleSelect"]:checked').val(), headers: {'token': localStorage.getItem('token')}, method: 'POST', data: { runSpeed: $("#runSpeed").val(), chargeLine: $("#chargeLine").val(), }, success: function (res) { if (res.code === 200){ layer.msg("配置已保存", {icon: 1,}); } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } }); } // 详情操作 ------------------------------------------------------------------------- var layerDetl; $(document).on('dblclick ','#shuttle-msg-table tr', function () { var shuttleNo = $(this).children("td").eq(0).html(); if (shuttleNo !== null && shuttleNo !== "") { layerDetl = layer.open({ type: 1, title: false, shadeClose: true, offset: 'rt', anim: 5, shade: [0], area: ['340px', '255px'], closeBtn: 0, content: $("#shuttle-detl"), success: function(layero, index){ $.ajax({ url: baseUrl+ "/shuttle/table/shuttle/state", headers: {'token': localStorage.getItem('token')}, method: 'POST', success: function (res) { if (res.code === 200){ var table = res.data; for (var i=1;i<=table.length;i++){ if (shuttleNo == table[i-1].shuttleNo) { $('#shuttleNo').val(shuttleNo); $('#workNo').val(table[i-1].taskNo); $('#pakMk').val(table[i-1].pakMk$); $('#token').val(table[i-1].token); } } } else if (res.code === 403){ window.location.href = baseUrl+"/login"; } else { console.log(res.msg); } } }); }, end: function () { $('#shuttleNo').val(""); $('#workNo').val(""); $('#pakMk').val(""); $('#token').val(""); } }) } }); $(document).on('click ','#cancel', function () { $('#shuttleNo').val(""); $('#workNo').val(""); $('#pakMk').val(""); $('#token').val(""); layer.close(layerDetl); }) </script>