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>("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>("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>("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>("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>("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 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(); 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(); 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(); 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(); 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(); 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(); 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(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(); 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(); } }