Browse Source

ServerView 服务器状态管理、ConnectEnv 连接状态分离、Authorization 服务授权、

master
修宁 5 months ago
parent
commit
d722680273
  1. 77
      servo/src/main/java/com/galaxis/rcs/ptr/PtrAgvItem.java
  2. 89
      servo/src/main/java/com/yvan/entity/AgvStatusVo.java
  3. 12
      servo/src/main/java/com/yvan/entity/ServerAuthorizationConfigVo.java
  4. 96
      servo/src/main/java/com/yvan/entity/ServerStatusVo.java
  5. 2
      servo/src/main/java/com/yvan/logisticsEnv/EnvConfig.java
  6. 28
      servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntime.java
  7. 7
      servo/src/main/java/com/yvan/logisticsModel/LogisticsRuntimeService.java
  8. 56
      servo/src/main/java/com/yvan/logisticsModel/RuntimeState.java
  9. 8
      servo/src/main/java/com/yvan/pusher/FrontendMessagePushService.java
  10. 1
      servo/src/main/java/com/yvan/redis/LccRedisService.java
  11. 10
      servo/src/main/java/com/yvan/workbench/autoconfigure/LccConfigProperties.java
  12. 29
      servo/src/main/java/com/yvan/workbench/controller/AuthController.java
  13. 140
      servo/src/main/java/com/yvan/workbench/controller/LccController.java
  14. 11
      servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java
  15. 151
      servo/src/main/java/com/yvan/workbench/controller/ServerController.java
  16. 2
      servo/src/main/java/com/yvan/workbench/service/LccMapService.java
  17. 20
      servo/src/main/resources/application-dev.yml

77
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<String, String> 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;
}
}

89
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;
}
}

12
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;
}

96
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<String, Object> toMap() {
Map<String, Object> 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;
}
}

2
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;

28
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<String> 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;
}
}

7
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<LogisticsRuntime> getAllRuntimeList() {
synchronized (LOCK) {
return List.copyOf(runtimeMap.values());
}
}
@SneakyThrows
public LogisticsRuntime create(LccProject project, LccProjectEnv env) {
synchronized (LOCK) {

56
servo/src/main/java/com/yvan/logisticsModel/RuntimeState.java

@ -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<String, Object> toMap() {
Map<String, Object> 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;
}
}

8
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<String, Object> statusData) {
public void pushServerState(ServerStatusVo statusData) {
String topic = buildTopic("server");
publishJson(topic, statusData);
}

1
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());
}

10
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;
}
}

29
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<ServerAuthorizationConfigVo> getAuthorizationConfig(@RequestBody Map<String, Object> 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);
}
}

140
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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<AgvStatusVo> 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);
}

11
servo/src/main/java/com/yvan/workbench/controller/LccModelManager.java

@ -32,8 +32,9 @@ public class LccModelManager {
private static Map<String, Object> 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<String, Object> entity) {
String projectUuid = Conv.asString(entity.get("projectUuid"));
String projectLabel = Conv.asString(entity.get("projectLabel"));
List<String> 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));

151
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<String, Object> params) {
String projectUuid = Conv.asString(params.get("projectUUID"));
long envId = Conv.asLong(params.get("envId"));
var mapService = SpringContext.HOLDER.getBean(LccMapService.class);
// 从文件夹读取全部 项目+环境
List<ServerStatusVo> 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<String> startServer(@RequestBody Map<String, Object> 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<String> stopServer(@RequestBody Map<String, Object> 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");
}
}

2
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;

20
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

Loading…
Cancel
Save