| New file |
| | |
| | | package com.zy.ai.mcp.config; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.zy.ai.mcp.dto.McpToolHandler; |
| | | import com.zy.ai.mcp.dto.ToolDefinition; |
| | | import com.zy.ai.mcp.dto.ToolRegistry; |
| | | import com.zy.ai.mcp.service.WcsDataFacade; |
| | | |
| | | import java.util.*; |
| | | |
| | | public class McpToolsBootstrap { |
| | | |
| | | public static void registerAll(ToolRegistry registry, final WcsDataFacade facade) { |
| | | |
| | | registry.register(tool( |
| | | "device.get_crn_status", |
| | | "Query realtime status of a crn device by deviceNo.", |
| | | schemaObj( |
| | | propInt("crnNos", true) |
| | | ), |
| | | schemaObj( |
| | | propObj("devices", true) |
| | | ), |
| | | new McpToolHandler() { |
| | | public Object handle(JSONObject args) { |
| | | return facade.getCrnDeviceStatus(args); |
| | | } |
| | | } |
| | | )); |
| | | |
| | | registry.register(tool( |
| | | "device.get_station_status", |
| | | "Query realtime status of a station device", |
| | | schemaObj( |
| | | |
| | | ), |
| | | schemaObj( |
| | | propObj("stations", true) |
| | | ), |
| | | new McpToolHandler() { |
| | | public Object handle(JSONObject args) { |
| | | return facade.getStationDeviceStatus(args); |
| | | } |
| | | } |
| | | )); |
| | | |
| | | registry.register(tool( |
| | | "device.get_rgv_status", |
| | | "Query realtime status of a rgv device by deviceNo.", |
| | | schemaObj( |
| | | propInt("rgvNos", true) |
| | | ), |
| | | schemaObj( |
| | | propObj("devices", true) |
| | | ), |
| | | new McpToolHandler() { |
| | | public Object handle(JSONObject args) { |
| | | return facade.getRgvDeviceStatus(args); |
| | | } |
| | | } |
| | | )); |
| | | |
| | | registry.register(tool( |
| | | "task.list", |
| | | "List tasks by filters (status/CrnDevice/RgvDevice//time window).", |
| | | schemaObj( |
| | | propInt("crnNo", false), |
| | | propInt("rgvNo", false), |
| | | propArr("taskNos", false, "integer"), |
| | | propInt("limit", false) |
| | | ), |
| | | schemaObj(propArr("tasks", true, "object")), |
| | | new McpToolHandler() { |
| | | public Object handle(JSONObject args) { |
| | | return facade.getTasks(args); |
| | | } |
| | | } |
| | | )); |
| | | |
| | | registry.register(tool( |
| | | "log.query", |
| | | "Query logs by keyword/level/time window/device/task. Return clipped log lines.", |
| | | schemaObj( |
| | | propInt("limit", false) |
| | | ), |
| | | schemaObj(propArr("logs", true, "object")), |
| | | new McpToolHandler() { |
| | | public Object handle(JSONObject args) { |
| | | return facade.getLogs(args); |
| | | } |
| | | } |
| | | )); |
| | | |
| | | registry.register(tool( |
| | | "config.get_device_config", |
| | | "Get device config by deviceCode.", |
| | | schemaObj( |
| | | propArr("crnNos", false, "integer"), |
| | | propArr("rgvNos", false, "integer"), |
| | | propArr("devpNos", false, "integer") |
| | | ), |
| | | schemaObj(propObj("deviceConfigs", true)), |
| | | new McpToolHandler() { |
| | | public Object handle(JSONObject args) { |
| | | return facade.getDeviceConfig(args); |
| | | } |
| | | } |
| | | )); |
| | | |
| | | registry.register(tool( |
| | | "config.get_system_config", |
| | | "Get key system configs for diagnosis.", |
| | | schemaObj( |
| | | |
| | | ), |
| | | schemaObj( |
| | | propObj("systemConfigs", true) |
| | | ), |
| | | new McpToolHandler() { |
| | | public Object handle(JSONObject args) { |
| | | return facade.getSystemConfig(args); |
| | | } |
| | | } |
| | | )); |
| | | |
| | | // // ★ 诊断聚合快照:一次拿全 |
| | | // registry.register(tool( |
| | | // "build_diagnosis_snapshot", |
| | | // "Aggregate diagnosis snapshot: tasks + device realtime + configs + clipped logs for diagnosis.", |
| | | // schemaObj( |
| | | // propStr("warehouseCode", true), |
| | | // propArr("deviceCodes", false, "string"), // 不传则按任务涉及设备推导 |
| | | // propStr("taskNo", false), |
| | | // propStr("fromTime", true), |
| | | // propStr("toTime", true), |
| | | // propInt("taskLimit", false), |
| | | // propInt("logLimit", false), |
| | | // propArr("logKeywords", false, "string"), |
| | | // propBool("includeSystemConfig", false), |
| | | // propBool("includeDeviceConfig", false) |
| | | // ), |
| | | // schemaObj( |
| | | // propObj("snapshot", true), |
| | | // propArr("hints", false, "string") |
| | | // ), |
| | | // new McpToolHandler() { |
| | | // public Object handle(JSONObject args) { |
| | | // return facade.buildDiagnosisSnapshot(args); |
| | | // } |
| | | // } |
| | | // )); |
| | | } |
| | | |
| | | // ---------- schema helpers ---------- |
| | | private static ToolDefinition tool(String name, String desc, |
| | | Map<String, Object> in, Map<String, Object> out, |
| | | McpToolHandler handler) { |
| | | ToolDefinition d = new ToolDefinition(); |
| | | d.setName(name); |
| | | d.setDescription(desc); |
| | | d.setInputSchema(in); |
| | | d.setOutputSchema(out); |
| | | d.setHandler(handler); |
| | | return d; |
| | | } |
| | | |
| | | private static Map<String, Object> schemaObj(Object... props) { |
| | | Map<String, Object> m = new LinkedHashMap<String, Object>(); |
| | | m.put("type", "object"); |
| | | |
| | | Map<String, Object> properties = new LinkedHashMap<String, Object>(); |
| | | List<String> required = new ArrayList<String>(); |
| | | |
| | | for (Object p : props) { |
| | | @SuppressWarnings("unchecked") |
| | | Map<String, Object> pm = (Map<String, Object>) p; |
| | | String name = String.valueOf(pm.get("name")); |
| | | boolean req = Boolean.TRUE.equals(pm.get("required")); |
| | | pm.remove("name"); |
| | | pm.remove("required"); |
| | | properties.put(name, pm); |
| | | if (req) required.add(name); |
| | | } |
| | | |
| | | m.put("properties", properties); |
| | | if (!required.isEmpty()) m.put("required", required); |
| | | return m; |
| | | } |
| | | |
| | | private static Map<String, Object> propStr(String name, boolean required) { |
| | | Map<String, Object> m = new LinkedHashMap<String, Object>(); |
| | | m.put("name", name); |
| | | m.put("required", required); |
| | | m.put("type", "string"); |
| | | return m; |
| | | } |
| | | |
| | | private static Map<String, Object> propInt(String name, boolean required) { |
| | | Map<String, Object> m = new LinkedHashMap<String, Object>(); |
| | | m.put("name", name); |
| | | m.put("required", required); |
| | | m.put("type", "integer"); |
| | | return m; |
| | | } |
| | | |
| | | private static Map<String, Object> propBool(String name, boolean required) { |
| | | Map<String, Object> m = new LinkedHashMap<String, Object>(); |
| | | m.put("name", name); |
| | | m.put("required", required); |
| | | m.put("type", "boolean"); |
| | | return m; |
| | | } |
| | | |
| | | private static Map<String, Object> propObj(String name, boolean required) { |
| | | Map<String, Object> m = new LinkedHashMap<String, Object>(); |
| | | m.put("name", name); |
| | | m.put("required", required); |
| | | m.put("type", "object"); |
| | | return m; |
| | | } |
| | | |
| | | private static Map<String, Object> propArr(String name, boolean required, String itemType) { |
| | | Map<String, Object> m = new LinkedHashMap<String, Object>(); |
| | | m.put("name", name); |
| | | m.put("required", required); |
| | | m.put("type", "array"); |
| | | Map<String, Object> items = new LinkedHashMap<String, Object>(); |
| | | items.put("type", itemType); |
| | | m.put("items", items); |
| | | return m; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.controller; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.zy.ai.mcp.config.McpToolsBootstrap; |
| | | import com.zy.ai.mcp.dto.JsonRpcRequest; |
| | | import com.zy.ai.mcp.dto.JsonRpcResponse; |
| | | import com.zy.ai.mcp.dto.ToolDefinition; |
| | | import com.zy.ai.mcp.dto.ToolRegistry; |
| | | import com.zy.ai.mcp.service.WcsDataFacade; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | import java.util.*; |
| | | |
| | | @Slf4j |
| | | @RestController |
| | | @RequestMapping("/ai/mcp") |
| | | public class McpController { |
| | | |
| | | private final ToolRegistry registry = new ToolRegistry(); |
| | | |
| | | @Autowired |
| | | private WcsDataFacade wcsDataFacade; |
| | | |
| | | public McpController(WcsDataFacade wcsDataFacade) { |
| | | this.wcsDataFacade = wcsDataFacade; |
| | | } |
| | | |
| | | @PostConstruct |
| | | public void init() { |
| | | McpToolsBootstrap.registerAll(registry, wcsDataFacade); |
| | | log.info("MCP initialized, tools={}", registry.listTools().size()); |
| | | } |
| | | |
| | | @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) |
| | | public Object handle(@RequestBody JsonRpcRequest req, |
| | | @RequestHeader(value = "Authorization", required = false) String auth) { |
| | | |
| | | // (建议)做一个简单鉴权:防止被随便调用生产系统 |
| | | // if (!"Bearer your-token".equals(auth)) return JsonRpcResponse.err(null, 401, "Unauthorized", null); |
| | | |
| | | String id = req.getId(); |
| | | String method = req.getMethod(); |
| | | JSONObject params = JSON.parseObject(JSON.toJSONString(req.getParams())); |
| | | |
| | | try { |
| | | if ("initialize".equals(method)) { |
| | | Map<String, Object> result = new LinkedHashMap<String, Object>(); |
| | | result.put("serverName", "wcs-mcp"); |
| | | result.put("serverVersion", "1.0.0"); |
| | | result.put("capabilities", Arrays.asList("tools")); |
| | | return JsonRpcResponse.ok(id, result); |
| | | } |
| | | |
| | | if ("tools/list".equals(method)) { |
| | | Map<String, Object> result = new LinkedHashMap<String, Object>(); |
| | | result.put("tools", registry.listTools()); |
| | | // cursor/paging 你后面需要再加 |
| | | return JsonRpcResponse.ok(id, result); |
| | | } |
| | | |
| | | if ("tools/call".equals(method)) { |
| | | String toolName = params.getString("name"); |
| | | JSONObject arguments = params.getJSONObject("arguments"); |
| | | if (toolName == null || toolName.trim().isEmpty()) { |
| | | return JsonRpcResponse.err(id, -32602, "Invalid params: missing tool name", null); |
| | | } |
| | | ToolDefinition def = registry.get(toolName); |
| | | if (def == null) { |
| | | return JsonRpcResponse.err(id, -32601, "Method not found: tool " + toolName, null); |
| | | } |
| | | Object output = def.getHandler().handle(arguments == null ? new JSONObject() : arguments); |
| | | |
| | | Map<String, Object> result = new LinkedHashMap<String, Object>(); |
| | | result.put("content", output); // 你也可以按 MCP 常见返回结构做 text/json 分段 |
| | | return JsonRpcResponse.ok(id, result); |
| | | } |
| | | |
| | | return JsonRpcResponse.err(id, -32601, "Method not found: " + method, null); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("MCP handle error, method={}, params={}", method, params, e); |
| | | return JsonRpcResponse.err(id, -32000, "Server error", e.getMessage()); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | class JsonRpcError { |
| | | private int code; |
| | | private String message; |
| | | private Object data; |
| | | |
| | | public JsonRpcError(int code, String message, Object data) { |
| | | this.code = code; |
| | | this.message = message; |
| | | this.data = data; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.Map; |
| | | |
| | | @Data |
| | | public class JsonRpcRequest { |
| | | private String jsonrpc; // "2.0" |
| | | private String id; // string/number 都行,这里用 string |
| | | private String method; // "tools/list" | "tools/call" |
| | | private Map<String, Object> params; |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class JsonRpcResponse { |
| | | private String jsonrpc = "2.0"; |
| | | private String id; |
| | | private Object result; |
| | | private JsonRpcError error; |
| | | |
| | | public static JsonRpcResponse ok(String id, Object result) { |
| | | JsonRpcResponse r = new JsonRpcResponse(); |
| | | r.id = id; |
| | | r.result = result; |
| | | return r; |
| | | } |
| | | |
| | | public static JsonRpcResponse err(String id, int code, String message, Object data) { |
| | | JsonRpcResponse r = new JsonRpcResponse(); |
| | | r.id = id; |
| | | r.error = new JsonRpcError(code, message, data); |
| | | return r; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.dto; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | |
| | | public interface McpToolHandler { |
| | | Object handle(JSONObject arguments) throws Exception; |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.dto; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.*; |
| | | |
| | | @Data |
| | | public class ToolDefinition { |
| | | private String name; |
| | | private String description; |
| | | private Map<String, Object> inputSchema; // JSON Schema as Map |
| | | private Map<String, Object> outputSchema; // JSON Schema as Map |
| | | private McpToolHandler handler; |
| | | |
| | | public Map<String, Object> toMcpToolJson() { |
| | | Map<String, Object> m = new LinkedHashMap<String, Object>(); |
| | | m.put("name", name); |
| | | m.put("description", description); |
| | | m.put("inputSchema", inputSchema); |
| | | m.put("outputSchema", outputSchema); |
| | | return m; |
| | | } |
| | | } |
| | | |
| New file |
| | |
| | | package com.zy.ai.mcp.dto; |
| | | |
| | | import java.util.*; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | public class ToolRegistry { |
| | | private final Map<String, ToolDefinition> tools = new ConcurrentHashMap<String, ToolDefinition>(); |
| | | |
| | | public void register(ToolDefinition def) { |
| | | tools.put(def.getName(), def); |
| | | } |
| | | |
| | | public List<Map<String, Object>> listTools() { |
| | | List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); |
| | | for (ToolDefinition def : tools.values()) { |
| | | list.add(def.toMcpToolJson()); |
| | | } |
| | | // 为了稳定输出,按 name 排序 |
| | | Collections.sort(list, new Comparator<Map<String, Object>>() { |
| | | public int compare(Map<String, Object> a, Map<String, Object> b) { |
| | | return String.valueOf(a.get("name")).compareTo(String.valueOf(b.get("name"))); |
| | | } |
| | | }); |
| | | return list; |
| | | } |
| | | |
| | | public ToolDefinition get(String name) { |
| | | return tools.get(name); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.service; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | |
| | | public interface WcsDataFacade { |
| | | |
| | | Object getCrnDeviceStatus(JSONObject args); |
| | | |
| | | Object getStationDeviceStatus(JSONObject args); |
| | | |
| | | Object getRgvDeviceStatus(JSONObject args); |
| | | |
| | | Object getTasks(JSONObject args); |
| | | |
| | | Object getLogs(JSONObject args); |
| | | |
| | | Object getDeviceConfig(JSONObject args); |
| | | |
| | | Object getSystemConfig(JSONObject args); |
| | | |
| | | /** |
| | | * ★ 聚合快照:核心诊断输入 |
| | | */ |
| | | Object buildDiagnosisSnapshot(JSONObject args); |
| | | } |
| New file |
| | |
| | | package com.zy.ai.mcp.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.zy.ai.entity.DeviceConfigsData; |
| | | import com.zy.ai.log.AiLogAppender; |
| | | import com.zy.ai.mcp.service.WcsDataFacade; |
| | | import com.zy.asrs.entity.BasCrnp; |
| | | import com.zy.asrs.entity.BasDevp; |
| | | import com.zy.asrs.entity.BasRgv; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.BasCrnpService; |
| | | import com.zy.asrs.service.BasDevpService; |
| | | import com.zy.asrs.service.BasRgvService; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.core.cache.SlaveConnection; |
| | | import com.zy.core.enums.SlaveType; |
| | | import com.zy.core.model.StationObjModel; |
| | | import com.zy.core.model.protocol.CrnProtocol; |
| | | import com.zy.core.model.protocol.RgvProtocol; |
| | | import com.zy.core.model.protocol.StationProtocol; |
| | | import com.zy.core.thread.CrnThread; |
| | | import com.zy.core.thread.RgvThread; |
| | | import com.zy.core.thread.StationThread; |
| | | import com.zy.system.entity.Config; |
| | | import com.zy.system.service.ConfigService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.*; |
| | | |
| | | @Service("wcsDataFacade") |
| | | @RequiredArgsConstructor |
| | | public class WcsDataFacadeImpl implements WcsDataFacade { |
| | | |
| | | @Autowired |
| | | private BasCrnpService basCrnpService; |
| | | @Autowired |
| | | private BasDevpService basDevpService; |
| | | @Autowired |
| | | private BasRgvService basRgvService; |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | | private ConfigService configService; |
| | | |
| | | @Override |
| | | public Object getCrnDeviceStatus(JSONObject args) { |
| | | List<Integer> deviceNoList = optIntList(args, "crnNos"); |
| | | EntityWrapper<BasCrnp> wrapper = new EntityWrapper<>(); |
| | | if (deviceNoList != null && deviceNoList.size() > 0) { |
| | | wrapper.in("crn_no", deviceNoList); |
| | | } |
| | | JSONObject data = new JSONObject(); |
| | | |
| | | List<Object> deviceList = new ArrayList<>(); |
| | | List<BasCrnp> basCrnps = basCrnpService.selectList(wrapper); |
| | | for (BasCrnp basCrnp : basCrnps) { |
| | | CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, basCrnp.getCrnNo()); |
| | | if (crnThread == null) { |
| | | continue; |
| | | } |
| | | CrnProtocol protocol = crnThread.getStatus(); |
| | | deviceList.add(protocol); |
| | | } |
| | | |
| | | data.put("devices", deviceList); |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public Object getStationDeviceStatus(JSONObject args) { |
| | | List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>()); |
| | | JSONObject data = new JSONObject(); |
| | | |
| | | List<Object> stationList = new ArrayList<>(); |
| | | for (BasDevp basDevp : basDevps) { |
| | | StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo()); |
| | | if (stationThread == null) { |
| | | continue; |
| | | } |
| | | |
| | | Map<Integer, StationProtocol> map = stationThread.getStatusMap(); |
| | | |
| | | for (StationObjModel stationObjModel : basDevp.getStationList$()) { |
| | | StationProtocol stationProtocol = map.get(stationObjModel.getStationId()); |
| | | if (stationProtocol == null) { |
| | | continue; |
| | | } |
| | | stationList.add(stationProtocol); |
| | | } |
| | | } |
| | | |
| | | data.put("stations", stationList); |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public Object getRgvDeviceStatus(JSONObject args) { |
| | | List<Integer> deviceNoList = optIntList(args, "rgvNos"); |
| | | EntityWrapper<BasRgv> wrapper = new EntityWrapper<>(); |
| | | if (deviceNoList != null && deviceNoList.size() > 0) { |
| | | wrapper.in("rgv_no", deviceNoList); |
| | | } |
| | | JSONObject data = new JSONObject(); |
| | | |
| | | List<Object> deviceList = new ArrayList<>(); |
| | | List<BasRgv> basRgvs = basRgvService.selectList(wrapper); |
| | | for (BasRgv basRgv : basRgvs) { |
| | | RgvThread rgvThread = (RgvThread) SlaveConnection.get(SlaveType.Rgv, basRgv.getRgvNo()); |
| | | if (rgvThread == null) { |
| | | continue; |
| | | } |
| | | RgvProtocol rgvProtocol = rgvThread.getStatus(); |
| | | deviceList.add(rgvProtocol); |
| | | } |
| | | |
| | | data.put("devices", deviceList); |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public Object getTasks(JSONObject args) { |
| | | int crnNo = optInt(args, "crnNo", -1); |
| | | int rgvNo = optInt(args, "rgvNo", -1); |
| | | List<Integer> taskNos = optIntList(args, "taskNos"); |
| | | int limit = optInt(args, "limit", 200); |
| | | |
| | | EntityWrapper<WrkMast> wrapper = new EntityWrapper<>(); |
| | | if (taskNos != null && taskNos.size() > 0) { |
| | | wrapper.in("wrk_no", taskNos); |
| | | } |
| | | |
| | | if (crnNo != -1) { |
| | | wrapper.eq("crn_no", crnNo); |
| | | } |
| | | |
| | | if (rgvNo != -1) { |
| | | wrapper.eq("rgv_no", rgvNo); |
| | | } |
| | | |
| | | List<WrkMast> tasks = wrkMastService.selectList(wrapper); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("tasks", tasks); |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public Object getLogs(JSONObject args) { |
| | | int limit = optInt(args, "limit", 500); |
| | | List<String> logs = AiLogAppender.getRecentLogs(limit); |
| | | JSONObject data = new JSONObject(); |
| | | data.put("logs", logs); |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public Object getDeviceConfig(JSONObject args) { |
| | | JSONObject data = new JSONObject(); |
| | | List<DeviceConfigsData> deviceConfigsDataList = new ArrayList<>(); |
| | | |
| | | List<Integer> crnNoList = optIntList(args, "crnNos"); |
| | | EntityWrapper<BasCrnp> crnWrapper = new EntityWrapper<>(); |
| | | if (crnNoList != null && crnNoList.size() > 0) { |
| | | crnWrapper.in("crn_no", crnNoList); |
| | | } |
| | | |
| | | List<Integer> rgvNoList = optIntList(args, "rgvNos"); |
| | | EntityWrapper<BasRgv> rgvWrapper = new EntityWrapper<>(); |
| | | if (rgvNoList != null && rgvNoList.size() > 0) { |
| | | rgvWrapper.in("rgv_no", rgvNoList); |
| | | } |
| | | |
| | | List<Integer> devpNoList = optIntList(args, "devpNos"); |
| | | EntityWrapper<BasDevp> devpWrapper = new EntityWrapper<>(); |
| | | if (devpNoList != null && devpNoList.size() > 0) { |
| | | devpWrapper.in("devp_no", devpNoList); |
| | | } |
| | | |
| | | List<BasCrnp> basCrnps = basCrnpService.selectList(crnWrapper); |
| | | for (BasCrnp basCrnp : basCrnps) { |
| | | DeviceConfigsData deviceConfigsData = new DeviceConfigsData(); |
| | | deviceConfigsData.setDeviceNo(basCrnp.getCrnNo()); |
| | | deviceConfigsData.setDeviceType(String.valueOf(SlaveType.Crn)); |
| | | deviceConfigsData.setDeviceData(basCrnp); |
| | | deviceConfigsDataList.add(deviceConfigsData); |
| | | } |
| | | |
| | | List<BasRgv> basRgvs = basRgvService.selectList(rgvWrapper); |
| | | for (BasRgv basRgv : basRgvs) { |
| | | DeviceConfigsData deviceConfigsData = new DeviceConfigsData(); |
| | | deviceConfigsData.setDeviceNo(basRgv.getRgvNo()); |
| | | deviceConfigsData.setDeviceType(String.valueOf(SlaveType.Rgv)); |
| | | deviceConfigsData.setDeviceData(basRgv); |
| | | deviceConfigsDataList.add(deviceConfigsData); |
| | | } |
| | | |
| | | List<BasDevp> basDevps = basDevpService.selectList(devpWrapper); |
| | | for (BasDevp basDevp : basDevps) { |
| | | DeviceConfigsData deviceConfigsData = new DeviceConfigsData(); |
| | | deviceConfigsData.setDeviceNo(basDevp.getDevpNo()); |
| | | deviceConfigsData.setDeviceType(String.valueOf(SlaveType.Devp)); |
| | | deviceConfigsData.setDeviceData(basDevp); |
| | | deviceConfigsDataList.add(deviceConfigsData); |
| | | } |
| | | |
| | | data.put("deviceConfigs", deviceConfigsDataList); |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public Object getSystemConfig(JSONObject args) { |
| | | JSONObject data = new JSONObject(); |
| | | List<Config> systemConfigList = configService.selectList(new EntityWrapper<Config>().notIn("dingdingReportUrl")); |
| | | data.put("systemConfigs", systemConfigList); |
| | | return data; |
| | | } |
| | | |
| | | @Override |
| | | public Object buildDiagnosisSnapshot(JSONObject args) { |
| | | String wh = mustStr(args, "warehouseCode"); |
| | | List<String> crnDeviceNos = optStrList(args, "crnDeviceNos"); |
| | | List<String> taskIds = optStrList(args, "taskIds"); |
| | | int lookbackSeconds = optInt(args, "lookbackSeconds", 300); |
| | | int logMaxLines = optInt(args, "logMaxLines", 600); |
| | | boolean includeConfig = optBool(args, "includeConfig", true); |
| | | |
| | | long now = System.currentTimeMillis(); |
| | | long fromTs = now - lookbackSeconds * 1000L; |
| | | |
| | | // 1) crn devices |
| | | JSONObject devArgs = new JSONObject(); |
| | | devArgs.put("deviceNos", crnDeviceNos); |
| | | JSONObject devices = (JSONObject) getCrnDeviceStatus(devArgs); |
| | | |
| | | // 2) tasks |
| | | JSONObject taskArgs = new JSONObject(); |
| | | taskArgs.put("warehouseCode", wh); |
| | | taskArgs.put("taskIds", taskIds); |
| | | taskArgs.put("limit", 200); |
| | | JSONObject tasks = (JSONObject) getTasks(taskArgs); |
| | | |
| | | // 3) logs (一次性取回,然后做分桶+排序+截断) |
| | | JSONObject logArgs = new JSONObject(); |
| | | logArgs.put("warehouseCode", wh); |
| | | logArgs.put("fromTs", fromTs); |
| | | logArgs.put("toTs", now); |
| | | // logArgs.put("deviceIds", deviceIds); |
| | | logArgs.put("taskIds", taskIds); |
| | | logArgs.put("maxLines", logMaxLines); |
| | | JSONObject logs = (JSONObject) getLogs(logArgs); |
| | | |
| | | // 4) 结构化快照输出(建议:分桶) |
| | | JSONObject snapshot = new JSONObject(); |
| | | snapshot.put("warehouseCode", wh); |
| | | snapshot.put("generatedTs", now); |
| | | snapshot.put("timeRange", new JSONObject() |
| | | .fluentPut("fromTs", fromTs) |
| | | .fluentPut("toTs", now) |
| | | .fluentPut("lookbackSeconds", lookbackSeconds)); |
| | | |
| | | snapshot.put("devices", devices); |
| | | snapshot.put("tasks", tasks); |
| | | snapshot.put("logs", logs); |
| | | |
| | | JSONArray hints = new JSONArray(); |
| | | hints.add("Prefer diagnosing with snapshot.devices + snapshot.tasks + snapshot.logs"); |
| | | hints.add("Logs are already filtered by time range; if missing, expand lookbackSeconds"); |
| | | snapshot.put("hints", hints); |
| | | |
| | | JSONObject data = new JSONObject(); |
| | | data.put("snapshot", snapshot); |
| | | return data; |
| | | } |
| | | |
| | | // --------- helpers --------- |
| | | |
| | | private String mustStr(JSONObject o, String key) { |
| | | if (o == null || o.getString(key) == null || o.getString(key).trim().isEmpty()) |
| | | throw new IllegalArgumentException(key + " is required"); |
| | | return o.getString(key).trim(); |
| | | } |
| | | |
| | | private long mustLong(JSONObject o, String key) { |
| | | if (o == null || !o.containsKey(key)) throw new IllegalArgumentException(key + " is required"); |
| | | return o.getLongValue(key); |
| | | } |
| | | |
| | | private int optInt(JSONObject o, String key, int def) { |
| | | if (o == null || !o.containsKey(key)) return def; |
| | | return o.getIntValue(key); |
| | | } |
| | | |
| | | private boolean optBool(JSONObject o, String key, boolean def) { |
| | | if (o == null || !o.containsKey(key)) return def; |
| | | return o.getBooleanValue(key); |
| | | } |
| | | |
| | | private List<String> optStrList(JSONObject o, String key) { |
| | | if (o == null || !o.containsKey(key)) return Collections.emptyList(); |
| | | JSONArray arr = o.getJSONArray(key); |
| | | if (arr == null) return Collections.emptyList(); |
| | | List<String> list = new ArrayList<>(); |
| | | for (int i = 0; i < arr.size(); i++) { |
| | | String s = arr.getString(i); |
| | | if (s != null && !s.trim().isEmpty()) list.add(s.trim()); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private List<Integer> optIntList(JSONObject o, String key) { |
| | | if (o == null || !o.containsKey(key)) return Collections.emptyList(); |
| | | JSONArray arr = o.getJSONArray(key); |
| | | if (arr == null) return Collections.emptyList(); |
| | | List<Integer> list = new ArrayList<>(); |
| | | for (int i = 0; i < arr.size(); i++) { |
| | | String s = arr.getString(i); |
| | | if (s != null && !s.trim().isEmpty()) list.add(Integer.parseInt(s.trim())); |
| | | } |
| | | return list; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.zy.ai.service; |
| | | |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | @Service |
| | | public class WcsQueryService { |
| | | |
| | | // 这里注入你现有的各类 Service/Mapper:deviceService/taskService/logService/configService... |
| | | |
| | | public Map<String, Object> buildDiagnosisSnapshot(Map<String, Object> args) { |
| | | Map<String, Object> focus = (Map<String, Object>) args.get("focus"); |
| | | List<String> deviceIds = focus == null ? Collections.emptyList() : (List<String>) focus.get("deviceIds"); |
| | | List<String> taskIds = focus == null ? Collections.emptyList() : (List<String>) focus.get("taskIds"); |
| | | |
| | | int timeWindowSec = getInt(args, "timeWindowSec", 600); |
| | | int logLimit = getInt(args, "logLimit", 400); |
| | | boolean includeConfigs = getBool(args, "includeConfigs", true); |
| | | boolean includeDerived = getBool(args, "includeDerivedSignals", true); |
| | | |
| | | Date now = new Date(); |
| | | Date from = new Date(now.getTime() - timeWindowSec * 1000L); |
| | | |
| | | // 1) devices |
| | | List<Object> devices = new ArrayList<>(); |
| | | for (String deviceId : safeList(deviceIds)) { |
| | | Map<String, Object> a = new HashMap<>(); |
| | | a.put("deviceId", deviceId); |
| | | devices.add(getDeviceState(a)); |
| | | } |
| | | |
| | | // 2) tasks |
| | | Map<String, Object> taskArgs = new HashMap<>(); |
| | | if (!safeList(taskIds).isEmpty()) { |
| | | // 你可以让 listTasks 支持 taskIds 精确过滤 |
| | | taskArgs.put("taskIds", taskIds); |
| | | } else if (!safeList(deviceIds).isEmpty()) { |
| | | taskArgs.put("deviceId", deviceIds.get(0)); // 或改成支持 deviceIds 数组 |
| | | taskArgs.put("statuses", Arrays.asList("WAITING","RUNNING","SUSPENDED")); |
| | | taskArgs.put("limit", 200); |
| | | } |
| | | Map<String, Object> taskResult = (Map<String, Object>) listTasks(taskArgs); |
| | | List<Object> tasks = taskResult == null ? new ArrayList<>() : (List<Object>) taskResult.get("tasks"); |
| | | |
| | | // 3) logs |
| | | Map<String, Object> logArgs = new HashMap<>(); |
| | | logArgs.put("timeFrom", iso(from)); |
| | | logArgs.put("timeTo", iso(now)); |
| | | logArgs.put("limit", logLimit); |
| | | if (!safeList(deviceIds).isEmpty()) logArgs.put("deviceId", deviceIds.get(0)); |
| | | if (!safeList(taskIds).isEmpty()) logArgs.put("taskId", taskIds.get(0)); |
| | | Map<String, Object> logResult = (Map<String, Object>) queryLogs(logArgs); |
| | | List<Object> logs = logResult == null ? new ArrayList<>() : (List<Object>) logResult.get("logs"); |
| | | |
| | | // 4) configs |
| | | Object configs = null; |
| | | if (includeConfigs) { |
| | | configs = getSystemConfig(new HashMap<String, Object>()); |
| | | } |
| | | |
| | | // 5) derived |
| | | Object derived = null; |
| | | if (includeDerived) { |
| | | derived = deriveSignals(devices, tasks, logs); |
| | | } |
| | | |
| | | // output |
| | | Map<String, Object> out = new LinkedHashMap<>(); |
| | | Map<String, Object> meta = new LinkedHashMap<>(); |
| | | meta.put("snapshotId", UUID.randomUUID().toString()); |
| | | meta.put("generatedAt", iso(now)); |
| | | meta.put("timeFrom", iso(from)); |
| | | meta.put("timeTo", iso(now)); |
| | | |
| | | out.put("meta", meta); |
| | | out.put("devices", devices); |
| | | out.put("tasks", tasks); |
| | | out.put("logs", logs); |
| | | out.put("configs", configs); |
| | | out.put("derivedSignals", derived); |
| | | return out; |
| | | } |
| | | |
| | | private Map<String, Object> deriveSignals(List<Object> devices, List<Object> tasks, List<Object> logs) { |
| | | Map<String, Object> d = new LinkedHashMap<>(); |
| | | List<String> flags = new ArrayList<>(); |
| | | List<String> causes = new ArrayList<>(); |
| | | List<String> bottlenecks = new ArrayList<>(); |
| | | |
| | | // TODO:把你 WCS 领域规则塞这里(心跳超时、等待确认、命令无ACK、站台满、下游阻塞等) |
| | | // 先给个示例: |
| | | if (tasks != null && !tasks.isEmpty() && (devices == null || devices.isEmpty())) { |
| | | flags.add("HAS_TASKS_BUT_NO_DEVICE_SNAPSHOT"); |
| | | } |
| | | |
| | | d.put("anomalyFlags", flags); |
| | | d.put("suspectedRootCauses", causes); |
| | | d.put("suspectedBottlenecks", bottlenecks); |
| | | return d; |
| | | } |
| | | |
| | | // ======= 下面这些函数,你用现有 service 实现即可 ======= |
| | | public Map<String, Object> getDeviceState(Map<String, Object> args) { /* ... */ return new HashMap<>(); } |
| | | public Map<String, Object> listTasks(Map<String, Object> args) { /* ... */ return new HashMap<>(); } |
| | | public Map<String, Object> queryLogs(Map<String, Object> args) { /* ... */ return new HashMap<>(); } |
| | | public Object getSystemConfig(Map<String, Object> args) { /* ... */ return new HashMap<>(); } |
| | | |
| | | // helpers |
| | | private int getInt(Map<String, Object> m, String k, int def) { |
| | | Object v = m.get(k); |
| | | if (v == null) return def; |
| | | if (v instanceof Number) return ((Number) v).intValue(); |
| | | return Integer.parseInt(String.valueOf(v)); |
| | | } |
| | | private boolean getBool(Map<String, Object> m, String k, boolean def) { |
| | | Object v = m.get(k); |
| | | if (v == null) return def; |
| | | if (v instanceof Boolean) return (Boolean) v; |
| | | return Boolean.parseBoolean(String.valueOf(v)); |
| | | } |
| | | private List<String> safeList(List<String> l) { return l == null ? Collections.emptyList() : l; } |
| | | private String iso(Date d) { |
| | | SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); |
| | | f.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); |
| | | return f.format(d); |
| | | } |
| | | } |
| | |
| | | return R.error("线程不存在"); |
| | | } |
| | | DualCrnCommand command = crnThread.getPickAndPutCommand(sourceLocNo, targetLocNo, 9999, crnNo, station); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command)); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command)); |
| | | return R.ok(); |
| | | } |
| | | |
| | |
| | | return R.error("线程不存在"); |
| | | } |
| | | DualCrnCommand command = crnThread.getPickCommand(targetLocNo, 9999, crnNo, station); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command)); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command)); |
| | | return R.ok(); |
| | | } |
| | | |
| | |
| | | return R.error("线程不存在"); |
| | | } |
| | | DualCrnCommand command = crnThread.getPutCommand(targetLocNo, 9999, crnNo, station); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command)); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command)); |
| | | return R.ok(); |
| | | } |
| | | |
| | |
| | | if (station != null) { |
| | | command.setStation(station.shortValue()); |
| | | } |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command)); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command)); |
| | | return R.ok(); |
| | | } |
| | | |
| | |
| | | return R.error("线程不存在"); |
| | | } |
| | | DualCrnCommand command = crnThread.getResetCommand(crnNo, station); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, command)); |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command)); |
| | | return R.ok(); |
| | | } |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.annotations.TableId; |
| | | import com.baomidou.mybatisplus.enums.IdType; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.annotations.TableField; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | |
| | | package com.zy.asrs.entity; |
| | | |
| | | import com.core.common.Cools;import com.baomidou.mybatisplus.annotations.TableId; |
| | | import com.core.common.Cools; |
| | | import com.zy.core.model.StationObjModel; |
| | | import com.baomidou.mybatisplus.annotations.TableId; |
| | | import com.baomidou.mybatisplus.enums.IdType; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONArray; |
| | | import com.baomidou.mybatisplus.annotations.TableField; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import io.swagger.annotations.ApiModelProperty; |
| | |
| | | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime); |
| | | } |
| | | |
| | | public List<StationObjModel> getInStationList$(){ |
| | | List<StationObjModel> list = new ArrayList<>(); |
| | | if (Cools.isEmpty(this.inStationList)){ |
| | | return list; |
| | | } |
| | | |
| | | List<StationObjModel> jsonList = JSON.parseArray(this.inStationList,StationObjModel.class); |
| | | for (StationObjModel json : jsonList){ |
| | | list.add(json); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | public List<StationObjModel> getOutStationList$(){ |
| | | List<StationObjModel> list = new ArrayList<>(); |
| | | if (Cools.isEmpty(this.outStationList)){ |
| | | return list; |
| | | } |
| | | |
| | | List<StationObjModel> jsonList = JSON.parseArray(this.outStationList,StationObjModel.class); |
| | | for (StationObjModel json : jsonList){ |
| | | list.add(json); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | public List<List<Integer>> getControlRows$(){ |
| | | List<List<Integer>> rowList = new ArrayList<>(); |
| | | if(Cools.isEmpty(this.controlRows)){ |
| | | return rowList; |
| | | } |
| | | JSONArray list = JSON.parseArray(this.controlRows); |
| | | for (Object o : list) { |
| | | List<Integer> rows = JSON.parseArray(JSON.toJSONString(o), Integer.class); |
| | | rowList.add(rows); |
| | | } |
| | | return rowList; |
| | | } |
| | | |
| | | } |
| | |
| | | private Integer crnNo; |
| | | |
| | | /** |
| | | * 双工位堆垛机号 |
| | | */ |
| | | @ApiModelProperty(value= "双工位堆垛机号") |
| | | @TableField(value = "dual_crn_no",strategy = FieldStrategy.IGNORED) |
| | | private Integer dualCrnNo; |
| | | |
| | | /** |
| | | * RGV号 |
| | | */ |
| | | @ApiModelProperty(value= "RGV号") |
| | |
| | | import com.baomidou.mybatisplus.annotations.TableField; |
| | | import com.baomidou.mybatisplus.annotations.TableId; |
| | | import com.baomidou.mybatisplus.annotations.TableName; |
| | | import com.baomidou.mybatisplus.enums.FieldStrategy; |
| | | import com.baomidou.mybatisplus.enums.IdType; |
| | | import com.core.common.Cools; |
| | | import com.core.common.SpringUtils; |
| | |
| | | @TableField(value = "crn_no") |
| | | private Integer crnNo; |
| | | |
| | | /** |
| | | * 双工位堆垛机号 |
| | | */ |
| | | @ApiModelProperty(value= "双工位堆垛机号") |
| | | @TableField(value = "dual_crn_no") |
| | | private Integer dualCrnNo; |
| | | |
| | | /** |
| | | * RGV号 |
| | | */ |
| | |
| | | import com.core.common.SpringUtils; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.BasCrnp; |
| | | import com.zy.asrs.entity.BasDualCrnp; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.BasCrnpService; |
| | | import com.zy.asrs.service.BasDualCrnpService; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.common.model.NavigateNode; |
| | | import com.zy.common.utils.NavigateUtils; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import com.zy.core.News; |
| | | import com.zy.core.cache.SlaveConnection; |
| | | import com.zy.core.enums.CrnModeType; |
| | | import com.zy.core.enums.RedisKeyType; |
| | | import com.zy.core.enums.SlaveType; |
| | | import com.zy.core.enums.WrkIoType; |
| | | import com.zy.core.enums.*; |
| | | import com.zy.core.model.StationObjModel; |
| | | import com.zy.core.model.protocol.CrnProtocol; |
| | | import com.zy.core.model.protocol.DualCrnProtocol; |
| | | import com.zy.core.thread.CrnThread; |
| | | import com.zy.core.thread.DualCrnThread; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.text.DecimalFormat; |
| | |
| | | } |
| | | |
| | | //获取入库任务可用排 |
| | | public static List<Integer> getInTaskEnableRow() { |
| | | return getInTaskEnableRow(new ArrayList<>(), true); |
| | | public static List<Integer> getInTaskEnableRow(Integer stationId) { |
| | | return getInTaskEnableRow(stationId, new ArrayList<>(), new ArrayList<>(), true); |
| | | } |
| | | |
| | | //获取入库任务可用排 |
| | | public static List<Integer> getInTaskEnableRow(List<Integer> excludeCrnList, boolean maxInTaskControl) { |
| | | public static List<Integer> getInTaskEnableRow(Integer stationId, List<Integer> excludeCrnList, List<Integer> excludeDualCrnList, boolean maxInTaskControl) { |
| | | //获取堆垛机入库任务可用排 |
| | | List<Integer> rowList = getCrnInTaskEnableRow(stationId, excludeCrnList, maxInTaskControl); |
| | | //获取双工位堆垛机入库任务可用排 |
| | | List<Integer> dualRowList = getDualCrnInTaskEnableRow(stationId, excludeDualCrnList, maxInTaskControl); |
| | | if (!dualRowList.isEmpty()) { |
| | | rowList.addAll(dualRowList); |
| | | } |
| | | return rowList; |
| | | } |
| | | |
| | | //获取堆垛机入库任务可用排 |
| | | public static List<Integer> getCrnInTaskEnableRow(Integer stationId, List<Integer> excludeCrnList, boolean maxInTaskControl) { |
| | | List<Integer> list = new ArrayList<>(); |
| | | try { |
| | | RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); |
| | | NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class); |
| | | WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class); |
| | | BasCrnpService basCrnpService = SpringUtils.getBean(BasCrnpService.class); |
| | | |
| | |
| | | if (excludeCrnList.contains(basCrnp.getCrnNo())) { |
| | | continue; |
| | | } |
| | | enabledCrnps.add(basCrnp); |
| | | |
| | | //计算站点是否可达该堆垛机 |
| | | List<StationObjModel> inStationList = basCrnp.getInStationList$(); |
| | | boolean enableGo = false; |
| | | for (StationObjModel stationObjModel : inStationList) { |
| | | try { |
| | | List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(stationId, stationObjModel.getStationId()); |
| | | if(navigateNodes != null && !navigateNodes.isEmpty()) { |
| | | enableGo = true; |
| | | break; |
| | | } |
| | | } catch (Exception e) { |
| | | |
| | | } |
| | | } |
| | | |
| | | if (enableGo) { |
| | | enabledCrnps.add(basCrnp); |
| | | } |
| | | } |
| | | |
| | | enabledCrnps.sort(Comparator.comparingInt(o -> map.getOrDefault(o.getCrnNo(), 0))); |
| | |
| | | return list; |
| | | } |
| | | |
| | | //获取双工位堆垛机入库任务可用排 |
| | | public static List<Integer> getDualCrnInTaskEnableRow(Integer stationId, List<Integer> excludeCrnList, boolean maxInTaskControl) { |
| | | List<Integer> list = new ArrayList<>(); |
| | | try { |
| | | RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class); |
| | | NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class); |
| | | WrkMastService wrkMastService = SpringUtils.getBean(WrkMastService.class); |
| | | BasDualCrnpService basDualCrnpService = SpringUtils.getBean(BasDualCrnpService.class); |
| | | |
| | | Wrapper<BasDualCrnp> wrapper = new EntityWrapper<BasDualCrnp>() |
| | | .eq("in_enable", "Y") |
| | | .eq("status", 1); |
| | | |
| | | HashMap<Integer, Integer> map = new HashMap<>(); |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<>()); |
| | | List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(wrapper); |
| | | |
| | | for (WrkMast wrkMast : wrkMasts) { |
| | | Integer dualCrnNo = wrkMast.getDualCrnNo(); |
| | | map.put(dualCrnNo, map.getOrDefault(dualCrnNo, 0) + 1); |
| | | } |
| | | |
| | | List<BasDualCrnp> enabledCrnps = new ArrayList<>(); |
| | | for (BasDualCrnp basDualCrnp : basDualCrnps) { |
| | | DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, basDualCrnp.getCrnNo()); |
| | | if (dualCrnThread == null) { |
| | | continue; |
| | | } |
| | | DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus(); |
| | | if (dualCrnProtocol.getMode() != DualCrnModeType.AUTO.id) { |
| | | continue; |
| | | } |
| | | |
| | | List<WrkMast> inWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .eq("dual_crn_no", basDualCrnp.getCrnNo()) |
| | | .eq("io_type", WrkIoType.IN.id) |
| | | ); |
| | | // 检查是否超过最大入库任务数 |
| | | if (maxInTaskControl && inWrkMasts.size() >= basDualCrnp.getMaxInTask()) { |
| | | News.info("堆垛机:{} 已达最大入库任务数,当前任务数:{}", basDualCrnp.getCrnNo(), inWrkMasts.size()); |
| | | continue; |
| | | } |
| | | if (excludeCrnList.contains(basDualCrnp.getCrnNo())) { |
| | | continue; |
| | | } |
| | | |
| | | //计算站点是否可达该堆垛机 |
| | | List<StationObjModel> inStationList = basDualCrnp.getInStationList$(); |
| | | boolean enableGo = false; |
| | | for (StationObjModel stationObjModel : inStationList) { |
| | | try { |
| | | List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(stationId, stationObjModel.getStationId()); |
| | | if(navigateNodes != null && !navigateNodes.isEmpty()) { |
| | | enableGo = true; |
| | | break; |
| | | } |
| | | } catch (Exception e) { |
| | | |
| | | } |
| | | } |
| | | |
| | | if (enableGo) { |
| | | enabledCrnps.add(basDualCrnp); |
| | | } |
| | | } |
| | | |
| | | enabledCrnps.sort(Comparator.comparingInt(o -> map.getOrDefault(o.getCrnNo(), 0))); |
| | | |
| | | for (BasDualCrnp basDualCrnp : enabledCrnps) { |
| | | List<List<Integer>> rowList = basDualCrnp.getControlRows$(); |
| | | for (List<Integer> rows : rowList) { |
| | | list.addAll(rows); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | public static Map<String, Object> convertObjectToMap(Object obj) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | Class<?> clazz = obj.getClass(); |
| New file |
| | |
| | | package com.zy.common.entity; |
| | | |
| | | import com.zy.core.enums.SlaveType; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | public class FindCrnNoResult { |
| | | |
| | | private Integer crnNo; |
| | | |
| | | private SlaveType crnType; |
| | | |
| | | } |
| | |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.entity.FindCrnNoResult; |
| | | import com.zy.common.model.NavigateNode; |
| | | import com.zy.common.utils.NavigateUtils; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import com.zy.core.News; |
| | | import com.zy.core.enums.RedisKeyType; |
| | | import com.zy.core.enums.SlaveType; |
| | | import com.zy.core.enums.WrkIoType; |
| | | import com.zy.core.enums.WrkStsType; |
| | | import com.zy.core.model.StationObjModel; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | |
| | | private LocMastService locMastService; |
| | | @Autowired |
| | | private BasCrnpService basCrnpService; |
| | | @Autowired |
| | | private BasDualCrnpService basDualCrnpService; |
| | | @Autowired |
| | | private NavigateUtils navigateUtils; |
| | | @Autowired |
| | |
| | | ioPri = param.getTaskPri().doubleValue(); |
| | | } |
| | | |
| | | Integer sourceCrnNo = this.findCrnNoByLocNo(sourceLocMast.getLocNo()); |
| | | if (sourceCrnNo == null) { |
| | | FindCrnNoResult sourceCrnResult = this.findCrnNoByLocNo(sourceLocMast.getLocNo()); |
| | | if (sourceCrnResult == null) { |
| | | throw new CoolException("未找到对应堆垛机"); |
| | | } |
| | | |
| | | Integer crnNo = this.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (crnNo == null) { |
| | | FindCrnNoResult targetCrnResult = this.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (targetCrnResult == null) { |
| | | throw new CoolException("未找到对应堆垛机"); |
| | | } |
| | | |
| | | if (!sourceCrnNo.equals(crnNo)) { |
| | | if (!sourceCrnResult.getCrnNo().equals(targetCrnResult.getCrnNo())) { |
| | | throw new CoolException("源库位和目标库位不在同一巷道"); |
| | | } |
| | | Integer crnNo = targetCrnResult.getCrnNo(); |
| | | |
| | | // 获取工作号 |
| | | int workNo = getWorkNo(WrkIoType.LOC_MOVE.id); |
| | |
| | | ioPri = param.getTaskPri().doubleValue(); |
| | | } |
| | | |
| | | Integer crnNo = this.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (crnNo == null) { |
| | | FindCrnNoResult findCrnResult = this.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (findCrnResult == null) { |
| | | throw new CoolException("未找到对应堆垛机"); |
| | | } |
| | | Integer crnNo = findCrnResult.getCrnNo(); |
| | | |
| | | // 获取工作号 |
| | | int workNo = getWorkNo(WrkIoType.IN.id); |
| | |
| | | wrkMast.setStaNo(param.getStaNo());//目标站 |
| | | wrkMast.setWmsWrkNo(param.getTaskNo()); |
| | | wrkMast.setBarcode(param.getBarcode()); |
| | | wrkMast.setCrnNo(crnNo); |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiTime(now); |
| | | |
| | | if (findCrnResult.getCrnType().equals(SlaveType.Crn)) { |
| | | wrkMast.setCrnNo(findCrnResult.getCrnNo()); |
| | | |
| | | //缓存记录当前命令堆垛机编号 |
| | | redisUtil.set(RedisKeyType.CURRENT_CIRCLE_TASK_CRN_NO.key, crnNo, 60 * 60 * 24); |
| | | } else if (findCrnResult.getCrnType().equals(SlaveType.DualCrn)) { |
| | | wrkMast.setDualCrnNo(findCrnResult.getCrnNo()); |
| | | }else { |
| | | throw new CoolException("未知设备类型"); |
| | | } |
| | | |
| | | boolean res = wrkMastService.insert(wrkMast); |
| | | if (!res) { |
| | | News.error("入库任务 --- 保存工作档失败!"); |
| | |
| | | locMast.setLocSts("S"); |
| | | locMast.setModiTime(new Date()); |
| | | locMastService.updateById(locMast); |
| | | |
| | | //缓存记录当前命令堆垛机编号 |
| | | redisUtil.set(RedisKeyType.CURRENT_CIRCLE_TASK_CRN_NO.key, crnNo, 60 * 60 * 24); |
| | | return wrkMast; |
| | | } |
| | | |
| | |
| | | ioPri = param.getTaskPri().doubleValue(); |
| | | } |
| | | |
| | | Integer crnNo = this.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (crnNo == null) { |
| | | FindCrnNoResult findCrnResult = this.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (findCrnResult == null) { |
| | | throw new CoolException("未找到对应堆垛机"); |
| | | } |
| | | Integer crnNo = findCrnResult.getCrnNo(); |
| | | |
| | | Integer sourceStationId = this.findOutStationId(crnNo, param.getStaNo()); |
| | | Integer sourceStationId = this.findOutStationId(findCrnResult, param.getStaNo()); |
| | | if (sourceStationId == null) { |
| | | throw new CoolException("未找到输送目标站点可走行路径"); |
| | | } |
| | | |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if(basCrnp == null) { |
| | | throw new CoolException("未找到对应堆垛机数据"); |
| | | } |
| | | List<WrkMast> outWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .eq("crn_no", crnNo) |
| | | .eq("io_type", WrkIoType.OUT.id) |
| | | ); |
| | | // 检查是否超过最大出库任务数 |
| | | if(outWrkMasts.size() >= basCrnp.getMaxOutTask()){ |
| | | News.info("堆垛机:{} 已达最大出库任务数,当前任务数:{}", basCrnp.getCrnNo(), outWrkMasts.size()); |
| | | throw new CoolException("堆垛机:" + basCrnp.getCrnNo() + "已达最大出库任务数,当前任务数:" + outWrkMasts.size()); |
| | | } |
| | | |
| | | // 获取工作号 |
| | |
| | | wrkMast.setStaNo(param.getStaNo());//目标站 |
| | | wrkMast.setWmsWrkNo(param.getTaskNo()); |
| | | wrkMast.setBarcode(locMast.getBarcode()); |
| | | wrkMast.setCrnNo(crnNo); |
| | | wrkMast.setAppeTime(now); |
| | | wrkMast.setModiTime(now); |
| | | |
| | | if (findCrnResult.getCrnType().equals(SlaveType.Crn)) { |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if(basCrnp == null) { |
| | | throw new CoolException("未找到对应堆垛机数据"); |
| | | } |
| | | List<WrkMast> outWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .eq("crn_no", crnNo) |
| | | .eq("io_type", WrkIoType.OUT.id) |
| | | ); |
| | | // 检查是否超过最大出库任务数 |
| | | if(outWrkMasts.size() >= basCrnp.getMaxOutTask()){ |
| | | News.info("堆垛机:{} 已达最大出库任务数,当前任务数:{}", basCrnp.getCrnNo(), outWrkMasts.size()); |
| | | throw new CoolException("堆垛机:" + basCrnp.getCrnNo() + "已达最大出库任务数,当前任务数:" + outWrkMasts.size()); |
| | | } |
| | | |
| | | wrkMast.setCrnNo(findCrnResult.getCrnNo()); |
| | | } else if (findCrnResult.getCrnType().equals(SlaveType.DualCrn)) { |
| | | BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo)); |
| | | if(basDualCrnp == null) { |
| | | throw new CoolException("未找到对应双工位堆垛机数据"); |
| | | } |
| | | List<WrkMast> outWrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .eq("dual_crn_no", crnNo) |
| | | .eq("io_type", WrkIoType.OUT.id) |
| | | ); |
| | | // 检查是否超过最大出库任务数 |
| | | if(outWrkMasts.size() >= basDualCrnp.getMaxOutTask()){ |
| | | News.info("双工位堆垛机:{} 已达最大出库任务数,当前任务数:{}", basDualCrnp.getCrnNo(), outWrkMasts.size()); |
| | | throw new CoolException("双工位堆垛机:" + basDualCrnp.getCrnNo() + "已达最大出库任务数,当前任务数:" + outWrkMasts.size()); |
| | | } |
| | | |
| | | wrkMast.setDualCrnNo(findCrnResult.getCrnNo()); |
| | | }else { |
| | | throw new CoolException("未知设备类型"); |
| | | } |
| | | |
| | | boolean res = wrkMastService.insert(wrkMast); |
| | | if (!res) { |
| | | News.error("出库任务 --- 保存工作档失败!"); |
| | |
| | | return true; |
| | | } |
| | | |
| | | public Integer findCrnNoByLocNo(String locNo) { |
| | | public FindCrnNoResult findCrnNoByLocNo(String locNo) { |
| | | List<BasCrnp> basCrnps = basCrnpService.selectList(new EntityWrapper<>()); |
| | | for (BasCrnp basCrnp : basCrnps) { |
| | | List<List<Integer>> rowList = basCrnp.getControlRows$(); |
| | | for (List<Integer> rows : rowList) { |
| | | if(rows.contains(Utils.getRow(locNo))) { |
| | | return basCrnp.getCrnNo(); |
| | | FindCrnNoResult result = new FindCrnNoResult(); |
| | | result.setCrnNo(basCrnp.getCrnNo()); |
| | | result.setCrnType(SlaveType.Crn); |
| | | return result; |
| | | } |
| | | } |
| | | } |
| | | |
| | | List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>()); |
| | | for (BasDualCrnp basDualCrnp : basDualCrnps) { |
| | | List<List<Integer>> rowList = basDualCrnp.getControlRows$(); |
| | | for (List<Integer> rows : rowList) { |
| | | if(rows.contains(Utils.getRow(locNo))) { |
| | | FindCrnNoResult result = new FindCrnNoResult(); |
| | | result.setCrnNo(basDualCrnp.getCrnNo()); |
| | | result.setCrnType(SlaveType.DualCrn); |
| | | return result; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | public Integer findInStationId(Integer crnNo, Integer sourceStationId) { |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if(basCrnp == null) { |
| | | return null; |
| | | public Integer findInStationId(FindCrnNoResult findCrnNoResult, Integer sourceStationId) { |
| | | List<StationObjModel> stationList = new ArrayList<>(); |
| | | Integer crnNo = findCrnNoResult.getCrnNo(); |
| | | if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) { |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if(basCrnp == null) { |
| | | return null; |
| | | } |
| | | stationList = basCrnp.getInStationList$(); |
| | | } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) { |
| | | BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo)); |
| | | if(basDualCrnp == null) { |
| | | return null; |
| | | } |
| | | stationList = basDualCrnp.getInStationList$(); |
| | | } |
| | | |
| | | Integer targetStationId = null; |
| | | List<StationObjModel> stationList = basCrnp.getInStationList$(); |
| | | for (StationObjModel stationObjModel : stationList) { |
| | | try { |
| | | List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(sourceStationId, stationObjModel.getStationId()); |
| | |
| | | return targetStationId; |
| | | } |
| | | |
| | | public Integer findOutStationId(Integer crnNo, Integer targetStationId) { |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if(basCrnp == null) { |
| | | return null; |
| | | public Integer findOutStationId(FindCrnNoResult findCrnNoResult, Integer targetStationId) { |
| | | List<StationObjModel> stationList = new ArrayList<>(); |
| | | Integer crnNo = findCrnNoResult.getCrnNo(); |
| | | if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) { |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if(basCrnp == null) { |
| | | return null; |
| | | } |
| | | stationList = basCrnp.getOutStationList$(); |
| | | } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) { |
| | | BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo)); |
| | | if(basDualCrnp == null) { |
| | | return null; |
| | | } |
| | | stationList = basDualCrnp.getOutStationList$(); |
| | | } |
| | | |
| | | Integer finalSourceStationId = null; |
| | | List<StationObjModel> stationList = basCrnp.getOutStationList$(); |
| | | for (StationObjModel stationObjModel : stationList) { |
| | | try { |
| | | List<NavigateNode> navigateNodes = navigateUtils.calcByStationId(stationObjModel.getStationId(), targetStationId); |
| | |
| | | LIFT_WORK_FLAG("lift_wrk_no_"), |
| | | LIFT_FLAG("lift_"), |
| | | |
| | | DUAL_CRN_COMMAND_("dual_crn_command_"), |
| | | |
| | | QUEUE_CRN("queue_crn_"), |
| | | QUEUE_DEVP("queue_devp_"), |
| | | QUEUE_RGV("queue_rgv_"), |
| | |
| | | CHECK_OUT_STATION_STAY_TIME_OUT_LIMIT("check_out_station_stay_time_out_limit_"), |
| | | CHECK_IN_STATION_STAY_TIME_OUT_LIMIT("check_in_station_stay_time_out_limit_"), |
| | | CRN_IO_EXECUTE_FINISH_LIMIT("crn_io_execute_finish_limit_"), |
| | | DUAL_CRN_IO_EXECUTE_FINISH_LIMIT("dual_crn_io_execute_finish_limit_"), |
| | | STATION_IN_EXECUTE_LIMIT("station_in_execute_limit_"), |
| | | STATION_OUT_EXECUTE_LIMIT("station_out_execute_limit_"), |
| | | CHECK_STATION_RUN_BLOCK_LIMIT_("check_station_run_block_limit_"), |
| | | CHECK_SHALLOW_LOC_STATUS_LIMIT("check_shallow_loc_status_limit_"), |
| | | |
| | | DUAL_CRN_PICK_WAIT_NEXT_TASK("dual_crn_pick_wait_next_task_"), |
| | | |
| | | CURRENT_CIRCLE_TASK_CRN_NO("current_circle_task_crn_no_"), |
| | | AI_CHAT_HISTORY("ai_chat_history_"), |
| | | AI_CHAT_META("ai_chat_meta_"), |
| | |
| | | |
| | | private void commandTaskComplete(DualCrnCommand command) { |
| | | if(command.getStation() == 1) { |
| | | this.crnStatus.setTaskNo(0); |
| | | if (crnStatus.getLoaded() == 0) { |
| | | this.crnStatus.setTaskNo(0); |
| | | } |
| | | this.crnStatus.setTaskReceive(0); |
| | | this.crnStatus.setStatus(CrnStatusType.IDLE.id); |
| | | }else { |
| | | this.crnStatus.setTaskNoTwo(0); |
| | | if (crnStatus.getLoadedTwo() == 0) { |
| | | this.crnStatus.setTaskNoTwo(0); |
| | | } |
| | | this.crnStatus.setTaskReceiveTwo(0); |
| | | this.crnStatus.setStatusTwo(CrnStatusType.IDLE.id); |
| | | } |
| | |
| | | import com.zy.asrs.domain.param.CreateOutTaskParam; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.common.entity.FindCrnNoResult; |
| | | import com.zy.common.model.StartupDto; |
| | | import com.zy.common.service.CommonService; |
| | | import com.zy.common.utils.RedisUtil; |
| | |
| | | import com.zy.core.model.command.CrnCommand; |
| | | import com.zy.core.model.command.StationCommand; |
| | | import com.zy.core.model.protocol.CrnProtocol; |
| | | import com.zy.core.model.protocol.DualCrnProtocol; |
| | | import com.zy.core.model.protocol.StationProtocol; |
| | | import com.zy.core.properties.SystemProperties; |
| | | import com.zy.core.thread.CrnThread; |
| | | import com.zy.core.thread.DualCrnThread; |
| | | import com.zy.core.thread.StationThread; |
| | | import com.zy.core.utils.CrnOperateProcessUtils; |
| | | import com.zy.core.utils.DualCrnOperateProcessUtils; |
| | | import com.zy.core.utils.StationOperateProcessUtils; |
| | | import com.zy.core.utils.WmsOperateUtils; |
| | | import com.zy.system.entity.Config; |
| | |
| | | @Autowired |
| | | private BasCrnpService basCrnpService; |
| | | @Autowired |
| | | private BasDualCrnpService basDualCrnpService; |
| | | @Autowired |
| | | private RedisUtil redisUtil; |
| | | @Autowired |
| | | private CrnOperateProcessUtils crnOperateUtils; |
| | |
| | | private StationOperateProcessUtils stationOperateProcessUtils; |
| | | @Autowired |
| | | private WmsOperateUtils wmsOperateUtils; |
| | | @Autowired |
| | | private DualCrnOperateProcessUtils dualCrnOperateProcessUtils; |
| | | |
| | | @Override |
| | | public void run() { |
| | |
| | | stationOperateProcessUtils.stationOutExecute(); |
| | | //检测输送站点出库任务执行完成 |
| | | stationOperateProcessUtils.stationOutExecuteFinish(); |
| | | |
| | | //执行双工位堆垛机任务 |
| | | dualCrnOperateProcessUtils.dualRrnIoExecute(); |
| | | //双工位堆垛机任务执行完成 |
| | | dualCrnOperateProcessUtils.dualCrnIoExecuteFinish(); |
| | | } |
| | | |
| | | public void asyncRun() { |
| | |
| | | int nextInt = new Random().nextInt(locMastList.size()); |
| | | LocMast locMast = locMastList.get(nextInt); |
| | | |
| | | Integer crnNo = commonService.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (crnNo == null) { |
| | | FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (findCrnNoResult == null) { |
| | | continue; |
| | | } |
| | | |
| | | Integer targetStationId = commonService.findInStationId(crnNo, stationId); |
| | | Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationId); |
| | | if (targetStationId == null) { |
| | | continue; |
| | | } |
| | |
| | | } |
| | | |
| | | LocMast locMast = locMastList.get(0); |
| | | |
| | | Integer crnNo = commonService.findCrnNoByLocNo(locMast.getLocNo()); |
| | | if (crnNo == null) { |
| | | continue; |
| | | } |
| | | |
| | | CreateOutTaskParam taskParam = new CreateOutTaskParam(); |
| | | taskParam.setTaskNo(String.valueOf(commonService.getWorkNo(WrkIoType.OUT.id))); |
| | |
| | | News.info("堆垛机:{} 入库站点未设置", basCrnp.getCrnNo()); |
| | | continue; |
| | | } |
| | | checkInStationListCrnTake(inStationList); |
| | | } |
| | | |
| | | for (StationObjModel stationObjModel : inStationList) { |
| | | Object lock = redisUtil.get(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId()); |
| | | if(lock != null){ |
| | | continue; |
| | | } |
| | | List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>()); |
| | | for (BasDualCrnp basDualCrnp : basDualCrnps) { |
| | | List<StationObjModel> inStationList = basDualCrnp.getInStationList$(); |
| | | if(inStationList.isEmpty()){ |
| | | News.info("双工位堆垛机:{} 入库站点未设置", basDualCrnp.getCrnNo()); |
| | | continue; |
| | | } |
| | | checkInStationListCrnTake(inStationList); |
| | | } |
| | | } |
| | | |
| | | StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo()); |
| | | if(stationThread == null){ |
| | | continue; |
| | | } |
| | | private void checkInStationListCrnTake(List<StationObjModel> inStationList) { |
| | | for (StationObjModel stationObjModel : inStationList) { |
| | | Object lock = redisUtil.get(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId()); |
| | | if(lock != null){ |
| | | continue; |
| | | } |
| | | |
| | | StationCommand command = stationThread.getMoveCommand(0, stationObjModel.getStationId(), 0, 0); |
| | | if(command == null){ |
| | | continue; |
| | | } |
| | | StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo()); |
| | | if(stationThread == null){ |
| | | continue; |
| | | } |
| | | |
| | | Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap(); |
| | | StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId()); |
| | | if (stationProtocol == null) { |
| | | continue; |
| | | } |
| | | StationCommand command = stationThread.getMoveCommand(0, stationObjModel.getStationId(), 0, 0); |
| | | if(command == null){ |
| | | continue; |
| | | } |
| | | |
| | | if(stationProtocol.getTaskNo() > 0) { |
| | | WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo()); |
| | | if (wrkMast == null) { |
| | | MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); |
| | | redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10); |
| | | News.info("输送站点重置命令下发成功(task_over),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command)); |
| | | }else { |
| | | if (wrkMast.getWrkSts() != WrkStsType.NEW_INBOUND.sts && wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts) { |
| | | Integer crnNo = wrkMast.getCrnNo(); |
| | | Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap(); |
| | | StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId()); |
| | | if (stationProtocol == null) { |
| | | continue; |
| | | } |
| | | |
| | | if(stationProtocol.getTaskNo() > 0) { |
| | | WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo()); |
| | | if (wrkMast == null) { |
| | | MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); |
| | | redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10); |
| | | News.info("输送站点重置命令下发成功(task_over),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command)); |
| | | }else { |
| | | if (wrkMast.getWrkSts() != WrkStsType.NEW_INBOUND.sts && wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts) { |
| | | Integer crnNo = wrkMast.getCrnNo(); |
| | | if (crnNo != null) { |
| | | CrnThread crnThread = (CrnThread) SlaveConnection.get(SlaveType.Crn, crnNo); |
| | | if (crnThread == null) { |
| | | continue; |
| | |
| | | MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); |
| | | redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10); |
| | | News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command)); |
| | | }else { |
| | | Integer dualCrnNo = wrkMast.getDualCrnNo(); |
| | | DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, dualCrnNo); |
| | | if (dualCrnThread == null) { |
| | | continue; |
| | | } |
| | | DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus(); |
| | | if (!dualCrnProtocol.getStatusType().equals(DualCrnStatusType.PUT_MOVING) && !dualCrnProtocol.getStatusType().equals(DualCrnStatusType.PUTTING)) { |
| | | continue; |
| | | } |
| | | |
| | | MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command)); |
| | | redisUtil.set(RedisKeyType.CHECK_IN_STATION_STAY_TIME_OUT_LIMIT.key + stationObjModel.getStationId(), "lock",10); |
| | | News.info("输送站点重置命令下发成功(crn_fetch),站点号={},命令数据={}", stationObjModel.getStationId(), JSON.toJSONString(command)); |
| | | } |
| | | } |
| | | } |
| | |
| | | package com.zy.core.thread.impl; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.alibaba.fastjson.serializer.SerializerFeature; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.DateUtils; |
| | | import com.core.common.SpringUtils; |
| | |
| | | import com.zy.asrs.service.BasDualCrnpService; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import com.zy.core.News; |
| | | import com.zy.core.cache.MessageQueue; |
| | | import com.zy.core.cache.OutputQueue; |
| | | import com.zy.core.enums.DualCrnTaskModeType; |
| | | import com.zy.core.enums.RedisKeyType; |
| | | import com.zy.core.enums.SlaveType; |
| | | import com.zy.core.enums.*; |
| | | import com.zy.core.model.CommandResponse; |
| | | import com.zy.core.model.Task; |
| | | import com.zy.core.model.command.DualCrnCommand; |
| | |
| | | |
| | | import java.text.MessageFormat; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.ThreadFactory; |
| | |
| | | private volatile boolean closed = false; |
| | | private ScheduledExecutorService readExecutor; |
| | | private ScheduledExecutorService processExecutor; |
| | | private ScheduledExecutorService commandExecutor; |
| | | |
| | | public ZySiemensDualCrnThread(DeviceConfig deviceConfig, RedisUtil redisUtil) { |
| | | this.deviceConfig = deviceConfig; |
| | |
| | | if (task != null) { |
| | | step = task.getStep(); |
| | | } |
| | | if (step == 2 && task != null) { |
| | | |
| | | if (step == 2) { |
| | | List<DualCrnCommand> commandList = (List<DualCrnCommand>) task.getData(); |
| | | DualCrnCommand command = commandList.get(0); |
| | | |
| | | HashMap<String, Object> map = new HashMap<>(); |
| | | map.put("commands", commandList); |
| | | map.put("idx", 1); |
| | | redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + command.getTaskNo(), JSON.toJSONString(map, SerializerFeature.DisableCircularReferenceDetect), 60 * 60 * 24); |
| | | sendCommand(command); |
| | | } else if (step == 3) { |
| | | sendCommand((DualCrnCommand) task.getData()); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | }, 0, 200, TimeUnit.MILLISECONDS); |
| | | |
| | | commandExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { |
| | | @Override |
| | | public Thread newThread(Runnable r) { |
| | | Thread t = new Thread(r); |
| | | t.setName("DualCrnCommand-" + deviceConfig.getDeviceNo()); |
| | | t.setDaemon(true); |
| | | return t; |
| | | } |
| | | }); |
| | | commandExecutor.scheduleAtFixedRate(() -> { |
| | | if (closed || Thread.currentThread().isInterrupted()) { |
| | | return; |
| | | } |
| | | try { |
| | | if(crnProtocol.getMode() != DualCrnModeType.AUTO.id) { |
| | | return; |
| | | } |
| | | |
| | | if(crnProtocol.getAlarm() != 0) { |
| | | return; |
| | | } |
| | | |
| | | //等待下一个任务 |
| | | Object wait = redisUtil.get(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnProtocol.getCrnNo()); |
| | | if (wait != null) { |
| | | return; |
| | | } |
| | | |
| | | if(crnProtocol.getTaskNo() > 0 && crnProtocol.getStatus() == DualCrnStatusType.IDLE.id) { |
| | | Integer taskNo = crnProtocol.getTaskNo(); |
| | | Object commandObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo); |
| | | if (commandObj == null) { |
| | | News.error("双工位堆垛机,工位1空闲等待下发命令,但未找到命令。堆垛机号={},工作号={}", crnProtocol.getCrnNo(), taskNo); |
| | | return; |
| | | } |
| | | |
| | | JSONObject commandMap = JSON.parseObject(commandObj.toString()); |
| | | Integer idx = commandMap.getInteger("idx"); |
| | | List<DualCrnCommand> commandList = commandMap.getJSONArray("commands").toJavaList(DualCrnCommand.class); |
| | | DualCrnCommand dualCommand = commandList.get(idx); |
| | | idx++; |
| | | commandMap.put("idx", idx); |
| | | sendCommand(dualCommand); |
| | | redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo, commandMap.toJSONString(), 60 * 60 * 24); |
| | | } |
| | | |
| | | if(crnProtocol.getTaskNoTwo() > 0 && crnProtocol.getStatusTwo() == DualCrnStatusType.IDLE.id) { |
| | | Integer taskNo = crnProtocol.getTaskNoTwo(); |
| | | Object commandObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo); |
| | | if (commandObj == null) { |
| | | News.error("双工位堆垛机,工位2空闲等待下发命令,但未找到命令。堆垛机号={},工作号={}", crnProtocol.getCrnNo(), taskNo); |
| | | return; |
| | | } |
| | | |
| | | JSONObject commandMap = JSON.parseObject(commandObj.toString()); |
| | | Integer idx = commandMap.getInteger("idx"); |
| | | List<DualCrnCommand> commandList = commandMap.getJSONArray("commands").toJavaList(DualCrnCommand.class); |
| | | DualCrnCommand dualCommand = commandList.get(idx); |
| | | idx++; |
| | | commandMap.put("idx", idx); |
| | | sendCommand(dualCommand); |
| | | redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + taskNo, commandMap.toJSONString(), 60 * 60 * 24); |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | log.error("DualCrnCommandThread Fail", e); |
| | | } |
| | | }, 0, 200, TimeUnit.MILLISECONDS); |
| | | } |
| | | |
| | | /** |
| New file |
| | |
| | | package com.zy.core.utils; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.domain.param.CreateLocMoveTaskParam; |
| | | import com.zy.asrs.entity.BasCrnp; |
| | | import com.zy.asrs.entity.BasDualCrnp; |
| | | import com.zy.asrs.entity.LocMast; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.BasDualCrnpService; |
| | | import com.zy.asrs.service.LocMastService; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.model.StartupDto; |
| | | import com.zy.common.service.CommonService; |
| | | import com.zy.common.utils.RedisUtil; |
| | | import com.zy.core.News; |
| | | import com.zy.core.cache.MessageQueue; |
| | | import com.zy.core.cache.SlaveConnection; |
| | | import com.zy.core.enums.*; |
| | | import com.zy.core.model.StationObjModel; |
| | | import com.zy.core.model.Task; |
| | | import com.zy.core.model.command.CrnCommand; |
| | | import com.zy.core.model.command.DualCrnCommand; |
| | | import com.zy.core.model.protocol.CrnProtocol; |
| | | import com.zy.core.model.protocol.DualCrnProtocol; |
| | | import com.zy.core.model.protocol.StationProtocol; |
| | | import com.zy.core.thread.CrnThread; |
| | | import com.zy.core.thread.DualCrnThread; |
| | | import com.zy.core.thread.StationThread; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @Component |
| | | public class DualCrnOperateProcessUtils { |
| | | |
| | | @Autowired |
| | | private WrkMastService wrkMastService; |
| | | @Autowired |
| | | private BasDualCrnpService basDualCrnpService; |
| | | @Autowired |
| | | private LocMastService locMastService; |
| | | @Autowired |
| | | private RedisUtil redisUtil; |
| | | @Autowired |
| | | private WmsOperateUtils wmsOperateUtils; |
| | | @Autowired |
| | | private CommonService commonService; |
| | | |
| | | //入出库 ===>> 双工位堆垛机入出库作业下发 |
| | | public synchronized void dualRrnIoExecute() { |
| | | List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>()); |
| | | for (BasDualCrnp basDualCrnp : basDualCrnps) { |
| | | DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, basDualCrnp.getCrnNo()); |
| | | if(dualCrnThread == null){ |
| | | continue; |
| | | } |
| | | |
| | | DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus(); |
| | | if(dualCrnProtocol == null){ |
| | | continue; |
| | | } |
| | | |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .eq("dual_crn_no", basDualCrnp.getCrnNo()) |
| | | .in("wrk_sts", WrkStsType.INBOUND_RUN.sts, WrkStsType.OUTBOUND_RUN.sts) |
| | | ); |
| | | if(wrkMasts.size() >= 2){ |
| | | continue; |
| | | } |
| | | |
| | | if(dualCrnProtocol.getMode() != DualCrnModeType.AUTO.id) { |
| | | continue; |
| | | } |
| | | |
| | | if(dualCrnProtocol.getAlarm() != 0) { |
| | | continue; |
| | | } |
| | | |
| | | int executeTaskNo = 0; |
| | | if (dualCrnProtocol.getTaskNo() > 0) { |
| | | executeTaskNo = dualCrnProtocol.getTaskNo(); |
| | | } |
| | | if (dualCrnProtocol.getTaskNoTwo() > 0) { |
| | | executeTaskNo = dualCrnProtocol.getTaskNoTwo(); |
| | | } |
| | | |
| | | if (executeTaskNo > 0) { |
| | | WrkMast wrkMast = wrkMastService.selectByWorkNo(executeTaskNo); |
| | | if (wrkMast != null) { |
| | | if (wrkMast.getIoType().equals(WrkIoType.IN.id)) { |
| | | this.crnExecuteIn(basDualCrnp, dualCrnThread); // 入库 |
| | | } else if (wrkMast.getIoType().equals(WrkIoType.OUT.id)) { |
| | | this.crnExecuteOut(basDualCrnp, dualCrnThread); // 出库 |
| | | }else { |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 如果最近一次是入库模式 |
| | | if (dualCrnProtocol.getLastIo().equals("I")) { |
| | | if (basDualCrnp.getInEnable().equals("Y")) { |
| | | this.crnExecuteIn(basDualCrnp, dualCrnThread); // 入库 |
| | | dualCrnProtocol.setLastIo("O"); |
| | | } else if (basDualCrnp.getOutEnable().equals("Y")) { |
| | | this.crnExecuteOut(basDualCrnp, dualCrnThread); // 出库 |
| | | dualCrnProtocol.setLastIo("I"); |
| | | } |
| | | } |
| | | // 如果最近一次是出库模式 |
| | | else if (dualCrnProtocol.getLastIo().equals("O")) { |
| | | if (basDualCrnp.getOutEnable().equals("Y")) { |
| | | this.crnExecuteOut(basDualCrnp, dualCrnThread); // 出库 |
| | | dualCrnProtocol.setLastIo("I"); |
| | | } else if (basDualCrnp.getInEnable().equals("Y")) { |
| | | this.crnExecuteIn(basDualCrnp, dualCrnThread); // 入库 |
| | | dualCrnProtocol.setLastIo("O"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private synchronized void crnExecuteIn(BasDualCrnp basDualCrnp, DualCrnThread dualCrnThread) { |
| | | DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus(); |
| | | if(dualCrnProtocol == null){ |
| | | return; |
| | | } |
| | | |
| | | if(!basDualCrnp.getInEnable().equals("Y")){ |
| | | News.info("双工位堆垛机:{} 可入信号不满足", basDualCrnp.getCrnNo()); |
| | | return; |
| | | } |
| | | |
| | | List<StationObjModel> inStationList = basDualCrnp.getInStationList$(); |
| | | if(inStationList.isEmpty()){ |
| | | News.info("双工位堆垛机:{} 入库站点未设置", basDualCrnp.getCrnNo()); |
| | | return; |
| | | } |
| | | |
| | | Integer crnNo = basDualCrnp.getCrnNo(); |
| | | int station = calcStation(dualCrnProtocol); |
| | | if(station == 0){ |
| | | News.info("双工位堆垛机:{} 无可用工位", basDualCrnp.getCrnNo()); |
| | | return; |
| | | } |
| | | |
| | | for (StationObjModel stationObjModel : inStationList) { |
| | | StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo()); |
| | | if (stationThread == null) { |
| | | continue; |
| | | } |
| | | |
| | | Map<Integer, StationProtocol> stationProtocolMap = stationThread.getStatusMap(); |
| | | StationProtocol stationProtocol = stationProtocolMap.get(stationObjModel.getStationId()); |
| | | if (stationProtocol == null) { |
| | | continue; |
| | | } |
| | | |
| | | if (!stationProtocol.isAutoing()) { |
| | | continue; |
| | | } |
| | | |
| | | if (!stationProtocol.isLoading()) { |
| | | continue; |
| | | } |
| | | |
| | | if (stationProtocol.getTaskNo() <= 0) { |
| | | continue; |
| | | } |
| | | |
| | | if (!stationProtocol.isInEnable()) { |
| | | News.taskInfo(stationProtocol.getTaskNo(), "取货站点:{} 没有可入信号", stationObjModel.getStationId()); |
| | | continue; |
| | | } |
| | | |
| | | // 获取任务 |
| | | WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo()); |
| | | if (null == wrkMast) { |
| | | News.taskInfo(stationProtocol.getTaskNo(), "工作号:{} 任务信息不存在", stationProtocol.getTaskNo()); |
| | | continue; |
| | | } |
| | | |
| | | if(wrkMast.getWrkSts() != WrkStsType.INBOUND_DEVICE_RUN.sts){ |
| | | News.taskInfo(stationProtocol.getTaskNo(), "工作号:{} 任务状态异常", stationProtocol.getTaskNo()); |
| | | continue; |
| | | } |
| | | |
| | | // 获取库位信息 |
| | | LocMast locMast = locMastService.selectById(wrkMast.getLocNo()); |
| | | if (locMast == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "目标库位:{} 信息不存在", wrkMast.getLocNo()); |
| | | continue; |
| | | } |
| | | |
| | | if (!locMast.getLocSts().equals("S")) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "目标库位:{} 状态异常", wrkMast.getLocNo()); |
| | | continue; |
| | | } |
| | | |
| | | //检测浅库位状态 |
| | | boolean checkStatus = checkShallowLocStatus(locMast.getLocNo(), wrkMast.getWrkNo()); |
| | | if (!checkStatus) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "因浅库位堵塞无法执行"); |
| | | continue; |
| | | } |
| | | |
| | | String sourceLocNo = Utils.getLocNo(stationObjModel.getDeviceRow(), stationObjModel.getDeviceBay(), stationObjModel.getDeviceLev()); |
| | | |
| | | List<DualCrnCommand> commandList = new ArrayList<>(); |
| | | DualCrnCommand pickCommand = dualCrnThread.getPickCommand(sourceLocNo, wrkMast.getWrkNo(), crnNo, station); |
| | | DualCrnCommand putCommand = dualCrnThread.getPutCommand(wrkMast.getLocNo(), wrkMast.getWrkNo(), crnNo, station); |
| | | commandList.add(pickCommand); |
| | | commandList.add(putCommand); |
| | | |
| | | wrkMast.setWrkSts(WrkStsType.INBOUND_RUN.sts); |
| | | wrkMast.setDualCrnNo(crnNo); |
| | | wrkMast.setSystemMsg(""); |
| | | wrkMast.setIoTime(new Date()); |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, commandList)); |
| | | News.info("双工位堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(commandList)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private synchronized void crnExecuteOut(BasDualCrnp basDualCrnp, DualCrnThread dualCrnThread) { |
| | | DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus(); |
| | | if(dualCrnProtocol == null){ |
| | | return; |
| | | } |
| | | |
| | | if(!basDualCrnp.getOutEnable().equals("Y")){ |
| | | News.info("双工位堆垛机:{} 可出信号不满足", basDualCrnp.getCrnNo()); |
| | | return; |
| | | } |
| | | |
| | | List<StationObjModel> outStationList = basDualCrnp.getOutStationList$(); |
| | | if(outStationList.isEmpty()){ |
| | | News.info("双工位堆垛机:{} 出库站点未设置", basDualCrnp.getCrnNo()); |
| | | return; |
| | | } |
| | | |
| | | Integer crnNo = basDualCrnp.getCrnNo(); |
| | | int station = calcStation(dualCrnProtocol); |
| | | if(station == 0){ |
| | | News.info("双工位堆垛机:{} 无可用工位", basDualCrnp.getCrnNo()); |
| | | return; |
| | | } |
| | | |
| | | List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>() |
| | | .eq("crn_no", crnNo) |
| | | .eq("wrk_sts", WrkStsType.NEW_OUTBOUND.sts) |
| | | ); |
| | | |
| | | for (WrkMast wrkMast : wrkMasts) { |
| | | for (StationObjModel stationObjModel : outStationList) { |
| | | StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo()); |
| | | if (stationThread == null) { |
| | | continue; |
| | | } |
| | | |
| | | Map<Integer, StationProtocol> stationProtocolMap = stationThread.getStatusMap(); |
| | | StationProtocol stationProtocol = stationProtocolMap.get(stationObjModel.getStationId()); |
| | | if (stationProtocol == null) { |
| | | continue; |
| | | } |
| | | |
| | | if (!stationProtocol.isAutoing()) { |
| | | continue; |
| | | } |
| | | |
| | | if (stationProtocol.isLoading()) { |
| | | continue; |
| | | } |
| | | |
| | | if (stationProtocol.getTaskNo() != 0) { |
| | | continue; |
| | | } |
| | | |
| | | if (!stationProtocol.isOutEnable()) { |
| | | News.info("放货站点:{} 没有可出信号", stationObjModel.getStationId()); |
| | | continue; |
| | | } |
| | | |
| | | // 获取库位信息 |
| | | LocMast locMast = locMastService.selectById(wrkMast.getSourceLocNo()); |
| | | if (locMast == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 信息不存在", wrkMast.getSourceLocNo()); |
| | | continue; |
| | | } |
| | | |
| | | if (!locMast.getLocSts().equals("R")) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "源库位:{} 状态异常", wrkMast.getSourceLocNo()); |
| | | continue; |
| | | } |
| | | |
| | | //检测浅库位状态 |
| | | boolean checkStatus = checkShallowLocStatus(locMast.getLocNo(), wrkMast.getWrkNo()); |
| | | if (!checkStatus) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "因浅库位堵塞无法执行"); |
| | | continue; |
| | | } |
| | | |
| | | String targetLocNo = Utils.getLocNo(stationObjModel.getDeviceRow(), stationObjModel.getDeviceBay(), stationObjModel.getDeviceLev()); |
| | | |
| | | List<DualCrnCommand> commandList = new ArrayList<>(); |
| | | DualCrnCommand pickCommand = dualCrnThread.getPickCommand(wrkMast.getSourceLocNo(), wrkMast.getWrkNo(), crnNo, station); |
| | | DualCrnCommand putCommand = dualCrnThread.getPutCommand(targetLocNo, wrkMast.getWrkNo(), crnNo, station); |
| | | commandList.add(pickCommand); |
| | | commandList.add(putCommand); |
| | | |
| | | wrkMast.setWrkSts(WrkStsType.OUTBOUND_RUN.sts); |
| | | wrkMast.setDualCrnNo(crnNo); |
| | | wrkMast.setSystemMsg(""); |
| | | wrkMast.setIoTime(new Date()); |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(2, commandList)); |
| | | //取货后等待下一个任务时长 |
| | | redisUtil.set(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnNo, "wait", 5); |
| | | News.info("双工位堆垛机命令下发成功,堆垛机号={},任务数据={}", crnNo, JSON.toJSON(commandList)); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | //双工位堆垛机任务执行完成 |
| | | public synchronized void dualCrnIoExecuteFinish() { |
| | | List<BasDualCrnp> basDualCrnps = basDualCrnpService.selectList(new EntityWrapper<>()); |
| | | for (BasDualCrnp basDualCrnp : basDualCrnps) { |
| | | DualCrnThread dualCrnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, basDualCrnp.getCrnNo()); |
| | | if(dualCrnThread == null){ |
| | | continue; |
| | | } |
| | | |
| | | DualCrnProtocol dualCrnProtocol = dualCrnThread.getStatus(); |
| | | if(dualCrnProtocol == null){ |
| | | continue; |
| | | } |
| | | |
| | | if(dualCrnProtocol.getMode() != DualCrnModeType.AUTO.id) { |
| | | continue; |
| | | } |
| | | |
| | | if(dualCrnProtocol.getAlarm() != 0) { |
| | | continue; |
| | | } |
| | | |
| | | if(dualCrnProtocol.getTaskNo() > 0 && dualCrnProtocol.getStatus() == DualCrnStatusType.WAITING.id) { |
| | | executeFinish(basDualCrnp, dualCrnThread, dualCrnProtocol, dualCrnProtocol.getTaskNo(), 1); |
| | | continue; |
| | | } |
| | | |
| | | if(dualCrnProtocol.getTaskNoTwo() > 0 && dualCrnProtocol.getStatusTwo() == DualCrnStatusType.WAITING.id) { |
| | | executeFinish(basDualCrnp, dualCrnThread, dualCrnProtocol, dualCrnProtocol.getTaskNoTwo(), 2); |
| | | continue; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void executeFinish(BasDualCrnp basDualCrnp, DualCrnThread dualCrnThread, DualCrnProtocol dualCrnProtocol, int taskNo, int station) { |
| | | Object lock = redisUtil.get(RedisKeyType.DUAL_CRN_IO_EXECUTE_FINISH_LIMIT.key + basDualCrnp.getCrnNo() + "_" + taskNo); |
| | | if (lock != null) { |
| | | return; |
| | | } |
| | | |
| | | // 获取待确认工作档 |
| | | WrkMast wrkMast = wrkMastService.selectByWorkNo(taskNo); |
| | | if (wrkMast == null) { |
| | | News.error("双工位堆垛机处于等待确认且任务完成状态,但未找到工作档。堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo); |
| | | return; |
| | | } |
| | | |
| | | Object commandObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + wrkMast.getWrkNo()); |
| | | if (commandObj == null) { |
| | | News.error("双工位堆垛机处于等待确认且任务完成状态,但未找到命令。堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo); |
| | | return; |
| | | } |
| | | |
| | | JSONObject commandMap = JSON.parseObject(commandObj.toString()); |
| | | Integer idx = commandMap.getInteger("idx"); |
| | | List<DualCrnCommand> commandList = commandMap.getJSONArray("commands").toJavaList(DualCrnCommand.class); |
| | | if (idx >= commandList.size()) { |
| | | Long updateWrkSts = null; |
| | | if (wrkMast.getWrkSts() == WrkStsType.INBOUND_RUN.sts) { |
| | | updateWrkSts = WrkStsType.COMPLETE_INBOUND.sts; |
| | | } else if (wrkMast.getWrkSts() == WrkStsType.OUTBOUND_RUN.sts) { |
| | | updateWrkSts = WrkStsType.OUTBOUND_RUN_COMPLETE.sts; |
| | | } else if (wrkMast.getWrkSts() == WrkStsType.LOC_MOVE_RUN.sts) { |
| | | updateWrkSts = WrkStsType.COMPLETE_LOC_MOVE.sts; |
| | | } else { |
| | | News.error("双工位堆垛机处于等待确认且任务完成状态,但工作状态异常。堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo); |
| | | return; |
| | | } |
| | | |
| | | wrkMast.setWrkSts(updateWrkSts); |
| | | wrkMast.setSystemMsg(""); |
| | | wrkMast.setIoTime(new Date()); |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | DualCrnCommand resetCommand = dualCrnThread.getResetCommand(dualCrnProtocol.getCrnNo(), station); |
| | | MessageQueue.offer(SlaveType.DualCrn, dualCrnProtocol.getCrnNo(), new Task(3, resetCommand)); |
| | | News.info("双工位堆垛机任务状态更新成功,堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo); |
| | | } |
| | | redisUtil.set(RedisKeyType.DUAL_CRN_IO_EXECUTE_FINISH_LIMIT.key + basDualCrnp.getCrnNo() + "_" + taskNo, "lock", 10); |
| | | }else { |
| | | DualCrnCommand resetCommand = dualCrnThread.getResetCommand(dualCrnProtocol.getCrnNo(), station); |
| | | MessageQueue.offer(SlaveType.DualCrn, dualCrnProtocol.getCrnNo(), new Task(3, resetCommand)); |
| | | News.info("双工位堆垛机命令完成确认成功,堆垛机号={},工作号={}", basDualCrnp.getCrnNo(), taskNo); |
| | | } |
| | | } |
| | | |
| | | //检测浅库位状态 |
| | | public synchronized boolean checkShallowLocStatus(String locNo, Integer taskNo) { |
| | | String checkDeepLocOutTaskBlockReport = "Y"; |
| | | Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key); |
| | | if (systemConfigMapObj != null) { |
| | | HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj; |
| | | checkDeepLocOutTaskBlockReport = systemConfigMap.get("checkDeepLocOutTaskBlockReport"); |
| | | } |
| | | |
| | | if (!checkDeepLocOutTaskBlockReport.equals("Y")) { |
| | | return true; |
| | | } |
| | | |
| | | Object lock = redisUtil.get(RedisKeyType.CHECK_SHALLOW_LOC_STATUS_LIMIT.key + taskNo); |
| | | if (lock != null) { |
| | | return false; |
| | | } |
| | | redisUtil.set(RedisKeyType.CHECK_SHALLOW_LOC_STATUS_LIMIT.key + taskNo, "lock", 5); |
| | | |
| | | Integer shallowRow = Utils.getShallowRowByDeepRow(Utils.getRow(locNo)); |
| | | if (shallowRow == null) { |
| | | return true; |
| | | } |
| | | |
| | | String shallowLocNo = Utils.getLocNo(shallowRow, Utils.getBay(locNo), Utils.getLev(locNo)); |
| | | LocMast shallowLocMast = locMastService.queryByLoc(shallowLocNo); |
| | | if (shallowLocMast == null) { |
| | | News.taskInfo(taskNo, "浅库位:{} 数据不存在", shallowLocNo); |
| | | return false; |
| | | } |
| | | |
| | | if (shallowLocMast.getLocSts().equals("O")) { |
| | | return true; |
| | | } |
| | | |
| | | if (shallowLocMast.getLocSts().equals("F")) { |
| | | //浅库位状态有货,申请更换库位 |
| | | String response = wmsOperateUtils.applyChangeLocNo(shallowLocNo); |
| | | if (response == null) { |
| | | News.taskError(taskNo, "WCS申请在库库位更换库位失败,WMS接口未响应!!!response:{}", response); |
| | | return false; |
| | | } |
| | | JSONObject jsonObject = JSON.parseObject(response); |
| | | if (jsonObject.getInteger("code").equals(200)) { |
| | | StartupDto dto = jsonObject.getObject("data", StartupDto.class); |
| | | String moveLocNo = dto.getLocNo(); |
| | | |
| | | CreateLocMoveTaskParam moveTaskParam = new CreateLocMoveTaskParam(); |
| | | moveTaskParam.setTaskNo(dto.getTaskNo()); |
| | | moveTaskParam.setSourceLocNo(shallowLocNo); |
| | | moveTaskParam.setLocNo(moveLocNo); |
| | | try { |
| | | boolean result = commonService.createLocMoveTask(moveTaskParam); |
| | | } catch (CoolException e) { |
| | | News.taskInfo(taskNo, e.getMessage()); |
| | | } |
| | | } else { |
| | | News.error("请求WMS申请更换库位接口失败!!!response:{}", response); |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private int calcStation(DualCrnProtocol dualCrnProtocol) { |
| | | int station = 0; |
| | | if(dualCrnProtocol.getTaskNo() == 0){ |
| | | station = 1; |
| | | }else if (dualCrnProtocol.getTaskNoTwo() == 0){ |
| | | station = 2; |
| | | } |
| | | |
| | | return station; |
| | | } |
| | | |
| | | } |
| | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.*; |
| | | import com.zy.asrs.service.*; |
| | | import com.zy.common.entity.FindCrnNoResult; |
| | | import com.zy.common.model.StartupDto; |
| | | import com.zy.common.service.CommonService; |
| | | import com.zy.common.utils.RedisUtil; |
| | |
| | | } |
| | | |
| | | String locNo = wrkMast.getLocNo(); |
| | | Integer crnNo = commonService.findCrnNoByLocNo(locNo); |
| | | if (crnNo == null) { |
| | | FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo); |
| | | if (findCrnNoResult == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "未匹配到堆垛机"); |
| | | continue; |
| | | } |
| | | |
| | | Integer targetStationId = commonService.findInStationId(crnNo, stationId); |
| | | Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationId); |
| | | if (targetStationId == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "搜索入库站点失败"); |
| | | continue; |
| | |
| | | if (runBlockReassignLocStationList.contains(stationProtocol.getStationId())) { |
| | | //站点处于重新分配库位区域 |
| | | //运行堵塞,重新申请任务 |
| | | String response = wmsOperateUtils.applyReassignTaskLocNo(wrkMast.getWrkNo()); |
| | | String response = wmsOperateUtils.applyReassignTaskLocNo(wrkMast.getWrkNo(), stationProtocol.getStationId()); |
| | | if (response == null) { |
| | | News.taskError(wrkMast.getWrkNo(), "请求WMS重新分配库位接口失败,接口未响应!!!response:{}", response); |
| | | continue; |
| | |
| | | continue; |
| | | } |
| | | |
| | | Integer crnNo = commonService.findCrnNoByLocNo(locNo); |
| | | if (crnNo == null) { |
| | | FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo); |
| | | if (findCrnNoResult == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "未匹配到堆垛机"); |
| | | continue; |
| | | } |
| | | Integer crnNo = findCrnNoResult.getCrnNo(); |
| | | |
| | | Integer targetStationId = commonService.findInStationId(crnNo, stationProtocol.getStationId()); |
| | | Integer targetStationId = commonService.findInStationId(findCrnNoResult, stationProtocol.getStationId()); |
| | | if (targetStationId == null) { |
| | | News.taskInfo(wrkMast.getWrkNo(), "搜索入库站点失败"); |
| | | continue; |
| | |
| | | |
| | | //更新工作档数据 |
| | | wrkMast.setLocNo(locNo); |
| | | wrkMast.setCrnNo(crnNo); |
| | | wrkMast.setStaNo(targetStationId); |
| | | |
| | | if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) { |
| | | wrkMast.setCrnNo(crnNo); |
| | | } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) { |
| | | wrkMast.setDualCrnNo(crnNo); |
| | | }else { |
| | | throw new CoolException("未知设备类型"); |
| | | } |
| | | |
| | | if (wrkMastService.updateById(wrkMast)) { |
| | | MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command)); |
| | | } |
| | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.mapper.EntityWrapper; |
| | | import com.core.common.Cools; |
| | | import com.core.exception.CoolException; |
| | | import com.zy.asrs.entity.BasCrnp; |
| | | import com.zy.asrs.entity.BasDualCrnp; |
| | | import com.zy.asrs.entity.HttpRequestLog; |
| | | import com.zy.asrs.entity.WrkMast; |
| | | import com.zy.asrs.service.BasCrnpService; |
| | | import com.zy.asrs.service.BasDualCrnpService; |
| | | import com.zy.asrs.service.HttpRequestLogService; |
| | | import com.zy.asrs.service.WrkMastService; |
| | | import com.zy.asrs.utils.Utils; |
| | | import com.zy.common.entity.FindCrnNoResult; |
| | | import com.zy.common.service.CommonService; |
| | | import com.zy.common.utils.HttpHandler; |
| | | import com.zy.core.News; |
| | | import com.zy.core.enums.SlaveType; |
| | | import com.zy.system.entity.Config; |
| | | import com.zy.system.service.ConfigService; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | |
| | | private CommonService commonService; |
| | | @Autowired |
| | | private BasCrnpService basCrnpService; |
| | | @Autowired |
| | | private BasDualCrnpService basDualCrnpService; |
| | | |
| | | //申请入库任务 |
| | | public synchronized String applyInTask(String barcode, Integer sourceStaNo, Integer locType1) { |
| | |
| | | requestParam.put("barcode", barcode); |
| | | requestParam.put("sourceStaNo", sourceStaNo); |
| | | requestParam.put("locType1", locType1); |
| | | requestParam.put("row", Utils.getInTaskEnableRow()); |
| | | requestParam.put("row", Utils.getInTaskEnableRow(sourceStaNo)); |
| | | |
| | | response = new HttpHandler.Builder() |
| | | .setUri(wmsUrl) |
| | |
| | | } |
| | | |
| | | //申请任务重新分配库位 |
| | | public synchronized String applyReassignTaskLocNo(Integer taskNo) { |
| | | public synchronized String applyReassignTaskLocNo(Integer taskNo, Integer stationId) { |
| | | String wmsUrl = null; |
| | | Config wmsSystemUriConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "wmsSystemUri")); |
| | | if (wmsSystemUriConfig != null) { |
| | |
| | | wmsSystemReassignInTaskUrl = wmsSystemReassignInTaskUrlConfig.getValue(); |
| | | } |
| | | |
| | | if(wmsSystemReassignInTaskUrl == null){ |
| | | if (wmsSystemReassignInTaskUrl == null) { |
| | | News.error("未配置WMS任务重新分配入库库位接口地址,配置文件Code编码:wmsSystemReassignInTaskUrl"); |
| | | return null; |
| | | } |
| | |
| | | String response = null; |
| | | int result = 0; |
| | | try { |
| | | List<Integer> excludeCrnList = new ArrayList<>(); |
| | | List<Integer> excludeDualCrnList = new ArrayList<>(); |
| | | if (!Cools.isEmpty(wrkMast.getCrnNo())) { |
| | | excludeCrnList.add(wrkMast.getCrnNo()); |
| | | } |
| | | if (!Cools.isEmpty(wrkMast.getDualCrnNo())) { |
| | | excludeDualCrnList.add(wrkMast.getDualCrnNo()); |
| | | } |
| | | |
| | | requestParam.put("taskNo", wrkMast.getWmsWrkNo()); |
| | | requestParam.put("row", Utils.getInTaskEnableRow(new ArrayList<>(wrkMast.getCrnNo()), false)); |
| | | requestParam.put("row", Utils.getInTaskEnableRow(stationId, excludeCrnList, excludeDualCrnList, false)); |
| | | |
| | | response = new HttpHandler.Builder() |
| | | .setUri(wmsUrl) |
| | |
| | | if (jsonObject.getInteger("code") == 200) { |
| | | result = 1; |
| | | News.info("请求申请任务重新分配入库接口成功!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response); |
| | | }else { |
| | | } else { |
| | | News.info("请求申请任务重新分配入库接口失败,接口返回Code异常!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response); |
| | | } |
| | | }else { |
| | | } else { |
| | | News.info("请求申请任务重新分配入库接口失败,接口未响应!!!url:{};request:{};response:{}", wmsUrl + wmsSystemReassignInTaskUrl, JSON.toJSONString(requestParam), response); |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | return null; |
| | | } |
| | | |
| | | Integer crnNo = commonService.findCrnNoByLocNo(locNo); |
| | | if (crnNo == null) { |
| | | FindCrnNoResult findCrnNoResult = commonService.findCrnNoByLocNo(locNo); |
| | | if (findCrnNoResult == null) { |
| | | return null; |
| | | } |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if (basCrnp == null) { |
| | | return null; |
| | | } |
| | | |
| | | Integer crnNo = findCrnNoResult.getCrnNo(); |
| | | List<Integer> crnRows = new ArrayList<>(); |
| | | List<List<Integer>> rowList = basCrnp.getControlRows$(); |
| | | for (List<Integer> list : rowList) { |
| | | crnRows.addAll(list); |
| | | |
| | | if (findCrnNoResult.getCrnType().equals(SlaveType.Crn)) { |
| | | BasCrnp basCrnp = basCrnpService.selectOne(new EntityWrapper<BasCrnp>().eq("crn_no", crnNo)); |
| | | if (basCrnp == null) { |
| | | return null; |
| | | } |
| | | List<List<Integer>> rowList = basCrnp.getControlRows$(); |
| | | for (List<Integer> list : rowList) { |
| | | crnRows.addAll(list); |
| | | } |
| | | } else if (findCrnNoResult.getCrnType().equals(SlaveType.DualCrn)) { |
| | | BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", crnNo)); |
| | | if (basDualCrnp == null) { |
| | | return null; |
| | | } |
| | | List<List<Integer>> rowList = basDualCrnp.getControlRows$(); |
| | | for (List<Integer> list : rowList) { |
| | | crnRows.addAll(list); |
| | | } |
| | | }else { |
| | | throw new CoolException("未知设备类型"); |
| | | } |
| | | |
| | | HashMap<String, Object> requestParam = new HashMap<>(); |
| | |
| | | <result column="error_memo" property="errorMemo" /> |
| | | <result column="memo" property="memo" /> |
| | | <result column="barcode" property="barcode" /> |
| | | <result column="lift_no" property="liftNo" /> |
| | | <result column="shuttle_no" property="shuttleNo" /> |
| | | <result column="crn_no" property="crnNo" /> |
| | | <result column="dual_crn_no" property="dualCrnNo" /> |
| | | <result column="rgv_no" property="rgvNo" /> |
| | | <result column="wms_wrk_no" property="wmsWrkNo" /> |
| | | <result column="system_msg" property="systemMsg" /> |
| | | </resultMap> |
| | |
| | | <result column="memo" property="memo" /> |
| | | <result column="barcode" property="barcode" /> |
| | | <result column="crn_no" property="crnNo" /> |
| | | <result column="dual_crn_no" property="dualCrnNo" /> |
| | | <result column="rgv_no" property="rgvNo" /> |
| | | <result column="wms_wrk_no" property="wmsWrkNo" /> |
| | | <result column="system_msg" property="systemMsg" /> |
| | |
| | | {type: 'checkbox'} |
| | | ,{field: 'crnNo', align: 'center',title: '编号'} |
| | | ,{field: 'status$', align: 'center',title: '状态'} |
| | | ,{field: 'wrkNo', align: 'center',title: '工作号'} |
| | | // ,{field: 'wrkNo', align: 'center',title: '工作号'} |
| | | ,{field: 'inEnable', align: 'center',title: '可入(checkBox)'} |
| | | ,{field: 'outEnable', align: 'center',title: '可出(checkBox)'} |
| | | // ,{field: 'createBy', align: 'center',title: '创建人员'} |
| | |
| | | ,{field: 'sourceLocNo', align: 'center',title: '源库位'} |
| | | ,{field: 'locNo', align: 'center',title: '目标库位'} |
| | | ,{field: 'crnNo', align: 'center',title: '堆垛机'} |
| | | ,{field: 'dualCrnNo', align: 'center',title: '双工位堆垛机'} |
| | | ,{field: 'modiUser$', align: 'center',title: '修改人员', hide:true} |
| | | ,{field: 'modiTime$', align: 'center',title: '修改时间', hide:true} |
| | | // ,{field: 'appeUser$', align: 'center',title: '创建者',event: 'appeUser', style: 'cursor:pointer'} |
| | |
| | | <!-- 表单弹窗 --> |
| | | <script type="text/html" id="editDialog"> |
| | | <form id="detail" lay-filter="detail" class="layui-form admin-form model-form"> |
| | | <input name="id" type="hidden"> |
| | | <input name="crnNo" type="hidden"> |
| | | <div class="layui-row"> |
| | | <div class="layui-col-md12"> |
| | | <div class="layui-form-item"> |
| | |
| | | </select> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">工作号: </label> |
| | | <div class="layui-input-block"> |
| | | <input class="layui-input" name="wrkNo" placeholder="请输入工作号"> |
| | | </div> |
| | | </div> |
| | | <!-- <div class="layui-form-item">--> |
| | | <!-- <label class="layui-form-label">工作号: </label>--> |
| | | <!-- <div class="layui-input-block">--> |
| | | <!-- <input class="layui-input" name="wrkNo" placeholder="请输入工作号">--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | <div class="layui-form-item"> |
| | | <label class="layui-form-label">可入(checkBox): </label> |
| | | <div class="layui-input-block"> |
| | |
| | | </el-table-column> |
| | | <el-table-column property="crnNo" label="堆垛机"> |
| | | </el-table-column> |
| | | <el-table-column property="dualCrnNo" label="双工位堆垛机"> |
| | | </el-table-column> |
| | | <el-table-column property="systemMsg" label="系统消息"> |
| | | </el-table-column> |
| | | <el-table-column label="操作" width="100"> |