Ajustes de regras no health worker, Sen, Atu, Bat, Trj, preenchido dinamicamente top bar do operation control
This commit is contained in:
parent
7398624ad7
commit
ffbd86d8a4
|
|
@ -2795,7 +2795,7 @@ namespace AgroBase.Models
|
|||
if (!Iniciado)
|
||||
{
|
||||
Liberado = true;
|
||||
Motivos.Add("Não iniciado");
|
||||
Motivos = new List<string>() { "Não iniciado" };
|
||||
Status = AutonomiaCorredorStatus.Desconhecido;
|
||||
return;
|
||||
}
|
||||
|
|
@ -2948,7 +2948,10 @@ 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 houver liberação supervisionada.");
|
||||
motivosBloqueio.Add($"Corredor {idxCorredor + 1}: LIBERAÇÃO MANUAL. Autonomia insuficiente, mas houve liberação supervisionada.");
|
||||
|
||||
|
||||
motivosBloqueio.Clear();
|
||||
|
||||
// Destrava o corredor (o operador assumiu)
|
||||
_corredoresTravados.Remove(idxCorredor);
|
||||
|
|
@ -3010,7 +3013,7 @@ namespace AgroBase.Models
|
|||
else
|
||||
{
|
||||
CorredoresLiberados.Add(idxCorredor, res);
|
||||
Variaveis.OperacaoEmAndamento.Sensoriamento.InserirLog(T_Code.Trj, liberadoFinal ? StatusModulo.Operante : StatusModulo.Alerta, liberadoFinal ? 100 : 0, $"Corredor {idxCorredor + 1} bloqueado por autonomia insuficiente");
|
||||
Variaveis.OperacaoEmAndamento.Sensoriamento.InserirLog(T_Code.Trj, liberadoFinal ? StatusModulo.Operante : StatusModulo.Alerta, liberadoFinal ? 100 : 0, $"{motivoFinal}");
|
||||
}
|
||||
|
||||
// Atualiza estado exposto
|
||||
|
|
|
|||
|
|
@ -532,8 +532,8 @@ namespace AgroBase.Models
|
|||
{ TipoMovimentoDirecional.MovimentoLateral, 90 },
|
||||
{ TipoMovimentoDirecional.Diagnostico, 25 },
|
||||
};
|
||||
public static double AnguloInclinacaoRollMax { get; set; } = 30.0;
|
||||
public static double AnguloInclinacaoPitchMax { get; set; } = 45.0;
|
||||
public static double AnguloInclinacaoRollMax { get; set; } = 30.0; // Frontal
|
||||
public static double AnguloInclinacaoPitchMax { get; set; } = 45.0; // Lateral
|
||||
public static string VozAlerta { get; set; } = "Microsoft Maria Desktop";
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -147,10 +147,11 @@ namespace AgroBase.Services.Operadores
|
|||
dist_dir = _t.DistanciaDireita,
|
||||
angulo = _t.AnguloMedioCorredor,
|
||||
pontos_restantes = _t.CorredorAtual.QtdPontos - pontoComparar.idxPontoCorredor,
|
||||
//liberado = _t.AutonomiaCooredor?.Liberado ?? false,
|
||||
//motivo = _t.AutonomiaCooredor?.Motivo ?? "",
|
||||
//bateria_ok = _t.AutonomiaCooredor?.BateriaSuficiente ?? false,
|
||||
//herbicida_ok = _t.AutonomiaCooredor?.HerbicidaSuficiente ?? false
|
||||
liberado = _t.AutonomiaCooredor?.Liberado ?? false,
|
||||
motivo_bat = _t.AutonomiaCooredor?.Motivos?.FirstOrDefault(x => x.Contains("Bateria")) ?? "",
|
||||
bateria_ok = _t.AutonomiaCooredor?.BateriaSuficiente ?? false,
|
||||
motivo_hrb = _t.AutonomiaCooredor?.Motivos?.FirstOrDefault(x => x.Contains("Herbicida")) ?? "",
|
||||
herbicida_ok = _t.AutonomiaCooredor?.HerbicidaSuficiente ?? false
|
||||
},
|
||||
} : null
|
||||
),
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ class ModuloAtuador(ModuloDiagnosticoBase):
|
|||
FREQ_MIN = FREQ_BASE * 0.5
|
||||
SAUDE_MIN_ALERTA = 80
|
||||
|
||||
sensor_massa_ativado = False
|
||||
sensor_massa_em_uso = False
|
||||
sensor_massa_conectado = False
|
||||
|
||||
sensores_ativos = dados_atu.get("sensores", {}).get("ativos", [])
|
||||
for key in sensores_ativos:
|
||||
|
|
@ -48,7 +49,9 @@ class ModuloAtuador(ModuloDiagnosticoBase):
|
|||
padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {})
|
||||
conectado = dados_sensor.get("conectado", False)
|
||||
mandatorio = dados_sensor.get("mandatorio", False)
|
||||
if dados_sensor.get("label") == "MASRS" and conectado and mandatorio and aferir: sensor_massa_ativado = True
|
||||
if dados_sensor.get("label") == "MASRS":
|
||||
sensor_massa_em_uso = mandatorio and aferir
|
||||
sensor_massa_conectado = conectado
|
||||
if not conectado:
|
||||
saude = 0
|
||||
motivos.append(f"desconectado")
|
||||
|
|
@ -284,39 +287,39 @@ class ModuloAtuador(ModuloDiagnosticoBase):
|
|||
|
||||
cond_op_mod = []
|
||||
penalidade_percentual_herbicida = 0
|
||||
if sensor_massa_ativado:
|
||||
_contexto = ContextoGlobalRedis.get_contexto()
|
||||
herbicida_suficiente_corredor = _contexto.get("Trajetoria", {}).get("CorredorAtual", {}).get("herbicida_ok", True)
|
||||
percent_atual = round(_contexto.get("Gerais", {}).get("percentual_reservatorio", 0.0), 2)
|
||||
percent_min = ContextoGlobalRedis.get_equipamento().get("percentual_reservatorio_min", 5.0)
|
||||
if percent_atual < percent_min:
|
||||
penalidade_percentual_herbicida = 50
|
||||
if sensor_massa_em_uso:
|
||||
if sensor_massa_conectado:
|
||||
_contexto = ContextoGlobalRedis.get_contexto()
|
||||
herbicida_suficiente_corredor = _contexto.get("Trajetoria", {}).get("CorredorAtual", {}).get("herbicida_ok", True)
|
||||
percent_atual = round(_contexto.get("Gerais", {}).get("percentual_reservatorio", 0.0), 2)
|
||||
percent_min = ContextoGlobalRedis.get_equipamento().get("percentual_reservatorio_min", 5.0)
|
||||
if percent_atual < percent_min:
|
||||
penalidade_percentual_herbicida = 50
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 100,
|
||||
"descricao": f"Nível do reservatório de herbicida abaixo do limite mínimo!"
|
||||
})
|
||||
elif percent_atual < 20.0:
|
||||
penalidade_percentual_herbicida = 21
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 30,
|
||||
"descricao": f"Nível do reservatório de herbicida baixo!"
|
||||
})
|
||||
if not herbicida_suficiente_corredor:
|
||||
_motivo_herb = _contexto.get("Trajetoria", {}).get("CorredorAtual", {}).get("motivo_hrb", "Herbicida insuficiente")
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 90,
|
||||
"descricao": _motivo_herb
|
||||
})
|
||||
else:
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"valor": 0,
|
||||
"severidade": 100,
|
||||
"descricao": f"Nível do reservatório de herbicida abaixo do limite mínimo!"
|
||||
"descricao": f"Sensor do nível do reservatório desconectado!"
|
||||
})
|
||||
elif percent_atual < 20.0:
|
||||
penalidade_percentual_herbicida = 21
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 30,
|
||||
"descricao": f"Nível do reservatório de herbicida baixo!"
|
||||
})
|
||||
if not herbicida_suficiente_corredor:
|
||||
penalidade_percentual_herbicida = 21
|
||||
_motivo_herb = _contexto.get("Trajetoria", {}).get("CorredorAtual", {}).get("motivo", "Herbicida insuficiente")
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 30,
|
||||
"descricao": _motivo_herb
|
||||
})
|
||||
else:
|
||||
cond_op_mod.append({
|
||||
"valor": 0,
|
||||
"severidade": 100,
|
||||
"descricao": f"Sensor do nível do reservatório desconectado!"
|
||||
})
|
||||
|
||||
saude_final = (saude_total // total_ativos) if total_ativos > 0 else 0
|
||||
saude_final = saude_final - penalidade_percentual_herbicida
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class ModuloBateria(ModuloDiagnosticoBase):
|
|||
delta_cells = v_max - v_min
|
||||
|
||||
# ------------ SCORES PARCIAIS ------------
|
||||
|
||||
|
||||
# 1) Score de comunicação / frescor
|
||||
if not dados:
|
||||
score_com = 0.0
|
||||
|
|
@ -73,20 +73,23 @@ class ModuloBateria(ModuloDiagnosticoBase):
|
|||
|
||||
# 2) Score de SOC
|
||||
if soc is None:
|
||||
score_soc = 60.0 # penaliza por não ter SOC
|
||||
score_soc = 10.0 # penaliza por não ter SOC
|
||||
motivos.append("SOC da bateria indisponível / não informado pelo BMS.")
|
||||
else:
|
||||
score_soc = 100.0
|
||||
percent_min = ContextoGlobalRedis.get_equipamento().get("percentual_tensao_bateria_min", 5.0)
|
||||
if soc <= 3:
|
||||
score_soc = 20.0
|
||||
score_soc = 10.0
|
||||
motivos.append(f"SOC crítico ({soc:.1f}%).")
|
||||
elif soc <= 10:
|
||||
score_soc = 40.0
|
||||
score_soc = 19.0
|
||||
motivos.append(f"SOC muito baixo ({soc:.1f}%).")
|
||||
elif soc <= 20:
|
||||
score_soc = 60.0
|
||||
score_soc = 40.0
|
||||
motivos.append(f"SOC baixo ({soc:.1f}%).")
|
||||
else:
|
||||
score_soc = 100.0
|
||||
if soc < percent_min:
|
||||
score_soc -= 15.0
|
||||
motivos.append(f"Nível da bateria abaixo do limite mínimo ({soc:.1f}/{percent_min:.1f}%)")
|
||||
|
||||
# 3) Score de desbalanceamento entre células
|
||||
if delta_cells is None:
|
||||
|
|
@ -165,7 +168,21 @@ class ModuloBateria(ModuloDiagnosticoBase):
|
|||
|
||||
# 1) SOC
|
||||
cond_soc = []
|
||||
if score_soc < SAUDE_MIN_ALERTA:
|
||||
_corredor_atual = ContextoGlobalRedis.get_contexto().get("Trajetoria", {}).get("CorredorAtual", {})
|
||||
bateria_suficiente_corredor = _corredor_atual.get("bateria_ok", True)
|
||||
if not bateria_suficiente_corredor:
|
||||
c = {
|
||||
"label": "Estado de carga (SOC)",
|
||||
"valor": soc if soc is not None else -1,
|
||||
"severidade": 100,
|
||||
"descricao": _corredor_atual.get("motivo_bat", "Bateria insuficiente"),
|
||||
"acoes": [
|
||||
"Trocar a bateria para retomar a operação em andamento."
|
||||
]
|
||||
}
|
||||
condicoes.append(c)
|
||||
cond_soc.append(c)
|
||||
if score_soc < 50:
|
||||
severidade = int(max(0, 100 - score_soc))
|
||||
c = {
|
||||
"label": "Estado de carga (SOC)",
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
|
|||
FREQ_MIN = FREQ_BASE * 0.5
|
||||
SAUDE_MIN_ALERTA = 80
|
||||
|
||||
bms_ligado = dados_sen.get("bms_ligado", False)
|
||||
sensor_bateria_ativado = False
|
||||
sensor_bateria_em_uso = False
|
||||
sensor_bateria_conectado = False
|
||||
|
||||
sensores_ativos = dados_sen.get("sensores", {}).get("ativos", [])
|
||||
for key in sensores_ativos:
|
||||
|
|
@ -50,7 +50,10 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
|
|||
padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {})
|
||||
conectado = dados_sensor.get("conectado", False)
|
||||
mandatorio = dados_sensor.get("mandatorio", False)
|
||||
if dados_sensor.get("label") == "AB36V" and conectado and mandatorio and aferir: sensor_bateria_ativado = True
|
||||
if dados_sensor.get("label") == "AB36V":
|
||||
bms_conetado = dados_sen.get("bms_ligado", False)
|
||||
sensor_bateria_em_uso = not bms_conetado and mandatorio and aferir
|
||||
sensor_bateria_conectado = conectado
|
||||
if not conectado:
|
||||
saude = 0
|
||||
motivos.append(f"desconectado")
|
||||
|
|
@ -272,33 +275,46 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
|
|||
|
||||
cond_op_mod = []
|
||||
penalidade_percentual_bateria = 0
|
||||
if not bms_ligado:
|
||||
if sensor_bateria_ativado:
|
||||
if sensor_bateria_em_uso:
|
||||
if sensor_bateria_conectado:
|
||||
_contexto = ContextoGlobalRedis.get_contexto()
|
||||
bateria_suficiente_corredor = _contexto.get("Trajetoria", {}).get("CorredorAtual", {}).get("bateria_ok", True)
|
||||
percent_atual = _contexto.get("Gerais", {}).get("percentual_bateria", 0.0)
|
||||
percent_min = ContextoGlobalRedis.get_equipamento().get("percentual_tensao_bateria_min", 5.0)
|
||||
if percent_atual < percent_min:
|
||||
penalidade_percentual_bateria = 70
|
||||
if percent_atual <= 3.0:
|
||||
penalidade_percentual_bateria = 90
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 100,
|
||||
"descricao": f"Nível da bateria abaixo do limite mínimo!"
|
||||
"descricao": f"SOC crítico ({percent_atual:.1f}%)!"
|
||||
})
|
||||
elif percent_atual < 25.0:
|
||||
penalidade_percentual_bateria = 25
|
||||
elif percent_atual <= 10.0:
|
||||
penalidade_percentual_bateria = 75
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 30,
|
||||
"descricao": f"Nível da bateria baixo!"
|
||||
"severidade": 90,
|
||||
"descricao": f"SOC muito baixo ({percent_atual:.1f}%)!"
|
||||
})
|
||||
elif percent_atual <= 20.0:
|
||||
penalidade_percentual_bateria = 30
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 50,
|
||||
"descricao": f"SOC baixo ({percent_atual:.1f}%)!"
|
||||
})
|
||||
if percent_atual < percent_min:
|
||||
penalidade_percentual_bateria += 20
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 100,
|
||||
"descricao": f"Nível da bateria abaixo do limite mínimo ({percent_atual:.1f}/{percent_min:.1f}%)"
|
||||
})
|
||||
if not bateria_suficiente_corredor:
|
||||
penalidade_percentual_bateria = 25
|
||||
_motivo_bat = _contexto.get("Trajetoria", {}).get("CorredorAtual", {}).get("motivo", "Bateria insuficiente")
|
||||
penalidade_percentual_bateria += 15
|
||||
cond_op_mod.append({
|
||||
"valor": percent_atual,
|
||||
"severidade": 30,
|
||||
"descricao": _motivo_bat
|
||||
"severidade": 100,
|
||||
"descricao": _contexto.get("Trajetoria", {}).get("CorredorAtual", {}).get("motivo_bat", "Bateria insuficiente")
|
||||
})
|
||||
else:
|
||||
cond_op_mod.append({
|
||||
|
|
|
|||
|
|
@ -12,23 +12,26 @@ class ModuloTrajetorira(ModuloDiagnosticoBase):
|
|||
try:
|
||||
m = ContextoGlobalRedis.get_modulo(self.t_code) or {}
|
||||
|
||||
SAUDE_MIN_ALERTA = 50
|
||||
SAUDE_MIN_ALERTA = 80
|
||||
|
||||
iniciado = bool(m.get("iniciado", False))
|
||||
liberado = bool(m.get("liberado", False))
|
||||
bateria_ok = bool(m.get("bateria_ok", False))
|
||||
herbicida_ok = bool(m.get("herbicida_ok", False))
|
||||
motivo = m.get("motivo", "")
|
||||
motivos = m.get("motivos", [])
|
||||
|
||||
saude = 100
|
||||
motivos = []
|
||||
|
||||
if iniciado:
|
||||
if not bateria_ok:
|
||||
saude -= 50
|
||||
saude -= 30
|
||||
if not herbicida_ok:
|
||||
saude -= 50
|
||||
motivos.append(motivo)
|
||||
saude -= 30
|
||||
if (not bateria_ok or not herbicida_ok) and liberado:
|
||||
saude += 15
|
||||
motivos.append(f"Realizada liberação supervisionada! Bateria {'OK' if bateria_ok else 'ALERTA'}, Herbicida {'OK' if herbicida_ok else 'ALERTA'}")
|
||||
else:
|
||||
motivos = []
|
||||
|
||||
saude = max(saude, 0)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
from .base import ProcessadorBase
|
||||
from manager_worker.processadores.padroes import comando_parado
|
||||
from manager_worker.modulos.regras_taticas import verifica_controle_liberado
|
||||
|
||||
class ProcessadorAguardando(ProcessadorBase):
|
||||
def processar(self):
|
||||
try:
|
||||
return comando_parado()
|
||||
motivos_parada = verifica_controle_liberado(ignorar_parada=True)
|
||||
return comando_parado(motivos=motivos_parada)
|
||||
except Exception as e:
|
||||
from manager_worker.config import mostrar_log
|
||||
mostrar_log(f"Erro no processador Aguardando: {e}")
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ class ContextoGlobalRedis:
|
|||
condicoes_operacionais = _saude.get("condicoes_operacionais", [])
|
||||
detalhes = _saude.get("detalhes")
|
||||
|
||||
tem_condicao_critica = any(cond.get("severidade") == 100 for cond in condicoes_operacionais)
|
||||
tem_condicao_critica = any(cond.get("severidade") >= 90 for cond in condicoes_operacionais)
|
||||
mod_mandatorio = t_code.value in modulos_mandatorios
|
||||
mod_operante = status in [StatusModulo.OPERANTE.value, StatusModulo.ALERTA.value]
|
||||
mod_inoperante = mod_mandatorio and tem_condicao_critica
|
||||
|
|
@ -252,7 +252,7 @@ class ContextoGlobalRedis:
|
|||
descricoes_criticas = [
|
||||
cond.get("descricao", "Condição crítica sem descrição")
|
||||
for cond in condicoes_operacionais
|
||||
if cond.get("severidade") == 100
|
||||
if cond.get("severidade") >= 90
|
||||
]
|
||||
# adiciona ao array de motivos
|
||||
motivos_dos_modulos_mandatorios.extend(descricoes_criticas)
|
||||
|
|
|
|||
|
|
@ -163,4 +163,14 @@ namespace OperationControl.ViewModels.Views.Operacao
|
|||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
|
||||
}
|
||||
}
|
||||
|
||||
public class MotivoTopBarModel
|
||||
{
|
||||
public int Prioridade { get; set; }
|
||||
public string Fonte { get; set; } = "";
|
||||
public string Titulo { get; set; } = "";
|
||||
public string Descricao { get; set; } = "";
|
||||
public StatusModulo StatusVisual { get; set; }
|
||||
public T_Code? Modulo { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -362,6 +362,219 @@ namespace OperationControl.ViewModels
|
|||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
|
||||
}
|
||||
|
||||
public void AtualizarBarraSuperior(OperacaoParametrosModel rover)
|
||||
{
|
||||
var obj = rover?.DadosLeitura;
|
||||
if (rover == null || obj == null)
|
||||
return;
|
||||
|
||||
var eventos = new List<MotivoTopBarModel>();
|
||||
|
||||
// ============================
|
||||
// 1) Emergência
|
||||
// ============================
|
||||
if (obj.Operacao?.Emergencia == true)
|
||||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 1000,
|
||||
Fonte = "Emergencia",
|
||||
Titulo = "OPERAÇÃO BLOQUEADA POR EMERGÊNCIA",
|
||||
Descricao = "Parada de emergência solicitada.",
|
||||
StatusVisual = StatusModulo.Falha
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 2) Pausa
|
||||
// ============================
|
||||
if (obj.Operacao?.Pausa == true)
|
||||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 900,
|
||||
Fonte = "Pausa",
|
||||
Titulo = "OPERAÇÃO PAUSADA",
|
||||
Descricao = "Pausa operacional solicitada.",
|
||||
StatusVisual = StatusModulo.Alerta
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 3) Controle
|
||||
// ============================
|
||||
var motivosControle = obj.Controle?.Motivos?
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.Distinct()
|
||||
.ToList() ?? new List<string>();
|
||||
|
||||
foreach (var motivo in motivosControle)
|
||||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 800,
|
||||
Fonte = "Controle",
|
||||
Titulo = "CONTROLE SEM LIBERAÇÃO",
|
||||
Descricao = motivo,
|
||||
StatusVisual = StatusModulo.Alerta
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 4) Trajetória / autonomia
|
||||
// ============================
|
||||
var motivosTrajetoria = obj.Trajetoria?.AutonomiaCorredor?.Motivos?
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.Distinct()
|
||||
.ToList() ?? new List<string>();
|
||||
|
||||
foreach (var motivo in motivosTrajetoria)
|
||||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 700,
|
||||
Fonte = "Trajetoria",
|
||||
Titulo = "TRAJETÓRIA BLOQUEADA",
|
||||
Descricao = motivo,
|
||||
StatusVisual = StatusModulo.Alerta
|
||||
});
|
||||
}
|
||||
|
||||
// ============================
|
||||
// 5) Módulos com condições operacionais críticas
|
||||
// ============================
|
||||
var modulosCriticos = obj.ModulosSaude?
|
||||
.Where(mod => mod?.condicoes_operacionais?.Any(cond => cond?.severidade > 90) ?? false)
|
||||
.ToList() ?? new List<AgroBase.Models.Operadores.ManagerWorkerMessageResponseModulosPendentesModel>();
|
||||
|
||||
foreach (var modulo in modulosCriticos)
|
||||
{
|
||||
var nomeModulo = (modulo?.modulo ?? T_Code.Vzo).ToString();
|
||||
|
||||
var descricoesCriticas = modulo?.condicoes_operacionais?
|
||||
.Where(cond => cond?.severidade > 90)
|
||||
.Select(cond => cond?.descricao ?? "")
|
||||
.Where(desc => !string.IsNullOrWhiteSpace(desc))
|
||||
.Distinct()
|
||||
.ToList() ?? new List<string>();
|
||||
|
||||
foreach (var desc in descricoesCriticas)
|
||||
{
|
||||
eventos.Add(new MotivoTopBarModel
|
||||
{
|
||||
Prioridade = 600,
|
||||
Fonte = "ModuloCritico",
|
||||
Titulo = "CONDIÇÕES OPERACIONAIS CRÍTICAS",
|
||||
Descricao = $"{nomeModulo}: {desc}",
|
||||
StatusVisual = StatusModulo.Alerta,
|
||||
Modulo = modulo?.modulo
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var ordemModulos = new Dictionary<T_Code, int>
|
||||
{
|
||||
{ T_Code.Ipb, 1 },
|
||||
{ T_Code.Npc, 2 },
|
||||
{ T_Code.Bat, 3 },
|
||||
{ T_Code.Atu, 4 },
|
||||
{ T_Code.Sen, 5 }
|
||||
};
|
||||
|
||||
// ============================
|
||||
// 6) Remove vazios / repetidos
|
||||
// ============================
|
||||
var eventosOrdenados = eventos
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Titulo) && !string.IsNullOrWhiteSpace(x.Descricao))
|
||||
.GroupBy(x => new { x.Fonte, x.Titulo, x.Descricao, x.Prioridade, x.StatusVisual })
|
||||
.Select(g => g.First())
|
||||
.OrderByDescending(x => x.Prioridade)
|
||||
.ThenBy(x => x.Modulo.HasValue && ordemModulos.ContainsKey(x.Modulo.Value)? ordemModulos[x.Modulo.Value] : int.MaxValue)
|
||||
.ThenBy(x => x.Fonte)
|
||||
.ToList();
|
||||
|
||||
// ============================
|
||||
// 7) Monta visual final
|
||||
// ============================
|
||||
StatusModulo statusVisual;
|
||||
string linha1;
|
||||
string linha2;
|
||||
string badge;
|
||||
string resumo;
|
||||
|
||||
if (eventosOrdenados.Any())
|
||||
{
|
||||
var principal = eventosOrdenados.First();
|
||||
|
||||
statusVisual = principal.StatusVisual;
|
||||
linha1 = principal.Titulo;
|
||||
|
||||
// Pega até 3 descrições distintas, por prioridade
|
||||
var descricoes = eventosOrdenados
|
||||
.Select(x => x.Descricao?.Trim())
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.Distinct()
|
||||
.Take(3)
|
||||
.ToList();
|
||||
|
||||
linha2 = string.Join(" • ", descricoes);
|
||||
|
||||
// Badge curto
|
||||
badge = principal.Fonte switch
|
||||
{
|
||||
"Emergencia" => "EMERGÊNCIA",
|
||||
"Pausa" => "PAUSADO",
|
||||
"Trajetoria" => "TRAJETÓRIA",
|
||||
"Controle" => "CONTROLE",
|
||||
"ModuloCritico" => "ALERTA",
|
||||
_ => statusVisual.ToString().ToUpper()
|
||||
};
|
||||
|
||||
// Resumo curto
|
||||
resumo = principal.Fonte switch
|
||||
{
|
||||
"Emergencia" => "Parada imediata",
|
||||
"Pausa" => "Aguardando retomada",
|
||||
"Trajetoria" => "Operação bloqueada",
|
||||
"Controle" => "Controle bloqueado",
|
||||
"ModuloCritico" => "Atenção operacional",
|
||||
_ => (obj.Operacao?.Status ?? StatusOperacao.NaoIniciado).ToString()
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
statusVisual = obj.StatusRover == StatusModulo.Desconectado
|
||||
? StatusModulo.Desconectado
|
||||
: StatusModulo.Operante;
|
||||
|
||||
linha1 = "ROVER OPERANDO NORMALMENTE";
|
||||
linha2 = "Trajetória, controle e operação em condição normal.";
|
||||
badge = statusVisual.ToString().ToUpper();
|
||||
resumo = (obj.Operacao?.Status ?? StatusOperacao.NaoIniciado).ToString();
|
||||
}
|
||||
|
||||
// Segurança extra: evita linha vazia
|
||||
if (string.IsNullOrWhiteSpace(linha2))
|
||||
linha2 = "Sem detalhes adicionais.";
|
||||
|
||||
Variaveis.MostrarLog($"LINHA 1: {linha1}");
|
||||
|
||||
// ============================
|
||||
// 8) Atualiza UI
|
||||
// ============================
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
_viewOperacaoTop?._vm.AtualizarStatus(
|
||||
statusVisual,
|
||||
rover.RoverId,
|
||||
linha1,
|
||||
linha2,
|
||||
badge,
|
||||
resumo
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
public void AtualizarBarraSuperior(StatusModulo status, string titulo, string linha1, string linha2, string status_str, string resumo)
|
||||
{
|
||||
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
|
||||
|
|
@ -546,9 +759,7 @@ namespace OperationControl.ViewModels
|
|||
|
||||
if (rover.RoverId != VariaveisControleOperacao.SelectedRoverId) return;
|
||||
|
||||
string motivos_trajetoria = string.Join("", obj.Trajetoria?.AutonomiaCorredor?.Motivos ?? new List<string>() { "Liberado" });
|
||||
string motivos_controle = string.Join("", obj.Controle?.Motivos ?? new List<string>() { "Liberado" });
|
||||
AtualizarBarraSuperior(obj.StatusRover, rover.RoverId, $"Trajetória: {motivos_trajetoria}", $"Controle: {motivos_controle}", obj.StatusRover.ToString(), (obj.Operacao?.Status ?? StatusOperacao.NaoIniciado).ToString());
|
||||
AtualizarBarraSuperior(rover);
|
||||
|
||||
// ESQUERDA
|
||||
var conexao = obj.ModulosSaude?.FirstOrDefault(x => x.modulo == T_Code.Ipb);
|
||||
|
|
@ -715,7 +926,7 @@ namespace OperationControl.ViewModels
|
|||
|
||||
AtualizarDadosMapa(VariaveisControleOperacao.RoverEmFoco);
|
||||
|
||||
AtualizarBarraSuperior(rover.Status, rover.NumeroSerie, "VISÃO GERAL", VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.ImpedimentoErro ?? "Sistema operante", rover.Status.ToString(), (VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Status ?? StatusOperacao.NaoIniciado).ToString());
|
||||
AtualizarBarraSuperior(VariaveisControleOperacao.RoverEmFoco);
|
||||
}
|
||||
}
|
||||
private void OnSecaoSelecionadaChanged(SecaoRightBar secao)
|
||||
|
|
|
|||
Loading…
Reference in New Issue