WorkJPanelOP40.java 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. package com.mes.component;
  2. import com.alibaba.fastjson2.JSON;
  3. import com.alibaba.fastjson2.JSONObject;
  4. import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
  5. import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
  6. import com.mes.ui.CacheData;
  7. import com.mes.ui.DataUtil;
  8. import com.mes.ui.MesClient;
  9. import com.mes.util.JdbcUtils;
  10. import com.mes.util.TCPClient;
  11. import org.slf4j.Logger;
  12. import org.slf4j.LoggerFactory;
  13. import javax.swing.*;
  14. import java.awt.*;
  15. import java.awt.event.*;
  16. import java.util.Timer;
  17. import java.util.TimerTask;
  18. import java.util.concurrent.ExecutorService;
  19. import java.util.concurrent.Executors;
  20. public class WorkJPanelOP40 extends JPanel {
  21. public static final Logger log = LoggerFactory.getLogger(WorkJPanelOP40.class);
  22. public String oprno = "OP055";
  23. public String pos = "A";
  24. public String lastSn = ""; // 最近的码
  25. public String lineSn = "CZ060";
  26. public JLabel feedinglabel;
  27. public JLabel feedingmeslabel;
  28. public JLabel runlabel; //运行反馈,
  29. public JLabel blankinglabel; // 下料反馈
  30. public JLabel blankingmeslabel; // 下料MES反馈
  31. public JLabel feedingtodevicelabel; // 上料到设备
  32. public JLabel feedingtotransferlabel; // 上料到中转车
  33. public JLabel transfertodevicelabel; // 上料到中转车
  34. public JButton scanBtn;
  35. public JTextField productSn;
  36. public JTextField productSnFeeding;
  37. public JButton status_menu;
  38. public JButton resetBtn;
  39. public JButton resetFeedingBtn;
  40. public JButton submitBtn; // 手动提交按钮
  41. public JButton signalBtn; // 信号监控按钮
  42. public PlcSignalMonitor signalMonitor; // 信号监控组件
  43. public ImageIcon imageGreen;
  44. public ImageIcon imageGray;
  45. public String plcIp1 = "192.168.90.83"; // plc3
  46. public String plcIp2 = "192.168.90.84"; // plc4
  47. public S7PLC s7PLC = null;
  48. public Integer workWidth = 470;
  49. public Integer workHeight = 300;
  50. public String plcDb = "";
  51. public Integer tjFeedingFlag = 0; // 上料状态标识
  52. public Integer tjFlag = 0; // 1=可加工 2=设备运行中 3=加工结束
  53. public Integer tjTransferStatus = 0; // 中转台提交标识
  54. public Integer tjQualityStatus = 0; // 质量上传标识
  55. // 扫码重试机制
  56. private int scanRetryCount = 0;
  57. private static final int MAX_SCAN_RETRY = 2; // 最大重试2次
  58. // 用于检测状态变化的上一次值
  59. private Boolean lastRetBlanking = null;
  60. private Boolean lastRetFeeding = null;
  61. private Boolean lastRetRunning = null;
  62. private Boolean lastTransferToDevice = null;
  63. private Boolean lastToDevice = null;
  64. private Boolean lastToTransfer = null;
  65. private Integer lastTjFlag = null;
  66. private Integer lastTjFeedingFlag = null;
  67. private Integer lastTjTransferStatus = null;
  68. private Integer lastTjQualityStatus = null;
  69. private String lastProductSn = null;
  70. private String lastProductSnFeeding = null;
  71. public Boolean toDevice = false;
  72. public Boolean toTransfer = false;
  73. public Boolean transferToDevice = false;
  74. public Boolean plcHeart = false;
  75. public Integer isLocal = 0; // 0=正式 1=本地
  76. public Integer isScan = 1; // 1=西侧 2=东测
  77. public CacheData cacheData = null;
  78. public String cacheName = "";
  79. public WorkJPanelOP40(String position){
  80. this.setLayout(null);
  81. this.setBackground(Color.WHITE);
  82. this.pos = position;
  83. cacheName = "cache_"+oprno+pos;
  84. cacheData = JdbcUtils.getCache(cacheName);
  85. if(cacheData == null){
  86. cacheData = new CacheData();
  87. cacheData.setLastSn("");
  88. cacheData.setSn("");
  89. cacheData.setFeedingSn("");
  90. cacheData.setTjStatus(0);
  91. cacheData.setTjFlag(0);
  92. cacheData.setError(-1);
  93. cacheData.setMsg("");
  94. JdbcUtils.setCache(cacheName, JSON.toJSONString(cacheData));
  95. }
  96. // A/B/C 由 mes.side 切换东西侧;D-F 西 / G-L 东 逻辑保留
  97. if(position.equals("A") || position.equals("B") || position.equals("C")){
  98. if(MesClient.isEastSide()){
  99. s7PLC = new S7PLC(EPlcType.S1500, plcIp2);
  100. isScan = 2;
  101. }else{
  102. s7PLC = new S7PLC(EPlcType.S1500, plcIp1);
  103. isScan = 1;
  104. }
  105. }else if(position.equals("D") || position.equals("E") || position.equals("F")){
  106. s7PLC = new S7PLC(EPlcType.S1500, plcIp1);
  107. isScan = 1;
  108. }else{
  109. s7PLC = new S7PLC(EPlcType.S1500, plcIp2);
  110. isScan = 2;
  111. }
  112. switch (position){
  113. case "A":
  114. plcDb = "DB7000";
  115. break;
  116. case "B":
  117. plcDb = "DB7001";
  118. break;
  119. case "C":
  120. plcDb = "DB7002";
  121. break;
  122. case "D":
  123. plcDb = "DB7003";
  124. break;
  125. case "E":
  126. plcDb = "DB7004";
  127. break;
  128. case "F":
  129. plcDb = "DB7005";
  130. break;
  131. case "G":
  132. plcDb = "DB7000";
  133. break;
  134. case "H":
  135. plcDb = "DB7001";
  136. break;
  137. case "I":
  138. plcDb = "DB7002";
  139. break;
  140. case "J":
  141. plcDb = "DB7003";
  142. break;
  143. case "K":
  144. plcDb = "DB7004";
  145. break;
  146. case "L":
  147. plcDb = "DB7005";
  148. break;
  149. }
  150. JLabel oprnoLabel = new JLabel(oprno+pos);
  151. oprnoLabel.setHorizontalAlignment(SwingConstants.CENTER);
  152. oprnoLabel.setForeground(Color.BLACK);
  153. oprnoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
  154. oprnoLabel.setBounds(0, 0, workWidth/5, 25);
  155. this.add(oprnoLabel);
  156. // 工位标注(东1站-东6站,西1站-西6站)
  157. String stationLabel = getStationLabel(position);
  158. JLabel stationNameLabel = new JLabel(stationLabel);
  159. stationNameLabel.setHorizontalAlignment(SwingConstants.CENTER);
  160. stationNameLabel.setForeground(Color.BLACK);
  161. stationNameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
  162. stationNameLabel.setBounds(0, 25, workWidth/5, 15);
  163. this.add(stationNameLabel);
  164. status_menu = new JButton("等待请求扫码");
  165. status_menu.setBounds(workWidth/5, 0, workWidth*4/5, 40);
  166. status_menu.setForeground(Color.GREEN);
  167. status_menu.setForeground(Color.GREEN);
  168. status_menu.setFont(new Font("微软雅黑", Font.PLAIN, 16));
  169. status_menu.setBackground(Color.BLACK);
  170. this.add(status_menu);
  171. JLabel oprnoLabelFeeding = new JLabel("上料");
  172. oprnoLabelFeeding.setHorizontalAlignment(SwingConstants.CENTER);
  173. oprnoLabelFeeding.setForeground(Color.BLACK);
  174. oprnoLabelFeeding.setFont(new Font("微软雅黑", Font.PLAIN, 20));
  175. oprnoLabelFeeding.setBounds(0, 50, workWidth/5, 40);
  176. this.add(oprnoLabelFeeding);
  177. productSnFeeding = new JTextField("");
  178. productSnFeeding.setHorizontalAlignment(SwingConstants.CENTER);
  179. productSnFeeding.setForeground(Color.BLACK);
  180. productSnFeeding.setFont(new Font("微软雅黑", Font.PLAIN, 16));
  181. productSnFeeding.setEditable(false);
  182. productSnFeeding.setBounds(workWidth/5, 50, workWidth*3/5, 40);
  183. productSnFeeding.addMouseListener(new MouseAdapter() {
  184. public void mouseClicked(MouseEvent e) {
  185. String sn = productSnFeeding.getText().trim();
  186. if(!sn.isEmpty()){
  187. MesClient.createQRCode(productSnFeeding.getText(),oprno+pos);
  188. }
  189. }
  190. });
  191. this.add(productSnFeeding);
  192. JLabel oprnoLabelWork = new JLabel("加工");
  193. oprnoLabelWork.setHorizontalAlignment(SwingConstants.CENTER);
  194. oprnoLabelWork.setForeground(Color.BLACK);
  195. oprnoLabelWork.setFont(new Font("微软雅黑", Font.PLAIN, 20));
  196. oprnoLabelWork.setBounds(0, 100, workWidth/5, 40);
  197. this.add(oprnoLabelWork);
  198. productSn = new JTextField("");
  199. productSn.setHorizontalAlignment(SwingConstants.CENTER);
  200. productSn.setForeground(Color.BLACK);
  201. productSn.setFont(new Font("微软雅黑", Font.PLAIN, 16));
  202. productSn.setEditable(false);
  203. productSn.setBounds(workWidth/5, 100, workWidth*3/5, 40);
  204. productSn.addMouseListener(new MouseAdapter() {
  205. public void mouseClicked(MouseEvent e) {
  206. String sn = productSn.getText().trim();
  207. if(!sn.isEmpty()){
  208. MesClient.createQRCode(productSn.getText(),oprno+pos);
  209. }
  210. }
  211. });
  212. this.add(productSn);
  213. // scanBtn = new JButton("扫码");
  214. // scanBtn.addActionListener(new ActionListener() {
  215. // public void actionPerformed(ActionEvent e) {
  216. // log.info("test2:"+productSn.getText());
  217. // barCode();
  218. // }
  219. // });
  220. // scanBtn.setIcon(new ImageIcon(MesClient.class.getResource("/bg/scan_barcode.png")));
  221. // scanBtn.setFont(new Font("微软雅黑", Font.PLAIN, 32));
  222. // scanBtn.setBounds(0, 160, workWidth/2 - 5, 50);
  223. // this.add(scanBtn);
  224. resetFeedingBtn = new JButton("刷新");
  225. resetFeedingBtn.addActionListener(new ActionListener() {
  226. public void actionPerformed(ActionEvent e) {
  227. int choice = JOptionPane.showConfirmDialog(null, "确定刷新上料工件吗?", "操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  228. if (choice == JOptionPane.YES_OPTION) {
  229. resetFeeding();
  230. }
  231. }
  232. });
  233. // resetFeedingBtn.setIcon(new ImageIcon(MesClient.class.getResource("/bg/reset_logo.png")));
  234. resetFeedingBtn.setFont(new Font("微软雅黑", Font.PLAIN, 22));
  235. resetFeedingBtn.setBounds(workWidth*4/5 + 10, 50, workWidth/5 - 10, 40);
  236. this.add(resetFeedingBtn);
  237. resetBtn = new JButton("刷新");
  238. resetBtn.addActionListener(new ActionListener() {
  239. public void actionPerformed(ActionEvent e) {
  240. int choice = JOptionPane.showConfirmDialog(null, "确定刷新加工工件吗?", "操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  241. if (choice == JOptionPane.YES_OPTION) {
  242. resetBlanking();
  243. }
  244. }
  245. });
  246. // resetBtn.setIcon(new ImageIcon(MesClient.class.getResource("/bg/reset_logo.png")));
  247. resetBtn.setFont(new Font("微软雅黑", Font.PLAIN, 22));
  248. resetBtn.setBounds(workWidth*4/5 + 10, 100, workWidth/5 - 10, 40);
  249. this.add(resetBtn);
  250. imageGreen = new ImageIcon(MesClient.class.getResource("/bg/green_dot.png"));
  251. imageGreen.setImage(imageGreen.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH));
  252. imageGray = new ImageIcon(MesClient.class.getResource("/bg/grey_dot.png"));
  253. imageGray.setImage(imageGray.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH));
  254. feedinglabel = new JLabel("请求上料");
  255. feedinglabel.setHorizontalAlignment(SwingConstants.LEFT);
  256. feedinglabel.setIcon(imageGray); // 默认 0,等 PLC 轮询后再亮
  257. feedinglabel.setForeground(Color.BLACK);
  258. feedinglabel.setBounds(0, 150, workWidth/3, 30);
  259. this.add(feedinglabel);
  260. feedingmeslabel = new JLabel("MES允许上料");
  261. feedingmeslabel.setHorizontalAlignment(SwingConstants.LEFT);
  262. feedingmeslabel.setIcon(imageGray);
  263. feedingmeslabel.setForeground(Color.BLACK);
  264. feedingmeslabel.setBounds(workWidth/3, 150, workWidth/3, 30);
  265. feedingmeslabel.addMouseListener(new MouseAdapter() {
  266. public void mouseClicked(MouseEvent e) {
  267. boolean ret = readAllowFeeding();
  268. int choice = JOptionPane.showConfirmDialog(null, "确定修改MES允许上料结果为"+(ret?"false":"true")+"吗?", "操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  269. if (choice == JOptionPane.YES_OPTION) {
  270. writeAllowFeeding(!ret);
  271. }
  272. }
  273. });
  274. this.add(feedingmeslabel);
  275. runlabel = new JLabel("设备运行中");
  276. runlabel.setHorizontalAlignment(SwingConstants.LEFT);
  277. runlabel.setIcon(imageGray);
  278. runlabel.setForeground(Color.BLACK);
  279. runlabel.setBounds(workWidth*2/3, 150, workWidth/3, 30);
  280. this.add(runlabel);
  281. blankinglabel = new JLabel("下料请求");
  282. blankinglabel.setHorizontalAlignment(SwingConstants.LEFT);
  283. blankinglabel.setIcon(imageGray);
  284. blankinglabel.setForeground(Color.BLACK);
  285. blankinglabel.setBounds(0, 190, workWidth/3, 30);
  286. this.add(blankinglabel);
  287. blankingmeslabel = new JLabel("MES允许下料");
  288. blankingmeslabel.setHorizontalAlignment(SwingConstants.LEFT);
  289. blankingmeslabel.setIcon(imageGray);
  290. blankingmeslabel.setForeground(Color.BLACK);
  291. blankingmeslabel.setBounds(workWidth/3, 190, workWidth/3, 30);
  292. this.add(blankingmeslabel);
  293. blankingmeslabel.addMouseListener(new MouseAdapter() {
  294. public void mouseClicked(MouseEvent e) {
  295. boolean ret = readAllowBlanking();
  296. int choice = JOptionPane.showConfirmDialog(null, "确定修改MES允许下料结果为"+(ret?"false":"true")+"吗?", "操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  297. if (choice == JOptionPane.YES_OPTION) {
  298. writeAllowBlanking(!ret);
  299. }
  300. }
  301. });
  302. feedingtodevicelabel = new JLabel("上料到设备");
  303. feedingtodevicelabel.setHorizontalAlignment(SwingConstants.LEFT);
  304. feedingtodevicelabel.setIcon(imageGray);
  305. feedingtodevicelabel.setForeground(Color.BLACK);
  306. feedingtodevicelabel.setBounds(workWidth*2/3, 190, workWidth/3, 30);
  307. this.add(feedingtodevicelabel);
  308. feedingtotransferlabel = new JLabel("上料到中转车");
  309. feedingtotransferlabel.setHorizontalAlignment(SwingConstants.LEFT);
  310. feedingtotransferlabel.setIcon(imageGray);
  311. feedingtotransferlabel.setForeground(Color.BLACK);
  312. feedingtotransferlabel.setBounds(0, 230, workWidth/3, 30);
  313. this.add(feedingtotransferlabel);
  314. feedingtotransferlabel.setVisible(MesClient.transferEnabled);
  315. transfertodevicelabel = new JLabel("中转车上料到设备");
  316. transfertodevicelabel.setHorizontalAlignment(SwingConstants.LEFT);
  317. transfertodevicelabel.setIcon(imageGray);
  318. transfertodevicelabel.setForeground(Color.BLACK);
  319. transfertodevicelabel.setBounds(workWidth/3, 230, workWidth/3, 30);
  320. this.add(transfertodevicelabel);
  321. transfertodevicelabel.setVisible(MesClient.transferEnabled);
  322. // 手动提交按钮
  323. submitBtn = new JButton("提交");
  324. submitBtn.setFont(new Font("微软雅黑", Font.PLAIN, 12));
  325. submitBtn.setBounds(workWidth*2/3 + 10, 230, 60, 26);
  326. submitBtn.addActionListener(new ActionListener() {
  327. public void actionPerformed(ActionEvent e) {
  328. String sn = productSn.getText().trim();
  329. String msg;
  330. if(sn.isEmpty() || sn.equals("空结果")){
  331. msg = "确定重置当前工位状态吗?";
  332. }else{
  333. msg = "确定手动提交工件 " + sn + " 并重置状态吗?";
  334. }
  335. int choice = JOptionPane.showConfirmDialog(null, msg, "操作确认",
  336. JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  337. if (choice == JOptionPane.YES_OPTION) {
  338. manualSubmit();
  339. }
  340. }
  341. });
  342. this.add(submitBtn);
  343. // 信号监控按钮
  344. signalMonitor = new PlcSignalMonitor(s7PLC, plcDb, oprno + pos, MesClient.mesClientFrame);
  345. signalBtn = signalMonitor.createSignalButton();
  346. signalBtn.setBounds(workWidth*2/3 + 64, 230, 90, 26);
  347. this.add(signalBtn);
  348. this.startOprnoTimer();
  349. heartData();
  350. resetScanA();
  351. formatElementUI();
  352. }
  353. public void formatElementUI(){
  354. cacheData = JdbcUtils.getCache(cacheName);
  355. if(cacheData == null){
  356. return;
  357. }
  358. String msg = cacheData.getMsg();
  359. int error = cacheData.getError();
  360. String sn = cacheData.getSn();
  361. productSn.setText(sn);
  362. String feedingSn = cacheData.getFeedingSn();
  363. productSnFeeding.setText(feedingSn);
  364. tjFlag = cacheData.getTjFlag();
  365. lastSn = cacheData.getLastSn();
  366. setMenuStatus(msg,error);
  367. this.repaint();
  368. }
  369. public void setMenuStatus(String msg,int error){
  370. if(error == 0){
  371. this.status_menu.setForeground(Color.GREEN);
  372. }else{
  373. this.status_menu.setForeground(Color.RED);
  374. }
  375. this.status_menu.setText(msg);
  376. cacheData.setMsg(msg);
  377. cacheData.setError(error);
  378. cacheData.setTjFlag(tjFlag);
  379. // cacheData.setTjStatus(tjStatus);
  380. cacheData.setLastSn(lastSn);
  381. cacheData.setSn(productSn.getText());
  382. cacheData.setFeedingSn(productSnFeeding.getText());
  383. JdbcUtils.setCache(cacheName, JSON.toJSONString(cacheData));
  384. }
  385. // 定时任务 -----------------------------------------------------------------------------------------------------
  386. public Timer cjTimerText2;
  387. public void heartData() {
  388. if(cjTimerText2!=null) {
  389. cjTimerText2.cancel();
  390. }
  391. cjTimerText2 = new Timer();
  392. cjTimerText2.schedule(new TimerTask() {
  393. public void run() {
  394. if(MesClient.isLogin == 1 && isLocal == 0){
  395. plcHeart = !plcHeart;
  396. writeBoolean(plcDb+".0.6",plcHeart);
  397. }
  398. }
  399. }, 1000,1000);
  400. }
  401. public Timer oprnoTimer;
  402. public void startOprnoTimer() {
  403. //心跳显示图标
  404. if(oprnoTimer!=null) {
  405. oprnoTimer.cancel();
  406. }
  407. oprnoTimer = new Timer();
  408. oprnoTimer.schedule(new TimerTask() {
  409. public void run() {
  410. try{
  411. if(MesClient.isLogin == 1){
  412. Boolean retFeeding = readFeeding();
  413. feedinglabel.setIcon(retFeeding?imageGreen:imageGray);
  414. Boolean retFeedingAllow = readAllowFeeding();
  415. feedingmeslabel.setIcon(retFeedingAllow?imageGreen:imageGray);
  416. // 与 auto3 一致:PLC 不再请求上料时,清掉 MES 允许上料,避免信号粘滞
  417. if(!retFeeding && retFeedingAllow){
  418. writeAllowFeeding(false);
  419. }
  420. Boolean retBlanking = readBlanking();
  421. blankinglabel.setIcon(retBlanking?imageGreen:imageGray);
  422. Boolean retAllowBlanking = readAllowBlanking();
  423. blankingmeslabel.setIcon(retAllowBlanking?imageGreen:imageGray);
  424. toDevice = readFeedingToDevice();
  425. feedingtodevicelabel.setIcon(toDevice?imageGreen:imageGray);
  426. toTransfer = MesClient.transferEnabled && readFeedingToTransfer();
  427. if (MesClient.transferEnabled) {
  428. feedingtotransferlabel.setIcon(toTransfer?imageGreen:imageGray);
  429. }
  430. transferToDevice = MesClient.transferEnabled && readFeedingTransferToDevice();
  431. if (MesClient.transferEnabled) {
  432. transfertodevicelabel.setIcon(transferToDevice?imageGreen:imageGray);
  433. }
  434. Boolean retRunning = readRunning();
  435. runlabel.setIcon(retRunning?imageGreen:imageGray);
  436. // 无加工码却请求下料:允许下料并复位,防止死锁(对齐 auto3)
  437. if(retBlanking && productSn.getText().isEmpty()){
  438. writeAllowBlanking(true);
  439. resetBlanking();
  440. }
  441. // 只在状态变化时打印日志,减少日志量
  442. String currentProductSn = productSn.getText();
  443. String currentProductSnFeeding = productSnFeeding.getText();
  444. boolean stateChanged = !java.util.Objects.equals(lastRetBlanking, retBlanking) ||
  445. !java.util.Objects.equals(lastRetFeeding, retFeeding) ||
  446. !java.util.Objects.equals(lastRetRunning, retRunning) ||
  447. !java.util.Objects.equals(lastTjFlag, tjFlag) ||
  448. !java.util.Objects.equals(lastTjFeedingFlag, tjFeedingFlag) ||
  449. !java.util.Objects.equals(lastTjTransferStatus, tjTransferStatus) ||
  450. !java.util.Objects.equals(lastTjQualityStatus, tjQualityStatus) ||
  451. !java.util.Objects.equals(lastTransferToDevice, transferToDevice) ||
  452. !java.util.Objects.equals(lastToDevice, toDevice) ||
  453. !java.util.Objects.equals(lastToTransfer, toTransfer) ||
  454. !java.util.Objects.equals(lastProductSn, currentProductSn) ||
  455. !java.util.Objects.equals(lastProductSnFeeding, currentProductSnFeeding);
  456. if(stateChanged){
  457. log.info("[{}]状态变化: tjFeedingFlag={}, tjFlag={}, tjTransferStatus={}, tjQualityStatus={}, retFeeding={}, retBlanking={}, retRunning={}, toDevice={}, toTransfer={}, transferToDevice={}, productSnFeeding={}, productSn={}",
  458. oprno+pos, tjFeedingFlag, tjFlag, tjTransferStatus, tjQualityStatus, retFeeding, retBlanking, retRunning, toDevice, toTransfer, transferToDevice, currentProductSnFeeding, currentProductSn);
  459. lastRetBlanking = retBlanking;
  460. lastRetFeeding = retFeeding;
  461. lastRetRunning = retRunning;
  462. lastTjFlag = tjFlag;
  463. lastTjFeedingFlag = tjFeedingFlag;
  464. lastTjTransferStatus = tjTransferStatus;
  465. lastTjQualityStatus = tjQualityStatus;
  466. lastTransferToDevice = transferToDevice;
  467. lastToDevice = toDevice;
  468. lastToTransfer = toTransfer;
  469. lastProductSn = currentProductSn;
  470. lastProductSnFeeding = currentProductSnFeeding;
  471. }
  472. if(tjFeedingFlag == 0){
  473. if(retFeeding){
  474. if(MesClient.transferEnabled && plcDb.equals("DB7005") && toTransfer){
  475. log.info("[{}]tjFeedingFlag=0且retFeeding=true且toTransfer=true,触发中转车扫码", oprno+pos);
  476. barCodeForTransfer();
  477. } else {
  478. log.info("[{}]tjFeedingFlag=0且retFeeding=true,触发工位取码", oprno+pos);
  479. barCode();
  480. }
  481. }
  482. }else if(tjFeedingFlag == 1){
  483. if(tjFlag == 0 && retRunning){
  484. log.info("[{}]tjFeedingFlag=1, tjFlag=0, retRunning=true -> 设置tjFlag=1,工件进入加工位", oprno+pos);
  485. tjFlag = 1;
  486. productSn.setText(productSnFeeding.getText());
  487. // resetBtn.setEnabled(false);
  488. resetFeeding();
  489. }
  490. if(MesClient.transferEnabled && toTransfer){ // 去中转台
  491. int transferSn = readTransferNo();
  492. int transferFloor = readTransferFloor();
  493. log.info("[{}]去中转台: transferSn={}, transferFloor={}, tjTransferStatus={}", oprno+pos, transferSn, transferFloor, tjTransferStatus);
  494. if(transferSn > 0 && transferFloor > 0){
  495. if(tjTransferStatus == 0) {
  496. tjTransferStatus = 1;
  497. log.info("[{}]提交中转台数据...", oprno+pos);
  498. JSONObject retObj = DataUtil.saveSn(oprno+pos,productSnFeeding.getText().trim(),transferSn,transferFloor,MesClient.user_menu.getText());
  499. log.info("[{}]中转台提交结果: {}", oprno+pos, retObj);
  500. if(retObj != null && retObj.get("result")!=null&&retObj.get("result").toString().equalsIgnoreCase("true")) {
  501. tjTransferStatus = 0;
  502. resetFeeding();
  503. }else{
  504. tjTransferStatus = 0;
  505. if(retObj == null || retObj.get("result")==null){
  506. setMenuStatus("请求失败,请重试",-1);
  507. }else if(retObj.get("result").toString().equalsIgnoreCase("false")){
  508. setMenuStatus(retObj.getString("message"),-1);
  509. }
  510. }
  511. }
  512. }
  513. }
  514. }
  515. if(tjFlag == 0 && !retBlanking){
  516. writeAllowBlanking(false);
  517. }
  518. if(tjFlag == 1){
  519. // 只在状态变化时打印,避免日志过多
  520. // log.info("[{}]tjFlag=1, 等待设备运行, toDevice={}, retRunning={}", oprno+pos, toDevice, retRunning);
  521. // 当tjFlag=1时,工件已在设备上(无论是直接上料还是中转车上料),只要设备运行中就认为在加工
  522. if(retRunning){
  523. log.info("[{}]tjFlag 1->2,工件加工中", oprno+pos);
  524. tjFlag = 2;
  525. setMenuStatus("工件加工中", 0);
  526. // 运行中清除下料反馈
  527. writeAllowBlanking(false);
  528. }else{
  529. }
  530. }else if(tjFlag == 2){
  531. // 与 auto3 一致:只认 PLC 请求下料,不停机即报工
  532. if(retBlanking){
  533. upResult();
  534. }
  535. }else if(tjFlag == 3){
  536. // 只在状态变化时打印,避免日志过多
  537. // log.info("[{}]tjFlag=3, 等待上传完成重置, tjQualityStatus={}", oprno+pos, tjQualityStatus);
  538. }
  539. }
  540. }catch (Exception e) {
  541. log.error(e.getMessage());
  542. }
  543. }
  544. }, 100,1500);
  545. }
  546. public void upResult(){
  547. if(tjQualityStatus == 1){
  548. log.info("[{}]tjQualityStatus=1,跳过上传(已在上传中)", oprno+pos);
  549. return;
  550. }
  551. String sn = productSn.getText() == null ? "" : productSn.getText().trim();
  552. if(sn.isEmpty() || sn.equals("空结果")){
  553. log.warn("[{}]下料时加工码为空,允许下料并复位", oprno+pos);
  554. writeAllowBlanking(true);
  555. resetBlanking();
  556. return;
  557. }
  558. log.info("[{}]tjFlag 2->3,收到下料信号,准备上传结果, sn={}", oprno+pos, sn);
  559. tjFlag = 3;
  560. tjQualityStatus = 1;
  561. setMenuStatus("工件加工结束,结果上传中", 0);
  562. try {
  563. JSONObject retObj = DataUtil.sendQuality(sn, oprno+pos, "OK", MesClient.user_menu.getText());
  564. log.info("[{}]质量上传返回结果: {}", oprno+pos, retObj);
  565. if(retObj != null && retObj.get("result") != null
  566. && retObj.get("result").toString().equalsIgnoreCase("true")) {
  567. log.info("[{}]质量上传成功,执行resetBlanking", oprno+pos);
  568. resetBlanking();
  569. }else{
  570. tjQualityStatus = 0;
  571. tjFlag = 2;
  572. if(retObj == null || retObj.get("result") == null){
  573. log.error("[{}]质量上传失败,result为null", oprno+pos);
  574. setMenuStatus("请求失败,请重试", -1);
  575. }else{
  576. log.error("[{}]质量上传失败: {}", oprno+pos, retObj.getString("message"));
  577. setMenuStatus(retObj.getString("message"), -1);
  578. }
  579. }
  580. } catch (Exception e) {
  581. tjQualityStatus = 0;
  582. tjFlag = 2;
  583. log.error("[{}]质量上传异常: {}", oprno+pos, e.getMessage(), e);
  584. setMenuStatus("请求失败,请重试", -1);
  585. }
  586. }
  587. public void barCode(){
  588. if(!productSnFeeding.getText().isEmpty()){
  589. return;
  590. }
  591. String sn = readQrcode();
  592. if(sn == null){
  593. sn = "";
  594. }
  595. sn = sn.trim();
  596. if(sn.isEmpty()){
  597. // 对齐 auto3:码未就绪不写死「空结果」,下个轮询继续取
  598. setMenuStatus("等待扫码站扫码", 0);
  599. return;
  600. }
  601. productSnFeeding.setText(sn);
  602. lastSn = sn;
  603. consumeScanSn(sn);
  604. JSONObject retObj = DataUtil.checkQuality(sn, oprno+pos, MesClient.user_menu.getText());
  605. if(retObj != null && retObj.get("result") != null
  606. && retObj.get("result").toString().equalsIgnoreCase("true")) {
  607. tjFeedingFlag = 1;
  608. scanRetryCount = 0;
  609. setMenuStatus("工件可以加工", 0);
  610. writeAllowFeeding(true);
  611. }else{
  612. writeAllowFeeding(false);
  613. resetFeedingBtn.setEnabled(true);
  614. if(retObj == null || retObj.get("result") == null){
  615. setMenuStatus("请求失败,请重试", -1);
  616. }else{
  617. setMenuStatus(retObj.getString("message"), -1);
  618. }
  619. }
  620. }
  621. private void consumeScanSn(String sn){
  622. if(sn == null || sn.isEmpty()){
  623. return;
  624. }
  625. if(isScan == 1 && sn.equals(MesClient.scanSnA)){
  626. MesClient.scanSnA = "";
  627. }else if(isScan == 2 && sn.equals(MesClient.scanSnB)){
  628. MesClient.scanSnB = "";
  629. }
  630. }
  631. /**
  632. * 专门给中转车扫码的方法(仅工位F/L使用)
  633. * 触发摄像头扫码,但码赋值给中转车的productSnFeeding,不影响工位6的状态
  634. */
  635. public void barCodeForTransfer(){
  636. // 获取对应的中转车面板
  637. WorkJPanelOP40Transfer transferPanel = null;
  638. if(pos.equals("F")){
  639. transferPanel = MesClient.workJPanelOP40Transfer1;
  640. } else if(pos.equals("L")){
  641. transferPanel = MesClient.workJPanelOP40Transfer2;
  642. }
  643. if(transferPanel == null){
  644. log.error("[{}]barCodeForTransfer: 找不到对应的中转车面板", oprno+pos);
  645. return;
  646. }
  647. // 判断是否为有效工件码(排除"空结果"等无效值)
  648. String currentSn = transferPanel.productSnFeeding.getText().trim();
  649. boolean isValidSn = !currentSn.isEmpty() && !currentSn.equals("空结果");
  650. // 如果中转车已有有效码,跳过扫码
  651. if(isValidSn){
  652. log.info("[{}]barCodeForTransfer: 中转车已有有效码({}),跳过扫码", oprno+pos, currentSn);
  653. return;
  654. }
  655. // 如果是无效码(如"空结果"),检查重试次数
  656. if(!currentSn.isEmpty() && !isValidSn){
  657. if(transferPanel.scanRetryCount > WorkJPanelOP40Transfer.MAX_SCAN_RETRY){
  658. log.info("[{}]barCodeForTransfer: 已达最大重试次数({}),等待人工处理", oprno+pos, transferPanel.scanRetryCount);
  659. return;
  660. }
  661. // 清空无效码,准备重试
  662. log.info("[{}]barCodeForTransfer: 检测到无效码({}),准备重试(第{}次)", oprno+pos, currentSn, transferPanel.scanRetryCount + 1);
  663. transferPanel.productSnFeeding.setText("");
  664. }
  665. // 触发摄像头扫码
  666. String sn = "";
  667. if(isScan == 1){
  668. log.info("[{}]触发西侧摄像头扫码(给中转车)", oprno+pos);
  669. // sn = MesClient.scanQrcode1();
  670. sn = MesClient.scanSnA;
  671. }else{
  672. log.info("[{}]触发东侧摄像头扫码(给中转车)", oprno+pos);
  673. // sn = MesClient.scanQrcode2();
  674. sn = MesClient.scanSnB;
  675. }
  676. log.info("[{}]中转车扫码完成,结果: {}", oprno+pos, sn);
  677. // // 如果中转车已有有效码,跳过扫码
  678. // if(isValidSn){
  679. // if(sn.equals(currentSn)){
  680. // log.info("[{}]barCodeForTransfer: 中转车已有有效码({}),跳过扫码", oprno+pos, currentSn);
  681. // return;
  682. // }
  683. // }
  684. if(sn.equals("")){
  685. transferPanel.scanRetryCount++; // 扫码失败,增加重试计数
  686. transferPanel.productSnFeeding.setText("空结果");
  687. if(transferPanel.scanRetryCount > WorkJPanelOP40Transfer.MAX_SCAN_RETRY){
  688. transferPanel.setMenuStatus("扫码失败(已重试" + transferPanel.scanRetryCount + "次),请人工处理", -1);
  689. log.warn("[{}]中转车扫码失败,已达最大重试次数,等待人工处理", oprno+pos);
  690. }else{
  691. transferPanel.setMenuStatus("扫码结果为空,准备重试", -1);
  692. log.info("[{}]中转车扫码失败,将在3秒后重试(第{}次)", oprno+pos, transferPanel.scanRetryCount);
  693. }
  694. }else{
  695. // 码赋值给中转车的productSnFeeding
  696. transferPanel.productSnFeeding.setText(sn);
  697. transferPanel.lastSn = sn;
  698. // 校验工件质量
  699. JSONObject retObj = DataUtil.checkQuality(sn, oprno+pos, MesClient.user_menu.getText());
  700. if(retObj.get("result")!=null && retObj.get("result").toString().equalsIgnoreCase("true")) {
  701. transferPanel.tjFeedingFlag = 1;
  702. transferPanel.setMenuStatus("工件校验通过,准备保存", 0);
  703. // 调用saveSn保存到数据库
  704. int transferSn = readTransferNo();
  705. int transferFloor = readTransferFloor();
  706. log.info("[{}]中转车扫码成功,准备saveSn: sn={}, transferSn={}, transferFloor={}", oprno+pos, sn, transferSn, transferFloor);
  707. if(transferSn > 0 && transferFloor > 0){
  708. JSONObject saveRet = DataUtil.saveSn(oprno+pos, sn, transferSn, transferFloor, MesClient.user_menu.getText());
  709. log.info("[{}]saveSn结果: {}", oprno+pos, saveRet);
  710. if(saveRet.get("result")!=null && saveRet.get("result").toString().equalsIgnoreCase("true")) {
  711. writeAllowFeeding(true);
  712. transferPanel.setMenuStatus("工件已保存到中转车", 0);
  713. }else{
  714. writeAllowFeeding(false);
  715. if(saveRet.get("result")==null){
  716. transferPanel.setMenuStatus("保存失败,请重试", -1);
  717. }else{
  718. transferPanel.setMenuStatus(saveRet.getString("message"), -1);
  719. }
  720. }
  721. }else{
  722. log.error("[{}]中转车号或层数无效: transferSn={}, transferFloor={}", oprno+pos, transferSn, transferFloor);
  723. transferPanel.setMenuStatus("中转车号或层数无效", -1);
  724. writeAllowFeeding(false);
  725. }
  726. }else{
  727. writeAllowFeeding(false);
  728. transferPanel.resetFeedingBtn.setEnabled(true);
  729. if(retObj.get("result")==null){
  730. transferPanel.setMenuStatus("请求失败,请重试", -1);
  731. }else{
  732. if(retObj.get("result").toString().equalsIgnoreCase("false")){
  733. transferPanel.setMenuStatus(retObj.getString("message"), -1);
  734. }
  735. }
  736. }
  737. }
  738. }
  739. public void resetBlanking() {
  740. log.info("[{}]resetBlanking执行: tjFlag {} -> 0, tjQualityStatus {} -> 0", oprno+pos, tjFlag, tjQualityStatus);
  741. tjFlag = 0;
  742. tjQualityStatus = 0;
  743. productSn.setText("");
  744. setMenuStatus("工件结果已提交,等待下一件",0);
  745. resetBtn.setEnabled(true);
  746. // writeAllowFeeding(false);
  747. // writeAllowBlanking(false);
  748. }
  749. public void resetFeeding() {
  750. log.info("[{}]resetFeeding执行: tjFeedingFlag {} -> 0", oprno+pos, tjFeedingFlag);
  751. productSnFeeding.setText("");
  752. tjFeedingFlag = 0;
  753. tjTransferStatus = 0; // 重置中转台状态
  754. scanRetryCount = 0; // 重置扫码重试计数
  755. setMenuStatus("等待物料扫码",0);
  756. resetFeedingBtn.setEnabled(true);
  757. writeAllowFeeding(false);
  758. }
  759. public void resetScanA() {
  760. tjFeedingFlag = 0;
  761. tjFlag = 0;
  762. tjTransferStatus = 0;
  763. tjQualityStatus = 0;
  764. scanRetryCount = 0;
  765. productSn.setText("");
  766. productSnFeeding.setText("");
  767. // setMenuStatus("等待请求扫码",0);
  768. resetBtn.setEnabled(true);
  769. resetFeedingBtn.setEnabled(true);
  770. // 延迟写入PLC,避免初始化时连接超时
  771. if(MesClient.isLogin == 1) {
  772. writeAllowFeeding(false);
  773. writeAllowBlanking(false);
  774. }
  775. }
  776. // 手动提交方法
  777. public void manualSubmit() {
  778. String sn = productSn.getText().trim();
  779. if(sn.isEmpty() || sn.equals("空结果")){
  780. // 无码:直接重置状态,不提交
  781. log.info("[{}]手动重置(无码)", oprno+pos);
  782. resetScanA();
  783. setMenuStatus("已重置,等待下一件", 0);
  784. }else{
  785. // 有码:先提交再重置
  786. log.info("[{}]手动提交: sn={}", oprno+pos, sn);
  787. JSONObject retObj = DataUtil.sendQuality(sn, oprno+pos, "OK", MesClient.user_menu.getText());
  788. log.info("[{}]手动提交结果: {}", oprno+pos, retObj);
  789. if(retObj.get("result")!=null && retObj.get("result").toString().equalsIgnoreCase("true")) {
  790. resetScanA();
  791. setMenuStatus("提交成功,等待下一件", 0);
  792. }else{
  793. if(retObj.get("result")==null){
  794. setMenuStatus("提交失败,请重试", -1);
  795. }else{
  796. setMenuStatus(retObj.getString("message"), -1);
  797. }
  798. }
  799. }
  800. }
  801. // 与设备交互-----------------------------------------------------------------------------------------
  802. // 请求扫码
  803. public boolean readFeeding(){
  804. if(isLocal == 1){
  805. return false;
  806. }else{
  807. return readBoolean(plcDb+".0.0");
  808. }
  809. }
  810. // 读取上料到设备
  811. public boolean readFeedingToDevice(){
  812. if(isLocal == 1){
  813. return true;
  814. }else{
  815. return readBoolean(plcDb+".0.7");
  816. }
  817. }
  818. // 读取上料到中转车
  819. public boolean readFeedingToTransfer(){
  820. if(isLocal == 1){
  821. return true;
  822. }else{
  823. return readBoolean(plcDb+".1.0");
  824. }
  825. }
  826. // 读取中转车上料到设备
  827. public boolean readFeedingTransferToDevice(){
  828. if(isLocal == 1){
  829. return true;
  830. }else{
  831. return readBoolean(plcDb+".1.1");
  832. }
  833. }
  834. // 读取下料信号
  835. public boolean readBlanking(){
  836. if(isLocal == 1){
  837. return false;
  838. }else{
  839. return readBoolean(plcDb+".0.1");
  840. }
  841. }
  842. // 读取设备运行信号
  843. public boolean readRunning(){
  844. if(isLocal == 1){
  845. return true;
  846. }else{
  847. return readBoolean(plcDb+".0.2");
  848. }
  849. }
  850. // 读取设备通讯状态
  851. public boolean readDeviceStatus(){
  852. if(isLocal == 1){
  853. return true;
  854. }else{
  855. return readBoolean(plcDb+".0.3");
  856. }
  857. }
  858. // 读取MES允许上料信号
  859. public boolean readAllowFeeding(){
  860. if(isLocal == 1){
  861. return false;
  862. }else{
  863. return readBoolean(plcDb+".0.4");
  864. }
  865. }
  866. // 写入MES允许上料信号
  867. public boolean writeAllowFeeding(Boolean b){
  868. if(isLocal == 1){
  869. return true;
  870. }
  871. // 判断MES是否屏蔽
  872. if(isScan == 1 && !MesClient.mesEnabledWest){
  873. log.info("[{}]西侧MES已屏蔽,跳过writeAllowFeeding({})", oprno+pos, b);
  874. return true;
  875. }
  876. if(isScan == 2 && !MesClient.mesEnabledEast){
  877. log.info("[{}]东侧MES已屏蔽,跳过writeAllowFeeding({})", oprno+pos, b);
  878. return true;
  879. }
  880. return writeBoolean(plcDb+".0.4",b);
  881. }
  882. // 读取MES允许下料信号
  883. public boolean readAllowBlanking(){
  884. if(isLocal == 1){
  885. return true;
  886. }else{
  887. return readBoolean(plcDb+".0.5");
  888. }
  889. }
  890. // 写入MES允许下料信号
  891. public boolean writeAllowBlanking(Boolean b){
  892. if(isLocal == 1){
  893. return true;
  894. }
  895. // 判断MES是否屏蔽
  896. if(isScan == 1 && !MesClient.mesEnabledWest){
  897. log.info("[{}]西侧MES已屏蔽,跳过writeAllowBlanking({})", oprno+pos, b);
  898. return true;
  899. }
  900. if(isScan == 2 && !MesClient.mesEnabledEast){
  901. log.info("[{}]东侧MES已屏蔽,跳过writeAllowBlanking({})", oprno+pos, b);
  902. return true;
  903. }
  904. return writeBoolean(plcDb+".0.5",b);
  905. }
  906. // 读取中转车号
  907. public int readTransferNo(){
  908. if(isLocal == 1){
  909. return 1;
  910. }else{
  911. return s7PLC.readInt16(plcDb+".2.0");
  912. }
  913. }
  914. // 读取中转车层数
  915. public int readTransferFloor(){
  916. if(isLocal == 1){
  917. return 1;
  918. }else{
  919. return s7PLC.readInt16(plcDb+".4.0");
  920. }
  921. }
  922. // 控制扫码枪读取二维码
  923. public String readQrcode(){
  924. // String sn = "5001040043561010006";
  925. String sn = "";
  926. if(isLocal == 1){
  927. return "";
  928. }else{
  929. try{
  930. if(MesClient.transferEnabled && transferToDevice){ // 中转车上料到设备
  931. int transferSn = readTransferNo();
  932. int transferFloor = readTransferFloor();
  933. log.info("[{}]中转车上料到设备: transferSn={}, transferFloor={}", oprno+pos, transferSn, transferFloor);
  934. JSONObject retObj = DataUtil.getSn(oprno+pos,transferSn,transferFloor,MesClient.user_menu.getText());
  935. log.info("[{}]getSn返回结果: {}", oprno+pos, retObj);
  936. if(retObj != null && retObj.get("result")!=null&&retObj.get("result").toString().equalsIgnoreCase("true")) {
  937. sn = retObj.getString("data");
  938. log.info("[{}]中转车获取到工件码: {}", oprno+pos, sn);
  939. this.setMenuStatus("允许工件加工",0);
  940. }else{
  941. if(retObj == null || retObj.get("result")==null){
  942. log.error("[{}]getSn失败: result为null", oprno+pos);
  943. this.setMenuStatus("请求失败,请重试",-1);
  944. }else if(retObj.get("result").toString().equalsIgnoreCase("false")){
  945. log.error("[{}]getSn失败: {}", oprno+pos, retObj.getString("message"));
  946. this.setMenuStatus(retObj.getString("message"),-1);
  947. }
  948. }
  949. }else{
  950. if(isScan == 1){
  951. sn = MesClient.scanSnA == null ? "" : MesClient.scanSnA;
  952. }else{
  953. sn = MesClient.scanSnB == null ? "" : MesClient.scanSnB;
  954. }
  955. }
  956. log.info("[{}]扫码完成,结果: {}", oprno+pos, sn);
  957. }catch (Exception e) {
  958. e.printStackTrace();
  959. }
  960. }
  961. return sn;
  962. }
  963. public boolean readBoolean(String db){
  964. boolean permit;
  965. try {
  966. // 检查PLC连接是否可用
  967. if(s7PLC == null) {
  968. return false;
  969. }
  970. permit = s7PLC.readBoolean(db);
  971. // log.info("<"+this.oprno+this.pos+">读取"+db+"-->成功,结果:{}", permit ? "true" : "false");
  972. } catch (Exception e) {
  973. // 连接超时时不打印完整堆栈,只记录简要信息
  974. if(e.getMessage() != null && e.getMessage().contains("connect timed out")) {
  975. // 连接超时是常见情况,降低日志级别
  976. // log.debug("<"+this.oprno+this.pos+">读取"+db+"-->连接超时");
  977. } else {
  978. log.error("<"+this.oprno+this.pos+">读取"+db+"-->失败: {}", e.getMessage());
  979. }
  980. return false;
  981. }
  982. return permit;
  983. }
  984. public boolean writeBoolean(String db, boolean permit){
  985. try {
  986. // 检查PLC连接是否可用
  987. if(s7PLC == null) {
  988. log.warn("<"+this.oprno+this.pos+">PLC未初始化,跳过写入"+db);
  989. return false;
  990. }
  991. s7PLC.writeBoolean(db,permit);
  992. // log.info("<"+this.oprno+this.pos+">写入"+db+"-->成功,写入内容:{}", permit ? "true" : "false");
  993. } catch (Exception e) {
  994. // 连接超时时不打印完整堆栈,只记录简要信息
  995. if(e.getMessage() != null && e.getMessage().contains("connect timed out")) {
  996. log.warn("<"+this.oprno+this.pos+">写入"+db+"-->连接超时(PLC未连接)");
  997. } else {
  998. log.error("<"+this.oprno+this.pos+">写入"+db+"-->失败,写入内容:{}", permit ? "true" : "false");
  999. log.error(e.getMessage());
  1000. }
  1001. return false;
  1002. }
  1003. return true;
  1004. }
  1005. // 获取工位站点标注
  1006. private String getStationLabel(String position) {
  1007. String side = MesClient.isEastSide() ? "东侧" : "西侧";
  1008. switch (position) {
  1009. case "A": return side + "1号机";
  1010. case "B": return side + "2号机";
  1011. case "C": return side + "3号机";
  1012. case "D": return "西侧4号机";
  1013. case "E": return "西侧5号机";
  1014. case "F": return "西侧6号机";
  1015. case "G": return "东侧1号机";
  1016. case "H": return "东侧2号机";
  1017. case "I": return "东侧3号机";
  1018. case "J": return "东侧4号机";
  1019. case "K": return "东侧5号机";
  1020. case "L": return "东侧6号机";
  1021. default: return "";
  1022. }
  1023. }
  1024. }