ajustado bloqueio da operacao por atuador quando pulverizador automatico estiver desligado, ajustado erro na saude do ipb

This commit is contained in:
Diego Freitas 2026-07-08 08:08:52 -03:00
parent bebb1f42c8
commit 86d2204153
5 changed files with 133 additions and 46 deletions

View File

@ -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);

View File

@ -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
{

View File

@ -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):

View File

@ -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):

View File

@ -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);
}));
}