HeliumFlow.java 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package com.mes.plc;
  2. import com.alibaba.fastjson2.JSONObject;
  3. import com.mes.component.StationPanel;
  4. import com.mes.ui.DataUtil;
  5. import com.mes.ui.MesClient;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. /**
  9. * 氦检单工位流程:
  10. * M205 上升沿 → 读条码 → 复位 M205 → 校验 → 写 M206
  11. * M207 上升沿 → 清 M206 → 检测中
  12. * M208 上升沿 → 读泄露 → 显示结果
  13. *
  14. * 开始/结束信号是保持电平,只在 0→1 时触发
  15. */
  16. public class HeliumFlow {
  17. private static final Logger log = LoggerFactory.getLogger(HeliumFlow.class);
  18. private final int station;
  19. private final McPlcClient plc;
  20. private final StationPanel ui;
  21. private final String scanAddr;
  22. private final String allowAddr;
  23. private final String startAddr;
  24. private final String endAddr;
  25. private final String leakAddr;
  26. private final String codeAddr;
  27. private boolean initialized = false;
  28. private boolean lastScan = false; // 启动时若已扫码,也要处理
  29. private boolean lastStart;
  30. private boolean lastEnd;
  31. private String currentSn = "";
  32. public HeliumFlow(int station, McPlcClient plc, StationPanel ui,
  33. String scanAddr, String allowAddr, String startAddr, String endAddr,
  34. String leakAddr, String codeAddr) {
  35. this.station = station;
  36. this.plc = plc;
  37. this.ui = ui;
  38. this.scanAddr = scanAddr;
  39. this.allowAddr = allowAddr;
  40. this.startAddr = startAddr;
  41. this.endAddr = endAddr;
  42. this.leakAddr = leakAddr;
  43. this.codeAddr = codeAddr;
  44. }
  45. private String name() {
  46. return station == 2 ? "B" : "A";
  47. }
  48. /** 启动时同步开始/结束信号的当前电平,避免误触发 */
  49. private void init() {
  50. Boolean start = plc.tryReadBit(startAddr);
  51. Boolean end = plc.tryReadBit(endAddr);
  52. if (start == null || end == null) {
  53. return; // 通信未就绪,下轮再同步
  54. }
  55. lastStart = start;
  56. lastEnd = end;
  57. initialized = true;
  58. log.info(name() + " 工位流程初始化: start=" + start + " end=" + end);
  59. }
  60. public void poll() {
  61. if (!initialized) {
  62. init();
  63. return;
  64. }
  65. if (!plc.isConnected()) {
  66. initialized = false;
  67. return;
  68. }
  69. Boolean scan = plc.tryReadBit(scanAddr);
  70. Boolean start = plc.tryReadBit(startAddr);
  71. Boolean end = plc.tryReadBit(endAddr);
  72. if (scan == null || start == null || end == null) {
  73. return; // 本轮通信异常,跳过
  74. }
  75. if (scan && !lastScan) {
  76. onScan();
  77. }
  78. lastScan = scan;
  79. if (start && !lastStart) {
  80. onStart();
  81. }
  82. lastStart = start;
  83. if (end && !lastEnd) {
  84. onEnd();
  85. }
  86. lastEnd = end;
  87. }
  88. /** 扫码:读码 → 复位扫码信号 → 查质量 → 写允许位 */
  89. private void onScan() {
  90. String code = plc.readString(codeAddr, MesClient.plc_code_len);
  91. if (code == null || code.isEmpty()) {
  92. MesClient.addLog(name() + " 扫码信号已到,但条码为空,等待重试");
  93. return;
  94. }
  95. currentSn = code;
  96. ui.setCode(code);
  97. ui.setSignal(StationPanel.SIG_SCAN, true);
  98. ui.setSignal(StationPanel.SIG_CODE, true);
  99. ui.setState("校验中", StationPanel.STATE_BUSY);
  100. MesClient.addLog(name() + " 读到条码 " + code);
  101. // 读码成功后复位扫码成功信号
  102. plc.writeBit(scanAddr, false);
  103. MesClient.getUser();
  104. JSONObject ret = DataUtil.checkQuality(code, MesClient.user20);
  105. boolean allow = ret != null && "true".equalsIgnoreCase(String.valueOf(ret.get("result")));
  106. plc.writeBit(allowAddr, allow);
  107. ui.setSignal(StationPanel.SIG_ALLOW, allow);
  108. if (allow) {
  109. ui.setState("允许运行", StationPanel.STATE_OK);
  110. MesClient.addLog(name() + " 校验通过,允许运行");
  111. } else {
  112. currentSn = ""; // 禁止运行,不参与后续提交
  113. ui.setState("禁止运行", StationPanel.STATE_NG);
  114. String msg = ret == null ? "请求失败" : ret.getString("message");
  115. MesClient.addLog(name() + " 禁止运行:" + msg);
  116. }
  117. }
  118. /** 检测开始:清允许位,界面进入检测中 */
  119. private void onStart() {
  120. plc.writeBit(allowAddr, false);
  121. ui.setSignal(StationPanel.SIG_ALLOW, false);
  122. ui.setSignal(StationPanel.SIG_START, true);
  123. ui.setState("检测中", StationPanel.STATE_RUN);
  124. MesClient.addLog(name() + " 检测开始");
  125. }
  126. /** 检测结束:读泄露,提交结果 */
  127. private void onEnd() {
  128. String leak = plc.readString(leakAddr, 8);
  129. ui.setData(null, leak);
  130. ui.setSignal(StationPanel.SIG_LEAK, !leak.isEmpty());
  131. ui.setSignal(StationPanel.SIG_END, true);
  132. MesClient.addLog(name() + " 检测结束,泄露=" + leak);
  133. if (currentSn.isEmpty()) {
  134. MesClient.addLog(name() + " 无当前条码,跳过提交");
  135. return;
  136. }
  137. // 设备判定结果点位待补,当前按 OK 提交
  138. String result = "OK";
  139. ui.setState("上传中", StationPanel.STATE_BUSY);
  140. MesClient.getUser();
  141. JSONObject ret = DataUtil.sendQuality(currentSn, result, MesClient.user20);
  142. boolean ok = ret != null && "true".equalsIgnoreCase(String.valueOf(ret.get("result")));
  143. if (ok) {
  144. ui.setResult(result);
  145. ui.setState("检测完成", StationPanel.STATE_OK);
  146. MesClient.addLog(name() + " 结果已提交 " + currentSn + " " + result);
  147. } else {
  148. ui.setState("提交失败", StationPanel.STATE_NG);
  149. MesClient.addLog(name() + " 结果提交失败:" + (ret == null ? "请求失败" : ret.getString("message")));
  150. }
  151. }
  152. }