using RobotNet.VDA5050.Type; using RobotNet10.RobotApp.Devices; using RobotNet10.RobotApp.Services.Exceptions; using RobotNet10.RobotApp.Interfaces; namespace RobotNet10.RobotApp.Services.Robot.Actions; /// /// Bật đèn camera (M918 - coil 2966). /// action tương tự các action PLC toggle khác: ghi ON, rồi chờ PLC phản hồi đã ON. /// [RobotAction(ActionType.CONTROL_LIGHT, [ActionScope.INSTANT, ActionScope.NODE, ActionScope.EDGE], [BlockingType.NONE, BlockingType.SOFT, BlockingType.HARD], "Bật đèn camera (M918 Light on).", "Đèn camera đã bật (M918 Light on).")] public class ControlLightAction(IServiceProvider ServiceProvider) : RobotAction(ServiceProvider) { private IPlcController? PlcController; private const int MAX_TIMEOUT = 4000; private int CountTimeout = 0; private bool IsLightOn = false; protected override void Initialize() { base.Initialize(); var controlTypeParam = Action?.ActionParameters?.FirstOrDefault(p => string.Equals(p.Key, "CONTROL_TYPE", StringComparison.OrdinalIgnoreCase)); if (controlTypeParam is null || string.IsNullOrWhiteSpace(controlTypeParam.Value)) { throw new ActionException("ControlLight requires actionParameter CONTROL_TYPE (CONTROL_ON/CONTROL_OFF)."); } var controlType = controlTypeParam.Value.Trim(); if (string.Equals(controlType, "CONTROL_ON", StringComparison.OrdinalIgnoreCase)) { IsLightOn = true; } else if (string.Equals(controlType, "CONTROL_OFF", StringComparison.OrdinalIgnoreCase)) { IsLightOn = false; } else { throw new ActionException($"CONTROL_TYPE value '{controlType}' is invalid. Expected CONTROL_ON or CONTROL_OFF."); } CountTimeout = 0; } protected override Task StartAction() { PlcController = ServiceProvider.GetRequiredService(); PlcController.SetLightOn(IsLightOn); // M918 Light on return base.StartAction(); } protected override Task ExecuteAction() { if (PlcController is not null && PlcController.SetLightOnValue == IsLightOn) { SetStatus(ActionEvent.FINISHED); ResultDescription = string.IsNullOrEmpty(ActionAttribute.ResultDescription) ? ResultDescription : ActionAttribute.ResultDescription; } else if (CountTimeout++ > MAX_TIMEOUT / ActionInterval) { SetStatus(ActionEvent.FAILED); ResultDescription = "Timeout action"; } return base.ExecuteAction(); } }