张田野 2 tygodni temu
rodzic
commit
8aef4f6246

+ 333 - 0
src/com/mes/ui/ConfigPanel.java

@@ -0,0 +1,333 @@
+package com.mes.ui;
+
+import com.mes.util.JdbcUtils;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+
+public class ConfigPanel extends JPanel {
+
+    private static final Font LABEL_FONT = new Font("微软雅黑", Font.PLAIN, 16);
+    private static final Font TITLE_FONT = new Font("微软雅黑", Font.BOLD, 18);
+
+    private final JTextField gwField = new JTextField();
+    private final JTextField gwDesField = new JTextField();
+    private final JTextField lineSnField = new JTextField();
+    private final JTextField serverIpField = new JTextField();
+
+    private final GunFields gunA = new GunFields();
+    private final GunFields gunB = new GunFields();
+
+    public ConfigPanel() {
+        setLayout(new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridx = 0;
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.weightx = 1;
+        c.insets = new Insets(8, 12, 8, 12);
+
+        c.gridy = 0;
+        add(buildBasicPanel(), c);
+        c.gridy = 1;
+        add(buildGunPanel("A枪", gunA), c);
+        c.gridy = 2;
+        add(buildGunPanel("B枪", gunB), c);
+
+        JButton saveBtn = new JButton("保存配置");
+        saveBtn.setFont(new Font("微软雅黑", Font.PLAIN, 20));
+        saveBtn.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                saveConfig();
+            }
+        });
+        c.gridy = 3;
+        c.fill = GridBagConstraints.NONE;
+        c.anchor = GridBagConstraints.CENTER;
+        c.insets = new Insets(4, 12, 16, 12);
+        add(saveBtn, c);
+
+        JLabel hint = new JLabel("保存后请重启客户端生效。配置保存在本地数据库 mes_db.db。", SwingConstants.CENTER);
+        hint.setFont(new Font("微软雅黑", Font.PLAIN, 13));
+        hint.setForeground(Color.DARK_GRAY);
+        c.gridy = 4;
+        c.fill = GridBagConstraints.HORIZONTAL;
+        add(hint, c);
+
+        gwField.addFocusListener(new FocusAdapter() {
+            public void focusLost(FocusEvent e) {
+                autoFillGwDes();
+            }
+        });
+        lineSnField.addFocusListener(new FocusAdapter() {
+            public void focusLost(FocusEvent e) {
+                autoFillGwDes();
+            }
+        });
+
+        reloadFromMemory();
+    }
+
+    public void reloadFromMemory() {
+        ConfigUtil.loadFromDb();
+        gwField.setText(nvl(MesClient.mes_gw));
+        gwDesField.setText(nvl(MesClient.mes_gw_des));
+        lineSnField.setText(nvl(MesClient.mes_line_sn));
+        serverIpField.setText(nvl(MesClient.mes_server_ip));
+
+        gunA.ip.setText(nvl(MesClient.plcAIp));
+        gunA.setNum.setText(String.valueOf(MesClient.aSetNum));
+        gunA.sMin.setText(String.valueOf(MesClient.aSMin));
+        gunA.sMax.setText(String.valueOf(MesClient.aSMax));
+        gunA.fMin.setText(String.valueOf(MesClient.aFMin));
+        gunA.fMax.setText(String.valueOf(MesClient.aFMax));
+        gunA.switchEnable.setSelected(MesClient.aSwitchEnable);
+        gunA.switchFrom.setText(String.valueOf(MesClient.aSwitchFrom));
+        gunA.swSMin.setText(String.valueOf(MesClient.aSwitchSMin));
+        gunA.swSMax.setText(String.valueOf(MesClient.aSwitchSMax));
+        gunA.swFMin.setText(String.valueOf(MesClient.aSwitchFMin));
+        gunA.swFMax.setText(String.valueOf(MesClient.aSwitchFMax));
+        gunA.setSwitchEnabled(MesClient.aSwitchEnable);
+
+        gunB.ip.setText(nvl(MesClient.plcBIp));
+        gunB.setNum.setText(String.valueOf(MesClient.bSetNum));
+        gunB.sMin.setText(String.valueOf(MesClient.bSMin));
+        gunB.sMax.setText(String.valueOf(MesClient.bSMax));
+        gunB.fMin.setText(String.valueOf(MesClient.bFMin));
+        gunB.fMax.setText(String.valueOf(MesClient.bFMax));
+        gunB.switchEnable.setSelected(MesClient.bSwitchEnable);
+        gunB.switchFrom.setText(String.valueOf(MesClient.bSwitchFrom));
+        gunB.swSMin.setText(String.valueOf(MesClient.bSwitchSMin));
+        gunB.swSMax.setText(String.valueOf(MesClient.bSwitchSMax));
+        gunB.swFMin.setText(String.valueOf(MesClient.bSwitchFMin));
+        gunB.swFMax.setText(String.valueOf(MesClient.bSwitchFMax));
+        gunB.setSwitchEnabled(MesClient.bSwitchEnable);
+    }
+
+    private JPanel buildBasicPanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "基本参数", 0, 0, TITLE_FONT));
+        addRow(panel, 0, "工位号", gwField);
+        addRow(panel, 1, "工位名称", gwDesField);
+        addRow(panel, 2, "产线编号", lineSnField);
+        addRow(panel, 3, "服务器IP", serverIpField);
+        return panel;
+    }
+
+    private JPanel buildGunPanel(String title, final GunFields g) {
+        JPanel panel = new JPanel(new GridBagLayout());
+        panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title, 0, 0, TITLE_FONT));
+        addRow(panel, 0, "设备地址", g.ip);
+        addRow(panel, 1, "拉铆颗数", g.setNum);
+        addRow(panel, 2, "初始行程下限(1070)", g.sMin);
+        addRow(panel, 3, "初始行程上限(1071)", g.sMax);
+        addRow(panel, 4, "初始拉力下限(1068)", g.fMin);
+        addRow(panel, 5, "初始拉力上限(1069)", g.fMax);
+
+        GridBagConstraints c = new GridBagConstraints();
+        c.gridx = 0;
+        c.gridy = 6;
+        c.gridwidth = 2;
+        c.anchor = GridBagConstraints.WEST;
+        c.insets = new Insets(6, 8, 4, 8);
+        g.switchEnable.setFont(LABEL_FONT);
+        g.switchEnable.setText("需要切换配方");
+        panel.add(g.switchEnable, c);
+
+        g.switchPanel.setLayout(new GridBagLayout());
+        addRow(g.switchPanel, 0, "第几颗开始切换", g.switchFrom);
+        addRow(g.switchPanel, 1, "切换后行程下限(1070)", g.swSMin);
+        addRow(g.switchPanel, 2, "切换后行程上限(1071)", g.swSMax);
+        addRow(g.switchPanel, 3, "切换后拉力下限(1068)", g.swFMin);
+        addRow(g.switchPanel, 4, "切换后拉力上限(1069)", g.swFMax);
+        c.gridy = 7;
+        c.fill = GridBagConstraints.HORIZONTAL;
+        c.weightx = 1;
+        c.insets = new Insets(0, 16, 8, 8);
+        panel.add(g.switchPanel, c);
+
+        g.switchEnable.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                g.setSwitchEnabled(g.switchEnable.isSelected());
+            }
+        });
+        return panel;
+    }
+
+    private void addRow(JPanel panel, int row, String label, JTextField field) {
+        GridBagConstraints c = new GridBagConstraints();
+        c.insets = new Insets(4, 8, 4, 8);
+        c.gridy = row;
+        c.anchor = GridBagConstraints.WEST;
+
+        JLabel lb = new JLabel(label);
+        lb.setFont(LABEL_FONT);
+        c.gridx = 0;
+        c.weightx = 0;
+        c.fill = GridBagConstraints.NONE;
+        panel.add(lb, c);
+
+        field.setFont(LABEL_FONT);
+        field.setColumns(18);
+        c.gridx = 1;
+        c.weightx = 1;
+        c.fill = GridBagConstraints.HORIZONTAL;
+        panel.add(field, c);
+    }
+
+    private void autoFillGwDes() {
+        String gw = gwField.getText().trim();
+        String lineSn = lineSnField.getText().trim();
+        if (gw.isEmpty() || lineSn.isEmpty()) {
+            return;
+        }
+        String des = OprnoUtil.lookupGwDes(lineSn, gw);
+        if (des != null && !des.isEmpty()) {
+            String cur = gwDesField.getText().trim();
+            if (cur.isEmpty()) {
+                gwDesField.setText(des);
+            }
+        }
+    }
+
+    private void saveConfig() {
+        try {
+            LamaoStationConfig station = new LamaoStationConfig();
+            station.setMesGw(required(gwField, "工位号"));
+            station.setMesGwDes(required(gwDesField, "工位名称"));
+            station.setMesLineSn(required(lineSnField, "产线编号"));
+            station.setMesServerIp(required(serverIpField, "服务器IP"));
+
+            LamaoGunConfig gunAConfig = buildGunConfig("A", gunA, "A枪");
+            LamaoGunConfig gunBConfig = buildGunConfig("B", gunB, "B枪");
+
+            ConfigUtil.saveToDb(station, gunAConfig, gunBConfig);
+            JOptionPane.showMessageDialog(MesClient.mesClientFrame,
+                    "配置已保存到本地数据库\n请重启客户端后生效",
+                    "提示窗口", JOptionPane.INFORMATION_MESSAGE);
+        } catch (IllegalArgumentException ex) {
+            JOptionPane.showMessageDialog(MesClient.mesClientFrame, ex.getMessage(), "提示窗口", JOptionPane.WARNING_MESSAGE);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            JOptionPane.showMessageDialog(MesClient.mesClientFrame, "保存失败:" + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
+        }
+    }
+
+    private LamaoGunConfig buildGunConfig(String gunCode, GunFields g, String title) {
+        LamaoGunConfig config = JdbcUtils.getGunConfig(gunCode);
+        if (config == null) {
+            config = new LamaoGunConfig();
+            config.setGunCode(gunCode);
+        }
+
+        String ip = required(g.ip, title + "设备地址");
+        short setNum = parseShort(g.setNum, title + "拉铆颗数");
+        if (setNum <= 0) {
+            throw new IllegalArgumentException(title + "拉铆颗数必须大于0");
+        }
+        short sMin = parseShort(g.sMin, title + "初始行程下限");
+        short sMax = parseShort(g.sMax, title + "初始行程上限");
+        short fMin = parseShort(g.fMin, title + "初始拉力下限");
+        short fMax = parseShort(g.fMax, title + "初始拉力上限");
+
+        boolean switchEnable = g.switchEnable.isSelected();
+        short switchFrom = 24;
+        short swSMin = sMin;
+        short swSMax = sMax;
+        short swFMin = fMin;
+        short swFMax = fMax;
+        if (switchEnable) {
+            switchFrom = parseShort(g.switchFrom, title + "第几颗开始切换");
+            if (switchFrom < 2) {
+                throw new IllegalArgumentException(title + "第几颗开始切换必须大于等于2(第1颗使用初始配方)");
+            }
+            if (switchFrom > setNum) {
+                throw new IllegalArgumentException(title + "第几颗开始切换不能大于拉铆颗数");
+            }
+            swSMin = parseShort(g.swSMin, title + "切换后行程下限");
+            swSMax = parseShort(g.swSMax, title + "切换后行程上限");
+            swFMin = parseShort(g.swFMin, title + "切换后拉力下限");
+            swFMax = parseShort(g.swFMax, title + "切换后拉力上限");
+        }
+
+        config.setIpAddress(ip);
+        config.setSetNum(setNum);
+        config.setSMin(sMin);
+        config.setSMax(sMax);
+        config.setFMin(fMin);
+        config.setFMax(fMax);
+        config.setSwitchEnable(switchEnable);
+        config.setSwitchFrom(switchFrom);
+        config.setSwitchSMin(swSMin);
+        config.setSwitchSMax(swSMax);
+        config.setSwitchFMin(swFMin);
+        config.setSwitchFMax(swFMax);
+        return config;
+    }
+
+    private String required(JTextField field, String name) {
+        String v = field.getText() == null ? "" : field.getText().trim();
+        if (v.isEmpty()) {
+            throw new IllegalArgumentException(name + "不能为空");
+        }
+        return v;
+    }
+
+    private short parseShort(JTextField field, String name) {
+        String v = required(field, name);
+        try {
+            int n = Integer.parseInt(v);
+            if (n < Short.MIN_VALUE || n > Short.MAX_VALUE) {
+                throw new NumberFormatException();
+            }
+            return (short) n;
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException(name + "必须是整数");
+        }
+    }
+
+    private static String nvl(String s) {
+        return s == null ? "" : s;
+    }
+
+    private static class GunFields {
+        final JTextField ip = new JTextField();
+        final JTextField setNum = new JTextField();
+        final JTextField sMin = new JTextField();
+        final JTextField sMax = new JTextField();
+        final JTextField fMin = new JTextField();
+        final JTextField fMax = new JTextField();
+        final JCheckBox switchEnable = new JCheckBox();
+        final JTextField switchFrom = new JTextField();
+        final JTextField swSMin = new JTextField();
+        final JTextField swSMax = new JTextField();
+        final JTextField swFMin = new JTextField();
+        final JTextField swFMax = new JTextField();
+        final JPanel switchPanel = new JPanel();
+
+        void setSwitchEnabled(boolean enabled) {
+            switchPanel.setVisible(enabled);
+            switchFrom.setEnabled(enabled);
+            swSMin.setEnabled(enabled);
+            swSMax.setEnabled(enabled);
+            swFMin.setEnabled(enabled);
+            swFMax.setEnabled(enabled);
+            switchPanel.revalidate();
+            switchPanel.repaint();
+        }
+    }
+}

