|
|
@@ -0,0 +1,582 @@
|
|
|
+package com.mes.ui;
|
|
|
+
|
|
|
+import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
|
|
|
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
|
|
|
+
|
|
|
+import javax.swing.*;
|
|
|
+import javax.swing.table.DefaultTableCellRenderer;
|
|
|
+import javax.swing.table.DefaultTableModel;
|
|
|
+import java.awt.*;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.Timer;
|
|
|
+import java.util.TimerTask;
|
|
|
+
|
|
|
+/**
|
|
|
+ * OP50 PLC 信号监控面板
|
|
|
+ * 独立运行,不依赖 MES 服务器连接,直连 S7-1200 读写 DB200 点位
|
|
|
+ */
|
|
|
+public class PlcSignalPanel extends JFrame {
|
|
|
+
|
|
|
+ // ===== 点位定义(与 PlcUtil 保持一致)=====
|
|
|
+ private static final String DB = "DB200";
|
|
|
+ private static final String A_PERMIT = DB + ".0.1"; // A面MES允许启动
|
|
|
+ private static final String B_PERMIT = DB + ".38.0"; // B面MES允许启动
|
|
|
+ private static final String A_STATUS = DB + ".34"; // A面状态 Int16
|
|
|
+ private static final String B_STATUS = DB + ".72"; // B面状态 Int16
|
|
|
+ private static final String A_POSITION = DB + ".156.3"; // A面到位
|
|
|
+ private static final String B_POSITION = DB + ".156.4"; // B面到位
|
|
|
+
|
|
|
+ /** 焊点点位:名称, 完成标志, 序号, 电流, 电压, 送丝速度, 焊接速度 */
|
|
|
+ private static final String[][] WELD_POINTS = {
|
|
|
+ {"R1", "76.1", "78", "80", "84", "88", "92"},
|
|
|
+ {"R2", "96.2", "98", "100", "104", "108", "112"},
|
|
|
+ {"R3", "116.2", "118", "120", "124", "128", "132"},
|
|
|
+ {"R4", "136.2", "138", "140", "144", "148", "152"}
|
|
|
+ };
|
|
|
+
|
|
|
+ private static final Color GREEN = new Color(0, 200, 0);
|
|
|
+ private static final Color YELLOW = new Color(230, 170, 0);
|
|
|
+ private static final Color GRAY = Color.GRAY;
|
|
|
+ private static final Color BLUE = new Color(0, 100, 200);
|
|
|
+
|
|
|
+ private final String defaultIp;
|
|
|
+ private volatile S7PLC s7PLC;
|
|
|
+ private volatile boolean connected = false;
|
|
|
+
|
|
|
+ // 连接控制
|
|
|
+ private JTextField ipField;
|
|
|
+ private JButton connectBtn;
|
|
|
+ private JButton disconnectBtn;
|
|
|
+ private JLabel connLight;
|
|
|
+
|
|
|
+ // 转台位置
|
|
|
+ private JLabel lightPosA;
|
|
|
+ private JLabel lightPosB;
|
|
|
+ private JLabel valueCurSide;
|
|
|
+
|
|
|
+ // MES允许启动
|
|
|
+ private JLabel lightPermitA;
|
|
|
+ private JLabel lightPermitB;
|
|
|
+ private JButton permitSetA;
|
|
|
+ private JButton permitResetA;
|
|
|
+ private JButton permitSetB;
|
|
|
+ private JButton permitResetB;
|
|
|
+
|
|
|
+ // 焊接状态
|
|
|
+ private JLabel lightStatusA;
|
|
|
+ private JLabel lightStatusB;
|
|
|
+ private JLabel valueStatusA;
|
|
|
+ private JLabel valueStatusB;
|
|
|
+ private JButton ackBtnA;
|
|
|
+ private JButton ackBtnB;
|
|
|
+
|
|
|
+ // 焊接参数表
|
|
|
+ private DefaultTableModel weldModel;
|
|
|
+
|
|
|
+ // 日志
|
|
|
+ private JTextArea logArea;
|
|
|
+
|
|
|
+ private Timer monitorTimer;
|
|
|
+
|
|
|
+ public PlcSignalPanel(String defaultIp) {
|
|
|
+ this.defaultIp = (defaultIp == null || defaultIp.trim().isEmpty()) ? "192.168.1.1" : defaultIp.trim();
|
|
|
+ initUI();
|
|
|
+ startMonitor();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initUI() {
|
|
|
+ setTitle("OP50 PLC 信号监控 - 框架总成焊接1");
|
|
|
+ setSize(900, 900);
|
|
|
+ setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
|
|
+ setLocationRelativeTo(null);
|
|
|
+
|
|
|
+ JPanel main = new JPanel(new BorderLayout(8, 8));
|
|
|
+ main.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
|
|
|
+
|
|
|
+ JPanel top = new JPanel();
|
|
|
+ top.setLayout(new BoxLayout(top, BoxLayout.Y_AXIS));
|
|
|
+ top.add(createConnPanel());
|
|
|
+ top.add(createPositionPanel());
|
|
|
+ top.add(createPermitPanel());
|
|
|
+ top.add(createStatusPanel());
|
|
|
+ main.add(top, BorderLayout.NORTH);
|
|
|
+
|
|
|
+ JPanel center = new JPanel(new BorderLayout(8, 8));
|
|
|
+ center.add(createWeldTablePanel(), BorderLayout.CENTER);
|
|
|
+ center.add(createLogPanel(), BorderLayout.SOUTH);
|
|
|
+ main.add(center, BorderLayout.CENTER);
|
|
|
+
|
|
|
+ add(main);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 连接控制面板
|
|
|
+ private JPanel createConnPanel() {
|
|
|
+ JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 5));
|
|
|
+ panel.setBorder(BorderFactory.createTitledBorder("连接控制"));
|
|
|
+
|
|
|
+ panel.add(label("PLC IP:", 14));
|
|
|
+
|
|
|
+ ipField = new JTextField(defaultIp, 14);
|
|
|
+ ipField.setFont(new Font("Consolas", Font.PLAIN, 14));
|
|
|
+ panel.add(ipField);
|
|
|
+
|
|
|
+ connectBtn = new JButton("连接");
|
|
|
+ connectBtn.addActionListener(e -> doConnect());
|
|
|
+ panel.add(connectBtn);
|
|
|
+
|
|
|
+ disconnectBtn = new JButton("断开");
|
|
|
+ disconnectBtn.setEnabled(false);
|
|
|
+ disconnectBtn.addActionListener(e -> doDisconnect());
|
|
|
+ panel.add(disconnectBtn);
|
|
|
+
|
|
|
+ connLight = light(GRAY);
|
|
|
+ panel.add(connLight);
|
|
|
+
|
|
|
+ panel.add(label("S7-1200 / DB200", 12));
|
|
|
+ return panel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转台位置面板
|
|
|
+ private JPanel createPositionPanel() {
|
|
|
+ JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT, 12, 5));
|
|
|
+ panel.setBorder(BorderFactory.createTitledBorder("转台位置(只读)"));
|
|
|
+
|
|
|
+ panel.add(label("A面到位 " + A_POSITION, 13));
|
|
|
+ lightPosA = light(GRAY);
|
|
|
+ panel.add(lightPosA);
|
|
|
+
|
|
|
+ panel.add(label(" B面到位 " + B_POSITION, 13));
|
|
|
+ lightPosB = light(GRAY);
|
|
|
+ panel.add(lightPosB);
|
|
|
+
|
|
|
+ panel.add(label(" 推算当前面:", 13));
|
|
|
+ valueCurSide = new JLabel("--");
|
|
|
+ valueCurSide.setFont(new Font("微软雅黑", Font.BOLD, 16));
|
|
|
+ valueCurSide.setForeground(BLUE);
|
|
|
+ panel.add(valueCurSide);
|
|
|
+
|
|
|
+ return panel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // MES允许启动面板
|
|
|
+ private JPanel createPermitPanel() {
|
|
|
+ JPanel panel = new JPanel(new GridLayout(2, 1, 4, 4));
|
|
|
+ panel.setBorder(BorderFactory.createTitledBorder("MES允许启动(可读写 — 写操作会真实影响 PLC)"));
|
|
|
+
|
|
|
+ JPanel rowA = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 3));
|
|
|
+ rowA.add(fixedLabel("A面MES允许启动 " + A_PERMIT, 230));
|
|
|
+ lightPermitA = light(GRAY);
|
|
|
+ rowA.add(lightPermitA);
|
|
|
+ permitSetA = new JButton("置位 true");
|
|
|
+ permitSetA.addActionListener(e -> writePermit("A", true));
|
|
|
+ rowA.add(permitSetA);
|
|
|
+ permitResetA = new JButton("复位 false");
|
|
|
+ permitResetA.addActionListener(e -> writePermit("A", false));
|
|
|
+ rowA.add(permitResetA);
|
|
|
+ panel.add(rowA);
|
|
|
+
|
|
|
+ JPanel rowB = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 3));
|
|
|
+ rowB.add(fixedLabel("B面MES允许启动 " + B_PERMIT, 230));
|
|
|
+ lightPermitB = light(GRAY);
|
|
|
+ rowB.add(lightPermitB);
|
|
|
+ permitSetB = new JButton("置位 true");
|
|
|
+ permitSetB.addActionListener(e -> writePermit("B", true));
|
|
|
+ rowB.add(permitSetB);
|
|
|
+ permitResetB = new JButton("复位 false");
|
|
|
+ permitResetB.addActionListener(e -> writePermit("B", false));
|
|
|
+ rowB.add(permitResetB);
|
|
|
+ panel.add(rowB);
|
|
|
+
|
|
|
+ return panel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 焊接状态面板
|
|
|
+ private JPanel createStatusPanel() {
|
|
|
+ JPanel panel = new JPanel(new GridLayout(2, 1, 4, 4));
|
|
|
+ panel.setBorder(BorderFactory.createTitledBorder("焊接状态(只读 Int16 — 0空闲/1运行中/2完成)"));
|
|
|
+
|
|
|
+ JPanel rowA = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 3));
|
|
|
+ rowA.add(fixedLabel("A面状态 " + A_STATUS, 180));
|
|
|
+ lightStatusA = light(GRAY);
|
|
|
+ rowA.add(lightStatusA);
|
|
|
+ valueStatusA = valueLabel("--");
|
|
|
+ rowA.add(valueStatusA);
|
|
|
+ ackBtnA = new JButton("应答清零");
|
|
|
+ ackBtnA.addActionListener(e -> ackStatus("A"));
|
|
|
+ rowA.add(ackBtnA);
|
|
|
+ panel.add(rowA);
|
|
|
+
|
|
|
+ JPanel rowB = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 3));
|
|
|
+ rowB.add(fixedLabel("B面状态 " + B_STATUS, 180));
|
|
|
+ lightStatusB = light(GRAY);
|
|
|
+ rowB.add(lightStatusB);
|
|
|
+ valueStatusB = valueLabel("--");
|
|
|
+ rowB.add(valueStatusB);
|
|
|
+ ackBtnB = new JButton("应答清零");
|
|
|
+ ackBtnB.addActionListener(e -> ackStatus("B"));
|
|
|
+ rowB.add(ackBtnB);
|
|
|
+ panel.add(rowB);
|
|
|
+
|
|
|
+ return panel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 焊接参数表格面板
|
|
|
+ private JPanel createWeldTablePanel() {
|
|
|
+ JPanel panel = new JPanel(new BorderLayout());
|
|
|
+ panel.setBorder(BorderFactory.createTitledBorder("焊接参数(只读 — R1~R4 四个焊点)"));
|
|
|
+
|
|
|
+ String[] cols = {"焊点", "完成标志", "序号", "电流", "电压", "送丝速度", "焊接速度"};
|
|
|
+ weldModel = new DefaultTableModel(cols, 0) {
|
|
|
+ @Override
|
|
|
+ public boolean isCellEditable(int row, int column) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 初始化 4 行
|
|
|
+ for (String[] point : WELD_POINTS) {
|
|
|
+ weldModel.addRow(new Object[]{point[0], "--", "--", "--", "--", "--", "--"});
|
|
|
+ }
|
|
|
+
|
|
|
+ JTable table = new JTable(weldModel);
|
|
|
+ table.setFont(new Font("Consolas", Font.PLAIN, 13));
|
|
|
+ table.setRowHeight(28);
|
|
|
+ table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13));
|
|
|
+
|
|
|
+ // 完成标志列居中,用绿点显示
|
|
|
+ DefaultTableCellRenderer centerRenderer = new DefaultTableCellRenderer();
|
|
|
+ centerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
|
|
|
+ table.getColumnModel().getColumn(1).setCellRenderer(centerRenderer);
|
|
|
+
|
|
|
+ JScrollPane scroll = new JScrollPane(table);
|
|
|
+ scroll.setPreferredSize(new Dimension(0, 150));
|
|
|
+ panel.add(scroll, BorderLayout.CENTER);
|
|
|
+
|
|
|
+ return panel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 日志面板
|
|
|
+ private JPanel createLogPanel() {
|
|
|
+ JPanel panel = new JPanel(new BorderLayout());
|
|
|
+ panel.setBorder(BorderFactory.createTitledBorder("操作日志"));
|
|
|
+
|
|
|
+ logArea = new JTextArea(6, 0);
|
|
|
+ logArea.setEditable(false);
|
|
|
+ logArea.setFont(new Font("微软雅黑", Font.PLAIN, 12));
|
|
|
+ JScrollPane scroll = new JScrollPane(logArea);
|
|
|
+ panel.add(scroll, BorderLayout.CENTER);
|
|
|
+
|
|
|
+ return panel;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 连接 PLC
|
|
|
+ private void doConnect() {
|
|
|
+ String ip = ipField.getText().trim();
|
|
|
+ if (ip.isEmpty()) {
|
|
|
+ JOptionPane.showMessageDialog(this, "请输入 PLC IP 地址", "提示", JOptionPane.WARNING_MESSAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ connectBtn.setEnabled(false);
|
|
|
+ log("连接中: " + ip);
|
|
|
+
|
|
|
+ new Thread(() -> {
|
|
|
+ try {
|
|
|
+ s7PLC = new S7PLC(EPlcType.S1200, ip);
|
|
|
+ // 测试连接
|
|
|
+ s7PLC.readBoolean(A_POSITION);
|
|
|
+ connected = true;
|
|
|
+ SwingUtilities.invokeLater(() -> {
|
|
|
+ connectBtn.setEnabled(false);
|
|
|
+ disconnectBtn.setEnabled(true);
|
|
|
+ ipField.setEnabled(false);
|
|
|
+ log("✓ 连接成功: " + ip);
|
|
|
+ });
|
|
|
+ } catch (Exception e) {
|
|
|
+ connected = false;
|
|
|
+ SwingUtilities.invokeLater(() -> {
|
|
|
+ connectBtn.setEnabled(true);
|
|
|
+ disconnectBtn.setEnabled(false);
|
|
|
+ log("✗ 连接失败: " + e.getMessage());
|
|
|
+ JOptionPane.showMessageDialog(this, "连接失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }, "PLC-Connect").start();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 断开 PLC
|
|
|
+ private void doDisconnect() {
|
|
|
+ try {
|
|
|
+ if (s7PLC != null) {
|
|
|
+ s7PLC.close();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log("断开异常: " + e.getMessage());
|
|
|
+ }
|
|
|
+ connected = false;
|
|
|
+ s7PLC = null;
|
|
|
+ connectBtn.setEnabled(true);
|
|
|
+ disconnectBtn.setEnabled(false);
|
|
|
+ ipField.setEnabled(true);
|
|
|
+ log("已断开连接");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 写许可信号
|
|
|
+ private void writePermit(String side, boolean value) {
|
|
|
+ if (!connected) {
|
|
|
+ JOptionPane.showMessageDialog(this, "PLC 未连接", "提示", JOptionPane.WARNING_MESSAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String addr = side.equals("A") ? A_PERMIT : B_PERMIT;
|
|
|
+ int confirm = JOptionPane.showConfirmDialog(this,
|
|
|
+ "确认写入 " + addr + " = " + value + " ?\n这会影响 PLC 实际状态!",
|
|
|
+ "写操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
|
|
+
|
|
|
+ if (confirm != JOptionPane.YES_OPTION) {
|
|
|
+ log("已取消写操作: " + addr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ new Thread(() -> {
|
|
|
+ try {
|
|
|
+ s7PLC.writeBoolean(addr, value);
|
|
|
+ log("✓ 写入成功: " + addr + " = " + value);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log("✗ 写入失败: " + addr + " - " + e.getMessage());
|
|
|
+ SwingUtilities.invokeLater(() ->
|
|
|
+ JOptionPane.showMessageDialog(this, "写入失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE));
|
|
|
+ }
|
|
|
+ }, "PLC-Write").start();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 应答清零状态
|
|
|
+ private void ackStatus(String side) {
|
|
|
+ if (!connected) {
|
|
|
+ JOptionPane.showMessageDialog(this, "PLC 未连接", "提示", JOptionPane.WARNING_MESSAGE);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ String addr = side.equals("A") ? A_STATUS : B_STATUS;
|
|
|
+ int confirm = JOptionPane.showConfirmDialog(this,
|
|
|
+ "确认应答清零 " + addr + " = 0 ?\n这会清除 PLC 焊接完成标志!",
|
|
|
+ "写操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
|
|
+
|
|
|
+ if (confirm != JOptionPane.YES_OPTION) {
|
|
|
+ log("已取消应答: " + addr);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ new Thread(() -> {
|
|
|
+ try {
|
|
|
+ s7PLC.writeInt16(addr, (short) 0);
|
|
|
+ log("✓ 应答成功: " + addr + " = 0");
|
|
|
+ } catch (Exception e) {
|
|
|
+ log("✗ 应答失败: " + addr + " - " + e.getMessage());
|
|
|
+ SwingUtilities.invokeLater(() ->
|
|
|
+ JOptionPane.showMessageDialog(this, "应答失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE));
|
|
|
+ }
|
|
|
+ }, "PLC-Ack").start();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 启动监控定时器
|
|
|
+ private void startMonitor() {
|
|
|
+ monitorTimer = new Timer();
|
|
|
+ monitorTimer.schedule(new TimerTask() {
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ updateMonitor();
|
|
|
+ }
|
|
|
+ }, 500, 1000); // 首次 0.5s,之后每 1s
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新监控数据
|
|
|
+ private void updateMonitor() {
|
|
|
+ boolean isConnected = connected && s7PLC != null;
|
|
|
+ SwingUtilities.invokeLater(() -> updateLight(connLight, isConnected));
|
|
|
+
|
|
|
+ if (!isConnected) {
|
|
|
+ SwingUtilities.invokeLater(this::clearAllDisplays);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 转台位置
|
|
|
+ boolean posA = readBoolSafe(A_POSITION);
|
|
|
+ boolean posB = readBoolSafe(B_POSITION);
|
|
|
+
|
|
|
+ // MES允许启动
|
|
|
+ boolean permitA = readBoolSafe(A_PERMIT);
|
|
|
+ boolean permitB = readBoolSafe(B_PERMIT);
|
|
|
+
|
|
|
+ // 焊接状态
|
|
|
+ int statusA = readInt16Safe(A_STATUS);
|
|
|
+ int statusB = readInt16Safe(B_STATUS);
|
|
|
+
|
|
|
+ // 焊接参数
|
|
|
+ Object[][] weldData = new Object[4][7];
|
|
|
+ for (int i = 0; i < WELD_POINTS.length; i++) {
|
|
|
+ String[] point = WELD_POINTS[i];
|
|
|
+ weldData[i][0] = point[0]; // 焊点名
|
|
|
+ weldData[i][1] = readBoolSafe(DB + "." + point[1]) ? "●" : "○"; // 完成标志
|
|
|
+ weldData[i][2] = readInt16Safe(DB + "." + point[2]); // 序号
|
|
|
+ weldData[i][3] = String.format("%.1f", readFloat32Safe(DB + "." + point[3])); // 电流
|
|
|
+ weldData[i][4] = String.format("%.1f", readFloat32Safe(DB + "." + point[4])); // 电压
|
|
|
+ weldData[i][5] = String.format("%.1f", readFloat32Safe(DB + "." + point[5])); // 送丝速度
|
|
|
+ weldData[i][6] = String.format("%.1f", readFloat32Safe(DB + "." + point[6])); // 焊接速度
|
|
|
+ }
|
|
|
+
|
|
|
+ // UI 更新
|
|
|
+ SwingUtilities.invokeLater(() -> {
|
|
|
+ // 转台位置
|
|
|
+ updateLight(lightPosA, posA);
|
|
|
+ updateLight(lightPosB, posB);
|
|
|
+ valueCurSide.setText(getCurSide(posA, posB));
|
|
|
+
|
|
|
+ // MES允许启动
|
|
|
+ updateLight(lightPermitA, permitA);
|
|
|
+ updateLight(lightPermitB, permitB);
|
|
|
+
|
|
|
+ // 焊接状态
|
|
|
+ updateStatusDisplay(statusA, lightStatusA, valueStatusA);
|
|
|
+ updateStatusDisplay(statusB, lightStatusB, valueStatusB);
|
|
|
+
|
|
|
+ // 焊接参数
|
|
|
+ for (int i = 0; i < weldData.length; i++) {
|
|
|
+ for (int j = 0; j < weldData[i].length; j++) {
|
|
|
+ weldModel.setValueAt(weldData[i][j], i, j);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ // 不阻塞轮询,静默记录
|
|
|
+ System.err.println("轮询异常: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 安全读取 Bool
|
|
|
+ private boolean readBoolSafe(String addr) {
|
|
|
+ try {
|
|
|
+ return s7PLC.readBoolean(addr);
|
|
|
+ } catch (Exception e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 安全读取 Int16
|
|
|
+ private int readInt16Safe(String addr) {
|
|
|
+ try {
|
|
|
+ return s7PLC.readInt16(addr);
|
|
|
+ } catch (Exception e) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 安全读取 Float32
|
|
|
+ private float readFloat32Safe(String addr) {
|
|
|
+ try {
|
|
|
+ return s7PLC.readFloat32(addr);
|
|
|
+ } catch (Exception e) {
|
|
|
+ return 0f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 推算当前面
|
|
|
+ private String getCurSide(boolean posA, boolean posB) {
|
|
|
+ if (posA) return "A";
|
|
|
+ if (posB) return "B";
|
|
|
+ return "--";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态显示
|
|
|
+ private void updateStatusDisplay(int status, JLabel light, JLabel valueLabel) {
|
|
|
+ String text;
|
|
|
+ Color color;
|
|
|
+ if (status == 0) {
|
|
|
+ text = "0 空闲";
|
|
|
+ color = GRAY;
|
|
|
+ } else if (status == 1) {
|
|
|
+ text = "1 运行中";
|
|
|
+ color = YELLOW;
|
|
|
+ } else if (status == 2) {
|
|
|
+ text = "2 完成";
|
|
|
+ color = GREEN;
|
|
|
+ } else {
|
|
|
+ text = status + " (?)";
|
|
|
+ color = GRAY;
|
|
|
+ }
|
|
|
+ valueLabel.setText(text);
|
|
|
+ updateLight(light, status > 0);
|
|
|
+ light.setForeground(color);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空所有显示
|
|
|
+ private void clearAllDisplays() {
|
|
|
+ updateLight(lightPosA, false);
|
|
|
+ updateLight(lightPosB, false);
|
|
|
+ valueCurSide.setText("--");
|
|
|
+ updateLight(lightPermitA, false);
|
|
|
+ updateLight(lightPermitB, false);
|
|
|
+ updateLight(lightStatusA, false);
|
|
|
+ updateLight(lightStatusB, false);
|
|
|
+ valueStatusA.setText("--");
|
|
|
+ valueStatusB.setText("--");
|
|
|
+ for (int i = 0; i < weldModel.getRowCount(); i++) {
|
|
|
+ for (int j = 1; j < weldModel.getColumnCount(); j++) {
|
|
|
+ weldModel.setValueAt("--", i, j);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新指示灯颜色
|
|
|
+ private void updateLight(JLabel light, boolean on) {
|
|
|
+ light.setForeground(on ? GREEN : GRAY);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 日志记录
|
|
|
+ private void log(String msg) {
|
|
|
+ String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
|
|
|
+ SwingUtilities.invokeLater(() -> {
|
|
|
+ logArea.append("[" + time + "] " + msg + "\n");
|
|
|
+ logArea.setCaretPosition(logArea.getDocument().getLength());
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 停止监控
|
|
|
+ public void stopMonitor() {
|
|
|
+ if (monitorTimer != null) {
|
|
|
+ monitorTimer.cancel();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ===== UI 组件工具方法 =====
|
|
|
+
|
|
|
+ private JLabel light(Color color) {
|
|
|
+ JLabel light = new JLabel("●");
|
|
|
+ light.setFont(new Font("Arial", Font.BOLD, 28));
|
|
|
+ light.setForeground(color);
|
|
|
+ return light;
|
|
|
+ }
|
|
|
+
|
|
|
+ private JLabel label(String text, int fontSize) {
|
|
|
+ JLabel label = new JLabel(text);
|
|
|
+ label.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));
|
|
|
+ return label;
|
|
|
+ }
|
|
|
+
|
|
|
+ private JLabel fixedLabel(String text, int width) {
|
|
|
+ JLabel label = new JLabel(text);
|
|
|
+ label.setFont(new Font("微软雅黑", Font.PLAIN, 13));
|
|
|
+ label.setPreferredSize(new Dimension(width, 25));
|
|
|
+ return label;
|
|
|
+ }
|
|
|
+
|
|
|
+ private JLabel valueLabel(String text) {
|
|
|
+ JLabel label = new JLabel(text);
|
|
|
+ label.setFont(new Font("Consolas", Font.BOLD, 15));
|
|
|
+ label.setForeground(BLUE);
|
|
|
+ return label;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|