package com.galaxis.rcs; import com.galaxis.rcs.common.entity.AddTaskRequest; import com.galaxis.rcs.common.entity.AddTaskResult; import com.galaxis.rcs.common.enums.LCCDirection; import com.galaxis.rcs.connector.cl2.Cl2Item; import com.galaxis.rcs.plan.path.PathUtils; import com.google.common.base.Strings; import com.yvan.logisticsModel.LogisticsRuntime; import com.yvan.logisticsModel.LogisticsRuntimeService; import com.yvan.logisticsModel.StaticItem; import com.yvan.workbench.SpringContext; import com.yvan.workbench.model.entity.LccProject; import com.yvan.workbench.service.LccMapService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.clever.core.Conv; import org.clever.core.json.JsonWrapper; import org.clever.core.mapper.JacksonMapper; import org.clever.data.jdbc.DaoFactory; import org.clever.data.jdbc.QueryDSL; import org.clever.data.jdbc.querydsl.utils.QueryDslUtils; import java.util.List; import java.util.Map; import static com.galaxis.rcs.common.query.QLccBasExecutor.lccBasExecutor; /** * RCS 对外API调用类 */ @Slf4j public class RCSService { public static void ok() { } /** * 添加任务 */ public static AddTaskResult addTask(String projectUuid, long envId, AddTaskRequest request) { AddTaskResult result = new AddTaskResult(); LogisticsRuntime logisticsRuntime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUuid, envId); String bizTaskId = logisticsRuntime.taskService.addBizTask(request); result.bizTaskId = bizTaskId; return result; } @SneakyThrows public static void projectStart(String projectUuid, Long envId) { LogisticsRuntime runtime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUuid, envId); if (runtime != null) { log.info("Project {} with envId {} is already started.", projectUuid, envId); return; } var lccMapService = SpringContext.HOLDER.getBean(LccMapService.class); var project = lccMapService.getProjectById(projectUuid); if (project == null) { throw new RuntimeException("Project not found: " + projectUuid); } if (project.getOtherData().isEmpty()) { throw new RuntimeException("Project " + projectUuid + " has no data."); } if (project.getDirectoryData().length == 0) { throw new RuntimeException("Project " + projectUuid + " has no catalog data."); } var env = lccMapService.getEnvById(projectUuid, envId); if (env.getEnvConfig() == null) { throw new RuntimeException("Project " + projectUuid + " envId " + envId + " has no envConfig data."); } runtime = LogisticsRuntimeService.INSTANCE.create(project, env); // 获取所有楼层数据 for (LccProject.CatalogGroup floor : project.getDirectoryData()) { for (LccProject.CatalogItem item : floor.getItems()) { String catalogCode = item.getCatalogCode(); if (Strings.isNullOrEmpty(catalogCode)) { continue; } // 读取楼层数据 String floorJson = lccMapService.loadFloor(projectUuid, catalogCode); if (!Strings.isNullOrEmpty(floorJson)) { List> items = JacksonMapper.getInstance().fromJson(floorJson, List.class); runtime.loadMap(catalogCode, items); } } } // 读取所有的库存 // 读取所有的执行器 // 读取地图上所有的车 final QueryDSL queryDSL = DaoFactory.getQueryDSL(); var list = queryDSL.select(QueryDslUtils.linkedMap( lccBasExecutor.executorId, lccBasExecutor.virtualLocationAt, lccBasExecutor.virtualExecutorPayload )) .from(lccBasExecutor) .where(lccBasExecutor.envId.eq(envId)) .where(lccBasExecutor.isActive.eq(true)) .fetch(); for (var item : list) { // 车的属性 String payload = Conv.asString(item.get("virtual_executor_payload")); /** * { * "id": "3", * "t": "cl2", * "v": true, * "dt": { * "ptrWidth": 1.5, * "ptrDepth": 1.5, * "ptrHeight": 1.98 * } * } */ JsonWrapper jwPayload = new JsonWrapper(payload); String wayPointId = ""; String direction = ""; if (env.getIsVirtual()) { // 如果是虚拟车,需要读取虚拟姿态 String virtualLocationAt = Conv.asString(item.get("virtual_location_at")); if (Strings.isNullOrEmpty(virtualLocationAt)) { log.warn("Virtual location at is null for executorId: {}", item.get("executor_id")); continue; // 跳过虚拟位置为空的执行器 } if (!virtualLocationAt.contains(":")) { log.warn("Invalid virtual_location_at format: {}, id:{}", virtualLocationAt, item.get("executor_id")); continue; // 跳过格式不正确的虚拟位置 } String[] parts = virtualLocationAt.split(":"); wayPointId = parts[0]; direction = parts[1]; if(Strings.isNullOrEmpty(wayPointId)){ log.warn("wayPointId is empty for executorId: {}", item.get("executor_id")); continue; // 跳过wayPointId为空的执行器 } if(Strings.isNullOrEmpty(direction)) { log.warn("direction is empty for executorId: {}", item.get("executor_id")); continue; // 跳过方向为空的执行器 } } switch (jwPayload.asStr("t")) { case "cl2": case "clx": // 处理 CL2 或 CLX 类型的执行器 // 车所在的标记位置,及方向 11_4:RIGHT var eitem = new Cl2Item(runtime, (Map) jwPayload.getInnerMap()); // 找到地标位置 StaticItem staticItem = runtime.getStaticItemById(wayPointId); if (staticItem != null) { eitem.logicX = staticItem.logicX; eitem.logicY = staticItem.logicY; eitem.direction = PathUtils.convertDirectionToPtrDiretion(LCCDirection.fromString(direction)); } else { log.warn("Static item not found for wayPointId: {}", wayPointId); } runtime.executorItemMap.put(eitem.getId(), eitem); break; default: log.warn("Unknown executor type: {}", jwPayload.asStr("t")); continue; // 跳过未知类型 } } runtime.start(); } // /** // * 初始化RCS服务 // */ // public void init() { // this.createAutoStartEnv(); // } // // /** // * 加载所有自动启动的环境和楼层数据 // * 并启动对应的环境 // */ // @SneakyThrows // private void createAutoStartEnv() { // QueryDSL queryDSL = DaoFactory.getQueryDSL(); // var list = queryDSL.select(QueryDslUtils.linkedMap( // lccEnvInfo.envId, // lccEnvInfo.worldId, // lccEnvInfo.envPayload, // lccModelFloor.catalogCode // // )).from(lccEnvInfo) // .innerJoin(lccModelFloor).on( // lccEnvInfo.worldId.eq(lccModelFloor.projectUuid) // ) // .where(lccEnvInfo.autoStart.eq(true)) // .where(lccModelFloor.autoStart.eq(true)) // .fetch(); // // Map runtimePayLoad = Maps.newHashMap(); // for (Map map : list) { // long envId = Conv.asLong(map.get("env_id")); // String projectUuid = Conv.asString(map.get("world_id")); // String envPayload = Conv.asString(map.get("env_payload")); // String catalogCode = Conv.asString(map.get("catalog_code")); // // EnvConfig payload; // if (!Strings.isNullOrEmpty(envPayload) && !"N/A".equals(envPayload)) { // payload = new JsonWrapper(envPayload).asObject(EnvConfig.class); // } else { // payload = new EnvConfig(); // } // // var runtime = loadFloor(projectUuid, catalogCode, envId, payload); // runtimePayLoad.put(runtime, payload); // } // // String[] logBanners = new String[runtimePayLoad.entrySet().size()]; // int i = 0; // for (Map.Entry entry : runtimePayLoad.entrySet()) { // var runtime = entry.getKey(); // var envPayload = entry.getValue(); // // logBanners[i++] = String.format("projectUUID: %s, envId: %d", runtime.projectUUID, runtime.envId); // // EnvStartParam param = new EnvStartParam(); // param.setTimeRate(1); // param.setVirtual(false); // param.setEnvConfig(envPayload); // param.setClientId(InetAddress.getLocalHost().getHostName()); // runtime.start(param); // } // // BannerUtils.printConfig(log, "RCS服务已启动", logBanners); // } // /** // * 加载项目的楼层数据 (只加载物理生产环境) // */ // @SneakyThrows // public static LogisticsRuntime loadFloor(String projectUUID, String catalogCode, long envId, EnvConfig envConfig) { // LogisticsRuntime runtime = LogisticsRuntimeService.INSTANCE.getByProjectEnv(projectUUID, envId); // if (runtime == null) { // QueryDSL queryDsl = DaoFactory.getQueryDSL(); // String floorPayload = queryDsl.select(QLccModelFloor.lccModelFloor.items) // .from(QLccModelFloor.lccModelFloor) // .where(QLccModelFloor.lccModelFloor.projectUuid.eq(projectUUID)) // .where(QLccModelFloor.lccModelFloor.catalogCode.eq(catalogCode)) // .fetchFirst(); // // if (Strings.isNullOrEmpty(floorPayload)) { // throw new RuntimeException("not found floor data for projectUUID: " + projectUUID + ", catalogCode: " + catalogCode); // } // // JsonWrapper jw = new JsonWrapper("{ \"catalogCode\": \"" + catalogCode + "\", \"t\": \"floor\", \"items\": " + floorPayload + "}"); // // runtime = LogisticsRuntimeService.INSTANCE.createEnv(projectUUID, envId); // // log.info("loadFloor: projectUUID={}, catalogCode={}, envId={}", projectUUID, catalogCode, envId); // runtime.loadMap(jw); // } // return runtime; // } // public static Object runPath() { // String executorId = "10"; // 执行器ID // String lpn = "pallet1124"; // long envId = 1; // // LogisticsRuntime logisticsRuntime = LogisticsRuntimeService.INSTANCE.findByEnvCode(envId); // RcsTaskBiz bizTask = new RcsTaskBiz(); // bizTask.setBizTaskId(100L); // bizTask.setEnvId(envId); // bizTask.setBizType(BizTaskType.CARRY.toString()); // bizTask.setLpn(lpn); // bizTask.setPriority(1); // bizTask.setTaskFrom("rack1_0_1_0"); // bizTask.setTaskTo("54_0_0_0"); // bizTask.setAllocatedExecutorId(executorId); // bizTask.setBizTaskPayload("N/A"); // bizTask.setBizTaskErrorInfo("N/A"); // bizTask.setBizTaskDescription("N/A"); // bizTask.setBizTaskStatus(BizTaskStatus.WAITING_FOR_DISPATCH.toString()); // // PlanTaskSequence planSequence = new PlanTaskSequence(executorId, logisticsRuntime, bizTask, "demo"); // // CarryTask carryTask = new CarryTask( // executorId, lpn, 1, // new StoreLocation("rack1", 0, 1, 0), // new StoreLocation("54", 0, 0, 0) // ); // // logisticsRuntime.pathPlannerMap.get("cl2") // .planCarryTask(planSequence, "17", LCCDirection.DOWN, carryTask); // return planSequence.toPrettyMap(); // } // // public static Object runPath2() { // String executorId = "10"; // 执行器ID // String lpn = "pallet1124"; // long envId = 1; // // LogisticsRuntime logisticsRuntime = LogisticsRuntimeService.INSTANCE.findByEnvCode(envId); // RcsTaskBiz bizTask = new RcsTaskBiz(); // bizTask.setBizTaskId(100L); // bizTask.setEnvId(envId); // bizTask.setBizType(BizTaskType.CARRY.toString()); // bizTask.setLpn(lpn); // bizTask.setPriority(1); // bizTask.setTaskFrom("rack1_0_1_0"); // bizTask.setTaskTo("54_0_0_0"); // bizTask.setAllocatedExecutorId(executorId); // bizTask.setBizTaskPayload("N/A"); // bizTask.setBizTaskErrorInfo("N/A"); // bizTask.setBizTaskDescription("N/A"); // bizTask.setBizTaskStatus(BizTaskStatus.WAITING_FOR_DISPATCH.toString()); // // PlanTaskSequence planSequence = new PlanTaskSequence(executorId, logisticsRuntime, bizTask, "demo"); // // CarryTask carryTask = new CarryTask( // executorId, lpn, 1, // new StoreLocation("rack1", 0, 1, 0), // new StoreLocation("54", 0, 0, 0) // ); // // logisticsRuntime.pathPlannerMap.get("cl2") // .planCarryTask(planSequence, "27", LCCDirection.UP, carryTask); // return planSequence.toPrettyMap(); // } // // public static void runDemo() { // String executorId = "10"; // 执行器ID // String lpn = "pallet1124"; // long envId = 1; // // AddTaskRequest request = new AddTaskRequest(); // request.setType(BizTaskType.CARRY); // request.setTaskExecutorId(executorId); // request.setLpn(lpn); // request.setPriority(1); // request.setFrom(new StoreLocation("rack1", 0, 1, 0)); // request.setTo(new StoreLocation("54", 0, 0, 0)); // request.setDescription("从rack1的0/1/0, 取货到地堆54"); // request.setCreateBy("runDemo"); // // AddTaskResult result = RCSService.addTask(envId, request); // // LogisticsRuntime logisticsRuntime = LogisticsRuntimeService.INSTANCE.findByEnvCode(envId); // RcsTaskBiz bizTask = logisticsRuntime.taskService.waitingTaskList.get(logisticsRuntime.taskService.waitingTaskList.size() - 1); // // // Planner planner = TaskPlannerFactory.getPlanner("cl2"); // // // 规划任务序列 // PlanTaskSequence planSequence = new PlanTaskSequence(executorId, logisticsRuntime, bizTask, "demo"); // planSequence.addMoveTo("20"); // planSequence.addMoveTo("21"); // planSequence.addMoveTo("22"); // planSequence.addMoveTo("23"); // planSequence.addRotationTo(90); // planSequence.addMoveTo("24"); // planSequence.addMoveTo("25"); // planSequence.addMoveTo("26"); // planSequence.addMoveTo("27"); // planSequence.addLoad(lpn, "rack1", 0, 1, 0); // planSequence.addMoveTo("26"); // planSequence.addMoveTo("25"); // planSequence.addMoveTo("24"); // planSequence.addMoveTo("23"); // planSequence.addRotationTo(-90); // planSequence.addMoveTo("22"); // planSequence.addMoveTo("21"); // planSequence.addMoveTo("20"); // planSequence.addUnload("54", 0, 0, 0); // planSequence.addFinish(); // // planner.appendSequence(planSequence); // } // // public static LogisticsRuntime getDemo() { // return LogisticsRuntimeService.INSTANCE.findByEnvCode(1L); // } }