|
@@ -9,7 +9,8 @@ import java.util.TimerTask;
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 涂胶 PLC 监控:可改 IP;同一台 PLC 同时显示 a1 / b1 两把胶枪数据。
|
|
|
|
|
|
|
+ * 涂胶 PLC 只读监控(对齐服务端 ProductTjScheduling / ProductTjBScheduling)。
|
|
|
|
|
+ * 唯一写操作:A/B「重置进站」将质量通过位(64.2 / 64.3)置 false。
|
|
|
*/
|
|
*/
|
|
|
public class TjPlcMonitorPanel extends JPanel {
|
|
public class TjPlcMonitorPanel extends JPanel {
|
|
|
|
|
|
|
@@ -17,13 +18,14 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
private final JTextField hostField = new JTextField(16);
|
|
private final JTextField hostField = new JTextField(16);
|
|
|
private final JLabel dbLabel = new JLabel("-");
|
|
private final JLabel dbLabel = new JLabel("-");
|
|
|
|
|
|
|
|
- private final GunView a1View = new GunView("胶枪 A1");
|
|
|
|
|
- private final GunView b1View = new GunView("胶枪 B1");
|
|
|
|
|
|
|
+ private final GunView a1View = new GunView("TJ / OP220", true);
|
|
|
|
|
+ private final GunView b1View = new GunView("TJB / OP240B", false);
|
|
|
|
|
|
|
|
private TjPlcConfig config;
|
|
private TjPlcConfig config;
|
|
|
private TjS7Client s7Client;
|
|
private TjS7Client s7Client;
|
|
|
private Timer timer;
|
|
private Timer timer;
|
|
|
private final AtomicBoolean refreshing = new AtomicBoolean(false);
|
|
private final AtomicBoolean refreshing = new AtomicBoolean(false);
|
|
|
|
|
+ private final AtomicBoolean resetting = new AtomicBoolean(false);
|
|
|
private volatile boolean active;
|
|
private volatile boolean active;
|
|
|
|
|
|
|
|
public TjPlcMonitorPanel() {
|
|
public TjPlcMonitorPanel() {
|
|
@@ -42,7 +44,7 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
|
|
|
|
|
JButton refreshBtn = new JButton("立即刷新");
|
|
JButton refreshBtn = new JButton("立即刷新");
|
|
|
refreshBtn.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
refreshBtn.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
|
- refreshBtn.addActionListener(e -> refreshOnce());
|
|
|
|
|
|
|
+ refreshBtn.addActionListener(e -> refreshOnce(true));
|
|
|
|
|
|
|
|
statusLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
|
|
statusLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
|
|
|
dbLabel.setFont(new Font("Consolas", Font.PLAIN, 16));
|
|
dbLabel.setFont(new Font("Consolas", Font.PLAIN, 16));
|
|
@@ -60,13 +62,18 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
center.add(b1View);
|
|
center.add(b1View);
|
|
|
add(center, BorderLayout.CENTER);
|
|
add(center, BorderLayout.CENTER);
|
|
|
|
|
|
|
|
- loadUiFromConfig();
|
|
|
|
|
|
|
+ loadUiFromConfig(true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void loadUiFromConfig() {
|
|
|
|
|
|
|
+ private void loadUiFromConfig(boolean syncHostField) {
|
|
|
|
|
+ String keepHost = hostField.getText() == null ? "" : hostField.getText().trim();
|
|
|
config = TjPlcConfig.load();
|
|
config = TjPlcConfig.load();
|
|
|
- hostField.setText(config.host);
|
|
|
|
|
- dbLabel.setText("DB" + config.db + " 工作枪=" + config.machine);
|
|
|
|
|
|
|
+ if (syncHostField || keepHost.isEmpty()) {
|
|
|
|
|
+ hostField.setText(config.host);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ config.host = keepHost;
|
|
|
|
|
+ }
|
|
|
|
|
+ dbLabel.setText("DB" + config.db + " 只读监控(作业在服务端)");
|
|
|
a1View.bindAddr(config.a1, config.db);
|
|
a1View.bindAddr(config.a1, config.db);
|
|
|
b1View.bindAddr(config.b1, config.db);
|
|
b1View.bindAddr(config.b1, config.db);
|
|
|
}
|
|
}
|
|
@@ -84,21 +91,19 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
if (s7Client != null) {
|
|
if (s7Client != null) {
|
|
|
s7Client.updateHost(ip);
|
|
s7Client.updateHost(ip);
|
|
|
}
|
|
}
|
|
|
- TjPlcPoller.reloadHost(ip);
|
|
|
|
|
if (ok) {
|
|
if (ok) {
|
|
|
statusLabel.setForeground(new Color(0, 128, 0));
|
|
statusLabel.setForeground(new Color(0, 128, 0));
|
|
|
statusLabel.setText("IP已保存: " + ip);
|
|
statusLabel.setText("IP已保存: " + ip);
|
|
|
- refreshOnce();
|
|
|
|
|
} else {
|
|
} else {
|
|
|
statusLabel.setForeground(Color.ORANGE.darker());
|
|
statusLabel.setForeground(Color.ORANGE.darker());
|
|
|
statusLabel.setText("IP已用于当前连接,但写配置文件失败");
|
|
statusLabel.setText("IP已用于当前连接,但写配置文件失败");
|
|
|
- refreshOnce();
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+ refreshOnce(true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public void startMonitor() {
|
|
public void startMonitor() {
|
|
|
active = true;
|
|
active = true;
|
|
|
- loadUiFromConfig();
|
|
|
|
|
|
|
+ loadUiFromConfig(true);
|
|
|
if (s7Client == null) {
|
|
if (s7Client == null) {
|
|
|
s7Client = new TjS7Client(config);
|
|
s7Client = new TjS7Client(config);
|
|
|
} else {
|
|
} else {
|
|
@@ -112,7 +117,7 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
@Override
|
|
@Override
|
|
|
public void run() {
|
|
public void run() {
|
|
|
if (active) {
|
|
if (active) {
|
|
|
- refreshOnce();
|
|
|
|
|
|
|
+ refreshOnce(true);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}, 200, 1000);
|
|
}, 200, 1000);
|
|
@@ -131,17 +136,20 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
SwingUtilities.invokeLater(() -> statusLabel.setText("已停止刷新"));
|
|
SwingUtilities.invokeLater(() -> statusLabel.setText("已停止刷新"));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private void refreshOnce() {
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param reloadConfig true=从磁盘重载偏移/类型地址(立即刷新与定时刷新都重载,避免改配置后必须重启)
|
|
|
|
|
+ */
|
|
|
|
|
+ private void refreshOnce(boolean reloadConfig) {
|
|
|
if (!refreshing.compareAndSet(false, true)) {
|
|
if (!refreshing.compareAndSet(false, true)) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
- if (config == null) {
|
|
|
|
|
- config = TjPlcConfig.load();
|
|
|
|
|
|
|
+ String ipBefore = hostField.getText() == null ? "" : hostField.getText().trim();
|
|
|
|
|
+ if (reloadConfig || config == null) {
|
|
|
|
|
+ loadUiFromConfig(false);
|
|
|
}
|
|
}
|
|
|
- String ip = hostField.getText() == null ? "" : hostField.getText().trim();
|
|
|
|
|
- if (!ip.isEmpty()) {
|
|
|
|
|
- config.host = ip;
|
|
|
|
|
|
|
+ if (!ipBefore.isEmpty()) {
|
|
|
|
|
+ config.host = ipBefore;
|
|
|
}
|
|
}
|
|
|
if (s7Client == null) {
|
|
if (s7Client == null) {
|
|
|
s7Client = new TjS7Client(config);
|
|
s7Client = new TjS7Client(config);
|
|
@@ -163,16 +171,16 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
statusLabel.setText("已连接 · 实时刷新中");
|
|
statusLabel.setText("已连接 · 实时刷新中");
|
|
|
} else if (connDead) {
|
|
} else if (connDead) {
|
|
|
statusLabel.setForeground(Color.RED);
|
|
statusLabel.setForeground(Color.RED);
|
|
|
- statusLabel.setText("A1/B1均失败: " + shorten(a1.firstError()));
|
|
|
|
|
|
|
+ statusLabel.setText("TJ/TJB均失败: " + shorten(a1.firstError()));
|
|
|
} else if (!a1Ok && !b1Ok) {
|
|
} else if (!a1Ok && !b1Ok) {
|
|
|
statusLabel.setForeground(Color.RED);
|
|
statusLabel.setForeground(Color.RED);
|
|
|
- statusLabel.setText("A1失败[" + a1.firstFailAddr + "] B1失败[" + b1.firstFailAddr + "]");
|
|
|
|
|
|
|
+ statusLabel.setText("TJ失败[" + a1.firstFailAddr + "] TJB失败[" + b1.firstFailAddr + "]");
|
|
|
} else if (!a1Ok) {
|
|
} else if (!a1Ok) {
|
|
|
statusLabel.setForeground(Color.RED);
|
|
statusLabel.setForeground(Color.RED);
|
|
|
- statusLabel.setText("A1失败[" + a1.firstFailAddr + "]: " + shorten(a1.firstError()));
|
|
|
|
|
|
|
+ statusLabel.setText("TJ失败[" + a1.firstFailAddr + "]: " + shorten(a1.firstError()));
|
|
|
} else {
|
|
} else {
|
|
|
statusLabel.setForeground(Color.RED);
|
|
statusLabel.setForeground(Color.RED);
|
|
|
- statusLabel.setText("B1失败[" + b1.firstFailAddr + "]: " + shorten(b1.firstError()));
|
|
|
|
|
|
|
+ statusLabel.setText("TJB失败[" + b1.firstFailAddr + "]: " + shorten(b1.firstError()));
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
|
|
@@ -195,6 +203,52 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private void resetAllowEntry(boolean isA) {
|
|
|
|
|
+ if (!resetting.compareAndSet(false, true)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ final String side = isA ? "TJ/OP220" : "TJB/OP240B";
|
|
|
|
|
+ final String addrHint = isA ? "DB1300.DBX64.2" : "DB1300.DBX64.3";
|
|
|
|
|
+ int confirm = JOptionPane.showConfirmDialog(this,
|
|
|
|
|
+ "确认将 " + side + " 质量校验通过(允许进站)置为 0?\n地址: " + addrHint,
|
|
|
|
|
+ "重置进站", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
|
|
|
|
|
+ if (confirm != JOptionPane.YES_OPTION) {
|
|
|
|
|
+ resetting.set(false);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ new Thread(() -> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ if (config == null) {
|
|
|
|
|
+ loadUiFromConfig(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ String ip = hostField.getText() == null ? "" : hostField.getText().trim();
|
|
|
|
|
+ if (!ip.isEmpty()) {
|
|
|
|
|
+ config.host = ip;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (s7Client == null) {
|
|
|
|
|
+ s7Client = new TjS7Client(config);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ s7Client.updateHost(config.host);
|
|
|
|
|
+ }
|
|
|
|
|
+ TjPlcConfig.GunAddr gun = isA ? config.a1 : config.b1;
|
|
|
|
|
+ s7Client.writeBit(gun.allowEntryByte, gun.allowEntryBit, false);
|
|
|
|
|
+ SwingUtilities.invokeLater(() -> {
|
|
|
|
|
+ statusLabel.setForeground(new Color(0, 128, 0));
|
|
|
|
|
+ statusLabel.setText(side + " 已重置进站位=0 (" + gun.allowEntryAddr(config.db) + ")");
|
|
|
|
|
+ });
|
|
|
|
|
+ refreshOnce(false);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ final String msg = e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage();
|
|
|
|
|
+ SwingUtilities.invokeLater(() -> {
|
|
|
|
|
+ statusLabel.setForeground(Color.RED);
|
|
|
|
|
+ statusLabel.setText(side + " 重置失败: " + shorten(msg));
|
|
|
|
|
+ });
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ resetting.set(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, "TjResetAllowEntry").start();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private static String shorten(String msg) {
|
|
private static String shorten(String msg) {
|
|
|
if (msg == null) {
|
|
if (msg == null) {
|
|
|
return "";
|
|
return "";
|
|
@@ -224,7 +278,6 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
gun.seqAddr(config.db), s);
|
|
gun.seqAddr(config.db), s);
|
|
|
s.glueSpeed = readText(() -> String.format("%.3f", s7Client.readFloat(gun.glueSpeedOffset)),
|
|
s.glueSpeed = readText(() -> String.format("%.3f", s7Client.readFloat(gun.glueSpeedOffset)),
|
|
|
gun.glueSpeedAddr(config.db), s);
|
|
gun.glueSpeedAddr(config.db), s);
|
|
|
- // 涂胶长度:Word
|
|
|
|
|
s.glueLength = readText(() -> String.valueOf(s7Client.readUInt16(gun.glueLengthOffset)),
|
|
s.glueLength = readText(() -> String.valueOf(s7Client.readUInt16(gun.glueLengthOffset)),
|
|
|
gun.glueLengthAddr(config.db), s);
|
|
gun.glueLengthAddr(config.db), s);
|
|
|
return s;
|
|
return s;
|
|
@@ -293,7 +346,8 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static class GunView extends JPanel {
|
|
|
|
|
|
|
+ private class GunView extends JPanel {
|
|
|
|
|
+ private final boolean isA;
|
|
|
private final JLabel frameCode = valueLabel();
|
|
private final JLabel frameCode = valueLabel();
|
|
|
private final JLabel scanFeedback = valueLabel();
|
|
private final JLabel scanFeedback = valueLabel();
|
|
|
private final JLabel allowEntry = valueLabel();
|
|
private final JLabel allowEntry = valueLabel();
|
|
@@ -312,7 +366,8 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
private final JLabel glueSpeedAddr = addrLabel();
|
|
private final JLabel glueSpeedAddr = addrLabel();
|
|
|
private final JLabel glueLengthAddr = addrLabel();
|
|
private final JLabel glueLengthAddr = addrLabel();
|
|
|
|
|
|
|
|
- GunView(String title) {
|
|
|
|
|
|
|
+ GunView(String title, boolean isA) {
|
|
|
|
|
+ this.isA = isA;
|
|
|
setLayout(new GridBagLayout());
|
|
setLayout(new GridBagLayout());
|
|
|
setBorder(BorderFactory.createTitledBorder(
|
|
setBorder(BorderFactory.createTitledBorder(
|
|
|
BorderFactory.createEtchedBorder(), title,
|
|
BorderFactory.createEtchedBorder(), title,
|
|
@@ -325,12 +380,26 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
int row = 0;
|
|
int row = 0;
|
|
|
row = addRow(c, row, "框架码", frameCode, frameCodeAddr);
|
|
row = addRow(c, row, "框架码", frameCode, frameCodeAddr);
|
|
|
row = addRow(c, row, "扫码反馈", scanFeedback, scanFeedbackAddr);
|
|
row = addRow(c, row, "扫码反馈", scanFeedback, scanFeedbackAddr);
|
|
|
- row = addRow(c, row, "允许进站", allowEntry, allowEntryAddr);
|
|
|
|
|
- row = addRow(c, row, "单道结束", pathDone, pathDoneAddr);
|
|
|
|
|
- row = addRow(c, row, "全部结束", allDone, allDoneAddr);
|
|
|
|
|
|
|
+ row = addRow(c, row, "质量校验通过", allowEntry, allowEntryAddr);
|
|
|
|
|
+ row = addRow(c, row, "涂胶采集触发", pathDone, pathDoneAddr);
|
|
|
|
|
+ row = addRow(c, row, "整体完成", allDone, allDoneAddr);
|
|
|
row = addRow(c, row, "涂胶序号", seq, seqAddr);
|
|
row = addRow(c, row, "涂胶序号", seq, seqAddr);
|
|
|
row = addRow(c, row, "涂胶速度", glueSpeed, glueSpeedAddr);
|
|
row = addRow(c, row, "涂胶速度", glueSpeed, glueSpeedAddr);
|
|
|
- addRow(c, row, "涂胶长度", glueLength, glueLengthAddr);
|
|
|
|
|
|
|
+ row = addRow(c, row, "涂胶长度", glueLength, glueLengthAddr);
|
|
|
|
|
+
|
|
|
|
|
+ JButton resetBtn = new JButton("重置进站");
|
|
|
|
|
+ resetBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));
|
|
|
|
|
+ resetBtn.setMargin(new Insets(2, 8, 2, 8));
|
|
|
|
|
+ resetBtn.setPreferredSize(new Dimension(88, 26));
|
|
|
|
|
+ resetBtn.setToolTipText("将质量校验通过位写 0(A=64.2 / B=64.3)");
|
|
|
|
|
+ resetBtn.addActionListener(e -> resetAllowEntry(this.isA));
|
|
|
|
|
+ c.gridx = 0;
|
|
|
|
|
+ c.gridy = row;
|
|
|
|
|
+ c.gridwidth = 1;
|
|
|
|
|
+ c.weightx = 0;
|
|
|
|
|
+ c.fill = GridBagConstraints.NONE;
|
|
|
|
|
+ c.anchor = GridBagConstraints.WEST;
|
|
|
|
|
+ add(resetBtn, c);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private int addRow(GridBagConstraints c, int row, String title, JLabel value, JLabel addr) {
|
|
private int addRow(GridBagConstraints c, int row, String title, JLabel value, JLabel addr) {
|
|
@@ -338,6 +407,7 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
name.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
name.setFont(new Font("微软雅黑", Font.PLAIN, 16));
|
|
|
c.gridx = 0;
|
|
c.gridx = 0;
|
|
|
c.gridy = row;
|
|
c.gridy = row;
|
|
|
|
|
+ c.gridwidth = 1;
|
|
|
c.weightx = 0;
|
|
c.weightx = 0;
|
|
|
add(name, c);
|
|
add(name, c);
|
|
|
c.gridx = 1;
|
|
c.gridx = 1;
|
|
@@ -371,18 +441,18 @@ public class TjPlcMonitorPanel extends JPanel {
|
|
|
setField(glueLength, s.glueLength);
|
|
setField(glueLength, s.glueLength);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static void setField(JLabel label, FieldVal fv) {
|
|
|
|
|
|
|
+ private void setField(JLabel label, FieldVal fv) {
|
|
|
label.setText(fv.text);
|
|
label.setText(fv.text);
|
|
|
label.setForeground(fv.ok ? Color.BLACK : Color.RED);
|
|
label.setForeground(fv.ok ? Color.BLACK : Color.RED);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static JLabel valueLabel() {
|
|
|
|
|
|
|
+ private JLabel valueLabel() {
|
|
|
JLabel l = new JLabel("-");
|
|
JLabel l = new JLabel("-");
|
|
|
l.setFont(new Font("微软雅黑", Font.BOLD, 18));
|
|
l.setFont(new Font("微软雅黑", Font.BOLD, 18));
|
|
|
return l;
|
|
return l;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static JLabel addrLabel() {
|
|
|
|
|
|
|
+ private JLabel addrLabel() {
|
|
|
JLabel l = new JLabel("-");
|
|
JLabel l = new JLabel("-");
|
|
|
l.setFont(new Font("Consolas", Font.PLAIN, 13));
|
|
l.setFont(new Font("Consolas", Font.PLAIN, 13));
|
|
|
l.setForeground(Color.DARK_GRAY);
|
|
l.setForeground(Color.DARK_GRAY);
|