From d722680273a4238cc1505e305eb96362646b0c83 Mon Sep 17 00:00:00 2001 From: luoyifan Date: Mon, 7 Jul 2025 00:11:25 +0800 Subject: [PATCH] =?UTF-8?q?ServerView=20=E6=9C=8D=E5=8A=A1=E5=99=A8?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86=E3=80=81ConnectEnv=20?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E7=8A=B6=E6=80=81=E5=88=86=E7=A6=BB=E3=80=81?= =?UTF-8?q?Authorization=20=E6=9C=8D=E5=8A=A1=E6=8E=88=E6=9D=83=E3=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/galaxis/rcs/ptr/PtrAgvItem.java | 77 +++++------ .../src/main/java/com/yvan/entity/AgvStatusVo.java | 89 ++++++++---- .../yvan/entity/ServerAuthorizationConfigVo.java | 12 ++ .../main/java/com/yvan/entity/ServerStatusVo.java | 96 +++++++++++++ .../main/java/com/yvan/logisticsEnv/EnvConfig.java | 2 - .../com/yvan/logisticsModel/LogisticsRuntime.java | 28 ++-- .../logisticsModel/LogisticsRuntimeService.java | 7 + .../java/com/yvan/logisticsModel/RuntimeState.java | 56 -------- .../yvan/pusher/FrontendMessagePushService.java | 8 +- .../main/java/com/yvan/redis/LccRedisService.java | 1 - .../autoconfigure/LccConfigProperties.java | 10 ++ .../yvan/workbench/controller/AuthController.java | 29 ++++ .../yvan/workbench/controller/LccController.java | 140 ++++++++++--------- .../yvan/workbench/controller/LccModelManager.java | 11 +- .../workbench/controller/ServerController.java | 151 +++++++++++++++++++++ .../com/yvan/workbench/service/LccMapService.java | 2 +- servo/src/main/resources/application-dev.yml | 20 +-- 17 files changed, 513 insertions(+), 226 deletions(-) create mode 100644 servo/src/main/java/com/yvan/entity/ServerAuthorizationConfigVo.java create mode 100644 servo/src/main/java/com/yvan/entity/ServerStatusVo.java delete mode 100644 servo/src/main/java/com/yvan/logisticsModel/RuntimeState.java create mode 100644 servo/src/main/java/com/yvan/workbench/controller/AuthController.java create mode 100644 servo/src/main/java/com/yvan/workbench/controller/ServerController.java diff --git a/servo/src/main/java/com/galaxis/rcs/ptr/PtrAgvItem.java b/servo/src/main/java/com/galaxis/rcs/ptr/PtrAgvItem.java index a4f350e..5bbbc77 100644 --- a/servo/src/main/java/com/galaxis/rcs/ptr/PtrAgvItem.java +++ b/servo/src/main/java/com/galaxis/rcs/ptr/PtrAgvItem.java @@ -19,6 +19,7 @@ import lombok.Getter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.clever.core.Conv; +import org.clever.core.json.JsonWrapper; import org.clever.data.redis.Redis; import org.clever.data.redis.RedisAdmin; @@ -399,27 +400,18 @@ public abstract class PtrAgvItem extends ExecutorItem { updateRedisStatus(); } + @SneakyThrows public void updateRedisStatus() { String statusKey = getRedisKey("status"); - Map statusMap = new HashMap<>(); - statusMap.put("x", String.valueOf(x)); - statusMap.put("y", String.valueOf(y)); - statusMap.put("z", String.valueOf(z)); - statusMap.put("logicX", String.valueOf(logicX)); - statusMap.put("logicY", String.valueOf(logicY)); - statusMap.put("direction", String.valueOf(direction)); - statusMap.put("orientation", String.valueOf(orientation)); - statusMap.put("soc", this.battery == null ? "-1" : String.valueOf(this.battery.SOC)); - statusMap.put("mode", Conv.asString(this.__taskMode)); - statusMap.put("taskStatus", getTaskStatus()); - + var state = this.getState(); + var statusMap = new JsonWrapper(state).getInnerMap(); redis.hPutAll(statusKey, statusMap); } public void handleHeartbeat(AmrHeartbeatMessage heartbeat) { // 更新在线状态 String aliveKey = getRedisKey("alive"); - redis.vSet(aliveKey, "1"); + redis.vSet(aliveKey, this.runtime.serverId); redis.kExpire(aliveKey, 5); // 5秒过期 // 更新状态信息 @@ -850,36 +842,37 @@ public abstract class PtrAgvItem extends ExecutorItem { public AgvStatusVo getState() { var ptr = this; - int taskCompleted = 0; - int taskTotalCount = 0; + + var state = new AgvStatusVo(); + state.setId(ptr.id); + state.setType(ptr.getT()); + state.setIsOnline(ptr.isOnline); + state.setIsSystemManaged(ptr.isSystemManaged); + + state.setX(ptr.x); + state.setY(ptr.y); + state.setZ(ptr.z); + state.setLogicX(ptr.logicX); + state.setLogicY(ptr.logicY); + + state.setDirection(PathUtils.getDirectionByArmDirection(ptr.direction)); + state.setOrientation(ptr.orientation); + state.setSoc(ptr.battery == null ? -1 : ptr.battery.SOC); + state.setMode(ptr.get__taskMode()); + state.setTaskStatus(ptr.getTaskStatus()); + + state.setIsBlocked(ptr.isBlocked); if (ptr.planTaskSequence != null) { - taskCompleted = ptr.planTaskSequence.completedCount(); - taskTotalCount = ptr.planTaskSequence.taskTotalCount(); + state.setTaskCompleted(ptr.planTaskSequence.completedCount()); + state.setTaskTotalCount(ptr.planTaskSequence.taskTotalCount()); + state.setBizTaskId(ptr.planTaskSequence.bizTask.getBizTaskId()); + state.setBizTaskType(BizTaskType.fromString(ptr.planTaskSequence.bizTask.getBizType())); + state.setBizTaskStatus(BizTaskStatus.fromString(ptr.planTaskSequence.bizTask.getBizTaskStatus())); + state.setBizTaskFrom(ptr.planTaskSequence.bizTask.getTaskFrom()); + state.setBizTaskTo(ptr.planTaskSequence.bizTask.getTaskTo()); + state.setBizLpn(ptr.planTaskSequence.bizTask.getLpn()); } - return new AgvStatusVo( - ptr.id, - ptr.getT(), - ptr.isOnline, - ptr.isSystemManaged, - ptr.x, - ptr.y, - ptr.z, - ptr.logicX, - ptr.logicY, - PathUtils.getDirectionByArmDirection(ptr.direction), - ptr.orientation, - ptr.battery == null ? 0 : ptr.battery.SOC, - ptr.get__taskMode(), - ptr.getTaskStatus(), - ptr.isBlocked, - taskCompleted, - taskTotalCount, - ptr.planTaskSequence == null ? null : ptr.planTaskSequence.bizTask.getBizTaskId(), - ptr.planTaskSequence == null ? null : BizTaskType.fromString(ptr.planTaskSequence.bizTask.getBizType()), - ptr.planTaskSequence == null ? null : BizTaskStatus.fromString(ptr.planTaskSequence.bizTask.getBizTaskStatus()), - ptr.planTaskSequence == null ? null : ptr.planTaskSequence.bizTask.getTaskFrom(), - ptr.planTaskSequence == null ? null : ptr.planTaskSequence.bizTask.getTaskTo(), - ptr.planTaskSequence == null ? null : ptr.planTaskSequence.bizTask.getLpn() - ); + + return state; } } diff --git a/servo/src/main/java/com/yvan/entity/AgvStatusVo.java b/servo/src/main/java/com/yvan/entity/AgvStatusVo.java index 07cd6c0..6a7782e 100644 --- a/servo/src/main/java/com/yvan/entity/AgvStatusVo.java +++ b/servo/src/main/java/com/yvan/entity/AgvStatusVo.java @@ -4,30 +4,71 @@ import com.galaxis.rcs.common.enums.BizTaskStatus; import com.galaxis.rcs.common.enums.BizTaskType; import com.galaxis.rcs.common.enums.LCCDirection; import com.galaxis.rcs.ptr.AmrTaskMode; +import lombok.Data; -public record AgvStatusVo(String id, - String type, - Boolean isOnline, - Boolean isSystemManaged, - Double x, - Double y, - Double z, - Integer logicX, - Integer logicY, - LCCDirection direction, - Double orientation, - Double soc, - AmrTaskMode mode, - String taskStatus, - Boolean isBlocked, - Integer taskCompleted, - Integer taskTotalCount, - // 业务任务ID - Long bizTaskId, - BizTaskType bizTaskType, - BizTaskStatus bizTaskStatus, - String bizTaskFrom, - String bizTaskTo, - String bizLpn) { +@Data +public class AgvStatusVo { + private String id; + private String type; + private Boolean isOnline; + private Boolean isSystemManaged; + private Double x; + private Double y; + private Double z; + private Integer logicX; + private Integer logicY; + + private LCCDirection direction; + private Double orientation; + private Double soc; + private AmrTaskMode mode; + private String taskStatus; + + private Boolean isBlocked; + private Integer taskCompleted; + private Integer taskTotalCount; + private Long bizTaskId; + private BizTaskType bizTaskType; + + private BizTaskStatus bizTaskStatus; + private String bizTaskFrom; + private String bizTaskTo; + private String bizLpn; + + private String virtualLocationAt; + private String virtualExecutorPayload; + + public void copyFromExceptVirtual(AgvStatusVo state) { + if (state == null) { + return; + } + this.id = state.id; + this.type = state.type; + this.isOnline = state.isOnline; + this.isSystemManaged = state.isSystemManaged; + + this.x = state.x; + this.y = state.y; + this.z = state.z; + this.logicX = state.logicX; + this.logicY = state.logicY; + + this.direction = state.direction; + this.orientation = state.orientation; + this.soc = state.soc; + this.mode = state.mode; + this.taskStatus = state.taskStatus; + + this.isBlocked = state.isBlocked; + this.taskCompleted = state.taskCompleted; + this.taskTotalCount = state.taskTotalCount; + this.bizTaskId = state.bizTaskId; + this.bizTaskType = state.bizTaskType; + + this.bizTaskStatus = state.bizTaskStatus; + this.bizTaskFrom = state.bizTaskFrom; + this.bizTaskTo = state.bizTaskTo; + this.bizLpn = state.bizLpn; + } } diff --git a/servo/src/main/java/com/yvan/entity/ServerAuthorizationConfigVo.java b/servo/src/main/java/com/yvan/entity/ServerAuthorizationConfigVo.java new file mode 100644 index 0000000..e96c466 --- /dev/null +++ b/servo/src/main/java/com/yvan/entity/ServerAuthorizationConfigVo.java @@ -0,0 +1,12 @@ +package com.yvan.entity; + +import com.yvan.workbench.autoconfigure.LccConfigProperties; +import lombok.Data; + +@Data +public class ServerAuthorizationConfigVo { + private String serverId; + private String authorizationCode; + private Long expirationTime; + private LccConfigProperties.FrontendMqtt frontendMqtt; +} diff --git a/servo/src/main/java/com/yvan/entity/ServerStatusVo.java b/servo/src/main/java/com/yvan/entity/ServerStatusVo.java new file mode 100644 index 0000000..40b0570 --- /dev/null +++ b/servo/src/main/java/com/yvan/entity/ServerStatusVo.java @@ -0,0 +1,96 @@ +package com.yvan.entity; + +import com.yvan.logisticsEnv.EnvConfig; +import com.yvan.logisticsModel.SystemMetricsStore; +import org.clever.core.mapper.JacksonMapper; + +import java.util.HashMap; +import java.util.Map; + +/** + * 服务器状态信息 + */ +public class ServerStatusVo { + public String projectUuid; + public Long envId; + public Boolean isVirtual; + public String serverId; + public Boolean isRunning; + + public Long startTime; + public Long stopTime; + public Float timeRate; + public String[] subSystemList; + + public Float cpuUsage; + public Float memoryUsage; + public Float diskIoLoad; + /** + * 空闲内存,单位GB + */ + public Float freeMemory; + /** + * 磁盘剩余空间,单位GB + */ + public Float diskFreeSpace; + + public EnvConfig envConfig; + public String projectLabel; + + public void fillSystemInfos() { + this.cpuUsage = SystemMetricsStore.cpuUsage; + this.memoryUsage = SystemMetricsStore.memoryUsage; + this.freeMemory = SystemMetricsStore.freeMemory; + this.diskIoLoad = SystemMetricsStore.diskIoLoad; + this.diskFreeSpace = SystemMetricsStore.diskFreeSpace; + } + + public Map toMap() { + Map map = new HashMap<>(); + map.put("projectUuid", projectUuid); + map.put("envId", envId); + map.put("isVirtual", isVirtual); + map.put("serverId", serverId); + map.put("isRunning", isRunning); + + map.put("startTime", startTime); + map.put("stopTime", stopTime); + map.put("timeRate", timeRate); + map.put("subSystemList", subSystemList); + map.put("cpuUsage", cpuUsage); + + map.put("memoryUsage", memoryUsage); + map.put("diskIoLoad", diskIoLoad); + map.put("freeMemory", freeMemory); + map.put("diskFreeSpace", diskFreeSpace); + map.put("envConfig", envConfig != null ? JacksonMapper.getInstance().toJson(envConfig) : null); + + map.put("projectLabel", projectLabel); + return map; + } + + public void copyFrom(ServerStatusVo state) { + if (state == null) { + return; + } + this.projectUuid = state.projectUuid; + this.envId = state.envId; + this.isVirtual = state.isVirtual; + this.serverId = state.serverId; + this.isRunning = state.isRunning; + + this.startTime = state.startTime; + this.stopTime = state.stopTime; + this.timeRate = state.timeRate; + this.subSystemList = state.subSystemList; + + this.cpuUsage = state.cpuUsage; + this.memoryUsage = state.memoryUsage; + this.diskIoLoad = state.diskIoLoad; + this.freeMemory = state.freeMemory; + this.diskFreeSpace = state.diskFreeSpace; + + this.envConfig = state.envConfig; + this.projectLabel = state.projectLabel; + } +} diff --git a/servo/src/main/java/com/yvan/logisticsEnv/EnvConfig.java b/servo/src/main/java/com/yvan/logisticsEnv/EnvConfig.java index 59c2c61..5e19ffa 100644 --- a/servo/src/main/java/com/yvan/logisticsEnv/EnvConfig.java +++ b/servo/src/main/java/com/yvan/logisticsEnv/EnvConfig.java @@ -9,8 +9,6 @@ public class EnvConfig implements Serializable { private MqttConfig mqtt; - private MqttConfig frontendMqtt; - private MysqlConfig mysql; private RedisConfig redis; diff --git a/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java b/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java index 53b41ee..6dc2a5b 100644 --- a/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java +++ b/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java @@ -1,14 +1,11 @@ package com.yvan.logisticsModel; import com.galaxis.rcs.common.entity.RcsTaskPlan; -import com.galaxis.rcs.common.enums.BizTaskStatus; -import com.galaxis.rcs.common.enums.BizTaskType; import com.galaxis.rcs.common.enums.PlanTaskType; import com.galaxis.rcs.connector.cl2.Cl2Item; import com.galaxis.rcs.inv.InvManager; import com.galaxis.rcs.plan.PlanTaskSequence; import com.galaxis.rcs.plan.path.NavigationGraph; -import com.galaxis.rcs.plan.path.PathUtils; import com.galaxis.rcs.plan.path.PtrPathPlanner; import com.galaxis.rcs.ptr.AmrMessageHandler; import com.galaxis.rcs.ptr.PtrAgvItem; @@ -18,13 +15,17 @@ import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.yvan.entity.AgvStatusVo; import com.yvan.entity.LccProject; import com.yvan.entity.LccProjectEnv; +import com.yvan.entity.ServerStatusVo; import com.yvan.event.AgvEventManager; import com.yvan.event.AgvEventType; import com.yvan.pusher.FrontendMessagePushService; import com.yvan.redis.LccRedisService; +import com.yvan.workbench.SpringContext; +import com.yvan.workbench.autoconfigure.LccConfigProperties; +import com.yvan.workbench.service.LccMapService; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.clever.core.BannerUtils; import org.clever.core.Conv; @@ -356,9 +357,12 @@ public class LogisticsRuntime { // 启动 MQTT 监听 this.amrMessageHandler.start(this.env.getEnvConfig().getMqtt(), this.serverId); - this.frontendMessagePushService.start(this.env.getEnvConfig().getFrontendMqtt(), this.serverId + "_lcc_send"); this.lccRedisService.start(this.env.getEnvConfig().getRedis(), this.serverId); + var lccMapService = SpringContext.HOLDER.getBean(LccMapService.class); + LccConfigProperties lccConfigProperties = lccMapService.config; + this.frontendMessagePushService.start(lccConfigProperties.getFrontendMqtt(), this.serverId + "_lcc_send"); + // 开启所有机器人的任务处理 Set executorTypes = Sets.newHashSet(); for (ExecutorItem executorItem : executorItemMap.values()) { @@ -376,6 +380,9 @@ public class LogisticsRuntime { // 启动任务指派服务 this.taskDispatchFactory.startPolling(); + + // 推送服务状态 + this.frontendMessagePushService.pushServerState(this.getState()); } public boolean isRunning() { @@ -426,9 +433,11 @@ public class LogisticsRuntime { // 停止 MQTT 监听 this.amrMessageHandler.stop(); - this.frontendMessagePushService.stop(); this.lccRedisService.stop(); + this.frontendMessagePushService.pushServerState(this.getState()); + this.frontendMessagePushService.stop(); + BannerUtils.printConfig(log, "LogisticsRuntime stop.", new String[]{ "projectUUID: " + this.projectUuid, "envId: " + this.envId, @@ -439,8 +448,8 @@ public class LogisticsRuntime { }); } - public RuntimeState getState() { - RuntimeState state = new RuntimeState(); + public ServerStatusVo getState() { + ServerStatusVo state = new ServerStatusVo(); state.projectUuid = this.projectUuid; state.envId = this.envId; @@ -454,6 +463,9 @@ public class LogisticsRuntime { state.subSystemList = this.project.getSubSystemList(); state.fillSystemInfos(); + + state.envConfig = this.env.getEnvConfig(); + state.projectLabel = this.project.getProjectLabel(); return state; } } diff --git a/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntimeService.java b/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntimeService.java index 21c811f..d972348 100644 --- a/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntimeService.java +++ b/servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntimeService.java @@ -6,6 +6,7 @@ import com.yvan.entity.LccProjectEnv; import lombok.SneakyThrows; import java.net.InetAddress; +import java.util.List; import java.util.Map; /** @@ -56,6 +57,12 @@ public class LogisticsRuntimeService { } } + public List getAllRuntimeList() { + synchronized (LOCK) { + return List.copyOf(runtimeMap.values()); + } + } + @SneakyThrows public LogisticsRuntime create(LccProject project, LccProjectEnv env) { synchronized (LOCK) { diff --git a/servo/src/main/java/com/yvan/logisticsModel/RuntimeState.java b/servo/src/main/java/com/yvan/logisticsModel/RuntimeState.java deleted file mode 100644 index cb09e64..0000000 --- a/servo/src/main/java/com/yvan/logisticsModel/RuntimeState.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.yvan.logisticsModel; - -import java.util.HashMap; -import java.util.Map; - -public class RuntimeState { - public String projectUuid; - public long envId; - public boolean isVirtual; - public String serverId; - public boolean isRunning; - - public long startTime; - public long stopTime; - public float timeRate; - public String[] subSystemList; - - public float cpuUsage; - public float memoryUsage; - public float diskIoLoad; - /** - * 空闲内存,单位GB - */ - public float freeMemory; - /** - * 磁盘剩余空间,单位GB - */ - public float diskFreeSpace; - - public void fillSystemInfos() { - this.cpuUsage = SystemMetricsStore.cpuUsage; - this.memoryUsage = SystemMetricsStore.memoryUsage; - this.freeMemory = SystemMetricsStore.freeMemory; - this.diskIoLoad = SystemMetricsStore.diskIoLoad; - this.diskFreeSpace = SystemMetricsStore.diskFreeSpace; - } - - public Map toMap() { - Map map = new HashMap<>(); - map.put("projectUuid", projectUuid); - map.put("envId", envId); - map.put("isVirtual", isVirtual); - map.put("serverId", serverId); - map.put("isRunning", isRunning); - map.put("startTime", startTime); - map.put("stopTime", stopTime); - map.put("timeRate", timeRate); - map.put("subSystemList", subSystemList); - map.put("cpuUsage", cpuUsage); - map.put("memoryUsage", memoryUsage); - map.put("diskIoLoad", diskIoLoad); - map.put("freeMemory", freeMemory); - map.put("diskFreeSpace", diskFreeSpace); - return map; - } -} diff --git a/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java b/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java index 00e4294..0133420 100644 --- a/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java +++ b/servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java @@ -2,8 +2,10 @@ package com.yvan.pusher; import com.yvan.entity.AgvStatusVo; import com.yvan.entity.BasLocationVo; +import com.yvan.entity.ServerStatusVo; import com.yvan.logisticsEnv.EnvConfig; import com.yvan.logisticsModel.LogisticsRuntime; +import com.yvan.workbench.autoconfigure.LccConfigProperties; import lombok.Getter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -24,7 +26,7 @@ import java.util.concurrent.locks.ReentrantLock; @Slf4j public class FrontendMessagePushService implements MqttCallback { - private volatile EnvConfig.MqttConfig mqttConfig; + private volatile LccConfigProperties.FrontendMqtt mqttConfig; private volatile String clientId; private volatile MqttClient mqttClient; private final LogisticsRuntime runtime; @@ -51,7 +53,7 @@ public class FrontendMessagePushService implements MqttCallback { * 启动MQTT服务 */ @SneakyThrows - public void start(EnvConfig.MqttConfig mqttConfig, String clientId) { + public void start(LccConfigProperties.FrontendMqtt mqttConfig, String clientId) { this.mqttConfig = mqttConfig; this.clientId = clientId; connectionLock.lock(); @@ -138,7 +140,7 @@ public class FrontendMessagePushService implements MqttCallback { * * @param statusData 状态数据 */ - public void pushServerState(Map statusData) { + public void pushServerState(ServerStatusVo statusData) { String topic = buildTopic("server"); publishJson(topic, statusData); } diff --git a/servo/src/main/java/com/yvan/redis/LccRedisService.java b/servo/src/main/java/com/yvan/redis/LccRedisService.java index 5349b31..4c79e08 100644 --- a/servo/src/main/java/com/yvan/redis/LccRedisService.java +++ b/servo/src/main/java/com/yvan/redis/LccRedisService.java @@ -81,7 +81,6 @@ public class LccRedisService { redis.vSet(aliveKey, this.serverId); redis.kExpire(aliveKey, 15); // 15秒过期 - heartbeatKeys.put(statusKey, System.currentTimeMillis()); heartbeatKeys.put(aliveKey, System.currentTimeMillis()); } diff --git a/servo/src/main/java/com/yvan/workbench/autoconfigure/LccConfigProperties.java b/servo/src/main/java/com/yvan/workbench/autoconfigure/LccConfigProperties.java index 0d9e092..874669c 100644 --- a/servo/src/main/java/com/yvan/workbench/autoconfigure/LccConfigProperties.java +++ b/servo/src/main/java/com/yvan/workbench/autoconfigure/LccConfigProperties.java @@ -1,5 +1,6 @@ package com.yvan.workbench.autoconfigure; +import com.yvan.logisticsEnv.EnvConfig; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -9,10 +10,19 @@ public class LccConfigProperties { public static final String PREFIX = "lcc"; private String location; private AutoStartItem[] autoStart; + private FrontendMqtt frontendMqtt; @Data public static class AutoStartItem { private String projectUuid; private Long envId; } + + @Data + public static class FrontendMqtt { + private String brokerUrl; + private String username; + private String password; + private String websocket; + } } diff --git a/servo/src/main/java/com/yvan/workbench/controller/AuthController.java b/servo/src/main/java/com/yvan/workbench/controller/AuthController.java new file mode 100644 index 0000000..44877f9 --- /dev/null +++ b/servo/src/main/java/com/yvan/workbench/controller/AuthController.java @@ -0,0 +1,29 @@ +package com.yvan.workbench.controller; + +import com.yvan.entity.ServerAuthorizationConfigVo; +import com.yvan.workbench.SpringContext; +import com.yvan.workbench.autoconfigure.LccConfigProperties; +import com.yvan.workbench.service.LccMapService; +import lombok.SneakyThrows; +import org.clever.core.model.response.R; +import org.clever.web.mvc.annotation.RequestBody; + +import java.net.InetAddress; +import java.util.Map; + +public class AuthController { + + @SneakyThrows + public static R getAuthorizationConfig(@RequestBody Map params) { + var lccMapService = SpringContext.HOLDER.getBean(LccMapService.class); + LccConfigProperties lccConfigProperties = lccMapService.config; + + ServerAuthorizationConfigVo vo = new ServerAuthorizationConfigVo(); + vo.setServerId(InetAddress.getLocalHost().getHostName()); + vo.setAuthorizationCode("N/A"); + vo.setExpirationTime(0L); + vo.setFrontendMqtt(lccConfigProperties.getFrontendMqtt()); + + return R.success(vo); + } +} diff --git a/servo/src/main/java/com/yvan/workbench/controller/LccController.java b/servo/src/main/java/com/yvan/workbench/controller/LccController.java index 78705e1..546fb29 100644 --- a/servo/src/main/java/com/yvan/workbench/controller/LccController.java +++ b/servo/src/main/java/com/yvan/workbench/controller/LccController.java @@ -1,6 +1,6 @@ package com.yvan.workbench.controller; -import com.galaxis.rcs.RCSService; +import com.galaxis.rcs.common.enums.LCCDirection; import com.galaxis.rcs.ptr.PtrAgvItem; import com.google.common.base.Strings; import com.google.common.collect.Lists; @@ -9,6 +9,7 @@ import com.yvan.logisticsModel.LogisticsRuntimeService; import com.yvan.workbench.SpringContext; import com.yvan.workbench.service.LccMapService; import org.clever.core.Conv; +import org.clever.core.json.JsonWrapper; import org.clever.core.model.response.R; import org.clever.data.jdbc.DaoFactory; import org.clever.data.jdbc.QueryDSL; @@ -29,49 +30,6 @@ import static com.galaxis.rcs.common.query.QLccInvLpn.lccInvLpn; public class LccController { static final QueryDSL queryDSL = DaoFactory.getQueryDSL(); - public static R getAllProjects() { - var mapService = SpringContext.HOLDER.getBean(LccMapService.class); - return R.success(mapService.getAllProjects()); - } - - public static R serverStart(@RequestBody Map params) { - String projectUuid = Conv.asString(params.get("projectUUID")); - Long envId = Conv.asLong(params.get("envId")); - - if (Strings.isNullOrEmpty(projectUuid)) { - return R.fail("projectUUID Must not be empty"); - } - if (envId == null || envId < 0) { - return R.fail("envId Must not be empty"); - } - - // 启动 RCS 服务器 - RCSService.serverStart(projectUuid, envId); - - // 启动MFC服务器 / 启动WCS服务器 / 启动PES服务器 等等 - - return R.success("Project started successfully"); - } - - public static R serverStop(@RequestBody Map params) { - String projectUuid = Conv.asString(params.get("projectUUID")); - Long envId = Conv.asLong(params.get("envId")); - - if (Strings.isNullOrEmpty(projectUuid)) { - return R.fail("projectUUID Must not be empty"); - } - if (envId == null || envId < 0) { - return R.fail("envId Must not be empty"); - } - - // 停止RCS服务器 - RCSService.serverStop(projectUuid, envId); - - // 停止MFC服务器 / 停止WCS服务器 / 停止PES服务器 等等 - return R.success("Project stopped successfully"); - } - - public static R loadInv(@RequestBody Map params) { String catalogCode = Conv.asString(params.get("catalogCode")); Long envId = Conv.asLong(params.get("envId")); @@ -111,26 +69,26 @@ public class LccController { return R.success(list); } - public static R loadExecutor(@RequestBody Map params) { - Long envId = Conv.asLong(params.get("envId")); - - if (envId == null) { - return R.fail("envId must not be null"); - } - - var list = queryDSL.select(QueryDslUtils.linkedMap( - lccBasExecutor.executorId, - lccBasExecutor.virtualFloorCode, - lccBasExecutor.virtualLocationAt, - lccBasExecutor.virtualExecutorPayload - )) - .from(lccBasExecutor) - .where(lccBasExecutor.envId.eq(envId)) - .where(lccBasExecutor.isActive.eq(true)) - .fetch(); - - return R.success(list); - } + // public static R loadExecutor(@RequestBody Map params) { + // Long envId = Conv.asLong(params.get("envId")); + // + // if (envId == null) { + // return R.fail("envId must not be null"); + // } + // + // var list = queryDSL.select(QueryDslUtils.linkedMap( + // lccBasExecutor.executorId, + // lccBasExecutor.virtualFloorCode, + // lccBasExecutor.virtualLocationAt, + // lccBasExecutor.virtualExecutorPayload + // )) + // .from(lccBasExecutor) + // .where(lccBasExecutor.envId.eq(envId)) + // .where(lccBasExecutor.isActive.eq(true)) + // .fetch(); + // + // return R.success(list); + // } public static R queryDeviceInfoList(@RequestBody Map params) { String projectUuid = Conv.asString(params.get("projectUUID")); @@ -143,18 +101,56 @@ public class LccController { return R.fail("envId Must not be empty"); } - var runtime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUuid, envId); - if (runtime == null) { - return R.fail("Project environment is not running"); - } + var list = queryDSL.selectFrom(lccBasExecutor) + .where(lccBasExecutor.envId.eq(envId)) + .where(lccBasExecutor.isActive.eq(true)) + .fetch(); - // 拿到所有的车 List agvStatusList = Lists.newArrayList(); - for (var executor : runtime.executorItemMap.values()) { - if (executor instanceof PtrAgvItem) { - agvStatusList.add(((PtrAgvItem) executor).getState()); + + // ==================== 从数据库查询所有的车 ==================== + for (var row : list) { + AgvStatusVo agvStatus = new AgvStatusVo(); + agvStatusList.add(agvStatus); + + agvStatus.setId(row.getExecutorId()); + agvStatus.setVirtualLocationAt(row.getVirtualLocationAt()); + agvStatus.setVirtualExecutorPayload(row.getVirtualExecutorPayload()); + + agvStatus.setIsOnline(false); + + // 1_4:UP + String locationAt = row.getVirtualLocationAt(); + // 将 1_4:UP 转换为 LogicX=1 LogicY=4 Direction=UP + if (!Strings.isNullOrEmpty(locationAt)) { + String[] parts = locationAt.split(":"); + if (parts.length == 2) { + String[] coords = parts[0].split("_"); + if (coords.length == 2) { + agvStatus.setLogicX(Conv.asInteger(coords[0])); + agvStatus.setLogicY(Conv.asInteger(coords[1])); + } + agvStatus.setDirection(LCCDirection.fromString(parts[1])); + } } + + JsonWrapper jw = new JsonWrapper(row.getVirtualExecutorPayload()); + agvStatus.setType(jw.asStr("t")); } + + // ==================== 获取运行时环境中的车状态 ==================== + var runtime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUuid, envId); + if (runtime != null) { + for (var executor : runtime.executorItemMap.values()) { + for (var agv : agvStatusList) { + if (agv.getId().equals(executor.getId())) { + agv.copyFromExceptVirtual(((PtrAgvItem) executor).getState()); + break; + } + } + } + } + return R.success(agvStatusList); } diff --git a/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java b/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java index cec4143..84235f3 100644 --- a/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java +++ b/servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java @@ -32,8 +32,9 @@ public class LccModelManager { private static Map getOtherData(String projectUuid, String projectLabel) { String content = StringUtils.trim(String.format(""" { - "project_uuid": "%s", - "project_label": "%s", + "projectUuid": "%s", + "projectLabel": "%s", + "subSystemList": [ "RCS" ], "project_version": 0, "server": "demo", "Tool": { @@ -126,6 +127,7 @@ public class LccModelManager { public static R addOrUpdateWorld(@RequestBody Map entity) { String projectUuid = Conv.asString(entity.get("projectUuid")); String projectLabel = Conv.asString(entity.get("projectLabel")); + List subSystemList = (List) (entity.get("subSystemList")); String directoryData = Conv.asString(entity.get("directoryData")); String envId = Conv.asString(entity.get("envId")); String otherData = Conv.asString(entity.get("otherData")); @@ -134,9 +136,14 @@ public class LccModelManager { var lccMapService = SpringContext.HOLDER.getBean(LccMapService.class); lccMapService.checkProjectUuid(projectUuid, false); + if (subSystemList == null || subSystemList.isEmpty()) { + subSystemList = List.of("RCS"); + } + LccProject project = new LccProject(); project.setProjectUuid(projectUuid); project.setProjectLabel(projectLabel); + project.setSubSystemList(subSystemList.toArray(String[]::new)); project.setProjectFileLocation(""); project.setDirectoryData(JacksonMapper.getInstance().fromJson(directoryData, LccProject.CatalogGroup[].class)); project.setOtherData(JacksonMapper.getInstance().fromJson(otherData, Map.class)); diff --git a/servo/src/main/java/com/yvan/workbench/controller/ServerController.java b/servo/src/main/java/com/yvan/workbench/controller/ServerController.java new file mode 100644 index 0000000..1a2a7b5 --- /dev/null +++ b/servo/src/main/java/com/yvan/workbench/controller/ServerController.java @@ -0,0 +1,151 @@ +package com.yvan.workbench.controller; + +import com.galaxis.rcs.RCSService; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.yvan.entity.ServerStatusVo; +import com.yvan.logisticsModel.LogisticsRuntimeService; +import com.yvan.workbench.SpringContext; +import com.yvan.workbench.service.LccMapService; +import org.clever.core.Conv; +import org.clever.core.mapper.BeanCopyUtils; +import org.clever.core.model.response.R; +import org.clever.web.mvc.annotation.RequestBody; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +public class ServerController { + public static R queryServerState(@RequestBody Map params) { + String projectUuid = Conv.asString(params.get("projectUUID")); + long envId = Conv.asLong(params.get("envId")); + + var mapService = SpringContext.HOLDER.getBean(LccMapService.class); + + // 从文件夹读取全部 项目+环境 + List list = Lists.newArrayList(); + if (!Strings.isNullOrEmpty(projectUuid)) { + var proj = mapService.getProjectById(projectUuid); + if (proj == null) { + throw new IllegalArgumentException("Project not found: " + projectUuid); + } + if (envId > 0) { + // 读取指定项目+环境 + var env = mapService.getEnvById(projectUuid, envId); + if (env == null) { + throw new IllegalArgumentException("Environment not found: " + envId + " for project: " + projectUuid); + } + ServerStatusVo serverStatus = new ServerStatusVo(); + list.add(serverStatus); + + serverStatus.projectUuid = proj.getProjectUuid(); + serverStatus.projectLabel = proj.getProjectLabel(); + serverStatus.subSystemList = proj.getSubSystemList(); + serverStatus.envId = env.getEnvId(); + serverStatus.isVirtual = env.getIsVirtual(); + serverStatus.envConfig = env.getEnvConfig(); + serverStatus.isRunning = false; + + } else { + // 读取指定项目全部环境 + for (var env : mapService.getAllEnv(projectUuid)) { + if (envId > 0 && env.getEnvId() != envId) { + // 读取指定环境 + continue; + } + + ServerStatusVo serverStatus = new ServerStatusVo(); + list.add(serverStatus); + + serverStatus.projectUuid = proj.getProjectUuid(); + serverStatus.projectLabel = proj.getProjectLabel(); + serverStatus.subSystemList = proj.getSubSystemList(); + serverStatus.envId = env.getEnvId(); + serverStatus.isVirtual = env.getIsVirtual(); + serverStatus.envConfig = env.getEnvConfig(); + serverStatus.isRunning = false; + } + } + + } else { + // 全部项目+环境 + for (var proj : mapService.getAllProjects()) { + for (var env : mapService.getAllEnv(proj.getProjectUuid())) { + ServerStatusVo serverStatus = new ServerStatusVo(); + list.add(serverStatus); + + serverStatus.projectUuid = proj.getProjectUuid(); + serverStatus.projectLabel = proj.getProjectLabel(); + serverStatus.subSystemList = proj.getSubSystemList(); + serverStatus.envId = env.getEnvId(); + serverStatus.isVirtual = env.getIsVirtual(); + serverStatus.envConfig = env.getEnvConfig(); + serverStatus.isRunning = false; + } + } + } + + // 从运行时获取详情数据 + for (var runtime : LogisticsRuntimeService.INSTANCE.getAllRuntimeList()) { + if (Strings.isNullOrEmpty(runtime.projectUuid)) { + continue; // 跳过没有项目UUID的运行时 + } + if (runtime.envId < 0) { + continue; // 跳过没有环境ID的运行时 + } + ServerStatusVo serverStatus = null; + for (ServerStatusVo status : list) { + if (status.projectUuid.equals(runtime.projectUuid) && status.envId.equals(runtime.envId)) { + serverStatus = status; + break; + } + } + if (serverStatus != null) { + serverStatus.copyFrom(runtime.getState()); + } + } + + // list 根据 envId 排序 + list.sort(Comparator.comparingLong(a -> a.envId)); + + return R.success(list); + } + + public static R startServer(@RequestBody Map params) { + String projectUuid = Conv.asString(params.get("projectUUID")); + Long envId = Conv.asLong(params.get("envId")); + + if (Strings.isNullOrEmpty(projectUuid)) { + return R.fail("projectUUID Must not be empty"); + } + if (envId == null || envId < 0) { + return R.fail("envId Must not be empty"); + } + + // 启动 RCS 服务器 + RCSService.serverStart(projectUuid, envId); + + // 启动MFC服务器 / 启动WCS服务器 / 启动PES服务器 等等 + + return R.success("Project started successfully"); + } + + public static R stopServer(@RequestBody Map params) { + String projectUuid = Conv.asString(params.get("projectUUID")); + Long envId = Conv.asLong(params.get("envId")); + + if (Strings.isNullOrEmpty(projectUuid)) { + return R.fail("projectUUID Must not be empty"); + } + if (envId == null || envId < 0) { + return R.fail("envId Must not be empty"); + } + + // 停止RCS服务器 + RCSService.serverStop(projectUuid, envId); + + // 停止MFC服务器 / 停止WCS服务器 / 停止PES服务器 等等 + return R.success("Project stopped successfully"); + } +} diff --git a/servo/src/main/java/com/yvan/workbench/service/LccMapService.java b/servo/src/main/java/com/yvan/workbench/service/LccMapService.java index c0f31c3..99f8b77 100644 --- a/servo/src/main/java/com/yvan/workbench/service/LccMapService.java +++ b/servo/src/main/java/com/yvan/workbench/service/LccMapService.java @@ -19,7 +19,7 @@ import java.util.Objects; @Slf4j public class LccMapService { - private final LccConfigProperties config; + public final LccConfigProperties config; public LccMapService(LccConfigProperties lccConfigProperties) { this.config = lccConfigProperties; diff --git a/servo/src/main/resources/application-dev.yml b/servo/src/main/resources/application-dev.yml index 520871e..1ee0f98 100644 --- a/servo/src/main/resources/application-dev.yml +++ b/servo/src/main/resources/application-dev.yml @@ -9,6 +9,11 @@ lcc: autoStart: # - projectUuid: tw_test # envId: 1 + frontend-mqtt: + brokerUrl: tcp://127.0.0.1:1883 + username: user + password: user + websocket: mqtt://127.0.0.1:7883 mybatis: enable: true @@ -46,21 +51,6 @@ redis: database: 0 password: 'yxt123456' -#mqtt: -# broker-url: 'tcp://180.100.199.56:7097' -# client-id: 'luoyifan' -# username: 'galaxis' -# password: 'Admin1234_' -mqtt: - broker-url: 'tcp://10.10.203.239:1885' - client-id: 'yvan-rcs-dev' - username: 'admin' - password: 'admin' -#mqtt: -# broker-url: 'tcp://10.10.8.31:1883' -# client-id: 'yvan-rcs-dev' -# username: 'admin' -# password: 'admin' web: resources: enable: true