package com.ruoyi.tcp; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.common.utils.DictUtils; import com.ruoyi.device.srgv.domain.DeviceSrgv; import com.ruoyi.job.domain.MydoJob; import com.ruoyi.job.service.IMydoJobService; import com.ruoyi.schedule.plcRead.srgv.PlcSrgvRead; import lombok.Data; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; 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; import java.util.Map; @Component public class GetDeviceSrgvMap { private final TcpServerManager manager; private final ObjectMapper objectMapper = new ObjectMapper(); private final IMydoJobService mydoJobService; /** * 构造函数:注入 TCP 管理器与作业服务,用于管理 2222 端口广播并根据任务号补全物料信息 */ public GetDeviceSrgvMap(TcpServerManager manager, IMydoJobService mydoJobService) { this.manager = manager; this.mydoJobService = mydoJobService; } /** * 初始化:注册 2222 端口的客户端连接监听,客户端第一次连接时立即发送 AGV 数据 */ @PostConstruct public void init() { manager.setClientListener("port2222", this::handleConnect); } /** * 客户端连接处理:构建 AGV 数据并写入到 Socket 输出流 */ private void handleConnect(Socket socket) { try { String payload = buildAgvPayload(); OutputStream os = socket.getOutputStream(); os.write(((payload == null ? "" : payload) + "\n").getBytes(StandardCharsets.UTF_8)); os.flush(); } catch (Exception ignored) { } } /** * 周期发送:每 2 秒检查 2222 端口是否有连接,有则广播 AGV 数据,无连接不发送 */ @Scheduled(fixedRate = 2000) public void send() { Integer count = manager.status().getOrDefault("port2222", 0); if (count != null && count > 0) { String payload = buildAgvPayload(); manager.broadcast("port2222", payload == null ? "" : payload); } } /** * 构建 AGV 数据:从 PLC 缓存读取四向车状态并组装 JSON * - 计算在位与状态(基于执行阶段 workPhase) * - 报警码与文案:使用字典 srgv_alarm * - 当任务号有效时,查询 MydoJob 补齐托盘与物料信息 * 返回 JSON 字符串格式:{"AGV":[{...}]} */ private String buildAgvPayload() { Map map = PlcSrgvRead.deviceSrgvMap; List list = new ArrayList<>(); if (map != null) { for (DeviceSrgv d : map.values()) { AgvDto dto = new AgvDto(); dto.setId(d.getDeviceId() == null ? "" : String.format("%04d", d.getDeviceId())); dto.setTaskNo(d.getTaskNo() == null ? "" : String.valueOf(d.getTaskNo())); dto.setIsThere(d.getCargoFlag()==256?"1":"0"); Integer wp = d.getWorkPhase(); String status = "0"; if (wp != null) { if (wp == 3) status = "1"; else if (wp == 6) status = "2"; else if (wp == 24) status = "3"; } dto.setStatus(status); dto.setLocation(d.getCurrSite() == null ? "" : d.getCurrSite()); dto.setRow(d.getCurrSite() == null ? "" : d.getCurrSite().substring(2,4)); dto.setColumn(d.getCurrSite() == null ? "" :d.getCurrSite().substring(0,2)); dto.setLayer(d.getCurrSite() == null ? "" : d.getCurrSite().substring(4,6)); dto.setAlarm(d.getAlarm() == null ? "" : String.valueOf(d.getAlarm())); dto.setAlarmMsg(DictUtils.getDictLabel("srgv_alarm", d.getAlarm() == null ? "" : String.valueOf(d.getAlarm()))); if (d.getTaskNo() != null && d.getTaskNo() > 0) { try { MydoJob job = mydoJobService.selectMydoJobByTaskNo(Long.valueOf(d.getTaskNo())); dto.setTrayCode(job == null || job.getTrayCode() == null ? "" : job.getTrayCode()); dto.setProductCode(job == null || job.getProductId() == null ? "" : job.getProductId()); dto.setProductName(job == null || job.getProductName() == null ? "" : job.getProductName()); } catch (Exception e) { dto.setTrayCode(""); dto.setProductCode(""); dto.setProductName(""); } } else { dto.setTrayCode(""); dto.setProductCode(""); dto.setProductName(""); } list.add(dto); } } try { Wrapper w = new Wrapper(); w.setAGV(list); return objectMapper.writeValueAsString(w); } catch (Exception e) { return "{\"AGV\":[]}"; } } @Data private static class Wrapper { private List AGV; } @Data private static class AgvDto { private String id; private String taskNo; private String isThere; private String status; private String location; private String row; private String column; private String layer; private String alarm; private String alarmMsg; private String trayCode; private String productCode; private String productName; } }