+ 77 - 0
src/com/mes/ui/ConfigUtil.java

@@ -0,0 +1,77 @@
+package com.mes.ui;
+
+import com.mes.util.JdbcUtils;
+
+/**
+ * 拉铆工位参数配置,从 SQLite 读取/保存。
+ */
+public class ConfigUtil {
+
+    public static final String CONFIG_PASSWORD = "mes";
+
+    public static void loadFromDb() {
+        LamaoStationConfig station = JdbcUtils.getStationConfig();
+        LamaoGunConfig gunA = JdbcUtils.getGunConfig("A");
+        LamaoGunConfig gunB = JdbcUtils.getGunConfig("B");
+        apply(station, gunA, gunB);
+    }
+
+    public static void saveToDb(LamaoStationConfig station, LamaoGunConfig gunA, LamaoGunConfig gunB) {
+        JdbcUtils.saveStationConfig(station);
+        JdbcUtils.updateGunConfig(gunA);
+        JdbcUtils.updateGunConfig(gunB);
+    }
+
+    private static void apply(LamaoStationConfig station, LamaoGunConfig gunA, LamaoGunConfig gunB) {
+        MesClient.mes_gw = station.getMesGw();
+        MesClient.mes_line_sn = station.getMesLineSn();
+        MesClient.mes_server_ip = station.getMesServerIp();
+
+        String gwDes = station.getMesGwDes();
+        OprnoUtil.customGwDes = gwDes;
+        if (gwDes == null || gwDes.trim().isEmpty()) {
+            MesClient.mes_gw_des = OprnoUtil.getGwDes(MesClient.mes_line_sn, MesClient.mes_gw);
+        } else {
+            MesClient.mes_gw_des = gwDes.trim();
+        }
+
+        applyGun(gunA, true);
+        applyGun(gunB, false);
+
+        System.out.println(MesClient.mes_gw + ";" + MesClient.mes_gw_des + ";" + MesClient.mes_server_ip + ";"
+                + MesClient.mes_tcp_port + ";" + MesClient.mes_heart_beat_cycle);
+    }
+
+    private static void applyGun(LamaoGunConfig gun, boolean isA) {
+        if (gun == null) {
+            return;
+        }
+        if (isA) {
+            MesClient.plcAIp = gun.getIpAddress();
+            MesClient.aSetNum = gun.getSetNum();
+            MesClient.aSMin = gun.getSMin();
+            MesClient.aSMax = gun.getSMax();
+            MesClient.aFMin = gun.getFMin();
+            MesClient.aFMax = gun.getFMax();
+            MesClient.aSwitchEnable = gun.isSwitchEnable();
+            MesClient.aSwitchFrom = gun.getSwitchFrom();
+            MesClient.aSwitchSMin = gun.getSwitchSMin();
+            MesClient.aSwitchSMax = gun.getSwitchSMax();
+            MesClient.aSwitchFMin = gun.getSwitchFMin();
+            MesClient.aSwitchFMax = gun.getSwitchFMax();
+        } else {
+            MesClient.plcBIp = gun.getIpAddress();
+            MesClient.bSetNum = gun.getSetNum();
+            MesClient.bSMin = gun.getSMin();
+            MesClient.bSMax = gun.getSMax();
+            MesClient.bFMin = gun.getFMin();
+            MesClient.bFMax = gun.getFMax();
+            MesClient.bSwitchEnable = gun.isSwitchEnable();
+            MesClient.bSwitchFrom = gun.getSwitchFrom();
+            MesClient.bSwitchSMin = gun.getSwitchSMin();
+            MesClient.bSwitchSMax = gun.getSwitchSMax();
+            MesClient.bSwitchFMin = gun.getSwitchFMin();
+            MesClient.bSwitchFMax = gun.getSwitchFMax();
+        }
+    }
+}

