Initial commit

This commit is contained in:
2026-07-03 16:31:37 +07:00
commit 899c7c637d
1939 changed files with 641750 additions and 0 deletions

View File

@@ -0,0 +1,336 @@
using Appccelerate.StateMachine;
using Appccelerate.StateMachine.AsyncMachine;
using Appccelerate.StateMachine.AsyncMachine.Events;
namespace RobotNet10.RobotApp.Services.State;
public class RobotStateMachine(Logger<RobotStateMachine> Logger, RobotStateMachineExecute StateExecute)
{
private AsyncPassiveStateMachine<RobotStateType, RobotEventType>? _stateMachine;
private RobotStateType _currentState = RobotStateType.System;
public bool IsInitialized { get; private set; } = false;
public RobotStateType CurrentState => _currentState;
public event EventHandler<StateChangedEventArgs>? StateChanged;
// Dictionary để track hierarchy relationships cho helper methods
private readonly Dictionary<RobotStateType, RobotStateType> _stateHierarchies = [];
public async Task InitializeAsync()
{
if (IsInitialized) return;
var builder = new StateMachineDefinitionBuilder<RobotStateType, RobotEventType>();
// Build hierarchy map (chỉ cần track parent-child relationship)
BuildHierarchyMap();
// ===========================
// ROOT LEVEL - Hierarchical States
// ===========================
// System State Hierarchy
builder.In(RobotStateType.System)
.On(RobotEventType.EnterAuto).Goto(RobotStateType.Auto)
.On(RobotEventType.EnterManual).Goto(RobotStateType.Manual)
.On(RobotEventType.EnterService).Goto(RobotStateType.Service)
.On(RobotEventType.RemoteOverride).Goto(RobotStateType.Remote_Override)
.On(RobotEventType.EnterStop).Goto(RobotStateType.Stop)
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
builder.DefineHierarchyOn(RobotStateType.System)
.WithHistoryType(HistoryType.Deep)
.WithInitialSubState(RobotStateType.Initializing)
.WithSubState(RobotStateType.Standby)
.WithSubState(RobotStateType.Shutting_Down);
// Auto State Hierarchy
builder.In(RobotStateType.Auto)
.On(RobotEventType.EnterManual).Goto(RobotStateType.Manual)
.On(RobotEventType.EnterService).Goto(RobotStateType.Service)
.On(RobotEventType.RemoteOverride).Goto(RobotStateType.Remote_Override)
.On(RobotEventType.EnterStop).Goto(RobotStateType.Stop)
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
builder.DefineHierarchyOn(RobotStateType.Auto)
.WithHistoryType(HistoryType.Deep)
.WithInitialSubState(RobotStateType.Idle)
.WithSubState(RobotStateType.Executing)
.WithSubState(RobotStateType.Paused)
.WithSubState(RobotStateType.Canceling)
.WithSubState(RobotStateType.Recovering);
// Manual State
builder.In(RobotStateType.Manual)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Manual); StateExecute.EntryManual(); })
.ExecuteOnExit(StateExecute.ExitManual)
.On(RobotEventType.EnterAuto).Goto(RobotStateType.Auto)
.On(RobotEventType.EnterService).Goto(RobotStateType.Service)
.On(RobotEventType.RemoteOverride).Goto(RobotStateType.Remote_Override)
.On(RobotEventType.EnterStop).Goto(RobotStateType.Stop)
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
// Service State
builder.In(RobotStateType.Service)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Service); StateExecute.EntryService(); })
.ExecuteOnExit(StateExecute.ExitService)
.On(RobotEventType.EnterAuto).Goto(RobotStateType.Auto)
.On(RobotEventType.EnterManual).Goto(RobotStateType.Manual)
.On(RobotEventType.RemoteOverride).Goto(RobotStateType.Remote_Override)
.On(RobotEventType.EnterStop).Goto(RobotStateType.Stop)
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
// Stop State
builder.In(RobotStateType.Stop)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Stop); StateExecute.EntryStop(); })
.ExecuteOnExit(StateExecute.ExitStop)
.On(RobotEventType.ReleaseStop).Goto(RobotStateType.System)
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
// Fault State
builder.In(RobotStateType.Fault)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Fault); StateExecute.EntryFault(); })
.ExecuteOnExit(StateExecute.ExitFault)
.On(RobotEventType.ExitFault).Goto(RobotStateType.System);
// Remote_Override State (top-level, peer of Service)
builder.In(RobotStateType.Remote_Override)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Remote_Override); StateExecute.EntryRemoteOverride(); })
.ExecuteOnExit(StateExecute.ExitRemoteOverride)
.On(RobotEventType.EnterAuto).Goto(RobotStateType.Auto)
.On(RobotEventType.EnterManual).Goto(RobotStateType.Manual)
.On(RobotEventType.EnterService).Goto(RobotStateType.Service)
.On(RobotEventType.EnterStop).Goto(RobotStateType.Stop)
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
// ===========================
// SYSTEM SUB-STATES
// ===========================
builder.In(RobotStateType.Initializing)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Initializing); StateExecute.EntryInitializing(); })
.On(RobotEventType.InitializeCompleted).Goto(RobotStateType.Standby)
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
builder.In(RobotStateType.Standby)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Standby); StateExecute.EntryStandby(); })
.On(RobotEventType.Shutdown).Goto(RobotStateType.Shutting_Down);
builder.In(RobotStateType.Shutting_Down)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Shutting_Down); StateExecute.EntryShuttingDown(); })
.ExecuteOnExit(StateExecute.ExitShuttingDown)
.On(RobotEventType.ShutdownCompleted).Goto(RobotStateType.Standby);
// ===========================
// AUTO SUB-STATES
// ===========================
builder.In(RobotStateType.Idle)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Idle); StateExecute.EntryIdle(); })
.On(RobotEventType.StartExecution).Goto(RobotStateType.Executing);
// Executing State Hierarchy
builder.In(RobotStateType.Executing)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Executing); StateExecute.EntryExecuting(); })
.ExecuteOnExit(StateExecute.ExitExecuting)
.On(RobotEventType.PauseExecution).Goto(RobotStateType.Paused)
.On(RobotEventType.CancelExecution).Goto(RobotStateType.Canceling)
.On(RobotEventType.CompleteExecution).Goto(RobotStateType.Idle);
builder.DefineHierarchyOn(RobotStateType.Executing)
.WithHistoryType(HistoryType.Deep)
.WithInitialSubState(RobotStateType.Moving)
.WithSubState(RobotStateType.ACT);
builder.In(RobotStateType.Paused)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Paused); StateExecute.EntryPaused(); })
.ExecuteOnExit(StateExecute.ExitPaused)
.On(RobotEventType.ResumeExecution).Goto(RobotStateType.Executing)
.On(RobotEventType.CancelExecution).Goto(RobotStateType.Canceling);
builder.In(RobotStateType.Canceling)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Canceling); StateExecute.EntryCanceling(); })
.ExecuteOnExit(StateExecute.ExitCanceling)
.On(RobotEventType.CompleteExecution).Goto(RobotStateType.Idle);
builder.In(RobotStateType.Recovering)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Recovering); StateExecute.EntryRecovering(); })
.On(RobotEventType.CompleteRecovery).Goto(RobotStateType.Idle);
// ===========================
// EXECUTING SUB-STATES
// ===========================
// Moving State Hierarchy
builder.In(RobotStateType.Moving)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Moving); StateExecute.EntryMoving(); })
.ExecuteOnExit(StateExecute.ExitMoving)
.On(RobotEventType.StartACT).Goto(RobotStateType.ACT)
.On(RobotEventType.CompleteMoving).Goto(RobotStateType.Idle);
// ACT State Hierarchy
builder.In(RobotStateType.ACT)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.ACT); StateExecute.EntryACT(); })
.ExecuteOnExit(StateExecute.ExitACT)
.On(RobotEventType.StartMoving).Goto(RobotStateType.Moving)
.On(RobotEventType.CompleteACT).Goto(RobotStateType.Idle);
builder.DefineHierarchyOn(RobotStateType.ACT)
.WithHistoryType(HistoryType.Deep)
.WithInitialSubState(RobotStateType.Docking)
.WithSubState(RobotStateType.Docked)
.WithSubState(RobotStateType.Charging)
.WithSubState(RobotStateType.Undocking)
.WithSubState(RobotStateType.Loading)
.WithSubState(RobotStateType.Unloading)
.WithSubState(RobotStateType.TechAction);
// ===========================
// ACT SUB-STATES
// ===========================
builder.In(RobotStateType.Docking)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Docking); StateExecute.EntryDocking(); })
.On(RobotEventType.CompleteDocking).Goto(RobotStateType.Docked);
builder.In(RobotStateType.Docked)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Docked); StateExecute.EntryDocked(); })
.On(RobotEventType.StartCharging).Goto(RobotStateType.Charging)
.On(RobotEventType.StartUndocking).Goto(RobotStateType.Undocking)
.On(RobotEventType.StartLoading).Goto(RobotStateType.Loading)
.On(RobotEventType.StartUnloading).Goto(RobotStateType.Unloading);
builder.In(RobotStateType.Charging)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Charging); StateExecute.EntryCharging(); })
.ExecuteOnExit(StateExecute.ExitCharging)
.On(RobotEventType.CompleteCharging).Goto(RobotStateType.Docked);
builder.In(RobotStateType.Undocking)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Undocking); StateExecute.EntryUndocking(); })
.On(RobotEventType.CompleteUndocking).Goto(RobotStateType.Docking);
builder.In(RobotStateType.Loading)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Loading); StateExecute.EntryLoading(); })
.On(RobotEventType.CompleteLoading).Goto(RobotStateType.Docked);
builder.In(RobotStateType.Unloading)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.Unloading); StateExecute.EntryUnloading(); })
.On(RobotEventType.CompleteUnloading).Goto(RobotStateType.Docked);
builder.In(RobotStateType.TechAction)
.ExecuteOnEntry(() => { OnEnterState(RobotStateType.TechAction); StateExecute.EntryTechAction(); })
.On(RobotEventType.CompleteTechAction).Goto(RobotStateType.Docked);
// ===========================
// CREATE STATE MACHINE
// ===========================
_stateMachine = builder
.WithInitialState(RobotStateType.System)
.Build()
.CreatePassiveStateMachine();
// Subscribe to state change events
_stateMachine.TransitionCompleted += OnTransitionCompleted;
// Set IsInitialized = true TRƯỚC khi Start() để tránh deadlock
// Vì EntryInitializing() có thể gọi ModuleInitializeAsync() chờ IsInitialized
IsInitialized = true;
// Start state machine
await _stateMachine.Start();
Logger.Info($"State Machine initialized successfully with current state: {CurrentState}");
}
/// <summary>
/// Build hierarchy map - chỉ để track parent-child relationships cho helper methods
/// Không cần build transitions vì Appccelerate tự động xử lý
/// </summary>
private void BuildHierarchyMap()
{
// System sub-states
_stateHierarchies[RobotStateType.Initializing] = RobotStateType.System;
_stateHierarchies[RobotStateType.Standby] = RobotStateType.System;
_stateHierarchies[RobotStateType.Shutting_Down] = RobotStateType.System;
// Auto sub-states
_stateHierarchies[RobotStateType.Idle] = RobotStateType.Auto;
_stateHierarchies[RobotStateType.Executing] = RobotStateType.Auto;
_stateHierarchies[RobotStateType.Paused] = RobotStateType.Auto;
_stateHierarchies[RobotStateType.Canceling] = RobotStateType.Auto;
_stateHierarchies[RobotStateType.Recovering] = RobotStateType.Auto;
// Executing sub-states
_stateHierarchies[RobotStateType.Moving] = RobotStateType.Executing;
_stateHierarchies[RobotStateType.ACT] = RobotStateType.Executing;
// ACT sub-states
_stateHierarchies[RobotStateType.Docking] = RobotStateType.ACT;
_stateHierarchies[RobotStateType.Docked] = RobotStateType.ACT;
_stateHierarchies[RobotStateType.Charging] = RobotStateType.ACT;
_stateHierarchies[RobotStateType.Undocking] = RobotStateType.ACT;
_stateHierarchies[RobotStateType.Loading] = RobotStateType.ACT;
_stateHierarchies[RobotStateType.Unloading] = RobotStateType.ACT;
_stateHierarchies[RobotStateType.TechAction] = RobotStateType.ACT;
}
public void Initialize() => InitializeAsync().GetAwaiter().GetResult();
public async Task FireAsync(RobotEventType eventType)
{
if (!IsInitialized)
{
Logger.Warning("State Machine not initialized!");
return;
}
try
{
if (_stateMachine != null)
{
await _stateMachine.Fire(eventType);
}
}
catch (Exception ex)
{
Logger.Error($"Fire event {eventType} error: {ex.Message}");
}
}
public void Fire(RobotEventType eventType) => FireAsync(eventType).GetAwaiter().GetResult();
public bool IsInState(RobotStateType state)
{
if (!IsInitialized) return false;
if (CurrentState == state) return true;
if(_stateHierarchies.TryGetValue(CurrentState, out RobotStateType parentState))
{
if(parentState == state) return true;
while (_stateHierarchies.TryGetValue(parentState, out parentState))
{
if (parentState == state) return true;
}
}
return false;
}
private void OnEnterState(RobotStateType state)
{
_currentState = state;
}
private void OnTransitionCompleted(object? sender, TransitionCompletedEventArgs<RobotStateType, RobotEventType> e)
{
Logger.Info($"State Transition: {e.StateId} -> Event: {e.EventId}");
StateChanged?.Invoke(this, new StateChangedEventArgs(e.StateId, e.EventId));
}
}
public class StateChangedEventArgs(RobotStateType newState, RobotEventType eventType) : EventArgs
{
public RobotStateType NewState { get; } = newState;
public RobotEventType EventType { get; } = eventType;
}