update
This commit is contained in:
parent
90dcb67b60
commit
9ac5270885
|
|
@ -4,6 +4,7 @@ namespace RobotApp.Interfaces;
|
||||||
|
|
||||||
public interface IError
|
public interface IError
|
||||||
{
|
{
|
||||||
|
event Action? OnNewFatalError;
|
||||||
bool HasFatalError { get; }
|
bool HasFatalError { get; }
|
||||||
void AddError(Error error, TimeSpan? clearAfter = null);
|
void AddError(Error error, TimeSpan? clearAfter = null);
|
||||||
void DeleteErrorType(string errorType);
|
void DeleteErrorType(string errorType);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
namespace RobotApp.Interfaces;
|
using RobotApp.VDA5050.State;
|
||||||
|
|
||||||
|
namespace RobotApp.Interfaces;
|
||||||
|
|
||||||
public interface IInfomation
|
public interface IInfomation
|
||||||
{
|
{
|
||||||
|
void AddInfo(Information infor);
|
||||||
|
void DeleteInfoType(string infoType);
|
||||||
|
void ClearAllInfos();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
8
RobotApp/Interfaces/ILoad.cs
Normal file
8
RobotApp/Interfaces/ILoad.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
using RobotApp.VDA5050.State;
|
||||||
|
|
||||||
|
namespace RobotApp.Interfaces;
|
||||||
|
|
||||||
|
public interface ILoad
|
||||||
|
{
|
||||||
|
Load? Load { get; }
|
||||||
|
}
|
||||||
|
|
@ -6,20 +6,25 @@ using System.Text.Json;
|
||||||
|
|
||||||
namespace RobotApp.Services.Robot;
|
namespace RobotApp.Services.Robot;
|
||||||
|
|
||||||
public class RobotConnection(RobotConfiguration RobotConfiguration, Logger<RobotConnection> Logger, Logger<MQTTClient> MQTTClientLogger)
|
public class RobotConnection(RobotConfiguration RobotConfiguration,
|
||||||
|
Logger<RobotConnection> Logger,
|
||||||
|
Logger<MQTTClient> MQTTClientLogger)
|
||||||
{
|
{
|
||||||
private readonly VDA5050Setting VDA5050Setting = RobotConfiguration.VDA5050Setting;
|
private readonly VDA5050Setting VDA5050Setting = RobotConfiguration.VDA5050Setting;
|
||||||
private MQTTClient? MqttClient;
|
private MQTTClient? MqttClient;
|
||||||
|
|
||||||
public bool IsConnected => MqttClient is not null && MqttClient.IsConnected;
|
public bool IsConnected => MqttClient is not null && MqttClient.IsConnected;
|
||||||
public readonly string SerialNumber = RobotConfiguration.SerialNumber;
|
public event Action<OrderMsg>? OrderUpdated;
|
||||||
|
public event Action<InstantActionsMsg>? ActionUpdated;
|
||||||
|
|
||||||
|
|
||||||
private void OrderChanged(string data)
|
private void OrderChanged(string data)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var msg = JsonSerializer.Deserialize<OrderMsg>(data);
|
var msg = JsonSerializer.Deserialize<OrderMsg>(data);
|
||||||
if (msg is null || string.IsNullOrEmpty(msg.SerialNumber) || msg.SerialNumber != SerialNumber) return;
|
if (msg is null || string.IsNullOrEmpty(msg.SerialNumber) || msg.SerialNumber != RobotConfiguration.SerialNumber) return;
|
||||||
|
OrderUpdated?.Invoke(msg);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -32,7 +37,8 @@ public class RobotConnection(RobotConfiguration RobotConfiguration, Logger<Robot
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var msg = JsonSerializer.Deserialize<InstantActionsMsg>(data);
|
var msg = JsonSerializer.Deserialize<InstantActionsMsg>(data);
|
||||||
if (msg is null || string.IsNullOrEmpty(msg.SerialNumber) || msg.SerialNumber != SerialNumber) return;
|
if (msg is null || string.IsNullOrEmpty(msg.SerialNumber) || msg.SerialNumber != RobotConfiguration.SerialNumber) return;
|
||||||
|
ActionUpdated?.Invoke(msg);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using RobotApp.Interfaces;
|
using RobotApp.Common.Shares.Enums;
|
||||||
|
using RobotApp.Interfaces;
|
||||||
using RobotApp.Services.Exceptions;
|
using RobotApp.Services.Exceptions;
|
||||||
using RobotApp.Services.State;
|
using RobotApp.Services.State;
|
||||||
using RobotApp.VDA5050.InstantAction;
|
using RobotApp.VDA5050.InstantAction;
|
||||||
|
|
@ -12,9 +13,7 @@ public partial class RobotController(IOrder OrderManager,
|
||||||
IBattery BatteryManager,
|
IBattery BatteryManager,
|
||||||
ILocalization Localization,
|
ILocalization Localization,
|
||||||
IPeripheral PeripheralManager,
|
IPeripheral PeripheralManager,
|
||||||
ISafety SafetyManager,
|
|
||||||
IError ErrorManager,
|
IError ErrorManager,
|
||||||
IInfomation InfomationManager,
|
|
||||||
Logger<RobotController> Logger,
|
Logger<RobotController> Logger,
|
||||||
RobotConnection ConnectionManager,
|
RobotConnection ConnectionManager,
|
||||||
RobotStateMachine StateManager) : BackgroundService
|
RobotStateMachine StateManager) : BackgroundService
|
||||||
|
|
@ -22,15 +21,9 @@ public partial class RobotController(IOrder OrderManager,
|
||||||
private readonly Mutex NewOrderMutex = new();
|
private readonly Mutex NewOrderMutex = new();
|
||||||
private readonly Mutex NewInstanceMutex = new();
|
private readonly Mutex NewInstanceMutex = new();
|
||||||
|
|
||||||
private WatchTimer<RobotController>? UpdateStateTimer;
|
|
||||||
private const int UpdateStateInterval = 1000;
|
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
await InitializationingHandler(stoppingToken);
|
await InitializationingHandler(stoppingToken);
|
||||||
|
|
||||||
UpdateStateTimer = new(UpdateStateInterval, UpdateStateHandler, Logger);
|
|
||||||
UpdateStateTimer.Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task StopAsync(CancellationToken cancellationToken)
|
public override async Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
|
@ -39,18 +32,13 @@ public partial class RobotController(IOrder OrderManager,
|
||||||
await base.StopAsync(cancellationToken);
|
await base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateStateHandler()
|
|
||||||
{
|
|
||||||
// xử lý cập nhật trạng thái robot và gửi thông tin qua kết nối
|
|
||||||
}
|
|
||||||
|
|
||||||
public void NewOrderUpdated(OrderMsg order)
|
public void NewOrderUpdated(OrderMsg order)
|
||||||
{
|
{
|
||||||
if (NewOrderMutex.WaitOne(2000))
|
if (NewOrderMutex.WaitOne(2000))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (PeripheralManager.PeripheralMode != PeripheralMode.AUTO) throw new OrderException(RobotErrors.Error1006(PeripheralManager.PeripheralMode));
|
if (StateManager.RootStateName != RootStateType.Auto.ToString()) throw new OrderException(RobotErrors.Error1013(StateManager.RootStateName));
|
||||||
if (!string.IsNullOrEmpty(OrderManager.OrderId))
|
if (!string.IsNullOrEmpty(OrderManager.OrderId))
|
||||||
{
|
{
|
||||||
if (order.OrderId != OrderManager.OrderId) throw new OrderException(RobotErrors.Error1001(OrderManager.OrderId, order.OrderId));
|
if (order.OrderId != OrderManager.OrderId) throw new OrderException(RobotErrors.Error1001(OrderManager.OrderId, order.OrderId));
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ public partial class RobotController
|
||||||
}
|
}
|
||||||
Logger.Info("Robot đã khởi tạo xong. Đang kết nối tới Fleet Manager.");
|
Logger.Info("Robot đã khởi tạo xong. Đang kết nối tới Fleet Manager.");
|
||||||
|
|
||||||
|
ConnectionManager.OrderUpdated += NewOrderUpdated;
|
||||||
|
ConnectionManager.ActionUpdated += NewInstanceActionUpdated;
|
||||||
await ConnectionManager.StartConnection(cancellationToken);
|
await ConnectionManager.StartConnection(cancellationToken);
|
||||||
Logger.Info("Robot đã kết nối tới Fleet Manager.");
|
Logger.Info("Robot đã kết nối tới Fleet Manager.");
|
||||||
StateManager.TransitionTo(SystemStateType.Standby);
|
StateManager.TransitionTo(SystemStateType.Standby);
|
||||||
|
|
@ -54,7 +56,6 @@ public partial class RobotController
|
||||||
|
|
||||||
private void StopHandler()
|
private void StopHandler()
|
||||||
{
|
{
|
||||||
UpdateStateTimer?.Stop();
|
|
||||||
PeripheralManager.OnPeripheralModeChanged -= SwichModeChanged;
|
PeripheralManager.OnPeripheralModeChanged -= SwichModeChanged;
|
||||||
PeripheralManager.OnButtonPressed -= OnButtonPressed;
|
PeripheralManager.OnButtonPressed -= OnButtonPressed;
|
||||||
PeripheralManager.OnStop -= OnStop;
|
PeripheralManager.OnStop -= OnStop;
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,17 @@ namespace RobotApp.Services.Robot;
|
||||||
public class RobotErrors : IError
|
public class RobotErrors : IError
|
||||||
{
|
{
|
||||||
private readonly List<Error> Errors = [];
|
private readonly List<Error> Errors = [];
|
||||||
|
|
||||||
public bool HasFatalError => Errors.Any(e => e.ErrorLevel == ErrorLevel.FATAL.ToString());
|
public bool HasFatalError => Errors.Any(e => e.ErrorLevel == ErrorLevel.FATAL.ToString());
|
||||||
|
|
||||||
|
public event Action? OnNewFatalError;
|
||||||
|
|
||||||
public void AddError(Error error, TimeSpan? clearAfter = null)
|
public void AddError(Error error, TimeSpan? clearAfter = null)
|
||||||
{
|
{
|
||||||
|
if (Errors.Any(e => e.ErrorType == error.ErrorType && e.ErrorHint == error.ErrorHint)) return;
|
||||||
lock (Errors)
|
lock (Errors)
|
||||||
{
|
{
|
||||||
Errors.Add(error);
|
Errors.Add(error);
|
||||||
|
if(error.ErrorLevel == ErrorLevel.FATAL.ToString()) OnNewFatalError?.Invoke();
|
||||||
}
|
}
|
||||||
if (clearAfter is not null && clearAfter.HasValue)
|
if (clearAfter is not null && clearAfter.HasValue)
|
||||||
{
|
{
|
||||||
|
|
@ -89,8 +92,8 @@ public class RobotErrors : IError
|
||||||
=> CreateError(ErrorType.INITIALIZE_ORDER, "1011", ErrorLevel.WARNING, $"Order Edges không đúng thứ tự. EdgeId: {edgeId}, SequenceId: {sequenceId}, Vị trí đúng: {correctIndex}");
|
=> CreateError(ErrorType.INITIALIZE_ORDER, "1011", ErrorLevel.WARNING, $"Order Edges không đúng thứ tự. EdgeId: {edgeId}, SequenceId: {sequenceId}, Vị trí đúng: {correctIndex}");
|
||||||
public static Error Error1012(NavigationState state)
|
public static Error Error1012(NavigationState state)
|
||||||
=> CreateError(ErrorType.INITIALIZE_ORDER, "1012", ErrorLevel.WARNING, $"Không thể khởi tạo order mới khi hệ thống điều hướng không ở trạng thái sẵn sàng. Trạng thái hiện tại: {state}");
|
=> CreateError(ErrorType.INITIALIZE_ORDER, "1012", ErrorLevel.WARNING, $"Không thể khởi tạo order mới khi hệ thống điều hướng không ở trạng thái sẵn sàng. Trạng thái hiện tại: {state}");
|
||||||
public static Error Error1013()
|
public static Error Error1013(string rootState)
|
||||||
=> new();
|
=> CreateError(ErrorType.INITIALIZE_ORDER, "1013", ErrorLevel.WARNING, $"Robot chưa sẵn sàng để nhận Order. Trạng thái hiện tại {rootState}");
|
||||||
public static Error Error1014(string edgeId, string nodeId)
|
public static Error Error1014(string edgeId, string nodeId)
|
||||||
=> CreateError(ErrorType.INITIALIZE_ORDER, "1014", ErrorLevel.WARNING, $"Edge {edgeId} chứa StartNodeId {nodeId} không tồn tại trong Nodes");
|
=> CreateError(ErrorType.INITIALIZE_ORDER, "1014", ErrorLevel.WARNING, $"Edge {edgeId} chứa StartNodeId {nodeId} không tồn tại trong Nodes");
|
||||||
public static Error Error1015(string edgeId, string nodeId)
|
public static Error Error1015(string edgeId, string nodeId)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,33 @@
|
||||||
using RobotApp.Interfaces;
|
using RobotApp.Interfaces;
|
||||||
|
using RobotApp.VDA5050.State;
|
||||||
|
|
||||||
|
namespace RobotApp.Services.Robot;
|
||||||
|
|
||||||
namespace RobotApp.Services.Robot
|
|
||||||
{
|
|
||||||
public class RobotInfomations : IInfomation
|
public class RobotInfomations : IInfomation
|
||||||
{
|
{
|
||||||
|
private readonly List<Information> Infors = [];
|
||||||
|
public void AddInfo(Information infor)
|
||||||
|
{
|
||||||
|
if (Infors.Any(e => e.InfoType == infor.InfoType)) return;
|
||||||
|
lock (Infors)
|
||||||
|
{
|
||||||
|
Infors.Add(infor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeleteInfoType(string infoType)
|
||||||
|
{
|
||||||
|
lock (Infors)
|
||||||
|
{
|
||||||
|
Infors.RemoveAll(e => e.InfoType == infoType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearAllInfos()
|
||||||
|
{
|
||||||
|
lock (Infors)
|
||||||
|
{
|
||||||
|
Infors.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,31 @@
|
||||||
namespace RobotApp.Services.Robot;
|
using RobotApp.Interfaces;
|
||||||
|
using RobotApp.VDA5050.State;
|
||||||
|
|
||||||
public class RobotLoads
|
namespace RobotApp.Services.Robot;
|
||||||
|
|
||||||
|
public class RobotLoads(IPeripheral PeriperalManager) : ILoad
|
||||||
{
|
{
|
||||||
|
public Load? Load => PeriperalManager.HasLoad ? GetLoad() : null;
|
||||||
|
private static Load GetLoad()
|
||||||
|
{
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
LoadId = Guid.NewGuid().ToString(),
|
||||||
|
LoadDimensions = new VDA5050.Factsheet.LoadDimensions
|
||||||
|
{
|
||||||
|
Length = 0.5,
|
||||||
|
Width = 0.5,
|
||||||
|
Height = 0.5
|
||||||
|
},
|
||||||
|
LoadPosition = "on_top",
|
||||||
|
LoadType = "box",
|
||||||
|
BoundingBoxReference = new VDA5050.Factsheet.BoundingBoxReference
|
||||||
|
{
|
||||||
|
X = 0,
|
||||||
|
Y = 0,
|
||||||
|
Z = 0,
|
||||||
|
},
|
||||||
|
Weight = 999
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,74 @@
|
||||||
namespace RobotApp.Services.Robot;
|
using RobotApp.Common.Shares;
|
||||||
|
using RobotApp.Interfaces;
|
||||||
|
using RobotApp.VDA5050;
|
||||||
|
using RobotApp.VDA5050.State;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
public class RobotStates
|
namespace RobotApp.Services.Robot;
|
||||||
|
|
||||||
|
public class RobotStates(RobotConfiguration RobotConfiguration, RobotConnection ConnectionManager,
|
||||||
|
Logger<RobotStates> Logger,
|
||||||
|
IOrder OrderManager,
|
||||||
|
IPeripheral PeripheralManager) : BackgroundService
|
||||||
{
|
{
|
||||||
|
private uint HeaderId = 0;
|
||||||
|
private readonly string SerialNumber = RobotConfiguration.SerialNumber;
|
||||||
|
|
||||||
|
private WatchTimerAsync<RobotStates>? UpdateStateTimer;
|
||||||
|
private const int UpdateStateInterval = 1000;
|
||||||
|
|
||||||
|
public async Task PubState()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ConnectionManager.Publish(VDA5050Topic.STATE.ToTopicString(), JsonSerializer.Serialize(GetStateMsg(), JsonOptionExtends.Write));
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
private StateMsg GetStateMsg()
|
||||||
|
{
|
||||||
|
return new StateMsg
|
||||||
|
{
|
||||||
|
HeaderId = HeaderId++,
|
||||||
|
SerialNumber = SerialNumber,
|
||||||
|
Maps = [],
|
||||||
|
OrderId = OrderManager.OrderId,
|
||||||
|
OrderUpdateId = OrderManager.OrderUpdateId,
|
||||||
|
ZoneSetId = "",
|
||||||
|
LastNodeId = OrderManager.LastNodeId,
|
||||||
|
LastNodeSequenceId = OrderManager.LastNodeSequenceId,
|
||||||
|
Driving = false,
|
||||||
|
Paused = false,
|
||||||
|
NewBaseRequest = false,
|
||||||
|
DistanceSinceLastNode = 0,
|
||||||
|
OperatingMode = PeripheralManager.PeripheralMode.ToString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateStateHandler()
|
||||||
|
{
|
||||||
|
await PubState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
if (ConnectionManager.IsConnected) break;
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
if(!stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
UpdateStateTimer = new(UpdateStateInterval, UpdateStateHandler, Logger);
|
||||||
|
UpdateStateTimer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
UpdateStateTimer?.Dispose();
|
||||||
|
return base.StopAsync(cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ namespace RobotApp.Services.Robot;
|
||||||
|
|
||||||
public class RobotVisualization(ILocalization Localization, INavigation Navigation, RobotConfiguration RobotConfiguration, RobotConnection RobotConnection, Logger<RobotVisualization> Logger) : BackgroundService
|
public class RobotVisualization(ILocalization Localization, INavigation Navigation, RobotConfiguration RobotConfiguration, RobotConnection RobotConnection, Logger<RobotVisualization> Logger) : BackgroundService
|
||||||
{
|
{
|
||||||
public string SerialNumber { get; set; } = RobotConfiguration.SerialNumber;
|
public string SerialNumber = RobotConfiguration.SerialNumber;
|
||||||
private uint HeaderId;
|
private uint HeaderId;
|
||||||
|
|
||||||
private WatchTimerAsync<RobotVisualization>? UpdateTimer;
|
private WatchTimerAsync<RobotVisualization>? UpdateTimer;
|
||||||
private const int UpdateInterval = 50;
|
private const int UpdateInterval = 100;
|
||||||
private VisualizationMsg GetVisualizationMsg()
|
private VisualizationMsg GetVisualizationMsg()
|
||||||
{
|
{
|
||||||
return new VisualizationMsg()
|
return new VisualizationMsg()
|
||||||
|
|
@ -46,6 +46,7 @@ public class RobotVisualization(ILocalization Localization, INavigation Navigati
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
|
await Task.Yield();
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
if (RobotConnection.IsConnected) break;
|
if (RobotConnection.IsConnected) break;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using RobotApp.Common.Shares.Enums;
|
using RobotApp.Common.Shares.Enums;
|
||||||
using RobotApp.Interfaces;
|
|
||||||
|
|
||||||
namespace RobotApp.Services.State;
|
namespace RobotApp.Services.State;
|
||||||
|
|
||||||
|
|
@ -11,6 +10,7 @@ public record RobotStateMachine(Logger<RobotStateMachine> Logger) : IDisposable
|
||||||
public event Action<IRobotState?, IRobotState>? OnStateChanged;
|
public event Action<IRobotState?, IRobotState>? OnStateChanged;
|
||||||
public bool IsInitialized = false;
|
public bool IsInitialized = false;
|
||||||
public string CurrentStateName => CurrentState.Name.ToString();
|
public string CurrentStateName => CurrentState.Name.ToString();
|
||||||
|
public string RootStateName => GetRootStateName();
|
||||||
|
|
||||||
private readonly Lock StateLock = new();
|
private readonly Lock StateLock = new();
|
||||||
|
|
||||||
|
|
@ -330,22 +330,22 @@ public record RobotStateMachine(Logger<RobotStateMachine> Logger) : IDisposable
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public string GetRootStateName()
|
||||||
{
|
{
|
||||||
if (!IsInitialized)
|
if (CurrentState == null) return "Unknown";
|
||||||
|
|
||||||
|
var current = CurrentState;
|
||||||
|
while (current.SuperState != null)
|
||||||
{
|
{
|
||||||
Logger.Warning("State Machine chưa được khởi tạo");
|
current = current.SuperState;
|
||||||
return;
|
|
||||||
}
|
|
||||||
lock (StateLock)
|
|
||||||
{
|
|
||||||
CurrentState?.Update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return current.Name.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCurrentStatePath()
|
public string GetCurrentStatePath()
|
||||||
{
|
{
|
||||||
if (CurrentState == null) return "No State";
|
if (CurrentState == null) return "Unknown";
|
||||||
return GetStatePath(CurrentState);
|
return GetStatePath(CurrentState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user