Initial commit
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
@using RobotNet.VDA5050.Type
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Action States</MudText>
|
||||
@if (State?.ActionStates != null && State.ActionStates.Length > 0)
|
||||
{
|
||||
<MudTable Items="@State.ActionStates" T="ActionState" Hover="true" Dense="true" Height="400px" FixedHeader="true" Elevation="0">
|
||||
<HeaderContent>
|
||||
<MudTh>Action ID</MudTh>
|
||||
<MudTh>Action Type</MudTh>
|
||||
<MudTh>Status</MudTh>
|
||||
<MudTh>Description</MudTh>
|
||||
<MudTh>Result</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Action ID">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@context.ActionId
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Action Type">@(context.ActionType ?? "N/A")</MudTd>
|
||||
<MudTd DataLabel="Status">
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Color="@GetActionStatusColor(context.ActionStatus)">
|
||||
@context.ActionStatus
|
||||
</MudChip>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Description">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.ActionDescription ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Result">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.ResultDescription ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No action states available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
private Color GetActionStatusColor(ActionStatus status)
|
||||
{
|
||||
return status switch
|
||||
{
|
||||
ActionStatus.WAITING => Color.Default,
|
||||
ActionStatus.RUNNING => Color.Info,
|
||||
ActionStatus.FINISHED => Color.Success,
|
||||
ActionStatus.FAILED => Color.Error,
|
||||
_ => Color.Default
|
||||
};
|
||||
}
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
@if (ShowNameCard)
|
||||
{
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Battery State</MudText>
|
||||
}
|
||||
@if (BatteryState != null)
|
||||
{
|
||||
<MudSimpleTable Elevation="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Charge:</strong></td>
|
||||
<td>
|
||||
<MudProgressLinear Value="@BatteryState.BatteryCharge"
|
||||
Color="@GetBatteryColor(BatteryState.BatteryCharge)" />
|
||||
@BatteryState.BatteryCharge.ToString("F1")%
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Voltage:</strong></td>
|
||||
<td>@BatteryState.BatteryVoltage?.ToString("F2") V</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Health:</strong></td>
|
||||
<td>@BatteryState.BatteryHealth.ToString("F1")%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Charging:</strong></td>
|
||||
<td>
|
||||
@if (BatteryState.Charging)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Info">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Default">No</MudChip>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
@if (BatteryState.Reach > 0)
|
||||
{
|
||||
<tr>
|
||||
<td><strong>Reach:</strong></td>
|
||||
<td>@BatteryState.Reach?.ToString("F0") m</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No battery data available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public bool ShowNameCard { get; set; } = true;
|
||||
|
||||
public BatteryState? BatteryState { get; set; }
|
||||
|
||||
private Color GetBatteryColor(double charge)
|
||||
{
|
||||
if (charge > 50) return Color.Success;
|
||||
if (charge > 20) return Color.Warning;
|
||||
return Color.Error;
|
||||
}
|
||||
|
||||
public void Update(BatteryState? batteryState)
|
||||
{
|
||||
BatteryState = batteryState;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Edge States</MudText>
|
||||
@if (State?.EdgeStates != null && State.EdgeStates.Length > 0)
|
||||
{
|
||||
<MudTable Items="@State.EdgeStates" T="EdgeState" Hover="true" Dense="true" Height="400px" FixedHeader="true" Elevation="0">
|
||||
<HeaderContent>
|
||||
<MudTh>Edge ID</MudTh>
|
||||
<MudTh>Sequence ID</MudTh>
|
||||
<MudTh>Released</MudTh>
|
||||
<MudTh>Description</MudTh>
|
||||
<MudTh>Trajectory</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Edge ID">@context.EdgeId</MudTd>
|
||||
<MudTd DataLabel="Sequence ID">@context.SequenceId</MudTd>
|
||||
<MudTd DataLabel="Released">
|
||||
@if (context.Released)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Success">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Warning">No</MudChip>
|
||||
}
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Description">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.EdgeDescription ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Trajectory">
|
||||
@if (context.Trajectory != null)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Info">Available</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2">N/A</MudText>
|
||||
}
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No edge states available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
@using RobotNet.VDA5050.Type
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Errors</MudText>
|
||||
@if (Errors != null && Errors.Length > 0)
|
||||
{
|
||||
<MudTable Items="@Errors" T="Error" Hover="true" Dense="true" Height="400px" FixedHeader="true" Elevation="0">
|
||||
<HeaderContent>
|
||||
<MudTh>Error Type</MudTh>
|
||||
<MudTh>Level</MudTh>
|
||||
<MudTh>Description</MudTh>
|
||||
<MudTh>Hint</MudTh>
|
||||
<MudTh>References</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Error Type">@context.ErrorType</MudTd>
|
||||
<MudTd DataLabel="Level">
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Color="@GetErrorLevelColor(context.ErrorLevel)">
|
||||
@context.ErrorLevel
|
||||
</MudChip>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Description">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 250px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.ErrorDescription ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Hint">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.ErrorHint ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="References">
|
||||
@if (context.ErrorReferences != null && context.ErrorReferences.Length > 0)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Info">
|
||||
@context.ErrorReferences.Length reference(s)
|
||||
</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2">N/A</MudText>
|
||||
}
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No errors</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
private Error[]? Errors { get; set; }
|
||||
|
||||
private Color GetErrorLevelColor(ErrorLevel level)
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
ErrorLevel.NONE => Color.Success,
|
||||
ErrorLevel.WARNING => Color.Warning,
|
||||
ErrorLevel.FATAL => Color.Error,
|
||||
_ => Color.Default
|
||||
};
|
||||
}
|
||||
|
||||
public void Update(Error[]? errors)
|
||||
{
|
||||
Errors = errors;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Header Information</MudText>
|
||||
@if (State != null)
|
||||
{
|
||||
<MudSimpleTable Elevation="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Header ID:</strong></td>
|
||||
<td>@State.HeaderId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Timestamp:</strong></td>
|
||||
<td>@State.Timestamp.ToString("g")</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Version:</strong></td>
|
||||
<td>@State.Version</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Manufacturer:</strong></td>
|
||||
<td>@State.Manufacturer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Serial Number:</strong></td>
|
||||
<td>@State.SerialNumber</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No state data available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
@using RobotNet.VDA5050.Type
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Information</MudText>
|
||||
@if (Info != null && Info.Length > 0)
|
||||
{
|
||||
<MudTable Items="@Info" T="Information" Hover="true" Dense="true" Height="400px" FixedHeader="true" Elevation="0">
|
||||
<HeaderContent>
|
||||
<MudTh>Info Type</MudTh>
|
||||
<MudTh>Level</MudTh>
|
||||
<MudTh>Description</MudTh>
|
||||
<MudTh>References</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Info Type">@context.InfoType</MudTd>
|
||||
<MudTd DataLabel="Level">
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Color="@GetInfoLevelColor(context.InfoLevel)">
|
||||
@context.InfoLevel
|
||||
</MudChip>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Description">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 300px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.InfoDescription ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="References">
|
||||
@if (context.InfoReferences != null && context.InfoReferences.Length > 0)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Info">
|
||||
@context.InfoReferences.Length reference(s)
|
||||
</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2">N/A</MudText>
|
||||
}
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No information available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
private Information[]? Info { get; set; }
|
||||
|
||||
private Color GetInfoLevelColor(InfoLevel level)
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
InfoLevel.INFO => Color.Info,
|
||||
InfoLevel.DEBUG => Color.Default,
|
||||
_ => Color.Default
|
||||
};
|
||||
}
|
||||
|
||||
public void Update(Information[]? info)
|
||||
{
|
||||
Info = info;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Loads</MudText>
|
||||
@if (State?.Loads != null && State.Loads.Length > 0)
|
||||
{
|
||||
<MudTable Items="@State.Loads" T="Load" Hover="true" Dense="true" Height="400px" FixedHeader="true" Elevation="0">
|
||||
<HeaderContent>
|
||||
<MudTh>Load ID</MudTh>
|
||||
<MudTh>Load Type</MudTh>
|
||||
<MudTh>Position</MudTh>
|
||||
<MudTh>Weight</MudTh>
|
||||
<MudTh>Dimensions</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Load ID">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.LoadId ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Load Type">@(context.LoadType ?? "N/A")</MudTd>
|
||||
<MudTd DataLabel="Position">@(context.LoadPosition ?? "N/A")</MudTd>
|
||||
<MudTd DataLabel="Weight">@(context.Weight > 0 ? context.Weight?.ToString("F2") + " kg" : "N/A")</MudTd>
|
||||
<MudTd DataLabel="Dimensions">
|
||||
@if (context.LoadDimensions != null)
|
||||
{
|
||||
<MudText Typo="Typo.body2">
|
||||
@($"{context.LoadDimensions.Length:F2} × {context.LoadDimensions.Width:F2}")
|
||||
@if (context.LoadDimensions.Height > 0)
|
||||
{
|
||||
<text> × @context.LoadDimensions.Height.ToString("F2")</text>
|
||||
}
|
||||
<text> m</text>
|
||||
</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2">N/A</MudText>
|
||||
}
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No loads available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
@using RobotNet.VDA5050
|
||||
@using RobotNet.VDA5050.Type
|
||||
@using System.Net.Http.Json
|
||||
@using RobotNet10.FleetManager.Shared.Models
|
||||
@using RobotNet10.Shared
|
||||
@inject HttpClient HttpClient
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="0">
|
||||
<MudText Typo="Typo.h6" Class="mb-4">Manual Actions</MudText>
|
||||
|
||||
<MudStack Spacing="3">
|
||||
<!-- Action Type Selector -->
|
||||
<MudSelect @bind-Value="selectedActionType"
|
||||
Label="Action Type"
|
||||
Variant="Variant.Outlined"
|
||||
T="ActionType">
|
||||
@foreach (ActionType actionType in Enum.GetValues<ActionType>())
|
||||
{
|
||||
<MudSelectItem Value="@actionType">@actionType.ToString()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<!-- Blocking Type Selector -->
|
||||
<MudSelect @bind-Value="selectedBlockingType"
|
||||
Label="Blocking Type"
|
||||
Variant="Variant.Outlined"
|
||||
T="BlockingType">
|
||||
@foreach (BlockingType blockingType in Enum.GetValues<BlockingType>())
|
||||
{
|
||||
<MudSelectItem Value="@blockingType">@blockingType.ToString()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<!-- Action Parameters -->
|
||||
<MudText Typo="Typo.subtitle2">Action Parameters</MudText>
|
||||
@foreach (var param in actionParameters)
|
||||
{
|
||||
<MudGrid>
|
||||
<MudItem xs="5">
|
||||
<MudTextField @bind-Value="param.Key"
|
||||
Label="Key"
|
||||
Variant="Variant.Outlined"
|
||||
Margin="Margin.Dense" />
|
||||
</MudItem>
|
||||
<MudItem xs="5">
|
||||
<MudTextField @bind-Value="param.Value"
|
||||
Label="Value"
|
||||
Variant="Variant.Outlined"
|
||||
Margin="Margin.Dense" />
|
||||
</MudItem>
|
||||
<MudItem xs="2">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Color="Color.Error"
|
||||
Size="Size.Small"
|
||||
OnClick="@(() => RemoveParameter(param))" />
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
}
|
||||
|
||||
<MudButton StartIcon="@Icons.Material.Filled.Add"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Primary"
|
||||
OnClick="AddParameter">
|
||||
Add Parameter
|
||||
</MudButton>
|
||||
|
||||
<!-- Send Action Button -->
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.Send"
|
||||
OnClick="SendAction"
|
||||
Disabled="@isSending"
|
||||
FullWidth="true">
|
||||
@if (isSending)
|
||||
{
|
||||
<MudProgressCircular Class="mr-2" Size="Size.Small" Indeterminate="true" />
|
||||
<span>Sending...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Send Action</span>
|
||||
}
|
||||
</MudButton>
|
||||
|
||||
<!-- Action History -->
|
||||
<MudDivider />
|
||||
<MudText Typo="Typo.subtitle2">Recent Actions</MudText>
|
||||
@if (actionHistory.Count > 0)
|
||||
{
|
||||
<MudStack Spacing="1" Style="height: 200px; overflow-y: auto">
|
||||
@foreach (var action in actionHistory.Take(10))
|
||||
{
|
||||
<MudPaper Class="pa-2" Elevation="0">
|
||||
<MudText Typo="Typo.body2">
|
||||
<strong>@action.ActionType</strong> - @action.Timestamp.ToString("g")
|
||||
</MudText>
|
||||
</MudPaper>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No actions sent yet</MudText>
|
||||
}
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string RobotId { get; set; } = string.Empty;
|
||||
|
||||
private ActionType selectedActionType = ActionType.STATE_REQUEST;
|
||||
private BlockingType selectedBlockingType = BlockingType.HARD;
|
||||
private List<RobotNet.VDA5050.InstantAction.ActionParameter> actionParameters = new();
|
||||
private List<SentAction> actionHistory = new();
|
||||
private bool isSending = false;
|
||||
|
||||
|
||||
private class SentAction
|
||||
{
|
||||
public ActionType ActionType { get; set; }
|
||||
public DateTime Timestamp { get; set; }
|
||||
}
|
||||
|
||||
private void AddParameter()
|
||||
{
|
||||
actionParameters.Add(new RobotNet.VDA5050.InstantAction.ActionParameter());
|
||||
}
|
||||
|
||||
private void RemoveParameter(RobotNet.VDA5050.InstantAction.ActionParameter param)
|
||||
{
|
||||
actionParameters.Remove(param);
|
||||
}
|
||||
|
||||
private async Task SendAction()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(RobotId))
|
||||
{
|
||||
Snackbar.Add("Robot ID is required", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
isSending = true;
|
||||
StateHasChanged();
|
||||
|
||||
try
|
||||
{
|
||||
// Build action request
|
||||
var actionRequest = new RobotInstantActionModel
|
||||
{
|
||||
RobotId = RobotId,
|
||||
Action = new RobotNet.VDA5050.InstantAction.Action
|
||||
{
|
||||
ActionId = Guid.NewGuid().ToString(),
|
||||
BlockingType = selectedBlockingType,
|
||||
ActionType = selectedActionType.ToJsonString(),
|
||||
ActionParameters = [.. actionParameters.Where(p => !string.IsNullOrWhiteSpace(p.Key))],
|
||||
}
|
||||
};
|
||||
|
||||
// Call API endpoint (TODO: Create this endpoint in Phase 10)
|
||||
var response = await HttpClient.PostAsJsonAsync($"/api/robotManager/InstantActions", actionRequest);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var result = await response.Content.ReadFromJsonAsync<MessageResult>();
|
||||
if(result is null)
|
||||
{
|
||||
Snackbar.Add($"Sending action is failed", Severity.Warning);
|
||||
}
|
||||
else if (!result.IsSuccess)
|
||||
{
|
||||
Snackbar.Add($"{result.Message}", Severity.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add($"Action '{selectedActionType}' sent successfully", Severity.Success);
|
||||
|
||||
// Add to history
|
||||
actionHistory.Insert(0, new SentAction
|
||||
{
|
||||
ActionType = selectedActionType,
|
||||
Timestamp = DateTime.UtcNow
|
||||
});
|
||||
|
||||
// Clear parameters
|
||||
actionParameters.Clear();
|
||||
}
|
||||
}
|
||||
else if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
Snackbar.Add($"Robot with ID '{RobotId}' not found", Severity.Error);
|
||||
}
|
||||
else if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
|
||||
{
|
||||
var error = await response.Content.ReadAsStringAsync();
|
||||
Snackbar.Add($"Invalid action request: {error}", Severity.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
var error = await response.Content.ReadAsStringAsync();
|
||||
Snackbar.Add($"Error sending action: {error}", Severity.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"Error sending action: {ex.Message}", Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isSending = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
@using RobotNet10.FleetManager.Shared.DTOs.Robot
|
||||
@using RobotNet10.FleetManager.Client.Services
|
||||
@using RobotNet10.MapEditor.Services.API
|
||||
@using RobotNet10.MapEditor.Shared.DTOs.LayoutData
|
||||
@using RobotNet10.MapEditor.Shared.DTOs.Node
|
||||
@using RobotNet10.FleetManager.Shared.Models
|
||||
@using RobotNet10.Shared
|
||||
@using System.Net.Http.Json
|
||||
@inject HttpClient HttpClient
|
||||
@inject ISnackbar Snackbar
|
||||
@inject RobotApiService RobotApiService
|
||||
@inject MapManagerApiService MapApiService
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="0">
|
||||
<MudText Typo="Typo.h6" Class="mb-4">Manual Order</MudText>
|
||||
|
||||
<MudStack Spacing="3">
|
||||
<!-- Node Selector -->
|
||||
<MudSelect @bind-Value="selectedNodeName"
|
||||
Label="Select Node"
|
||||
Variant="Variant.Outlined"
|
||||
T="string"
|
||||
Disabled="@isLoadingNodes"
|
||||
ErrorText="@GetValidationError("NodeName")">
|
||||
@if (isLoadingNodes)
|
||||
{
|
||||
<MudSelectItem Value="@(string.Empty)" Disabled="true">Loading nodes...</MudSelectItem>
|
||||
}
|
||||
else if (nodes != null && nodes.Any())
|
||||
{
|
||||
<MudSelectItem Value="@(string.Empty)">-- Select Node --</MudSelectItem>
|
||||
@foreach (var node in nodes.Where(n => !string.IsNullOrEmpty(n.NodeName)).OrderBy(n => n.NodeName))
|
||||
{
|
||||
var displayName = !string.IsNullOrWhiteSpace(node.NodeName)
|
||||
? $"{node.NodeName} ({node.NodeId})"
|
||||
: node.NodeId;
|
||||
<MudSelectItem Value="@node.NodeName">@displayName</MudSelectItem>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudSelectItem Value="@(string.Empty)" Disabled="true">No nodes available</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(selectedNodeName))
|
||||
{
|
||||
var selectedNode = nodes?.FirstOrDefault(n =>
|
||||
(!string.IsNullOrWhiteSpace(n.NodeName) && n.NodeName == selectedNodeName) ||
|
||||
(string.IsNullOrWhiteSpace(n.NodeName) && n.NodeId == selectedNodeName));
|
||||
@if (selectedNode != null)
|
||||
{
|
||||
<MudPaper Class="pa-2" Elevation="0" Style="background-color: var(--mud-palette-background-grey);">
|
||||
<MudText Typo="Typo.body2">
|
||||
<strong>Node ID:</strong> @selectedNode.NodeId<br />
|
||||
@if (!string.IsNullOrWhiteSpace(selectedNode.NodeDescription))
|
||||
{
|
||||
<strong>Description:</strong> @selectedNode.NodeDescription<br />
|
||||
}
|
||||
<strong>Position:</strong> X: @selectedNode.X.ToString("F2")m, Y: @selectedNode.Y.ToString("F2")m
|
||||
</MudText>
|
||||
</MudPaper>
|
||||
}
|
||||
}
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<MudStack Row="true" Spacing="2">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.Send"
|
||||
OnClick="SendOrder"
|
||||
Disabled="@(isSending || string.IsNullOrWhiteSpace(selectedNodeName))"
|
||||
FullWidth="true">
|
||||
@if (isSending)
|
||||
{
|
||||
<MudProgressCircular Class="mr-2" Size="Size.Small" Indeterminate="true" />
|
||||
<span>Sending...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Send Order</span>
|
||||
}
|
||||
</MudButton>
|
||||
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Error"
|
||||
StartIcon="@Icons.Material.Filled.Cancel"
|
||||
OnClick="CancelOrder"
|
||||
Disabled="@isCanceling"
|
||||
FullWidth="true">
|
||||
@if (isCanceling)
|
||||
{
|
||||
<MudProgressCircular Class="mr-2" Size="Size.Small" Indeterminate="true" />
|
||||
<span>Canceling...</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>Cancel Order</span>
|
||||
}
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
|
||||
<!-- Order History -->
|
||||
<MudDivider />
|
||||
<MudText Typo="Typo.subtitle2">Recent Orders</MudText>
|
||||
@if (orderHistory.Count > 0)
|
||||
{
|
||||
<MudStack Spacing="1" Style="height: 200px; overflow: auto;">
|
||||
@foreach (var order in orderHistory.Take(10))
|
||||
{
|
||||
<MudPaper Class="pa-2" Elevation="0">
|
||||
<MudText Typo="Typo.body2">
|
||||
<strong>@order.NodeName</strong> - @order.Timestamp.ToString("g")
|
||||
@if (!order.IsSuccess)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Error" Class="ml-2">Failed</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Success" Class="ml-2">Success</MudChip>
|
||||
}
|
||||
</MudText>
|
||||
</MudPaper>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No orders sent yet</MudText>
|
||||
}
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string RobotId { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public Guid? MapId { get; set; }
|
||||
|
||||
private string selectedNodeName = string.Empty;
|
||||
private List<NodeDto> nodes = new();
|
||||
private List<SentOrder> orderHistory = new();
|
||||
private bool isSending = false;
|
||||
private bool isCanceling = false;
|
||||
private bool isLoadingNodes = false;
|
||||
private Dictionary<string, string> validationErrors = new();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await LoadNodesAsync();
|
||||
}
|
||||
|
||||
private async Task LoadNodesAsync()
|
||||
{
|
||||
if (!MapId.HasValue || MapId.Value == Guid.Empty)
|
||||
{
|
||||
// Try to get MapId from robot
|
||||
try
|
||||
{
|
||||
var robot = await RobotApiService.GetByRobotIdAsync(RobotId);
|
||||
if (robot?.MapId.HasValue == true)
|
||||
{
|
||||
MapId = robot.MapId;
|
||||
}
|
||||
else
|
||||
{
|
||||
nodes = new List<NodeDto>();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"Error loading robot: {ex.Message}", Severity.Warning);
|
||||
nodes = new List<NodeDto>();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
isLoadingNodes = true;
|
||||
StateHasChanged();
|
||||
try
|
||||
{
|
||||
var layoutData = await MapApiService.GetLayoutDataAsync(MapId.Value);
|
||||
nodes = layoutData.Nodes?.ToList() ?? new List<NodeDto>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"Error loading nodes: {ex.Message}", Severity.Warning);
|
||||
nodes = new List<NodeDto>();
|
||||
}
|
||||
finally
|
||||
{
|
||||
isLoadingNodes = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private string? GetValidationError(string fieldName)
|
||||
{
|
||||
return validationErrors.TryGetValue(fieldName, out var error) ? error : null;
|
||||
}
|
||||
|
||||
private async Task SendOrder()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(RobotId))
|
||||
{
|
||||
Snackbar.Add("Robot ID is required", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(selectedNodeName))
|
||||
{
|
||||
validationErrors["NodeName"] = "Please select a node";
|
||||
StateHasChanged();
|
||||
return;
|
||||
}
|
||||
|
||||
isSending = true;
|
||||
validationErrors.Clear();
|
||||
StateHasChanged();
|
||||
|
||||
try
|
||||
{
|
||||
// Find the selected node to get NodeName (preferred) or NodeId
|
||||
var selectedNode = nodes?.FirstOrDefault(n =>
|
||||
(!string.IsNullOrWhiteSpace(n.NodeName) && n.NodeName == selectedNodeName) ||
|
||||
(string.IsNullOrWhiteSpace(n.NodeName) && n.NodeId == selectedNodeName));
|
||||
|
||||
if (selectedNode == null)
|
||||
{
|
||||
Snackbar.Add("Selected node not found", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Use NodeName if available, otherwise use NodeId
|
||||
var nodeNameToSend = !string.IsNullOrWhiteSpace(selectedNode.NodeName)
|
||||
? selectedNode.NodeName
|
||||
: selectedNode.NodeId;
|
||||
|
||||
// Build order request
|
||||
var orderRequest = new RobotMoveToNodeModel
|
||||
{
|
||||
RobotId = RobotId,
|
||||
NodeName = nodeNameToSend,
|
||||
LastAngle = null, // Optional, can be enhanced later
|
||||
};
|
||||
|
||||
// Call API endpoint
|
||||
var response = await HttpClient.PostAsJsonAsync($"/api/RobotManager/MoveToNode", orderRequest);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var result = await response.Content.ReadFromJsonAsync<MessageResult>();
|
||||
if (result is null)
|
||||
{
|
||||
Snackbar.Add($"Sending order failed", Severity.Warning);
|
||||
orderHistory.Insert(0, new SentOrder
|
||||
{
|
||||
NodeName = selectedNodeName,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
IsSuccess = false
|
||||
});
|
||||
}
|
||||
else if (!result.IsSuccess)
|
||||
{
|
||||
Snackbar.Add($"{result.Message}", Severity.Warning);
|
||||
orderHistory.Insert(0, new SentOrder
|
||||
{
|
||||
NodeName = selectedNodeName,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
IsSuccess = false
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add($"Order to node '{selectedNodeName}' sent successfully", Severity.Success);
|
||||
|
||||
// Add to history
|
||||
orderHistory.Insert(0, new SentOrder
|
||||
{
|
||||
NodeName = selectedNodeName,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
IsSuccess = true
|
||||
});
|
||||
|
||||
// Clear selection
|
||||
selectedNodeName = string.Empty;
|
||||
}
|
||||
}
|
||||
else if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
Snackbar.Add($"Robot with ID '{RobotId}' not found", Severity.Error);
|
||||
orderHistory.Insert(0, new SentOrder
|
||||
{
|
||||
NodeName = selectedNodeName,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
IsSuccess = false
|
||||
});
|
||||
}
|
||||
else if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
|
||||
{
|
||||
var error = await response.Content.ReadAsStringAsync();
|
||||
Snackbar.Add($"Invalid order request: {error}", Severity.Warning);
|
||||
orderHistory.Insert(0, new SentOrder
|
||||
{
|
||||
NodeName = selectedNodeName,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
IsSuccess = false
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
var error = await response.Content.ReadAsStringAsync();
|
||||
Snackbar.Add($"Error sending order: {error}", Severity.Error);
|
||||
orderHistory.Insert(0, new SentOrder
|
||||
{
|
||||
NodeName = selectedNodeName,
|
||||
Timestamp = DateTime.UtcNow,
|
||||
IsSuccess = false
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"Error sending order: {ex.Message}", Severity.Error);
|
||||
orderHistory.Insert(0, new SentOrder
|
||||
{
|
||||
NodeName = selectedNodeName ?? "Unknown",
|
||||
Timestamp = DateTime.UtcNow,
|
||||
IsSuccess = false
|
||||
});
|
||||
}
|
||||
finally
|
||||
{
|
||||
isSending = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CancelOrder()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(RobotId))
|
||||
{
|
||||
Snackbar.Add("Robot ID is required", Severity.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
isCanceling = true;
|
||||
StateHasChanged();
|
||||
|
||||
try
|
||||
{
|
||||
// Call API endpoint
|
||||
var response = await HttpClient.DeleteAsync($"/api/RobotManager/MoveToNode/{RobotId}");
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
var result = await response.Content.ReadFromJsonAsync<MessageResult>();
|
||||
if (result is null)
|
||||
{
|
||||
Snackbar.Add($"Canceling order failed", Severity.Warning);
|
||||
}
|
||||
else if (!result.IsSuccess)
|
||||
{
|
||||
Snackbar.Add($"{result.Message}", Severity.Warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
Snackbar.Add($"Order canceled successfully", Severity.Success);
|
||||
}
|
||||
}
|
||||
else if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
{
|
||||
Snackbar.Add($"Robot with ID '{RobotId}' not found", Severity.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
var error = await response.Content.ReadAsStringAsync();
|
||||
Snackbar.Add($"Error canceling order: {error}", Severity.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Snackbar.Add($"Error canceling order: {ex.Message}", Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
isCanceling = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class for order history
|
||||
private class SentOrder
|
||||
{
|
||||
public string NodeName { get; set; } = string.Empty;
|
||||
public DateTime Timestamp { get; set; }
|
||||
public bool IsSuccess { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Maps</MudText>
|
||||
@if (State?.Maps != null && State.Maps.Length > 0)
|
||||
{
|
||||
<MudTable Items="@State.Maps" T="Map" Hover="true" Dense="true" Elevation="0">
|
||||
<HeaderContent>
|
||||
<MudTh>Map ID</MudTh>
|
||||
<MudTh>Map Description</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Map ID">@context.MapId</MudTd>
|
||||
<MudTd DataLabel="Map Description">@(context.MapDescription ?? "N/A")</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No maps available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Node States</MudText>
|
||||
@if (State?.NodeStates != null && State.NodeStates.Length > 0)
|
||||
{
|
||||
<MudTable Items="@State.NodeStates" T="NodeState" Hover="true" Dense="true" Height="400px" FixedHeader="true" Elevation="0">
|
||||
<HeaderContent>
|
||||
<MudTh>Node ID</MudTh>
|
||||
<MudTh>Sequence ID</MudTh>
|
||||
<MudTh>Released</MudTh>
|
||||
<MudTh>Description</MudTh>
|
||||
<MudTh>Position</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Node ID">@context.NodeId</MudTd>
|
||||
<MudTd DataLabel="Sequence ID">@context.SequenceId</MudTd>
|
||||
<MudTd DataLabel="Released">
|
||||
@if (context.Released)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Success">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Warning">No</MudChip>
|
||||
}
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Description">
|
||||
<MudText Typo="Typo.body2" Style="max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
@(context.NodeDescription ?? "N/A")
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Position">
|
||||
@if (context.NodePosition != null)
|
||||
{
|
||||
<MudText Typo="Typo.body2">
|
||||
@($"({context.NodePosition.X:F2}, {context.NodePosition.Y:F2})")
|
||||
</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2">N/A</MudText>
|
||||
}
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No node states available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
Console.WriteLine($"Update node state: {State?.NodeStates.Length}");
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Order Information</MudText>
|
||||
@if (State != null)
|
||||
{
|
||||
<MudSimpleTable Elevation="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Order ID:</strong></td>
|
||||
<td>@State.OrderId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Order Update ID:</strong></td>
|
||||
<td>@State.OrderUpdateId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Zone Set ID:</strong></td>
|
||||
<td>@(State.ZoneSetId ?? "N/A")</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Last Node ID:</strong></td>
|
||||
<td>@State.LastNodeId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Last Node Sequence ID:</strong></td>
|
||||
<td>@State.LastNodeSequenceId</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Driving:</strong></td>
|
||||
<td>
|
||||
@if (State.Driving)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Success">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Default">No</MudChip>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Paused:</strong></td>
|
||||
<td>
|
||||
@if (State.Paused)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Warning">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Default">No</MudChip>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Operating Mode:</strong></td>
|
||||
<td>@State.OperatingMode</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Distance Since Last Node:</strong></td>
|
||||
<td>@State.DistanceSinceLastNode?.ToString("F3") m</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>New Base Request:</strong></td>
|
||||
<td>
|
||||
@if (State.NewBaseRequest)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Warning">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Default">No</MudChip>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No order data available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Position</MudText>
|
||||
@if (State?.AgvPosition != null)
|
||||
{
|
||||
<MudSimpleTable Elevation="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>X:</strong></td>
|
||||
<td>@State.AgvPosition.X.ToString("F3") m</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Y:</strong></td>
|
||||
<td>@State.AgvPosition.Y.ToString("F3") m</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Theta:</strong></td>
|
||||
<td>@State.AgvPosition.Theta.ToString("F3") rad</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Map ID:</strong></td>
|
||||
<td>@(State.AgvPosition.MapId ?? "N/A")</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Position Initialized:</strong></td>
|
||||
<td>
|
||||
@if (State.AgvPosition.PositionInitialized)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Success">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Warning">No</MudChip>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
@if (State.AgvPosition.LocalizationScore >= 0)
|
||||
{
|
||||
<tr>
|
||||
<td><strong>Localization Score:</strong></td>
|
||||
<td>@State.AgvPosition.LocalizationScore.ToString("F3")</td>
|
||||
</tr>
|
||||
}
|
||||
@if (State.AgvPosition.DeviationRange >= 0)
|
||||
{
|
||||
<tr>
|
||||
<td><strong>Deviation Range:</strong></td>
|
||||
<td>@State.AgvPosition.DeviationRange.ToString("F3") m</td>
|
||||
</tr>
|
||||
}
|
||||
@if (!string.IsNullOrWhiteSpace(State.AgvPosition.MapDescription))
|
||||
{
|
||||
<tr>
|
||||
<td><strong>Map Description:</strong></td>
|
||||
<td>@State.AgvPosition.MapDescription</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No position data available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
@using RobotNet.VDA5050.Type
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Safety State</MudText>
|
||||
@if (State?.SafetyState != null)
|
||||
{
|
||||
<MudSimpleTable Elevation="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>E-Stop:</strong></td>
|
||||
<td>
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Color="@GetEStopColor(State.SafetyState.EStop)">
|
||||
@State.SafetyState.EStop
|
||||
</MudChip>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Field Violation:</strong></td>
|
||||
<td>
|
||||
@if (State.SafetyState.FieldViolation)
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Error">Yes</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudChip T="string" Size="Size.Small" Color="Color.Success">No</MudChip>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No safety state data available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
private Color GetEStopColor(EStop eStop)
|
||||
{
|
||||
return eStop switch
|
||||
{
|
||||
EStop.NONE => Color.Success,
|
||||
EStop.AUTOACK => Color.Warning,
|
||||
EStop.MANUAL => Color.Error,
|
||||
EStop.REMOTE => Color.Warning,
|
||||
_ => Color.Default
|
||||
};
|
||||
}
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
@using RobotNet.VDA5050.State
|
||||
|
||||
<MudPaper Class="pa-4" Elevation="2">
|
||||
<MudText Typo="Typo.h6" Class="mb-3">Velocity</MudText>
|
||||
@if (State?.Velocity != null)
|
||||
{
|
||||
<MudSimpleTable Elevation="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>Vx:</strong></td>
|
||||
<td>@State.Velocity.Vx.ToString("F3") m/s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Vy:</strong></td>
|
||||
<td>@State.Velocity.Vy.ToString("F3") m/s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Omega:</strong></td>
|
||||
<td>@State.Velocity.Omega.ToString("F3") rad/s</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MudSimpleTable>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Typo="Typo.body2" Align="Align.Center">No velocity data available</MudText>
|
||||
}
|
||||
</MudPaper>
|
||||
|
||||
@code {
|
||||
public StateMsg? State { get; set; }
|
||||
|
||||
public void Update(StateMsg? state)
|
||||
{
|
||||
State = state;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user