| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- package com.mes.component;
- import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
- import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
- import com.mes.ui.MesClient;
- import com.mes.util.SnSlot;
- import com.mes.util.TCPClient;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.MouseAdapter;
- import java.awt.event.MouseEvent;
- import java.util.Timer;
- import java.util.TimerTask;
- /**
- * 扫码面板(每台 PLC 一个,92 发 1、2 号枪,93 发 3 号枪,由 PLC 决定)
- * DB7010.0.0 请求扫码 / DB7010.0.1 扫码完成反馈 / DB7010.6(INT) 扫码枪号;0.2、2、4 为预留,不读不写
- * 枪号 0=未发;正常同一时间 92、93 只有一个非 0,PLC 收到扫码完成反馈后清零
- * 请求扫码时 PLC 给几号就触发几号枪,读到 16 位码存入正面扫码槽,正面机台请求上料时取用
- */
- public class WorkJPanelScan extends JPanel {
- public static final Logger log = LoggerFactory.getLogger(WorkJPanelScan.class);
- public static final int SN_LENGTH = 16;
- public String oprno = "OP130";
- public String plcIp;
- public String plcName; // 92 / 93,用于界面和日志
- public String plcDb = "DB7010";
- public String gunAddr = "DB7010.6";
- public S7PLC s7PLC;
- public SnSlot slot;
- public Integer workWidth = 470;
- public Integer workHeight = 300;
- private boolean scanDone = false; // 本次请求已扫码成功,等 PLC 复位请求
- private String lastGunState = ""; // 上次读到的枪号状态,变化时才记日志
- public JButton status_menu;
- public JTextField productSnFeeding; // 扫码槽当前码
- public JTextField gunField; // 本次扫码使用的枪
- public JButton resetFeedingBtn;
- public JLabel feedinglabel; // 0.0 请求扫码
- public JLabel feedingmeslabel; // 0.1 扫码完成反馈
- public JLabel gunNoLabel; // DB7010.6 实时枪号
- public ImageIcon imageGreen;
- public ImageIcon imageGray;
- public JButton signalBtn;
- public PlcSignalMonitor02 signalMonitor;
- public Timer oprnoTimer;
- public WorkJPanelScan(String plcIp) {
- this.setLayout(null);
- this.setBackground(Color.WHITE);
- this.plcIp = plcIp;
- this.plcName = plcIp.substring(plcIp.lastIndexOf('.') + 1);
- this.slot = MesClient.frontSlot;
- s7PLC = new S7PLC(EPlcType.S1500, plcIp);
- s7PLC.setConnectTimeout(1000);
- s7PLC.setReceiveTimeout(1000);
- initUI();
- productSnFeeding.setText(slot.getSn());
- setMenuStatus("等待请求扫码", 0);
- startOprnoTimer();
- }
- private String tag() {
- return oprno + "扫码" + plcName;
- }
- private void initUI() {
- JLabel oprnoLabel = new JLabel(oprno);
- oprnoLabel.setHorizontalAlignment(SwingConstants.CENTER);
- oprnoLabel.setForeground(Color.BLACK);
- oprnoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
- oprnoLabel.setBounds(0, 0, workWidth / 5, 40);
- this.add(oprnoLabel);
- JLabel nameLabel = new JLabel(plcName + "扫码");
- nameLabel.setHorizontalAlignment(SwingConstants.CENTER);
- nameLabel.setForeground(Color.BLACK);
- nameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
- nameLabel.setBounds(0, 17, workWidth / 5, 40);
- this.add(nameLabel);
- status_menu = new JButton("等待请求扫码");
- status_menu.setBounds(workWidth / 5, 0, workWidth * 4 / 5, 40);
- status_menu.setForeground(Color.GREEN);
- status_menu.setFont(new Font("微软雅黑", Font.PLAIN, 16));
- status_menu.setBackground(Color.BLACK);
- this.add(status_menu);
- addRowLabel("扫码", 50);
- productSnFeeding = createField(50, workWidth * 3 / 5);
- productSnFeeding.addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- String sn = productSnFeeding.getText().trim();
- if (!sn.isEmpty()) {
- MesClient.createQRCode(sn, tag());
- }
- }
- });
- resetFeedingBtn = new JButton("清空");
- resetFeedingBtn.setFont(new Font("微软雅黑", Font.PLAIN, 22));
- resetFeedingBtn.setBounds(workWidth * 4 / 5 + 10, 50, workWidth / 5 - 10, 40);
- resetFeedingBtn.addActionListener(e -> {
- String sn = slot.getSn();
- if (sn.isEmpty()) {
- return;
- }
- if (confirm("确定清空扫码结果" + sn + "吗?\n请求扫码仍在时会重新扫码")) {
- resetScan();
- }
- });
- this.add(resetFeedingBtn);
- addRowLabel("扫码枪", 100);
- gunField = createField(100, workWidth * 4 / 5);
- gunField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
- gunField.setText("未扫码");
- imageGreen = scaledIcon("/bg/green_dot.png");
- imageGray = scaledIcon("/bg/grey_dot.png");
- feedinglabel = createLight("请求扫码", 0, 150);
- feedingmeslabel = createLight("扫码完成反馈", workWidth / 3, 150);
- feedingmeslabel.addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- boolean ret = readBoolean(plcDb + ".0.1");
- if (confirm("确定修改" + plcName + "扫码完成反馈(" + plcDb + ".0.1)为" + !ret + "吗?")) {
- writeScanFinish(!ret);
- }
- }
- });
- // 实时显示 PLC 给的枪号(DB7010.6),每轮刷新
- gunNoLabel = new JLabel("PLC枪号:-");
- gunNoLabel.setHorizontalAlignment(SwingConstants.LEFT);
- gunNoLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
- gunNoLabel.setForeground(Color.DARK_GRAY);
- gunNoLabel.setBounds(workWidth * 2 / 3, 150, workWidth / 3, 30);
- this.add(gunNoLabel);
- JLabel ipLabel = new JLabel("PLC " + plcIp + " | " + plcDb + " | 枪号 " + gunAddr);
- ipLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
- ipLabel.setForeground(Color.DARK_GRAY);
- ipLabel.setBounds(5, 230, workWidth * 2 / 3 + 55, 26);
- this.add(ipLabel);
- signalMonitor = new PlcSignalMonitor02(s7PLC, plcDb, gunAddr, tag(), MesClient.mesClientFrame);
- signalBtn = signalMonitor.createSignalButton();
- signalBtn.setBounds(workWidth * 2 / 3 + 63, 230, 90, 26);
- this.add(signalBtn);
- }
- private void addRowLabel(String text, int y) {
- JLabel label = new JLabel(text);
- label.setHorizontalAlignment(SwingConstants.CENTER);
- label.setForeground(Color.BLACK);
- label.setFont(new Font("微软雅黑", Font.PLAIN, 20));
- label.setBounds(0, y, workWidth / 5, 40);
- this.add(label);
- }
- private JTextField createField(int y, int width) {
- JTextField field = new JTextField("");
- field.setHorizontalAlignment(SwingConstants.CENTER);
- field.setForeground(Color.BLACK);
- field.setFont(new Font("微软雅黑", Font.PLAIN, 16));
- field.setEditable(false);
- field.setBounds(workWidth / 5, y, width, 40);
- this.add(field);
- return field;
- }
- private JLabel createLight(String text, int x, int y) {
- JLabel label = new JLabel(text);
- label.setHorizontalAlignment(SwingConstants.LEFT);
- label.setIcon(imageGray);
- label.setForeground(Color.BLACK);
- label.setBounds(x, y, workWidth / 3, 30);
- this.add(label);
- return label;
- }
- private static ImageIcon scaledIcon(String path) {
- ImageIcon icon = new ImageIcon(MesClient.class.getResource(path));
- icon.setImage(icon.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH));
- return icon;
- }
- private static boolean confirm(String msg) {
- return JOptionPane.showConfirmDialog(null, msg, "操作确认", JOptionPane.YES_NO_OPTION,
- JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION;
- }
- public void setMenuStatus(String msg, int error) {
- status_menu.setForeground(error == 0 ? Color.GREEN : Color.RED);
- status_menu.setText(msg);
- }
- // scan.ips 里配了这把枪即有效,PLC 发几号就用几号
- private boolean isValidGun(int no) {
- return no >= 1 && no <= MesClient.scanClients.length;
- }
- // 定时任务 -----------------------------------------------------------------------------------------------------
- public void startOprnoTimer() {
- if (oprnoTimer != null) {
- oprnoTimer.cancel();
- }
- oprnoTimer = new Timer();
- oprnoTimer.schedule(new TimerTask() {
- public void run() {
- try {
- if (MesClient.isLogin == 1) {
- cycle();
- }
- } catch (Exception e) {
- log.error("<{}>轮询异常", tag(), e);
- }
- }
- }, 100, 1500);
- }
- private void cycle() {
- boolean retScan = readBoolean(plcDb + ".0.0");
- boolean retFinish = readBoolean(plcDb + ".0.1");
- feedinglabel.setIcon(retScan ? imageGreen : imageGray);
- feedingmeslabel.setIcon(retFinish ? imageGreen : imageGray);
- Integer plcGunNo = readGunNo();
- showGunNo(plcGunNo);
- // 显示扫码槽当前码,被正面机台取走后变空
- productSnFeeding.setText(slot.getSn());
- if (!retScan) {
- scanDone = false;
- if (retFinish) {
- writeScanFinish(false);
- }
- return;
- }
- if (scanDone) {
- if (!retFinish) {
- writeScanFinish(true);
- }
- return;
- }
- doScan(plcGunNo);
- }
- // 刷新界面上的 PLC 枪号:0=未发(灰),1-3 绿色,其他值/读不到红色
- private void showGunNo(Integer no) {
- if (no == null) {
- gunNoLabel.setForeground(Color.RED);
- gunNoLabel.setText("PLC枪号:读取失败");
- gunNoLabel.setToolTipText(gunAddr + " 读取失败,不扫码");
- return;
- }
- if (no == 0) {
- gunNoLabel.setForeground(Color.GRAY);
- gunNoLabel.setText("PLC枪号:0(未发)");
- gunNoLabel.setToolTipText("本PLC未发枪号");
- return;
- }
- boolean valid = isValidGun(no);
- gunNoLabel.setForeground(valid ? new Color(0, 128, 0) : Color.RED);
- gunNoLabel.setText("PLC枪号:" + no + (valid ? "" : "(无效)"));
- gunNoLabel.setToolTipText(valid ? no + "号枪 " + MesClient.scanClients[no - 1].serverIP : "有效范围 1-" + MesClient.scanClients.length);
- }
- private void doScan(Integer plcGunNo) {
- // 读不到枪号不扫码
- if (plcGunNo == null) {
- gunField.setText("未读到枪号");
- setMenuStatus("读取" + gunAddr + "失败,不扫码", -1);
- return;
- }
- int gunNo = plcGunNo;
- // 0 = PLC 还没发枪号,等下一轮
- if (gunNo == 0) {
- setMenuStatus("请求扫码,等待PLC发枪号", 0);
- return;
- }
- if (!isValidGun(gunNo)) {
- gunField.setText("枪号 " + gunNo + " 无效");
- setMenuStatus("扫码枪号无效:" + gunNo + "(" + gunAddr + " 应为 1-" + MesClient.scanClients.length + ")", -1);
- return;
- }
- TCPClient client = MesClient.scanClients[gunNo - 1];
- gunField.setText(gunNo + "号枪 " + client.serverIP + ":" + client.serverPort);
- setMenuStatus(gunNo + "号枪扫码中...", 0);
- String sn = MesClient.scanQrcode(gunNo);
- if (sn.length() != SN_LENGTH) {
- String reason = sn.isEmpty() ? "未读到码" : "码长度" + sn.length() + "位";
- setMenuStatus(gunNo + "号枪扫码失败(" + reason + "),重试中", -1);
- return;
- }
- slot.put(sn, gunNo + "号枪(" + plcName + ")");
- productSnFeeding.setText(sn);
- writeScanFinish(true);
- scanDone = true;
- setMenuStatus("扫码成功", 0);
- }
- public void resetScan() {
- slot.clear("人工清空(" + plcName + ")");
- productSnFeeding.setText("");
- scanDone = false;
- writeScanFinish(false);
- setMenuStatus("扫码结果已清空,等待请求扫码", 0);
- }
- // 与设备交互 -----------------------------------------------------------------------------------------
- // 读扫码枪号,读失败返回 null;每轮都读,只在值变化时记日志
- private Integer readGunNo() {
- Integer no = null;
- String err = "";
- try {
- no = (int) s7PLC.readInt16(gunAddr);
- } catch (Exception e) {
- err = e.getMessage();
- }
- String state = no == null ? "ERR" : String.valueOf(no);
- if (!state.equals(lastGunState)) {
- lastGunState = state;
- if (no == null) {
- log.warn("<{}>读取{}-->失败,不扫码:{}", tag(), gunAddr, err);
- } else {
- log.info("<{}>读取{}-->枪号变为:{}", tag(), gunAddr, no);
- }
- }
- return no;
- }
- public void writeScanFinish(boolean b) {
- writeBoolean(plcDb + ".0.1", b);
- }
- public boolean readBoolean(String addr) {
- try {
- return s7PLC.readBoolean(addr);
- } catch (Exception e) {
- log.error("<{}>读取{}-->失败:{}", tag(), addr, e.getMessage());
- return false;
- }
- }
- public boolean writeBoolean(String addr, boolean value) {
- try {
- s7PLC.writeBoolean(addr, value);
- log.info("<{}>写入{}-->成功,写入内容:{}", tag(), addr, value);
- return true;
- } catch (Exception e) {
- log.error("<{}>写入{}-->失败,写入内容:{},{}", tag(), addr, value, e.getMessage());
- return false;
- }
- }
- }
|