hfy 1 周之前
父节点
当前提交
3ab8d1fe39

+ 90 - 0
src/com/mes/device/DeviceStateReporter.java

@@ -0,0 +1,90 @@
+package com.mes.device;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.mes.util.HttpUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 工位客户端设备状态上报(按 gw + lineSn)
+ */
+public class DeviceStateReporter {
+
+    public static final Logger log = LoggerFactory.getLogger(DeviceStateReporter.class);
+
+    /** 正常运行 */
+    public static final String STATE_RUNNING = "1";
+    /** 工位退出/收班 */
+    public static final String STATE_STOP = "7";
+
+    private static DeviceStateReporter instance;
+
+    private String serverIp;
+    private String gw;
+    private String lineSn;
+
+    private DeviceStateReporter() {
+    }
+
+    public static DeviceStateReporter getInstance() {
+        if (instance == null) {
+            synchronized (DeviceStateReporter.class) {
+                if (instance == null) {
+                    instance = new DeviceStateReporter();
+                }
+            }
+        }
+        return instance;
+    }
+
+    public void init(String serverIp, String gw, String lineSn) {
+        this.serverIp = serverIp;
+        this.gw = gw;
+        this.lineSn = lineSn;
+        log.info("设备状态上报初始化: gw={}, lineSn={}", gw, lineSn);
+    }
+
+    /**
+     * 异步上报
+     */
+    public void reportAsync(final String state, final String content) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                reportSync(state, content);
+            }
+        }, "device-state-report-thread").start();
+    }
+
+    /**
+     * 同步上报
+     */
+    public boolean reportSync(String state, String content) {
+        if (isBlank(serverIp) || isBlank(gw) || isBlank(lineSn)) {
+            log.warn("设备状态上报跳过:配置不完整 serverIp={}, gw={}, lineSn={}", serverIp, gw, lineSn);
+            return false;
+        }
+        try {
+            String url = "http://" + serverIp + ":8980/js/a/mes/mesDevice/reportState";
+            JSONObject body = new JSONObject();
+            body.put("gw", gw);
+            body.put("lineSn", lineSn);
+            body.put("state", state);
+            body.put("content", content == null ? "" : content);
+            String result = HttpUtils.sendPostRequestJson(url, body.toJSONString());
+            log.info("设备状态上报: state={}, content={}, result={}", state, content, result);
+            if (isBlank(result) || "false".equalsIgnoreCase(result)) {
+                return false;
+            }
+            JSONObject retObj = JSONObject.parseObject(result);
+            return retObj != null && "true".equalsIgnoreCase(String.valueOf(retObj.get("result")));
+        } catch (Exception e) {
+            log.error("设备状态上报异常: state={}, content={}", state, content, e);
+            return false;
+        }
+    }
+
+    private boolean isBlank(String value) {
+        return value == null || value.trim().isEmpty();
+    }
+}

+ 13 - 1
src/com/mes/ui/DataUtil.java

@@ -297,7 +297,19 @@ public class DataUtil {
         return resp;
     }
 
