diff --git a/AgroBase/AgroBase/Forms/IHM/frmAjustes.cs b/AgroBase/AgroBase/Forms/IHM/frmAjustes.cs index 1ae1d4805..f3dac7ecd 100644 --- a/AgroBase/AgroBase/Forms/IHM/frmAjustes.cs +++ b/AgroBase/AgroBase/Forms/IHM/frmAjustes.cs @@ -1,7 +1,9 @@ using AgroBase.Models; using AgroBase.Models.Components; +using AgroBase.Models.Operadores; using AgroBase.Services; using AgroBase.Services.Operadores; +using Assimp; using System; using System.Collections.Generic; using System.Data; @@ -259,7 +261,15 @@ namespace AgroBase.Forms.IHM private async Task AtualizarCameras() { flwCamerasSolo.Controls.Clear(); - ListaCameras = CameraWorkerService.GetListaCameras(); + var cameras = CameraWorkerService.GetListaCameras(); + ListaCameras = cameras.Select(x => new OAKCameraModel() + { + Index = 0, + Dispositivo = x.dispositivo, + Version = x.versao, + Name = x.modelo, + Id = x.mx_id, + }).ToList(); CameraCaminho = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.Clone(); CamerasSolo = new List(Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo); diff --git a/AgroBase/AgroBase/Forms/IHM/frmIHM.cs b/AgroBase/AgroBase/Forms/IHM/frmIHM.cs index a759552f0..813a3c352 100644 --- a/AgroBase/AgroBase/Forms/IHM/frmIHM.cs +++ b/AgroBase/AgroBase/Forms/IHM/frmIHM.cs @@ -175,7 +175,7 @@ namespace AgroBase.Forms.IHM var CameraSolo = Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo.Count() > idx ? Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo[idx] : null; lbl.ForeColor = modDesconectado || CameraSolo?.Id == null ? Color.Black - : !listaCameras.Any(x => x.Id == CameraSolo.Id) ? + : !listaCameras.Any(x => x.mx_id == CameraSolo.Id) ? Color.DarkRed : Color.DarkGreen; } @@ -186,7 +186,7 @@ namespace AgroBase.Forms.IHM var CameraCaminho = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho; lbl.ForeColor = modDesconectado || CameraCaminho?.Id == null ? Color.Black - : !listaCameras.Any(x => x.Id == CameraCaminho.Id) + : !listaCameras.Any(x => x.mx_id == CameraCaminho.Id) ? Color.DarkRed : Color.DarkGreen; } diff --git a/AgroBase/AgroBase/Forms/frmOperarioSonar.cs b/AgroBase/AgroBase/Forms/frmOperarioSonar.cs index a3581a13d..3ae4f6b7f 100644 --- a/AgroBase/AgroBase/Forms/frmOperarioSonar.cs +++ b/AgroBase/AgroBase/Forms/frmOperarioSonar.cs @@ -41,7 +41,7 @@ namespace AgroBase.Forms private void AtualizarListaCameras() { cmbCameras.Items.Clear(); - cmbCameras.Items.AddRange(CameraWorkerService.GetListaCameras().Select(x => x.Name).ToArray()); + cmbCameras.Items.AddRange(CameraWorkerService.GetListaCameras().Select(x => x.modelo).ToArray()); cmbCameras.SelectedIndex = -1; } diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs index 5e0ba3414..711b41ba3 100644 --- a/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs +++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs @@ -1,6 +1,7 @@ using AgroBase.Models.Modules; using AgroBase.Models.Operadores; using AgroBase.Services; +using AgroBase.Services.Operadores; using System; using System.Collections.Generic; using System.ComponentModel; @@ -489,6 +490,8 @@ namespace AgroBase.Models.Operacoes public LivoxModel LivoxLidar { get; set; } public DateTime UltimoEnvioLog { get; set; } = DateTime.MinValue; public List Logs { get; set; } + public List Cameras { get; set; } + public VisualWorkerResumoModel OperadorVisual { get; set; } public void Atualizar() { @@ -765,6 +768,8 @@ namespace AgroBase.Models.Operacoes }; PerformanceNcp = sen?.DadosPerformance?.Clone(); LivoxLidar = sen?.LivoxLidar?.Clone(); + Cameras = CameraWorkerService.ListaCameras; + OperadorVisual = VisualWorkerService.DadosLeitura?.Resumo?.UpdateClone(); var l = sen?.Logs; Logs = l != null ? l.Where(x => x.Momento >= UltimoEnvioLog).ToList() : new List(); } @@ -792,6 +797,8 @@ namespace AgroBase.Models.Operacoes PerformanceNcp = PerformanceNcp?.Clone(), LivoxLidar = LivoxLidar?.Clone(), Logs = new List(Logs ?? new List()), + Cameras = new List(Cameras ?? new List()), + OperadorVisual = OperadorVisual?.Clone(), UltimoEnvioLog = UltimoEnvioLog }; } diff --git a/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs b/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs index 373a50d39..9e7f974ff 100644 --- a/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs +++ b/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs @@ -42,6 +42,13 @@ namespace AgroBase.Models.Operadores public bool rodando { get; set; } public bool tem_depth { get; set; } public bool tem_imu { get; set; } + + public bool streaming { get; set; } + public double fps { get; set; } + public int stream_w { get; set; } + public int stream_h { get; set; } + public int stream_kbps { get; set; } + public SaudeWorkerModel saude { get; set; } public CameraWorkerItemPerformanceModel performance { get; set; } } diff --git a/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs b/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs index 0bad3803c..cf844463e 100644 --- a/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs +++ b/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs @@ -1,4 +1,5 @@ -using System; +using AgroBase.Services.Operadores; +using System; using System.Collections.Generic; using System.Drawing; using System.Linq; @@ -52,6 +53,9 @@ namespace AgroBase.Models.Operadores public class VisualWorkerResumoModel { + public StatusCarroMapa StatusCarro { get; set; } + public double ErroLateral { get; set; } + public bool ObstaculoDetectado { get; set; } = false; public bool DeveParar { get; set; } = false; public bool EnviarComandoParada { get; set; } = false; @@ -63,6 +67,8 @@ namespace AgroBase.Models.Operadores { var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual; ObstaculoDetectado = (Sonar.Analises?.matriz_confianca?.block?.decision?.parar ?? false); + StatusCarro = Sonar?.Analises?.segmentacao?.status_corredor ?? StatusCarroMapa.Indefinido; + ErroLateral = Sonar?.Analises?.segmentacao?.erro_angular ?? 0; if (!Variaveis.OperacaoEmAndamento.Parametros.Controle.SonarAtivado) { @@ -95,6 +101,8 @@ namespace AgroBase.Models.Operadores { return new VisualWorkerResumoModel() { + StatusCarro = StatusCarro, + ErroLateral = ErroLateral, ObstaculoDetectado = ObstaculoDetectado, DeveParar = DeveParar, EnviarComandoParada = EnviarComandoParada, @@ -102,6 +110,12 @@ namespace AgroBase.Models.Operadores _comandoParadaEnviado = _comandoParadaEnviado, }; } + + public VisualWorkerResumoModel UpdateClone() + { + AtualizarStatusBloqueio(false); + return Clone(); + } } public class VisualWorkerDadosModel diff --git a/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs index 142a42002..576077ccc 100644 --- a/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs @@ -14,7 +14,8 @@ namespace AgroBase.Services.Operadores { public CameraWorkerModel DadosLeitura = new CameraWorkerModel(); public SaudeWorkerModel Saude { get; set; } = new SaudeWorkerModel(); - private static List CamerasConectadas = new List(); + private static List CamerasConectadas = new List(); + public static List ListaCameras => CamerasConectadas.Skip(1).ToList(); private bool DebugMode = true; @@ -85,15 +86,14 @@ namespace AgroBase.Services.Operadores } - public static List GetListaCameras() + public static List GetListaCameras() { - CamerasConectadas = new List() + CamerasConectadas = new List() { - new OAKCameraModel() + new CameraWorkerItemModel() { - Dispositivo = T_Code.Vzo, - Index = -1, - Name = "Sem Video" + dispositivo = T_Code.Vzo, + modelo = "Sem Video" } }; @@ -107,13 +107,7 @@ namespace AgroBase.Services.Operadores var camera_str = RedisService.Get(RedisService.CamKey(cam.Key)); var camera = JsonConvert.DeserializeObject(camera_str); if (camera.mx_id == null) continue; - CamerasConectadas.Add(new OAKCameraModel() - { - Dispositivo = camera.dispositivo, - Version = camera.versao, - Name = camera.modelo, - Id = camera.mx_id, - }); + CamerasConectadas.Add(camera); } } diff --git a/AgroBase/AgroBase/Services/SerialService.cs b/AgroBase/AgroBase/Services/SerialService.cs index 36e1a7501..a7927b01e 100644 --- a/AgroBase/AgroBase/Services/SerialService.cs +++ b/AgroBase/AgroBase/Services/SerialService.cs @@ -469,22 +469,22 @@ namespace AgroBase.Services GeneralJoystick.AtualizaDispositivo(); } - var _Cameras = CameraWorkerService.GetListaCameras().Where(x => x.Index > -1).ToList(); + var _Cameras = CameraWorkerService.ListaCameras; foreach (var cam in _Cameras) { - var disp = HealthWorkerService.ModulosSaude.FirstOrDefault(x => x.modulo == cam.Dispositivo); + var disp = HealthWorkerService.ModulosSaude.FirstOrDefault(x => x.modulo == cam.dispositivo); if (disp == null) continue; - var added = DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == cam.Dispositivo); + var added = DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == cam.dispositivo); bool connected = disp.status != StatusModulo.Desconectado; if (added == null && connected) { DispositivosMapeados.Add(new DispositivoDetalhesModel() { - Dispositivo = cam.Dispositivo, + Dispositivo = cam.dispositivo, Endereco = "USB", - Versao = cam.Version + Versao = cam.versao }); } else if (added != null && !connected) diff --git a/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs b/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs index e914e9377..8e689c709 100644 --- a/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs +++ b/AgroBase/OperationControl/Controls/MapViewControl.xaml.cs @@ -102,6 +102,7 @@ namespace OperationControl.Controls public MapMarkerManager markers; public event EventHandler? MarkerClicked; + private bool SemRoverFocado => VariaveisControleOperacao.RoverEmFoco == null; protected virtual void OnMarkerClicked(string markerId) { if (markerId == null) markers?.ClearMarkerFocused(); @@ -532,7 +533,8 @@ namespace OperationControl.Controls if (info?.Layer == markers.Layer && feat != null && markers != null && markers.TryGetIdFromFeature(feat, out var id)) { - OnMarkerClicked(id); + if (SemRoverFocado) + OnMarkerClicked(id); } else if (info?.Layer == MapaPlantacao_Layer && feat is MIFeature roadFeature) { @@ -556,7 +558,7 @@ namespace OperationControl.Controls var info = Mapa.GetMapInfo(sp, Mapa.Map.Layers /*, 18*/); var feat = info?.Feature; - if (feat != null && markers != null && markers.TryGetIdFromFeature(feat, out _)) + if (feat != null && markers != null && markers.TryGetIdFromFeature(feat, out _) && SemRoverFocado) Mapa.Cursor = System.Windows.Input.Cursors.Hand; else if (feat != null && info?.Layer == MapaPlantacao_Layer && feat is MIFeature roadFeature && ParametrizandoOperacao) Mapa.Cursor = System.Windows.Input.Cursors.Hand; diff --git a/AgroBase/OperationControl/Controls/Pulverizador/PulverizadorIndicator.xaml b/AgroBase/OperationControl/Controls/Pulverizador/PulverizadorIndicator.xaml index 2365d53ba..fdfacb669 100644 --- a/AgroBase/OperationControl/Controls/Pulverizador/PulverizadorIndicator.xaml +++ b/AgroBase/OperationControl/Controls/Pulverizador/PulverizadorIndicator.xaml @@ -79,15 +79,34 @@ - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -117,45 +136,21 @@ + VerticalAlignment="Top" + Margin="2,0,2,0" + AnguloControle="{Binding AnguloControle}" + OpeningAngle="{Binding OpeningAngle}" + IsCommandOn="{Binding IsCommandOn}" + IsSpraying="{Binding IsSpraying}" + Vazao="{Binding Vazao}" + TempoAtuado="{Binding TempoAtuado}" + Atuacoes="{Binding Atuacoes}" /> - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/AgroBase/OperationControl/Models/AlertaModel.cs b/AgroBase/OperationControl/Models/AlertaModel.cs index 4d5f87b06..b0cc04b75 100644 --- a/AgroBase/OperationControl/Models/AlertaModel.cs +++ b/AgroBase/OperationControl/Models/AlertaModel.cs @@ -17,7 +17,8 @@ namespace OperationControl.Models public T_Code Modulo { get; set; } // ex: "DIR", "SEN", "MOV" public string? Mod_ID { get; set; } // ID public string Mensagem { get; set; } // texto principal - public DateTime Timestamp { get; set; } // opcional: hora do evento + public DateTime CriadoEm { get; set; } + public DateTime? AtualizadoEm { get; set; } // Campo calculado para título (ex: "DIR — Falha no encoder") diff --git a/AgroBase/OperationControl/Models/AppShell.cs b/AgroBase/OperationControl/Models/AppShell.cs index f57d9d8a5..c0b5f2448 100644 --- a/AgroBase/OperationControl/Models/AppShell.cs +++ b/AgroBase/OperationControl/Models/AppShell.cs @@ -36,7 +36,7 @@ namespace OperationControl.Models Dock = new DockWindow(); Dock.Show(); - if (Mock) + if (Mock && false) { Task.Run(async () => { diff --git a/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs index eab81d75f..f0fd254c0 100644 --- a/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/Operacao/Monitoramento/MonitoramentoViewModel.cs @@ -1,13 +1,133 @@ -using OperationControl.ViewModels.Base; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using static AgroBase.Models.Enums; namespace OperationControl.ViewModels.Views.Operacao.Monitoramento { - public class MonitoramentoViewModel : NotifyBase + public class FrameTipoItem { + public TipoFrameCamera Valor { get; set; } + public string Nome { get; set; } + + public override string ToString() => Nome; + } + + public class MonitoramentoViewModel : INotifyPropertyChanged + { + public ObservableCollection CameraFrontalFrameTipos { get; set; } + public ObservableCollection CameraErvasFrameTipos { get; set; } + + private FrameTipoItem _cameraFrontalFrameTipoSelecionado; + public FrameTipoItem CameraFrontalFrameTipoSelecionado + { + get => _cameraFrontalFrameTipoSelecionado; + set + { + if (_cameraFrontalFrameTipoSelecionado != value) + { + _cameraFrontalFrameTipoSelecionado = value; + OnPropertyChanged(); + CameraFrontalFrameTipoAlterado?.Invoke(value?.Valor ?? default); + } + } + } + + private FrameTipoItem _cameraErvasFrameTipoSelecionado; + public FrameTipoItem CameraErvasFrameTipoSelecionado + { + get => _cameraErvasFrameTipoSelecionado; + set + { + if (_cameraErvasFrameTipoSelecionado != value) + { + _cameraErvasFrameTipoSelecionado = value; + OnPropertyChanged(); + CameraErvasFrameTipoAlterado?.Invoke(value?.Valor ?? default); + } + } + } + + public string CameraFrontalTitulo { get; } = "Camera Frontal"; + private string _cameraFrontalStatus = "Sem dados"; + public string CameraFrontalStatus + { + get => _cameraFrontalStatus; + set + { + _cameraFrontalStatus = value; + OnPropertyChanged(); + } + } + + public string CameraErvasTitulo { get; } = "Camera Ervas"; + private string _cameraErvasStatus = "Sem dados"; + public string CameraErvasStatus + { + get => _cameraErvasStatus; + set + { + _cameraErvasStatus = value; + OnPropertyChanged(); + } + } + + private bool _cameraFrontalSemSinal = true; + public bool CameraFrontalSemSinal + { + get => _cameraFrontalSemSinal; + set + { + _cameraFrontalSemSinal = value; + OnPropertyChanged(); + } + } + private bool _cameraErvasSemSinal = true; + public bool CameraErvasSemSinal + { + get => _cameraErvasSemSinal; + set + { + _cameraErvasSemSinal = value; + OnPropertyChanged(); + } + } + + + public event Action? CameraFrontalFrameTipoAlterado; + public event Action? CameraErvasFrameTipoAlterado; + + public MonitoramentoViewModel() + { + var itens = Enum.GetValues(typeof(TipoFrameCamera)) + .Cast() + .Select(x => new FrameTipoItem + { + Valor = x, + Nome = x.ToString() + }) + .ToList(); + + CameraFrontalFrameTipos = new ObservableCollection(itens); + CameraErvasFrameTipos = new ObservableCollection(itens); + + CameraFrontalFrameTipoSelecionado = CameraFrontalFrameTipos.FirstOrDefault(); + CameraErvasFrameTipoSelecionado = CameraErvasFrameTipos.FirstOrDefault(); + } + + public void AtualizarDadosCameras(double? cf_fps, double? cf_kbps, double? ct_fps, double? ct_kbps, StatusCarroMapa? status_carro, double? pct_ervas) + { + CameraFrontalStatus = $"{cf_fps ?? 0} fps • {cf_kbps ?? 0} kbps • {status_carro ?? StatusCarroMapa.Indefinido}"; + CameraErvasStatus = $"{ct_fps ?? 0} fps • {ct_kbps ?? 0} kbps • {pct_ervas ?? 0:F2}% ervas"; + CameraFrontalSemSinal = (cf_kbps ?? 0) == 0; + CameraErvasSemSinal = (ct_kbps ?? 0) == 0; + } + + public event PropertyChangedEventHandler? PropertyChanged; + + protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } } diff --git a/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoBottomViewModel.cs b/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoBottomViewModel.cs index 35003b1a8..8428e1b54 100644 --- a/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoBottomViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Views/Operacao/OperacaoBottomViewModel.cs @@ -82,7 +82,7 @@ namespace OperationControl.ViewModels.Views.Operacao Mod_ID = modId, Severidade = severidade, Mensagem = mensagem, - Timestamp = DateTime.Now + CriadoEm = DateTime.Now }; AlertasAtivos.Add(alerta); @@ -187,6 +187,11 @@ namespace OperationControl.ViewModels.Views.Operacao { App.Current.Dispatcher.BeginInvoke(new Action(() => { + string GerarChave(string roverId, T_Code modulo, string? modId) => $"{roverId}|{modulo}|{modId ?? ""}"; + + var agora = DateTime.Now; + + // 1) Gera os alertas que DEVERIAM existir neste momento var alertasEsperados = new List(); foreach (var rover in VariaveisControleOperacao.RoversNaRede) @@ -210,8 +215,8 @@ namespace OperationControl.ViewModels.Views.Operacao Modulo = mod.modulo, Mod_ID = ind.label, Severidade = DeParaStatus(ind.status, ind.em_uso), - Mensagem = string.Join(", ", ind.motivos ?? new List()), - Timestamp = DateTime.Now + Mensagem = string.Join(", ", ind.motivos ?? new List()) + // NÃO define Timestamp aqui ainda }); } } @@ -229,64 +234,75 @@ namespace OperationControl.ViewModels.Views.Operacao Modulo = mod.modulo, Mod_ID = null, Severidade = DeParaStatus(mod.status, mandatorio), - Mensagem = string.Join(", ", mod.motivos ?? new List()), - Timestamp = DateTime.Now + Mensagem = string.Join(", ", mod.motivos ?? new List()) + // NÃO define Timestamp aqui ainda }); } } } - string GerarChave(string roverId, T_Code modulo, string? modId) - => $"{roverId}|{modulo}|{modId ?? ""}"; - var mapaEsperado = alertasEsperados.ToDictionary( x => GerarChave(x.Rover_ID, x.Modulo, x.Mod_ID), x => x); - var alertasAtuais = AlertasAtivos.ToList(); + var mapaAtual = AlertasAtivos.ToDictionary( + x => GerarChave(x.Rover_ID, x.Modulo, x.Mod_ID), + x => x); - // Remove os alertas que não deveriam mais existir - foreach (var atual in alertasAtuais) + // 2) Remove os alertas que não existem mais + var chavesParaRemover = mapaAtual.Keys + .Where(chave => !mapaEsperado.ContainsKey(chave)) + .ToList(); + + foreach (var chave in chavesParaRemover) { - var chave = GerarChave(atual.Rover_ID, atual.Modulo, atual.Mod_ID); - if (!mapaEsperado.ContainsKey(chave)) - { - AlertasAtivos.Remove(atual); + var alertaRemover = mapaAtual[chave]; - if (ToastAlerta == atual) - LimparToast(); - } + AlertasAtivos.Remove(alertaRemover); + + if (ToastAlerta == alertaRemover) + LimparToast(); } - // Adiciona ou atualiza os alertas esperados - foreach (var esperado in alertasEsperados) + // 3) Adiciona novos ou atualiza os existentes + foreach (var kv in mapaEsperado) { - var existente = AlertasAtivos.FirstOrDefault(x => - x.Rover_ID == esperado.Rover_ID && - x.Modulo == esperado.Modulo && - x.Mod_ID == esperado.Mod_ID); + var chave = kv.Key; + var esperado = kv.Value; - if (existente == null) + if (!mapaAtual.TryGetValue(chave, out var existente)) { + // Novo alerta + esperado.CriadoEm = agora; AlertasAtivos.Add(esperado); MostrarToast(esperado); } else { + // Alerta já existia -> mantém Timestamp original bool mudou = existente.Mensagem != esperado.Mensagem || existente.Severidade != esperado.Severidade; - existente.Mensagem = esperado.Mensagem; - existente.Severidade = esperado.Severidade; - if (mudou) { - existente.Timestamp = DateTime.Now; + existente.Mensagem = esperado.Mensagem; + existente.Severidade = esperado.Severidade; + + // Se quiser que Timestamp represente "última mudança", mantém isso: + existente.AtualizadoEm = agora; + MostrarToast(existente); } } } + + var ordenado = AlertasAtivos.OrderByDescending(x => x.AtualizadoEm ?? x.CriadoEm).ToList(); + AlertasAtivos.Clear(); + foreach (var a in ordenado) + { + AlertasAtivos.Add(a); + } })); } diff --git a/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs b/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs index c61996c44..77f0fbe98 100644 --- a/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs @@ -9,7 +9,6 @@ using AgroBase.Models.Operacoes; using Newtonsoft.Json.Linq; using OperationControl.ViewModels.Views.Operacao; using OperationControl.Controls; -using static OpenTK.Graphics.OpenGL.GL; namespace OperationControl.ViewModels { @@ -528,15 +527,17 @@ namespace OperationControl.ViewModels var obj = rover.DadosLeitura; if (obj == null) return; + // MAPA var simulacao = obj.Controle?.SimulacaoMPC?.Select(x => new double[] { x.longitude, x.latitude })?.ToList(); _viewOperacaoCenter?.Mapa?.markers.UpdateMarkerPosition(rover.RoverId, lat: obj.Gnss?.Latitude, lon: obj.Gnss?.Longitude, heading: obj.Gnss?.OrientacaoReal, predict: simulacao); _viewOperacaoCenter?.Mapa?.markers.UpdateMarkerInfo(rover.RoverId, status: obj.Operacao?.Status ?? AgroBase.Models.Enums.StatusOperacao.NaoIniciado); - //_viewOperacaoBottom?._vm?.AtualizarListaAlertasRoverSelecionado(rover.RoverId); + // ALERTAS _viewOperacaoBottom?._vm?.AtualizarListaAlertasTodosRovers(); if (rover.RoverId != VariaveisControleOperacao.SelectedRoverId) return; + // ESQUERDA var conexao = obj.ModulosSaude?.FirstOrDefault(x => x.modulo == AgroBase.Models.Enums.T_Code.Ipb); double c = conexao?.saude ?? 0; double conexao_latencia = conexao?.detalhes?["avg_rtt"]?.Value() ?? 0.0; @@ -557,6 +558,7 @@ namespace OperationControl.ViewModels $"{obj.Gnss?.QualidadeFix ?? AgroBase.Models.Enums.TiposCorrecaoGPS.SemCorrecao} {obj.Gnss?.PrecisaoCm:F2} cm" ); + // DIREITA (RESUMO) _viewOperacaoRight?._vm?.AtualizarResumo(r => { r.Operacao = (obj.Operacao?.Liberada ?? false) ? "🔓 Liberada" : "🔒 Bloqueada"; @@ -580,14 +582,16 @@ namespace OperationControl.ViewModels r.InfestacaoPercentual = obj.Atuador?.PercentualErvasTerreno ?? 0; }); + // DIAGNOSTICO _viewOperacaoCenter?.Diagnostico?._vm?.AtualizarDados(rover); _viewOperacaoCenter?.Diagnostico?.AtualizarGraficos(); + // PULVERIZADOR var bomba = obj.Atuador?.Bombas?.FirstOrDefault(); var ATU = _viewOperacaoCenter.Monitoramento.Pulverizador; ATU.ComprimentoBarraCm = AgroBase.Models.VariaveisEquipamento.ComprimentoBarraPulverizadoraCm; ATU.DistanciaEntreBicosCm = AgroBase.Models.VariaveisEquipamento.DistanciaEntreBicosCm; - ATU.AlturaBarra = obj?.Controle?.AlturaBarra ?? AgroBase.Models.VariaveisEquipamento.AlturaBarraPulverizadoraCm; + //ATU.AlturaBarra = obj?.Controle?.AlturaBarra ?? AgroBase.Models.VariaveisEquipamento.AlturaBarraPulverizadoraCm; ATU.IsBombaOn = bomba?.LeituraEstado ?? false; ATU.PressaoLinha = obj?.Atuador?.PressaoLinhaPsi ?? 0; ATU.VazaoInstantanea = obj?.Atuador?.VazaoInstantaneaMLs ?? 0; @@ -615,6 +619,11 @@ namespace OperationControl.ViewModels bico.Atuacoes = _bc.QtdAtuacoes; bico.TempoAtuado = _bc.TempoAtuado / 1000.0; } + + // CAMERAS + var camera_snr = obj?.Cameras?.FirstOrDefault(x => x.dispositivo == AgroBase.Models.Enums.T_Code.Snr); + var camera_cam = obj?.Cameras?.FirstOrDefault(x => x.dispositivo == AgroBase.Models.Enums.T_Code.Cam); + _viewOperacaoCenter?.Monitoramento?._vm?.AtualizarDadosCameras(camera_snr?.fps, camera_snr?.stream_kbps, camera_cam?.fps, camera_cam?.stream_kbps, obj?.OperadorVisual?.StatusCarro, obj?.Atuador?.PercentualErvasNoRadar); } diff --git a/AgroBase/OperationControl/Views/Operacao/MonitoramentoView.xaml b/AgroBase/OperationControl/Views/Operacao/MonitoramentoView.xaml index 6cf76f5b7..ea5d84d18 100644 --- a/AgroBase/OperationControl/Views/Operacao/MonitoramentoView.xaml +++ b/AgroBase/OperationControl/Views/Operacao/MonitoramentoView.xaml @@ -9,6 +9,10 @@ d:DesignHeight="900" d:DesignWidth="1600"> + + + + @@ -21,13 +25,7 @@ - + @@ -36,49 +34,23 @@ - + - + - + - + - + - + @@ -87,15 +59,15 @@ - + - + - + - + @@ -120,18 +92,12 @@ - - + + - + @@ -139,17 +105,9 @@ - + - + @@ -164,7 +122,7 @@ - +