wangxichen 4 ngày trước cách đây
mục cha
commit
30f255484d

+ 96 - 33
src/com/mes/component/WorkJPanelScan.java

@@ -16,9 +16,10 @@ import java.util.Timer;
 import java.util.TimerTask;
 
 /**
- * 正面扫码面板(PLC 92 DB7010)
+ * 扫码面板(每台 PLC 一个,92 发 1、2 号枪,93 发 3 号枪,由 PLC 决定)
  * DB7010.0.0 请求扫码 / DB7010.0.1 扫码完成反馈 / DB7010.6(INT) 扫码枪号;0.2、2、4 为预留,不读不写
- * 请求扫码时按枪号触发对应扫码枪,读到 16 位码存入正面扫码槽,正面机台请求上料时取用
+ * 枪号 0=未发;正常同一时间 92、93 只有一个非 0,PLC 收到扫码完成反馈后清零
+ * 请求扫码时 PLC 给几号就触发几号枪,读到 16 位码存入正面扫码槽,正面机台请求上料时取用
  */
 public class WorkJPanelScan extends JPanel {
 
@@ -27,9 +28,10 @@ public class WorkJPanelScan extends JPanel {
     public static final int SN_LENGTH = 16;
 
     public String oprno = "OP130";
-    public String plcIp = WorkJPanelCnc.PLC_FRONT;
+    public String plcIp;
+    public String plcName;   // 92 / 93,用于界面和日志
     public String plcDb = "DB7010";
-    public String gunAddr = "DB7010.6"; // 扫码枪号 INT,1 对应 scan.ips 第一个
+    public String gunAddr = "DB7010.6";
 
     public S7PLC s7PLC;
     public SnSlot slot;
@@ -38,14 +40,16 @@ public class WorkJPanelScan extends JPanel {
     public Integer workHeight = 300;
 
     private boolean scanDone = false; // 本次请求已扫码成功,等 PLC 复位请求
+    private String lastGunState = ""; // 上次读到的枪号状态,变化时才记日志
 
     public JButton status_menu;
     public JTextField productSnFeeding; // 扫码槽当前码
-    public JTextField gunField;         // 当前扫码枪
+    public JTextField gunField;         // 本次扫码使用的枪
     public JButton resetFeedingBtn;
 
     public JLabel feedinglabel;    // 0.0 请求扫码
     public JLabel feedingmeslabel; // 0.1 扫码完成反馈
+    public JLabel gunNoLabel;      // DB7010.6 实时枪号
 
     public ImageIcon imageGreen;
     public ImageIcon imageGray;
@@ -55,9 +59,11 @@ public class WorkJPanelScan extends JPanel {
 
     public Timer oprnoTimer;
 
-    public WorkJPanelScan() {
+    public WorkJPanelScan(String plcIp) {
         this.setLayout(null);
         this.setBackground(Color.WHITE);
+        this.plcIp = plcIp;
+        this.plcName = plcIp.substring(plcIp.lastIndexOf('.') + 1);
         this.slot = MesClient.frontSlot;
 
         s7PLC = new S7PLC(EPlcType.S1500, plcIp);
@@ -70,6 +76,10 @@ public class WorkJPanelScan extends JPanel {
         startOprnoTimer();
     }
 
+    private String tag() {
+        return oprno + "扫码" + plcName;
+    }
+
     private void initUI() {
         JLabel oprnoLabel = new JLabel(oprno);
         oprnoLabel.setHorizontalAlignment(SwingConstants.CENTER);
@@ -78,7 +88,7 @@ public class WorkJPanelScan extends JPanel {
         oprnoLabel.setBounds(0, 0, workWidth / 5, 40);
         this.add(oprnoLabel);
 
-        JLabel nameLabel = new JLabel("正面扫码");
+        JLabel nameLabel = new JLabel(plcName + "扫码");
         nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
         nameLabel.setForeground(Color.BLACK);
         nameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
@@ -98,7 +108,7 @@ public class WorkJPanelScan extends JPanel {
             public void mouseClicked(MouseEvent e) {
                 String sn = productSnFeeding.getText().trim();
                 if (!sn.isEmpty()) {
-                    MesClient.createQRCode(sn, oprno + "扫码");
+                    MesClient.createQRCode(sn, tag());
                 }
             }
         });
@@ -120,7 +130,7 @@ public class WorkJPanelScan extends JPanel {
         addRowLabel("扫码枪", 100);
         gunField = createField(100, workWidth * 4 / 5);
         gunField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
-        gunField.setText("枪号读 " + gunAddr + ",共 " + MesClient.scanClients.length + " 把");
+        gunField.setText("未扫码");
 
         imageGreen = scaledIcon("/bg/green_dot.png");
         imageGray = scaledIcon("/bg/grey_dot.png");
@@ -130,19 +140,27 @@ public class WorkJPanelScan extends JPanel {
         feedingmeslabel.addMouseListener(new MouseAdapter() {
             public void mouseClicked(MouseEvent e) {
                 boolean ret = readBoolean(plcDb + ".0.1");
-                if (confirm("确定修改扫码完成反馈(" + plcDb + ".0.1)为" + !ret + "吗?")) {
+                if (confirm("确定修改" + plcName + "扫码完成反馈(" + plcDb + ".0.1)为" + !ret + "吗?")) {
                     writeScanFinish(!ret);
                 }
             }
         });
 
+        // 实时显示 PLC 给的枪号(DB7010.6),每轮刷新
+        gunNoLabel = new JLabel("PLC枪号:-");
+        gunNoLabel.setHorizontalAlignment(SwingConstants.LEFT);
+        gunNoLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
+        gunNoLabel.setForeground(Color.DARK_GRAY);
+        gunNoLabel.setBounds(workWidth * 2 / 3, 150, workWidth / 3, 30);
+        this.add(gunNoLabel);
+
         JLabel ipLabel = new JLabel("PLC " + plcIp + " | " + plcDb + " | 枪号 " + gunAddr);
         ipLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
         ipLabel.setForeground(Color.DARK_GRAY);
         ipLabel.setBounds(5, 230, workWidth * 2 / 3 + 55, 26);
         this.add(ipLabel);
 
-        signalMonitor = new PlcSignalMonitor02(s7PLC, plcDb, gunAddr, oprno + "扫码", MesClient.mesClientFrame);
+        signalMonitor = new PlcSignalMonitor02(s7PLC, plcDb, gunAddr, tag(), MesClient.mesClientFrame);
         signalBtn = signalMonitor.createSignalButton();
         signalBtn.setBounds(workWidth * 2 / 3 + 63, 230, 90, 26);
         this.add(signalBtn);
@@ -194,6 +212,11 @@ public class WorkJPanelScan extends JPanel {
         status_menu.setText(msg);
     }
 
+    // scan.ips 里配了这把枪即有效,PLC 发几号就用几号
+    private boolean isValidGun(int no) {
+        return no >= 1 && no <= MesClient.scanClients.length;
+    }
+
     // 定时任务 -----------------------------------------------------------------------------------------------------
 
     public void startOprnoTimer() {
@@ -208,7 +231,7 @@ public class WorkJPanelScan extends JPanel {
                         cycle();
                     }
                 } catch (Exception e) {
-                    log.error("<{}扫码>轮询异常", oprno, e);
+                    log.error("<{}>轮询异常", tag(), e);
                 }
             }
         }, 100, 1500);
@@ -220,6 +243,9 @@ public class WorkJPanelScan extends JPanel {
         feedinglabel.setIcon(retScan ? imageGreen : imageGray);
         feedingmeslabel.setIcon(retFinish ? imageGreen : imageGray);
 
+        Integer plcGunNo = readGunNo();
+        showGunNo(plcGunNo);
+
         // 显示扫码槽当前码,被正面机台取走后变空
         productSnFeeding.setText(slot.getSn());
 
@@ -236,22 +262,50 @@ public class WorkJPanelScan extends JPanel {
             }
             return;
         }
-        doScan();
+        doScan(plcGunNo);
     }
 
-    private void doScan() {
-        Integer plcGunNo = readGunNo();
-        int gunNo = plcGunNo == null ? 1 : plcGunNo; // 读不到枪号(点位还没加)时用 1 号枪
-        int gunCount = MesClient.scanClients.length;
-        if (gunNo < 1 || gunNo > gunCount) {
+    // 刷新界面上的 PLC 枪号:0=未发(灰),1-3 绿色,其他值/读不到红色
+    private void showGunNo(Integer no) {
+        if (no == null) {
+            gunNoLabel.setForeground(Color.RED);
+            gunNoLabel.setText("PLC枪号:读取失败");
+            gunNoLabel.setToolTipText(gunAddr + " 读取失败,不扫码");
+            return;
+        }
+        if (no == 0) {
+            gunNoLabel.setForeground(Color.GRAY);
+            gunNoLabel.setText("PLC枪号:0(未发)");
+            gunNoLabel.setToolTipText("本PLC未发枪号");
+            return;
+        }
+        boolean valid = isValidGun(no);
+        gunNoLabel.setForeground(valid ? new Color(0, 128, 0) : Color.RED);
+        gunNoLabel.setText("PLC枪号:" + no + (valid ? "" : "(无效)"));
+        gunNoLabel.setToolTipText(valid ? no + "号枪 " + MesClient.scanClients[no - 1].serverIP : "有效范围 1-" + MesClient.scanClients.length);
+    }
+
+    private void doScan(Integer plcGunNo) {
+        // 读不到枪号不扫码
+        if (plcGunNo == null) {
+            gunField.setText("未读到枪号");
+            setMenuStatus("读取" + gunAddr + "失败,不扫码", -1);
+            return;
+        }
+        int gunNo = plcGunNo;
+        // 0 = PLC 还没发枪号,等下一轮
+        if (gunNo == 0) {
+            setMenuStatus("请求扫码,等待PLC发枪号", 0);
+            return;
+        }
+        if (!isValidGun(gunNo)) {
             gunField.setText("枪号 " + gunNo + " 无效");
-            setMenuStatus("扫码枪号无效:" + gunNo + "(" + gunAddr + " 应为 1-" + gunCount + ")", -1);
+            setMenuStatus("扫码枪号无效:" + gunNo + "(" + gunAddr + " 应为 1-" + MesClient.scanClients.length + ")", -1);
             return;
         }
 
         TCPClient client = MesClient.scanClients[gunNo - 1];
-        gunField.setText(gunNo + "号枪 " + client.serverIP + ":" + client.serverPort
-                + (plcGunNo == null ? "(默认)" : ""));
+        gunField.setText(gunNo + "号枪 " + client.serverIP + ":" + client.serverPort);
         setMenuStatus(gunNo + "号枪扫码中...", 0);
 
         String sn = MesClient.scanQrcode(gunNo);
@@ -261,15 +315,15 @@ public class WorkJPanelScan extends JPanel {
             return;
         }
 
-        slot.put(sn, gunNo + "号枪");
+        slot.put(sn, gunNo + "号枪(" + plcName + ")");
         productSnFeeding.setText(sn);
         writeScanFinish(true);
         scanDone = true;
-        setMenuStatus("扫码成功" + (plcGunNo == null ? "(未读到" + gunAddr + ",用1号枪)" : ""), 0);
+        setMenuStatus("扫码成功", 0);
     }
 
     public void resetScan() {
-        slot.clear("人工清空");
+        slot.clear("人工清空(" + plcName + ")");
         productSnFeeding.setText("");
         scanDone = false;
         writeScanFinish(false);
@@ -278,16 +332,25 @@ public class WorkJPanelScan extends JPanel {
 
     // 与设备交互 -----------------------------------------------------------------------------------------
 
-    // 读扫码枪号,读失败返回 null
+    // 读扫码枪号,读失败返回 null;每轮都读,只在值变化时记日志
     private Integer readGunNo() {
+        Integer no = null;
+        String err = "";
         try {
-            int no = s7PLC.readInt16(gunAddr);
-            log.info("<{}扫码>读取{}-->成功,枪号:{}", oprno, gunAddr, no);
-            return no;
+            no = (int) s7PLC.readInt16(gunAddr);
         } catch (Exception e) {
-            log.warn("<{}扫码>读取{}-->失败,使用1号枪:{}", oprno, gunAddr, e.getMessage());
-            return null;
+            err = e.getMessage();
+        }
+        String state = no == null ? "ERR" : String.valueOf(no);
+        if (!state.equals(lastGunState)) {
+            lastGunState = state;
+            if (no == null) {
+                log.warn("<{}>读取{}-->失败,不扫码:{}", tag(), gunAddr, err);
+            } else {
+                log.info("<{}>读取{}-->枪号变为:{}", tag(), gunAddr, no);
+            }
         }
+        return no;
     }
 
     public void writeScanFinish(boolean b) {
@@ -298,7 +361,7 @@ public class WorkJPanelScan extends JPanel {
         try {
             return s7PLC.readBoolean(addr);
         } catch (Exception e) {
-            log.error("<{}扫码>读取{}-->失败:{}", oprno, addr, e.getMessage());
+            log.error("<{}>读取{}-->失败:{}", tag(), addr, e.getMessage());
             return false;
         }
     }
@@ -306,10 +369,10 @@ public class WorkJPanelScan extends JPanel {
     public boolean writeBoolean(String addr, boolean value) {
         try {
             s7PLC.writeBoolean(addr, value);
-            log.info("<{}扫码>写入{}-->成功,写入内容:{}", oprno, addr, value);
+            log.info("<{}>写入{}-->成功,写入内容:{}", tag(), addr, value);
             return true;
         } catch (Exception e) {
-            log.error("<{}扫码>写入{}-->失败,写入内容:{},{}", oprno, addr, value, e.getMessage());
+            log.error("<{}>写入{}-->失败,写入内容:{},{}", tag(), addr, value, e.getMessage());
             return false;
         }
     }

+ 6 - 3
src/com/mes/ui/MesClient.java

@@ -66,7 +66,8 @@ public class MesClient extends JFrame {
     public static final String[] SUB_STATIONS = {"A", "B", "C", "D", "E"};
     public static WorkJPanelCnc[] op130Panels = new WorkJPanelCnc[SUB_STATIONS.length];
     public static WorkJPanelCnc[] op135Panels = new WorkJPanelCnc[SUB_STATIONS.length];
-    public static WorkJPanelScan workJPanelScan;
+    public static WorkJPanelScan workJPanelScan92; // 92 DB7010(PLC 发 1、2 号枪)
+    public static WorkJPanelScan workJPanelScan93; // 93 DB7010(PLC 发 3 号枪)
     public static WorkJPanelBackSlot workJPanelBackSlot;
 
     public static void main(String[] args) {
@@ -276,13 +277,15 @@ public class MesClient extends JFrame {
             op130Panels[i] = new WorkJPanelCnc("OP130", SUB_STATIONS[i]);
             op135Panels[i] = new WorkJPanelCnc("OP135", SUB_STATIONS[i]);
         }
-        workJPanelScan = new WorkJPanelScan();
+        // 两台 PLC 的扫码都存入同一个正面扫码码
+        workJPanelScan92 = new WorkJPanelScan(WorkJPanelCnc.PLC_FRONT);
+        workJPanelScan93 = new WorkJPanelScan(WorkJPanelCnc.PLC_BACK);
         workJPanelBackSlot = new WorkJPanelBackSlot();
 
         // 每页 4 格,布局与原来一致
         tabbedPane.addTab("OP130正面:A-D", null,
                 gridTab(op130Panels[0], op130Panels[1], op130Panels[2], op130Panels[3]), null);
-        tabbedPane.addTab("OP130正面:E+扫码", null, gridTab(op130Panels[4], workJPanelScan), null);
+        tabbedPane.addTab("OP130正面:E+扫码", null, gridTab(op130Panels[4], workJPanelScan92, workJPanelScan93), null);
         tabbedPane.addTab("OP135反面:A-D", null,
                 gridTab(op135Panels[0], op135Panels[1], op135Panels[2], op135Panels[3]), null);
         tabbedPane.addTab("OP135反面:E+待上料码", null, gridTab(op135Panels[4], workJPanelBackSlot), null);

+ 2 - 3
src/resources/config/config.properties

@@ -2,8 +2,7 @@
 mes.server_ip=192.168.17.170
 mes.line_sn=CZ060
 
-# 正面扫码枪(PLC 92 DB7010 请求扫码时触发)
-# 按顺序对应 DB7010.6 扫码枪号:第1个=1号枪,第2个=2号枪,第3个=3号枪
-# 读不到 DB7010.6 时默认用 1 号枪
+# 扫码枪,按顺序对应 DB7010.6 扫码枪号:第1个=1号枪,第2个=2号枪,第3个=3号枪
+# PLC 发几号就用几号枪(92 发 1、2,93 发 3);读不到 DB7010.6 不扫码
 scan.ips=192.168.90.61,192.168.90.62,192.168.90.63
 scan.port=9004