RobotApp/RobotApp.Client/Pages/RobotConfigManager.razor.cs
Đăng Nguyễn 70e27da4a2 update
2025-11-03 10:29:18 +07:00

555 lines
22 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.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(Guid id)
{
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);
}
var response = await (await Http.PostAsync($"api/File/certificates/{id}", 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 config", Severity.Warning);
else return true;
return false;
}
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.VDA5050PublishRepeat,
SelectedVda.VDA5050EnablePassword,
SelectedVda.VDA5050EnableTls,
SelectedVda.VDA5050CA,
SelectedVda.VDA5050Cer,
SelectedVda.VDA5050Key,
SelectedVda.Description
};
var saveCer = await SaveCertificates(SelectedVda.Id);
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();
}
}
}