public async Task <CommandResult> ExecuteActionAsync(DeviceAction action, CancellationToken cancellationToken) { var result = CommandResult.NotApplied; IDeviceCommand command; if (_commands.TryGet(c => c.Action == action, out command) && CanApplyCommand(command)) { var execution = ApplyCommandsAsync(new[] { command }, cancellationToken); if (execution != null) { RecentCommandExecution = new DeviceCommandExecution(execution, command.TargetState); result = await execution; } } return(result); }
public bool TryGoToState(DeviceState targetState, CancellationToken cancellationToken, out Task <CommandResult> execution) { var currentState = State; execution = null; if (RecentCommandExecution.IsWorking == false && currentState != targetState) { IEnumerable <IDeviceCommand> commands = Enumerable.Empty <IDeviceCommand>(); var availableTriggers = _states.PermittedTriggers.ToArray(); if (currentState == DeviceState.Error) { // shortcut instead of double routing to target state first through disconnect after error and then forward to the target state. commands = _commands.Backward .SkipWhile(c => availableTriggers.Contains(c.Action) == false) .Concat(_commands.Forward.TakeUntil(c => c.TargetState == targetState)); } else if (currentState < targetState) { commands = _commands.Forward .SkipWhile(c => availableTriggers.Contains(c.Action) == false) .TakeUntil(c => c.TargetState == targetState); } else if (currentState > targetState) { commands = _commands.Backward .SkipWhile(c => availableTriggers.Contains(c.Action) == false) .TakeUntil(c => c.TargetState == targetState); } execution = ApplyCommandsAsync(commands, cancellationToken); if (execution != null) { RecentCommandExecution = new DeviceCommandExecution(execution, targetState); return(true); } } return(false); }