|
@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONObject;
|
|
|
import com.mes.component.MesRadio;
|
|
import com.mes.component.MesRadio;
|
|
|
import com.mes.component.MesWebView;
|
|
import com.mes.component.MesWebView;
|
|
|
import com.mes.component.StationPanel;
|
|
import com.mes.component.StationPanel;
|
|
|
|
|
+import com.mes.plc.McPlcClient;
|
|
|
import com.mes.util.DateLocalUtils;
|
|
import com.mes.util.DateLocalUtils;
|
|
|
import com.mes.util.HttpUtils;
|
|
import com.mes.util.HttpUtils;
|
|
|
import com.mes.util.JdbcUtils;
|
|
import com.mes.util.JdbcUtils;
|
|
@@ -39,13 +40,19 @@ public class MesClient extends JFrame {
|
|
|
public static int mes_heart_icon_cycle = 1;
|
|
public static int mes_heart_icon_cycle = 1;
|
|
|
public static String mes_line_sn = ""; // 产线编号
|
|
public static String mes_line_sn = ""; // 产线编号
|
|
|
|
|
|
|
|
|
|
+ // PLC(三菱 MC 3E)
|
|
|
|
|
+ public static String plc_ip = "";
|
|
|
|
|
+ public static int plc_port = 3000;
|
|
|
|
|
+ public static String plc_a_code_addr = "D5000";
|
|
|
|
|
+ public static String plc_b_code_addr = "D5000";
|
|
|
|
|
+ public static int plc_code_len = 20;
|
|
|
|
|
+
|
|
|
//session
|
|
//session
|
|
|
public static String sessionid = "";
|
|
public static String sessionid = "";
|
|
|
|
|
|
|
|
public static JPanel contentPane;
|
|
public static JPanel contentPane;
|
|
|
public static MesClient mesClientFrame;
|
|
public static MesClient mesClientFrame;
|
|
|
public static JTabbedPane tabbedPane;
|
|
public static JTabbedPane tabbedPane;
|
|
|
- public static JScrollPane indexScrollPaneA;
|
|
|
|
|
// public static JScrollPane searchScrollPane; // 已弃用,改为使用 WorkRecordPanel
|
|
// public static JScrollPane searchScrollPane; // 已弃用,改为使用 WorkRecordPanel
|
|
|
public static JScrollPane searchScrollPaneDj;
|
|
public static JScrollPane searchScrollPaneDj;
|
|
|
|
|
|
|
@@ -120,7 +127,12 @@ public class MesClient extends JFrame {
|
|
|
mes_server_ip = pro.getProperty("mes.server_ip");
|
|
mes_server_ip = pro.getProperty("mes.server_ip");
|
|
|
mes_line_sn = pro.getProperty("mes.line_sn");
|
|
mes_line_sn = pro.getProperty("mes.line_sn");
|
|
|
mes_gw_des = OprnoUtil.getGwDes(mes_line_sn,mes_gw);
|
|
mes_gw_des = OprnoUtil.getGwDes(mes_line_sn,mes_gw);
|
|
|
- log.info(mes_gw + ";" + mes_gw_des + ";" + mes_server_ip + ";");
|
|
|
|
|
|
|
+ plc_ip = pro.getProperty("plc.ip", "").trim();
|
|
|
|
|
+ plc_port = Integer.parseInt(pro.getProperty("plc.port", "3000").trim());
|
|
|
|
|
+ plc_a_code_addr = pro.getProperty("plc.a.code_addr", "D5000").trim();
|
|
|
|
|
+ plc_b_code_addr = pro.getProperty("plc.b.code_addr", "D5000").trim();
|
|
|
|
|
+ plc_code_len = Integer.parseInt(pro.getProperty("plc.code_len", "20").trim());
|
|
|
|
|
+ log.info(mes_gw + ";" + mes_gw_des + ";" + mes_server_ip + ";" + plc_ip + ":" + plc_port);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//启动心跳包程序
|
|
//启动心跳包程序
|
|
@@ -273,11 +285,6 @@ public class MesClient extends JFrame {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @Override
|
|
|
|
|
- public void windowOpened(WindowEvent e) {
|
|
|
|
|
- // 窗口显示后再写日志,避免与首次布局争抢锁
|
|
|
|
|
- addLog("界面已加载,等待 PLC 连接");
|
|
|
|
|
- }
|
|
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
JMenuBar menuBar = new JMenuBar();
|
|
JMenuBar menuBar = new JMenuBar();
|
|
@@ -403,6 +410,11 @@ public class MesClient extends JFrame {
|
|
|
plc_menu.setForeground(Color.RED);
|
|
plc_menu.setForeground(Color.RED);
|
|
|
plc_menu.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|
|
plc_menu.setFont(new Font("微软雅黑", Font.PLAIN, 20));
|
|
|
plc_menu.setBackground(Color.BLACK);
|
|
plc_menu.setBackground(Color.BLACK);
|
|
|
|
|
+ plc_menu.addActionListener(new ActionListener() {
|
|
|
|
|
+ public void actionPerformed(ActionEvent e) {
|
|
|
|
|
+ showPlcSignals();
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
toolBar.add(plc_menu);
|
|
toolBar.add(plc_menu);
|
|
|
|
|
|
|
|
tabbedPane = new JTabbedPane(JTabbedPane.TOP);
|
|
tabbedPane = new JTabbedPane(JTabbedPane.TOP);
|
|
@@ -412,37 +424,53 @@ public class MesClient extends JFrame {
|
|
|
|
|
|
|
|
//首页
|
|
//首页
|
|
|
JPanel indexPanelA = new JPanel();
|
|
JPanel indexPanelA = new JPanel();
|
|
|
- indexScrollPaneA = new JScrollPane(indexPanelA);
|
|
|
|
|
- indexScrollPaneA.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
|
|
|
|
|
- indexScrollPaneA.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
|
|
|
|
indexPanelA.setLayout(null);
|
|
indexPanelA.setLayout(null);
|
|
|
|
|
+ indexPanelA.setBackground(Color.WHITE);
|
|
|
|
|
|
|
|
// 氦检双工位面板:A/B 并排卡片 + 底部日志
|
|
// 氦检双工位面板:A/B 并排卡片 + 底部日志
|
|
|
// 点位顺序:扫码成功、MES允许、检测开始、检测结束、泄露、本底、二维码
|
|
// 点位顺序:扫码成功、MES允许、检测开始、检测结束、泄露、本底、二维码
|
|
|
// 本底、二维码点位待 PLC 确认,先留空
|
|
// 本底、二维码点位待 PLC 确认,先留空
|
|
|
stationA = new StationPanel("A 工位",
|
|
stationA = new StationPanel("A 工位",
|
|
|
- new String[]{"M205", "M206", "M207", "M208", "D200", "--", "--"});
|
|
|
|
|
- stationA.setBounds(10, 10, 460, 440);
|
|
|
|
|
|
|
+ new String[]{"M205", "M206", "M207", "M208", "D200", "--", "D5000"});
|
|
|
|
|
+ stationA.setBounds(10, 10, 460, 375);
|
|
|
indexPanelA.add(stationA);
|
|
indexPanelA.add(stationA);
|
|
|
|
|
|
|
|
stationB = new StationPanel("B 工位",
|
|
stationB = new StationPanel("B 工位",
|
|
|
- new String[]{"M215", "M216", "M217", "M218", "D210", "--", "--"});
|
|
|
|
|
- stationB.setBounds(485, 10, 460, 440);
|
|
|
|
|
|
|
+ new String[]{"M215", "M216", "M217", "M218", "D210", "--", "D6000"});
|
|
|
|
|
+ stationB.setBounds(485, 10, 460, 375);
|
|
|
indexPanelA.add(stationB);
|
|
indexPanelA.add(stationB);
|
|
|
|
|
|
|
|
|
|
+ // A/B 工位之间的分隔竖线
|
|
|
|
|
+ final JPanel divider = new JPanel();
|
|
|
|
|
+ divider.setBackground(new Color(0xBD, 0xBD, 0xBD));
|
|
|
|
|
+ divider.setBounds(472, 10, 2, 375);
|
|
|
|
|
+ indexPanelA.add(divider);
|
|
|
|
|
+
|
|
|
logArea = new JTextArea();
|
|
logArea = new JTextArea();
|
|
|
logArea.setEditable(false);
|
|
logArea.setEditable(false);
|
|
|
logArea.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
logArea.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
|
logArea.setBackground(Color.WHITE);
|
|
logArea.setBackground(Color.WHITE);
|
|
|
logArea.setForeground(Color.BLACK);
|
|
logArea.setForeground(Color.BLACK);
|
|
|
logArea.setMargin(new Insets(6, 8, 6, 8));
|
|
logArea.setMargin(new Insets(6, 8, 6, 8));
|
|
|
- JScrollPane logScrollPane = new JScrollPane(logArea);
|
|
|
|
|
- logScrollPane.setBounds(10, 455, 935, 90);
|
|
|
|
|
|
|
+ final JScrollPane logScrollPane = new JScrollPane(logArea);
|
|
|
|
|
+ logScrollPane.setBounds(10, 390, 935, 150);
|
|
|
indexPanelA.add(logScrollPane);
|
|
indexPanelA.add(logScrollPane);
|
|
|
|
|
|
|
|
- indexPanelA.setPreferredSize(new Dimension(955, 553));
|
|
|
|
|
|
|
+ // 面板宽度变化时整体居中,日志高度跟随窗口
|
|
|
|
|
+ indexPanelA.addComponentListener(new ComponentAdapter() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void componentResized(ComponentEvent e) {
|
|
|
|
|
+ int w = indexPanelA.getWidth();
|
|
|
|
|
+ int h = indexPanelA.getHeight();
|
|
|
|
|
+ int offset = Math.max(10, (w - 935) / 2);
|
|
|
|
|
+ stationA.setBounds(offset, 10, 460, 375);
|
|
|
|
|
+ stationB.setBounds(offset + 475, 10, 460, 375);
|
|
|
|
|
+ divider.setBounds(offset + 472, 10, 2, 375);
|
|
|
|
|
+ logScrollPane.setBounds(offset, 390, 935, Math.max(60, h - 400));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- tabbedPane.addTab("检测面板", new ImageIcon(MesClient.class.getResource("/bg/a_side.png")), indexScrollPaneA, null);
|
|
|
|
|
|
|
+ tabbedPane.addTab("检测面板", new ImageIcon(MesClient.class.getResource("/bg/a_side.png")), indexPanelA, null);
|
|
|
tabbedPane.setEnabledAt(0, true);
|
|
tabbedPane.setEnabledAt(0, true);
|
|
|
|
|
|
|
|
// searchScrollPane = new JScrollPane((Component) null);
|
|
// searchScrollPane = new JScrollPane((Component) null);
|
|
@@ -540,6 +568,84 @@ public class MesClient extends JFrame {
|
|
|
return station == 2 ? stationB : stationA;
|
|
return station == 2 ? stationB : stationA;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // ===== PLC 连接 =====
|
|
|
|
|
+
|
|
|
|
|
+ public static McPlcClient plcClient;
|
|
|
|
|
+ public static java.util.Timer plcTimer;
|
|
|
|
|
+
|
|
|
|
|
+ /** 点顶栏 PLC 状态,读取并显示所有点位当前值 */
|
|
|
|
|
+ public static void showPlcSignals() {
|
|
|
|
|
+ if (plcClient == null) {
|
|
|
|
|
+ plcClient = new McPlcClient(plc_ip, plc_port);
|
|
|
|
|
+ }
|
|
|
|
|
+ new Thread(() -> {
|
|
|
|
|
+ if (!plcClient.isConnected()) {
|
|
|
|
|
+ plcClient.connect();
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!plcClient.isConnected()) {
|
|
|
|
|
+ SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(mesClientFrame,
|
|
|
|
|
+ "PLC 未连接 " + plc_ip + ":" + plc_port, "PLC 信号", JOptionPane.WARNING_MESSAGE));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ appendSignals(sb, "A", "M205", "M206", "M207", "M208", "D200", plc_a_code_addr);
|
|
|
|
|
+ sb.append("\n");
|
|
|
|
|
+ appendSignals(sb, "B", "M215", "M216", "M217", "M218", "D210", plc_b_code_addr);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("PLC 信号:\n" + sb);
|
|
|
|
|
+ JTextArea area = new JTextArea(sb.toString());
|
|
|
|
|
+ area.setEditable(false);
|
|
|
|
|
+ area.setFont(new Font("微软雅黑", Font.PLAIN, 18));
|
|
|
|
|
+ area.setMargin(new Insets(8, 10, 8, 10));
|
|
|
|
|
+ SwingUtilities.invokeLater(() -> JOptionPane.showMessageDialog(mesClientFrame,
|
|
|
|
|
+ new JScrollPane(area), "PLC 信号 " + plc_ip + ":" + plc_port, JOptionPane.INFORMATION_MESSAGE));
|
|
|
|
|
+ }).start();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static void appendSignals(StringBuilder sb, String name,
|
|
|
|
|
+ String scan, String allow, String start, String end,
|
|
|
|
|
+ String leak, String code) {
|
|
|
|
|
+ sb.append(name).append(" 扫码成功(").append(scan).append(") = ").append(plcClient.readBit(scan)).append("\n");
|
|
|
|
|
+ sb.append(name).append(" MES允许(").append(allow).append(") = ").append(plcClient.readBit(allow)).append("\n");
|
|
|
|
|
+ sb.append(name).append(" 检测开始(").append(start).append(") = ").append(plcClient.readBit(start)).append("\n");
|
|
|
|
|
+ sb.append(name).append(" 检测结束(").append(end).append(") = ").append(plcClient.readBit(end)).append("\n");
|
|
|
|
|
+ sb.append(name).append(" 泄露(").append(leak).append(") = ").append(plcClient.readString(leak, 8)).append("\n");
|
|
|
|
|
+ sb.append(name).append(" 条码(").append(code).append(") = ").append(plcClient.readString(code, plc_code_len)).append("\n");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 启动 PLC 连接/重连,登录成功后调用 */
|
|
|
|
|
+ public static void startPlcTimer() {
|
|
|
|
|
+ if (plcTimer != null) {
|
|
|
|
|
+ plcTimer.cancel();
|
|
|
|
|
+ }
|
|
|
|
|
+ plcClient = new McPlcClient(plc_ip, plc_port);
|
|
|
|
|
+ plcTimer = new java.util.Timer(true);
|
|
|
|
|
+ plcTimer.schedule(new TimerTask() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void run() {
|
|
|
|
|
+ if (!plcClient.isConnected()) {
|
|
|
|
|
+ plcClient.connect();
|
|
|
|
|
+ if (plcClient.isConnected()) {
|
|
|
|
|
+ setPlcStatus(true);
|
|
|
|
|
+ addLog("PLC 已连接 " + plc_ip + ":" + plc_port);
|
|
|
|
|
+ String sig = "M205=" + plcClient.readBit("M205") + " M215=" + plcClient.readBit("M215");
|
|
|
|
|
+ addLog(sig);
|
|
|
|
|
+ log.info("PLC 点位: " + sig);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ setPlcStatus(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 心跳检测:主动读一次,断线时读失败会自动标记断开,下一轮重连
|
|
|
|
|
+ plcClient.readBit("M205");
|
|
|
|
|
+ if (!plcClient.isConnected()) {
|
|
|
|
|
+ setPlcStatus(false);
|
|
|
|
|
+ addLog("PLC 连接断开,等待重连");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 0, 3000);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public static void getMaterailData(){
|
|
public static void getMaterailData(){
|
|
|
try{
|
|
try{
|
|
|
JSONObject retObj = DataUtil.getBindMaterail();
|
|
JSONObject retObj = DataUtil.getBindMaterail();
|