package com.ruoyi.tcp; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.common.Constant; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import javax.annotation.PostConstruct; import java.io.OutputStream; import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @Component @Slf4j public class Wcs2wmsgetEmptyCargoSpace { private final TcpServerManager manager; private final ObjectMapper objectMapper = new ObjectMapper(); private final RestTemplate restTemplate = new RestTemplate(); /** * 构造函数:注入 TCP 管理器,用于在 1111 端口管理客户端与数据发送 */ public Wcs2wmsgetEmptyCargoSpace(TcpServerManager manager) { this.manager = manager; } /** * 初始化:注册 1111 端口客户端监听,客户端首次连接时触发数据发送 */ @PostConstruct public void init() { manager.setClientListener("port1111", this::handleConnect); } /** * 客户端连接处理:调用 WMS 接口获取空货位数据,转换为统一 JSON 并写入到 Socket */ private void handleConnect(Socket socket) { try { String url = Constant.WMS_BASE_URL + "twin/getEmptyCargoSpace"; log.info("Fetching WMS data from {}", url); String wmsResponse = restTemplate.getForObject(url, String.class); JsonNode root = objectMapper.readTree(wmsResponse); List cargoList = new ArrayList<>(); // Handle if root is array or wrapped in "data" or "rows" JsonNode arrayNode = null; if (root.isArray()) { arrayNode = root; } else if (root.has("data") && root.get("data").isArray()) { arrayNode = root.get("data"); } else if (root.has("rows") && root.get("rows").isArray()) { arrayNode = root.get("rows"); } if (arrayNode != null) { for (JsonNode node : arrayNode) { cargoList.add(mapToDto(node)); } } else { // If it's a single object, maybe treat as one item? // Or maybe the format is different. For now, log warning if empty. log.warn("WMS response is not an array: {}", wmsResponse); } CargoResponse response = new CargoResponse(); response.setCargo(cargoList); String json = objectMapper.writeValueAsString(response); OutputStream os = socket.getOutputStream(); os.write((json + "\n").getBytes(StandardCharsets.UTF_8)); os.flush(); log.info("Sent WMS data to client on port 1111"); } catch (Exception e) { log.error("Failed to fetch WMS data or send to client", e); } } /** * 映射单条 WMS 返回记录为 DTO:优先取目标字段名,兼容 BasCargoSpace 字段名 */ private CargoDto mapToDto(JsonNode node) { CargoDto dto = new CargoDto(); // Mapping strategy: try user's target keys first, then BasCargoSpace keys dto.setRow(getText(node, "row", "thePlatoon")); dto.setColumn(getText(node, "column", "theColumn")); dto.setLayer(getText(node, "layer", "theFloor")); dto.setStatus(getText(node, "status")); dto.setTrayCode(getText(node, "trayCode")); dto.setProductCode(getText(node, "productCode")); dto.setProductName(getText(node, "productName")); dto.setCargoSpaceId(getText(node, "cargoSpaceId")); return dto; } /** * 读取节点文本:按给定字段名顺序查找首个存在且非空的值 */ private String getText(JsonNode node, String... keys) { for (String key : keys) { if (node.has(key) && !node.get(key).isNull()) { return node.get(key).asText(); } } return ""; } @Data private static class CargoResponse { private List cargo; } @Data private static class CargoDto { private String row; private String column; private String layer; private String status; private String trayCode; private String productCode; private String productName; private String cargoSpaceId; } }