hou 2 päivää sitten
commit
1ea1d5f773
100 muutettua tiedostoa jossa 5160 lisäystä ja 0 poistoa
  1. 24 0
      .classpath
  2. 7 0
      .gitignore
  3. 0 0
      .lock
  4. 17 0
      .project
  5. 2 0
      image/.gitignore
  6. BIN
      image/background.png
  7. BIN
      image/bg/a_side.png
  8. BIN
      image/bg/b_side.png
  9. BIN
      image/bg/bar_add.png
  10. BIN
      image/bg/bar_bookmark.png
  11. BIN
      image/bg/bar_cmd_go.png
  12. BIN
      image/bg/bar_edit.png
  13. BIN
      image/bg/bar_pause.png
  14. BIN
      image/bg/bar_sampling.png
  15. BIN
      image/bg/bar_setting.png
  16. BIN
      image/bg/bar_stop.png
  17. BIN
      image/bg/close_bt.png
  18. BIN
      image/bg/company_setting_logo.png
  19. BIN
      image/bg/delete.png
  20. BIN
      image/bg/department_setting_logo.png
  21. BIN
      image/bg/download.png
  22. BIN
      image/bg/equipment_setting_logo.png
  23. BIN
      image/bg/gj_001_1_20.png
  24. BIN
      image/bg/gj_001_21_40.png
  25. BIN
      image/bg/gj_001_41_60.png
  26. BIN
      image/bg/green_dot.png
  27. BIN
      image/bg/grey_dot.png
  28. BIN
      image/bg/icon.png
  29. BIN
      image/bg/inductance_logo.png
  30. BIN
      image/bg/insulation_logo.png
  31. BIN
      image/bg/login.png
  32. BIN
      image/bg/logo.png
  33. BIN
      image/bg/logoff.png
  34. BIN
      image/bg/menu_data_analysis.png
  35. BIN
      image/bg/menu_data_preprocess.png
  36. BIN
      image/bg/menu_file.png
  37. BIN
      image/bg/menu_setting.png
  38. BIN
      image/bg/min_bt.png
  39. BIN
      image/bg/ng_bg.png
  40. BIN
      image/bg/ok_bg.png
  41. BIN
      image/bg/open_file.png
  42. BIN
      image/bg/refresh.png
  43. BIN
      image/bg/reset_logo.png
  44. BIN
      image/bg/resistance_logo.png
  45. BIN
      image/bg/save_bg.png
  46. BIN
      image/bg/scan_barcode.png
  47. BIN
      image/bg/tree_folder_icon.png
  48. BIN
      image/bg/tree_leaf_icon.png
  49. BIN
      image/bg/user.png
  50. BIN
      image/bg/vertical_line.png
  51. BIN
      image/bg/zoom_in.png
  52. BIN
      image/bg/zoom_out.png
  53. BIN
      image/close_bt.png
  54. 0 0
      image/cmd.txt
  55. BIN
      image/icon.ico
  56. BIN
      image/info_bt.png
  57. BIN
      image/min_bt.png
  58. BIN
      lib/commons-codec-1.15.jar
  59. BIN
      lib/core-3.5.1.jar
  60. BIN
      lib/fastjson2-2.0.16.jar
  61. BIN
      lib/gson-2.10.jar
  62. BIN
      lib/iot-communication-1.4.4.jar
  63. BIN
      lib/jSerialComm-2.6.2.jar
  64. BIN
      lib/javase-3.5.1.jar
  65. BIN
      lib/jfreechart-1.5.4.jar
  66. BIN
      lib/jshortcut-0.4-oberzalek.jar
  67. BIN
      lib/kotlin-stdlib-1.8.10.jar
  68. BIN
      lib/logback-classic-1.2.13.jar
  69. BIN
      lib/logback-core-1.2.13.jar
  70. BIN
      lib/netty-all-4.1.48.Final.jar
  71. BIN
      lib/okhttp-4.10.0.jar
  72. BIN
      lib/okio-jvm-3.3.0.jar
  73. BIN
      lib/s7connector-2.1.jar
  74. BIN
      lib/slf4j-api-1.7.36.jar
  75. BIN
      lib/sqlite-jdbc-3.36.0.3.jar
  76. 10 0
      src/com/mes/component/CallFromJs.java
  77. 57 0
      src/com/mes/component/MesRadio.java
  78. 44 0
      src/com/mes/component/MesWebView.java
  79. 30 0
      src/com/mes/component/MyDialog.java
  80. 90 0
      src/com/mes/netty/MesMsgUtils.java
  81. 63 0
      src/com/mes/netty/NettyClient.java
  82. 82 0
      src/com/mes/netty/NettyClientHandler.java
  83. 73 0
      src/com/mes/netty/ProtocolParam.java
  84. 168 0
      src/com/mes/netty/XDecoder.java
  85. 58 0
      src/com/mes/ui/BindMaterialResp.java
  86. 15 0
      src/com/mes/ui/CenterRenderer.java
  87. 317 0
      src/com/mes/ui/ConfigParam.java
  88. 459 0
      src/com/mes/ui/DataUtil.java
  89. 85 0
      src/com/mes/ui/LockUtil.java
  90. 241 0
      src/com/mes/ui/LoginFarme.java
  91. 2336 0
      src/com/mes/ui/MesClient.java
  92. 95 0
      src/com/mes/ui/MesRevice.java
  93. 61 0
      src/com/mes/ui/OprnoUtil.java
  94. 43 0
      src/com/mes/ui/TableCellEditorButton.java
  95. 14 0
      src/com/mes/ui/TableCellRendererButton.java
  96. 347 0
      src/com/mes/util/ATEQ.java
  97. 348 0
      src/com/mes/util/ATEQ2.java
  98. 11 0
      src/com/mes/util/Base64Utils.java
  99. 63 0
      src/com/mes/util/CommonUtils.java
  100. 0 0
      src/com/mes/util/DataUtils.java

+ 24 - 0
.classpath

@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+		<attributes>
+			<attribute name="module" value="true"/>
+		</attributes>
+	</classpathentry>
+    <classpathentry kind="src" path="image"/>
+	<classpathentry excluding="resources/" kind="src" path="src"/>
+	<classpathentry kind="src" path="src/resources"/>
+	<classpathentry kind="output" path="bin"/>
+	<classpathentry kind="lib" path="lib/s7connector-2.1.jar"/>
+	<classpathentry kind="lib" path="lib/slf4j-api-2.0.6.jar"/>
+	<classpathentry kind="lib" path="lib/okhttp-4.10.0.jar"/>
+	<classpathentry kind="lib" path="lib/kotlin-stdlib-1.8.10.jar"/>
+	<classpathentry kind="lib" path="lib/okio-jvm-3.3.0.jar"/>
+	<classpathentry kind="lib" path="lib/gson-2.10.jar"/>
+	<classpathentry kind="lib" path="lib/jfreechart-1.5.4.jar"/>
+	<classpathentry kind="lib" path="lib/jshortcut-0.4-oberzalek.jar"/>
+	<classpathentry kind="lib" path="lib/netty-all-4.1.48.Final.jar"/>
+	<classpathentry kind="lib" path="lib/sqlite-jdbc-3.36.0.3.jar"/>
+	<classpathentry kind="lib" path="lib/commons-codec-1.15.jar"/>
+	<classpathentry kind="lib" path="lib/fastjson2-2.0.16.jar"/>
+</classpath>

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+.idea
+.settings
+classes
+bin
+out
+*.db
+*.iml

+ 0 - 0
.lock


+ 17 - 0
.project

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>mesclient-qm</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

+ 2 - 0
image/.gitignore

@@ -0,0 +1,2 @@
+META-INF
+_system~.ini

BIN
image/background.png


BIN
image/bg/a_side.png


BIN
image/bg/b_side.png


BIN
image/bg/bar_add.png


BIN
image/bg/bar_bookmark.png


BIN
image/bg/bar_cmd_go.png


BIN
image/bg/bar_edit.png


BIN
image/bg/bar_pause.png


BIN
image/bg/bar_sampling.png


BIN
image/bg/bar_setting.png


BIN
image/bg/bar_stop.png


BIN
image/bg/close_bt.png


BIN
image/bg/company_setting_logo.png


BIN
image/bg/delete.png


BIN
image/bg/department_setting_logo.png


BIN
image/bg/download.png


BIN
image/bg/equipment_setting_logo.png


BIN
image/bg/gj_001_1_20.png


BIN
image/bg/gj_001_21_40.png


BIN
image/bg/gj_001_41_60.png


BIN
image/bg/green_dot.png


BIN
image/bg/grey_dot.png


BIN
image/bg/icon.png


BIN
image/bg/inductance_logo.png


BIN
image/bg/insulation_logo.png


BIN
image/bg/login.png


BIN
image/bg/logo.png


BIN
image/bg/logoff.png


BIN
image/bg/menu_data_analysis.png


BIN
image/bg/menu_data_preprocess.png


BIN
image/bg/menu_file.png


BIN
image/bg/menu_setting.png


BIN
image/bg/min_bt.png


BIN
image/bg/ng_bg.png


BIN
image/bg/ok_bg.png


BIN
image/bg/open_file.png


BIN
image/bg/refresh.png


BIN
image/bg/reset_logo.png


BIN
image/bg/resistance_logo.png


BIN
image/bg/save_bg.png


BIN
image/bg/scan_barcode.png


BIN
image/bg/tree_folder_icon.png


BIN
image/bg/tree_leaf_icon.png


BIN
image/bg/user.png


BIN
image/bg/vertical_line.png


BIN
image/bg/zoom_in.png


BIN
image/bg/zoom_out.png


BIN
image/close_bt.png


+ 0 - 0
image/cmd.txt


BIN
image/icon.ico


BIN
image/info_bt.png


BIN
image/min_bt.png


BIN
lib/commons-codec-1.15.jar


BIN
lib/core-3.5.1.jar


BIN
lib/fastjson2-2.0.16.jar


BIN
lib/gson-2.10.jar


BIN
lib/iot-communication-1.4.4.jar


BIN
lib/jSerialComm-2.6.2.jar


BIN
lib/javase-3.5.1.jar


BIN
lib/jfreechart-1.5.4.jar


BIN
lib/jshortcut-0.4-oberzalek.jar


BIN
lib/kotlin-stdlib-1.8.10.jar


BIN
lib/logback-classic-1.2.13.jar


BIN
lib/logback-core-1.2.13.jar


BIN
lib/netty-all-4.1.48.Final.jar


BIN
lib/okhttp-4.10.0.jar


BIN
lib/okio-jvm-3.3.0.jar


BIN
lib/s7connector-2.1.jar


BIN
lib/slf4j-api-1.7.36.jar


BIN
lib/sqlite-jdbc-3.36.0.3.jar


+ 10 - 0
src/com/mes/component/CallFromJs.java

@@ -0,0 +1,10 @@
+package com.mes.component;
+
+import com.mes.ui.MesClient;
+
+public class CallFromJs {
+    public String callFromJs(String info){
+        System.out.print("ss:"+info);
+        return MesClient.sessionid+":java:" + info;
+    }
+}

+ 57 - 0
src/com/mes/component/MesRadio.java

@@ -0,0 +1,57 @@
+package com.mes.component;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class MesRadio extends JPanel {
+
+    private String result = "";
+    private Integer i = 0;
+
+    public MesRadio(String[] radioTitles,String[] radioVals){
+        this.setLayout(new FlowLayout());
+        ButtonGroup group = new ButtonGroup();
+        i = 0;
+        for (String title:radioTitles){
+            JRadioButton radioButton = new JRadioButton(title);
+            radioButton.setFont(new Font("微软雅黑", Font.PLAIN, 28));
+
+            String val = radioVals[i];
+            radioButton.setName(val);
+
+            this.add(radioButton);
+            group.add(radioButton);
+
+            radioButton.addActionListener(new ActionListener() {
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    result = val;
+                    System.out.println("选择:"+result);
+                }
+            });
+            i++;
+        }
+    }
+
+    public void setResult(String ret){
+        this.result = "";
+        Component[] components = this.getComponents();
+        for (Component jRadioButton:components){
+            if(jRadioButton instanceof JRadioButton){
+                JRadioButton jRadioButtonParam = (JRadioButton)jRadioButton;
+                if(ret.equals(jRadioButtonParam.getName())){
+                    jRadioButtonParam.setSelected(true);
+                    this.result = jRadioButtonParam.getName();
+                }else{
+                    jRadioButtonParam.setSelected(false);
+                }
+            }
+        }
+    }
+
+    public String getResult(){
+        return this.result;
+    }
+}

+ 44 - 0
src/com/mes/component/MesWebView.java

