liuwei 5 napja
szülő
commit
1b4e7c8df6

+ 3 - 1
src/com/mes/plc/TjPlcConfig.java

@@ -13,7 +13,9 @@ import java.nio.charset.StandardCharsets;
 import java.util.Properties;
 
 /**
- * 涂胶 PLC 配置:一台 PLC,a1/b1 为两把胶枪地址。
+ * 涂胶 PLC 监控配置:一台 PLC。
+ * a1 对齐服务端 ProductTjScheduling(OP220);
+ * b1 对齐服务端 ProductTjBScheduling(OP240B)。
  */
 public class TjPlcConfig {
 

+ 103 - 33
src/com/mes/plc/TjPlcMonitorPanel.java

@@ -9,7 +9,8 @@ import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * 涂胶 PLC 监控:可改 IP;同一台 PLC 同时显示 a1 / b1 两把胶枪数据。
+ * 涂胶 PLC 只读监控(对齐服务端 ProductTjScheduling / ProductTjBScheduling)。
+ * 唯一写操作:A/B「重置进站」将质量通过位(64.2 / 64.3)置 false。
  */
 public class TjPlcMonitorPanel extends JPanel {
 
@@ -17,13 +18,14 @@ public class TjPlcMonitorPanel extends JPanel {
     private final JTextField hostField = new JTextField(16);
     private final JLabel dbLabel = new JLabel("-");
 
-    private final GunView a1View = new GunView("胶枪 A1");
-    private final GunView b1View = new GunView("胶枪 B1");
+    private final GunView a1View = new GunView("TJ / OP220", true);
+    private final GunView b1View = new GunView("TJB / OP240B", false);
 
     private TjPlcConfig config;
     private TjS7Client s7Client;
     private Timer timer;
     private final AtomicBoolean refreshing = new AtomicBoolean(false);
+    private final AtomicBoolean resetting = new AtomicBoolean(false);
     private volatile boolean active;
 
     public TjPlcMonitorPanel() {
@@ -42,7 +44,7 @@ public class TjPlcMonitorPanel extends JPanel {
 
         JButton refreshBtn = new JButton("立即刷新");
         refreshBtn.setFont(new Font("微软雅黑", Font.PLAIN, 16));
-        refreshBtn.addActionListener(e -> refreshOnce());
+        refreshBtn.addActionListener(e -> refreshOnce(true));
 
         statusLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
         dbLabel.setFont(new Font("Consolas", Font.PLAIN, 16));
@@ -60,13 +62,18 @@ public class TjPlcMonitorPanel extends JPanel {
         center.add(b1View);
         add(center, BorderLayout.CENTER);
 
-        loadUiFromConfig();
+        loadUiFromConfig(true);
     }
 
-    private void loadUiFromConfig() {
+    private void loadUiFromConfig(boolean syncHostField) {
+        String keepHost = hostField.getText() == null ? "" : hostField.getText().trim();
         config = TjPlcConfig.load();
-        hostField.setText(config.host);
-        dbLabel.setText("DB" + config.db + "  工作枪=" + config.machine);
+        if (syncHostField || keepHost.isEmpty()) {
+            hostField.setText(config.host);
+        } else {
+            config.host = keepHost;
+        }
+        dbLabel.setText("DB" + config.db + "  只读监控(作业在服务端)");
         a1View.bindAddr(config.a1, config.db);
         b1View.bindAddr(config.b1, config.db);
     }
@@ -84,21 +91,19 @@ public class TjPlcMonitorPanel extends JPanel {
         if (s7Client != null) {
             s7Client.updateHost(ip);
         }
-        TjPlcPoller.reloadHost(ip);
         if (ok) {
             statusLabel.setForeground(new Color(0, 128, 0));
             statusLabel.setText("IP已保存: " + ip);
-            refreshOnce();
         } else {
             statusLabel.setForeground(Color.ORANGE.darker());
             statusLabel.setText("IP已用于当前连接,但写配置文件失败");
-            refreshOnce();
         }
+        refreshOnce(true);
     }
 
     public void startMonitor() {
         active = true;
-        loadUiFromConfig();
+        loadUiFromConfig(true);
         if (s7Client == null) {
             s7Client = new TjS7Client(config);
         } else {
@@ -112,7 +117,7 @@ public class TjPlcMonitorPanel extends JPanel {
             @Override
             public void run() {
                 if (active) {
-                    refreshOnce();
+                    refreshOnce(true);
                 }
             }
         }, 200, 1000);
@@ -131,17 +136,20 @@ public class TjPlcMonitorPanel extends JPanel {
         SwingUtilities.invokeLater(() -> statusLabel.setText("已停止刷新"));
     }
 
-    private void refreshOnce() {
+    /**
+     * @param reloadConfig true=从磁盘重载偏移/类型地址(立即刷新与定时刷新都重载,避免改配置后必须重启)
+     */
+    private void refreshOnce(boolean reloadConfig) {
         if (!refreshing.compareAndSet(false, true)) {
             return;
         }
         try {
-            if (config == null) {
-                config = TjPlcConfig.load();
+            String ipBefore = hostField.getText() == null ? "" : hostField.getText().trim();
+            if (reloadConfig || config == null) {
+                loadUiFromConfig(false);
             }
-            String ip = hostField.getText() == null ? "" : hostField.getText().trim();
-            if (!ip.isEmpty()) {
-                config.host = ip;
+            if (!ipBefore.isEmpty()) {
+                config.host = ipBefore;
             }
             if (s7Client == null) {
                 s7Client = new TjS7Client(config);
@@ -163,16 +171,16 @@ public class TjPlcMonitorPanel extends JPanel {
                     statusLabel.setText("已连接 · 实时刷新中");
                 } else if (connDead) {
                     statusLabel.setForeground(Color.RED);
-                    statusLabel.setText("A1/B1均失败: " + shorten(a1.firstError()));
+                    statusLabel.setText("TJ/TJB均失败: " + shorten(a1.firstError()));
                 } else if (!a1Ok && !b1Ok) {
                     statusLabel.setForeground(Color.RED);
-                    statusLabel.setText("A1失败[" + a1.firstFailAddr + "]  B1失败[" + b1.firstFailAddr + "]");
+                    statusLabel.setText("TJ失败[" + a1.firstFailAddr + "]  TJB失败[" + b1.firstFailAddr + "]");
                 } else if (!a1Ok) {
                     statusLabel.setForeground(Color.RED);
-                    statusLabel.setText("A1失败[" + a1.firstFailAddr + "]: " + shorten(a1.firstError()));
+                    statusLabel.setText("TJ失败[" + a1.firstFailAddr + "]: " + shorten(a1.firstError()));
                 } else {
                     statusLabel.setForeground(Color.RED);
-                    statusLabel.setText("B1失败[" + b1.firstFailAddr + "]: " + shorten(b1.firstError()));
+                    statusLabel.setText("TJB失败[" + b1.firstFailAddr + "]: " + shorten(b1.firstError()));
                 }
             });
 
@@ -195,6 +203,52 @@ public class TjPlcMonitorPanel extends JPanel {
         }
     }
 
+    private void resetAllowEntry(boolean isA) {
+        if (!resetting.compareAndSet(false, true)) {
+            return;
+        }
+        final String side = isA ? "TJ/OP220" : "TJB/OP240B";
+        final String addrHint = isA ? "DB1300.DBX64.2" : "DB1300.DBX64.3";
+        int confirm = JOptionPane.showConfirmDialog(this,
+                "确认将 " + side + " 质量校验通过(允许进站)置为 0?\n地址: " + addrHint,
+                "重置进站", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
+        if (confirm != JOptionPane.YES_OPTION) {
+            resetting.set(false);
+            return;
+        }
+        new Thread(() -> {
+            try {
+                if (config == null) {
+                    loadUiFromConfig(false);
+                }
+                String ip = hostField.getText() == null ? "" : hostField.getText().trim();
+                if (!ip.isEmpty()) {
+                    config.host = ip;
+                }
+                if (s7Client == null) {
+                    s7Client = new TjS7Client(config);
+                } else {
+                    s7Client.updateHost(config.host);
+                }
+                TjPlcConfig.GunAddr gun = isA ? config.a1 : config.b1;
+                s7Client.writeBit(gun.allowEntryByte, gun.allowEntryBit, false);
+                SwingUtilities.invokeLater(() -> {
+                    statusLabel.setForeground(new Color(0, 128, 0));
+                    statusLabel.setText(side + " 已重置进站位=0 (" + gun.allowEntryAddr(config.db) + ")");
+                });
+                refreshOnce(false);
+            } catch (Exception e) {
+                final String msg = e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage();
+                SwingUtilities.invokeLater(() -> {
+                    statusLabel.setForeground(Color.RED);
+                    statusLabel.setText(side + " 重置失败: " + shorten(msg));
+                });
+            } finally {
+                resetting.set(false);
+            }
+        }, "TjResetAllowEntry").start();
+    }
+
     private static String shorten(String msg) {
         if (msg == null) {
             return "";
@@ -224,7 +278,6 @@ public class TjPlcMonitorPanel extends JPanel {
                 gun.seqAddr(config.db), s);
         s.glueSpeed = readText(() -> String.format("%.3f", s7Client.readFloat(gun.glueSpeedOffset)),
                 gun.glueSpeedAddr(config.db), s);
-        // 涂胶长度:Word
         s.glueLength = readText(() -> String.valueOf(s7Client.readUInt16(gun.glueLengthOffset)),
                 gun.glueLengthAddr(config.db), s);
         return s;
@@ -293,7 +346,8 @@ public class TjPlcMonitorPanel extends JPanel {
         }
     }
 
-    private static class GunView extends JPanel {
+    private class GunView extends JPanel {
+        private final boolean isA;
         private final JLabel frameCode = valueLabel();
         private final JLabel scanFeedback = valueLabel();
         private final JLabel allowEntry = valueLabel();
@@ -312,7 +366,8 @@ public class TjPlcMonitorPanel extends JPanel {
         private final JLabel glueSpeedAddr = addrLabel();
         private final JLabel glueLengthAddr = addrLabel();
 
-        GunView(String title) {
+        GunView(String title, boolean isA) {
+            this.isA = isA;
             setLayout(new GridBagLayout());
             setBorder(BorderFactory.createTitledBorder(
                     BorderFactory.createEtchedBorder(), title,
@@ -325,12 +380,26 @@ public class TjPlcMonitorPanel extends JPanel {
             int row = 0;
             row = addRow(c, row, "框架码", frameCode, frameCodeAddr);
             row = addRow(c, row, "扫码反馈", scanFeedback, scanFeedbackAddr);
-            row = addRow(c, row, "允许进站", allowEntry, allowEntryAddr);
-            row = addRow(c, row, "单道结束", pathDone, pathDoneAddr);
-            row = addRow(c, row, "全部结束", allDone, allDoneAddr);
+            row = addRow(c, row, "质量校验通过", allowEntry, allowEntryAddr);
+            row = addRow(c, row, "涂胶采集触发", pathDone, pathDoneAddr);
+            row = addRow(c, row, "整体完成", allDone, allDoneAddr);
             row = addRow(c, row, "涂胶序号", seq, seqAddr);
             row = addRow(c, row, "涂胶速度", glueSpeed, glueSpeedAddr);
-            addRow(c, row, "涂胶长度", glueLength, glueLengthAddr);
+            row = addRow(c, row, "涂胶长度", glueLength, glueLengthAddr);
+
+            JButton resetBtn = new JButton("重置进站");
+            resetBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));
+            resetBtn.setMargin(new Insets(2, 8, 2, 8));
+            resetBtn.setPreferredSize(new Dimension(88, 26));
+            resetBtn.setToolTipText("将质量校验通过位写 0(A=64.2 / B=64.3)");
+            resetBtn.addActionListener(e -> resetAllowEntry(this.isA));
+            c.gridx = 0;
+            c.gridy = row;
+            c.gridwidth = 1;
+            c.weightx = 0;
+            c.fill = GridBagConstraints.NONE;
+            c.anchor = GridBagConstraints.WEST;
+            add(resetBtn, c);
         }
 
         private int addRow(GridBagConstraints c, int row, String title, JLabel value, JLabel addr) {
@@ -338,6 +407,7 @@ public class TjPlcMonitorPanel extends JPanel {
             name.setFont(new Font("微软雅黑", Font.PLAIN, 16));
             c.gridx = 0;
             c.gridy = row;
+            c.gridwidth = 1;
             c.weightx = 0;
             add(name, c);
             c.gridx = 1;
@@ -371,18 +441,18 @@ public class TjPlcMonitorPanel extends JPanel {
             setField(glueLength, s.glueLength);
         }
 
-        private static void setField(JLabel label, FieldVal fv) {
+        private void setField(JLabel label, FieldVal fv) {
             label.setText(fv.text);
             label.setForeground(fv.ok ? Color.BLACK : Color.RED);
         }
 
-        private static JLabel valueLabel() {
+        private JLabel valueLabel() {
             JLabel l = new JLabel("-");
             l.setFont(new Font("微软雅黑", Font.BOLD, 18));
             return l;
         }
 
-        private static JLabel addrLabel() {
+        private JLabel addrLabel() {
             JLabel l = new JLabel("-");
             l.setFont(new Font("Consolas", Font.PLAIN, 13));
             l.setForeground(Color.DARK_GRAY);

+ 9 - 16
src/com/mes/ui/MesClient.java

@@ -6,7 +6,6 @@ import com.mes.component.MesRadio;
 import com.mes.component.MesWebView;
 import com.mes.netty.NettyClient;
 import com.mes.plc.TjPlcMonitorPanel;
-import com.mes.plc.TjPlcPoller;
 import com.mes.util.DateLocalUtils;
 import com.mes.util.JdbcUtils;
 import javafx.embed.swing.JFXPanel;
@@ -189,7 +188,7 @@ public class MesClient extends JFrame {
                     serialPort = ModbusRtu.connect();
 
                     startJsTimer();
-                    TjPlcPoller.start();
+                    // 涂胶作业已迁服务端 ProductTj/ProductTjB;客户端仅保留 PLC 监控
 
                 }catch (Exception e){
                     e.printStackTrace();
@@ -400,7 +399,6 @@ public class MesClient extends JFrame {
         MesClient.jsCount = 0;
         clearTjPathCache();
         refreshTjPathUi();
-        TjPlcPoller.resetCycle();
 //        MesClient.formatDeviceState();
         ModbusRtu.closeDevice(serialPort);
         updateMaterailData();
@@ -745,35 +743,27 @@ public class MesClient extends JFrame {
         finish_ng_bt.setEnabled(false);
         indexPanelA.add(finish_ng_bt);
 
-        tabbedPane.addTab("工作面板", new ImageIcon(MesClient.class.getResource("/bg/a_side.png")), indexScrollPaneA, null);
-        tabbedPane.setEnabledAt(0, true);
-
+        // 只展示 PLC 监控界面(作业在服务端)
         tjPlcMonitorPanel = new TjPlcMonitorPanel();
         JScrollPane tjMonitorScroll = new JScrollPane(tjPlcMonitorPanel);
         tabbedPane.addTab("PLC监控", new ImageIcon(MesClient.class.getResource("/bg/menu_data_preprocess.png")), tjMonitorScroll, null);
 
-//		searchScrollPane = new JScrollPane((Component) null);
-
         indexPanelC = new JPanel();
         searchScrollPaneDj = new JScrollPane(indexPanelC);
         indexPanelC.setLayout(null);
 
-        tabbedPane.addTab("开班点检", new ImageIcon(MesClient.class.getResource("/bg/menu_data_preprocess.png")), searchScrollPaneDj, null);
-
-
         indexPanelB = new JPanel();
         searchScrollPane = new JScrollPane(indexPanelB);
         indexPanelB.setLayout(null);
 
-		tabbedPane.addTab("工作记录", new ImageIcon(MesClient.class.getResource("/bg/menu_data_preprocess.png")), searchScrollPane, null);
-
-
 		tabbedPane.addChangeListener(new ChangeListener() {
             @Override
             public void stateChanged(ChangeEvent e) {
                 JTabbedPane pane = (JTabbedPane) e.getSource();
                 int selectedIndex = pane.getSelectedIndex();
-                System.out.println("selectedIndex:"+selectedIndex);
+                if (selectedIndex < 0) {
+                    return;
+                }
                 String title = pane.getTitleAt(selectedIndex);
                 if ("PLC监控".equals(title)) {
                     tjPlcMonitorPanel.startMonitor();
@@ -782,6 +772,9 @@ public class MesClient extends JFrame {
                 }
             }
         });
+
+        tabbedPane.setSelectedIndex(0);
+        tjPlcMonitorPanel.startMonitor();
     }
 
     public static void setMenuStatus(String msg,int error){
@@ -920,7 +913,7 @@ public class MesClient extends JFrame {
 
         JScrollPane indexScrollPaneB = new JScrollPane(indexPanelBB);
         indexPanelBB.setLayout(null);
-        tabbedPane.addTab("绑定物料", new ImageIcon(MesClient.class.getResource("/bg/menu_data_preprocess.png")), indexScrollPaneB, null);
+        // 监控专用客户端:不展示「绑定物料」Tab
     }
 
 }

+ 10 - 7
src/resources/config/config.properties

@@ -5,18 +5,20 @@ mes.tcp_port=3000
 mes.heart_beat_cycle=60
 mes.line_sn=XT
 
-# 工作面板当前处理哪把胶枪:a1 或 b1(同一台 PLC)
+# 历史字段,监控页不再做作业轮询
 mes.machine=a1
 
-# 涂胶 PLC:一台设备,a1/b1 为两把胶枪的不同地址
+# 涂胶 PLC 监控(作业握手已迁服务端 ProductTj / ProductTjB)
+# mes.tj.plc.enabled 必须为 false:客户端不做扫码/采集
 mes.tj.plc.enabled=false
-mes.tj.plc.host=10.0.20.xxx
+mes.tj.plc.host=10.0.40.100
 mes.tj.plc.rack=0
 mes.tj.plc.slot=1
 mes.tj.plc.db=1300
 
-# ---- 胶枪 A1 (R1) ----
-# 与博途一致:序号Word=66,速度Real=68,长度Word=72
+# ---- TJ / OP220(对应 ProductTjScheduling)----
+# 框架码String[30]=0;扫码反馈=64.0;质量通过=64.2;采集触发=64.4;整体完成=64.5
+# 序号Word=66;速度Real=68;长度Word=72
 mes.tj.a1.frameCodeOffset=0
 mes.tj.a1.frameCodeLen=30
 mes.tj.a1.scanFeedbackByte=64
@@ -31,8 +33,9 @@ mes.tj.a1.seqOffset=66
 mes.tj.a1.glueSpeedOffset=68
 mes.tj.a1.glueLengthOffset=72
 
-# ---- 胶枪 B1 (R2) ----
-# 与博途 InterfaceMes[DB1300] 一致:单道/全部=74.0/74.1,序号=76,速度Real=78,长度Word=82
+# ---- TJB / OP240B(对应 ProductTjBScheduling)----
+# 框架码=32;扫码反馈=64.1;质量通过=64.3;采集触发=74.0;整体完成=74.1
+# 序号Word=76;速度Real=78;长度Word=82
 mes.tj.b1.frameCodeOffset=32
 mes.tj.b1.frameCodeLen=30
 mes.tj.b1.scanFeedbackByte=64