// ============================================================================= // DEE Action: ASA_Scenario5_ResolveStationsDueForCalibration // Scenario: 5 — Custom DEE Action at Every Stage // Stage: Context (Resolver) // // Purpose: // Return the list of baking station resources that the QMS has scheduled // for recalibration in the current cycle. Only stations on the QMS schedule // receive tasks — stations that are not due are excluded entirely, so no // downstream DEE is ever invoked for them. // // This avoids the cost of creating and polling tasks for every BakingController // instance only to have them blocked at the detector stage because the QMS has // not scheduled them yet. The QMS schedule is the first and cheapest gate. // // Simulation: // The schedule state for each station is controlled by a per-station MES // Configuration Entry, toggled independently from the MES UI: // // Path : /Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationScheduled/{stationKey} // Type : Boolean // Value: true → station is due for recalibration → task is created // false → station is not scheduled this cycle → no task created // // Example entries for the tutorial resources: // /Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationScheduled/Baker-01 // /Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationScheduled/Baker-02 // // The resolver maps the station keys above to the sample MES resources // `ASA Baker-01` and `ASA Baker-02`. // // Set Baker-02 to false to demonstrate that the resolver excludes it entirely — // no task is created for Baker-02, and no downstream DEE is invoked for it. // // DEE Contract: // Input - Definition : AutomationScheduledActionDefinition // Output - Result : IResource[] (resources for which tasks should be created) // // Fail-closed: any exception returns an empty array — no tasks are created. // ============================================================================= using Cmf.Foundation.BusinessOrchestration.Abstractions; using Cmf.Foundation.BusinessOrchestration.ConfigurationManagement.InputObjects; using Cmf.Foundation.Common.Abstractions; using Cmf.Foundation.Configuration.Abstractions; using Cmf.Foundation.BusinessObjects.Abstractions; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; namespace Cmf.Custom.Tutorials.AutomationScheduleAction.Actions { public class ASA_Scenario5_ResolveStationsDueForCalibration : 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"); UseReference("", "Cmf.Foundation.BusinessObjects"); IServiceProvider _svcProvider = Input["ServiceProvider"] as IServiceProvider; IEntityFactory _entFactory = _svcProvider.GetService(); // In production this list would come from the QMS schedule API directly as resource names. // or by querying MES for a subset of AutomationControllerInstances of BakingController [A.1]. (string resourceName, string stationKey)[] knownStations = { ("ASA Baker-01", "Baker-01"), ("ASA Baker-02", "Baker-02") }; const string configParentPath = "/Cmf/Tutorials/AutomationScheduleAction/Scenario5/CalibrationScheduled"; var scheduledResources = new List(); foreach (var (resourceName, stationKey) in knownStations) { string configPath = $"{configParentPath}/{stationKey}"; IConfig scheduledConfig = _entFactory.Create(); if (!scheduledConfig.TryLoad(configPath)) { scheduledConfig.Name = stationKey; scheduledConfig.ValueType = "System.Boolean"; scheduledConfig.Value = false; scheduledConfig.Create(configParentPath); } bool isScheduled = scheduledConfig.GetConfigValue(); if (!isScheduled) { continue; } var resource = _entFactory.Create(); resource.Name = resourceName; resource.Load(); scheduledResources.Add(resource); } //OUTPUT: IResource[] Input["Result"] = scheduledResources.ToArray(); //---End DEE Code--- return Input; } } }