@@ -0,0 +1,44 @@
+package com.mes.component;
+
+import javafx.application.Platform;
+import javafx.beans.value.ObservableValue;
+import javafx.concurrent.Worker;
+import javafx.embed.swing.JFXPanel;
+import javafx.scene.Scene;
+import javafx.scene.web.WebEngine;
+import javafx.scene.web.WebView;
+import netscape.javascript.JSObject;
+
+import java.util.Date;
+
+public class MesWebView extends JFXPanel {
+
+    public static WebEngine engine = null;
+
+    public MesWebView(String url){
+
+        Platform.runLater(() -> {
+            WebView webView = new WebView();
+            setScene(new Scene(webView));
+            Date date = new Date();
+//            String url = "http://"+mes_server_ip+":8980/js/a/mes/mesQuality/check?__sid="+sessionid+"&oprno="+mes_gw+"&t="+date.getTime();
+            System.out.print(url);
+            engine = webView.getEngine();
+            CallFromJs bridge = new CallFromJs();
+            engine.getLoadWorker().stateProperty().addListener(
+                    (ObservableValue<? extends Worker.State> ov, Worker.State oldState, Worker.State newState) -> {
+                        if (newState == Worker.State.SUCCEEDED) {
+                            JSObject window = (JSObject) engine.executeScript("window");
+                            window.setMember("apps", bridge);
+                            window.setMember("sout", System.out);
+                        }
+                    }
+            );
+            engine.load(url);
+        });
+    }
+
+    public void reloadWeb(){
+        engine.reload();
+    }
+}

+ 30 - 0
src/com/mes/component/MyDialog.java

@@ -0,0 +1,30 @@
+package com.mes.component;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class MyDialog extends JDialog {
+
+    public MyDialog(Frame owner, String title, String msg){
+        super(owner, title);
+        init(msg);
+    }
+
+    private void init(String msg){
+        Container container = this.getContentPane();
+        container.setLayout(null);
+        container.setBackground(Color.BLACK);
+        this.setSize(800,220);
+        this.setLocationRelativeTo(null);
+
+        JLabel tslabel = new JLabel(msg);
+        tslabel.setHorizontalAlignment(SwingConstants.CENTER);
+        tslabel.setForeground(Color.RED);
+        tslabel.setFont(new Font("微软雅黑", Font.PLAIN,48));
+        tslabel.setBounds(0,30,800,100);
+
+        container.add(tslabel);
+        this.setModal(true);
+        this.setVisible(true);
+    }
+}

+ 90 - 0
src/com/mes/netty/MesMsgUtils.java

@@ -0,0 +1,90 @@
+package com.mes.netty;
+
+public class MesMsgUtils {
+
+    public static int SYNR_LEN = 46;
+    public static int AXTW_LEN = 46;
+    public static int ACLW_LEN = 46;
+    public static int MCJW_LEN = 96;
+    public static int AQDW_LEN = 96;
+    public static int MBDW_LEN = 96;
+    public static int MJBW_LEN = 96;
+    public static int MQDW_LEN = 96;
+    public static int MKSW_LEN = 96;
+    public static int MSBW_LEN = 96;
+    public static int MCSW_LEN = 96;
+    public static int AQRW_LEN = 96;
+
+    public static String MSG_TYPE[] = {
+        "SYNR",
+        "AXTW",
+        "ACLW",
+        "MCJW",
+        "AQDW",
+        "MBDW",
+        "MJBW",
+        "MQDW",
+        "MKSW",
+        "MSBW",
+        "MCSW",
+        "AQRW",
+    };
+
+    public static int isMsgContentOK(String msg, String msg_type) {
+        //ret=0OK,1 空内容,2 长度不符
+        int ret = 0;
+        if(msg==null||msg.equalsIgnoreCase("")) {
+            ret = 1;
+            return ret;
+        }
+
+        int len = msg.length();
+        //System.out.println("len="+len);
+        switch(msg_type) {
+            case "SYNR":
+            case "AXTW":
+            case "ACLW":
+                if(len==SYNR_LEN) {
+                    ret = 0;
+                }else {
+                    ret = 2;
+                }
+                break;
+            default:
+                if(len==AQDW_LEN) {
+                    ret = 0;
+                }else {
+                    ret = 2;
+                }
+                break;
+        }
+        return ret;
+    }
+
+    // 判断报文类型是否在清单里
+    public static boolean isMsgTypeOk(String msg_type) {
+        for (String str : MSG_TYPE) {
+            if (str.equals(msg_type)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // 处理报文数据
+    public static String processMsg(String msg, String msg_type) {
+        String processMsgRet = "";
+        if(msg_type.equalsIgnoreCase("SYNR")) {
+
+        }else if(msg_type.equalsIgnoreCase("AXTW")) {
+
+        }else if(msg_type.equalsIgnoreCase("ACLW")) {
+
+        }else{
+            processMsgRet = ProtocolParam.getResult(msg);
+        }
+        return processMsgRet;
+    }
+
+
+}

+ 63 - 0
src/com/mes/netty/NettyClient.java

@@ -0,0 +1,63 @@
+package com.mes.netty;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.string.StringEncoder;
+import java.util.concurrent.TimeUnit;
+
+import com.mes.ui.MesClient;
+
+public class NettyClient {
+    public SocketChannel socketChannel;
+    public static ChannelFuture future;
+
+    public  void run(Object msg){
+        //配置线程组
+        EventLoopGroup group = new NioEventLoopGroup();
+        //创建服务启动器
+        Bootstrap bootstrap = new Bootstrap();
+
+        //配置参数
+        bootstrap.group(group)
+                .channel(NioSocketChannel.class)
+                .option(ChannelOption.TCP_NODELAY,true)
+                .handler(new ChannelInitializer<SocketChannel>() {
+                    protected void initChannel(SocketChannel socketChannel) throws Exception {
+                        socketChannel.pipeline()
+                                .addLast(new XDecoder())
+                                .addLast(new StringEncoder())
+//                                    .addLast(new StringDecoder())
+                                .addLast(new NettyClientHandler());
+                    }
+                })
+                .remoteAddress(MesClient.mes_server_ip,MesClient.mes_tcp_port);
+
+        //连接
+        future = bootstrap.connect();
+        System.out.println("客户端正在连接服务端...");
+        //客户端断线重连逻辑
+        future.addListener((ChannelFutureListener) future1 -> {
+            if (future1.isSuccess()) {
+                //tcp连接成功
+                MesClient.tcp_connect_flag = true;
+                //设置TCP请求状态
+                MesClient.connect_request_flag = false;
+                System.out.println("连接Netty服务端成功");
+                future.channel().writeAndFlush(msg);
+            } else {
+                //tcp连接失败
+                MesClient.tcp_connect_flag = false;
+                MesClient.connect_request_flag = true;
+                System.out.println("连接失败,进行断线重连");
+                future1.channel().eventLoop().schedule(() -> run(msg), 10, TimeUnit.SECONDS);
+            }
+            //设置tcp连接状态
+            MesClient.setTcpStatus();
+        });
+        socketChannel = (SocketChannel) future.channel();
+
+    }
+}

+ 82 - 0
src/com/mes/netty/NettyClientHandler.java

@@ -0,0 +1,82 @@
+package com.mes.netty;
+
+import com.mes.ui.MesClient;
+import com.mes.ui.MesRevice;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class NettyClientHandler extends ChannelInboundHandlerAdapter {
+
+    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    public static byte[] responseByte;
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        System.out.println("mes connecting:" + sdf.format(new Date()));
+    }
+
+    @Override
+    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+        Channel channel = ctx.channel();
+        System.err.println("close tcp, ip:" + channel.remoteAddress());
+        MesClient.tcp_connect_flag = false;
+        MesClient.setTcpStatus();
+        // 关闭通道
+        channel.close();
+    }
+
+    @Override
+    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+        System.out.println("msg:"+msg);
+
+        String mes_msg = formatResult(msg.toString());
+        if(mes_msg == null || mes_msg.isEmpty()){ // error msg
+            return;
+        }
+
+        String msg_type = ProtocolParam.getMsgType(mes_msg);
+        System.out.println("msg_type="+msg_type);
+
+        String processMsgRet = MesMsgUtils.processMsg(mes_msg, msg_type);
+        System.out.println("processMsgRet="+processMsgRet);
+        switch(msg_type) {
+            case "AQDW": // 查询质量
+                MesRevice.checkQualityRevice(processMsgRet,mes_msg);
+                break;
+            case "MKSW":
+                MesRevice.startRevice(processMsgRet,mes_msg);
+                break;
+            case "MBDW":
+                MesRevice.bindRevice(processMsgRet,mes_msg);
+                break;
+            case "MJBW":
+                MesRevice.unbindRevice(processMsgRet,mes_msg);
+                break;
+            case "MQDW":
+                MesRevice.updateResultRevice(processMsgRet,mes_msg);
+                break;
+        }
+
+
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        ctx.close();
+    }
+
+    private String formatResult(String msg){
+        System.err.println("length:" + msg.length() + " content:" + msg);
+        String msgType = msg.substring(0,2).trim();
+        if(msgType.equals("OK")){
+            return msg.substring(3,msg.length());
+        }else{
+            return "";
+        }
+    }
+
+}

+ 73 - 0
src/com/mes/netty/ProtocolParam.java

@@ -0,0 +1,73 @@
+package com.mes.netty;
+
+
+// 固定格式报文各参数获取方法
+public class ProtocolParam {
+    // bbbbfffffARWAQDWGWOP100 GY100000ID151245P00000106200123062900001      RSOKDA2023-09-07ZT10:16:58
+    public static Integer fixedLength = 96; // 固定长度
+
+    // 获取消息类型  所有报文都可使用
+    public static String getMsgType(String msg){
+        System.out.print(msg);
+        if(msg.length() < 16){
+            return "";
+        }
+        return msg.substring(12,16);
+    }
+
+    // 获取工位号
+    public static String getOprno(String msg){
+        if(msg.length() < 24){
+            return "";
+        }
+        return msg.substring(18,24);
+    }
+
+    // 获取工艺号
+    public static String getCraft(String msg){
+        if(msg.length() < 32){
+            return "";
+        }
+        return msg.substring(26,32);
+    }
+
+    // 获取镭雕码或设备报警故障代码
+    public static String getSn(String msg){
+        if(msg.length() < 70){
+            return "";
+        }
+        return msg.substring(34,70);
+    }
+
+    public static String getLx(String msg){
+        if(msg.length() < 72){
+            return "";
+        }
+        return msg.substring(70,72);
+    }
+
+    // 获取结果
+    public static String getResult(String msg){
+        if(msg.length() < 74){
+            return "";
+        }
+        return msg.substring(72,74);
+    }
+
+    // 获取日期
+    public static String getDay(String msg){
+        if(msg.length() < 86){
+            return "";
+        }
+        return msg.substring(76,86);
+    }
+
+    // 获取时间
+    public static String getTime(String msg){
+        if(msg.length() < 96){
+            return "";
+        }
+        return msg.substring(88,96);
+    }
+
+}

+ 168 - 0
src/com/mes/netty/XDecoder.java

