|
@@ -5,8 +5,13 @@ import com.mes.core.StationContext;
|
|
|
import com.mes.tcp.MessageSender;
|
|
import com.mes.tcp.MessageSender;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 上传结果步骤
|
|
|
|
|
- * 发送MQDW消息上传加工结果
|
|
|
|
|
|
|
+ * 上传结果步骤(两阶段)
|
|
|
|
|
+ *
|
|
|
|
|
+ * 如果配置了物料绑定,执行流程:
|
|
|
|
|
+ * 阶段1: 发送MBDW(物料绑定),等待服务端响应
|
|
|
|
|
+ * 阶段2: MBDW成功后,发送MQDW(质量结果),等待服务端响应
|
|
|
|
|
+ *
|
|
|
|
|
+ * 如果没有物料,直接发送MQDW。
|
|
|
*
|
|
*
|
|
|
* 支持两种提交模式:
|
|
* 支持两种提交模式:
|
|
|
* - manual: 用户点击OK/NG后直接上传,不需要workStarted
|
|
* - manual: 用户点击OK/NG后直接上传,不需要workStarted
|
|
@@ -14,9 +19,17 @@ import com.mes.tcp.MessageSender;
|
|
|
*/
|
|
*/
|
|
|
public class UploadResultStep extends AbstractStep {
|
|
public class UploadResultStep extends AbstractStep {
|
|
|
|
|
|
|
|
|
|
+ /** 当前执行阶段 */
|
|
|
|
|
+ private enum Phase {
|
|
|
|
|
+ BIND_MATERIAL, // 阶段1: 绑定物料(MBDW)
|
|
|
|
|
+ UPLOAD_RESULT // 阶段2: 上传质量结果(MQDW)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private MessageSender messageSender;
|
|
private MessageSender messageSender;
|
|
|
private String result = "OK"; // 默认结果
|
|
private String result = "OK"; // 默认结果
|
|
|
private boolean manualMode = true; // 默认手动模式
|
|
private boolean manualMode = true; // 默认手动模式
|
|
|
|
|
+ private Phase currentPhase = Phase.UPLOAD_RESULT; // 当前阶段
|
|
|
|
|
+ private boolean needBindMaterial = false; // 是否需要绑定物料
|
|
|
|
|
|
|
|
public UploadResultStep() {
|
|
public UploadResultStep() {
|
|
|
super("upload_result", "上传结果");
|
|
super("upload_result", "上传结果");
|
|
@@ -28,10 +41,8 @@ public class UploadResultStep extends AbstractStep {
|
|
|
try {
|
|
try {
|
|
|
StationConfig config = StationConfig.getInstance();
|
|
StationConfig config = StationConfig.getInstance();
|
|
|
this.manualMode = config.isManualSubmitMode();
|
|
this.manualMode = config.isManualSubmitMode();
|
|
|
- // 手动模式需要用户点击OK/NG,自动模式不需要用户交互
|
|
|
|
|
this.requiresUserInteraction = this.manualMode;
|
|
this.requiresUserInteraction = this.manualMode;
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- // 配置未加载时使用默认值(手动模式)
|
|
|
|
|
this.requiresUserInteraction = true;
|
|
this.requiresUserInteraction = true;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -66,40 +77,59 @@ public class UploadResultStep extends AbstractStep {
|
|
|
context.setSubmitting(true);
|
|
context.setSubmitting(true);
|
|
|
context.setState(StationContext.WorkflowState.UPLOADING);
|
|
context.setState(StationContext.WorkflowState.UPLOADING);
|
|
|
|
|
|
|
|
- // 步骤1: 如果有物料且未绑定,先绑定物料
|
|
|
|
|
|
|
+ // 判断是否需要先绑定物料
|
|
|
StationConfig config = StationConfig.getInstance();
|
|
StationConfig config = StationConfig.getInstance();
|
|
|
- if (config.isShowMaterialInput() && context.getMaterialSn() != null && !context.getMaterialSn().isEmpty()) {
|
|
|
|
|
- if (!context.isMaterialBound()) {
|
|
|
|
|
- log.info("[{}] 开始绑定物料: {}", context.getStationCode(), context.getMaterialSn());
|
|
|
|
|
- context.setStatusMessage("正在绑定物料...", 0);
|
|
|
|
|
-
|
|
|
|
|
- if (messageSender != null) {
|
|
|
|
|
- boolean bindResult = messageSender.sendBindMaterial(
|
|
|
|
|
- productSn,
|
|
|
|
|
- context.getMaterialSn(),
|
|
|
|
|
- context.getUser(),
|
|
|
|
|
- "400004", // 物料绑定工艺号
|
|
|
|
|
- context.getStationCode()
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- if (!bindResult) {
|
|
|
|
|
- log.error("[{}] 物料绑定失败", context.getStationCode());
|
|
|
|
|
- context.setStatusMessage("物料绑定失败,自动提交中止", -1);
|
|
|
|
|
- context.setSubmitting(false);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- context.setMaterialBound(true);
|
|
|
|
|
- log.info("[{}] 物料绑定成功", context.getStationCode());
|
|
|
|
|
- } else {
|
|
|
|
|
- log.error("[{}] MessageSender未设置", context.getStationCode());
|
|
|
|
|
- context.setSubmitting(false);
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ needBindMaterial = config.isShowMaterialInput()
|
|
|
|
|
+ && context.getMaterialSn() != null
|
|
|
|
|
+ && !context.getMaterialSn().isEmpty()
|
|
|
|
|
+ && !context.isMaterialBound();
|
|
|
|
|
+
|
|
|
|
|
+ if (needBindMaterial) {
|
|
|
|
|
+ // 阶段1: 先发MBDW绑定物料,等待响应
|
|
|
|
|
+ currentPhase = Phase.BIND_MATERIAL;
|
|
|
|
|
+ this.messageType = "MBDW"; // 切换messageType,让引擎路由MBDW响应到本步骤
|
|
|
|
|
+
|
|
|
|
|
+ log.info("[{}] 开始绑定物料: {}", context.getStationCode(), context.getMaterialSn());
|
|
|
|
|
+ context.setStatusMessage("正在绑定物料...", 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (messageSender == null) {
|
|
|
|
|
+ log.error("[{}] MessageSender未设置", context.getStationCode());
|
|
|
|
|
+ context.setSubmitting(false);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ boolean sendOk = messageSender.sendBindMaterial(
|
|
|
|
|
+ productSn,
|
|
|
|
|
+ context.getMaterialSn(),
|
|
|
|
|
+ context.getUser(),
|
|
|
|
|
+ "400004", // 物料绑定工艺号
|
|
|
|
|
+ context.getStationCode()
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (!sendOk) {
|
|
|
|
|
+ log.error("[{}] 物料绑定消息发送失败", context.getStationCode());
|
|
|
|
|
+ context.setStatusMessage("物料绑定失败,自动提交中止", -1);
|
|
|
|
|
+ context.setSubmitting(false);
|
|
|
|
|
+ this.messageType = "MQDW"; // 恢复
|
|
|
|
|
+ currentPhase = Phase.UPLOAD_RESULT;
|
|
|
|
|
+ return false;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 返回true,等待MBDW服务端响应(引擎会设置超时)
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 不需要绑定物料,直接发MQDW
|
|
|
|
|
+ currentPhase = Phase.UPLOAD_RESULT;
|
|
|
|
|
+ this.messageType = "MQDW";
|
|
|
|
|
+ return sendQualityResult(context);
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 步骤2: 提交质量结果
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 发送质量结果(MQDW)
|
|
|
|
|
+ */
|
|
|
|
|
+ private boolean sendQualityResult(StationContext context) {
|
|
|
|
|
+ String productSn = context.getProcessedProductSn();
|
|
|
context.setStatusMessage("正在提交结果...", 0);
|
|
context.setStatusMessage("正在提交结果...", 0);
|
|
|
log.info("[{}] 上传结果: sn={}, result={}, craft={}", context.getStationCode(), productSn, result, craft);
|
|
log.info("[{}] 上传结果: sn={}, result={}, craft={}", context.getStationCode(), productSn, result, craft);
|
|
|
|
|
|
|
@@ -120,19 +150,64 @@ public class UploadResultStep extends AbstractStep {
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void onServerResponse(StationContext context, String resultCode, String message) {
|
|
public void onServerResponse(StationContext context, String resultCode, String message) {
|
|
|
|
|
+ if (currentPhase == Phase.BIND_MATERIAL) {
|
|
|
|
|
+ // 阶段1响应: MBDW物料绑定结果
|
|
|
|
|
+ handleBindMaterialResponse(context, resultCode, message);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 阶段2响应: MQDW质量结果上传
|
|
|
|
|
+ handleUploadResultResponse(context, resultCode, message);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 处理MBDW物料绑定响应
|
|
|
|
|
+ */
|
|
|
|
|
+ private void handleBindMaterialResponse(StationContext context, String resultCode, String message) {
|
|
|
|
|
+ if ("OK".equalsIgnoreCase(resultCode)) {
|
|
|
|
|
+ // 绑定成功,切换到阶段2
|
|
|
|
|
+ context.setMaterialBound(true);
|
|
|
|
|
+ log.info("[{}] 物料绑定成功,继续上传质量结果", context.getStationCode());
|
|
|
|
|
+
|
|
|
|
|
+ // 先切换messageType(让引擎检测到变化,不走onStepComplete)
|
|
|
|
|
+ currentPhase = Phase.UPLOAD_RESULT;
|
|
|
|
|
+ this.messageType = "MQDW";
|
|
|
|
|
+
|
|
|
|
|
+ // 发送MQDW
|
|
|
|
|
+ boolean sendOk = sendQualityResult(context);
|
|
|
|
|
+ if (!sendOk) {
|
|
|
|
|
+ // 发送失败,通过回调通知引擎步骤失败
|
|
|
|
|
+ log.error("[{}] 质量结果消息发送失败", context.getStationCode());
|
|
|
|
|
+ context.setSubmitting(false);
|
|
|
|
|
+ context.setStatusMessage("结果提交失败", -1);
|
|
|
|
|
+ notifyAsyncComplete(false);
|
|
|
|
|
+ }
|
|
|
|
|
+ // 发送成功则等待MQDW响应(引擎检测到messageType变化会更新映射并继续等待)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 绑定失败,messageType保持MBDW不变,引擎会调用onStepComplete(false)
|
|
|
|
|
+ context.setSubmitting(false);
|
|
|
|
|
+ String errorMsg = "物料绑定失败: " + resultCode;
|
|
|
|
|
+ context.setStatusMessage(errorMsg, -1);
|
|
|
|
|
+ log.error("[{}] {}", context.getStationCode(), errorMsg);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 处理MQDW质量结果上传响应
|
|
|
|
|
+ */
|
|
|
|
|
+ private void handleUploadResultResponse(StationContext context, String resultCode, String message) {
|
|
|
context.setSubmitting(false);
|
|
context.setSubmitting(false);
|
|
|
|
|
|
|
|
if ("OK".equalsIgnoreCase(resultCode)) {
|
|
if ("OK".equalsIgnoreCase(resultCode)) {
|
|
|
context.setResultUploaded(true);
|
|
context.setResultUploaded(true);
|
|
|
log.info("[{}] 结果上传成功", context.getStationCode());
|
|
log.info("[{}] 结果上传成功", context.getStationCode());
|
|
|
|
|
|
|
|
- // 步骤3: 清零PLC计数器(地址66、68、70)
|
|
|
|
|
|
|
+ // 清零PLC计数器(地址66、68、70)
|
|
|
if (context.getDeviceDriver() != null) {
|
|
if (context.getDeviceDriver() != null) {
|
|
|
try {
|
|
try {
|
|
|
log.info("[{}] 开始清零PLC计数器", context.getStationCode());
|
|
log.info("[{}] 开始清零PLC计数器", context.getStationCode());
|
|
|
- context.getDeviceDriver().writeRegister(66, 0); // 完成数量
|
|
|
|
|
- context.getDeviceDriver().writeRegister(68, 0); // 合格数量
|
|
|
|
|
- context.getDeviceDriver().writeRegister(70, 0); // 不合格数量
|
|
|
|
|
|
|
+ context.getDeviceDriver().writeRegister(66, 0);
|
|
|
|
|
+ context.getDeviceDriver().writeRegister(68, 0);
|
|
|
|
|
+ context.getDeviceDriver().writeRegister(70, 0);
|
|
|
log.info("[{}] PLC计数器清零成功", context.getStationCode());
|
|
log.info("[{}] PLC计数器清零成功", context.getStationCode());
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.error("[{}] PLC计数器清零失败: {}", context.getStationCode(), e.getMessage());
|
|
log.error("[{}] PLC计数器清零失败: {}", context.getStationCode(), e.getMessage());
|
|
@@ -153,12 +228,27 @@ public class UploadResultStep extends AbstractStep {
|
|
|
@Override
|
|
@Override
|
|
|
public void onTimeout(StationContext context) {
|
|
public void onTimeout(StationContext context) {
|
|
|
context.setSubmitting(false);
|
|
context.setSubmitting(false);
|
|
|
|
|
+ // 超时时恢复到初始状态
|
|
|
|
|
+ resetPhase();
|
|
|
super.onTimeout(context);
|
|
super.onTimeout(context);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 重置阶段状态(流程重置或超时时调用)
|
|
|
|
|
+ */
|
|
|
|
|
+ private void resetPhase() {
|
|
|
|
|
+ currentPhase = Phase.UPLOAD_RESULT;
|
|
|
|
|
+ this.messageType = "MQDW";
|
|
|
|
|
+ needBindMaterial = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void reset() {
|
|
|
|
|
+ resetPhase();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public void setManualMode(boolean manualMode) {
|
|
public void setManualMode(boolean manualMode) {
|
|
|
this.manualMode = manualMode;
|
|
this.manualMode = manualMode;
|
|
|
- // 手动模式需要用户交互,自动模式不需要
|
|
|
|
|
this.requiresUserInteraction = manualMode;
|
|
this.requiresUserInteraction = manualMode;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -177,32 +267,25 @@ public class UploadResultStep extends AbstractStep {
|
|
|
// 如果配置了物料,需要检查物料校验状态
|
|
// 如果配置了物料,需要检查物料校验状态
|
|
|
StationConfig config = StationConfig.getInstance();
|
|
StationConfig config = StationConfig.getInstance();
|
|
|
if (config.isShowMaterialInput()) {
|
|
if (config.isShowMaterialInput()) {
|
|
|
- // 有物料配置:需要物料已校验
|
|
|
|
|
boolean materialCondition = context.isMaterialValidated();
|
|
boolean materialCondition = context.isMaterialValidated();
|
|
|
log.debug("[{}] UploadResultStep.canExecute (with material): qualityPassed={}, materialValidated={}, resultUploaded={}",
|
|
log.debug("[{}] UploadResultStep.canExecute (with material): qualityPassed={}, materialValidated={}, resultUploaded={}",
|
|
|
context.getStationCode(), context.isQualityPassed(), context.isMaterialValidated(), context.isResultUploaded());
|
|
context.getStationCode(), context.isQualityPassed(), context.isMaterialValidated(), context.isResultUploaded());
|
|
|
|
|
|
|
|
- // 判断是否需要等待设备完成
|
|
|
|
|
if (context.isDeviceEnabled()) {
|
|
if (context.isDeviceEnabled()) {
|
|
|
- // 有设备:需要等待设备完成
|
|
|
|
|
boolean result = basicCondition && materialCondition && context.isWorkStarted();
|
|
boolean result = basicCondition && materialCondition && context.isWorkStarted();
|
|
|
log.debug("[{}] UploadResultStep.canExecute (device enabled): workStarted={}, result={}",
|
|
log.debug("[{}] UploadResultStep.canExecute (device enabled): workStarted={}, result={}",
|
|
|
context.getStationCode(), context.isWorkStarted(), result);
|
|
context.getStationCode(), context.isWorkStarted(), result);
|
|
|
return result;
|
|
return result;
|
|
|
} else {
|
|
} else {
|
|
|
- // 无设备:质量检查通过 + 物料已校验即可
|
|
|
|
|
return basicCondition && materialCondition;
|
|
return basicCondition && materialCondition;
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- // 无物料配置:按原逻辑
|
|
|
|
|
if (context.isDeviceEnabled()) {
|
|
if (context.isDeviceEnabled()) {
|
|
|
- // 有设备:需要等待设备完成
|
|
|
|
|
boolean result = basicCondition && context.isWorkStarted();
|
|
boolean result = basicCondition && context.isWorkStarted();
|
|
|
log.debug("[{}] UploadResultStep.canExecute (device enabled, no material): qualityPassed={}, workStarted={}, resultUploaded={}, result={}",
|
|
log.debug("[{}] UploadResultStep.canExecute (device enabled, no material): qualityPassed={}, workStarted={}, resultUploaded={}, result={}",
|
|
|
context.getStationCode(), context.isQualityPassed(), context.isWorkStarted(), context.isResultUploaded(), result);
|
|
context.getStationCode(), context.isQualityPassed(), context.isWorkStarted(), context.isResultUploaded(), result);
|
|
|
return result;
|
|
return result;
|
|
|
} else {
|
|
} else {
|
|
|
- // 无设备:质量检查通过即可
|
|
|
|
|
log.debug("[{}] UploadResultStep.canExecute (device disabled, no material): qualityPassed={}, resultUploaded={}, result={}",
|
|
log.debug("[{}] UploadResultStep.canExecute (device disabled, no material): qualityPassed={}, resultUploaded={}, result={}",
|
|
|
context.getStationCode(), context.isQualityPassed(), context.isResultUploaded(), basicCondition);
|
|
context.getStationCode(), context.isQualityPassed(), context.isResultUploaded(), basicCondition);
|
|
|
return basicCondition;
|
|
return basicCondition;
|
|
@@ -243,6 +326,7 @@ public class UploadResultStep extends AbstractStep {
|
|
|
context.setSubmitting(false);
|
|
context.setSubmitting(false);
|
|
|
context.setResultUploaded(true);
|
|
context.setResultUploaded(true);
|
|
|
context.setStatusMessage("(模拟) 结果提交成功,请扫下一件", 0);
|
|
context.setStatusMessage("(模拟) 结果提交成功,请扫下一件", 0);
|
|
|
|
|
+ resetPhase();
|
|
|
onSuccess(context);
|
|
onSuccess(context);
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+}
|