package com.mes.controller; import com.alibaba.fastjson2.JSON; import com.mes.device.LaserDevice; import com.mes.ui.MesClient; import com.mes.util.DateLocalUtils; import com.mes.util.JdbcUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; /** * 激光切割双面控制器 * 参考OP60双面逻辑 */ public class LaserControllerDual { private static final Logger log = LoggerFactory.getLogger(LaserControllerDual.class); private LaserDevice device; // A面状态机 0=未开始 1=已扫码等待启动 2=设备运行中 3=设备运行结束 public static Integer tjFlaga = 0; public static String curSna = ""; public static List hjparamsA = new ArrayList<>(); public static Integer tjStatusa = 0; // 1=提交失败 public static Boolean mesQualityFlagA = false; // true=MES质检通过可工作 // B面状态机 public static Integer tjFlagb = 0; public static String curSnb = ""; public static List hjparamsB = new ArrayList<>(); public static Integer tjStatusb = 0; public static Boolean mesQualityFlagB = false; public LaserControllerDual(LaserDevice device) { this.device = device; } /** * 状态检测(1秒调用1次,参考OP60的getPlcParam) */ public void checkStatus() { try { if(!device.isConnected()) { return; } // A面状态检测 checkStatusA(); // B面状态检测 checkStatusB(); } catch (Exception e) { log.error("状态检测异常", e); } } /** * A面状态检测(参考OP60的getStatusA) * 完成判定只看 #1593==1(持续信号),不要求 working==1 * 因为加工完成瞬间 #1591 会变 0、#1593 变 1,两者互斥 */ private void checkStatusA() { try { // 读取A面加工中状态 #1591 int working = device.readWorking("A"); if(tjFlaga == 1 && working == 1) { // 状态切换:1(等待启动)→ 2(运行中) tjFlaga = 2; log.info("A面检测到设备启动,开始采集参数"); MesClient.pxstatus1.setText("A面运行中"); // A面启动不清零#1590,保持允许信号给B面使用 log.info("A面启动,保持#1590=1供B面使用"); } else if(tjFlaga == 2) { // 运行中,检测是否完成(不看 working,因为完成瞬间 working 会变 0) int finish = device.readFinish("A"); if(finish == 1) { // 状态切换:2(运行中)→ 3(完成) tjFlaga = 3; log.info("A面检测到设备完成(#1593=1)"); MesClient.pxstatus1.setText("A面完成,提交中"); // 保存剩余参数 if(hjparamsA.size() > 0) { saveParams("A"); } // 上传结果到MES boolean sendret = sendQuality(curSna, "OK", "A"); if(!sendret) { tjStatusa = 1; log.error("A面结果上传MES失败"); MesClient.pxstatus1.setText("A面上传失败"); } else { log.info("A面结果上传成功,复位状态(不清零#1590,供B面使用)"); resetStatusA(); MesClient.pxstatus1.setText("A面提交成功"); } // A面完成不清零#1590,让B面可以直接启动 } } } catch (Exception e) { log.error("A面状态检测异常", e); } } /** * B面状态检测(参考OP60的getStatusB) * B面不需要扫码,利用A面的允许信号直接启动 * B面完成后才清零#1590,为下一轮A面扫码准备 */ private void checkStatusB() { try { // 读取B面加工中状态 #1592 int working = device.readWorking("B"); if(tjFlagb == 0 && working == 1) { // B面直接启动(无需扫码,tjFlagb从0直接到2) tjFlagb = 2; log.info("B面检测到设备启动(无需扫码),开始采集参数"); MesClient.pxstatus2.setText("B面运行中"); } else if(tjFlagb == 2) { // 运行中,检测是否完成 int finish = device.readFinish("B"); if(finish == 1) { // 状态切换:2(运行中)→ 3(完成) tjFlagb = 3; log.info("B面检测到设备完成(#1594=1)"); MesClient.pxstatus2.setText("B面完成,提交中"); // 保存剩余参数 if(hjparamsB.size() > 0) { saveParams("B"); } // B面不提交MES结果,只管控A面 log.info("B面完成,清零#1590禁止启动,等待下一轮A面扫码"); device.writeMesEnable(0); resetStatusB(); MesClient.pxstatus2.setText("B面完成"); } } } catch (Exception e) { log.error("B面状态检测异常", e); } } /** * 参数采集(1秒调用1次,参考OP60的getPlcParams) */ public void collectParams() { try { if(!device.isConnected()) { return; } // A面采集 if(tjFlaga == 2) { collectParamsA(); } // B面采集 if(tjFlagb == 2) { collectParamsB(); } } catch (Exception e) { log.error("参数采集异常", e); } } /** * A面参数采集 */ private void collectParamsA() { try { // 读取参数 double speed = device.readSpeed(); // #33563 进给速度 double time = device.readTime("A"); // #1595 加工时间 int count = device.readCount("A"); // #1597 零件计数 // 拼接参数字符串 String timestamp = DateLocalUtils.getCurrentTime(); String record = speed + "|" + time + "|" + count + "|" + timestamp; hjparamsA.add(record); log.debug("A面采集参数: {}", record); // 更新UI显示 MesClient.param1.setText(String.format("%.1f", speed)); MesClient.param2.setText(String.format("%.0f", time)); MesClient.param3.setText(String.valueOf(count)); // 满60条存储 if(hjparamsA.size() >= 60) { saveParams("A"); } } catch (Exception e) { log.error("A面参数采集异常", e); } } /** * B面参数采集 */ private void collectParamsB() { try { // 读取参数 double speed = device.readSpeed(); // #33563 进给速度 double time = device.readTime("B"); // #1596 加工时间 int count = device.readCount("B"); // #1598 零件计数 // 拼接参数字符串 String timestamp = DateLocalUtils.getCurrentTime(); String record = speed + "|" + time + "|" + count + "|" + timestamp; hjparamsB.add(record); log.debug("B面采集参数: {}", record); // 更新UI显示 MesClient.param21.setText(String.format("%.1f", speed)); MesClient.param22.setText(String.format("%.0f", time)); MesClient.param23.setText(String.valueOf(count)); // 满60条存储 if(hjparamsB.size() >= 60) { saveParams("B"); } } catch (Exception e) { log.error("B面参数采集异常", e); } } /** * 保存参数到SQLite */ private void saveParams(String side) { try { List params = side.equals("A") ? hjparamsA : hjparamsB; String sn = side.equals("A") ? curSna : curSnb; if(params.size() == 0) { return; } if(sn == null || sn.trim().isEmpty()) { log.warn("{}面工件码为空,跳过保存数据", side); params.clear(); return; } String oprno = MesClient.mes_gw; String lineSn = MesClient.mes_line_sn; String paramsJson = JSON.toJSONString(params); JdbcUtils.insertLaserData(oprno, lineSn, sn, paramsJson); log.info("{}面保存参数: sn={}, count={}", side, sn, params.size()); params.clear(); } catch (Exception e) { log.error("{}面保存参数异常", side, e); } } /** * 上传结果到MES */ private boolean sendQuality(String sn, String result, String side) { try { // 调用MES接口(使用标准的 sendQuality,会发送到MES服务器) String user = MesClient.user_menu.getText(); String user20 = MesClient.getBarcode(user); boolean ret = com.mes.ui.DataUtil.sendQuality( MesClient.nettyClient, sn, result, user20 ); log.info("{}面上传结果: sn={}, result={}, ret={}", side, sn, result, ret); return ret; } catch (Exception e) { log.error("{}面上传结果异常", side, e); return false; } } /** * 复位A面状态 */ private void resetStatusA() { tjFlaga = 0; curSna = ""; hjparamsA.clear(); tjStatusa = 0; mesQualityFlagA = false; MesClient.product_sn.setText(""); MesClient.param1.setText(""); MesClient.param2.setText(""); MesClient.param3.setText(""); MesClient.pxstatus1.setText("A"); log.info("A面状态已复位"); } /** * 复位B面状态 */ private void resetStatusB() { tjFlagb = 0; curSnb = ""; hjparamsB.clear(); tjStatusb = 0; mesQualityFlagB = false; MesClient.product_sn2.setText(""); MesClient.param21.setText(""); MesClient.param22.setText(""); MesClient.param23.setText(""); MesClient.pxstatus2.setText("B"); log.info("B面状态已复位"); } /** * 扫码处理(A面) */ public boolean onScanCodeA(String sn, String user) { try { // 检查状态 if(tjFlaga != 0) { log.warn("A面上一个工件未完成"); return false; } log.info("A面扫码: {}", sn); curSna = sn; tjFlaga = 1; // 等待MES质检回复后再写#1590=1 // 这里先标记状态,等DataUtil.checkQuality回调后再写 return true; } catch (Exception e) { log.error("A面扫码处理异常", e); return false; } } /** * 扫码处理(B面) */ public boolean onScanCodeB(String sn, String user) { try { // 检查状态 if(tjFlagb != 0) { log.warn("B面上一个工件未完成"); return false; } log.info("B面扫码: {}", sn); curSnb = sn; tjFlagb = 1; return true; } catch (Exception e) { log.error("B面扫码处理异常", e); return false; } } /** * MES质检通过回调(A面) */ public void onMesQualityPassA() { try { mesQualityFlagA = true; // 写#1590=1(允许启动) boolean ret = device.writeMesEnable(1); if(ret) { log.info("A面MES质检通过,写入#1590=1(允许启动)"); MesClient.pxstatus1.setText("A面等待启动"); } else { log.error("A面写入#1590=1失败"); MesClient.pxstatus1.setText("A面写信号失败"); } } catch (Exception e) { log.error("A面MES质检回调异常", e); } } /** * MES质检通过回调(B面) * B面不需要扫码,此方法不再使用 */ public void onMesQualityPassB() { try { mesQualityFlagB = true; log.info("B面质检回调(B面不需要扫码,忽略)"); // B面不写#1590,利用A面的允许信号 } catch (Exception e) { log.error("B面MES质检回调异常", e); } } /** * 手动复位A面 */ public void manualResetA() { log.warn("手动复位A面状态"); resetStatusA(); } /** * 手动复位B面 */ public void manualResetB() { log.warn("手动复位B面状态"); resetStatusB(); } }