From 86d220415369e8f51a98be3a11e7bfa794f7872d Mon Sep 17 00:00:00 2001 From: Diego Freitas Date: Wed, 8 Jul 2026 08:08:52 -0300 Subject: [PATCH] ajustado bloqueio da operacao por atuador quando pulverizador automatico estiver desligado, ajustado erro na saude do ipb --- .../Models/TrajetoriaMapaOperacaoModel.cs | 17 +- AgroBase/AgroBase/Models/Variaveis.cs | 2 +- .../workers/health_worker/modulos/atuador.py | 154 +++++++++++++----- .../workers/health_worker/modulos/ponte_ip.py | 2 +- .../ViewModels/Windows/DockWindowViewModel.cs | 4 +- 5 files changed, 133 insertions(+), 46 deletions(-) diff --git a/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs b/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs index 1d7414763..e731770ee 100644 --- a/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs +++ b/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs @@ -2881,8 +2881,16 @@ namespace AgroBase.Models bool bateriaOk = BateriaSuficiente && (_Bateria?.Iniciado ?? false); bool herbOk = HerbicidaSuficiente && (_Reservatorio?.Iniciado ?? false); - bool exigirPulverizacaoTotal = - op.Parametros?.ModulosMandatorios?.Any(x => x.Dispositivo == T_Code.Atu && x.Mandatorio && x.Utilizar) ?? false; + bool pulverizadorAutomatico = op.Parametros?.Controle?.PulverizadorAutomatico ?? false; + + bool atuMandatorio = + op.Parametros?.ModulosMandatorios?.Any(x => + x.Dispositivo == T_Code.Atu && + x.Mandatorio && + x.Utilizar + ) ?? false; + + bool exigirPulverizacaoTotal = pulverizadorAutomatico && atuMandatorio; // ========================== // 1) Calcula status "base" (sem considerar trava) @@ -3003,6 +3011,8 @@ namespace AgroBase.Models } else { + motivosBloqueio.Clear(); + // ❌ Ainda está crítico, mas operador insistiu -> OkSupervisionado (override) statusFinal = AutonomiaCorredorStatus.OkSupervisionado; liberadoFinal = true; @@ -3010,9 +3020,6 @@ namespace AgroBase.Models motivoFinal = $"Corredor {idxCorredor + 1}: LIBERAÇÃO MANUAL (override). " + (string.IsNullOrEmpty(motivoBase) ? "Autonomia insuficiente, mas liberado." : motivoBase); motivosBloqueio.Add($"Corredor {idxCorredor + 1}: LIBERAÇÃO MANUAL. Autonomia insuficiente, mas houve liberação supervisionada."); - - - motivosBloqueio.Clear(); // Destrava o corredor (o operador assumiu) DestravarCorredoresAte(idxCorredor); diff --git a/AgroBase/AgroBase/Models/Variaveis.cs b/AgroBase/AgroBase/Models/Variaveis.cs index 4f38c4e8d..a59e65c9c 100644 --- a/AgroBase/AgroBase/Models/Variaveis.cs +++ b/AgroBase/AgroBase/Models/Variaveis.cs @@ -862,7 +862,7 @@ namespace AgroBase.Models public static double ComprimentoFrente { get; } = 7.0; // 7 public static double ComprimentoTras { get; } = 107.0; // 107 public static double DistanciaEntreEixos { get; } = 92.0; - public static double LeverArmFrontalCm { get; } = 100.0; // cm + public static double LeverArmFrontalCm { get; } = 37.0; // cm public static double LeverArmLateralCm { get; } = 0.0; // cm public static double LarguraEquipamentoMm { diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py index 4cc12e87d..be2b9a93b 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/atuador.py @@ -304,7 +304,10 @@ class ModuloAtuador(ModuloDiagnosticoBase): ) herbicida_ok_corredor = self._bool(corredor.get("herbicida_ok", True), True) - motivo_herbicida_corredor = corredor.get("motivo_hrb", "Herbicida insuficiente para o corredor") + motivo_herbicida_corredor = self._texto_ou_padrao( + corredor.get("motivo_hrb"), + padrao="Herbicida insuficiente para pulverizar o corredor completo." + ) bomba_principal = self._achar_por_label(bombas, "BMBLN") agitador = self._achar_por_label(bombas, "BMBAGT") @@ -443,18 +446,42 @@ class ModuloAtuador(ModuloDiagnosticoBase): if percent < percent_min: motivos.append(f"Nível de herbicida abaixo do mínimo ({percent:.1f}% < {percent_min:.1f}%)") - condicoes.append({ - "label": "Reservatório", - "valor": percent, - "severidade": 95, - "classe": "recurso_operacional", - "descricao": "Nível do reservatório de herbicida abaixo do limite mínimo", - "acoes": [ - "Reabastecer reservatório.", - "Recalibrar sensor de massa se o valor estiver incoerente.", - ], - }) - score = min(score, 65) + + herbicida_pode_bloquear = bool( + ctx["pulverizador_automatico"] and + ctx["operacao_iniciada"] and + not ctx["calibrando"] and + not ctx["finalizando"] and + not ctx["pausa"] and + not ctx["emergencia"] + ) + + if herbicida_pode_bloquear: + condicoes.append({ + "label": "Reservatório", + "valor": percent, + "severidade": 95, + "classe": "recurso_operacional", + "descricao": "Nível do reservatório de herbicida abaixo do limite mínimo", + "acoes": [ + "Reabastecer reservatório.", + "Recalibrar sensor de massa se o valor estiver incoerente.", + ], + }) + score = min(score, 65) + else: + condicoes.append({ + "label": "Reservatório", + "valor": percent, + "severidade": 35, + "classe": "recurso_operacional", + "descricao": "Nível do reservatório abaixo do mínimo, mas pulverização automática não está ativa; não bloqueia deslocamento.", + "acoes": [ + "Reabastecer antes de habilitar pulverização.", + "Recalibrar sensor de massa se o valor estiver incoerente.", + ], + }) + score = min(score, 90) elif percent < 20: motivos.append(f"Nível de herbicida baixo ({percent:.1f}%)") condicoes.append({ @@ -943,6 +970,15 @@ class ModuloAtuador(ModuloDiagnosticoBase): calibrando = ctx["calibrando"] bomba_principal = ctx["bomba_principal"] + herbicida_pode_bloquear = bool( + auto and + ctx["operacao_iniciada"] and + not calibrando and + not ctx["finalizando"] and + not ctx["pausa"] and + not ctx["emergencia"] + ) + em_transicao = self._pulverizacao_em_transicao(ctx) bomba_principal_on = self._bomba_principal_ligada_fisica(ctx) bomba_principal_cmd = self._bomba_principal_comandada(ctx) @@ -984,18 +1020,32 @@ class ModuloAtuador(ModuloDiagnosticoBase): motivos.append( f"Reservatório abaixo do mínimo ({ctx['percent_reservatorio']:.1f}% < {ctx['percent_min']:.1f}%)" ) - condicoes.append({ - "label": "Reservatório", - "valor": ctx["percent_reservatorio"], - "severidade": 95, - "classe": "recurso_operacional", - "descricao": "Nível de herbicida abaixo do mínimo operacional", - "acoes": [ - "Reabastecer reservatório.", - "Validar leitura do sensor de massa se o tanque não estiver baixo.", - ], - }) - score = min(score, 65) + + if herbicida_pode_bloquear: + condicoes.append({ + "label": "Reservatório", + "valor": ctx["percent_reservatorio"], + "severidade": 95, + "classe": "recurso_operacional", + "descricao": "Nível de herbicida abaixo do mínimo operacional", + "acoes": [ + "Reabastecer reservatório.", + "Validar leitura do sensor de massa se o tanque não estiver baixo.", + ], + }) + score = min(score, 65) + else: + condicoes.append({ + "label": "Reservatório", + "valor": ctx["percent_reservatorio"], + "severidade": 35, + "classe": "recurso_operacional", + "descricao": "Nível de herbicida abaixo do mínimo, mas pulverização automática não está ativa; não bloqueia deslocamento.", + "acoes": [ + "Reabastecer antes de pulverizar.", + ], + }) + score = min(score, 90) elif ctx["percent_reservatorio"] < 20: motivos.append(f"Reservatório baixo ({ctx['percent_reservatorio']:.1f}%)") @@ -1010,18 +1060,37 @@ class ModuloAtuador(ModuloDiagnosticoBase): score = min(score, 90) if not ctx["herbicida_ok_corredor"]: - motivos.append(ctx["motivo_herbicida_corredor"]) - condicoes.append({ - "label": "Autonomia de herbicida", - "valor": ctx["percent_reservatorio"], - "severidade": 90, - "classe": "recurso_operacional", - "descricao": ctx["motivo_herbicida_corredor"], - "acoes": [ - "Reabastecer ou reduzir distância do corredor planejado.", - ], - }) - score = min(score, 80) + motivo = self._texto_ou_padrao( + ctx.get("motivo_herbicida_corredor"), + padrao="Herbicida insuficiente para pulverizar o corredor completo." + ) + + motivos.append(motivo) + + if herbicida_pode_bloquear: + condicoes.append({ + "label": "Autonomia de herbicida", + "valor": ctx["percent_reservatorio"], + "severidade": 90, + "classe": "recurso_operacional", + "descricao": motivo, + "acoes": [ + "Reabastecer ou reduzir distância do corredor planejado.", + ], + }) + score = min(score, 80) + else: + condicoes.append({ + "label": "Autonomia de herbicida", + "valor": ctx["percent_reservatorio"], + "severidade": 35, + "classe": "recurso_operacional", + "descricao": f"{motivo} Pulverização automática desligada; condição informativa, sem bloqueio de deslocamento.", + "acoes": [ + "Reabastecer antes de habilitar a pulverização automática.", + ], + }) + score = min(score, 90) if ( (bicos_cmd or bicos_on) and @@ -1567,6 +1636,17 @@ class ModuloAtuador(ModuloDiagnosticoBase): not self._telemetria_depois_do_comando(dados) ) + def _texto_ou_padrao(self, *valores, padrao=""): + for valor in valores: + try: + texto = str(valor or "").strip() + if texto: + return texto + except Exception: + pass + + return str(padrao or "").strip() + @staticmethod def _bool(valor, default=False): diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/ponte_ip.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/ponte_ip.py index 51196c9be..fe95cb323 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/ponte_ip.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/ponte_ip.py @@ -1260,7 +1260,7 @@ class ModuloIPBribge(ModuloDiagnosticoBase): "degraded_restrictive_signal": degraded_restrictive_signal, } - def _elapsed_since(now_mono: float, started_mono: float) -> float: + def _elapsed_since(self, now_mono: float, started_mono: float) -> float: return max(0.0, now_mono - started_mono) if started_mono > 0 else 0.0 def _update_persistence_counters(self, new_ping_sample: bool, instant): diff --git a/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs b/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs index 756716ca9..ce8f73813 100644 --- a/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs +++ b/AgroBase/OperationControl/ViewModels/Windows/DockWindowViewModel.cs @@ -692,7 +692,7 @@ namespace OperationControl.ViewModels // ============================ System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { - _viewOperacaoTop?._vm.AtualizarStatus( + _viewOperacaoTop?._vm?.AtualizarStatus( statusVisual, rover.RoverId, obj?.Operacao?.Status ?? StatusOperacao.NaoIniciado, @@ -708,7 +708,7 @@ namespace OperationControl.ViewModels { System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { - _viewOperacaoTop?._vm.AtualizarStatus(status, titulo, StatusOperacao.Parametrizando, linha1, linha2.Replace("\n\n", " • "), status_str, resumo); + _viewOperacaoTop?._vm?.AtualizarStatus(status, titulo, StatusOperacao.Parametrizando, linha1, linha2.Replace("\n\n", " • "), status_str, resumo); })); }