package com.mes.component; import com.github.xingshuangs.iot.protocol.s7.service.S7PLC; import com.mes.ui.MesClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.*; import java.awt.*; import java.util.ArrayList; import java.util.List; /** * PLC信号监控组件 * 可复用的信号监控面板,支持显示PLC信号状态和详细对话框 */ public class PlcSignalMonitor { private static final Logger log = LoggerFactory.getLogger(PlcSignalMonitor.class); private S7PLC s7PLC; private String plcDb; private String stationName; private JFrame parentFrame; // 信号标签(用于对话框中的实时更新) private JLabel signal_feeding; private JLabel signal_blanking; private JLabel signal_running; private JLabel signal_deviceStatus; private JLabel signal_allowFeeding; private JLabel signal_allowBlanking; private JLabel signal_heart; private JLabel signal_toDevice; private JLabel signal_toTransfer; private JLabel signal_transferToDevice; /** * 构造函数 * @param s7PLC PLC连接对象 * @param plcDb DB块名称(如 DB7000) * @param stationName 工位名称(如 OP040A) * @param parentFrame 父窗口 */ public PlcSignalMonitor(S7PLC s7PLC, String plcDb, String stationName, JFrame parentFrame) { this.s7PLC = s7PLC; this.plcDb = plcDb; this.stationName = stationName; this.parentFrame = parentFrame; } /** * 创建信号监控按钮(放在工位面板中) * @return 信号监控按钮 */ public JButton createSignalButton() { JButton signalBtn = new JButton("PLC信号"); signalBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12)); signalBtn.setForeground(new Color(0, 102, 204)); signalBtn.setToolTipText("点击查看PLC信号详情"); signalBtn.addActionListener(e -> showSignalDialog()); return signalBtn; } /** * 创建信号标签 */ private JLabel createSignalLabel(String text, boolean active) { JLabel label = new JLabel(text); label.setOpaque(true); label.setFont(new Font("微软雅黑", Font.PLAIN, 11)); label.setHorizontalAlignment(SwingConstants.CENTER); label.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1)); label.setPreferredSize(new Dimension(50, 18)); updateSignalLabel(label, active); return label; } /** * 更新信号标签状态 */ private void updateSignalLabel(JLabel label, boolean active) { if (active) { label.setBackground(new Color(0, 200, 0)); label.setForeground(Color.WHITE); } else { label.setBackground(new Color(200, 200, 200)); label.setForeground(Color.DARK_GRAY); } } /** * 显示信号监控对话框 */ public void showSignalDialog() { JDialog dialog = new JDialog(parentFrame, stationName + " - PLC信号监控", false); dialog.setSize(550, 400); dialog.setLocationRelativeTo(parentFrame); JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // 标题 JLabel title = new JLabel("PLC信号实时监控"); title.setFont(new Font("微软雅黑", Font.BOLD, 16)); title.setAlignmentX(Component.CENTER_ALIGNMENT); panel.add(title); panel.add(Box.createVerticalStrut(10)); // 工位信息 JLabel stationInfo = new JLabel("工位: " + stationName + " | DB块: " + plcDb); stationInfo.setFont(new Font("微软雅黑", Font.PLAIN, 12)); stationInfo.setForeground(Color.GRAY); stationInfo.setAlignmentX(Component.CENTER_ALIGNMENT); panel.add(stationInfo); panel.add(Box.createVerticalStrut(15)); // 信号详情面板 JPanel signalPanel = createSignalDetailPanel(); panel.add(signalPanel); panel.add(Box.createVerticalStrut(15)); // 刷新按钮 JButton refreshBtn = new JButton("刷新信号"); refreshBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12)); refreshBtn.setAlignmentX(Component.CENTER_ALIGNMENT); refreshBtn.addActionListener(e -> updateSignalDisplay()); panel.add(refreshBtn); dialog.add(panel); // 首次显示时更新信号 updateSignalDisplay(); dialog.setVisible(true); } /** * 创建信号详情面板 */ private JPanel createSignalDetailPanel() { List signalList = new ArrayList<>(); signalList.add(new String[]{"请求上料", plcDb + ".0.0", "PLC→MES"}); signalList.add(new String[]{"下料信号", plcDb + ".0.1", "PLC→MES"}); signalList.add(new String[]{"设备运行", plcDb + ".0.2", "PLC→MES"}); signalList.add(new String[]{"设备通讯", plcDb + ".0.3", "PLC状态"}); signalList.add(new String[]{"MES允许上料", plcDb + ".0.4", "MES→PLC"}); signalList.add(new String[]{"MES允许下料", plcDb + ".0.5", "MES→PLC"}); signalList.add(new String[]{"心跳信号", plcDb + ".0.6", "MES→PLC"}); signalList.add(new String[]{"上料到设备", plcDb + ".0.7", "PLC→MES"}); if (MesClient.transferEnabled) { signalList.add(new String[]{"上料到中转车", plcDb + ".1.0", "PLC→MES"}); signalList.add(new String[]{"中转车上料到设备", plcDb + ".1.1", "PLC→MES"}); } JPanel panel = new JPanel(new GridLayout(signalList.size() + 1, 4, 5, 5)); panel.setBorder(BorderFactory.createTitledBorder(stationName + " 信号状态")); // 表头 panel.add(createHeaderLabel("信号名称")); panel.add(createHeaderLabel("地址")); panel.add(createHeaderLabel("方向")); panel.add(createHeaderLabel("状态")); // 初始化信号标签 signal_feeding = createStatusLabel(); signal_blanking = createStatusLabel(); signal_running = createStatusLabel(); signal_deviceStatus = createStatusLabel(); signal_allowFeeding = createStatusLabel(); signal_allowBlanking = createStatusLabel(); signal_heart = createStatusLabel(); signal_toDevice = createStatusLabel(); signal_toTransfer = createStatusLabel(); signal_transferToDevice = createStatusLabel(); List statusLabels = new ArrayList<>(); statusLabels.add(signal_feeding); statusLabels.add(signal_blanking); statusLabels.add(signal_running); statusLabels.add(signal_deviceStatus); statusLabels.add(signal_allowFeeding); statusLabels.add(signal_allowBlanking); statusLabels.add(signal_heart); statusLabels.add(signal_toDevice); if (MesClient.transferEnabled) { statusLabels.add(signal_toTransfer); statusLabels.add(signal_transferToDevice); } // 添加信号行 for (int i = 0; i < signalList.size(); i++) { String[] signals = signalList.get(i); panel.add(new JLabel(signals[0], SwingConstants.CENTER)); panel.add(new JLabel(signals[1], SwingConstants.CENTER)); panel.add(new JLabel(signals[2], SwingConstants.CENTER)); panel.add(statusLabels.get(i)); } return panel; } /** * 创建表头标签 */ private JLabel createHeaderLabel(String text) { JLabel label = new JLabel(text, SwingConstants.CENTER); label.setFont(new Font("微软雅黑", Font.BOLD, 12)); return label; } /** * 创建状态标签 */ private JLabel createStatusLabel() { JLabel label = new JLabel("--", SwingConstants.CENTER); label.setOpaque(true); label.setBackground(Color.LIGHT_GRAY); label.setFont(new Font("微软雅黑", Font.PLAIN, 11)); return label; } /** * 更新信号显示 */ private void updateSignalDisplay() { try { if (s7PLC == null) { log.warn("[{}] PLC连接为空,无法读取信号", stationName); showConnectionError(); return; } // 读取所有信号 boolean feeding = s7PLC.readBoolean(plcDb + ".0.0"); boolean blanking = s7PLC.readBoolean(plcDb + ".0.1"); boolean running = s7PLC.readBoolean(plcDb + ".0.2"); boolean deviceStatus = s7PLC.readBoolean(plcDb + ".0.3"); boolean allowFeeding = s7PLC.readBoolean(plcDb + ".0.4"); boolean allowBlanking = s7PLC.readBoolean(plcDb + ".0.5"); boolean heart = s7PLC.readBoolean(plcDb + ".0.6"); boolean toDevice = s7PLC.readBoolean(plcDb + ".0.7"); boolean toTransfer = MesClient.transferEnabled && s7PLC.readBoolean(plcDb + ".1.0"); boolean transferToDevice = MesClient.transferEnabled && s7PLC.readBoolean(plcDb + ".1.1"); // 在EDT线程中更新UI SwingUtilities.invokeLater(() -> { updateStatusLabel(signal_feeding, feeding); updateStatusLabel(signal_blanking, blanking); updateStatusLabel(signal_running, running); updateStatusLabel(signal_deviceStatus, deviceStatus); updateStatusLabel(signal_allowFeeding, allowFeeding); updateStatusLabel(signal_allowBlanking, allowBlanking); updateStatusLabel(signal_heart, heart); updateStatusLabel(signal_toDevice, toDevice); if (MesClient.transferEnabled) { updateStatusLabel(signal_toTransfer, toTransfer); updateStatusLabel(signal_transferToDevice, transferToDevice); } }); } catch (Exception e) { String errorMsg = e.getMessage(); if (errorMsg != null && errorMsg.contains("connect timed out")) { log.warn("[{}] PLC连接超时,请检查网络连接", stationName); } else { log.error("[{}] 读取PLC信号异常: {}", stationName, errorMsg); } // 在UI上显示错误提示 SwingUtilities.invokeLater(this::showConnectionError); } } /** * 显示连接错误提示 */ private void showConnectionError() { JLabel[] labels = { signal_feeding, signal_blanking, signal_running, signal_deviceStatus, signal_allowFeeding, signal_allowBlanking, signal_heart, signal_toDevice, signal_toTransfer, signal_transferToDevice }; for (JLabel label : labels) { if (label != null && label.getParent() != null) { label.setText("ERR"); label.setBackground(Color.ORANGE); label.setForeground(Color.WHITE); } } } /** * 更新状态标签 */ private void updateStatusLabel(JLabel label, boolean active) { if (label != null) { if (active) { label.setText("1"); label.setBackground(new Color(0, 200, 0)); label.setForeground(Color.WHITE); } else { label.setText("0"); label.setBackground(new Color(200, 200, 200)); label.setForeground(Color.DARK_GRAY); } } } }