using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.SignalR.Client; using RobotNet10.Components.Clients; using RobotNet10.ScriptEngine.Shared; using RobotNet10.Shared; namespace RobotNet10.ScriptEditor.Clients; /// /// SignalR HubClient for ScriptManagerHub - handles ScriptEngine management operations. /// public class ScriptManagerHubClient : HubClient { public event Action? StateChanged; /// /// Gets the current ScriptEngine state. Updated when connected. /// public ScriptEngineState State { get; private set; } public ScriptManagerHubClient(NavigationManager navigationManager) : base(navigationManager.ToAbsoluteUri(HubEndpoints.ScriptManagerHubPath)) { Connection.On("StateChanged", state => { State = state; StateChanged?.Invoke(state); }); // Reload state when reconnected Connection.Reconnected += async _ => { if (IsConnected) { try { var newState = await GetStateAsync(); if (State != newState) { State = newState; StateChanged?.Invoke(newState); } else { // Even if state hasn't changed, trigger event to update UI StateChanged?.Invoke(newState); } } catch (Exception) { // Ignore errors when reloading state on reconnect } } }; } public override async Task StartAsync() { await base.StartAsync(); // Lưu state khi connected và trigger StateChanged event if (IsConnected) { var newState = await GetStateAsync(); if (State != newState) { State = newState; StateChanged?.Invoke(newState); } else { // Even if state hasn't changed, trigger event to update UI StateChanged?.Invoke(newState); } } } /// /// Gets the current state of the ScriptEngine. /// public Task GetStateAsync() => Connection.InvokeAsync("GetState"); /// /// Builds scripts from all files. Only allowed when state is Idle or BuildError. /// public Task BuildAsync() => Connection.InvokeAsync("Build"); /// /// Starts the ScriptEngine. Only allowed when state is Ready. /// public Task StartEingineAsync() => Connection.InvokeAsync("Start"); /// /// Stops the ScriptEngine. Only allowed when state is Running. /// public Task StopEingineAsync() => Connection.InvokeAsync("Stop"); /// /// Resets the ScriptEngine. Allowed from Idle, Ready, BuildError, Running, or Fault. /// public Task ResetAsync() => Connection.InvokeAsync("Reset"); #region VariableManager Methods /// /// Gets all script variables. /// public Task GetScriptVariablesAsync() => Connection.InvokeAsync("GetScriptVariables"); /// /// Finds specific script variables by names. /// public Task FindScriptVariablesAsync(string[] names) => Connection.InvokeAsync("FindScriptVariables", names); /// /// Sets the value of a script variable by name. /// public Task SetValueAsync(string name, string value) => Connection.InvokeAsync("SetValue", name, value); #endregion #region TaskManager Methods /// /// Gets all script tasks. /// public Task GetScriptTasksAsync() => Connection.InvokeAsync("GetScriptTasks"); /// /// Finds specific script tasks by names. /// public Task FindScriptTasksAsync(string[] names) => Connection.InvokeAsync("FindScriptTasks", names); /// /// Enables a task (resumes if paused, starts if stopped). /// public Task EnableTaskAsync(string name) => Connection.InvokeAsync("EnableTask", name); /// /// Disables a task (pauses if running). /// public Task DisableTaskAsync(string name) => Connection.InvokeAsync("DisableTask", name); #endregion #region MissionManager Methods /// /// Gets all script missions. /// public Task GetScriptMissionsAsync() => Connection.InvokeAsync("GetScriptMissions"); /// /// Finds specific script missions by names. /// public Task FindScriptMissionsAsync(string[] names) => Connection.InvokeAsync("FindScriptMissions", names); /// /// Creates a mission instance with parameters provided as a dictionary. /// /// The name of the mission model. /// Dictionary of parameter values keyed by parameter name (as strings). /// MessageResult containing the mission ID if successful. public Task> CreateMissionAsync(string name, IDictionary args) => Connection.InvokeAsync>("CreateMission", name, args); /// /// Cancels a running or paused mission. /// /// The ID of the mission instance to cancel. /// The reason for cancellation. /// True if the mission was canceled successfully, false otherwise. public Task CancelMissionAsync(Guid id, string reason) => Connection.InvokeAsync("CancelMission", id, reason); #endregion }