@@ -0,0 +1,168 @@
+package com.mes.netty;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
+import java.util.List;
+
+public class XDecoder extends ByteToMessageDecoder {
+    static final int PACKET_SIZE = 46; // 最短包长度
+    static final int PACKET_MAX_SIZE = 1000; // 最长包长度
+
+    // 用来临时保留没有处理过的请求报文
+    ByteBuf tempMsg = Unpooled.buffer();
+
+    /**
+     * @param ctx
+     * @param in 请求的数据
+     * @param out 将粘在一起的报文拆分后的结果保留起来
+     * @throws Exception
+     */
+    @Override
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        System.out.println(Thread.currentThread() + "收到了一次数据包,长度是:" + in.readableBytes());
+        String content = hexStringToAscii(ByteBufUtil.hexDump(in));
+        System.out.println("接收包内容:" + hexStringToAscii(ByteBufUtil.hexDump(in)));
+
+        // 合并报文
+        ByteBuf message = null;
+        int tmpMsgSize = tempMsg.readableBytes();
+        // 如果暂存有上一次余下的请求报文,则合并
+        if (tmpMsgSize > 0) {
+            message = Unpooled.buffer();
+            message.writeBytes(tempMsg);
+            message.writeBytes(in);
+            System.out.println("合并:上一数据包余下的长度为:" + tmpMsgSize + ",合并后长度为:" + message.readableBytes());
+            System.out.println("合并后包内容:" + hexStringToAscii(ByteBufUtil.hexDump(message)));
+        } else {
+            message = in;
+        }
+
+//        System.out.println(Thread.currentThread() + "收到了一次数据包,长度是:" + message.readableBytes());
+        int size = 0;
+        String split = "bbbbfffffARW";
+
+        while (true){
+            size = message.readableBytes();
+            if(size >= PACKET_SIZE){
+                String retType = "NG:";
+                int qcsize = 0;
+                String str = hexStringToAscii(ByteBufUtil.hexDump(message));
+                String[] lists = str.split(split);
+
+                if(lists.length == 1 && size > PACKET_MAX_SIZE){ // 大于最大包长度
+                    byte[] request = new byte[size - PACKET_MAX_SIZE];
+                    // 每次从总的消息中读取n个字节的数据
+                    message.readBytes(request);
+                    // 将拆分后的结果放入out列表中,交由后面的业务逻辑去处理
+                    out.add(retType+hexStringToAscii(ByteBufUtil.hexDump(Unpooled.copiedBuffer(request))));
+                    break;
+                }
+
+                if(lists[0].length() > 0){
+                    byte[] request = new byte[lists[0].length()];
+                    // 每次从总的消息中读取n个字节的数据
+                    message.readBytes(request);
+                    // 将拆分后的结果放入out列表中,交由后面的业务逻辑去处理
+                    out.add(retType+hexStringToAscii(ByteBufUtil.hexDump(Unpooled.copiedBuffer(request))));
+                }else{
+                    if(lists.length > 1){
+                        String ss = lists[1];
+                        if(ss.length() <= 4){
+                            qcsize += ss.length();
+                        }else{
+                            String msgType = ProtocolParam.getMsgType(split+ss);
+                            if(!MesMsgUtils.isMsgTypeOk(msgType)){
+                                qcsize += split.length() + ss.length();
+                            }else{
+                                Integer ppsize = checkResultSize(ss,msgType,split);
+                                if(ppsize > 0){
+                                    qcsize = ppsize;
+                                    retType = "OK:";
+                                }else{
+                                    qcsize += split.length() + ss.length();
+                                }
+                            }
+                        }
+                    }
+                }
+
+
+                if(qcsize > 0){
+                    byte[] request = new byte[qcsize];
+                    // 每次从总的消息中读取n个字节的数据
+                    message.readBytes(request);
+                    // 将拆分后的结果放入out列表中,交由后面的业务逻辑去处理
+                    out.add(retType+hexStringToAscii(ByteBufUtil.hexDump(Unpooled.copiedBuffer(request))));
+                }
+            }else{
+                break;
+            }
+        }
+
+        // 多余的报文存起来
+        // 第一个报文: i+  暂存
+        // 第二个报文: 1 与第一次
+        size = message.readableBytes();
+        if (size != 0) {
+            System.out.println("多余的数据长度:" + size);
+            // 剩下来的数据放到tempMsg暂存
+            tempMsg.clear();
+            tempMsg.writeBytes(message.readBytes(size));
+        }
+    }
+
+    private Integer checkResultSize(String str, String msg_type, String split){
+        String oldstr = str;
+        str = split+str;
+        int tpsize = 0;
+        switch(msg_type) {
+            case "SYNR": // 同步
+                if(str.length() >= MesMsgUtils.SYNR_LEN){
+                    tpsize = MesMsgUtils.SYNR_LEN;
+                }
+                break;
+            case "AXTW": // 心跳
+                if(str.length() >= MesMsgUtils.AXTW_LEN){
+                    tpsize = MesMsgUtils.AXTW_LEN;
+                }
+                break;
+            case "ACLW": // 重连
+                if(str.length() >= MesMsgUtils.ACLW_LEN){
+                    tpsize = MesMsgUtils.ACLW_LEN;
+                }
+                break;
+            case "MCJW":
+            case "AQDW":
+            case "MBDW":
+            case "MJBW":
+            case "MQDW":
+            case "MKSW":
+            case "MSBW":
+            case "MCSW":
+            case "AQRW":
+            default: // 默认新报文
+                if(str.length() >= ProtocolParam.fixedLength){ // 大于固定长度
+                    tpsize = ProtocolParam.fixedLength;
+                }
+                break;
+        }
+
+        return tpsize;
+    }
+
+    // 16字符串转Ascii
+    private String hexStringToAscii(String hexString) {
+        StringBuilder sbuilder = new StringBuilder();
+        for (int i = 0; i < hexString.length(); i += 2) {
+            String hexByte = hexString.substring(i, i + 2);
+            int byteValue = Integer.parseInt(hexByte, 16);
+            char c = (char) byteValue;
+            sbuilder.append(c);
+        }
+        return sbuilder.toString();
+    }
+}

+ 58 - 0
src/com/mes/ui/BindMaterialResp.java

