diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/controller/TwoFloorAgvController.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/controller/TwoFloorAgvController.java new file mode 100644 index 0000000..8995b4e --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/controller/TwoFloorAgvController.java @@ -0,0 +1,38 @@ +package org.nl.acs.agv.controller; + +import org.nl.acs.agv.service.impl.TwoFloorAgvStatusService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 二楼AGV状态控制器 + * 提供HTTP接口获取AGV状态信息 + */ +@RestController +@RequestMapping("/api/agv/two-floor") +public class TwoFloorAgvController { + + @Autowired + private TwoFloorAgvStatusService agvStatusService; + + /** + * 获取所有二楼AGV状态 + * @return 所有AGV状态列表 + */ + @GetMapping("/status") + public Object getAllAgvStatus() { + return agvStatusService.getAllAgvStatus(); + } + + /** + * 获取单个AGV状态 + * @param vehicleCode AGV车辆代码 + * @return AGV状态信息 + */ + @GetMapping("/status/{vehicleCode}") + public Object getAgvStatus(String vehicleCode) { + return agvStatusService.getAgvStatus(vehicleCode); + } +} diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/domain/TwoFloorAgvStatus.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/domain/TwoFloorAgvStatus.java new file mode 100644 index 0000000..9c928af --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/domain/TwoFloorAgvStatus.java @@ -0,0 +1,131 @@ +package org.nl.acs.agv.domain; + +import lombok.Data; + +/** + * 二楼AGV状态数据模型 + * 用于存储和传输AGV的实时状态信息 + */ +@Data +public class TwoFloorAgvStatus { + + /** + * AGV车辆代码 + */ + private String vehicle_code; + + /** + * AGV状态 + */ + private String status; + + /** + * AGV状态文本描述 + */ + private String status_text; + + /** + * 当前任务代码 + */ + private String task_code; + + /** + * 当前指令代码 + */ + private String inst_code; + + /** + * 当前阶段值 + */ + private Integer phase; + + /** + * 当前阶段名称 + */ + private String phase_name; + + /** + * 当前位置 + */ + private String address; + + /** + * 物料类型 + */ + private String material_type; + + /** + * 物料数量 + */ + private Integer quantity; + + /** + * 开始设备代码 + */ + private String start_device_code; + + /** + * 下一个设备代码 + */ + private String next_device_code; + + /** + * 是否有错误 + */ + private Boolean is_error; + + /** + * 错误代码 + */ + private String error_code; + + /** + * 错误信息 + */ + private String error_message; + + /** + * 卡住的Action + */ + private String error_action; + + /** + * 卡住的Mode + */ + private String error_mode; + + /** + * 电量 + */ + private Integer electric_qty; + + /** + * X坐标 + */ + private Integer x; + + /** + * Y坐标 + */ + private Integer y; + + /** + * 角度 + */ + private Integer angle; + + /** + * 区域 + */ + private Integer region; + + /** + * 是否在线 + */ + private Boolean is_online; + + /** + * 三色灯状态 + */ + private Integer status_light; +} \ No newline at end of file diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/service/impl/TwoFloorAgvStatusService.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/service/impl/TwoFloorAgvStatusService.java new file mode 100644 index 0000000..727ec94 --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/agv/service/impl/TwoFloorAgvStatusService.java @@ -0,0 +1,178 @@ +package org.nl.acs.agv.service.impl; + +import org.nl.acs.agv.domain.TwoFloorAgvStatus; +import org.nl.acs.device_driver.agv.utils.TwoAgvPhase; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 二楼AGV状态管理服务 + * 负责管理和更新AGV状态,通过HTTP接口提供状态查询 + */ +@Service +public class TwoFloorAgvStatusService { + + @Autowired + private TwoAgvPhase twoAgvPhase; + + /** + * 存储AGV状态信息,key为AGV车辆代码 + */ + private Map agvStatusMap = new HashMap<>(); + + /** + * 初始化AGV状态 + */ + public TwoFloorAgvStatusService() { + // 初始化二楼的4台AGV + for (int i = 1; i <= 4; i++) { + TwoFloorAgvStatus agvStatus = new TwoFloorAgvStatus(); + String vehicleCode = String.format("AGV%02d", i); + agvStatus.setVehicle_code(vehicleCode); + agvStatus.setStatus("idle"); + agvStatus.setStatus_text("空闲"); + agvStatus.setIs_error(false); + agvStatus.setIs_online(true); + agvStatusMap.put(vehicleCode, agvStatus); + } + } + + /** + * 更新AGV状态 + * @param agvStatus AGV状态信息 + */ + public void updateAgvStatus(TwoFloorAgvStatus agvStatus) { + if (agvStatus == null || agvStatus.getVehicle_code() == null) { + return; + } + + // 处理阶段名称 + if (agvStatus.getPhase() != null) { + String phaseName = twoAgvPhase.getPhaseName(agvStatus.getPhase()); + agvStatus.setPhase_name(phaseName); + } + + // 处理状态文本 + this.handleStatusText(agvStatus); + + // 更新状态 + agvStatusMap.put(agvStatus.getVehicle_code(), agvStatus); + + // 推送状态更新 + this.pushAgvStatusUpdate(); + } + + /** + * 处理AGV状态文本 + */ + private void handleStatusText(TwoFloorAgvStatus agvStatus) { + switch (agvStatus.getStatus()) { + case "running": + agvStatus.setStatus_text("运行中"); + break; + case "idle": + agvStatus.setStatus_text("空闲"); + break; + case "error": + agvStatus.setStatus_text("异常"); + agvStatus.setIs_error(true); + break; + case "charging": + agvStatus.setStatus_text("充电中"); + break; + default: + agvStatus.setStatus_text("未知"); + break; + } + } + + /** + * 获取单个AGV状态 + * @param vehicleCode AGV车辆代码 + * @return AGV状态信息 + */ + public TwoFloorAgvStatus getAgvStatus(String vehicleCode) { + return agvStatusMap.get(vehicleCode); + } + + /** + * 获取所有AGV状态 + * @return 所有AGV状态列表 + */ + public List getAllAgvStatus() { + return new ArrayList<>(agvStatusMap.values()); + } + + /** + * 更新AGV状态后不需要推送,由前端通过HTTP接口主动查询 + */ + public void pushAgvStatusUpdate() { + // 改为HTTP接口后,不再需要主动推送 + // 前端会通过定时请求获取最新状态 + } + + /** + * 更新AGV任务信息 + */ + public void updateAgvTaskInfo(String vehicleCode, String taskCode, String instCode) { + TwoFloorAgvStatus agvStatus = agvStatusMap.get(vehicleCode); + if (agvStatus != null) { + agvStatus.setTask_code(taskCode); + agvStatus.setInst_code(instCode); + this.pushAgvStatusUpdate(); + } + } + + /** + * 更新AGV阶段信息 + */ + public void updateAgvPhase(String vehicleCode, Integer phase) { + TwoFloorAgvStatus agvStatus = agvStatusMap.get(vehicleCode); + if (agvStatus != null) { + agvStatus.setPhase(phase); + agvStatus.setPhase_name(twoAgvPhase.getPhaseName(phase)); + this.pushAgvStatusUpdate(); + } + } + + /** + * 更新AGV错误信息 + */ + public void updateAgvError(String vehicleCode, String errorCode, String errorMessage, String errorAction, String errorMode) { + TwoFloorAgvStatus agvStatus = agvStatusMap.get(vehicleCode); + if (agvStatus != null) { + agvStatus.setIs_error(true); + agvStatus.setError_code(errorCode); + agvStatus.setError_message(errorMessage); + agvStatus.setError_action(errorAction); + agvStatus.setError_mode(errorMode); + agvStatus.setStatus("error"); + agvStatus.setStatus_text("异常"); + this.pushAgvStatusUpdate(); + } + } + + /** + * 清除AGV错误信息 + */ + public void clearAgvError(String vehicleCode) { + TwoFloorAgvStatus agvStatus = agvStatusMap.get(vehicleCode); + if (agvStatus != null) { + agvStatus.setIs_error(false); + agvStatus.setError_code(null); + agvStatus.setError_message(null); + agvStatus.setError_action(null); + agvStatus.setError_mode(null); + if ("error".equals(agvStatus.getStatus())) { + agvStatus.setStatus("idle"); + agvStatus.setStatus_text("空闲"); + } + this.pushAgvStatusUpdate(); + } + } +} \ No newline at end of file diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/auto/run/TwoNDCSocketConnectionAutoRun.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/auto/run/TwoNDCSocketConnectionAutoRun.java index 00a78c6..b85f293 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/auto/run/TwoNDCSocketConnectionAutoRun.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/auto/run/TwoNDCSocketConnectionAutoRun.java @@ -23,6 +23,7 @@ import org.nl.config.lucene.service.LuceneExecuteLogService; import org.nl.config.lucene.service.dto.LuceneLogDto; import org.nl.system.service.param.ISysParamService; import org.nl.system.service.param.impl.SysParamServiceImpl; +import org.nl.acs.agv.service.impl.TwoFloorAgvStatusService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -68,6 +69,11 @@ public class TwoNDCSocketConnectionAutoRun extends AbstractAutoRunnable { AutoRunService autoRunService; @Autowired LuceneExecuteLogService luceneExecuteLogService; + + /** + * 二楼AGV状态管理服务 + */ + private TwoFloorAgvStatusService agvStatusService; public TwoNDCSocketConnectionAutoRun() { @@ -93,6 +99,9 @@ public class TwoNDCSocketConnectionAutoRun extends AbstractAutoRunnable { DeviceAppService deviceAppService = SpringContextHolder.getBean(DeviceAppService.class); DeviceService deviceService = SpringContextHolder.getBean(DeviceService.class); DeviceExecuteLogService logServer = SpringContextHolder.getBean(DeviceExecuteLogService.class); + + // 初始化AGV状态管理服务 + agvStatusService = SpringContextHolder.getBean(TwoFloorAgvStatusService.class); try { log.info("2楼1区域AGV系统链接开始"); diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/agv/ndctwo/AgvNdcTwoDeviceDriver.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/agv/ndctwo/AgvNdcTwoDeviceDriver.java index 8d82b02..f15dd5a 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/agv/ndctwo/AgvNdcTwoDeviceDriver.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device_driver/agv/ndctwo/AgvNdcTwoDeviceDriver.java @@ -44,6 +44,8 @@ import org.nl.config.lucene.service.dto.LuceneLogDto; import org.nl.config.thread.ThreadPoolExecutorUtil; import org.nl.system.service.param.ISysParamService; import org.nl.config.SpringContextHolder; +import org.nl.acs.agv.domain.TwoFloorAgvStatus; +import org.nl.acs.agv.service.impl.TwoFloorAgvStatusService; import java.util.HashMap; import java.util.LinkedHashMap; @@ -71,6 +73,11 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic LuceneExecuteLogService luceneExecuteLogService = SpringContextHolder.getBean(LuceneExecuteLogService.class); TwoAgvPhase twoAgvPhase = new TwoAgvPhase(); + /** + * 二楼AGV状态管理服务 + */ + private TwoFloorAgvStatusService agvStatusService = SpringContextHolder.getBean(TwoFloorAgvStatusService.class); + String error_code = "0"; int agvaddr = 0; int agvaddr_copy = 0; @@ -100,6 +107,163 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic this.error_message = error_message; } + /** + * 更新AGV状态信息到TwoFloorAgvStatusService + * @param arr socket数据数组 + * @param carno 车号 + * @param phase 当前阶段 + * @param ikey 任务号 + * @param agvaddr 站点号 + * @param inst 指令信息 + * @param task 任务信息 + */ + private void updateAgvStatusToService(int[] arr, int carno, int phase, int ikey, int agvaddr, Instruction inst, TaskDto task) { + if (carno == 0) { + return; + } + + try { + // 创建AGV状态对象 + TwoFloorAgvStatus agvStatus = new TwoFloorAgvStatus(); + + // 设置AGV车辆代码 + String vehicleCode = String.format("AGV%02d", carno); + agvStatus.setVehicle_code(vehicleCode); + + // 设置状态 + String status = "running"; + if (iserror) { + status = "error"; + } else if (phase == 0x67 || phase == 0x71 || phase == 0x72 || phase == 0x73 || phase == 0x74 || phase == 0x75) { + status = "idle"; + } + agvStatus.setStatus(status); + + // 设置任务信息 + if (inst != null) { + agvStatus.setTask_code(inst.getTask_code()); + agvStatus.setInst_code(String.valueOf(ikey)); + } + + // 设置阶段信息 + agvStatus.setPhase(phase); + agvStatus.setPhase_name(twoAgvPhase.getPhaseName(phase)); + + // 设置位置信息 + String address = deviceService.queryDeviceCodeByAddress(agvaddr); + agvStatus.setAddress(address); + + // 设置错误信息 + agvStatus.setIs_error(iserror); + agvStatus.setError_code(error_code); + agvStatus.setError_message(error_message); + + // 设置电量 + agvStatus.setElectric_qty(electric_qty); + + // 设置坐标和角度 + agvStatus.setX(x); + agvStatus.setY(y); + agvStatus.setAngle(angle); + + // 设置区域 + agvStatus.setRegion(region); + + // 设置在线状态 + agvStatus.setIs_online(isonline); + + // 更新到服务 + agvStatusService.updateAgvStatus(agvStatus); + } catch (Exception e) { + log.error("更新AGV状态到服务失败: {}", e.getMessage()); + } + } + + /** + * 记录任务卡住原因 + * @param carno 车号 + * @param device_code 设备号 + * @param deviceDriver 设备驱动 + * @param message 错误信息 + */ + private void recordTaskStuckReason(int carno, String device_code, Object deviceDriver, String message) { + try { + // 解析错误信息,提取action和mode不满足的原因 + String error_action = null; + String error_mode = null; + + // 根据不同设备驱动类型,提取action和mode信息 + if (deviceDriver instanceof WasteFoilWeighingStationDriver) { + WasteFoilWeighingStationDriver driver = (WasteFoilWeighingStationDriver) deviceDriver; + if (driver.getAction() != 1) { + error_action = "动作信号:" + driver.getAction() + "不满足条件"; + } + if (driver.getMode() != 2) { + error_mode = "模式:" + driver.getMode() + "不满足条件"; + } + } else if (deviceDriver instanceof StandardOrdinarySiteDeviceDriver) { + StandardOrdinarySiteDeviceDriver driver = (StandardOrdinarySiteDeviceDriver) deviceDriver; + if (driver.getAction() != 1) { + error_action = "动作信号:" + driver.getAction() + "不满足条件"; + } + if (driver.getMode() != 2) { + error_mode = "模式:" + driver.getMode() + "不满足条件"; + } + } else if (deviceDriver instanceof HongXiangStationDeviceDriver) { + HongXiangStationDeviceDriver driver = (HongXiangStationDeviceDriver) deviceDriver; + if (driver.getAction() != 1) { + error_action = "动作信号:" + driver.getAction() + "不满足条件"; + } + if (driver.getMode() != 2) { + error_mode = "模式:" + driver.getMode() + "不满足条件"; + } + } else if (deviceDriver instanceof ManipulatorAgvStationDeviceDriver) { + ManipulatorAgvStationDeviceDriver driver = (ManipulatorAgvStationDeviceDriver) deviceDriver; + if (driver.getAction() != 1) { + error_action = "动作信号:" + driver.getAction() + "不满足条件"; + } + if (driver.getMode() != 2) { + error_mode = "模式:" + driver.getMode() + "不满足条件"; + } + } else if (deviceDriver instanceof RangingStationsDeviceDriver) { + RangingStationsDeviceDriver driver = (RangingStationsDeviceDriver) deviceDriver; + if (driver.getAction() != 1) { + error_action = "动作信号:" + driver.getAction() + "不满足条件"; + } + if (driver.getMode() != 2) { + error_mode = "模式:" + driver.getMode() + "不满足条件"; + } + } else if (deviceDriver instanceof StandardInspectSiteDeviceDriver) { + StandardInspectSiteDeviceDriver driver = (StandardInspectSiteDeviceDriver) deviceDriver; + if (driver.getAction() != 1) { + error_action = "动作信号:" + driver.getAction() + "不满足条件"; + } + if (driver.getMode() != 2) { + error_mode = "模式:" + driver.getMode() + "不满足条件"; + } + } + + // 创建AGV状态对象 + TwoFloorAgvStatus agvStatus = new TwoFloorAgvStatus(); + + // 设置AGV车辆代码 + String vehicleCode = String.format("AGV%02d", carno); + agvStatus.setVehicle_code(vehicleCode); + + // 设置错误信息 + agvStatus.setIs_error(true); + agvStatus.setStatus("error"); + agvStatus.setError_message(message); + agvStatus.setError_action(error_action); + agvStatus.setError_mode(error_mode); + + // 更新到服务 + agvStatusService.updateAgvStatus(agvStatus); + } catch (Exception e) { + log.error("记录任务卡住原因失败: {}", e.getMessage()); + } + } + public synchronized void processSocket(int[] arr) throws Exception { device_code = this.getDeviceCode(); byte[] data = null; @@ -180,6 +344,9 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic //废箔称重位 WasteFoilWeighingStationDriver wasteFoilWeighingStationDriver; + // 更新AGV状态信息到TwoFloorAgvStatusService + updateAgvStatusToService(arr, carno, phase, ikey, agvaddr, inst, task); + if (phase == 0x02) { if (ObjectUtil.isEmpty(inst)) { log.info("未找到指令号{}对应的指令", ikey); @@ -301,6 +468,8 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic .build(); logDto.setLog_level(4); luceneExecuteLogService.deviceExecuteLog(logDto); + // 记录任务卡住原因 + recordTaskStuckReason(carno, device_code, standardInspectSiteDeviceDriver, message); } } else if (device.getDeviceDriver() instanceof ManipulatorAgvStationDeviceDriver) { manipulatorAgvStationDeviceDriver = (ManipulatorAgvStationDeviceDriver) device.getDeviceDriver(); @@ -319,12 +488,15 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic luceneExecuteLogService.deviceExecuteLog(logDto); } else { log.info("设备{},动作信号{} ,不满足取货条件,指令号{}", manipulatorAgvStationDeviceDriver.getDeviceCode(), manipulatorAgvStationDeviceDriver.getAction(), ikey); + message = "设备号:" + device_code + "动作信号:" + manipulatorAgvStationDeviceDriver.getAction() + ",指令号:" + ikey + "不满足取货条件"; LuceneLogDto logDto = LuceneLogDto.builder() .device_code(manipulatorAgvStationDeviceDriver.getDeviceCode()) .content("未给agv进入信号原因是:" + manipulatorAgvStationDeviceDriver.getDevice_code() + "动作信号不为1") .build(); logDto.setLog_level(4); luceneExecuteLogService.deviceExecuteLog(logDto); + // 记录任务卡住原因 + recordTaskStuckReason(carno, device_code, manipulatorAgvStationDeviceDriver, message); } } else if (device.getDeviceDriver() instanceof HongXiangStationDeviceDriver) { hongXiangStationDeviceDriver = (HongXiangStationDeviceDriver) device.getDeviceDriver(); @@ -458,6 +630,8 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic .build(); logDto.setLog_level(4); luceneExecuteLogService.deviceExecuteLog(logDto); + // 记录任务卡住原因 + recordTaskStuckReason(carno, device_code, wasteFoilWeighingStationDriver, message); } } else { data = ndcAgvService.sendAgvTwoModeInst(phase, index, 0, 0, 0); @@ -863,6 +1037,8 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic .build(); logDto.setLog_level(4); luceneExecuteLogService.deviceExecuteLog(logDto); + // 记录任务卡住原因 + recordTaskStuckReason(carno, device_code, hongXiangStationDeviceDriver, message); } } else if (device.getDeviceDriver() instanceof StandardInspectSiteDeviceDriver) { standardInspectSiteDeviceDriver = (StandardInspectSiteDeviceDriver) device.getDeviceDriver(); diff --git a/acs2/nladmin-ui/src/router/routers.js b/acs2/nladmin-ui/src/router/routers.js index 99a4018..8dad58f 100644 --- a/acs2/nladmin-ui/src/router/routers.js +++ b/acs2/nladmin-ui/src/router/routers.js @@ -45,9 +45,9 @@ export const constantRouterMap = [ children: [ { path: 'dashboard', - component: (resolve) => require(['@/views/monitor/server/index'], resolve), + component: (resolve) => require(['@/views/screen/twoFloorAgvScreen'], resolve), name: 'Dashboard', - meta: { title: i18n.t('auto.common.home'), icon: 'index', affix: true, noCache: true } + meta: { title: '二楼AGV看板', icon: 'index', affix: true, noCache: true } } ] }, diff --git a/acs2/nladmin-ui/src/views/screen/twoFloorAgvScreen.vue b/acs2/nladmin-ui/src/views/screen/twoFloorAgvScreen.vue new file mode 100644 index 0000000..ff0837c --- /dev/null +++ b/acs2/nladmin-ui/src/views/screen/twoFloorAgvScreen.vue @@ -0,0 +1,387 @@ + + + + +