// ============================================================================= // DEE Action: ASA_Scenario5_ValidateCalibrationResult // Scenario: 5 — Custom DEE Action at Every Stage // Stage: Post-Action Validation // // Purpose: // After ASA_Scenario5_ExecuteStationRecalibration has run, query the QMS to // verify that the target baking station passed its post-calibration acceptance // tests. The QMS is the system of record — MES does not perform the check. // If the QMS reports the station failed or the result is not yet available, // return false so the task is marked ValidationFailed. // // Note: a ValidationFailed outcome does NOT undo the recalibration — the // action already ran. Investigate via the task's LastError field. // // Simulation: // The calibration acceptance result for each station is controlled by a // per-resource MES Configuration Entry, toggled independently from the MES UI: // // Path : /Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationPassed/{resourceName} // Type : Boolean // Value: true → acceptance tests passed → ProcessedSuccess // false → tests failed or pending → ValidationFailed // // Example entries for the tutorial resources: // /Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationPassed/ASA Baker-01 // /Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationPassed/ASA Baker-02 // // Set Baker-01 to false after the action runs to demonstrate a ValidationFailed // outcome where the action completed but the acceptance test did not pass. // // DEE Contract: // Input - Task : AutomationScheduledActionTask (includes target entity via EntityName) // Output - Result : Boolean (true = calibration passed, false = failed or pending) // // Fail-closed: any exception or missing config is treated as false. // ============================================================================= using Cmf.Foundation.BusinessOrchestration.Abstractions; using Cmf.Foundation.BusinessOrchestration.ConfigurationManagement.InputObjects; using Cmf.Foundation.Common.Abstractions; using Cmf.Foundation.Configuration.Abstractions; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; namespace Cmf.Custom.Tutorials.AutomationScheduleAction.Actions { public class ASA_Scenario5_ValidateCalibrationResult : DeeDevBase { public override bool DeeTestCondition(Dictionary Input) { //---Start DEE Condition Code--- return true; //---End DEE Condition Code--- } public override Dictionary DeeActionCode(Dictionary Input) { //---Start DEE Code--- UseReference("", "Cmf.Foundation.BusinessOrchestration.Abstractions"); UseReference("", "Cmf.Foundation.BusinessOrchestration.ConfigurationManagement"); UseReference("", "Cmf.Foundation.BusinessOrchestration.ConfigurationManagement.InputObjects"); IServiceProvider _svcProvider = Input["ServiceProvider"] as IServiceProvider; IEntityFactory _entFactory = _svcProvider.GetService(); //INPUT: Automation Scheduled Action Task var task = Input["Task"] as IAutomationScheduledActionTask; string resourceName = task?.EntityName ?? string.Empty; // In production this is where the QMS result query would go // For simulation, we just read the config value to determine if the calibration passed const string configParentPath = "/Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationPassed"; string configPath = $"{configParentPath}/{resourceName}"; IConfig calibConfig = _entFactory.Create(); if (!calibConfig.TryLoad(configPath)) { // Default to false if config is missing, which results in ValidationFailed, except for resources named Baker-01 var calibrationPassed = resourceName.Contains("Baker-01", StringComparison.OrdinalIgnoreCase); calibConfig.Name = resourceName; calibConfig.ValueType = "System.Boolean"; calibConfig.Value = calibrationPassed; calibConfig.Create(configParentPath); } bool passed = calibConfig.GetConfigValue(); //OUTPUT: Boolean - true if calibration passed, otherwise false to indicate that something will need to be investigated Input["Result"] = passed; //---End DEE Code--- return Input; } } }