|
|
@@ -97,8 +97,25 @@ public class MesClient extends JFrame {
|
|
|
public static JTextField param_bf; // B枪拉力
|
|
|
public static JTextField param_bs; // B枪位移
|
|
|
|
|
|
+ public static JButton repairBtnA;
|
|
|
+ public static JButton repairBtnB;
|
|
|
+ public static JTextField repairInputA;
|
|
|
+ public static JTextField repairInputB;
|
|
|
+ public static boolean repairModeA = false;
|
|
|
+ public static boolean repairModeB = false;
|
|
|
+ /** 返修偏移量(0=未返修);界面/判定有效数 = PLC读数 + repairOffset */
|
|
|
+ public static int repairOffsetA = 0;
|
|
|
+ public static int repairOffsetB = 0;
|
|
|
+ /** 上次 PLC 实际计数,用于检测新铆接(与返修下限独立) */
|
|
|
+ public static int lastPlcCountA = 0;
|
|
|
+ public static int lastPlcCountB = 0;
|
|
|
+ /** 本件是否经返修确认改过数(自动提交时按 OK 上报) */
|
|
|
+ public static boolean repairAppliedA = false;
|
|
|
+ public static boolean repairAppliedB = false;
|
|
|
+ private static final String REPAIR_MODE_PASSWORD = "503833";
|
|
|
+
|
|
|
public static String curIpA = "192.168.0.200"; // A枪 PLC IP
|
|
|
- public static String curIpB = "192.168.0.201"; // B枪 PLC IP
|
|
|
+ public static String curIpB = "192.168.0.202"; // B枪 PLC IP
|
|
|
public static S7PLC plcA = null; // A枪 PLC 对象
|
|
|
public static S7PLC plcB = null; // B枪 PLC 对象
|
|
|
|
|
|
@@ -151,7 +168,7 @@ public class MesClient extends JFrame {
|
|
|
readProperty();
|
|
|
|
|
|
// 3. 初始化本地数据库配置 (第一优先级,覆盖文件配置)
|
|
|
- initLocalConfig();
|
|
|
+ reloadLocalConfig();
|
|
|
|
|
|
// 3.5 最终初始化 PLC 连接 (根据确定的 IP)
|
|
|
if (plcA == null) {
|
|
|
@@ -283,12 +300,11 @@ public class MesClient extends JFrame {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 初始化本地数据库配置 (最高优先级)
|
|
|
+ * 从本地数据库重新加载配置并同步到内存、界面及 PLC 连接
|
|
|
*/
|
|
|
- private static void initLocalConfig() {
|
|
|
+ public static void reloadLocalConfig() {
|
|
|
Map<String, Object> config = JdbcUtils.getConfig();
|
|
|
if (config != null && config.size() > 0) {
|
|
|
- // 数据库中存在的字段且不为 null 时才覆盖
|
|
|
if (config.get("a_set_num") != null) {
|
|
|
aSetNum = (Integer) config.get("a_set_num");
|
|
|
aMax = aSetNum;
|
|
|
@@ -306,7 +322,6 @@ public class MesClient extends JFrame {
|
|
|
String dbGw = (String) config.get("mes_gw");
|
|
|
if (dbGw != null && !dbGw.isEmpty()) mes_gw = dbGw;
|
|
|
|
|
|
- // 无论数据库存的是什么描述,都根据工位号重新匹配最新的描述
|
|
|
mes_gw_des = OprnoUtil.getGwDes(mes_line_sn, mes_gw);
|
|
|
if (mes_gw_des == null || mes_gw_des.isEmpty()) {
|
|
|
String dbGwDes = (String) config.get("mes_gw_des");
|
|
|
@@ -318,9 +333,18 @@ public class MesClient extends JFrame {
|
|
|
log.info("本地数据库无配置,将维持配置文件或硬编码配置。");
|
|
|
}
|
|
|
|
|
|
- // 同步 UI (如果已初始化)
|
|
|
+ if (curIpA != null && !curIpA.isEmpty()) {
|
|
|
+ reconnectPlcA(curIpA);
|
|
|
+ }
|
|
|
+ if (curIpB != null && !curIpB.isEmpty()) {
|
|
|
+ reconnectPlcB(curIpB);
|
|
|
+ }
|
|
|
+
|
|
|
if (param1 != null) param1.setText(String.valueOf(aSetNum));
|
|
|
if (param3 != null) param3.setText(String.valueOf(bSetNum));
|
|
|
+ if (mesClientFrame != null) {
|
|
|
+ mesClientFrame.setTitle("MES系统客户端:" + mes_gw + "- " + mes_gw_des);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public static void getPlcParam() {
|
|
|
@@ -466,7 +490,159 @@ public class MesClient extends JFrame {
|
|
|
resetScanA();
|
|
|
}
|
|
|
|
|
|
+ private static void updateRepairBtnStyle(JButton btn, boolean active) {
|
|
|
+ if (btn == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (active) {
|
|
|
+ btn.setBackground(new Color(76, 175, 80));
|
|
|
+ btn.setForeground(Color.WHITE);
|
|
|
+ btn.setOpaque(true);
|
|
|
+ btn.setBorderPainted(false);
|
|
|
+ btn.setText("返修模式");
|
|
|
+ } else {
|
|
|
+ btn.setBackground(UIManager.getColor("Button.background"));
|
|
|
+ btn.setForeground(UIManager.getColor("Button.foreground"));
|
|
|
+ btn.setOpaque(true);
|
|
|
+ btn.setBorderPainted(true);
|
|
|
+ btn.setText("返修模式");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void resetRepairMode() {
|
|
|
+ repairModeA = false;
|
|
|
+ repairModeB = false;
|
|
|
+ updateRepairBtnStyle(repairBtnA, false);
|
|
|
+ updateRepairBtnStyle(repairBtnB, false);
|
|
|
+ if (repairInputA != null) {
|
|
|
+ repairInputA.setText("");
|
|
|
+ }
|
|
|
+ if (repairInputB != null) {
|
|
|
+ repairInputB.setText("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static boolean verifyRepairPassword() {
|
|
|
+ String pass = JOptionPane.showInputDialog(mesClientFrame, "请输入密码");
|
|
|
+ if (pass == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!REPAIR_MODE_PASSWORD.equals(pass.trim())) {
|
|
|
+ setMenuStatus("密码错误", -1);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void toggleRepairModeA() {
|
|
|
+ if (!repairModeA && !verifyRepairPassword()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ repairModeA = !repairModeA;
|
|
|
+ updateRepairBtnStyle(repairBtnA, repairModeA);
|
|
|
+ if (!repairModeA && repairInputA != null) {
|
|
|
+ repairInputA.setText("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void toggleRepairModeB() {
|
|
|
+ if (!repairModeB && !verifyRepairPassword()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ repairModeB = !repairModeB;
|
|
|
+ updateRepairBtnStyle(repairBtnB, repairModeB);
|
|
|
+ if (!repairModeB && repairInputB != null) {
|
|
|
+ repairInputB.setText("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void exitRepairModeA() {
|
|
|
+ repairModeA = false;
|
|
|
+ updateRepairBtnStyle(repairBtnA, false);
|
|
|
+ if (repairInputA != null) {
|
|
|
+ repairInputA.setText("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void exitRepairModeB() {
|
|
|
+ repairModeB = false;
|
|
|
+ updateRepairBtnStyle(repairBtnB, false);
|
|
|
+ if (repairInputB != null) {
|
|
|
+ repairInputB.setText("");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void confirmRepairCountA() {
|
|
|
+ if (!repairModeA) {
|
|
|
+ setMenuStatus("请先开启A枪返修模式", -1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (work_status != 1) {
|
|
|
+ setMenuStatus("请先扫码开始加工", -1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ int count = Integer.parseInt(repairInputA.getText().trim());
|
|
|
+ if (count <= 0 || count > aMax) {
|
|
|
+ setMenuStatus("A枪返修数量须在 1~" + aMax + " 之间", -1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int plcCount = 0;
|
|
|
+ try {
|
|
|
+ plcCount = plcA.readInt32("DB41.32");
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+ repairOffsetA = count - plcCount;
|
|
|
+ repairAppliedA = true;
|
|
|
+ lastPlcCountA = Math.max(lastPlcCountA, plcCount);
|
|
|
+ sortA = plcCount + repairOffsetA;
|
|
|
+ param2.setText(String.valueOf(sortA));
|
|
|
+ PlcUtil.applyRepairCountA(plcA, count);
|
|
|
+ exitRepairModeA();
|
|
|
+ setMenuStatus("A枪完成数量已设为 " + count, 0);
|
|
|
+ afterRepairCountChanged();
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ setMenuStatus("A枪返修数量请输入有效数字", -1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void confirmRepairCountB() {
|
|
|
+ if (!repairModeB) {
|
|
|
+ setMenuStatus("请先开启B枪返修模式", -1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (work_status != 1) {
|
|
|
+ setMenuStatus("请先扫码开始加工", -1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ int count = Integer.parseInt(repairInputB.getText().trim());
|
|
|
+ if (count <= 0 || count > bMax) {
|
|
|
+ setMenuStatus("B枪返修数量须在 1~" + bMax + " 之间", -1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ int plcCount = 0;
|
|
|
+ try {
|
|
|
+ plcCount = plcB.readInt32("DB41.32");
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+ repairOffsetB = count - plcCount;
|
|
|
+ repairAppliedB = true;
|
|
|
+ lastPlcCountB = Math.max(lastPlcCountB, plcCount);
|
|
|
+ sortB = plcCount + repairOffsetB;
|
|
|
+ param4.setText(String.valueOf(sortB));
|
|
|
+ PlcUtil.applyRepairCountB(plcB, count);
|
|
|
+ exitRepairModeB();
|
|
|
+ setMenuStatus("B枪完成数量已设为 " + count, 0);
|
|
|
+ afterRepairCountChanged();
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
+ setMenuStatus("B枪返修数量请输入有效数字", -1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public static void resetScanA() {
|
|
|
+ reloadLocalConfig();
|
|
|
+
|
|
|
MesClient.status_menu.setText("工件状态");
|
|
|
MesClient.curSn = "";
|
|
|
MesClient.product_sn.setText("");
|
|
|
@@ -481,6 +657,12 @@ public class MesClient extends JFrame {
|
|
|
MesClient.sortB = 0;
|
|
|
MesClient.aFinish = 0;
|
|
|
MesClient.bFinish = 0;
|
|
|
+ MesClient.repairOffsetA = 0;
|
|
|
+ MesClient.repairOffsetB = 0;
|
|
|
+ MesClient.repairAppliedA = false;
|
|
|
+ MesClient.repairAppliedB = false;
|
|
|
+ MesClient.lastPlcCountA = 0;
|
|
|
+ MesClient.lastPlcCountB = 0;
|
|
|
MesClient.alist.clear();
|
|
|
MesClient.atids.clear();
|
|
|
MesClient.param2.setText("0");
|
|
|
@@ -489,12 +671,98 @@ public class MesClient extends JFrame {
|
|
|
MesClient.param_as.setText("0");
|
|
|
MesClient.param_bf.setText("0");
|
|
|
MesClient.param_bs.setText("0");
|
|
|
+ MesClient.aMax = aSetNum;
|
|
|
+ MesClient.bMax = bSetNum;
|
|
|
MesClient.param1.setText(String.valueOf(aSetNum));
|
|
|
MesClient.param3.setText(String.valueOf(bSetNum));
|
|
|
|
|
|
PlcUtil.setTask(MesClient.plcA, MesClient.aSetNum, MesClient.bSetNum);
|
|
|
PlcUtil.setPowerOff(MesClient.plcA); // 远程关机
|
|
|
PlcUtil.setPowerOff(MesClient.plcB); // 远程关机
|
|
|
+ resetRepairMode();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 返修改数后立即检查是否双枪已满,触发关气与提交(无 syncGunPowerState 时手工同步气路) */
|
|
|
+ public static void afterRepairCountChanged() {
|
|
|
+ if (work_status != 1) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ if (plcA != null) {
|
|
|
+ int effectiveA = PlcUtil.getEffectiveCountA(plcA);
|
|
|
+ if (effectiveA >= aMax) {
|
|
|
+ PlcUtil.setPowerOff(plcA);
|
|
|
+ } else {
|
|
|
+ PlcUtil.setPowerOn(plcA);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (plcB != null && bMax > 0) {
|
|
|
+ int effectiveB = PlcUtil.getEffectiveCountB(plcB);
|
|
|
+ if (effectiveB >= bMax) {
|
|
|
+ PlcUtil.setPowerOff(plcB);
|
|
|
+ } else {
|
|
|
+ PlcUtil.setPowerOn(plcB);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("返修改数后同步气路失败", e);
|
|
|
+ }
|
|
|
+ tryAutoSubmitWhenBothGunsDone();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 双枪模式:A、B 均达到预定数量;单枪模式(bMax<=0):仅 A 达到即可(按有效完成数,含返修偏移) */
|
|
|
+ public static boolean isBothGunsReachTarget() {
|
|
|
+ if (curSn.isEmpty() || aMax <= 0 || plcA == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ int curA = PlcUtil.getEffectiveCountA(plcA);
|
|
|
+ if (curA < aMax) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (bMax <= 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (plcB == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ int curB = PlcUtil.getEffectiveCountB(plcB);
|
|
|
+ return curB >= bMax;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("读取 PLC 计数失败,使用内存计数兜底", e);
|
|
|
+ if (sortA < aMax) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (bMax <= 0) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return sortB >= bMax;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 达到预定数量后启用提交并自动上传结果(双枪须都完成) */
|
|
|
+ public static void tryAutoSubmitWhenBothGunsDone() {
|
|
|
+ if (!isBothGunsReachTarget()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ finish_ok_bt.setEnabled(true);
|
|
|
+ finish_ng_bt.setEnabled(true);
|
|
|
+ if (tjStatus != 0 || !check_quality_result) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ tjStatus = 1;
|
|
|
+ setMenuStatus("正在自动提交结果...", 0);
|
|
|
+ getUser();
|
|
|
+ String retf = "OK";
|
|
|
+ boolean repairAdjusted = repairAppliedA || repairAppliedB;
|
|
|
+ if (!repairAdjusted && (aFinish < aMax || (bMax > 0 && bFinish < bMax))) {
|
|
|
+ retf = "NG";
|
|
|
+ }
|
|
|
+ Boolean ret = DataUtil.sendQuality(nettyClient, product_sn.getText(), retf, user20);
|
|
|
+ if (!ret) {
|
|
|
+ tjStatus = 0;
|
|
|
+ setMenuStatus(tjFlagTextErr, -1);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
public static void checkSnType(String sn) {
|
|
|
@@ -824,6 +1092,44 @@ public class MesClient extends JFrame {
|
|
|
finish_ng_bt.setEnabled(false);
|
|
|
indexPanelA.add(finish_ng_bt);
|
|
|
|
|
|
+ Font repairFont = new Font("微软雅黑", Font.PLAIN, 14);
|
|
|
+
|
|
|
+ repairBtnA = new JButton("返修模式");
|
|
|
+ repairBtnA.setFont(repairFont);
|
|
|
+ repairBtnA.setBounds(25, 150, 95, 32);
|
|
|
+ repairBtnA.addActionListener(e -> toggleRepairModeA());
|
|
|
+ indexPanelA.add(repairBtnA);
|
|
|
+
|
|
|
+ repairInputA = new JTextField();
|
|
|
+ repairInputA.setFont(repairFont);
|
|
|
+ repairInputA.setHorizontalAlignment(SwingConstants.CENTER);
|
|
|
+ repairInputA.setBounds(125, 150, 55, 32);
|
|
|
+ indexPanelA.add(repairInputA);
|
|
|
+
|
|
|
+ JButton repairConfirmA = new JButton("确定数量");
|
|
|
+ repairConfirmA.setFont(repairFont);
|
|
|
+ repairConfirmA.setBounds(185, 150, 95, 32);
|
|
|
+ repairConfirmA.addActionListener(e -> confirmRepairCountA());
|
|
|
+ indexPanelA.add(repairConfirmA);
|
|
|
+
|
|
|
+ repairBtnB = new JButton("返修模式");
|
|
|
+ repairBtnB.setFont(repairFont);
|
|
|
+ repairBtnB.setBounds(480, 150, 95, 32);
|
|
|
+ repairBtnB.addActionListener(e -> toggleRepairModeB());
|
|
|
+ indexPanelA.add(repairBtnB);
|
|
|
+
|
|
|
+ repairInputB = new JTextField();
|
|
|
+ repairInputB.setFont(repairFont);
|
|
|
+ repairInputB.setHorizontalAlignment(SwingConstants.CENTER);
|
|
|
+ repairInputB.setBounds(580, 150, 55, 32);
|
|
|
+ indexPanelA.add(repairInputB);
|
|
|
+
|
|
|
+ JButton repairConfirmB = new JButton("确定数量");
|
|
|
+ repairConfirmB.setFont(repairFont);
|
|
|
+ repairConfirmB.setBounds(640, 150, 95, 32);
|
|
|
+ repairConfirmB.addActionListener(e -> confirmRepairCountB());
|
|
|
+ indexPanelA.add(repairConfirmB);
|
|
|
+
|
|
|
JLabel lblNewLabel = new JLabel("A枪");
|
|
|
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
|
|
lblNewLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|