570 lines
23 KiB
C#
570 lines
23 KiB
C#
using MudBlazor;
|
|
using RobotApp.Common.Shares;
|
|
using RobotApp.Common.Shares.Dtos;
|
|
using RobotApp.Common.Shares.Enums;
|
|
using System.Net.Http.Headers;
|
|
using System.Net.Http.Json;
|
|
using System.Xml.Schema;
|
|
|
|
namespace RobotApp.Client.Pages;
|
|
|
|
public partial class RobotConfigManager
|
|
{
|
|
private async Task LoadVDA5050Configs()
|
|
{
|
|
try
|
|
{
|
|
var res = await Http.GetFromJsonAsync<MessageResult<RobotVDA5050ConfigDto[]>>("api/RobotConfigs/vda5050");
|
|
if (res is null) Snackbar.Add("Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (!res.IsSuccess) Snackbar.Add(res.Message ?? "Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (res.Data is not null)
|
|
{
|
|
VdaConfigs.Clear();
|
|
VdaConfigs.AddRange(res.Data);
|
|
|
|
var activeIdx = VdaConfigs.FindIndex(x => x.IsActive);
|
|
if (activeIdx >= 0)
|
|
{
|
|
SelectedIndex = activeIdx;
|
|
SelectedVda = VdaConfigs[activeIdx] with { };
|
|
}
|
|
else
|
|
{
|
|
SelectedIndex = -1;
|
|
SelectedVda = null;
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
else
|
|
{
|
|
Snackbar.Add("No VDA5050 configs found", Severity.Info);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error loading PLC configs: {ex.Message}", Severity.Warning);
|
|
}
|
|
}
|
|
|
|
private async Task LoadRobotConfigs()
|
|
{
|
|
try
|
|
{
|
|
var res = await Http.GetFromJsonAsync<MessageResult<RobotConfigDto[]>>("api/RobotConfigs/robot");
|
|
if (res is null) Snackbar.Add("Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (!res.IsSuccess) Snackbar.Add(res.Message ?? "Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (res.Data is not null)
|
|
{
|
|
CoreConfigs.Clear();
|
|
CoreConfigs.AddRange(res.Data);
|
|
|
|
var activeIdx = CoreConfigs.FindIndex(x => x.IsActive);
|
|
if (activeIdx >= 0)
|
|
{
|
|
SelectedIndex = activeIdx;
|
|
SelectedCore = CoreConfigs[activeIdx] with { };
|
|
}
|
|
else
|
|
{
|
|
SelectedIndex = -1;
|
|
SelectedCore = null;
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error loading PLC configs: {ex.Message}", Severity.Warning);
|
|
}
|
|
}
|
|
|
|
private async Task LoadRobotSafetyConfigs()
|
|
{
|
|
try
|
|
{
|
|
var res = await Http.GetFromJsonAsync<MessageResult<RobotSafetyConfigDto[]>>("api/RobotConfigs/safety");
|
|
if (res is null) Snackbar.Add("Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (!res.IsSuccess) Snackbar.Add(res.Message ?? "Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (res.Data is not null)
|
|
{
|
|
SafetyConfigs.Clear();
|
|
SafetyConfigs.AddRange(res.Data);
|
|
|
|
var activeIdx = SafetyConfigs.FindIndex(x => x.IsActive);
|
|
if (activeIdx >= 0)
|
|
{
|
|
SelectedIndex = activeIdx;
|
|
SelectedSafety = SafetyConfigs[activeIdx] with { };
|
|
}
|
|
else
|
|
{
|
|
SelectedIndex = -1;
|
|
SelectedSafety = null;
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error loading PLC configs: {ex.Message}", Severity.Warning);
|
|
}
|
|
}
|
|
|
|
private async Task LoadRobotSimulationConfigs()
|
|
{
|
|
try
|
|
{
|
|
var res = await Http.GetFromJsonAsync<MessageResult<RobotSimulationConfigDto[]>>("api/RobotConfigs/simulation");
|
|
if (res is null) Snackbar.Add("Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (!res.IsSuccess) Snackbar.Add(res.Message ?? "Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (res.Data is not null)
|
|
{
|
|
SimulationConfigs.Clear();
|
|
SimulationConfigs.AddRange(res.Data);
|
|
|
|
var activeIdx = SimulationConfigs.FindIndex(x => x.IsActive);
|
|
if (activeIdx >= 0)
|
|
{
|
|
SelectedIndex = activeIdx;
|
|
SelectedSimulation = SimulationConfigs[activeIdx] with { };
|
|
}
|
|
else
|
|
{
|
|
SelectedIndex = -1;
|
|
SelectedSimulation = null;
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error loading PLC configs: {ex.Message}", Severity.Warning);
|
|
}
|
|
}
|
|
|
|
private async Task LoadRobotPlcConfigs()
|
|
{
|
|
try
|
|
{
|
|
var res = await Http.GetFromJsonAsync<MessageResult<RobotPlcConfigDto[]>>("api/RobotConfigs/plc");
|
|
if (res is null) Snackbar.Add("Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (!res.IsSuccess) Snackbar.Add(res.Message ?? "Failed to load VDA5050 configs", Severity.Warning);
|
|
else if (res.Data is not null)
|
|
{
|
|
PlcConfigs.Clear();
|
|
PlcConfigs.AddRange(res.Data);
|
|
var activeIdx = PlcConfigs.FindIndex(x => x.IsActive);
|
|
if (activeIdx >= 0)
|
|
{
|
|
SelectedIndex = activeIdx;
|
|
SelectedPlc = PlcConfigs[activeIdx] with { };
|
|
}
|
|
else
|
|
{
|
|
SelectedIndex = -1;
|
|
SelectedPlc = null;
|
|
}
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error loading PLC configs: {ex.Message}", Severity.Warning);
|
|
}
|
|
}
|
|
|
|
private async Task SaveNewConfigAsync()
|
|
{
|
|
try
|
|
{
|
|
HttpResponseMessage? res = null;
|
|
_ = Guid.TryParse(SelectedTemplateIdString, out Guid templateId);
|
|
|
|
switch (SelectedType)
|
|
{
|
|
case RobotConfigType.VDA5050:
|
|
{
|
|
var template = VdaConfigs.FirstOrDefault(x => x.Id == templateId);
|
|
if (template is null) return;
|
|
var payload = new
|
|
{
|
|
addForm.ConfigName,
|
|
addForm.Description,
|
|
template.SerialNumber,
|
|
template.VDA5050HostServer,
|
|
template.VDA5050Port,
|
|
template.VDA5050UserName,
|
|
template.VDA5050Password,
|
|
template.VDA5050Manufacturer,
|
|
template.VDA5050Version,
|
|
template.VDA5050TopicPrefix,
|
|
template.VDA5050PublishRepeat,
|
|
template.VDA5050EnablePassword,
|
|
template.VDA5050EnableTls
|
|
};
|
|
|
|
res = await Http.PostAsJsonAsync("api/RobotConfigs/vda5050", payload);
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.PLC:
|
|
{
|
|
var template = PlcConfigs.FirstOrDefault(x => x.Id == templateId);
|
|
if (template is null) return;
|
|
var payload = new
|
|
{
|
|
addForm.ConfigName,
|
|
addForm.Description,
|
|
template.PLCAddress,
|
|
template.PLCPort,
|
|
template.PLCUnitId
|
|
};
|
|
|
|
res = await Http.PostAsJsonAsync("api/RobotConfigs/plc", payload);
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.Safety:
|
|
{
|
|
var template = SafetyConfigs.FirstOrDefault(x => x.Id == templateId);
|
|
if (template is null) return;
|
|
var payload = new
|
|
{
|
|
addForm.ConfigName,
|
|
addForm.Description,
|
|
template.SafetySpeedVerySlow,
|
|
template.SafetySpeedSlow,
|
|
template.SafetySpeedNormal,
|
|
template.SafetySpeedMedium,
|
|
template.SafetySpeedOptimal,
|
|
template.SafetySpeedFast,
|
|
template.SafetySpeedVeryFast
|
|
};
|
|
|
|
res = await Http.PostAsJsonAsync("api/RobotConfigs/safety", payload);
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.Simulation:
|
|
{
|
|
var template = SimulationConfigs.FirstOrDefault(x => x.Id == templateId);
|
|
if (template is null) return;
|
|
var payload = new
|
|
{
|
|
addForm.ConfigName,
|
|
addForm.Description,
|
|
template.EnableSimulation,
|
|
template.SimulationMaxVelocity,
|
|
template.SimulationMaxAngularVelocity,
|
|
template.SimulationAcceleration,
|
|
template.SimulationDeceleration
|
|
};
|
|
|
|
res = await Http.PostAsJsonAsync("api/RobotConfigs/simulation", payload);
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.Core:
|
|
default:
|
|
{
|
|
var template = CoreConfigs.FirstOrDefault(x => x.Id == templateId);
|
|
if (template is null) return;
|
|
var payload = new
|
|
{
|
|
addForm.ConfigName,
|
|
addForm.Description,
|
|
template.NavigationType,
|
|
template.RadiusWheel,
|
|
template.Width,
|
|
template.Length,
|
|
template.Height
|
|
};
|
|
|
|
res = await Http.PostAsJsonAsync("api/RobotConfigs/robot", payload);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (res is not null && res.IsSuccessStatusCode)
|
|
{
|
|
Snackbar.Add("Config created", Severity.Success);
|
|
IsAddingNew = false;
|
|
await LoadForTypeAsync(SelectedType);
|
|
}
|
|
else
|
|
{
|
|
var message = res is null ? "No response" : await res.Content.ReadAsStringAsync();
|
|
Snackbar.Add($"Create failed: {message}", Severity.Error);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error creating config: {ex.Message}", Severity.Error);
|
|
}
|
|
}
|
|
|
|
private async Task<bool> SaveCertificates()
|
|
{
|
|
using var content = new MultipartFormDataContent();
|
|
|
|
if (RobotVDA5050ConfigRef.CaFile is not null)
|
|
{
|
|
var fileContent = new StreamContent(RobotVDA5050ConfigRef.CaFile.OpenReadStream(maxAllowedSize: RobotVDA5050ConfigRef.MaxFileSize));
|
|
content.Add(fileContent, "CaFile", RobotVDA5050ConfigRef.CaFile.Name);
|
|
}
|
|
if (RobotVDA5050ConfigRef.CertFile is not null)
|
|
{
|
|
var fileContent = new StreamContent(RobotVDA5050ConfigRef.CertFile.OpenReadStream(maxAllowedSize: RobotVDA5050ConfigRef.MaxFileSize));
|
|
content.Add(fileContent, "CertFile", RobotVDA5050ConfigRef.CertFile.Name);
|
|
}
|
|
if (RobotVDA5050ConfigRef.KeyFile is not null)
|
|
{
|
|
var fileContent = new StreamContent(RobotVDA5050ConfigRef.KeyFile.OpenReadStream(maxAllowedSize: RobotVDA5050ConfigRef.MaxFileSize));
|
|
content.Add(fileContent, "KeyFile", RobotVDA5050ConfigRef.KeyFile.Name);
|
|
}
|
|
if (content.Any())
|
|
{
|
|
var response = await (await Http.PostAsync($"api/File/certificates", content)).Content.ReadFromJsonAsync<MessageResult>();
|
|
if (response is null) Snackbar.Add("Failed to update certificates", Severity.Warning);
|
|
else if (!response.IsSuccess) Snackbar.Add(response.Message ?? "Failed to update certificates", Severity.Warning);
|
|
else return true;
|
|
StateHasChanged();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private async Task SaveConfig()
|
|
{
|
|
try
|
|
{
|
|
Guid? id = SelectedType switch
|
|
{
|
|
RobotConfigType.VDA5050 => SelectedVda?.Id,
|
|
RobotConfigType.Safety => SelectedSafety?.Id,
|
|
RobotConfigType.Simulation => SelectedSimulation?.Id,
|
|
RobotConfigType.PLC => SelectedPlc?.Id,
|
|
RobotConfigType.Core => SelectedCore?.Id,
|
|
_ => null
|
|
};
|
|
|
|
if (id == null || id == Guid.Empty)
|
|
{
|
|
Snackbar.Add("No config selected to save.", Severity.Warning);
|
|
return;
|
|
}
|
|
|
|
MessageResult? result = null;
|
|
|
|
switch (SelectedType)
|
|
{
|
|
case RobotConfigType.VDA5050:
|
|
{
|
|
if (SelectedVda is null) { Snackbar.Add("No VDA5050 config selected.", Severity.Warning); return; }
|
|
var updateDto = new
|
|
{
|
|
SelectedVda.SerialNumber,
|
|
SelectedVda.VDA5050HostServer,
|
|
SelectedVda.VDA5050Port,
|
|
SelectedVda.VDA5050UserName,
|
|
SelectedVda.VDA5050Password,
|
|
SelectedVda.VDA5050Manufacturer,
|
|
SelectedVda.VDA5050Version,
|
|
SelectedVda.VDA5050TopicPrefix,
|
|
SelectedVda.VDA5050PublishRepeat,
|
|
SelectedVda.VDA5050EnablePassword,
|
|
SelectedVda.VDA5050EnableTls,
|
|
SelectedVda.VDA5050CA,
|
|
SelectedVda.VDA5050Cer,
|
|
SelectedVda.VDA5050Key,
|
|
SelectedVda.Description
|
|
};
|
|
var saveCer = await SaveCertificates();
|
|
if (saveCer) result = await (await Http.PutAsJsonAsync($"api/RobotConfigs/vda5050/{id}", updateDto)).Content.ReadFromJsonAsync<MessageResult>();
|
|
else return;
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.PLC:
|
|
{
|
|
if (SelectedPlc is null) { Snackbar.Add("No PLC config selected.", Severity.Warning); return; }
|
|
var updateDto = new
|
|
{
|
|
SelectedPlc.Description,
|
|
SelectedPlc.PLCAddress,
|
|
SelectedPlc.PLCPort,
|
|
SelectedPlc.PLCUnitId
|
|
};
|
|
|
|
result = await (await Http.PutAsJsonAsync($"api/RobotConfigs/plc/{id}", updateDto)).Content.ReadFromJsonAsync<MessageResult>();
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.Safety:
|
|
{
|
|
if (SelectedSafety is null) { Snackbar.Add("No Safety config selected.", Severity.Warning); return; }
|
|
var updateDto = new
|
|
{
|
|
SelectedSafety.SafetySpeedVerySlow,
|
|
SelectedSafety.SafetySpeedSlow,
|
|
SelectedSafety.SafetySpeedNormal,
|
|
SelectedSafety.SafetySpeedMedium,
|
|
SelectedSafety.SafetySpeedOptimal,
|
|
SelectedSafety.SafetySpeedFast,
|
|
SelectedSafety.SafetySpeedVeryFast,
|
|
SelectedSafety.Description
|
|
};
|
|
|
|
result = await (await Http.PutAsJsonAsync($"api/RobotConfigs/safety/{id}", updateDto)).Content.ReadFromJsonAsync<MessageResult>();
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.Simulation:
|
|
{
|
|
if (SelectedSimulation is null) { Snackbar.Add("No Simulation config selected.", Severity.Warning); return; }
|
|
var updateDto = new
|
|
{
|
|
SelectedSimulation.EnableSimulation,
|
|
SelectedSimulation.SimulationMaxVelocity,
|
|
SelectedSimulation.SimulationMaxAngularVelocity,
|
|
SelectedSimulation.SimulationAcceleration,
|
|
SelectedSimulation.SimulationDeceleration,
|
|
SelectedSimulation.Description
|
|
};
|
|
|
|
result = await (await Http.PutAsJsonAsync($"api/RobotConfigs/simulation/{id}", updateDto)).Content.ReadFromJsonAsync<MessageResult>();
|
|
break;
|
|
}
|
|
|
|
case RobotConfigType.Core:
|
|
default:
|
|
{
|
|
if (SelectedCore is null) { Snackbar.Add("No Core config selected.", Severity.Warning); return; }
|
|
var updateDto = new
|
|
{
|
|
SelectedCore.NavigationType,
|
|
SelectedCore.RadiusWheel,
|
|
SelectedCore.Width,
|
|
SelectedCore.Length,
|
|
SelectedCore.Height,
|
|
SelectedCore.Description
|
|
};
|
|
|
|
result = await (await Http.PutAsJsonAsync($"api/RobotConfigs/robot/{id}", updateDto)).Content.ReadFromJsonAsync<MessageResult>();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (result is null) Snackbar.Add("Failed to update config", Severity.Warning);
|
|
else if (!result.IsSuccess) Snackbar.Add(result.Message ?? "Failed to update config", Severity.Warning);
|
|
else
|
|
{
|
|
Snackbar.Add("Config saved", Severity.Success);
|
|
|
|
await LoadForTypeAsync(SelectedType);
|
|
|
|
switch (SelectedType)
|
|
{
|
|
case RobotConfigType.VDA5050:
|
|
var vIdx = VdaConfigs.FindIndex(x => x.Id == id);
|
|
if (vIdx >= 0) { SelectedIndex = vIdx; SelectedVda = VdaConfigs[vIdx] with { }; }
|
|
break;
|
|
case RobotConfigType.Safety:
|
|
var sIdx = SafetyConfigs.FindIndex(x => x.Id == id);
|
|
if (sIdx >= 0) { SelectedIndex = sIdx; SelectedSafety = SafetyConfigs[sIdx] with { }; }
|
|
break;
|
|
case RobotConfigType.Simulation:
|
|
var simIdx = SimulationConfigs.FindIndex(x => x.Id == id);
|
|
if (simIdx >= 0) { SelectedIndex = simIdx; SelectedSimulation = SimulationConfigs[simIdx] with { }; }
|
|
break;
|
|
case RobotConfigType.PLC:
|
|
var pIdx = PlcConfigs.FindIndex(x => x.Id == id);
|
|
if (pIdx >= 0) { SelectedIndex = pIdx; SelectedPlc = PlcConfigs[pIdx] with { }; }
|
|
break;
|
|
case RobotConfigType.Core:
|
|
var cIdx = CoreConfigs.FindIndex(x => x.Id == id);
|
|
if (cIdx >= 0) { SelectedIndex = cIdx; SelectedCore = CoreConfigs[cIdx] with { }; }
|
|
break;
|
|
}
|
|
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error saving config: {ex.Message}", Severity.Error);
|
|
}
|
|
}
|
|
|
|
private async Task ConfirmDeleteAsync()
|
|
{
|
|
try
|
|
{
|
|
if (DeletePendingId is null || DeletePendingId == Guid.Empty)
|
|
{
|
|
Snackbar.Add("No config selected to delete.", Severity.Warning);
|
|
CancelDelete();
|
|
return;
|
|
}
|
|
|
|
var id = DeletePendingId.Value;
|
|
string path = SelectedType switch
|
|
{
|
|
RobotConfigType.VDA5050 => $"api/RobotConfigs/vda5050/{id}",
|
|
RobotConfigType.Safety => $"api/RobotConfigs/safety/{id}",
|
|
RobotConfigType.Simulation => $"api/RobotConfigs/simulation/{id}",
|
|
RobotConfigType.PLC => $"api/RobotConfigs/plc/{id}",
|
|
RobotConfigType.Core => $"api/RobotConfigs/robot/{id}",
|
|
_ => throw new InvalidOperationException("Unsupported config type")
|
|
};
|
|
|
|
IsLoading = true;
|
|
StateHasChanged();
|
|
|
|
var httpRes = await Http.DeleteFromJsonAsync<MessageResult>(path);
|
|
|
|
if (httpRes is null) Snackbar.Add("Failed to delete config", Severity.Warning);
|
|
else if (!httpRes.IsSuccess) Snackbar.Add(httpRes.Message ?? "Failed to delete config", Severity.Warning);
|
|
else
|
|
{
|
|
Snackbar.Add("Config deleted", Severity.Success);
|
|
|
|
SelectedIndex = -1;
|
|
switch (SelectedType)
|
|
{
|
|
case RobotConfigType.VDA5050: SelectedVda = null; break;
|
|
case RobotConfigType.Safety: SelectedSafety = null; break;
|
|
case RobotConfigType.Simulation: SelectedSimulation = null; break;
|
|
case RobotConfigType.PLC: SelectedPlc = null; break;
|
|
case RobotConfigType.Core: SelectedCore = null; break;
|
|
}
|
|
|
|
await LoadForTypeAsync(SelectedType);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Snackbar.Add($"Error deleting config: {ex.Message}", Severity.Error);
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
CancelDelete();
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
private async Task LoadConfig()
|
|
{
|
|
var response = await (await Http.PostAsync($"api/RobotConfigs/load", null)).Content.ReadFromJsonAsync<MessageResult>();
|
|
if (response is null) Snackbar.Add("Failed to load config", Severity.Warning);
|
|
else if (!response.IsSuccess) Snackbar.Add(response.Message ?? "Failed to load config", Severity.Warning);
|
|
else Snackbar.Add("Config loaded", Severity.Success);
|
|
StateHasChanged();
|
|
}
|
|
}
|