WorkJPanelScan.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  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 org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import javax.swing.*;
  13. import java.awt.*;
  14. import java.awt.event.ActionEvent;
  15. import java.awt.event.ActionListener;
  16. import java.awt.event.KeyAdapter;
  17. import java.awt.event.KeyEvent;
  18. import java.awt.event.MouseAdapter;
  19. import java.awt.event.MouseEvent;
  20. import java.util.Timer;
  21. import java.util.TimerTask;
  22. public class WorkJPanelScan extends JPanel {
  23. public static final Logger log = LoggerFactory.getLogger(WorkJPanelScan.class);
  24. public String oprno = "OP055";
  25. public String pos = "A";
  26. public String lastSn = ""; // 最近的码
  27. public String lineSn = "CZ060";
  28. /** 兼容现场短码、旧码和 24 位 EVE 长码 */
  29. public static final int SN_LEN_SHORT = 16;
  30. public static final int SN_LEN_LEGACY = 19;
  31. public static final int SN_LEN_EVE = 24;
  32. public JLabel feedinglabel;
  33. public JLabel feedingmeslabel;
  34. public JLabel runlabel; //运行反馈,
  35. public JLabel blankinglabel; // 下料反馈
  36. public JLabel blankingmeslabel; // 下料MES反馈
  37. public JLabel feedingtodevicelabel; // 上料到设备
  38. public JLabel feedingtotransferlabel; // 上料到中转车
  39. public JLabel transfertodevicelabel; // 上料到中转车
  40. public JButton scanBtn;
  41. public JTextField productSn;
  42. public JTextField productSnFeeding;
  43. public JButton status_menu;
  44. public JButton resetBtn;
  45. public JButton resetFeedingBtn;
  46. public ImageIcon imageGreen;
  47. public ImageIcon imageGray;
  48. public String plcIp1 = "192.168.90.83"; // plc3
  49. public String plcIp2 = "192.168.90.84"; // plc4
  50. public S7PLC s7PLC = null;
  51. public Integer workWidth = 470;
  52. public Integer workHeight = 300;
  53. public String plcDb = "DB35";
  54. public Integer tjFeedingFlag = 0; // 上料状态标识
  55. public Integer tjFlag = 0; // 1=可加工 2=设备运行中 3=加工结束
  56. public Integer tjStatus = 0; // 提交标识
  57. public Boolean toDevice = false;
  58. public Boolean toTransfer = false;
  59. public Boolean transferToDevice = false;
  60. public Boolean plcHeart = false;
  61. public Integer isLocal = 0; // 0=正式 1=本地
  62. public Integer isScan = 1; // 1=西侧 2=东测
  63. public int transferSn = 0;
  64. public int transferFloor = 0;
  65. public CacheData cacheData = null;
  66. public String cacheName = "";
  67. private Boolean lastScanRequest = null;
  68. private boolean scanCompletedForRequest = false;
  69. private String manualPendingSn = "";
  70. public WorkJPanelScan(String position){
  71. this.setLayout(null);
  72. this.setBackground(Color.WHITE);
  73. this.pos = position;
  74. if(position.equals("A")){
  75. s7PLC = new S7PLC(EPlcType.S1500, plcIp1);
  76. }else{
  77. s7PLC = new S7PLC(EPlcType.S1500, plcIp2);
  78. }
  79. cacheName = "cache_scan_"+oprno+pos;
  80. cacheData = JdbcUtils.getCache(cacheName);
  81. if(cacheData == null){
  82. cacheData = new CacheData();
  83. cacheData.setLastSn("");
  84. cacheData.setSn("");
  85. cacheData.setFeedingSn("");
  86. cacheData.setTjStatus(0);
  87. cacheData.setTjFlag(0);
  88. cacheData.setError(-1);
  89. cacheData.setMsg("");
  90. JdbcUtils.setCache(cacheName, JSON.toJSONString(cacheData));
  91. }
  92. JLabel oprnoLabel = new JLabel(oprno);
  93. oprnoLabel.setHorizontalAlignment(SwingConstants.CENTER);
  94. oprnoLabel.setForeground(Color.BLACK);
  95. oprnoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
  96. oprnoLabel.setBounds(0, 0, workWidth/5, 40);
  97. this.add(oprnoLabel);
  98. if(this.pos.equals("A")){
  99. oprnoLabel.setText("西侧");
  100. }else{
  101. oprnoLabel.setText("东侧");
  102. }
  103. status_menu = new JButton("等待请求扫码");
  104. status_menu.setBounds(workWidth/5, 0, workWidth*4/5, 40);
  105. status_menu.setForeground(Color.GREEN);
  106. status_menu.setForeground(Color.GREEN);
  107. status_menu.setFont(new Font("微软雅黑", Font.PLAIN, 16));
  108. status_menu.setBackground(Color.BLACK);
  109. this.add(status_menu);
  110. JLabel oprnoLabelFeeding = new JLabel("扫码");
  111. oprnoLabelFeeding.setHorizontalAlignment(SwingConstants.CENTER);
  112. oprnoLabelFeeding.setForeground(Color.BLACK);
  113. oprnoLabelFeeding.setFont(new Font("微软雅黑", Font.PLAIN, 20));
  114. oprnoLabelFeeding.setBounds(0, 50, workWidth/5, 40);
  115. this.add(oprnoLabelFeeding);
  116. productSnFeeding = new JTextField("");
  117. productSnFeeding.setHorizontalAlignment(SwingConstants.CENTER);
  118. productSnFeeding.setForeground(Color.BLACK);
  119. productSnFeeding.setFont(new Font("微软雅黑", Font.PLAIN, 16));
  120. productSnFeeding.setEditable(true);
  121. productSnFeeding.setToolTipText("可手动输入工件码后按回车确认");
  122. productSnFeeding.setBounds(workWidth/5, 50, workWidth*3/5, 40);
  123. productSnFeeding.addKeyListener(new KeyAdapter() {
  124. @Override
  125. public void keyPressed(KeyEvent e) {
  126. if (e.getKeyCode() == KeyEvent.VK_ENTER) {
  127. applyManualSn();
  128. }
  129. }
  130. });
  131. productSnFeeding.addMouseListener(new MouseAdapter() {
  132. public void mouseClicked(MouseEvent e) {
  133. if (e.getClickCount() >= 2) {
  134. String sn = productSnFeeding.getText().trim();
  135. if (!sn.isEmpty()) {
  136. MesClient.createQRCode(sn, oprno + pos);
  137. }
  138. }
  139. }
  140. });
  141. this.add(productSnFeeding);
  142. resetFeedingBtn = new JButton("刷新");
  143. resetFeedingBtn.addActionListener(new ActionListener() {
  144. public void actionPerformed(ActionEvent e) {
  145. int choice = JOptionPane.showConfirmDialog(null, "确定刷新上料工件吗?", "操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  146. if (choice == JOptionPane.YES_OPTION) {
  147. resetScanA();
  148. }
  149. }
  150. });
  151. resetFeedingBtn.setFont(new Font("微软雅黑", Font.PLAIN, 22));
  152. resetFeedingBtn.setBounds(workWidth*4/5 + 10, 50, workWidth/5 - 10, 40);
  153. this.add(resetFeedingBtn);
  154. imageGreen = new ImageIcon(MesClient.class.getResource("/bg/green_dot.png"));
  155. imageGreen.setImage(imageGreen.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH));
  156. imageGray = new ImageIcon(MesClient.class.getResource("/bg/grey_dot.png"));
  157. imageGray.setImage(imageGray.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH));
  158. feedinglabel = new JLabel("请求扫码");
  159. feedinglabel.setHorizontalAlignment(SwingConstants.LEFT);
  160. feedinglabel.setIcon(imageGray); // 默认 0
  161. feedinglabel.setForeground(Color.BLACK);
  162. feedinglabel.setBounds(0, 150, workWidth/3, 30);
  163. this.add(feedinglabel);
  164. feedingmeslabel = new JLabel("MES允许扫码");
  165. feedingmeslabel.setHorizontalAlignment(SwingConstants.LEFT);
  166. feedingmeslabel.setIcon(imageGray);
  167. feedingmeslabel.setForeground(Color.BLACK);
  168. feedingmeslabel.setBounds(workWidth/3, 150, workWidth/3, 30);
  169. feedingmeslabel.addMouseListener(new MouseAdapter() {
  170. public void mouseClicked(MouseEvent e) {
  171. boolean ret = readScanFinish();
  172. int choice = JOptionPane.showConfirmDialog(null, "确定修改MES允许扫码结果为"+(ret?"false":"true")+"吗?", "操作确认", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
  173. if (choice == JOptionPane.YES_OPTION) {
  174. writeScanFinish(!ret);
  175. }
  176. }
  177. });
  178. this.add(feedingmeslabel);
  179. // transfertodevicelabel = new JLabel("中转车上料到设备");
  180. // transfertodevicelabel.setHorizontalAlignment(SwingConstants.LEFT);
  181. // transfertodevicelabel.setIcon(imageGreen);
  182. // transfertodevicelabel.setForeground(Color.BLACK);
  183. // transfertodevicelabel.setBounds(workWidth*2/3, 150, workWidth/3, 30);
  184. // this.add(transfertodevicelabel);
  185. //
  186. // blankinglabel = new JLabel("中转车号");
  187. // blankinglabel.setHorizontalAlignment(SwingConstants.LEFT);
  188. // blankinglabel.setIcon(imageGreen);
  189. // blankinglabel.setForeground(Color.BLACK);
  190. // blankinglabel.setBounds(0, 190, workWidth/3, 30);
  191. // this.add(blankinglabel);
  192. //
  193. // blankingmeslabel = new JLabel("放置层数");
  194. // blankingmeslabel.setHorizontalAlignment(SwingConstants.LEFT);
  195. // blankingmeslabel.setIcon(imageGreen);
  196. // blankingmeslabel.setForeground(Color.BLACK);
  197. // blankingmeslabel.setBounds(workWidth/3, 190, workWidth/3, 30);
  198. // this.add(blankingmeslabel);
  199. startOprnoTimer();
  200. resetScanA();
  201. formatElementUI();
  202. }
  203. public void formatElementUI(){
  204. cacheData = JdbcUtils.getCache(cacheName);
  205. if(cacheData == null){
  206. return;
  207. }
  208. String msg = cacheData.getMsg();
  209. int error = cacheData.getError();
  210. // String sn = cacheData.getSn();
  211. // productSn.setText(sn);
  212. // 缓存的码只用于历史追踪,不能恢复为当前扫码结果,否则会被误认为本轮已完成
  213. productSnFeeding.setText("");
  214. tjFlag = cacheData.getTjFlag();
  215. lastSn = cacheData.getLastSn();
  216. setMenuStatus(msg,error);
  217. this.repaint();
  218. }
  219. public void setMenuStatus(String msg,int error){
  220. if(error == 0){
  221. this.status_menu.setForeground(Color.GREEN);
  222. }else{
  223. this.status_menu.setForeground(Color.RED);
  224. }
  225. this.status_menu.setText(msg);
  226. cacheData.setMsg(msg);
  227. cacheData.setError(error);
  228. cacheData.setTjFlag(tjFlag);
  229. // cacheData.setTjStatus(tjStatus);
  230. cacheData.setLastSn(lastSn);
  231. cacheData.setSn(productSnFeeding.getText());
  232. cacheData.setFeedingSn(productSnFeeding.getText());
  233. JdbcUtils.setCache(cacheName, JSON.toJSONString(cacheData));
  234. }
  235. // 定时任务 -----------------------------------------------------------------------------------------------------
  236. public Timer oprnoTimer;
  237. public void startOprnoTimer() {
  238. //心跳显示图标
  239. if(oprnoTimer!=null) {
  240. oprnoTimer.cancel();
  241. }
  242. oprnoTimer = new Timer();
  243. oprnoTimer.schedule(new TimerTask() {
  244. public void run() {
  245. try{
  246. if(MesClient.isLogin == 1){
  247. Boolean retFeeding = readScanFeeding();
  248. feedinglabel.setIcon(retFeeding?imageGreen:imageGray);
  249. Boolean retFeedingAllow = readScanFinish();
  250. feedingmeslabel.setIcon(retFeedingAllow?imageGreen:imageGray);
  251. if(retFeeding){
  252. if(!Boolean.TRUE.equals(lastScanRequest)){
  253. startScanRequest();
  254. }
  255. if(scanCompletedForRequest){
  256. writeScanFinish(true);
  257. }else{
  258. barCode2();
  259. }
  260. }else{
  261. scanCompletedForRequest = false;
  262. writeScanFinish(false);
  263. }
  264. lastScanRequest = retFeeding;
  265. }
  266. }catch (Exception e) {
  267. log.error(e.getMessage());
  268. }
  269. }
  270. }, 100,1500);
  271. }
  272. private void startScanRequest(){
  273. scanCompletedForRequest = false;
  274. productSnFeeding.setText("");
  275. MesClient.clearScanCode(isScan);
  276. String pendingSn = manualPendingSn == null ? "" : manualPendingSn.trim();
  277. manualPendingSn = "";
  278. if(isValidSn(pendingSn)){
  279. publishScanResult(pendingSn, "手动录入");
  280. }else{
  281. setMenuStatus("正在扫码", 0);
  282. }
  283. }
  284. public void barCode2(){
  285. String sn = readQrcode();
  286. if(sn == null){
  287. sn = "";
  288. }
  289. sn = sn.trim();
  290. if(!isValidSn(sn)){
  291. setMenuStatus("扫码结果为空或格式不符", -1);
  292. return;
  293. }
  294. publishScanResult(sn, "扫码");
  295. }
  296. private void publishScanResult(String sn, String source){
  297. MesClient.publishScanCode(isScan, sn);
  298. productSnFeeding.setText(sn);
  299. scanCompletedForRequest = true;
  300. setMenuStatus(source + "成功", 0);
  301. if(readScanFeeding()){
  302. writeScanFinish(true);
  303. }
  304. }
  305. /** 手动输入工件码:回车确认,写入全局码并回写 PLC 扫码完成 */
  306. public void applyManualSn(){
  307. String sn = productSnFeeding.getText() == null ? "" : productSnFeeding.getText().trim();
  308. if(sn.isEmpty()){
  309. setMenuStatus("请输入工件码", -1);
  310. return;
  311. }
  312. if(!isValidSn(sn)){
  313. setMenuStatus("工件码应为16、19或24位,当前" + sn.length() + "位", -1);
  314. return;
  315. }
  316. manualPendingSn = sn;
  317. productSnFeeding.setText(sn);
  318. if(Boolean.TRUE.equals(lastScanRequest)){
  319. publishScanResult(sn, "手动录入");
  320. manualPendingSn = "";
  321. }else{
  322. setMenuStatus("手动录入成功,等待请求扫码", 0);
  323. }
  324. log.info("[{}]手动录入工件码: {}", oprno + pos, sn);
  325. }
  326. public static boolean isValidSn(String sn){
  327. if(sn == null){
  328. return false;
  329. }
  330. int length = sn.trim().length();
  331. return length == SN_LEN_SHORT || length == SN_LEN_LEGACY || length == SN_LEN_EVE;
  332. }
  333. public void resetFeeding() {
  334. productSnFeeding.setText("");
  335. tjFeedingFlag = 0;
  336. manualPendingSn = "";
  337. scanCompletedForRequest = false;
  338. MesClient.clearScanCode(isScan);
  339. setMenuStatus("等待请求扫码",0);
  340. resetFeedingBtn.setEnabled(true);
  341. // writeAllowFeeding(false);
  342. }
  343. public void resetScanA() {
  344. tjFeedingFlag = 0;
  345. tjFlag = 0;
  346. tjStatus = 0;
  347. // productSnFeeding.setText("5001040043561100050");
  348. productSnFeeding.setText("");
  349. manualPendingSn = "";
  350. scanCompletedForRequest = false;
  351. MesClient.clearScanCode(isScan);
  352. // setMenuStatus("等待请求扫码",0);
  353. if(isLocal == 0){
  354. writeScanFinish(false);
  355. }
  356. }
  357. // 与设备交互-----------------------------------------------------------------------------------------
  358. // 请求扫码
  359. public boolean readScanFeeding(){
  360. if(isLocal == 1){
  361. return true;
  362. }else{
  363. return readBoolean(plcDb+".0.0"); //7002 扫码
  364. }
  365. }
  366. // 扫码完成
  367. public boolean readScanFinish(){
  368. if(isLocal == 1){
  369. return false;
  370. }else{
  371. return readBoolean(plcDb+".0.1"); // MES允许扫码
  372. }
  373. }
  374. // MES允许扫码 / 扫码完成反馈
  375. public boolean writeScanFinish(boolean bt){
  376. if(isLocal == 1){
  377. return false;
  378. }else{
  379. return writeBoolean(plcDb+".0.1",bt);
  380. }
  381. }
  382. // 读取中转车上料到设备
  383. public boolean readFeedingTransferToDevice(){
  384. if(isLocal == 1){
  385. return true;
  386. }else{
  387. return readBoolean(plcDb+".0.2");
  388. }
  389. }
  390. // 读取中转车号
  391. public int readTransferNo(){
  392. if(isLocal == 1){
  393. return 1;
  394. }else{
  395. return s7PLC.readInt16(plcDb+".2.0");
  396. }
  397. }
  398. // 读取中转车层数
  399. public int readTransferFloor(){
  400. if(isLocal == 1){
  401. return 1;
  402. }else{
  403. return s7PLC.readInt16(plcDb+".4.0");
  404. }
  405. }
  406. // 控制扫码枪读取二维码
  407. public String readQrcode(){
  408. // String sn = "5001040043561010006";
  409. String sn = "";
  410. if(isLocal == 1){
  411. return "";
  412. }else{
  413. try{
  414. if(this.pos.equals("A")){
  415. sn = MesClient.scanQrcode1();
  416. }else{
  417. sn = MesClient.scanQrcode2();
  418. }
  419. }catch (Exception e) {
  420. e.printStackTrace();
  421. }
  422. }
  423. return sn;
  424. }
  425. public boolean readBoolean(String db){
  426. boolean permit;
  427. try {
  428. permit = s7PLC.readBoolean(db);
  429. // log.info("<"+this.oprno+this.pos+">读取"+db+"-->成功,结果:{}", permit ? "true" : "false");
  430. } catch (Exception e) {
  431. log.error("<"+this.oprno+this.pos+">读取"+db+"-->失败", e);
  432. return false;
  433. }
  434. return permit;
  435. }
  436. public boolean writeBoolean(String db, boolean permit){
  437. try {
  438. s7PLC.writeBoolean(db,permit);
  439. // log.info("<"+this.oprno+this.pos+">写入"+db+"-->成功,写入内容:{}", permit ? "true" : "false");
  440. } catch (Exception e) {
  441. // log.error("<"+this.oprno+this.pos+">写入"+db+"-->失败,写入内容:{}", permit ? "true" : "false");
  442. log.error(e.getMessage(), e);
  443. return false;
  444. }
  445. return true;
  446. }
  447. }