package com.ruoyi.tcp; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.common.utils.DictUtils; import com.ruoyi.device.ssj.domain.DeviceSsj; import com.ruoyi.job.domain.MydoJob; import com.ruoyi.job.service.IMydoJobService; import com.ruoyi.schedule.plcRead.ssj.PlcSsjRead; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; 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 GetDeviceSsjMap { private final TcpServerManager manager; private final ObjectMapper objectMapper = new ObjectMapper(); private final IMydoJobService mydoJobService; /** * 构造函数:注入 TCP 管理器与作业服务,用于管理 3333 端口广播并根据任务号补全物料信息 */ public GetDeviceSsjMap(TcpServerManager manager, IMydoJobService mydoJobService) { this.manager = manager; this.mydoJobService = mydoJobService; } /** * 初始化:注册 3333 端口的客户端连接监听,客户端第一次连接时立即发送输送机数据 */ @PostConstruct public void init() { manager.setClientListener("port3333", this::handleConnect); } /** * 客户端连接处理:构建输送机数据并写入到 Socket 输出流 */ private void handleConnect(Socket socket) { try { String payload = readConveyorsFromCache(); OutputStream os = socket.getOutputStream(); os.write(((payload == null ? "" : payload) + "\n").getBytes(StandardCharsets.UTF_8)); os.flush(); } catch (Exception ignored) { } } /** * 周期发送:每 2 秒检查 3333 端口是否有连接,有则广播输送机数据,无连接不发送 */ @Scheduled(fixedRate = 2000) public void send() { Integer count = manager.status().getOrDefault("port3333", 0); if (count != null && count > 0) { String payload = readConveyorsFromCache(); manager.broadcast("port3333", payload == null ? "" : payload); } } /** * 从 PLC 缓存读取输送机状态并组装 JSON * - 工作模式转换为中文标签 * - 报警码与文案:使用字典 ssj_ex * - 当任务号有效时,查询 MydoJob 补齐托盘与物料信息 * 返回 JSON 字符串格式:{"ssj":[{...}]} */ private String readConveyorsFromCache() { Map map = PlcSsjRead.deviceSsjMap; List list = new ArrayList<>(); if (map == null || map.isEmpty()) { return toJson(list); } for (DeviceSsj d : map.values()) { SsjDto dto = new SsjDto(); dto.setId(d.getDeviceCode()); Integer cf = d.getModel(); String mode = "0"; if (cf != null) { if (cf == 1) { mode = "手动"; }else if (cf == 2) { mode = "自动"; }else { mode = String.valueOf(cf); } } dto.setWorkingMode(mode); dto.setTaskNo(String.valueOf(d.getTaskNo())); dto.setRotationDirection(calcRotationDirection(d.getTaskNo())); dto.setAlarm(String.valueOf(d.getException())); dto.setAlarmMsg(DictUtils.getDictLabel("ssj_ex", String.valueOf(d.getException()))); dto.setKX(String.valueOf(d.getKx())); if (!dto.getTaskNo().equals("0")){ if (dto.getRotationDirection().equals("1")){ dto.setDW(String.valueOf(d.getDw())); }else { if (dto.getKX().equals("0")){ dto.setDW("1"); }else { dto.setDW("0"); } } }else { dto.setDW("0"); } if (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(""); } dto.setRunning(""); list.add(dto); } return toJson(list); } /** * 计算输送机旋转方向:依据作业 inOrOut 字段,>=20 返回 "2",<20 返回 "1" */ private String calcRotationDirection(int taskNo) { try { if (taskNo <= 0) { return "0"; } return taskNo <= 50000 ? "1" : "2"; } catch (Exception e) { return "0"; } } /** * 列表对象序列化为 JSON 字符串 */ private String toJson(List list) { try { Wrapper w = new Wrapper(); w.setSsj(list); return objectMapper.writeValueAsString(w); } catch (Exception e) { return "{\"ssj\":[]}"; } } public static class Wrapper { private List ssj; /** * 获取输送机列表 */ public List getSsj() { return ssj; } /** * 设置输送机列表 */ public void setSsj(List ssj) { this.ssj = ssj; } } @Data @AllArgsConstructor @NoArgsConstructor public static class SsjDto { private String id; private String workingMode; private String taskNo; private String rotationDirection; private String alarm; private String alarmMsg; private String DW; private String KX; private String running; private String trayCode; private String productCode; private String productName; } }