+ 14 - 40
src/com/mes/ui/DataUtil.java

@@ -9,7 +9,6 @@ import java.io.*;
 import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.Properties;
 
 public class DataUtil {
 
@@ -126,16 +125,11 @@ public class DataUtil {
 
     public static Boolean sendMessage(NettyClient nettyClient,String msgType,String craft,String lx,String sn,String result,String user,String paramNums,String params){
         try{
-            String enconding = "UTF-8";
-            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
-            Properties pro = new Properties();
-            BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
-            pro.load(br);
-            String gw = "GW"+rightPad(pro.getProperty("mes.gw"), 6);
+            String gw = "GW"+rightPad(MesClient.mes_gw, 6);
             String start = "aaaabbbbbABW";
             String gy = "GY" + rightPad(craft, 6);
             String reslx = "LX" + rightPad(lx, 2);
-            String id = pro.getProperty("mes.line_sn") + rightPad(sn, 36);
+            String id = MesClient.mes_line_sn + rightPad(sn, 36);
             String rs = "RS"+ rightPad(result, 2);
             String da = "DA" + DateLocalUtils.getCurrentDate();
             String zt = "ZT" + DateLocalUtils.getCurrentTimeHMS();
@@ -164,14 +158,9 @@ public class DataUtil {
 
     public static JSONObject getBindMaterail() {
         try{
-            String enconding = "UTF-8";
-            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
-            Properties pro = new Properties();
-            BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
-            pro.load(br);
-            String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
-            String lineSn = pro.getProperty("mes.line_sn").trim();
+            String mes_server_ip = MesClient.mes_server_ip;
+            String oprno = MesClient.mes_gw.trim();
+            String lineSn = MesClient.mes_line_sn.trim();
             String url = "http://"+mes_server_ip+":8980/js/a/mes/mesLineProcessMaterial/materials";
             String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn;
             System.out.println("params="+params);
@@ -190,14 +179,9 @@ public class DataUtil {
 
     public static JSONObject saveBindMaterail(String batchSn,String craft,String materialId,String type) {
         try{
-            String enconding = "UTF-8";
-            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
-            Properties pro = new Properties();
-            BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
-            pro.load(br);
-            String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
-            String lineSn = pro.getProperty("mes.line_sn").trim();
+            String mes_server_ip = MesClient.mes_server_ip;
+            String oprno = MesClient.mes_gw.trim();
+            String lineSn = MesClient.mes_line_sn.trim();
             String url = "http://"+mes_server_ip+":8980/js/a/mes/mesMaterialPrebind/bind";
             String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&batchSn="+batchSn+"&craft="+craft+"&materialId="+materialId+"&type="+type;
             System.out.println("params="+params);
@@ -295,14 +279,9 @@ public class DataUtil {
 
     public static JSONObject addNgData(String sn,String pos) {
         try{
-            String enconding = "UTF-8";
-            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
-            Properties pro = new Properties();
-            BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
-            pro.load(br);
-            String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
-            String lineSn = pro.getProperty("mes.line_sn").trim();
+            String mes_server_ip = MesClient.mes_server_ip;
+            String oprno = MesClient.mes_gw.trim();
+            String lineSn = MesClient.mes_line_sn.trim();
             String url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductNg/addData";
             String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&sn="+sn+"&pos="+pos;
             System.out.println("url="+url);
@@ -322,14 +301,9 @@ public class DataUtil {
 
     public static JSONObject checkNgData(String sn,String pos) {
         try{
-            String enconding = "UTF-8";
-            InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
-            Properties pro = new Properties();
-            BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
-            pro.load(br);
-            String mes_server_ip = pro.getProperty("mes.server_ip");
-            String oprno = pro.getProperty("mes.gw").trim();
-            String lineSn = pro.getProperty("mes.line_sn").trim();
+            String mes_server_ip = MesClient.mes_server_ip;
+            String oprno = MesClient.mes_gw.trim();
+            String lineSn = MesClient.mes_line_sn.trim();
             String url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductNg/ngcheck";
             String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&sn="+sn+"&pos="+pos;
             System.out.println("url="+url);

+ 177 - 0
src/com/mes/ui/FirstSetupDialog.java

@@ -0,0 +1,177 @@
+package com.mes.ui;
+
+import com.mes.util.JdbcUtils;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+/**
+ * 首次启动时设置服务器IP、工位号、工位名称。
+ */
+public class FirstSetupDialog extends JDialog {
+
+    private final JTextField gwField = new JTextField();
+    private final JTextField gwDesField = new JTextField();
+    private final JTextField serverIpField = new JTextField();
+    private boolean saved = false;
+
+    public FirstSetupDialog(Frame owner) {
+        super(owner, "首次使用 - 基本参数设置", true);
+        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+        setResizable(false);
+
+        JPanel panel = new JPanel(new GridBagLayout());
+        GridBagConstraints c = new GridBagConstraints();
+        c.insets = new Insets(8, 12, 8, 12);
+        c.fill = GridBagConstraints.HORIZONTAL;
+
+        JLabel tip = new JLabel("首次启动,请先设置以下参数(后续可在「参数配置」中修改)", SwingConstants.LEFT);
+        tip.setFont(new Font("微软雅黑", Font.PLAIN, 14));
+        tip.setForeground(Color.DARK_GRAY);
+        c.gridx = 0;
+        c.gridy = 0;
+        c.gridwidth = 2;
+        panel.add(tip, c);
+
+        c.gridwidth = 1;
+        c.gridy = 1;
+        c.gridx = 0;
+        c.weightx = 0;
+        JLabel gwLabel = new JLabel("工位号");
+        gwLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        panel.add(gwLabel, c);
+        c.gridx = 1;
+        c.weightx = 1;
+        gwField.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        gwField.setColumns(18);
+        panel.add(gwField, c);
+
+        c.gridy = 2;
+        c.gridx = 0;
+        c.weightx = 0;
+        JLabel gwDesLabel = new JLabel("工位名称");
+        gwDesLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        panel.add(gwDesLabel, c);
+        c.gridx = 1;
+        c.weightx = 1;
+        gwDesField.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        panel.add(gwDesField, c);
+
+        c.gridy = 3;
+        c.gridx = 0;
+        c.weightx = 0;
+        JLabel ipLabel = new JLabel("服务器IP");
+        ipLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        panel.add(ipLabel, c);
+        c.gridx = 1;
+        c.weightx = 1;
+        serverIpField.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        panel.add(serverIpField, c);
+
+        LamaoStationConfig station = JdbcUtils.getStationConfig();
+        gwField.setText(nvl(station.getMesGw()));
+        gwDesField.setText(nvl(station.getMesGwDes()));
+        serverIpField.setText(nvl(station.getMesServerIp()));
+
+        JButton okBtn = new JButton("保存并继续");
+        okBtn.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        okBtn.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                if (save()) {
+                    saved = true;
+                    dispose();
+                }
+            }
+        });
+
+        JButton cancelBtn = new JButton("退出");
+        cancelBtn.setFont(new Font("微软雅黑", Font.PLAIN, 16));
+        cancelBtn.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                saved = false;
+                dispose();
+            }
+        });
+
+        JPanel btnPanel = new JPanel();
+        btnPanel.add(okBtn);
+        btnPanel.add(cancelBtn);
+
+        getContentPane().setLayout(new BorderLayout());
+        getContentPane().add(panel, BorderLayout.CENTER);
+        getContentPane().add(btnPanel, BorderLayout.SOUTH);
+
+        addWindowListener(new WindowAdapter() {
+            public void windowClosing(WindowEvent e) {
+                saved = false;
+                dispose();
+            }
+        });
+
+        pack();
+        setLocationRelativeTo(owner);
+    }
+
+    private boolean save() {
+        String gw = gwField.getText() == null ? "" : gwField.getText().trim();
+        String gwDes = gwDesField.getText() == null ? "" : gwDesField.getText().trim();
+        String serverIp = serverIpField.getText() == null ? "" : serverIpField.getText().trim();
+        if (gw.isEmpty()) {
+            JOptionPane.showMessageDialog(this, "工位号不能为空", "提示窗口", JOptionPane.WARNING_MESSAGE);
+            return false;
+        }
+        if (gwDes.isEmpty()) {
+            JOptionPane.showMessageDialog(this, "工位名称不能为空", "提示窗口", JOptionPane.WARNING_MESSAGE);
+            return false;
+        }
+        if (serverIp.isEmpty()) {
+            JOptionPane.showMessageDialog(this, "服务器IP不能为空", "提示窗口", JOptionPane.WARNING_MESSAGE);
+            return false;
+        }
+
+        LamaoStationConfig station = JdbcUtils.getStationConfig();
+        station.setMesGw(gw);
+        station.setMesGwDes(gwDes);
+        station.setMesServerIp(serverIp);
+        if (station.getMesLineSn() == null || station.getMesLineSn().trim().isEmpty()) {
+            station.setMesLineSn("XT");
+        }
+        if (!JdbcUtils.saveStationConfig(station) || !JdbcUtils.markStationSetupDone()) {
+            JOptionPane.showMessageDialog(this, "保存失败,请重试", "错误", JOptionPane.ERROR_MESSAGE);
+            return false;
+        }
+        return true;
+    }
+
+    private static String nvl(String s) {
+        return s == null ? "" : s;
+    }
+
+    /**
+     * @return true 已保存;false 用户取消/退出
+     */
+    public static boolean showIfNeeded() {
+        if (!JdbcUtils.needsFirstSetup()) {
+            return true;
+        }
+        FirstSetupDialog dialog = new FirstSetupDialog(null);
+        dialog.setVisible(true);
+        return dialog.saved;
+    }
+}

+ 130 - 0
src/com/mes/ui/LamaoGunConfig.java

@@ -0,0 +1,130 @@
+package com.mes.ui;
+
+public class LamaoGunConfig {
+    private int id;
+    private String gunCode;
+    private String ipAddress;
+    private short setNum;
+    private short sMin;
+    private short sMax;
+    private short fMin;
+    private short fMax;
+    private boolean switchEnable;
+    private short switchFrom;
+    private short switchSMin;
+    private short switchSMax;
+    private short switchFMin;
+    private short switchFMax;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getGunCode() {
+        return gunCode;
+    }
+
+    public void setGunCode(String gunCode) {
+        this.gunCode = gunCode;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    public short getSetNum() {
+        return setNum;
+    }
+
+    public void setSetNum(short setNum) {
+        this.setNum = setNum;
+    }
+
+    public short getSMin() {
+        return sMin;
+    }
+
+    public void setSMin(short sMin) {
+        this.sMin = sMin;
+    }
+
+    public short getSMax() {
+        return sMax;
+    }
+
+    public void setSMax(short sMax) {
+        this.sMax = sMax;
+    }
+
+    public short getFMin() {
+        return fMin;
+    }
+
+    public void setFMin(short fMin) {
+        this.fMin = fMin;
+    }
+
+    public short getFMax() {
+        return fMax;
+    }
+
+    public void setFMax(short fMax) {
+        this.fMax = fMax;
+    }
+
+    public boolean isSwitchEnable() {
+        return switchEnable;
+    }
+
+    public void setSwitchEnable(boolean switchEnable) {
+        this.switchEnable = switchEnable;
+    }
+
+    public short getSwitchFrom() {
+        return switchFrom;
+    }
+
+    public void setSwitchFrom(short switchFrom) {
+        this.switchFrom = switchFrom;
+    }
+
+    public short getSwitchSMin() {
+        return switchSMin;
+    }
+
+    public void setSwitchSMin(short switchSMin) {
+        this.switchSMin = switchSMin;
+    }
+
+    public short getSwitchSMax() {
+        return switchSMax;
+    }
+
+    public void setSwitchSMax(short switchSMax) {
+        this.switchSMax = switchSMax;
+    }
+
+    public short getSwitchFMin() {
+        return switchFMin;
+    }
+
+    public void setSwitchFMin(short switchFMin) {
+        this.switchFMin = switchFMin;
+    }
+
+    public short getSwitchFMax() {
+        return switchFMax;
+    }
+
+    public void setSwitchFMax(short switchFMax) {
+        this.switchFMax = switchFMax;
+    }
+}

+ 49 - 0
src/com/mes/ui/LamaoStationConfig.java

@@ -0,0 +1,49 @@
+package com.mes.ui;
+
+public class LamaoStationConfig {
+    private int id = 1;
+    private String mesGw = "";
+    private String mesGwDes = "";
+    private String mesLineSn = "XT";
+    private String mesServerIp = "";
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getMesGw() {
+        return mesGw;
+    }
+
+    public void setMesGw(String mesGw) {
+        this.mesGw = mesGw;
+    }
+
+    public String getMesGwDes() {
+        return mesGwDes;
+    }
+
+    public void setMesGwDes(String mesGwDes) {
+        this.mesGwDes = mesGwDes;
+    }
+
+    public String getMesLineSn() {
+        return mesLineSn;
+    }
+
+    public void setMesLineSn(String mesLineSn) {
+        this.mesLineSn = mesLineSn;
+    }
+
+    public String getMesServerIp() {
+        return mesServerIp;
+    }
+
+    public void setMesServerIp(String mesServerIp) {
+        this.mesServerIp = mesServerIp;
+    }
+}

+ 101 - 34
src/com/mes/ui/MesClient.java

@@ -53,6 +53,10 @@ public class MesClient extends JFrame {
     public static JPanel contentPane;
     public static MesClient mesClientFrame;
     public static JTabbedPane tabbedPane;
+    public static int configTabIndex = -1;
+    private ConfigPanel configPanel;
+    private int lastNonConfigTabIndex = 0;
+    private boolean configTabReverting = false;
     public static JScrollPane indexScrollPaneA;
     public static JScrollPane searchScrollPane;
     public static JScrollPane searchScrollPaneDj;
@@ -86,15 +90,10 @@ public class MesClient extends JFrame {
     public static JTextField param3;
     public static JTextField param4;
 
-
-
-//    tw -210b
-//    public static ModbusTcp plcA = new ModbusTcp(1, "192.168.1.7");//81
-//    public static ModbusTcp plcB = new ModbusTcp(1, "192.168.1.8");//1
-
-//    tw-op130b
-    public static ModbusTcp plcA = new ModbusTcp(1, "192.168.1.7");//29
-    public static ModbusTcp plcB = new ModbusTcp(1, "192.168.1.8");//26
+    public static ModbusTcp plcA;
+    public static ModbusTcp plcB;
+    public static String plcAIp = "192.168.1.7";
+    public static String plcBIp = "192.168.1.8";
 
     public static Timer cjTimer;
 
@@ -102,15 +101,32 @@ public class MesClient extends JFrame {
 
     public static Timer cjTimer3;
 
-    public static Short aSetNum = 29;
-//public static Short aSetNum = 81;
-
+    public static Short aSetNum = 26;
+    public static short aSMin = 3200;
+    public static short aSMax = 4200;
+    public static short aFMin = 10500;
+    public static short aFMax = 11500;
+    public static boolean aSwitchEnable = false;
+    public static short aSwitchFrom = 24;
+    public static short aSwitchSMin = 4000;
+    public static short aSwitchSMax = 5000;
+    public static short aSwitchFMin = 10500;
+    public static short aSwitchFMax = 11500;
     public static Short sortA = 0;
     public static Short aMax = 0;
     public static Short aFinish = 0;
     public static List<Map> alist = new ArrayList<>();
-    public static Short bSetNum = 26;
-//public static Short bSetNum = 1;
+    public static Short bSetNum = 28;
+    public static short bSMin = 3500;
+    public static short bSMax = 4900;
+    public static short bFMin = 10500;
+    public static short bFMax = 11500;
+    public static boolean bSwitchEnable = true;
+    public static short bSwitchFrom = 27;
+    public static short bSwitchSMin = 3000;
+    public static short bSwitchSMax = 4500;
+    public static short bSwitchFMin = 10500;
+    public static short bSwitchFMax = 11500;
     public static Short sortB = 0;
     public static Short bMax = 0;
     public static Short bFinish = 0;
@@ -154,15 +170,22 @@ public class MesClient extends JFrame {
             @Override
             public void run() {
                 try{
-                    //读文件配置
+                    //读基础配置(仅TCP等固定参数,业务配置从数据库读取)
                     readProperty();
 
+                    JdbcUtils.getConn();
+                    // 首次启动:先设置服务器IP、工位号、工位名称
+                    if (!FirstSetupDialog.showIfNeeded()) {
+                        System.exit(0);
+                        return;
+                    }
+                    ConfigUtil.loadFromDb();
+                    initPlc();
+
                     // 显示界面
                     mesClientFrame = new MesClient();
                     mesClientFrame.setVisible(false);
 
-                    JdbcUtils.getConn();
-
                     welcomeWin = new LoginFarme();
                     welcomeWin.setVisible(true);
 
@@ -193,7 +216,9 @@ public class MesClient extends JFrame {
                     if(work_status == 1){
                         List<Boolean> yxstatus = plcA.readCoil(3128,1);
                         if(yxstatus.size() >= 1 && !yxstatus.get(0)){
-                            if(!MesClient.curSn.isEmpty() && MesClient.aMax > 0 && MesClient.aMax == MesClient.sortA){
+                            if(MesClient.zdStatusA == 1){
+                                // NG复判中断中,保持锁枪
+                            }else if(!MesClient.curSn.isEmpty() && MesClient.aMax > 0 && MesClient.aMax == MesClient.sortA){
                                 ModbusUtil.setPowerOff(plcA);
                             }else{
                                 ModbusUtil.setPowerOn(plcA);
@@ -202,7 +227,9 @@ public class MesClient extends JFrame {
 
                         List<Boolean> yxstatusb = plcB.readCoil(3128,1);
                         if(yxstatusb.size() >= 1 && !yxstatusb.get(0)){
-                            if(!MesClient.curSn.isEmpty() && MesClient.bMax > 0 && MesClient.bMax == MesClient.sortB){
+                            if(MesClient.zdStatusB == 1){
+                                // NG复判中断中,保持锁枪
+                            }else if(!MesClient.curSn.isEmpty() && MesClient.bMax > 0 && MesClient.bMax == MesClient.sortB){
                                 ModbusUtil.setPowerOff(plcB);
                             }else{
                                 ModbusUtil.setPowerOn(plcB);
@@ -226,24 +253,22 @@ public class MesClient extends JFrame {
         }, 1000,1000);
     }
 
-    //读配置文件
+    //读配置文件(仅TCP等固定参数,业务配置从数据库读取)
     private static void readProperty() throws IOException{
         String enconding = "UTF-8";
         InputStream is = ClassLoader.getSystemResourceAsStream("config/config.properties");
         Properties pro = new Properties();
         BufferedReader br = new BufferedReader(new InputStreamReader(is, enconding));
         pro.load(br);
-        mes_gw =  pro.getProperty("mes.gw");
-
-//        mes_gw_des = pro.getProperty("mes.gw_des");
-        mes_server_ip = pro.getProperty("mes.server_ip");
         mes_tcp_port = Integer.parseInt(pro.getProperty("mes.tcp_port"));
         mes_heart_beat_cycle = Integer.parseInt(pro.getProperty("mes.heart_beat_cycle"));
-        mes_line_sn = pro.getProperty("mes.line_sn");
-
-        mes_gw_des = OprnoUtil.getGwDes(mes_line_sn,mes_gw);
+    }
 
-        System.out.println(mes_gw + ";" + mes_gw_des + ";" + mes_server_ip + ";" + mes_tcp_port + ";" + mes_heart_beat_cycle);
+    public static void initPlc() {
+        plcA = new ModbusTcp(1, plcAIp);
+        plcB = new ModbusTcp(1, plcBIp);
+        ModbusUtil.applyTimeout(plcA);
+        ModbusUtil.applyTimeout(plcB);
     }
 
     public static void getPlcParam() {
@@ -471,8 +496,8 @@ public class MesClient extends JFrame {
         ModbusUtil.setPowerOff(MesClient.plcA); // 远程关机
         ModbusUtil.setPowerOff(MesClient.plcB); // 远程关机
 
-        ModbusUtil.setTask(MesClient.plcA,MesClient.aSetNum);
-        ModbusUtil.setTask(MesClient.plcB,MesClient.bSetNum);
+        ModbusUtil.setTask(MesClient.plcA, MesClient.aSetNum, MesClient.aSMin, MesClient.aSMax, MesClient.aFMin, MesClient.aFMax);
+        ModbusUtil.setTask(MesClient.plcB, MesClient.bSetNum, MesClient.bSMin, MesClient.bSMax, MesClient.bFMin, MesClient.bFMax);
 
         updateMaterailData();
     }
@@ -631,6 +656,20 @@ public class MesClient extends JFrame {
         });
         settingMenu.add(resetTcpMenu_1);
 
+        JMenuItem configMenu = new JMenuItem("参数配置");
+        configMenu.setIcon(new ImageIcon(MesClient.class.getResource("/bg/menu_setting.png")));
+        configMenu.setFont(new Font("微软雅黑", Font.PLAIN, 20));
+        configMenu.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mousePressed(MouseEvent e) {
+                super.mouseClicked(e);
+                if(configTabIndex >= 0){
+                    tabbedPane.setSelectedIndex(configTabIndex);
+                }
+            }
+        });
+        settingMenu.add(configMenu);
+
         contentPane = new JPanel();
         contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
         setContentPane(contentPane);
@@ -1085,21 +1124,49 @@ public class MesClient extends JFrame {
 
 		tabbedPane.addTab("工作记录", new ImageIcon(MesClient.class.getResource("/bg/menu_data_preprocess.png")), searchScrollPane, null);
 
+        configPanel = new ConfigPanel();
+        JScrollPane configScrollPane = new JScrollPane(configPanel);
+        tabbedPane.addTab("参数配置", new ImageIcon(MesClient.class.getResource("/bg/menu_setting.png")), configScrollPane, null);
+        configTabIndex = tabbedPane.getTabCount() - 1;
 
 		tabbedPane.addChangeListener(new ChangeListener() {
             @Override
             public void stateChanged(ChangeEvent e) {
-                JTabbedPane tabbedPane = (JTabbedPane) e.getSource();
-                int selectedIndex = tabbedPane.getSelectedIndex();
+                JTabbedPane pane = (JTabbedPane) e.getSource();
+                int selectedIndex = pane.getSelectedIndex();
                 System.out.println("selectedIndex:"+selectedIndex);
 
-                if(selectedIndex == 1){
-
+                if(configTabReverting){
+                    return;
+                }
+                if(selectedIndex == configTabIndex){
+                    if(!verifyConfigPassword()){
+                        configTabReverting = true;
+                        pane.setSelectedIndex(lastNonConfigTabIndex);
+                        configTabReverting = false;
+                        return;
+                    }
+                    configPanel.reloadFromMemory();
+                }else{
+                    lastNonConfigTabIndex = selectedIndex;
                 }
             }
         });
     }
 
+    private boolean verifyConfigPassword() {
+        JPasswordField pf = new JPasswordField();
+        int ok = JOptionPane.showConfirmDialog(this, pf, "请输入配置密码", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
+        if(ok != JOptionPane.OK_OPTION){
+            return false;
+        }
+        if(ConfigUtil.CONFIG_PASSWORD.equals(new String(pf.getPassword()).trim())){
+            return true;
+        }
+        JOptionPane.showMessageDialog(this, "密码错误,无法进入参数配置页面", "提示窗口", JOptionPane.WARNING_MESSAGE);
+        return false;
+    }
+
     public static void setMenuStatus(String msg,int error){
         if(error == 0){
             MesClient.status_menu.setForeground(Color.GREEN);

+ 2 - 2
src/com/mes/ui/MesRevice.java

@@ -56,8 +56,8 @@ public class MesRevice {
                 ModbusUtil.setPowerOn(MesClient.plcA); // 远程开机
                 ModbusUtil.setPowerOn(MesClient.plcB); // 远程开机
 
-                ModbusUtil.setTask(MesClient.plcA,MesClient.aSetNum);
-                ModbusUtil.setTask(MesClient.plcB,MesClient.bSetNum);
+                ModbusUtil.setTask(MesClient.plcA, MesClient.aSetNum, MesClient.aSMin, MesClient.aSMax, MesClient.aFMin, MesClient.aFMax);
+                ModbusUtil.setTask(MesClient.plcB, MesClient.bSetNum, MesClient.bSMin, MesClient.bSMax, MesClient.bFMin, MesClient.bFMax);
             }
         }catch (Exception e){
             e.printStackTrace();

+ 91 - 78
src/com/mes/ui/ModbusUtil.java

@@ -4,11 +4,47 @@ import com.github.xingshuangs.iot.protocol.modbus.service.ModbusTcp;
 import com.mes.util.JdbcUtils;
 
 import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 public class ModbusUtil {
 
-    public static void getDataA(ModbusTcp plc){
+    public static final int PLC_TIMEOUT_MS = 5000;
+    private static final Map<ModbusTcp, Long> failUntil = new ConcurrentHashMap<ModbusTcp, Long>();
+
+    public static void applyTimeout(ModbusTcp plc) {
+        if (plc == null) {
+            return;
+        }
+        plc.setConnectTimeout(PLC_TIMEOUT_MS);
+        plc.setReceiveTimeout(PLC_TIMEOUT_MS);
+    }
 
+    private static boolean isUnavailable(ModbusTcp plc) {
+        if (plc == null) {
+            return true;
+        }
+        Long until = failUntil.get(plc);
+        return until != null && System.currentTimeMillis() < until;
+    }
+
+    private static void markOk(ModbusTcp plc) {
+        failUntil.remove(plc);
+    }
+
+    private static void markFail(ModbusTcp plc) {
+        failUntil.put(plc, System.currentTimeMillis() + PLC_TIMEOUT_MS);
+        try {
+            plc.close();
+        } catch (Exception ignore) {
+        }
+    }
+
+    public static void getDataA(ModbusTcp plc){
+        if (isUnavailable(plc)) {
+            return;
+        }
+        try {
         // 说明预设数量有变化不能修改
         // 打钉数应按实际监听数算
 
@@ -17,14 +53,6 @@ public class ModbusUtil {
         // 预设数量=41129  完成数=41137
 
         Short cur = plc.readInt16(1136);
-//        System.out.println("F-out:"+plc.readInt16(1064));
-//        System.out.println("S-out:"+plc.readInt16(1065));
-//        System.out.println("F-min:"+plc.readInt16(1068));
-//        System.out.println("S-min:"+plc.readInt16(1070));
-//        System.out.println("F-max:"+plc.readInt16(1069));
-//        System.out.println("S-max:"+plc.readInt16(1071));
-//        System.out.println("预设数量:"+plc.readInt16(1128));
-        //System.out.println("当前数量:"+cur);
         if(MesClient.aMax <= 0){
             MesClient.aMax = plc.readInt16(1128); // 任务数量
             MesClient.param1.setText(String.valueOf(MesClient.aMax));
@@ -45,19 +73,10 @@ public class ModbusUtil {
             MesClient.param2.setText(cur+"");
             System.out.println("cur:"+cur);
 
-
-//            op130
-            if(MesClient.sortA == 23){
-                plc.writeInt16(1070,(short) 4000);
-                plc.writeInt16(1071,(short) 5000);
+            if(MesClient.aSwitchEnable && MesClient.sortA == MesClient.aSwitchFrom - 1){
+                writeRecipe(plc, MesClient.aSwitchSMin, MesClient.aSwitchSMax, MesClient.aSwitchFMin, MesClient.aSwitchFMax);
             }
 
-            //210
-//            if(MesClient.sortA == 75){
-//                plc.writeInt16(1070,(short) 2500);
-//                plc.writeInt16(1071,(short) 3500);
-//            }
-
             if(!MesClient.product_sn.getText().isEmpty()){
                 String qty = "1";
                 if(Integer.valueOf(fout) < Integer.valueOf(fmin) || Integer.valueOf(fout) > Integer.valueOf(fmax)){
@@ -91,24 +110,23 @@ public class ModbusUtil {
         if(MesClient.zdStatusA == 0 && MesClient.zdStatusB == 0){
             upResult();
         }
+            markOk(plc);
+        } catch (Exception e) {
+            markFail(plc);
+            e.printStackTrace();
+        }
     }
 
     public static void getDataB(ModbusTcp plc){
-
+        if (isUnavailable(plc)) {
+            return;
+        }
+        try {
         // 41065=F-out  41066=S-out
         // 41069=F-min  41071=S-min 41070=F-max  41072=S-max
         // 预设数量=41129  完成数=41137
 
         Short cur = plc.readInt16(1136);
-//        System.out.println("F-out:"+plc.readInt16(1064));
-//        System.out.println("S-out:"+plc.readInt16(1065));
-//        System.out.println("F-min:"+plc.readInt16(1068));
-//        System.out.println("S-min:"+plc.readInt16(1070));
-//        System.out.println("F-max:"+plc.readInt16(1069));
-//        System.out.println("S-max:"+plc.readInt16(1071));
-//        System.out.println("set:"+plc.readInt16(1128));
-//        System.out.println("cur:"+cur);
-//        System.out.println("cur2:"+MesClient.sortB);
 
         if(MesClient.bMax <= 0){
             MesClient.bMax = plc.readInt16(1128);
@@ -127,10 +145,14 @@ public class ModbusUtil {
             String fmax = plc.readInt16(1069)+"";
             String smax = (float)plc.readInt16(1071)/1000+"";
 
+            if(MesClient.bSwitchEnable && MesClient.sortB == MesClient.bSwitchFrom - 1){
+                writeRecipe(plc, MesClient.bSwitchSMin, MesClient.bSwitchSMax, MesClient.bSwitchFMin, MesClient.bSwitchFMax);
+            }
 
             MesClient.param4.setText(cur+"");
 
             System.out.println("cur:"+cur);
+
             if(!MesClient.product_sn.getText().isEmpty()){
                 String qty = "1";
                 if(Integer.valueOf(fout) < Integer.valueOf(fmin) || Integer.valueOf(fout) > Integer.valueOf(fmax)){
@@ -164,7 +186,11 @@ public class ModbusUtil {
         if(MesClient.zdStatusA == 0 && MesClient.zdStatusB == 0){
             upResult();
         }
-
+            markOk(plc);
+        } catch (Exception e) {
+            markFail(plc);
+            e.printStackTrace();
+        }
     }
 
     // 上传总结果
@@ -198,9 +224,14 @@ public class ModbusUtil {
     // 获取控制模式
     public static short getControlModel(ModbusTcp plc){
         short control = 0;
+        if (isUnavailable(plc)) {
+            return control;
+        }
         try{
             control = plc.readInt16(1090);
+            markOk(plc);
         }catch (Exception e){
+            markFail(plc);
             e.printStackTrace();
         }
 
@@ -210,9 +241,14 @@ public class ModbusUtil {
     // 获取二维码
     public static String getSn(ModbusTcp plc){
         String sn = "";
+        if (isUnavailable(plc)) {
+            return sn;
+        }
         try{
             sn = plc.readString(1216,40, Charset.forName("UTF8"));
+            markOk(plc);
         }catch (Exception e){
+            markFail(plc);
             e.printStackTrace();
         }
 
@@ -243,12 +279,15 @@ public class ModbusUtil {
     // 远程开机
     public static Boolean setPowerOn(ModbusTcp plc){
         Boolean ret = false;
+        if (isUnavailable(plc)) {
+            return ret;
+        }
         try{
             plc.writeCoil(3128,true);
-//            plc.writeCoil(3079,false);
-//            plc.writeCoil(3328,true); // 必须选关掉关机,开机才起左右
+            markOk(plc);
             ret = true;
         }catch (Exception e){
+            markFail(plc);
             e.printStackTrace();
             ret = false;
         }
@@ -259,13 +298,15 @@ public class ModbusUtil {
     // 远程关机
     public static Boolean setPowerOff(ModbusTcp plc){
         Boolean ret = false;
+        if (isUnavailable(plc)) {
+            return ret;
+        }
         try{
             plc.writeCoil(3128,false);
-//            plc.writeCoil(3328,false);
-//            plc.writeCoil(3079,true); // 关机
-            // 必须选关掉关机,开机才起左右
+            markOk(plc);
             ret = true;
         }catch (Exception e){
+            markFail(plc);
             e.printStackTrace();
             ret = false;
         }
@@ -273,8 +314,11 @@ public class ModbusUtil {
         return ret;
     }
 
-    // 重置任务
-    public static void setTask(ModbusTcp plc,Short setNum){
+    // 重置任务,写入颗数和初始行程/拉力
+    public static void setTask(ModbusTcp plc, Short setNum, short sMin, short sMax, short fMin, short fMax){
+        if (isUnavailable(plc)) {
+            return;
+        }
         try{
             // 设置模式 1=标记铆接模式
             plc.writeInt16(1092,(short) 1);
@@ -282,50 +326,19 @@ public class ModbusUtil {
             plc.writeInt16(1128,setNum);
             plc.writeInt16(1136,(short) 0);
             plc.writeInt16(1138,(short) 0);
-
-//            if(setNum == 81){
-//                plc.writeInt16(1070,(short) 3000);
-//                plc.writeInt16(1071,(short) 4000);
-//            }
-
-
-//            op130
-            if(setNum == 29){
-                plc.writeInt16(1070,(short) 3200);
-                plc.writeInt16(1071,(short) 4200);
-            }
-
-//            op130
-            if(setNum == 26){
-                plc.writeInt16(1070,(short) 3200);
-                plc.writeInt16(1071,(short) 4200);
-            }
-
+            writeRecipe(plc, sMin, sMax, fMin, fMax);
+            markOk(plc);
         }catch (Exception e){
+            markFail(plc);
             e.printStackTrace();
         }
     }
 
+    private static void writeRecipe(ModbusTcp plc, short sMin, short sMax, short fMin, short fMax){
+        plc.writeInt16(1070, sMin);
+        plc.writeInt16(1071, sMax);
+        plc.writeInt16(1068, fMin);
+        plc.writeInt16(1069, fMax);
+    }
 
-//        A枪说明 192.168.1.7
-//        plc.writeCoil(3079,false);
-//        plc.writeCoil(3328,true); // 必须选关掉关机,开机才起左右
-////        plc.writeCoil(3128,false);
-//        System.out.println("控制模式:"+plc.readInt16(1090)); // 1091 控制模式
-//        System.out.println("系统运行中:"+plc.readCoil(3128,1)); // 3129 系统运行中
-//        System.out.println("结束暂停:"+plc.readCoil(3132,1)); // 3133 系统运行中
-//        System.out.println("远程开机:"+plc.readCoil(3328,1)); // 3329 远程开机
-//        System.out.println("远程关机:"+plc.readCoil(3079,1)); // 3080 远程关机
-//        System.out.println("作业模式:"+plc.readInt16(1092)); // 1093 作业模式
-//        System.out.println("最大拉力:"+plc.readInt16(1064)); // 1065 最大拉力
-//        System.out.println("对应位移:"+plc.readInt16(1065)); // 1066 对应位移
-//        System.out.println("任务数量:"+plc.readInt16(1128)); // 1129 任务数量
-//        System.out.println("合格数量:"+plc.readInt16(1138)); // 1139 合格数量
-//        System.out.println("质量状态:"+plc.readInt16(1072)); // 1073 质量状态
-//        System.out.println("F-out:"+plc.readInt16(1064));
-//        System.out.println("S-out:"+plc.readInt16(1065));
-//        System.out.println("F-min:"+plc.readInt16(1068));
-//        System.out.println("S-min:"+plc.readInt16(1070));
-//        System.out.println("F-max:"+plc.readInt16(1069));
-//        System.out.println("S-max:"+plc.readInt16(1071));
 }

+ 10 - 2
src/com/mes/ui/OprnoUtil.java

@@ -5,13 +5,14 @@ import java.util.List;
 import java.util.Map;
 
 public class OprnoUtil {
+    public static String customGwDes = "";
 
     public static String[] xtoprnos = new String[]{
 
-            "OP210","OP130"
+            "OP210","OP130","OP230","OP310"
     };
     public static String[] xtoprnodes = new String[]{
-            "总成反面装配1","液冷板拉铆"
+            "总成反面装配1","液冷板拉铆","正面拉铆","反面拉铆"
     };
     public static String[] lboprnos = new String[]{
             "OP040","OP050","OP060","OP070","OP080","OP090","OP100","OP110",
@@ -24,6 +25,13 @@ public class OprnoUtil {
             "M5+M6钢丝牙套安装","冷板汽检","冷板氦检"
     };
     public static String getGwDes(String lineSn,String oprno){
+        if(customGwDes != null && !customGwDes.trim().isEmpty()){
+            return customGwDes.trim();
+        }
+        return lookupGwDes(lineSn, oprno);
+    }
+
+    public static String lookupGwDes(String lineSn,String oprno){
         String des = "";
         oprno = formatOprno(oprno);
         if(lineSn.equals("XT")){

+ 278 - 0
src/com/mes/util/JdbcUtils.java

@@ -13,11 +13,15 @@ public class JdbcUtils {
     
     public static Connection getConn(){
         try {
+            if (conn != null && !conn.isClosed()) {
+                return conn;
+            }
             Class.forName(Drivde);// 加载驱动,连接sqlite的jdbc
             conn = DriverManager.getConnection("jdbc:sqlite:mes_db.db");//连接数据库zhou.db,不存在则创建
             System.out.println("连接到SQLite数据库成功!");
             create_bw_record();//初始化结构表
             create_bw_prod();
+            create_lamao_config();//初始化拉铆配置表
         } catch (Exception e) {
             // TODO Auto-generated catch block
         	close();//关闭数据库连接
@@ -160,6 +164,280 @@ public class JdbcUtils {
 		return prods;
 	}
 
+	public static void create_lamao_config() throws SQLException {
+		Statement statement = conn.createStatement();
+		String stationSql = "CREATE TABLE if not exists lamao_station_config("
+				+ "id INTEGER PRIMARY KEY,"
+				+ "mes_gw VARCHAR(20),"
+				+ "mes_gw_des VARCHAR(100),"
+				+ "mes_line_sn VARCHAR(20),"
+				+ "mes_server_ip VARCHAR(50),"
+				+ "setup_done INTEGER DEFAULT 0,"
+				+ "update_time DATETIME)";
+		statement.executeUpdate(stationSql);
+
+		String gunSql = "CREATE TABLE if not exists lamao_gun_config("
+				+ "id INTEGER PRIMARY KEY AUTOINCREMENT,"
+				+ "gun_code VARCHAR(5),"
+				+ "ip_address VARCHAR(50),"
+				+ "set_num INTEGER,"
+				+ "s_min INTEGER,"
+				+ "s_max INTEGER,"
+				+ "f_min INTEGER,"
+				+ "f_max INTEGER,"
+				+ "switch_enable INTEGER DEFAULT 0,"
+				+ "switch_from INTEGER,"
+				+ "switch_s_min INTEGER,"
+				+ "switch_s_max INTEGER,"
+				+ "switch_f_min INTEGER,"
+				+ "switch_f_max INTEGER,"
+				+ "update_time DATETIME)";
+		statement.executeUpdate(gunSql);
+		System.out.println("拉铆配置表创建成功!");
+
+		ensureSetupDoneColumn(statement);
+
+		ResultSet rs = statement.executeQuery("SELECT count(*) FROM lamao_station_config");
+		int stationCount = 0;
+		if (rs.next()) {
+			stationCount = rs.getInt(1);
+		}
+		rs.close();
+
+		ResultSet gunRs = statement.executeQuery("SELECT count(*) FROM lamao_gun_config");
+		int gunCount = 0;
+		if (gunRs.next()) {
+			gunCount = gunRs.getInt(1);
+		}
+		gunRs.close();
+		statement.close();
+
+		if (stationCount == 0 || gunCount < 2) {
+			initDefaultLamaoConfig();
+		}
+	}
+
+	private static void ensureSetupDoneColumn(Statement statement) {
+		try {
+			statement.executeQuery("SELECT setup_done FROM lamao_station_config LIMIT 1").close();
+		} catch (Exception e) {
+			try {
+				statement.executeUpdate("ALTER TABLE lamao_station_config ADD COLUMN setup_done INTEGER DEFAULT 0");
+				// 已有工位数据的旧库视为已完成首次设置
+				statement.executeUpdate("UPDATE lamao_station_config SET setup_done = 1 WHERE "
+						+ "mes_gw IS NOT NULL AND trim(mes_gw) <> '' AND "
+						+ "mes_server_ip IS NOT NULL AND trim(mes_server_ip) <> ''");
+			} catch (Exception ex) {
+				ex.printStackTrace();
+			}
+		}
+	}
+
+	public static boolean needsFirstSetup() {
+		try {
+			getConn();
+			Statement statement = conn.createStatement();
+			ResultSet rs = statement.executeQuery("SELECT setup_done, mes_gw, mes_server_ip FROM lamao_station_config WHERE id = 1");
+			boolean need = true;
+			if (rs.next()) {
+				int setupDone = rs.getInt("setup_done");
+				String gw = rs.getString("mes_gw");
+				String ip = rs.getString("mes_server_ip");
+				need = setupDone != 1
+						|| gw == null || gw.trim().isEmpty()
+						|| ip == null || ip.trim().isEmpty();
+			}
+			rs.close();
+			statement.close();
+			return need;
+		} catch (Exception e) {
+			e.printStackTrace();
+			return true;
+		}
+	}
+
+	public static boolean markStationSetupDone() {
+		try {
+			getConn();
+			Statement statement = conn.createStatement();
+			statement.executeUpdate("UPDATE lamao_station_config SET setup_done = 1 WHERE id = 1");
+			statement.close();
+			return true;
+		} catch (Exception e) {
+			e.printStackTrace();
+			return false;
+		}
+	}
+
+	private static void initDefaultLamaoConfig() throws SQLException {
+		String now = DateLocalUtils.getCurrentTime();
+		Statement statement = conn.createStatement();
+
+		ResultSet stationRs = statement.executeQuery("SELECT count(*) FROM lamao_station_config");
+		int stationCount = 0;
+		if (stationRs.next()) {
+			stationCount = stationRs.getInt(1);
+		}
+		stationRs.close();
+
+		if (stationCount == 0) {
+			// setup_done=0:首次启动需用户填写工位号/工位名称/服务器IP
+			statement.executeUpdate("INSERT INTO lamao_station_config (id, mes_gw, mes_gw_des, mes_line_sn, mes_server_ip, setup_done, update_time) VALUES "
+					+ "(1, '', '', 'XT', '', 0, '" + now + "')");
+		}
+
+		ResultSet gunRs = statement.executeQuery("SELECT count(*) FROM lamao_gun_config WHERE gun_code = 'A'");
+		int gunACount = 0;
+		if (gunRs.next()) {
+			gunACount = gunRs.getInt(1);
+		}
+		gunRs.close();
+
+		if (gunACount == 0) {
+			statement.executeUpdate("INSERT INTO lamao_gun_config (gun_code, ip_address, set_num, s_min, s_max, f_min, f_max, switch_enable, switch_from, switch_s_min, switch_s_max, switch_f_min, switch_f_max, update_time) VALUES "
+					+ "('A', '192.168.1.9', 26, 3200, 4200, 10500, 11500, 0, 24, 4000, 5000, 10500, 11500, '" + now + "')");
+		}
+
+		ResultSet gunBRs = statement.executeQuery("SELECT count(*) FROM lamao_gun_config WHERE gun_code = 'B'");
+		int gunBCount = 0;
+		if (gunBRs.next()) {
+			gunBCount = gunBRs.getInt(1);
+		}
+		gunBRs.close();
+
+		if (gunBCount == 0) {
+			statement.executeUpdate("INSERT INTO lamao_gun_config (gun_code, ip_address, set_num, s_min, s_max, f_min, f_max, switch_enable, switch_from, switch_s_min, switch_s_max, switch_f_min, switch_f_max, update_time) VALUES "
+					+ "('B', '192.168.1.8', 28, 3500, 4900, 10500, 11500, 1, 27, 3000, 4500, 10500, 11500, '" + now + "')");
+		}
+
+		System.out.println("默认拉铆配置初始化完成!");
+		statement.close();
+	}
+
+	public static com.mes.ui.LamaoStationConfig getStationConfig() {
+		com.mes.ui.LamaoStationConfig config = new com.mes.ui.LamaoStationConfig();
+		try {
+			getConn();
+			Statement statement = conn.createStatement();
+			ResultSet rs = statement.executeQuery("SELECT id, mes_gw, mes_gw_des, mes_line_sn, mes_server_ip FROM lamao_station_config WHERE id = 1");
+			if (rs.next()) {
+				config.setId(rs.getInt("id"));
+				config.setMesGw(rs.getString("mes_gw"));
+				config.setMesGwDes(rs.getString("mes_gw_des"));
+				config.setMesLineSn(rs.getString("mes_line_sn"));
+				config.setMesServerIp(rs.getString("mes_server_ip"));
+			}
+			rs.close();
+			statement.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return config;
+	}
+
+	public static boolean saveStationConfig(com.mes.ui.LamaoStationConfig config) {
+		boolean ret = false;
+		try {
+			getConn();
+			String now = DateLocalUtils.getCurrentTime();
+			Statement statement = conn.createStatement();
+			ResultSet rs = statement.executeQuery("SELECT count(*) FROM lamao_station_config WHERE id = 1");
+			int count = 0;
+			if (rs.next()) {
+				count = rs.getInt(1);
+			}
+			rs.close();
+
+			String sql;
+			if (count > 0) {
+				sql = "UPDATE lamao_station_config SET mes_gw = '" + esc(config.getMesGw()) + "', "
+						+ "mes_gw_des = '" + esc(config.getMesGwDes()) + "', "
+						+ "mes_line_sn = '" + esc(config.getMesLineSn()) + "', "
+						+ "mes_server_ip = '" + esc(config.getMesServerIp()) + "', "
+						+ "setup_done = 1, "
+						+ "update_time = '" + now + "' WHERE id = 1";
+			} else {
+				sql = "INSERT INTO lamao_station_config (id, mes_gw, mes_gw_des, mes_line_sn, mes_server_ip, setup_done, update_time) VALUES (1, '"
+						+ esc(config.getMesGw()) + "', '" + esc(config.getMesGwDes()) + "', '"
+						+ esc(config.getMesLineSn()) + "', '" + esc(config.getMesServerIp()) + "', 1, '" + now + "')";
+			}
+			statement.executeUpdate(sql);
+			statement.close();
+			ret = true;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return ret;
+	}
+
+	public static com.mes.ui.LamaoGunConfig getGunConfig(String gunCode) {
+		com.mes.ui.LamaoGunConfig config = null;
+		try {
+			getConn();
+			Statement statement = conn.createStatement();
+			ResultSet rs = statement.executeQuery("SELECT id, gun_code, ip_address, set_num, s_min, s_max, f_min, f_max, switch_enable, switch_from, switch_s_min, switch_s_max, switch_f_min, switch_f_max "
+					+ "FROM lamao_gun_config WHERE gun_code = '" + esc(gunCode) + "'");
+			if (rs.next()) {
+				config = new com.mes.ui.LamaoGunConfig();
+				config.setId(rs.getInt("id"));
+				config.setGunCode(rs.getString("gun_code"));
+				config.setIpAddress(rs.getString("ip_address"));
+				config.setSetNum((short) rs.getInt("set_num"));
+				config.setSMin((short) rs.getInt("s_min"));
+				config.setSMax((short) rs.getInt("s_max"));
+				config.setFMin((short) rs.getInt("f_min"));
+				config.setFMax((short) rs.getInt("f_max"));
+				config.setSwitchEnable(rs.getInt("switch_enable") == 1);
+				config.setSwitchFrom((short) rs.getInt("switch_from"));
+				config.setSwitchSMin((short) rs.getInt("switch_s_min"));
+				config.setSwitchSMax((short) rs.getInt("switch_s_max"));
+				config.setSwitchFMin((short) rs.getInt("switch_f_min"));
+				config.setSwitchFMax((short) rs.getInt("switch_f_max"));
+			}
+			rs.close();
+			statement.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return config;
+	}
+
+	public static boolean updateGunConfig(com.mes.ui.LamaoGunConfig config) {
+		boolean ret = false;
+		try {
+			getConn();
+			String now = DateLocalUtils.getCurrentTime();
+			Statement statement = conn.createStatement();
+			String sql = "UPDATE lamao_gun_config SET ip_address = '" + esc(config.getIpAddress()) + "', "
+					+ "set_num = " + config.getSetNum() + ", "
+					+ "s_min = " + config.getSMin() + ", "
+					+ "s_max = " + config.getSMax() + ", "
+					+ "f_min = " + config.getFMin() + ", "
+					+ "f_max = " + config.getFMax() + ", "
+					+ "switch_enable = " + (config.isSwitchEnable() ? 1 : 0) + ", "
+					+ "switch_from = " + config.getSwitchFrom() + ", "
+					+ "switch_s_min = " + config.getSwitchSMin() + ", "
+					+ "switch_s_max = " + config.getSwitchSMax() + ", "
+					+ "switch_f_min = " + config.getSwitchFMin() + ", "
+					+ "switch_f_max = " + config.getSwitchFMax() + ", "
+					+ "update_time = '" + now + "' "
+					+ "WHERE gun_code = '" + esc(config.getGunCode()) + "'";
+			statement.executeUpdate(sql);
+			statement.close();
+			ret = true;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return ret;
+	}
+
+	private static String esc(String value) {
+		if (value == null) {
+			return "";
+		}
+		return value.replace("'", "''");
+	}
+
 }
  
 

+ 0 - 4
src/resources/config/config.properties

@@ -1,6 +1,2 @@
-mes.gw=OP130B
-#mes.server_ip=127.0.0.1
-mes.server_ip=192.168.24.99
 mes.tcp_port=3000
 mes.heart_beat_cycle=60
-mes.line_sn=XT