@@ -0,0 +1,58 @@
+package com.mes.ui;
+
+public class BindMaterialResp {
+    private String materialId;
+    private String materialTitle;
+    private String craft;
+    private String batchSn;
+    private String lastTimes;
+    private String type;
+
+    public String getMaterialId() {
+        return materialId;
+    }
+
+    public void setMaterialId(String materialId) {
+        this.materialId = materialId;
+    }
+
+    public String getMaterialTitle() {
+        return materialTitle;
+    }
+
+    public void setMaterialTitle(String materialTitle) {
+        this.materialTitle = materialTitle;
+    }
+
+    public String getCraft() {
+        return craft;
+    }
+
+    public void setCraft(String craft) {
+        this.craft = craft;
+    }
+
+    public String getBatchSn() {
+        return batchSn;
+    }
+
+    public void setBatchSn(String batchSn) {
+        this.batchSn = batchSn;
+    }
+
+    public String getLastTimes() {
+        return lastTimes;
+    }
+
+    public void setLastTimes(String lastTimes) {
+        this.lastTimes = lastTimes;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+}

+ 15 - 0
src/com/mes/ui/CenterRenderer.java

@@ -0,0 +1,15 @@
+package com.mes.ui;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
+import java.awt.*;
+
+public class CenterRenderer extends DefaultTableCellRenderer {
+    public Component getTableCellRendererComponent(JTable table,Object value,
+                                                   boolean isSelected, boolean hasFocus,
+                                                   int row, int column){
+        JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+        label.setHorizontalAlignment(JLabel.CENTER); // 设置水平对齐方式为居中
+        return label;
+    }
+}

+ 317 - 0
src/com/mes/ui/ConfigParam.java

@@ -0,0 +1,317 @@
+package com.mes.ui;
+
+public class ConfigParam {
+	public Integer id;
+	public String programNo;
+	public String serialPort;
+	public String baudRate;
+	public String dataBits;
+	public String checkBit;
+	public String stopBit;
+	public String leakage;
+	public String oprnoTitle;
+	public String oprno;
+	public String modbusSite;
+	public String programNo2;
+	public String serialPort2;
+	public String baudRate2;
+	public String dataBits2;
+	public String checkBit2;
+	public String stopBit2;
+	public String leakage2;
+	public String oprnoTitle2;
+	public String oprno2;
+	public String modbusSite2;
+	public String printLabel;
+	public String printName;
+	public String labelName;
+	public String labelx;
+	public String labely;
+	public String labelLineSpace;
+	public String labelFont;
+	public String lineSn;
+	public String device;
+	public String device2;
+
+	public Integer getId() {
+		return id;
+	}
+
+	public void setId(Integer id) {
+		this.id = id;
+	}
+
+	public String getProgramNo() {
+		return programNo;
+	}
+
+	public void setProgramNo(String programNo) {
+		this.programNo = programNo;
+	}
+
+	public String getSerialPort() {
+		return serialPort;
+	}
+
+	public void setSerialPort(String serialPort) {
+		this.serialPort = serialPort;
+	}
+
+	public String getBaudRate() {
+		return baudRate;
+	}
+
+	public void setBaudRate(String baudRate) {
+		this.baudRate = baudRate;
+	}
+
+	public String getDataBits() {
+		return dataBits;
+	}
+
+	public void setDataBits(String dataBits) {
+		this.dataBits = dataBits;
+	}
+
+	public String getCheckBit() {
+		return checkBit;
+	}
+
+	public void setCheckBit(String checkBit) {
+		this.checkBit = checkBit;
+	}
+
+	public String getStopBit() {
+		return stopBit;
+	}
+
+	public void setStopBit(String stopBit) {
+		this.stopBit = stopBit;
+	}
+
+	public String getLeakage() {
+		return leakage;
+	}
+
+	public void setLeakage(String leakage) {
+		this.leakage = leakage;
+	}
+
+	public String getProgramNo2() {
+		return programNo2;
+	}
+
+	public void setProgramNo2(String programNo2) {
+		this.programNo2 = programNo2;
+	}
+
+	public String getSerialPort2() {
+		return serialPort2;
+	}
+
+	public void setSerialPort2(String serialPort2) {
+		this.serialPort2 = serialPort2;
+	}
+
+	public String getBaudRate2() {
+		return baudRate2;
+	}
+
+	public void setBaudRate2(String baudRate2) {
+		this.baudRate2 = baudRate2;
+	}
+
+	public String getDataBits2() {
+		return dataBits2;
+	}
+
+	public void setDataBits2(String dataBits2) {
+		this.dataBits2 = dataBits2;
+	}
+
+	public String getCheckBit2() {
+		return checkBit2;
+	}
+
+	public void setCheckBit2(String checkBit2) {
+		this.checkBit2 = checkBit2;
+	}
+
+	public String getStopBit2() {
+		return stopBit2;
+	}
+
+	public void setStopBit2(String stopBit2) {
+		this.stopBit2 = stopBit2;
+	}
+
+	public String getLeakage2() {
+		return leakage2;
+	}
+
+	public void setLeakage2(String leakage2) {
+		this.leakage2 = leakage2;
+	}
+
+	public String getPrintLabel() {
+		return printLabel;
+	}
+
+	public void setPrintLabel(String printLabel) {
+		this.printLabel = printLabel;
+	}
+
+	public String getPrintName() {
+		return printName;
+	}
+
+	public void setPrintName(String printName) {
+		this.printName = printName;
+	}
+
+	public String getLabelName() {
+		return labelName;
+	}
+
+	public void setLabelName(String labelName) {
+		this.labelName = labelName;
+	}
+
+	public String getLabelx() {
+		return labelx;
+	}
+
+	public void setLabelx(String labelx) {
+		this.labelx = labelx;
+	}
+
+	public String getLabely() {
+		return labely;
+	}
+
+	public void setLabely(String labely) {
+		this.labely = labely;
+	}
+
+	public String getLabelLineSpace() {
+		return labelLineSpace;
+	}
+
+	public void setLabelLineSpace(String labelLineSpace) {
+		this.labelLineSpace = labelLineSpace;
+	}
+
+	public String getLabelFont() {
+		return labelFont;
+	}
+
+	public void setLabelFont(String labelFont) {
+		this.labelFont = labelFont;
+	}
+
+	public String getOprnoTitle() {
+		return oprnoTitle;
+	}
+
+	public void setOprnoTitle(String oprnoTitle) {
+		this.oprnoTitle = oprnoTitle;
+	}
+
+	public String getOprno() {
+		return oprno;
+	}
+
+	public void setOprno(String oprno) {
+		this.oprno = oprno;
+	}
+
+	public String getOprnoTitle2() {
+		return oprnoTitle2;
+	}
+
+	public void setOprnoTitle2(String oprnoTitle2) {
+		this.oprnoTitle2 = oprnoTitle2;
+	}
+
+	public String getModbusSite() {
+		return modbusSite;
+	}
+
+	public void setModbusSite(String modbusSite) {
+		this.modbusSite = modbusSite;
+	}
+
+	public String getOprno2() {
+		return oprno2;
+	}
+
+	public void setOprno2(String oprno2) {
+		this.oprno2 = oprno2;
+	}
+
+	public String getModbusSite2() {
+		return modbusSite2;
+	}
+
+	public void setModbusSite2(String modbusSite2) {
+		this.modbusSite2 = modbusSite2;
+	}
+
+	public String getLineSn() {
+		return lineSn;
+	}
+
+	public void setLineSn(String lineSn) {
+		this.lineSn = lineSn;
+	}
+
+	public String getDevice() {
+		return device;
+	}
+
+	public void setDevice(String device) {
+		this.device = device;
+	}
+
+	public String getDevice2() {
+		return device2;
+	}
+
+	public void setDevice2(String device2) {
+		this.device2 = device2;
+	}
+
+	@Override
+	public String toString() {
+		return "ConfigParam{" +
+				"id=" + id +
+				", programNo='" + programNo + '\'' +
+				", serialPort='" + serialPort + '\'' +
+				", baudRate='" + baudRate + '\'' +
+				", dataBits='" + dataBits + '\'' +
+				", checkBit='" + checkBit + '\'' +
+				", stopBit='" + stopBit + '\'' +
+				", leakage='" + leakage + '\'' +
+				", oprnoTitle='" + oprnoTitle + '\'' +
+				", oprno='" + oprno + '\'' +
+				", modbusSite='" + modbusSite + '\'' +
+				", programNo2='" + programNo2 + '\'' +
+				", serialPort2='" + serialPort2 + '\'' +
+				", baudRate2='" + baudRate2 + '\'' +
+				", dataBits2='" + dataBits2 + '\'' +
+				", checkBit2='" + checkBit2 + '\'' +
+				", stopBit2='" + stopBit2 + '\'' +
+				", leakage2='" + leakage2 + '\'' +
+				", oprnoTitle2='" + oprnoTitle2 + '\'' +
+				", oprno2='" + oprno2 + '\'' +
+				", modbusSite2='" + modbusSite2 + '\'' +
+				", printLabel='" + printLabel + '\'' +
+				", printName='" + printName + '\'' +
+				", labelName='" + labelName + '\'' +
+				", labelx='" + labelx + '\'' +
+				", labely='" + labely + '\'' +
+				", labelLineSpace='" + labelLineSpace + '\'' +
+				", labelFont='" + labelFont + '\'' +
+				'}';
+	}
+}

+ 459 - 0
src/com/mes/ui/DataUtil.java

@@ -0,0 +1,459 @@
+package com.mes.ui;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.mes.netty.NettyClient;
+import com.mes.util.*;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Properties;
+
+
+public class DataUtil {
+
+    public static Boolean synrTcp(NettyClient nettyClient,String mes_gw){
+        try{
+            //TCP连接后,直接先发同步报文
+            String start = "aaaabbbbbABW";
+            String msgType = "SYNR";
+            String gw = "GW"+DataUtil.rightPad(mes_gw, 6);
+            String da = "DA" + DateLocalUtils.getCurrentDate();
+            String zt = "ZT" + DateLocalUtils.getCurrentTimeHMS();
+            String synr_str = start + msgType + gw + da + zt;
+            //插入报文本地数据
+            String gy = "";
+            String sn = "";
+            JdbcUtils.insertData(gw, gy, synr_str, msgType, sn);
+
+            nettyClient.run(synr_str);
+
+            return true;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean heartBeat(NettyClient nettyClient,String mes_gw){
+        try{
+            //TCP连接后,直接先发同步报文
+            String start = "aaaabbbbbABW";
+            String msgType = "AXTW";
+            String gw = "GW"+DataUtil.rightPad(mes_gw, 6);
+            String da = "DA" + DateLocalUtils.getCurrentDate();
+            String zt = "ZT" + DateLocalUtils.getCurrentTimeHMS();
+            String axtw_str = start + msgType + gw + da + zt;
+            //插入报文本地数据
+            String gy = "";
+            String sn = "";
+            JdbcUtils.insertData(gw, gy, axtw_str, msgType, sn);
+            nettyClient.future.channel().writeAndFlush(axtw_str);
+
+            return true;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean checkQuality(NettyClient nettyClient, String sn, String user){
+        try{
+            String msgType = "AQDW";
+            String gy = "100000";
+            Boolean aqdw_str = sendMessage(nettyClient,msgType,gy,"",sn,"",user,"00","");
+            return aqdw_str;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean startWork(NettyClient nettyClient,String sn,String user){
+        try{
+            String msgType = "MKSW";
+            String gy = "";
+            Boolean aqdw_str = sendMessage(nettyClient,msgType,gy,"",sn,"",user,"00","");
+            return aqdw_str;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean bindUser(NettyClient nettyClient,String sn,String user){
+        try{
+            String msgType = "MBDW";
+            String gy = "400001";
+            String param = rightPad(user, 36);
+            Boolean aqdw_str = sendMessage(nettyClient,msgType,gy,"",sn,"",user,"01",param);
+            return aqdw_str;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean bindWarehouse(NettyClient nettyClient,String sn,String wsn,String user,String craft){
+        try{
+            String msgType = "MBDW";
+            String param = rightPad(wsn, 36);
+            Boolean aqdw_str = sendMessage(nettyClient,msgType,craft,"",sn,"",user,"01",param);
+            return aqdw_str;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean unBindWarehouse(NettyClient nettyClient,String sn,String wsn,String user,String craft){
+        try{
+            String msgType = "MJBW";
+            String param = rightPad(wsn, 36);
+            Boolean aqdw_str = sendMessage(nettyClient,msgType,craft,"",sn,"",user,"01",param);
+            return aqdw_str;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean sendQuality(NettyClient nettyClient,String sn,String ret,String user){
+        try{
+            String msgType = "MQDW";
+            String gy = "100000";
+            String param = "";
+            Boolean aqdw_str = sendMessage(nettyClient,msgType,gy,"",sn,ret,user,"00",param);
+            return aqdw_str;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static Boolean sendQualityNew(NettyClient nettyClient,String sn,String ret,String user){
+        try{
+            String msgType = "MQDW";
+            String craft = "100000";
+            String params = "";
+            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 start = "aaaabbbbbABW";
+            String gy = "GY" + rightPad(craft, 6);
+            String reslx = "LX" + rightPad("", 2);
+            String id = pro.getProperty("mes.line_sn") + rightPad(sn, 36);
+            String rs = "RS"+ rightPad(ret, 2);
+            String da = "DA" + DateLocalUtils.getCurrentDate();
+            String zt = "ZT" + DateLocalUtils.getCurrentTimeHMS();
+            String yh = "YH" + rightPad(user, 20);
+            String aqdw_str = start + msgType + gw + gy + reslx + id + rs + da + zt + yh + "00" + params;
+            System.out.println("message="+aqdw_str);
+            JdbcUtils.insertSubmitRecord(gw, sn, aqdw_str);
+            return true;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    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 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 rs = "RS"+ rightPad(result, 2);
+            String da = "DA" + DateLocalUtils.getCurrentDate();
+            String zt = "ZT" + DateLocalUtils.getCurrentTimeHMS();
+            String yh = "YH" + rightPad(user, 20);
+            String aqdw_str = start + msgType + gw + gy + reslx + id + rs + da + zt + yh + paramNums + params;
+            System.out.println("message="+aqdw_str);
+            JdbcUtils.insertData(gw, gy, aqdw_str, msgType, sn);
+            nettyClient.future.channel().writeAndFlush(aqdw_str);
+            return true;
+        }catch (Exception e){
+            return false;
+        }
+    }
+
+    public static String rightPad(final String str, final int size) {
+        if (str == null) {
+            return null;
+        }
+
+        String strret = str;
+        if(str.length() > size){
+            strret = str.substring(0,size);
+        }
+        return String.format("%-"+size+"s", strret);
+    }
+
+    // 检查工件质量
+    public static JSONObject qmcheck(String sn,String craft) {
+        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 url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductRecord/qmcheck";
+            String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn+"&craft="+craft+"&sn="+sn;
+            System.out.println("params="+params);
+            String result = doPost(url,params);
+            System.out.println("result="+result);
+
+            if(result.equalsIgnoreCase("false")) {
+                return null;
+            }else {
+                return JSONObject.parseObject(result);
+            }
+        }catch (Exception e){
+            return null;
+        }
+    }
+
+    // 检查工件质量
+    public static JSONObject qmresult(String craft, TestParam testParam) {
+        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 oprno = testParam.getOprno();
+            String lineSn = pro.getProperty("mes.line_sn").trim();
+            String url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductRecord/qmresult";
+            String params = "__ajax=json&oprno="+oprno+
+                    "&lineSn="+lineSn+
+                    "&craft="+craft+
+                    "&sn="+testParam.getSn()+
+                    "&workNum="+testParam.getUcode()+
+                    "&cxm="+testParam.getProgramNo()+
+                    "&result="+testParam.getResult()+
+                    "&testPressure=" +DataUtils.getBase64Encode(testParam.getPressure())+
+                    "&testPressureUnit="+testParam.getPressureUnit() +
+                    "&leakVal="+DataUtils.getBase64Encode(testParam.getLeak())+
+                    "&leakValUnit="+testParam.getLeakUnit() +
+                    "&testTime="+ DataUtils.getBase64Encode(testParam.getCreateTime())+
+                    "&title="+DataUtils.getBase64Encode(testParam.getOprnoTitle()) +
+                    "&remark="+testParam.getRemark() +
+                    "&deviceType="+URLEncoder.encode(testParam.getDeviceType() != null ? testParam.getDeviceType() : "", "UTF-8")
+                    +"&cq="+ URLEncoder.encode("", "UTF-8")
+                    +"&by="+URLEncoder.encode("", "UTF-8")
+                    +"&cs="+URLEncoder.encode("", "UTF-8")
+                    +"&leakRate="+URLEncoder.encode("", "UTF-8")
+                    +"&leakRateUnit="+URLEncoder.encode("", "UTF-8")
+                    +"&type="+URLEncoder.encode("", "UTF-8");
+            System.out.println("params="+params);
+            String result = doPost(url,params);
+            System.out.println("result="+result);
+
+            if(result.equalsIgnoreCase("false")) {
+                return null;
+            }else {
+                return JSONObject.parseObject(result);
+            }
+        }catch (Exception e){
+            return null;
+        }
+    }
+
+
+
+// 上传气密结果
+public static JSONObject qmResultData(TestParam testParam) {
+    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 url = "http://"+mes_server_ip+":8980/js/a/mes/mesProductRecord/qmresult";
+        // 根据服务器端代码,对特定参数进行Base64编码
+        String testPressureBase64 = Base64Utils.getBase64(testParam.getPressure() != null ? testParam.getPressure() : "");
+        String leakValBase64 = Base64Utils.getBase64(testParam.getLeak() != null ? testParam.getLeak() : "");
+        String testTimeBase64 = Base64Utils.getBase64(testParam.getCreateTime() != null ? testParam.getCreateTime() : "");
+        String titleBase64 = Base64Utils.getBase64(testParam.getOprnoTitle() != null ? testParam.getOprnoTitle() : "");
+        // 注意:sn(序列号)和workNum(测试人员)不应该Base64编码
+
+//        System.out.println();("服务器端需要Base64编码的参数: testPressure='{}'->'{}', leakVal='{}'->'{}', testTime='{}'->'{}', title='{}'->'{}'"
+//                , testParam.getTestPressure(), testPressureBase64, testParam.getLeakVal(), leakValBase64
+//                , testParam.getCreateTime(), testTimeBase64, testParam.getOprnoTitle(), titleBase64);
+
+        String params = "__ajax=json&oprno="+URLEncoder.encode(testParam.getOprno() != null ? testParam.getOprno() : "", "UTF-8")
+                +"&lineSn="+URLEncoder.encode(testParam.getLineSn() != null ? testParam.getLineSn() : "", "UTF-8")
+                +"&sn="+URLEncoder.encode(testParam.getSn() != null ? testParam.getSn() : "", "UTF-8")
+                +"&workNum="+URLEncoder.encode(testParam.getUcode() != null ? testParam.getUcode() : "", "UTF-8")
+                +"&cxm="+URLEncoder.encode(testParam.getProgramNo() != null ? testParam.getProgramNo() : "", "UTF-8")
+                +"&result="+URLEncoder.encode(testParam.getResult() != null ? testParam.getResult() : "", "UTF-8")
+                +"&testPressure="+URLEncoder.encode(testPressureBase64, "UTF-8")
+                +"&testPressureUnit="+URLEncoder.encode(testParam.getPressureUnit() != null ? testParam.getPressureUnit() : "", "UTF-8")
+                +"&leakVal="+URLEncoder.encode(leakValBase64, "UTF-8")
+                +"&leakValUnit="+URLEncoder.encode(testParam.getLeakUnit() != null ? testParam.getLeakUnit() : "", "UTF-8")
+                +"&testTime="+URLEncoder.encode(testTimeBase64, "UTF-8")
+                +"&title="+URLEncoder.encode(titleBase64, "UTF-8")
+                +"&remark="+URLEncoder.encode(testParam.getRemark() != null ? testParam.getRemark() : "", "UTF-8")
+                +"&deviceType="+URLEncoder.encode(testParam.getDeviceType() != null ? testParam.getDeviceType() : "", "UTF-8")
+                // 添加服务器端期望的参数
+                +"&cq="+URLEncoder.encode("", "UTF-8")
+                +"&by="+URLEncoder.encode("", "UTF-8")
+                +"&cs="+URLEncoder.encode("", "UTF-8")
+                +"&leakRate="+URLEncoder.encode("", "UTF-8")
+                +"&leakRateUnit="+URLEncoder.encode("", "UTF-8")
+                +"&type="+URLEncoder.encode("", "UTF-8");
+
+        // 添加sessionid
+//            if (MesClient.sessionid != null && !MesClient.sessionid.isEmpty()) {
+//                params += "&__sid=" + MesClient.sessionid;
+//            }
+        System.out.println("params="+params);
+        String result = doPost(url,params);
+        System.out.println("result="+result);
+
+        // 检查result是否为null或空
+        if(result == null || result.trim().isEmpty()) {
+            System.out.println("HTTP请求返回结果为空,请检查服务器连接和参数格式");
+            System.out.println("压力值: '{}', 压力单位: '{}', 泄漏值: '{}', 泄漏单位: '{}'"+
+                    testParam.getPressure()+" : "+testParam.getPressureUnit()+" : "+testParam.getLeak()+" : "+testParam.getLeakUnit());
+            return null;
+        }
+
+        if(result.equalsIgnoreCase("false")) {
+            return null;
+        }else {
+            try {
+                return JSONObject.parseObject(result);
+            } catch (Exception e) {
+                System.out.println("解析JSON响应失败: " + e.getMessage() + ", 原始响应: " + result);
+                return null;
+            }
+        }
+    }catch (Exception e){
+        System.out.println("qmResultData方法执行异常: " + e.getMessage());
+        e.printStackTrace();
+        return null;
+    }
+}
+
+
+    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 url = "http://"+mes_server_ip+":8980/js/a/mes/mesLineProcessMaterial/materials";
+            String params = "__ajax=json&oprno="+oprno+"&lineSn="+lineSn;
+            System.out.println("params="+params);
+            String result = doPost(url,params);
+            System.out.println("result="+result);
+
+            if(result.equalsIgnoreCase("false")) {
+                return null;
+            }else {
+                return JSONObject.parseObject(result);
+            }
+        }catch (Exception e){
+            return null;
+        }
+    }
+
+    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 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);
+            String result = doPost(url,params);
+            System.out.println("result="+result);
+
+            if(result.equalsIgnoreCase("false")) {
+                return null;
+            }else {
+                return JSONObject.parseObject(result);
+            }
+        }catch (Exception e){
+            return null;
+        }
+    }
+
+    public static String doPost(String httpUrl, String param) {
+        HttpURLConnection connection = null;
+        InputStream is = null;
+        OutputStream os = null;
+        BufferedReader br = null;
+        String result = null;
+        try {
+            URL url = new URL(httpUrl);
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setRequestMethod("POST");
+            connection.setConnectTimeout(15000);
+            connection.setReadTimeout(60000);
+            connection.setDoOutput(true);
+            connection.setDoInput(true);
+            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+            connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
+            os = connection.getOutputStream();
+            os.write(param.getBytes());
+            if (connection.getResponseCode() == 200) {
+                is = connection.getInputStream();
+                br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+                StringBuffer sbf = new StringBuffer();
+                String temp = null;
+                while ((temp = br.readLine()) != null) {
+                    sbf.append(temp);
+                    sbf.append("\r\n");
+                }
+                result = sbf.toString();
+            }
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (null != br) {
+                try {
+                    br.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (null != os) {
+                try {
+                    os.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (null != is) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            connection.disconnect();
+        }
+        return result;
+    }
+}

+ 85 - 0
src/com/mes/ui/LockUtil.java

@@ -0,0 +1,85 @@
+package com.mes.ui;
+
+import java.io.File;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+
+public class LockUtil {
+    private FileChannel channel;
+
+    private FileLock lock;
+
+    private File file;
+
+    private static LockUtil instance = null;
+
+    /**
+     * 获取唯一进程限制的实例
+     * @Title: getInstance
+     * @return  唯一进程实例
+     */
+    public static LockUtil getInstance(){
+        if(instance == null){
+            instance = new LockUtil();
+        }
+        return instance;
+    }
+
+    /**
+     * 进程是否正在运行
+     * @Title: isAppActive
+     * @return  运行与否
+     */
+    public boolean isAppActive() {
+        File file = new File(".lock");
+        try {
+            channel = new RandomAccessFile(file, "rw").getChannel();
+            try {
+                lock = channel.tryLock();
+
+            } catch (OverlappingFileLockException e) {
+                closeLock();
+                return true;
+            }
+            if (lock == null) {
+                closeLock();
+                return true;
+            }
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                public void run() {
+                    closeLock();
+                    deleteFile();
+                }
+            });
+            return false;
+        } catch (Exception e) {
+            closeLock();
+            return true;
+        }
+    }
+
+    protected void deleteFile() {
+        try {
+            file.delete();
+        } catch (Exception e) {
+
+        }
+
+    }
+
+    private void closeLock() {
+        try {
+            lock.release();
+        } catch (Exception e) {
+
+        }
+
+        try {
+            channel.close();
+        } catch (Exception e) {
+
+        }
+    }
+}

+ 241 - 0
src/com/mes/ui/LoginFarme.java

@@ -0,0 +1,241 @@
+package com.mes.ui;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.mes.component.MesRadio;
+import com.mes.component.MesWebView;
+import com.mes.util.Base64Utils;
+import com.mes.util.HttpUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.time.LocalDateTime;
+
+public class LoginFarme extends JFrame {
+    //登录模块组件
+    static JLabel userNameLabel= new JLabel("<html><body>用户名:</body></html>",JLabel.LEFT);//用户名
+    static JLabel userPasswordLabel= new JLabel("<html><body>密码:</body></html>",JLabel.LEFT);//用户名
+    public static JTextField userNameTxt;
+    public static JPasswordField userPasswordTxt;
+    static JButton loginButton = new JButton("用户密码登录");
+    static JButton scanLoginButton = new JButton("扫  码  登  录");
+
+    public LoginFarme(){
+        setTitle("MES系统客户端:气密检测");
+
+        ImageIcon bg = new ImageIcon(MesClient.class.getResource("/background.png"));
+        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        JLabel imgLabel = new JLabel(bg);//将背景图放在标签里。
+        getLayeredPane().add(imgLabel, new Integer(Integer.MIN_VALUE));//注意这里是关键,将背景标签添加到jfram的LayeredPane面板里。
+        imgLabel.setBounds(0,0,bg.getIconWidth(), bg.getIconHeight());//设置背景标签的位置
+        Container contentPane=getContentPane();
+        contentPane.setLayout(null);//布局,很重要
+        JPanel welcomePanel = new JPanel();
+        //welcomePanel.setLayout(new GridLayout(3, 1));
+        welcomePanel.setLayout(null);
+        //welcomeLable.setBounds(10, 5, 700, 100);
+        welcomePanel.setBounds(30, 330, 890, 300);
+        welcomePanel.setOpaque(false);//背景透明
+        contentPane.add(welcomePanel);
+
+        //登录页面
+        userNameLabel.setBounds(300, 100, 120, 40);
+        userNameLabel.setFont(new java.awt.Font("Dialog",   1,   16));
+        userPasswordLabel.setBounds(300, 150, 120, 40);
+        userPasswordLabel.setFont(new java.awt.Font("Dialog",   1,   16));
+        userNameTxt = new JTextField(20);
+        userNameTxt.setText("system");
+        userNameTxt.setBounds(400, 105, 150, 30);
+        userPasswordTxt = new JPasswordField(20);
+        userPasswordTxt.setBounds(400, 155, 150, 30);
+        userPasswordTxt.setText("Aa111111");
+        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")));
+
+//        scanLoginButton.setVisible(false);
+        scanLoginButton.setFont(new java.awt.Font("Dialog",   1,   16));
+        scanLoginButton.setBounds(300, 250, 255, 40);
+        scanLoginButton.setIcon(new ImageIcon(MesClient.class.getResource("/bg/scan_barcode.png")));
+
+        welcomePanel.add(userNameLabel);
+        welcomePanel.add(userPasswordLabel);
+        welcomePanel.add(userNameTxt);
+        welcomePanel.add(userPasswordTxt);
+        welcomePanel.add(loginButton);
+        welcomePanel.add(scanLoginButton);
+        loginButton.addActionListener(new ActionListener(){
+            public void actionPerformed(ActionEvent e) {
+                login();
+            }
+        });
+        scanLoginButton.addActionListener(new ActionListener(){
+            public void actionPerformed(ActionEvent e) {
+                scanLogin();
+            }
+        });
+
+        ((JPanel)contentPane).setOpaque(false); //注意这里,将内容面板设为透明。这样LayeredPane面板中的背景才能显示出来。
+        //welcomeWin.setSize(902,678);
+        setResizable(false);//禁止最大化
+        setIconImage(Toolkit.getDefaultToolkit().getImage(MesClient.class.getResource("/bg/logo.png")));
+
+        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
+        int width = 902;
+        int height = 678;
+        setBounds((d.width-width)/2, (d.height-height)/2-(d.height-height)/4, width, height);
+        /*****正常模式******/
+        setVisible(true);
+    }
+
+    //登录
+    public static void login() {
+        String user_str = userNameTxt.getText().toString();
+        String password_str = userPasswordTxt.getText().toString();
+        if(user_str.equalsIgnoreCase("")||password_str.equalsIgnoreCase("")) {
+            JOptionPane.showMessageDialog(MesClient.mesClientFrame,"用户名或密码不能为空","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+            return;
+        }
+        String username = Base64Utils.getBase64(user_str);
+        String password = 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);
+        if(loginResult.equalsIgnoreCase("false")) {
+            JOptionPane.showMessageDialog(MesClient.mesClientFrame,"登录异常,请检查网络或联系网络管理员","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+            return;
+        }else {
+            JSONObject retObj = JSONObject.parseObject(loginResult);
+            if(retObj.get("result")!=null&&retObj.get("result").toString().equalsIgnoreCase("true")) {
+                //检查用户权限是否可登录界面
+                checkUserAuthority(retObj);
+            }else {
+                //ret = "msg save error";
+                //ret = false;
+                JOptionPane.showMessageDialog(MesClient.mesClientFrame,"登录失败,用户名或密码错误","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }
+        }
+    }
+    //扫码登录
+    public static void scanLogin() {
+        //userNameTxt.setText("");
+        //userPasswordTxt.setText("");
+        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 loginResult = HttpUtils.sendRequest(url);
+            System.out.println("loginResult="+loginResult);
+            if(loginResult.equalsIgnoreCase("false")) {
+                JOptionPane.showMessageDialog(MesClient.mesClientFrame,"登录异常,请检查网络或联系网络管理员","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+                return;
+            }else {
+                JSONObject retObj = JSONObject.parseObject(loginResult);
+                if(retObj.get("result")!=null&&retObj.get("result").toString().equalsIgnoreCase("true")) {
+                    //检查用户权限是否可登录界面
+                    checkUserAuthority(retObj);
+                }else {
+                    JOptionPane.showMessageDialog(MesClient.mesClientFrame,"登录失败,用户名或密码错误","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+                    return;
+                }
+            }
+        }else {
+            JOptionPane.showMessageDialog(MesClient.mesClientFrame,"扫码内容错误","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+            return;
+        }
+    }
+
+    //检查用户权限是否可登录界面
+    public static void checkUserAuthority(JSONObject retObj) {
+        //设置登录用户名
+        JSONObject userObj = JSONObject.parseObject(retObj.get("user").toString());
+        String user_id = userObj.getString("id").toString();
+
+        //获取sessionid,判断权限
+        MesClient.sessionid = retObj.get("sessionid").toString();
+        if(MesClient.sessionid!=null&&!MesClient.sessionid.equalsIgnoreCase("")) {
+            //请求权限
+            String url_authority = "http://"+MesClient.mes_server_ip+":8980/js/a/mes/mesLineProcess/userAuth?__ajax=json&type=0&__sid="+MesClient.sessionid+"&oprno="+MesClient.mes_gw+"&lineSn="+MesClient.mes_line_sn;
+            String authorityResult = HttpUtils.sendRequest(url_authority);
+            System.out.println("authorityResult="+authorityResult);
+            JSONObject authorityObj = JSONObject.parseObject(authorityResult);
+            if(authorityObj.get("result")!=null&&authorityObj.get("result").toString().equalsIgnoreCase("true")) {
+                JSONObject authObjTmp = JSONObject.parseObject(authorityObj.get("data").toString());
+                MesClient.mes_auth = Integer.parseInt(authObjTmp.getString("auth").toString());
+                if(MesClient.mes_auth==0) {
+                    //无权限登录
+                    JOptionPane.showMessageDialog(MesClient.mesClientFrame,"您无权登录该工位","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+                    return;
+                }else if(MesClient.mes_auth==1||MesClient.mes_auth==2) {
+                    // 获取等于所处时间-当前小时
+                    LocalDateTime now = LocalDateTime.now();
+                    MesClient.userLoginHours = now.getHour();
+                    //初始化tcp连接,发送同步报文
+                    MesClient.initTcpConnection();
+                    //启动timer心跳包
+                    MesClient.startHeartBeatTimer();
+
+                    //1操作工人,2管理员
+                    //登录成功
+                    MesClient.user_menu.setText(user_id);
+                    MesClient.welcomeWin.setVisible(false);
+                    MesClient.mesClientFrame.setVisible(true);
+
+                    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;
+                        MesClient.jfxPanel = new MesWebView(url);
+                        MesClient.jfxPanel.setSize(990, 550);
+                        MesClient.indexPanelB.add(MesClient.jfxPanel);
+                    }
+
+
+                    // 1. 预加载【左工位】点检
+                    String leftOprno = MesClient.configParam.getOprno();
+
+                    System.out.println("leftOprno: " + leftOprno);
+                    if(leftOprno != null && !leftOprno.isEmpty()){
+                        String urlLeft = "http://" + MesClient.mes_server_ip + ":8980/js/a/mes/mesProcessCheckRecord/ulist?ucode="
+                                + user_id
+                                + "&oprno=" + leftOprno
+                                + "&lineSn=" + MesClient.mes_line_sn;
+
+                        // 创建对象并缓存到 MesClient.jfxPanelLeft
+                        MesClient.jfxPanelLeft = new MesWebView(urlLeft);
+                        MesClient.jfxPanelLeft.setSize(990, 550);
+                        System.out.println("左工位点检页面预加载完成: " + leftOprno);
+                    }
+
+                    // 2. 预加载【右工位】点检
+                    String rightOprno = MesClient.configParam.getOprno2();
+                    System.out.println("rightOprno: " + rightOprno);
+                    if(rightOprno != null && !rightOprno.isEmpty()){
+                        String urlRight = "http://" + MesClient.mes_server_ip + ":8980/js/a/mes/mesProcessCheckRecord/ulist?ucode="
+                                + user_id
+                                + "&oprno=" + rightOprno
+                                + "&lineSn=" + MesClient.mes_line_sn;
+
+                        // 创建对象并缓存到 MesClient.jfxPanelRight
+                        MesClient.jfxPanelRight = new MesWebView(urlRight);
+                        MesClient.jfxPanelRight.setSize(990, 550);
+                        System.out.println("右工位点检页面预加载完成: " + rightOprno);
+                    }
+
+                    // 3. 初始显示 (默认显示左工位)
+                    if (MesClient.jfxPanelLeft != null) {
+                        MesClient.indexPanelC.removeAll();
+                        MesClient.indexPanelC.add(MesClient.jfxPanelLeft);
+                        MesClient.indexPanelC.revalidate();
+                        MesClient.indexPanelC.repaint();
+                    }
+                    MesClient.initWarehouseData();
+                }
+            }
+
+        }else {
+            JOptionPane.showMessageDialog(MesClient.mesClientFrame,"登录失败,用户名或密码错误","提示窗口", JOptionPane.INFORMATION_MESSAGE);
+            return;
+        }
+    }
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 2336 - 0
src/com/mes/ui/MesClient.java


+ 95 - 0
src/com/mes/ui/MesRevice.java

@@ -0,0 +1,95 @@
+package com.mes.ui;
+
+import com.mes.netty.ProtocolParam;
+import com.mes.component.MyDialog;
+import com.mes.util.ErrorMsg;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class MesRevice {
+
+    // 质量查询
+    public static void checkQualityRevice(String processMsgRet,String mes_msg){
+        try{
+            if(processMsgRet.equalsIgnoreCase("UD")) {
+                MesClient.status_menu.setForeground(Color.GREEN);
+                MesClient.check_quality_result = true;//质量合格,可以绑定加工
+                MesClient.status_menu.setText("该工件可以加工");
+                MesClient.work_status = 1;
+                MesClient.f_scan_data_bt_1.setEnabled(false);
+                MesClient.finish_ok_bt.setEnabled(true);
+                MesClient.finish_ng_bt.setEnabled(true);
+
+                String oprno = ProtocolParam.getOprno(mes_msg).trim();
+                if(oprno.equals("OP400")){
+                    String lx = ProtocolParam.getLx(mes_msg);
+                    if(lx.equals("FX")){
+                        MesClient.fxlabel.setVisible(true);
+                    }
+                }
+            }else {
+                MesClient.check_quality_result = false;
+                String lmsg = ErrorMsg.getErrorMsg(processMsgRet, ProtocolParam.getLx(mes_msg));
+                MesClient.setMenuStatus(lmsg,-1);
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    // 开始回复处理
+    public static void startRevice(String processMsgRet,String mes_msg){
+        try{
+            if(processMsgRet.equalsIgnoreCase("OK")) {
+
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    // 绑定
+    public static void bindRevice(String processMsgRet,String mes_msg){
+        try{
+            if(processMsgRet.equalsIgnoreCase("OK")) {
+
+            }else{
+
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    // 解绑
+    public static void unbindRevice(String processMsgRet,String mes_msg){
+        try{
+            if(processMsgRet.equalsIgnoreCase("OK")) {
+
+            }else{
+
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    // 上传质量
+    public static void updateResultRevice(String processMsgRet,String mes_msg){
+        try{
+            if(processMsgRet.equalsIgnoreCase("OK")) {
+
+                MesClient.resetScanA();
+                MesClient.setMenuStatus("结果提交成功,请扫下一件",0);
+                MesClient.scan_type = 1;
+                MesClient.scanBarcode();
+
+            }else{
+                MesClient.setMenuStatus("结果提交失败,请重试",-1);
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+}

+ 61 - 0
src/com/mes/ui/OprnoUtil.java

@@ -0,0 +1,61 @@
+package com.mes.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class OprnoUtil {
+    public static String[] xtoprnos = new String[]{
+            "OP060","OP090","OP100","OP130","OP140","OP170","OP180",
+            "OP190","OP210","OP220","OP230","OP240","OP250","OP290",
+            "OP300", "OP320","OP350","OP360","OP390","OP400"
+    };
+    public static String[] xtoprnodes = new String[]{
+            "后梁FSW","后梁找漏","后梁CNC","框架CMT焊接","人工补焊","框架气密检测","CNC总成正面加工",
+            "CNC总成反面加工","总成压套筒","正面拉铆安装","框架涂胶","FDS","反面拉铆安装","半成品气密",
+            "底护板安装","总成气密+冷板气密", "拉铆装配","总成检具","CCD检测","GP12"
+    };
+    public static String[] lboprnos = new String[]{
+
+    };
+    public static String[] lboprnodes = new String[]{
+
+    };
+    public static String getGwDes(String lineSn,String oprno){
+        String des = "";
+        oprno = formatOprno(oprno);
+        if(lineSn.equals("XT")){
+            int i = 0;
+            for (String gw:xtoprnos){
+                if(gw.equals(oprno)){
+                    des = xtoprnodes[i];
+                    break;
+                }
+                i++;
+            }
+        }else if(lineSn.equals("LB")){
+            int i = 0;
+            for (String gw:lboprnos){
+                if(gw.equals(oprno)){
+                    des = lboprnodes[i];
+                    break;
+                }
+                i++;
+            }
+        }
+        return des;
+    }
+
+    public static String formatOprno(String oprno){
+        List<String> lists = new ArrayList<>();
+
+        if(oprno.length() == 6){
+            String ysoprno = oprno.substring(0,5).trim();
+            if(!lists.contains(ysoprno)){
+                oprno = ysoprno;
+            }
+        }
+
+        return  oprno;
+    }
+}

+ 43 - 0
src/com/mes/ui/TableCellEditorButton.java

@@ -0,0 +1,43 @@
+package com.mes.ui;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class TableCellEditorButton extends DefaultCellEditor {
+    private JButton btn;
+    public TableCellEditorButton() {
+        super(new JTextField());
+        //设置点击一次就激活,否则默认好像是点击2次激活。
+        this.setClickCountToStart(1);
+        btn = new JButton("扫码");
+        btn.addActionListener(new ActionListener() {
+
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                System.out.println("按钮事件触发----");
+                int selectedRow = MesClient.table.getSelectedRow();//获得选中行的索引
+//                MesClient.rowData[selectedRow][1] = (new Date()).getTime();
+//                MesClient.table.repaint(); //重绘
+
+//                MesClient.scan_type = selectedRow + 4;
+                BindMaterialResp bindMaterialResp = new BindMaterialResp();
+                bindMaterialResp.setMaterialTitle(MesClient.rowData[selectedRow][0] + "");
+                bindMaterialResp.setBatchSn(MesClient.rowData[selectedRow][1] + "");
+                bindMaterialResp.setLastTimes(MesClient.rowData[selectedRow][2] + "");
+                bindMaterialResp.setCraft(MesClient.rowData[selectedRow][4] + "");
+                bindMaterialResp.setMaterialId(MesClient.rowData[selectedRow][5] + "");
+                bindMaterialResp.setType(MesClient.rowData[selectedRow][6] + "");
+
+//                MesClient.scanBatchSn(bindMaterialResp);
+            }
+        });
+
+    }
+    @Override
+    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+
+        return btn;
+    }
+}

+ 14 - 0
src/com/mes/ui/TableCellRendererButton.java

@@ -0,0 +1,14 @@
+package com.mes.ui;
+
+import javax.swing.*;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+
+public class TableCellRendererButton implements TableCellRenderer {
+    @Override
+    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
+                                                   int row, int column) {
+        JButton button = new JButton("扫码");
+        return button;
+    }
+}

+ 347 - 0
src/com/mes/util/ATEQ.java

@@ -0,0 +1,347 @@
+package com.mes.util;
+
+import com.mes.ui.MesClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+
+public class ATEQ {
+    private static final Logger log = LoggerFactory.getLogger(ATEQ.class);
+
+    public static boolean stop() {
+        String s1 = DataUtils.CRC16(ATEQ.getStationNo()+" 05 00 00 FF 00");
+
+        byte[] read = MesClient.serialPortUtils.read(s1);
+        boolean result = Arrays.equals(read, DataUtils.hexStringToByteArray(s1));
+        log.info("左工位气密仪停止{}", result ? "成功" : "失败");
+        return result;
+    }
+
+    public static boolean start() {
+        String s1 = DataUtils.CRC16(ATEQ.getStationNo()+" 05 00 01 FF 00");
+        System.out.println("s1:"+s1);
+        byte[] read = MesClient.serialPortUtils.read(s1);
+        boolean result = Arrays.equals(read, DataUtils.hexStringToByteArray(s1));
+        log.info("左工位气密仪开始{}", result ? "成功" : "失败");
+        return result;
+    }
+
+//    public static boolean resetFIFO() {
+//        byte[] read = SerialUtil.read("01 05 00 02 FF 00 2D FA");
+//        boolean result = Arrays.equals(read, DataUtils.hexStringToByteArray("01 05 00 02 FF 00 2D FA"));
+//        log.info("重置FIFO{}", result ? "成功" : "失败");
+//        return result;
+//    }
+
+    // 读取实时结果
+    public static RealtimeResult readRealtimeResult() {
+        String s1 = DataUtils.CRC16(ATEQ.getStationNo()+" 03 00 30 00 0D");
+        byte[] read = MesClient.serialPortUtils.read(s1);
+        if(read.length > 30) {
+            return new RealtimeResult(read);
+        } else {
+            throw new RuntimeException("读取实时结果时, 返回的数据长度不够");
+        }
+    }
+
+//    // 读取先入先出队列中的待处理结果
+//    public static FIFOResult readFIFOResult() {
+//        byte[] read = SerialUtil.read("01 03 00 10 00 0D 85 CA");
+//        if(read.length > 28) {
+//            return new FIFOResult(read);
+//        } else {
+//            throw new RuntimeException("读取FIFO结果时, 返回的数据长度不够");
+//        }
+//    }
+
+    // 读取最后结果
+    public static LastResult readLastResult() {
+        String s1 = DataUtils.CRC16(ATEQ.getStationNo()+" 03 00 11 00 0C");
+        byte[] read = MesClient.serialPortUtils.read(s1);
+        if(read.length > 20) {
+            return new LastResult(read);
+        } else {
+            throw new RuntimeException("左工位读取FIFO结果时, 返回的数据长度不够");
+        }
+    }
+
+
+
+    // 获取参数, 传入程序号, 获取对应程序号的参数
+    public static Parameters getParams(Integer programNumber) {
+
+        // 步骤1: 选择要编辑的程序
+        String s1 = DataUtils.CRC16("01 10 30 04 00 01 02 " + DataUtils.intToWord(programNumber - 1));
+        MesClient.serialPortUtils.read(s1);
+
+        // 步骤2: 写入要读取的标识符
+        String s2 = "01 10 00 00 00 04 08 03 00 01 00 02 00 03 00 F6 F6"; // s2 表示读取3个参数, 分别是 填充时间、稳定时间、测试时间
+        MesClient.serialPortUtils.read(s2);
+
+        // 步骤3: 读取数据
+        byte[] read = MesClient.serialPortUtils.read("01 03 00 00 00 09 85 CC");
+        if(read.length > 22) {
+            return new Parameters(read);
+        } else {
+            throw new RuntimeException("读取参数时, 返回的数据长度不够");
+        }
+    }
+
+    // 获取站号
+    public static String getStationNo() {
+
+        try{
+            int decimalNumber = Integer.valueOf(MesClient.configParam.getModbusSite()); // 示例十进制数
+            String hexString = Integer.toHexString(decimalNumber); // 转换为16进制字符串
+            System.out.println(hexString.toUpperCase()); // 输出结果
+
+            if(hexString.length() == 1) {
+                hexString = "0" + hexString;
+            }
+
+            return hexString;
+        }catch (Exception e){
+            return "01";
+        }
+    }
+
+    public static class RealtimeResult {
+        public final Integer programNumber;               // 程序号
+        //        public final Integer FIFO_Number;
+        public final String testType;                     // 测试类型
+        public final String step;                         // 当前步骤
+        public final Integer stepCode;                     // 当前步骤码
+        public final Double pressureValue;                // 压力值
+        public final Double leakValue;                    // 泄漏值
+        public final Boolean isCycleEnd;                  // 测试是否结束
+        public final Boolean isPass;                      // 测试是否通过
+        public final Boolean isKeyExist;                  //
+        public final String pressureUnit;                 // 压力单位
+        public final String leakUnit;                     // 泄漏单位
+        public RealtimeResult(byte[] data) {
+            // 大端排序互换位置
+            // 01031a 0000(程序号) 0800(测试模式) 0100(测试状态) 0080(报警状态) 0600(测试阶段) 160d0000(测试压力) e02e0000(压力单位) 00000000(泄漏量结果) 38c70000(泄漏量单位) cf93
+            // 01031a 0000(程序号) 0800(测试模式) 0100(测试状态) 3080(报警状态) ffff(测试阶段) 160d0000(测试压力) e02e0000(压力单位) 00000000(泄漏量结果) 38c70000(泄漏量单位) 1b0a
+            log.info("左工位实时数据:"+DataUtils.bytesToHex(data));
+            this.programNumber = DataUtils.bytesToInt(Arrays.copyOfRange(data, 3, 5)) + 1;
+//            this.FIFO_Number = DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7));
+            this.testType = getTestTypeStr(DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7)));
+            int state = DataUtils.bytesToInt(Arrays.copyOfRange(data, 7, 9));
+            this.isCycleEnd = DataUtils.getBit(state, 5) == 1;
+            this.isPass = DataUtils.getBit(state, 0) == 1;
+            this.isKeyExist = DataUtils.getBit(state, 15) == 1;
+            this.stepCode = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 13));
+            this.step = getStepStr(this.stepCode);
+            this.pressureValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 13, 17)) / 1000.0;
+            this.pressureUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 17, 21)));
+            this.leakValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 21, 25)) / 1000.0;
+            this.leakUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 25, 29)));
+        }
+
+        @Override
+        public String toString() {
+            return "左工位实时结果{" +
+                    " 压力值: " + pressureValue +
+                    ", 泄漏值: " + leakValue +
+//                    ", FIFO数量: " + FIFO_Number +
+                    ", 当前步骤CODE: " + stepCode +
+                    ", 当前步骤: " + step +
+//                    ", 循环是否结束: " + isCycleEnd +
+//                    ", 测试通过: " + isPass +
+//                    ", 是否关键存在: " + isKeyExist +
+                    ", 程序号: " + programNumber +
+//                    ", 测试类型: " + testType +
+                    '}';
+        }
+    }
+
+//    public static class FIFOResult {
+//        public final Integer programNumber;
+//        public final String testType;
+//        public final Double pressureValue;
+//        public final Double leakValue;
+//        public final Boolean isPass;
+//        public final Boolean isTestLeak;
+//        public final Boolean isReferLeak;
+//        public final String pressureUnit;
+//        public final String leakUnit;
+//        public FIFOResult(byte[] data) {
+//            this.programNumber = DataUtils.bytesToInt(Arrays.copyOfRange(data, 3, 5)) + 1;
+//            this.testType = getTestTypeStr(DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7)));
+//            int state = DataUtils.bytesToInt(Arrays.copyOfRange(data, 7, 9));
+//            this.isPass = DataUtils.getBit(state, 0) == 1;
+//            this.isTestLeak = DataUtils.getBit(state, 1) == 1;
+//            this.isReferLeak = DataUtils.getBit(state, 2) == 1;
+//            this.pressureValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000.0;
+//            this.pressureUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 15, 19)));
+//            this.leakValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 19, 23)) / 1000.0;
+//            this.leakUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 23, 27)));
+//        }
+//
+//        @Override
+//        public String toString() {
+//            return "FIFO结果{" +
+//                    " 压力值: " + pressureValue +
+//                    ", 泄漏值: " + leakValue +
+//                    ", 测试通过: " + isPass +
+//                    ", 测试泄漏: " + isTestLeak +
+//                    ", 参考泄漏: " + isReferLeak +
+//                    ", 程序号: " + programNumber +
+//                    ", 测试类型: " + testType +
+//                    '}';
+//        }
+//    }
+
+    // 最后结果类
+    public static class LastResult {
+        public final Integer programNumber;         // 程序号
+        public final String testType;               // 测试类型
+        public final Double pressureValue;          // 压力值
+        public final Double leakValue;              // 泄漏值
+        public final Boolean isPass;                // 测试是否通过(true表示OK, false表示NG)
+        public final Boolean isTestLeak;
+        public final Boolean isReferLeak;
+        public final String pressureUnit;           // 压力单位
+        public final String leakUnit;               // 测试单位
+        public LastResult(byte[] data) {
+            // 010318 0000(程序号) 0100(测试模式) 0800(测试状态) 0200(报警状态) 160D0000(压力值) E02E0000(压力单位) 00000000(泄露值) 38C70000(泄露值单位) 1EE9
+            log.info("最终结果:"+DataUtils.bytesToHex(data));
+            this.programNumber = DataUtils.bytesToInt(Arrays.copyOfRange(data, 3, 5)) + 1;
+            this.testType = getTestTypeStr(DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7)));
+            int state = DataUtils.bytesToInt(Arrays.copyOfRange(data, 7, 9));
+            this.isPass = DataUtils.getBit(state, 0) == 1;
+            this.isTestLeak = DataUtils.getBit(state, 1) == 1;
+            this.isReferLeak = DataUtils.getBit(state, 2) == 1;
+            this.pressureValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000.0;
+            this.pressureUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 15, 19)));
+            this.leakValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 19, 23)) / 1000.0;
+            this.leakUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 23, 27)));
+            if(this.leakValue == 0 && !this.isPass){
+//                this.leakValue = Double.valueOf(9999);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "最后结果{" +
+                    " 压力值: " + pressureValue +
+                    ", 泄漏值: " + leakValue +
+                    ", 测试通过: " + isPass +
+                    ", 测试泄漏: " + isTestLeak +
+                    ", 参考泄漏: " + isReferLeak +
+                    ", 程序号: " + programNumber +
+//                    ", 测试类型: " + testType +
+                    '}';
+        }
+    }
+
+
+    // 参数类
+    public static class Parameters {
+        public final Integer fillTime;         // 填充时间
+        public final Integer stabilizeTime;    // 稳定时间
+        public final Integer testTime;         // 测试时间
+
+        public Parameters(byte[] data) {
+            log.info("时间参数:"+DataUtils.bytesToHex(data));
+            this.fillTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 9)) / 1000;
+            this.stabilizeTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000;
+            this.testTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 17, 21)) / 1000;
+        }
+
+        @Override
+        public String toString() {
+            return "参数{" +
+                    "填充时间: " + fillTime +
+                    "s, 稳定时间: " + stabilizeTime +
+                    "s, 测试时间: " + testTime +
+                    "s}";
+        }
+    }
+
+    private static String getTestTypeStr(Integer testTypeCode) {
+        String s = "未知";
+        if(testTypeCode == 1) {
+            s = "泄漏";
+        }
+        return s;
+    }
+
+    private static String getStepStr(Integer stepCode) {
+        String s = "未知";
+        switch (stepCode) {
+            case 0:
+                s = "预填充";
+                break;
+            case 1:
+                s = "预排气";
+                break;
+            case 2:
+                s = "密封零件测试充气";
+                break;
+            case 3:
+                s = "密封零件测试保压";
+                break;
+            case 4:
+                s = "充气";
+                break;
+            case 5:
+                s = "保压";
+                break;
+            case 6:
+//                s = "测试"; // 充气
+                s = "充气";
+                break;
+            case 7:
+//                s = "排气"; // 保压
+                s = "保压";
+                break;
+            case 8:
+                s = "测试"; // 保压
+                break;
+            case 65535:
+                s = "未进行测试";
+                break;
+        }
+        return s;
+    }
+
+    private static String getUnit(Integer unitCode) {
+        String s = "";
+        switch (unitCode) {
+            case 0:
+                s = "cm3/s";
+                break;
+            case 1000:
+                s = "cm3/min";
+                break;
+            case 2000:
+                s = "cm3/h";
+                break;
+            case 6000:
+                s = "Pa";
+                break;
+            case 8000:
+                s = "Pa/s";
+                break;
+            case 11000:
+                s = "Bar";
+                break;
+            case 12000:
+                s = "kPa";
+                break;
+            case 50000:
+                s = "ml/s";
+                break;
+            case 51000:
+                s = "ml/min";
+                break;
+            case 52000:
+                s = "ml/h";
+                break;
+        }
+        return s;
+    }
+
+}

+ 348 - 0
src/com/mes/util/ATEQ2.java

@@ -0,0 +1,348 @@
+package com.mes.util;
+
+import com.mes.ui.MesClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+
+public class ATEQ2 {
+    private static final Logger log = LoggerFactory.getLogger(ATEQ2.class);
+
+    public static boolean stop() {
+        String s1 = DataUtils.CRC16(ATEQ2.getStationNo()+" 05 00 00 FF 00");
+
+        byte[] read = MesClient.serialPortUtils2.read(s1);
+        boolean result = Arrays.equals(read, DataUtils.hexStringToByteArray(s1));
+        log.info("右工位气密仪停止{}", result ? "成功" : "失败");
+        return result;
+    }
+
+    public static boolean start() {
+        String s1 = DataUtils.CRC16(ATEQ2.getStationNo()+" 05 00 01 FF 00");
+        System.out.println("s1:"+s1);
+        byte[] read = MesClient.serialPortUtils2.read(s1);
+        boolean result = Arrays.equals(read, DataUtils.hexStringToByteArray(s1));
+        log.info("右工位气密仪开始{}", result ? "成功" : "失败");
+        return result;
+    }
+
+//    public static boolean resetFIFO() {
+//        byte[] read = SerialUtil.read("01 05 00 02 FF 00 2D FA");
+//        boolean result = Arrays.equals(read, DataUtils.hexStringToByteArray("01 05 00 02 FF 00 2D FA"));
+//        log.info("重置FIFO{}", result ? "成功" : "失败");
+//        return result;
+//    }
+
+    // 读取实时结果
+    public static RealtimeResult readRealtimeResult() {
+        String s1 = DataUtils.CRC16(ATEQ2.getStationNo()+" 03 00 30 00 0D");
+        byte[] read = MesClient.serialPortUtils2.read(s1);
+        System.out.println("右工位结果读取:"+DataUtils.bytesToHex(read));
+        if(read.length > 30) {
+            return new RealtimeResult(read);
+        } else {
+            throw new RuntimeException("右工位读取实时结果时, 返回的数据长度不够");
+        }
+    }
+
+//    // 读取先入先出队列中的待处理结果
+//    public static FIFOResult readFIFOResult() {
+//        byte[] read = SerialUtil.read("01 03 00 10 00 0D 85 CA");
+//        if(read.length > 28) {
+//            return new FIFOResult(read);
+//        } else {
+//            throw new RuntimeException("读取FIFO结果时, 返回的数据长度不够");
+//        }
+//    }
+
+    // 读取最后结果
+    public static LastResult readLastResult() {
+        String s1 = DataUtils.CRC16(ATEQ2.getStationNo()+" 03 00 11 00 0C");
+        byte[] read = MesClient.serialPortUtils2.read(s1);
+        if(read.length > 20) {
+            return new LastResult(read);
+        } else {
+            throw new RuntimeException("右工位读取FIFO结果时, 返回的数据长度不够");
+        }
+    }
+
+
+
+    // 获取参数, 传入程序号, 获取对应程序号的参数
+    public static Parameters getParams(Integer programNumber) {
+
+        // 步骤1: 选择要编辑的程序
+        String s1 = DataUtils.CRC16("01 10 30 04 00 01 02 " + DataUtils.intToWord(programNumber - 1));
+        MesClient.serialPortUtils2.read(s1);
+
+        // 步骤2: 写入要读取的标识符
+        String s2 = "01 10 00 00 00 04 08 03 00 01 00 02 00 03 00 F6 F6"; // s2 表示读取3个参数, 分别是 填充时间、稳定时间、测试时间
+        MesClient.serialPortUtils2.read(s2);
+
+        // 步骤3: 读取数据
+        byte[] read = MesClient.serialPortUtils2.read("01 03 00 00 00 09 85 CC");
+        if(read.length > 22) {
+            return new Parameters(read);
+        } else {
+            throw new RuntimeException("读取参数时, 返回的数据长度不够");
+        }
+    }
+
+    // 获取站号
+    public static String getStationNo() {
+
+        try{
+            int decimalNumber = Integer.valueOf(MesClient.configParam.getModbusSite2()); // 示例十进制数
+            String hexString = Integer.toHexString(decimalNumber); // 转换为16进制字符串
+//            System.out.println(hexString.toUpperCase()); // 输出结果
+
+            if(hexString.length() == 1) {
+                hexString = "0" + hexString;
+            }
+
+            return hexString;
+        }catch (Exception e){
+            return "01";
+        }
+    }
+
+    public static class RealtimeResult {
+        public final Integer programNumber;               // 程序号
+        //        public final Integer FIFO_Number;
+        public final String testType;                     // 测试类型
+        public final String step;                         // 当前步骤
+        public final Integer stepCode;                     // 当前步骤码
+        public final Double pressureValue;                // 压力值
+        public final Double leakValue;                    // 泄漏值
+        public final Boolean isCycleEnd;                  // 测试是否结束
+        public final Boolean isPass;                      // 测试是否通过
+        public final Boolean isKeyExist;                  //
+        public final String pressureUnit;                 // 压力单位
+        public final String leakUnit;                     // 泄漏单位
+        public RealtimeResult(byte[] data) {
+            // 大端排序互换位置
+            // 01031a 0000(程序号) 0800(测试模式) 0100(测试状态) 0080(报警状态) 0600(测试阶段) 160d0000(测试压力) e02e0000(压力单位) 00000000(泄漏量结果) 38c70000(泄漏量单位) cf93
+            // 01031a 0000(程序号) 0800(测试模式) 0100(测试状态) 3080(报警状态) ffff(测试阶段) 160d0000(测试压力) e02e0000(压力单位) 00000000(泄漏量结果) 38c70000(泄漏量单位) 1b0a
+            System.out.println("右工位实时数据:"+DataUtils.bytesToHex(data));
+            this.programNumber = DataUtils.bytesToInt(Arrays.copyOfRange(data, 3, 5)) + 1;
+//            this.FIFO_Number = DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7));
+            this.testType = getTestTypeStr(DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7)));
+            int state = DataUtils.bytesToInt(Arrays.copyOfRange(data, 7, 9));
+            this.isCycleEnd = DataUtils.getBit(state, 5) == 1;
+            this.isPass = DataUtils.getBit(state, 0) == 1;
+            this.isKeyExist = DataUtils.getBit(state, 15) == 1;
+            this.stepCode = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 13));
+            this.step = getStepStr(this.stepCode);
+            this.pressureValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 13, 17)) / 1000.0;
+            this.pressureUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 17, 21)));
+            this.leakValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 21, 25)) / 1000.0;
+            this.leakUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 25, 29)));
+        }
+
+        @Override
+        public String toString() {
+            return "右工位实时结果{" +
+                    " 压力值: " + pressureValue +
+                    ", 泄漏值: " + leakValue +
+//                    ", FIFO数量: " + FIFO_Number +
+                    ", 当前步骤CODE: " + stepCode +
+                    ", 当前步骤: " + step +
+//                    ", 循环是否结束: " + isCycleEnd +
+//                    ", 测试通过: " + isPass +
+//                    ", 是否关键存在: " + isKeyExist +
+                    ", 程序号: " + programNumber +
+//                    ", 测试类型: " + testType +
+                    '}';
+        }
+    }
+
+//    public static class FIFOResult {
+//        public final Integer programNumber;
+//        public final String testType;
+//        public final Double pressureValue;
+//        public final Double leakValue;
+//        public final Boolean isPass;
+//        public final Boolean isTestLeak;
+//        public final Boolean isReferLeak;
+//        public final String pressureUnit;
+//        public final String leakUnit;
+//        public FIFOResult(byte[] data) {
+//            this.programNumber = DataUtils.bytesToInt(Arrays.copyOfRange(data, 3, 5)) + 1;
+//            this.testType = getTestTypeStr(DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7)));
+//            int state = DataUtils.bytesToInt(Arrays.copyOfRange(data, 7, 9));
+//            this.isPass = DataUtils.getBit(state, 0) == 1;
+//            this.isTestLeak = DataUtils.getBit(state, 1) == 1;
+//            this.isReferLeak = DataUtils.getBit(state, 2) == 1;
+//            this.pressureValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000.0;
+//            this.pressureUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 15, 19)));
+//            this.leakValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 19, 23)) / 1000.0;
+//            this.leakUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 23, 27)));
+//        }
+//
+//        @Override
+//        public String toString() {
+//            return "FIFO结果{" +
+//                    " 压力值: " + pressureValue +
+//                    ", 泄漏值: " + leakValue +
+//                    ", 测试通过: " + isPass +
+//                    ", 测试泄漏: " + isTestLeak +
+//                    ", 参考泄漏: " + isReferLeak +
+//                    ", 程序号: " + programNumber +
+//                    ", 测试类型: " + testType +
+//                    '}';
+//        }
+//    }
+
+    // 最后结果类
+    public static class LastResult {
+        public final Integer programNumber;         // 程序号
+        public final String testType;               // 测试类型
+        public final Double pressureValue;          // 压力值
+        public final Double leakValue;              // 泄漏值
+        public final Boolean isPass;                // 测试是否通过(true表示OK, false表示NG)
+        public final Boolean isTestLeak;
+        public final Boolean isReferLeak;
+        public final String pressureUnit;           // 压力单位
+        public final String leakUnit;               // 测试单位
+        public LastResult(byte[] data) {
+            // 010318 0000(程序号) 0100(测试模式) 0800(测试状态) 0200(报警状态) 160D0000(压力值) E02E0000(压力单位) 00000000(泄露值) 38C70000(泄露值单位) 1EE9
+            log.info("最终结果:"+DataUtils.bytesToHex(data));
+            this.programNumber = DataUtils.bytesToInt(Arrays.copyOfRange(data, 3, 5)) + 1;
+            this.testType = getTestTypeStr(DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 7)));
+            int state = DataUtils.bytesToInt(Arrays.copyOfRange(data, 7, 9));
+            this.isPass = DataUtils.getBit(state, 0) == 1;
+            this.isTestLeak = DataUtils.getBit(state, 1) == 1;
+            this.isReferLeak = DataUtils.getBit(state, 2) == 1;
+            this.pressureValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000.0;
+            this.pressureUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 15, 19)));
+            this.leakValue = DataUtils.bytesToInt(Arrays.copyOfRange(data, 19, 23)) / 1000.0;
+            this.leakUnit = getUnit(DataUtils.bytesToInt(Arrays.copyOfRange(data, 23, 27)));
+            if(this.leakValue == 0 && !this.isPass){
+//                this.leakValue = Double.valueOf(9999);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "最后结果{" +
+                    " 压力值: " + pressureValue +
+                    ", 泄漏值: " + leakValue +
+                    ", 测试通过: " + isPass +
+                    ", 测试泄漏: " + isTestLeak +
+                    ", 参考泄漏: " + isReferLeak +
+                    ", 程序号: " + programNumber +
+//                    ", 测试类型: " + testType +
+                    '}';
+        }
+    }
+
+
+    // 参数类
+    public static class Parameters {
+        public final Integer fillTime;         // 填充时间
+        public final Integer stabilizeTime;    // 稳定时间
+        public final Integer testTime;         // 测试时间
+
+        public Parameters(byte[] data) {
+            log.info("时间参数:"+DataUtils.bytesToHex(data));
+            this.fillTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 5, 9)) / 1000;
+            this.stabilizeTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 11, 15)) / 1000;
+            this.testTime = DataUtils.bytesToInt(Arrays.copyOfRange(data, 17, 21)) / 1000;
+        }
+
+        @Override
+        public String toString() {
+            return "参数{" +
+                    "填充时间: " + fillTime +
+                    "s, 稳定时间: " + stabilizeTime +
+                    "s, 测试时间: " + testTime +
+                    "s}";
+        }
+    }
+
+    private static String getTestTypeStr(Integer testTypeCode) {
+        String s = "未知";
+        if(testTypeCode == 1) {
+            s = "泄漏";
+        }
+        return s;
+    }
+
+    private static String getStepStr(Integer stepCode) {
+        String s = "未知";
+        switch (stepCode) {
+            case 0:
+                s = "预填充";
+                break;
+            case 1:
+                s = "预排气";
+                break;
+            case 2:
+                s = "密封零件测试充气";
+                break;
+            case 3:
+                s = "密封零件测试保压";
+                break;
+            case 4:
+                s = "充气";
+                break;
+            case 5:
+                s = "保压";
+                break;
+            case 6:
+//                s = "测试"; // 充气
+                s = "充气";
+                break;
+            case 7:
+//                s = "排气"; // 保压
+                s = "保压";
+                break;
+            case 8:
+                s = "测试"; // 保压
+                break;
+            case 65535:
+                s = "未进行测试";
+                break;
+        }
+        return s;
+    }
+
+    private static String getUnit(Integer unitCode) {
+        String s = "";
+        switch (unitCode) {
+            case 0:
+                s = "cm3/s";
+                break;
+            case 1000:
+                s = "cm3/min";
+                break;
+            case 2000:
+                s = "cm3/h";
+                break;
+            case 6000:
+                s = "Pa";
+                break;
+            case 8000:
+                s = "Pa/s";
+                break;
+            case 11000:
+                s = "Bar";
+                break;
+            case 12000:
+                s = "kPa";
+                break;
+            case 50000:
+                s = "ml/s";
+                break;
+            case 51000:
+                s = "ml/min";
+                break;
+            case 52000:
+                s = "ml/h";
+                break;
+        }
+        return s;
+    }
+
+}