-
+    //删除当前工位工件码
+    public static JSONObject delCurSn(String oprno,String serverIp,String lineSn){
+        try {
+            String url = "http://"+serverIp+":8980/js/a/mes/mesProductRecord/cancelCurSn";
+            String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&__sid="+MesClient.sessionid;
+            JSONObject result = JSONObject.parseObject(doPost(url, params));
+//            log.info("请求参数:"+params);
+            return result;
+        } catch (Exception e) {
+            log.info("e="+e.getMessage());
+            return null;
+        }
+    }
     // 发送气密数据
     public static JSONObject sendQualityParam(String user, String sn, String oprno, String lineSn, QmParam qmParam) {
         try {

+ 19 - 7
src/com/mes/ui/LoginFarme.java

@@ -10,6 +10,8 @@ import javax.swing.*;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
 import java.time.LocalDateTime;
 
 public class LoginFarme extends JFrame {
@@ -45,11 +47,11 @@ public class LoginFarme extends JFrame {
         userPasswordLabel.setBounds(300, 150, 120, 40);
         userPasswordLabel.setFont(new java.awt.Font("Dialog",   1,   16));
         userNameTxt = new JTextField(20);
-        userNameTxt.setText("system");
+        userNameTxt.setText("");
         userNameTxt.setBounds(400, 105, 150, 30);
         userPasswordTxt = new JPasswordField(20);
         userPasswordTxt.setBounds(400, 155, 150, 30);
-        userPasswordTxt.setText("Aa111111");
+        userPasswordTxt.setText("");
         loginButton.setFont(new java.awt.Font("Dialog",   1,   16));
         loginButton.setBounds(300, 200, 255, 40);
         loginButton.setIcon(new ImageIcon(MesClient.class.getResource("/bg/user.png")));
@@ -97,8 +99,8 @@ public class LoginFarme extends JFrame {
             JOptionPane.showMessageDialog(MesClient.mesClientFrame,"用户名或密码不能为空","提示窗口", JOptionPane.INFORMATION_MESSAGE);
             return;
         }
-        String username = Base64Utils.getBase64(user_str);
-        String password = Base64Utils.getBase64(password_str);
+        String username = urlEncode(Base64Utils.getBase64(user_str));
+        String password = urlEncode(Base64Utils.getBase64(password_str));
         System.out.println("&username=" + username + "&password=" + password);
         String url = "http://"+MesClient.mes_server_ip+":8980/js/a/login?__ajax=json&username="+username+"&password="+password+"&validCode=&__sid=";
         String loginResult = HttpUtils.sendRequest(url);
@@ -125,7 +127,7 @@ public class LoginFarme extends JFrame {
         String scanContent = JOptionPane.showInputDialog(null, "请扫码工牌二维码");
         System.out.println("scanContent="+scanContent);
         if(scanContent!=null&&!scanContent.equalsIgnoreCase("")) {
-            String url = "http://"+MesClient.mes_server_ip+":8980/js/a/mes/mesLogin/login?__login=true&__ajax=json&username="+scanContent;
+            String url = "http://"+MesClient.mes_server_ip+":8980/js/a/mes/mesLogin/login?__login=true&__ajax=json&username="+urlEncode(scanContent);
             String loginResult = HttpUtils.sendRequest(url);
             System.out.println("loginResult="+loginResult);
             if(loginResult.equalsIgnoreCase("false")) {
@@ -174,14 +176,16 @@ public class LoginFarme extends JFrame {
                     MesClient.userLoginHours = now.getHour();
                     //启动timer心跳包
                     MesClient.startHeartBeatTimer();
+                    // 上报设备开机状态并启动定时上报
+                    MesClient.reportDeviceRunning();
 
 
                     //1操作工人,2管理员
                     //登录成功
+                    MesClient.startGetCurSn();
                     MesClient.user_menu.setText(user_id);
                     MesClient.welcomeWin.setVisible(false);
                     MesClient.mesClientFrame.setVisible(true);
-                    MesClient.startGetCurSn();
                     // 已弃用WebView(工作记录),改为使用WorkRecordPanel
                      if(MesClient.jfxPanel == null){
                          String url = "http://"+ MesClient.mes_server_ip+":8980/js/a/mes/mesProductRecord/work?oprno="+MesClient.mes_gw+"&lineSn="+MesClient.mes_line_sn;
@@ -197,7 +201,7 @@ public class LoginFarme extends JFrame {
                         MesClient.indexPanelC.add(MesClient.jfxPanel2);
                     }
 
-                    MesClient.initWarehouseData();
+                   // MesClient.initWarehouseData();
                 }
 
             }
@@ -207,4 +211,12 @@ public class LoginFarme extends JFrame {
             return;
         }
     }
+
+    private static String urlEncode(String value) {
+        try {
+            return URLEncoder.encode(value != null ? value : "", "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalStateException("UTF-8 is not supported", e);
+        }
+    }
 }

+ 71 - 5
src/com/mes/ui/MesClient.java

@@ -5,6 +5,7 @@ import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
 import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
 import com.mes.component.MesRadio;
 import com.mes.component.MesWebView;
+import com.mes.device.DeviceStateReporter;
 import com.mes.util.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -34,6 +35,7 @@ public class MesClient extends JFrame {
     public static String mes_server_ip = ""; // 服务器IP地址
     public static int mes_heart_icon_cycle = 1;
     public static String mes_line_sn = ""; // 产线编号
+    public static int mes_device_heartbeat_minutes = 5; // 设备状态上报间隔(分钟)
     public static String csyq =  "";
 
     //session
@@ -128,12 +130,22 @@ public class MesClient extends JFrame {
         mes_line_sn = pro.getProperty("mes.line_sn");
         csyq = pro.getProperty("mes.csyq");
         mes_gw_des = OprnoUtil.getGwDes(mes_line_sn,mes_gw);
+        try {
+            mes_device_heartbeat_minutes = Integer.parseInt(pro.getProperty("mes.device.heartbeat.minutes", "5").trim());
+        } catch (Exception e) {
+            mes_device_heartbeat_minutes = 5;
+        }
+        if (mes_device_heartbeat_minutes <= 0) {
+            mes_device_heartbeat_minutes = 5;
+        }
         log.info(mes_gw + ";" + mes_gw_des + ";" + mes_server_ip + ";");
     }
 
     //启动心跳包程序
     public static java.util.Timer heartBeatTimer;
     public static java.util.Timer heartBeatIconTimer;
+    // 设备状态定时上报
+    public static java.util.Timer deviceReportTimer;
     public static boolean iconREDFlag = true;
     public static void startHeartBeatTimer() {
         if(heartBeatTimer!=null) {
@@ -160,6 +172,49 @@ public class MesClient extends JFrame {
         }, 100,mes_heart_icon_cycle*1000);
     }
 
+    /**
+     * 启动设备状态定时上报
+     */
+    public static void startDeviceReportTimer() {
+        stopDeviceReportTimer();
+        long intervalMs = mes_device_heartbeat_minutes * 60L * 1000L;
+        deviceReportTimer = new Timer("device-report-timer", true);
+        deviceReportTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                DeviceStateReporter.getInstance().reportAsync(DeviceStateReporter.STATE_RUNNING, "运行心跳");
+            }
+        }, intervalMs, intervalMs);
+        log.info("设备状态定时上报已启动,间隔 {} 分钟", mes_device_heartbeat_minutes);
+    }
+
+    /**
+     * 停止设备状态定时上报
+     */
+    public static void stopDeviceReportTimer() {
+        if (deviceReportTimer != null) {
+            deviceReportTimer.cancel();
+            deviceReportTimer = null;
+        }
+    }
+
+    /**
+     * 登录成功后上报设备开机状态
+     */
+    public static void reportDeviceRunning() {
+        DeviceStateReporter.getInstance().init(mes_server_ip, mes_gw, mes_line_sn);
+        DeviceStateReporter.getInstance().reportAsync(DeviceStateReporter.STATE_RUNNING, "工位登录,设备开机");
+        startDeviceReportTimer();
+    }
+
+    /**
+     * 退出或关闭时上报设备停机状态
+     */
+    public static void reportDeviceStopped() {
+        stopDeviceReportTimer();
+        DeviceStateReporter.getInstance().reportSync(DeviceStateReporter.STATE_STOP, "工位退出,设备停机");
+    }
+
     //设置tcp连接状态显示
     public static void setTcpStatus() {
         status_menu.setText("已连接MES服务器");
@@ -172,7 +227,9 @@ public class MesClient extends JFrame {
     }
 
     public static void resetScanA() {
-        work_status = 0;
+        JSONObject retObj = DataUtil.delCurSn(MesClient.mes_gw, mes_server_ip, mes_line_sn);
+        if (retObj.get("result")!=null && retObj.get("result").toString().equalsIgnoreCase("true")) {
+            work_status = 0;
         check_quality_result = false;
         MesClient.finish_ok_bt.setEnabled(false);
         MesClient.finish_ng_bt.setEnabled(false);
@@ -185,6 +242,9 @@ public class MesClient extends JFrame {
 
         updateMaterailData();
 //        shiftUserCheck();
+    } else {
+        MesClient.setMenuStatus("刷新失败",0);
+    }
     }
 
     public static int userLoginHours;//用户登录所处小时
@@ -297,6 +357,11 @@ public class MesClient extends JFrame {
     }
 
     public static void logoff() {
+        reportDeviceStopped();
+        if (getSnBeatTimer != null) {
+            getSnBeatTimer.cancel();
+            getSnBeatTimer = null;
+        }
         welcomeWin.setVisible(true);
         mesClientFrame.setVisible(false);
     }
@@ -314,8 +379,8 @@ public class MesClient extends JFrame {
             public void windowClosing(WindowEvent e) {
                 int choice = JOptionPane.showConfirmDialog(null, "确定要关闭窗口吗?", "关闭确认", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
                 if (choice == JOptionPane.YES_OPTION) {
-                    // 如果用户点击“是”,则关闭窗口
-                    dispose(); // 释放窗口资源并关闭窗口
+                    reportDeviceStopped();
+                    dispose();
                     System.exit(0);
                 }
             }
@@ -713,8 +778,6 @@ public class MesClient extends JFrame {
                         }
                     }
                 } else if (work_status == 0) {
-                    String abc = PLCUtils.getResult(plc);
-                    System.out.println(abc);
                     JSONObject result = DataUtil.getCurSn(mes_gw, mes_server_ip, mes_line_sn);
                     // 正常处理结果
                     if (result.containsKey("data")) {
@@ -737,6 +800,9 @@ public class MesClient extends JFrame {
                             }
                         }
                     }
+                    String abc = PLCUtils.getResult(plc);
+                    System.out.println(abc);
+
                 }
             }
 

+ 1 - 1
src/com/mes/ui/OprnoUtil.java

@@ -21,7 +21,7 @@ public class OprnoUtil {
             "凸焊","左边梁防爆阀拉铆","CMT框架一序焊接",
             "人工补焊", "框架CMT二序焊接", "人工补焊", "焊道检查", "总成正面CNC",
             "总成反面CNC", "框架去毛刺+清洁", "封堵片焊接+打磨", "白件气密检测", "焊道补焊",
-            "框架反面涂胶", "液冷板安装", "正面溢胶清理,补胶", "液冷板激光点固", "液冷板水嘴处焊接",
+            "框架反面涂胶", "总成气密检测", "正面溢胶清理,补胶", "液冷板激光点固", "液冷板水嘴处焊接",
             "焊道打磨", "液冷板FSW", "匙孔补焊打磨", "总成反面拉铆", "总成正面拉铆1",
             "总成正面拉铆2", "边梁套筒涂胶+压合", "箱体封堵", "胶水固化", "半成品气密",
             "补强板安装", "胶水固化", "拆卸补强板压紧工装", "FSW焊道涂胶+双层拉铆螺母涂胶", "人工抹胶",

+ 3 - 1
src/com/mes/util/Base64Utils.java

@@ -2,9 +2,11 @@ package com.mes.util;
 
 import org.apache.commons.codec.binary.Base64;
 
+import java.nio.charset.StandardCharsets;
+
 public class Base64Utils {
 	public static String getBase64(String str) {
-        byte[] binaryData = str.getBytes();
+        byte[] binaryData = str.getBytes(StandardCharsets.UTF_8);
         String encodedString = Base64.encodeBase64String(binaryData);
         return encodedString;
 	}

+ 4 - 2
src/com/mes/util/HttpUtils.java

@@ -27,7 +27,7 @@ public class HttpUtils {
             //设置请求类型
             con.setRequestMethod(requestType);
             //设置请求需要返回的数据类型和字符集类型
-            con.setRequestProperty("Content-Type", "application/json;charset=GBK");  
+             con.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
             //允许写出
             con.setDoOutput(true);
             //允许读入
@@ -80,7 +80,7 @@ public class HttpUtils {
             //设置请求类型
             con.setRequestMethod(requestType);
             //设置请求需要返回的数据类型和字符集类型
-            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=GBK");
+            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
             //允许写出
             con.setDoOutput(true);
             //允许读入
@@ -92,6 +92,8 @@ public class HttpUtils {
             OutputStreamWriter out = new OutputStreamWriter( con.getOutputStream(),"UTF-8");// utf-8编码
             // 发送请求参数
             out.write(params);
+            out.flush();
+            out.close();
 
             //得到响应码
             int responseCode = con.getResponseCode();

+ 1 - 1
src/com/mes/util/PLCUtils.java

@@ -56,7 +56,7 @@ public class PLCUtils {
         qmParam.setDeviceType(MesClient.csyq);
         qmParam.setTestPace(loopTime);
         long start = System.currentTimeMillis();
-        final long MAX_WAIT = 3000;
+        final long MAX_WAIT = 5000;
         while (true){
             leakageValue = plc.readString("VB307", 7);
             // 条件1:读取到非空,直接跳出循环

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

@@ -1,5 +1,7 @@
-mes.gw=OP190A
+mes.gw=OP190B
 #mes.server_ip=127.0.0.1
 mes.server_ip=192.168.9.180
 mes.line_sn=HEVXT
-mes.csyq=comso
+mes.csyq=comso
+# 设备状态定时上报间隔(分钟)
+mes.device.heartbeat.minutes=5