LaserController.java 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. package com.mes.controller;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.mes.device.LaserDevice;
  4. import com.mes.ui.MesClient;
  5. import com.mes.util.DateLocalUtils;
  6. import com.mes.util.JdbcUtils;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import java.util.ArrayList;
  10. import java.util.List;
  11. /**
  12. * 激光切割设备控制器
  13. * 参考OP60焊接PlcUtil的模式
  14. */
  15. public class LaserController {
  16. private static final Logger log = LoggerFactory.getLogger(LaserController.class);
  17. private LaserDevice device;
  18. // 状态机 0=未开始 1=已扫码等待启动 2=设备运行中 3=设备运行结束
  19. public static Integer tjFlag = 0;
  20. // 当前工件号
  21. public static String curSn = "";
  22. // 参数采集缓存(60条批量存储)
  23. public static List<String> hjparams = new ArrayList<>();
  24. // 上传失败标志
  25. public static Integer tjStatus = 0; // 1=提交失败
  26. // 开始时间
  27. private long startTime = 0;
  28. // 宏变量地址配置
  29. private static final int MACRO_MES_ENABLE = 3100; // MES允许启动
  30. private static final int MACRO_SPEED = 33563; // 进给速度
  31. private static final int MACRO_TIME = 33868; // 加工时间
  32. private static final int MACRO_COUNT = 33870; // 零件计数
  33. // PLC变量地址配置
  34. private static final String PLC_RUNNING = "42.0"; // 运行中 MO42.0
  35. private static final String PLC_STOPPED = "42.2"; // 停止 MO42.2
  36. private static final String PLC_READY = "42.3"; // 就绪 MO42.3
  37. private static final int PLC_TYPE_MO = 1; // MO类型
  38. public LaserController(LaserDevice device) {
  39. this.device = device;
  40. }
  41. /**
  42. * 扫码处理(参考OP60)
  43. */
  44. public boolean onScanCode(String sn, String user) {
  45. try {
  46. // 检查状态
  47. if(tjFlag != 0) {
  48. log.warn("上一个工件未完成,不能扫码");
  49. MesClient.showError("上一个工件未完成");
  50. return false;
  51. }
  52. // 检查设备连接
  53. if(!device.isConnected()) {
  54. log.error("设备未连接");
  55. MesClient.showError("设备未连接");
  56. return false;
  57. }
  58. log.info("扫码: {}", sn);
  59. // 1. MES质检(这里需要调用MES接口)
  60. // TODO: 调用checkQuality接口
  61. // 2. 开始加工(通知MES)
  62. // TODO: 调用startWork接口
  63. // 3. 写MES允许启动信号
  64. boolean writeResult = device.writeMacro(MACRO_MES_ENABLE, 1.0);
  65. if(!writeResult) {
  66. log.error("写入MES允许信号失败");
  67. MesClient.showError("写入MES允许信号失败");
  68. return false;
  69. }
  70. // 4. 切换状态
  71. tjFlag = 1;
  72. curSn = sn;
  73. startTime = System.currentTimeMillis();
  74. log.info("扫码成功,等待操作员启动设备");
  75. return true;
  76. } catch (Exception e) {
  77. log.error("扫码处理异常", e);
  78. return false;
  79. }
  80. }
  81. /**
  82. * 状态检测(1秒调用1次,参考OP60的getPlcParam)
  83. */
  84. public void checkStatus() {
  85. try {
  86. if(!device.isConnected()) {
  87. return;
  88. }
  89. // 根据状态执行不同逻辑
  90. if(tjFlag == 1) {
  91. checkStart(); // 检测启动
  92. } else if(tjFlag == 2) {
  93. checkFinish(); // 检测完成
  94. }
  95. } catch (Exception e) {
  96. log.error("状态检测异常", e);
  97. }
  98. }
  99. /**
  100. * 检测设备是否启动(参考OP60的getStatusA)
  101. */
  102. private void checkStart() {
  103. try {
  104. // 读取运行状态 MO42.0
  105. long running = device.readPlc(PLC_RUNNING, PLC_TYPE_MO);
  106. if(running == 1) {
  107. // 检测到设备启动
  108. tjFlag = 2;
  109. log.info("检测到设备启动,开始采集参数");
  110. MesClient.updateStatus("设备运行中");
  111. // 记录实际开始时间
  112. startTime = System.currentTimeMillis();
  113. }
  114. } catch (Exception e) {
  115. log.error("检测启动异常", e);
  116. }
  117. }
  118. /**
  119. * 检测设备是否完成(参考OP60的getStatusA)
  120. */
  121. private void checkFinish() {
  122. try {
  123. // 读取停止和就绪状态
  124. long stopped = device.readPlc(PLC_STOPPED, PLC_TYPE_MO);
  125. long ready = device.readPlc(PLC_READY, PLC_TYPE_MO);
  126. if(stopped == 1 && ready == 1) {
  127. // 设备完成
  128. tjFlag = 3;
  129. log.info("检测到设备完成");
  130. MesClient.updateStatus("设备运行结束,提交结果中");
  131. // 保存剩余参数
  132. if(hjparams.size() > 0) {
  133. saveParams();
  134. }
  135. // 上传结果到MES
  136. boolean sendret = sendQuality(curSn, "OK");
  137. if(!sendret) {
  138. // 上传失败
  139. tjStatus = 1;
  140. log.error("结果上传MES失败");
  141. MesClient.updateStatus("结果上传MES失败");
  142. } else {
  143. // 上传成功,复位
  144. log.info("结果上传成功,复位状态");
  145. resetStatus();
  146. MesClient.updateStatus("提交成功");
  147. }
  148. }
  149. } catch (Exception e) {
  150. log.error("检测完成异常", e);
  151. }
  152. }
  153. /**
  154. * 参数采集(1秒调用1次,参考OP60的getPlcParams)
  155. */
  156. public void collectParams() {
  157. try {
  158. if(!device.isConnected()) {
  159. return;
  160. }
  161. // 只有运行中才采集
  162. if(tjFlag != 2) {
  163. return;
  164. }
  165. // 读取系统宏变量
  166. double speed = device.readMacro(MACRO_SPEED); // 进给速度
  167. double time = device.readMacro(MACRO_TIME); // 加工时间
  168. double count = device.readMacro(MACRO_COUNT); // 零件计数
  169. // 拼接参数字符串(参考OP60的格式)
  170. String timestamp = DateLocalUtils.getCurrentTime();
  171. String record = speed + "|" + time + "|" + count + "|" + timestamp;
  172. hjparams.add(record);
  173. log.debug("采集参数: {}", record);
  174. // 满60条存储(参考OP60)
  175. if(hjparams.size() == 60) {
  176. saveParams();
  177. }
  178. } catch (Exception e) {
  179. log.error("参数采集异常", e);
  180. }
  181. }
  182. /**
  183. * 保存参数到SQLite(参考OP60)
  184. */
  185. private void saveParams() {
  186. try {
  187. if(hjparams.size() == 0) {
  188. return;
  189. }
  190. // 检查工件码是否为空
  191. if(curSn == null || curSn.trim().isEmpty()) {
  192. log.warn("工件码为空,跳过保存数据");
  193. hjparams.clear();
  194. return;
  195. }
  196. String oprno = MesClient.mes_gw;
  197. String lineSn = MesClient.mes_line_sn;
  198. String paramsJson = JSON.toJSONString(hjparams);
  199. JdbcUtils.insertLaserData(oprno, lineSn, curSn, paramsJson);
  200. log.info("保存参数: sn={}, count={}", curSn, hjparams.size());
  201. hjparams.clear();
  202. } catch (Exception e) {
  203. log.error("保存参数异常", e);
  204. }
  205. }
  206. /**
  207. * 上传结果到MES(参考OP60的sendQuality)
  208. */
  209. private boolean sendQuality(String sn, String result) {
  210. try {
  211. // TODO: 调用MES接口上传结果
  212. // 参考OP60: DataUtil.sendQuality(nettyClient, sn, result, user, oprno);
  213. // 实际项目中需要实现这个接口
  214. log.info("上传结果: sn={}, result={}", sn, result);
  215. // 暂时返回true,等待实际MES接口对接
  216. return true;
  217. } catch (Exception e) {
  218. log.error("上传结果异常", e);
  219. return false;
  220. }
  221. }
  222. /**
  223. * 更新UI状态(静态方法,供MesClient调用)
  224. */
  225. public static void updateStatusLabel(String text) {
  226. try {
  227. if(MesClient.fxlabel != null) {
  228. MesClient.fxlabel.setText(text);
  229. }
  230. } catch (Exception e) {
  231. log.error("更新状态标签异常", e);
  232. }
  233. }
  234. /**
  235. * 复位状态(完成后调用)
  236. */
  237. private void resetStatus() {
  238. try {
  239. // 1. 复位MES允许信号(激光切割需要,OP60不需要)
  240. device.writeMacro(MACRO_MES_ENABLE, 0.0);
  241. // 2. 清空状态
  242. tjFlag = 0;
  243. curSn = "";
  244. hjparams.clear();
  245. tjStatus = 0;
  246. startTime = 0;
  247. log.info("状态已复位");
  248. } catch (Exception e) {
  249. log.error("复位状态异常", e);
  250. }
  251. }
  252. /**
  253. * 手动复位(上传失败时使用)
  254. */
  255. public void manualReset() {
  256. log.warn("手动复位状态");
  257. resetStatus();
  258. }
  259. /**
  260. * 获取当前状态
  261. */
  262. public int getStatus() {
  263. return tjFlag;
  264. }
  265. /**
  266. * 获取当前工件号
  267. */
  268. public String getCurrentSn() {
  269. return curSn;
  270. }
  271. /**
  272. * 获取运行时长(秒)
  273. */
  274. public long getRunningTime() {
  275. if(startTime == 0) {
  276. return 0;
  277. }
  278. return (System.currentTimeMillis() - startTime) / 1000;
  279. }
  280. }