+ 11 - 0
src/com/mes/util/Base64Utils.java

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

+ 63 - 0
src/com/mes/util/CommonUtils.java

@@ -0,0 +1,63 @@
+package com.mes.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+public class CommonUtils {
+
+    public static String getDateByBefor(int ngTime) {
+        try{
+            Calendar beforeTime = Calendar.getInstance();
+            beforeTime.add(Calendar.MINUTE, -ngTime);// 5分钟之前的时间
+            Date beforeD = beforeTime.getTime();
+            String before5 = new SimpleDateFormat("yyyyMMddHHmmss").format(beforeD);
+            return before5;
+        }catch (Exception e){
+            return null;
+        }
+    }
+
+    public static long jsSecond(String timeStr1,String timeStr2){
+//        String timeStr1 = "2023-01-01 12:10:00";
+//        String timeStr2 = "2023-01-01 12:05:00";
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        try {
+            Date date1 = sdf.parse(timeStr1);
+            Date date2 = sdf.parse(timeStr2);
+            long diffInMillies = Math.abs(date2.getTime() - date1.getTime());
+            long seconds = TimeUnit.MILLISECONDS.toSeconds(diffInMillies);
+            return seconds;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return 0;
+        }
+    }
+
+    /**
+     * 判段工件码是否符合要求
+     * @param sn  工件码
+     * @param spec  规格
+     * @param specStart  规格开始位置
+     * @param length   码长度
+     * @return
+     */
+    public static Boolean checkSnByModel(String sn, String spec,Integer specStart, Integer length) {
+        if(sn.length()!=length){
+            return false;
+        }
+        Integer start=specStart - 1;
+        Integer end=start + spec.length();
+        if(length > end){
+            String newSpec = sn.substring(start,end);
+            if(newSpec.equals(spec)){
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+}

+ 0 - 0
src/com/mes/util/DataUtils.java


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä