Workers atualizados

This commit is contained in:
Diego Freitas 2025-12-18 15:24:13 -03:00
parent b5ba765526
commit ff4e6116d6
4 changed files with 334 additions and 263 deletions

View File

@ -32,8 +32,15 @@ class ModuloAtuador(ModuloDiagnosticoBase):
sensor_massa_ativado = False sensor_massa_ativado = False
for tipo, sensores in dados_atu.get("sensores", {}).items(): sensores_ativos = dados_atu.get("sensores", {}).get("ativos", [])
for sensor_id, dados_sensor in sensores.items(): for key in sensores_ativos:
tipo, sensor_id = key.split(".")
sensores_tipo = dados_atu.get("sensores", {}).get(tipo, {})
dados_sensor = sensores_tipo.get(sensor_id)
if not dados_sensor:
continue
#for tipo, sensores in dados_atu.get("sensores", {}).items():
# for sensor_id, dados_sensor in sensores.items():
saude = 100 saude = 100
motivos = [] motivos = []
condicoes_operacionais = [] condicoes_operacionais = []
@ -41,9 +48,7 @@ class ModuloAtuador(ModuloDiagnosticoBase):
padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {}) padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {})
conectado = dados_sensor.get("conectado", False) conectado = dados_sensor.get("conectado", False)
mandatorio = dados_sensor.get("mandatorio", 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" and conectado and mandatorio and aferir: sensor_massa_ativado = True
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")
@ -91,8 +96,16 @@ class ModuloAtuador(ModuloDiagnosticoBase):
motivos_gerais.extend([f"{chave}: {m}" for m in motivos]) motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_sensor["saude"] = saude_mod dados_sensor["saude"] = saude_mod
for tipo, bicos in dados_atu.get("bicos", {}).items(): bicos_ativos = dados_atu.get("bicos", {}).get("ativos", [])
for bico_id, dados_bico in bicos.items(): for key in bicos_ativos:
tipo, bico_id = key.split(".")
bicos_tipo = dados_atu.get("bicos", {}).get(tipo, {})
dados_bico = bicos_tipo.get(bico_id)
if not dados_bico:
continue
#for tipo, bicos in dados_atu.get("bicos", {}).items():
# for bico_id, dados_bico in bicos.items():
saude = 100 saude = 100
motivos = [] motivos = []
condicoes_operacionais = [] condicoes_operacionais = []
@ -117,7 +130,6 @@ class ModuloAtuador(ModuloDiagnosticoBase):
saude -= penalidade saude -= penalidade
if (freq <= FREQ_MIN): if (freq <= FREQ_MIN):
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)") motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
atual = campo.get("atual") atual = campo.get("atual")
padrao = padroes.get(label) if atual else None padrao = padroes.get(label) if atual else None
if padrao is not None: if padrao is not None:
@ -147,8 +159,15 @@ class ModuloAtuador(ModuloDiagnosticoBase):
motivos_gerais.extend([f"{chave}: {m}" for m in motivos]) motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_bico["saude"] = saude_mod dados_bico["saude"] = saude_mod
for tipo, bombas in dados_atu.get("bombas", {}).items(): bombas_ativos = dados_atu.get("bombas", {}).get("ativos", [])
for bomba_id, dados_bomba in bombas.items(): for key in bombas_ativos:
tipo, bomba_id = key.split(".")
bombas_tipo = dados_atu.get("bombas", {}).get(tipo, {})
dados_bomba = bombas_tipo.get(bomba_id)
if not dados_bomba:
continue
#for tipo, bombas in dados_atu.get("bombas", {}).items():
# for bomba_id, dados_bomba in bombas.items():
saude = 100 saude = 100
motivos = [] motivos = []
condicoes_operacionais = [] condicoes_operacionais = []
@ -173,7 +192,6 @@ class ModuloAtuador(ModuloDiagnosticoBase):
saude -= penalidade saude -= penalidade
if (freq <= FREQ_MIN): if (freq <= FREQ_MIN):
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)") motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
atual = campo.get("atual") atual = campo.get("atual")
padrao = padroes.get(label) if atual else None padrao = padroes.get(label) if atual else None
if padrao is not None: if padrao is not None:
@ -203,6 +221,67 @@ class ModuloAtuador(ModuloDiagnosticoBase):
motivos_gerais.extend([f"{chave}: {m}" for m in motivos]) motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_bomba["saude"] = saude_mod dados_bomba["saude"] = saude_mod
servos_ativos = dados_atu.get("servos", {}).get("ativos", [])
for key in servos_ativos:
tipo, servo_id = key.split(".")
servos_tipo = dados_atu.get("servos", {}).get(tipo, {})
dados_servo = servos_tipo.get(servo_id)
if not dados_servo:
continue
#for servo_id, dados_servo in dados_atu.get("servos", {}).items():
saude = 100
motivos = []
condicoes_operacionais = []
controlar = dados_servo.get("controlar", False)
conectado = dados_servo.get("conectado", False)
mandatorio = dados_servo.get("mandatorio", False)
if not conectado:
saude = 0
motivos.append(f"desconectado")
else:
for dado in dados_servo.get("dados", {}):
label = dado.get("label")
if label is None:
continue
freq = dado.get("freq", 0.0)
if freq == 0:
saude = 0
motivos.append(f"{label} sem resposta (freq = 0 Hz)")
else:
penalidade = penalizar_frequencia(freq, FREQ_BASE, FREQ_MIN, (100 - SAUDE_MIN_ALERTA))
saude -= penalidade
if freq <= FREQ_MIN:
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
if label == "ServoAnguloLeitura":
angulo = dado.get("atual", 0.0)
angulo_sp = dados_servo.get("angulo_sp", 0.0)
erro = abs(angulo - angulo_sp)
if erro > 0:
condicoes_operacionais.append({
"valor": angulo,
"severidade": erro,
"descricao": f"{label} fora do padrão"
})
saude = max(0, saude)
chave = f"servo_{servo_id}"
saude_mod = {
"id": servo_id,
"label": dados_servo.get("label"),
"status": (StatusModulo.DESCONECTADO if not conectado else StatusModulo.OPERANTE if saude >= SAUDE_MIN_ALERTA else StatusModulo.ALERTA if saude > 0 else StatusModulo.FALHA).value,
"saude": saude,
"motivos": motivos,
"condicoes_operacionais": condicoes_operacionais,
"em_uso": controlar
}
saude_individual.append(saude_mod)
if mandatorio:
total_ativos += 1
saude_total += saude
motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_servo["saude"] = saude_mod
cond_op_mod = [] cond_op_mod = []
penalidade_percentual_herbicida = 0 penalidade_percentual_herbicida = 0
if sensor_massa_ativado: if sensor_massa_ativado:

View File

@ -15,20 +15,24 @@ class ModuloDirecional(ModuloDiagnosticoBase):
total_drivers_em_uso = 0 total_drivers_em_uso = 0
motivos_dos_ativos = [] motivos_dos_ativos = []
saude_individual = [] saude_individual = []
drivers_respondendo = []
SAUDE_MIN_ALERTA = 80 SAUDE_MIN_ALERTA = 80
ENDERECOS_DRIVERS = {1, 2, 3, 4}
mod_conectado = False mod_conectado = False
dados_dir = ContextoGlobalRedis.get_modulo(self.t_code) dados_dir = ContextoGlobalRedis.get_modulo(self.t_code)
for endereco_str, modulo in dados_dir.items(): ativos = dados_dir.get("ativos", [])
try: for endereco in ativos:
endereco = int(endereco_str) endereco = str(endereco) # Redis costuma serializar chave como string
except ValueError: modulo = dados_dir.get(endereco)
continue if not modulo:
drivers_respondendo.append(endereco) continue # ativo listado, mas sem dados (race condition)
#for endereco_str, modulo in dados_dir.items():
# try:
# endereco = int(endereco_str)
# except ValueError:
# continue
mod_id = modulo.get("mod_id") mod_id = modulo.get("mod_id")
#print(f"atualizando saude do modulo {mod_id} com endereco {endereco}") #print(f"atualizando saude do modulo {mod_id} com endereco {endereco}")
FREQ_BASE = modulo.get("freq_base", 1) FREQ_BASE = modulo.get("freq_base", 1)
@ -96,26 +100,6 @@ class ModuloDirecional(ModuloDiagnosticoBase):
if conectado: if conectado:
mod_conectado = True mod_conectado = True
# Verifica se algum driver esperado está ausente
drivers_esperados = ENDERECOS_DRIVERS
drivers_ausentes = drivers_esperados - set(drivers_respondendo)
for endereco in drivers_ausentes:
saude_individual.append({
"id": endereco,
"label": "",
"status": StatusModulo.DESCONECTADO.value,
"saude": 0,
"motivos": ["Nenhuma resposta recebida"],
"condicoes_operacionais": [{
"label": "",
"valor": 0,
"severidade": 100,
"descricao": f"Sem comunicacao"
}]
})
motivos_dos_ativos.append(f"Driver {endereco}: ausente (sem nenhuma mensagem recebida)")
saude_individual.sort(key=lambda x: x["id"]) saude_individual.sort(key=lambda x: x["id"])
saude_final = (saude_total // total_drivers_em_uso) if total_drivers_em_uso > 0 else 0 saude_final = (saude_total // total_drivers_em_uso) if total_drivers_em_uso > 0 else 0
@ -123,7 +107,7 @@ class ModuloDirecional(ModuloDiagnosticoBase):
status = StatusModulo.OPERANTE status = StatusModulo.OPERANTE
if not mod_conectado: if not mod_conectado:
status = StatusModulo.DESCONECTADO status = StatusModulo.DESCONECTADO
elif saude_final <= 0 or len(drivers_ausentes) > 0: elif saude_final <= 0:
status = StatusModulo.FALHA status = StatusModulo.FALHA
elif saude_final < SAUDE_MIN_ALERTA or any(saude["saude"] < SAUDE_MIN_ALERTA for saude in saude_individual): elif saude_final < SAUDE_MIN_ALERTA or any(saude["saude"] < SAUDE_MIN_ALERTA for saude in saude_individual):
status = StatusModulo.ALERTA status = StatusModulo.ALERTA

View File

@ -26,21 +26,24 @@ class ModuloMovimentacao(ModuloDiagnosticoBase):
total_drivers_em_uso = 0 total_drivers_em_uso = 0
motivos_dos_ativos = [] motivos_dos_ativos = []
saude_individual = [] saude_individual = []
drivers_respondendo = []
SAUDE_MIN_ALERTA = 80 SAUDE_MIN_ALERTA = 80
ENDERECOS_DRIVERS = {5, 6, 7, 8}
LIMITE_ERRO_RPM = 30 LIMITE_ERRO_RPM = 30
mod_conectado = False mod_conectado = False
dados_mov = ContextoGlobalRedis.get_modulo(self.t_code) dados_mov = ContextoGlobalRedis.get_modulo(self.t_code)
for endereco_str, modulo in dados_mov.items(): ativos = dados_mov.get("ativos", [])
try: for endereco in ativos:
endereco = int(endereco_str) endereco = str(endereco) # Redis costuma serializar chave como string
except ValueError: modulo = dados_mov.get(endereco)
continue if not modulo:
drivers_respondendo.append(endereco) continue # ativo listado, mas sem dados (race condition)
#for endereco_str, modulo in dados_mov.items():
# try:
# endereco = int(endereco_str)
# except ValueError:
# continue
mod_id = modulo.get("mod_id") mod_id = modulo.get("mod_id")
FREQ_BASE = modulo.get("freq_base", 1) FREQ_BASE = modulo.get("freq_base", 1)
FREQ_MIN = FREQ_BASE * 0.5 FREQ_MIN = FREQ_BASE * 0.5
@ -184,26 +187,6 @@ class ModuloMovimentacao(ModuloDiagnosticoBase):
if conectado: if conectado:
mod_conectado = True mod_conectado = True
# Verificação de ausência de drivers esperados
drivers_esperados = ENDERECOS_DRIVERS
drivers_ausentes = drivers_esperados - set(drivers_respondendo)
for endereco in drivers_ausentes:
saude_individual.append({
"id": endereco,
"label": "",
"status": StatusModulo.DESCONECTADO.value,
"saude": 0,
"motivos": ["Nenhuma resposta recebida"],
"condicoes_operacionais": [{
"label": "",
"valor": 0,
"severidade": 100,
"descricao": f"Sem comunicacao"
}]
})
motivos_dos_ativos.append(f"Driver {endereco}: ausente (sem nenhuma mensagem recebida)")
saude_individual.sort(key=lambda x: x["id"]) saude_individual.sort(key=lambda x: x["id"])
saude_final = (saude_total // total_drivers_em_uso) if total_drivers_em_uso > 0 else 0 saude_final = (saude_total // total_drivers_em_uso) if total_drivers_em_uso > 0 else 0
@ -211,7 +194,7 @@ class ModuloMovimentacao(ModuloDiagnosticoBase):
status = StatusModulo.OPERANTE status = StatusModulo.OPERANTE
if not mod_conectado: if not mod_conectado:
status = StatusModulo.DESCONECTADO status = StatusModulo.DESCONECTADO
elif saude_final <= 0 or len(drivers_ausentes) > 0: elif saude_final <= 0:
status = StatusModulo.FALHA status = StatusModulo.FALHA
elif saude_final < SAUDE_MIN_ALERTA or any(saude["saude"] < SAUDE_MIN_ALERTA for saude in saude_individual): elif saude_final < SAUDE_MIN_ALERTA or any(saude["saude"] < SAUDE_MIN_ALERTA for saude in saude_individual):
status = StatusModulo.ALERTA status = StatusModulo.ALERTA

View File

@ -31,8 +31,15 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
sensor_bateria_ativado = False sensor_bateria_ativado = False
for tipo, sensores in dados_sen.get("sensores", {}).items(): sensores_ativos = dados_sen.get("sensores", {}).get("ativos", [])
for sensor_id, dados_sensor in sensores.items(): for key in sensores_ativos:
tipo, sensor_id = key.split(".")
sensores_tipo = dados_sen.get("sensores", {}).get(tipo, {})
dados_sensor = sensores_tipo.get(sensor_id)
if not dados_sensor:
continue
#for tipo, sensores in dados_sen.get("sensores", {}).items():
# for sensor_id, dados_sensor in sensores.items():
saude = 100 saude = 100
motivos = [] motivos = []
condicoes_operacionais = [] condicoes_operacionais = []
@ -40,9 +47,7 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {}) padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {})
conectado = dados_sensor.get("conectado", False) conectado = dados_sensor.get("conectado", False)
mandatorio = dados_sensor.get("mandatorio", 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" and conectado and mandatorio and aferir: sensor_bateria_ativado = True
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")
@ -60,7 +65,6 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
saude -= penalidade saude -= penalidade
if (freq <= FREQ_MIN): if (freq <= FREQ_MIN):
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)") motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
atual = campo.get("atual") atual = campo.get("atual")
padrao = padroes.get(label) if atual else None padrao = padroes.get(label) if atual else None
if padrao is not None: if padrao is not None:
@ -90,7 +94,14 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
motivos_gerais.extend([f"{chave}: {m}" for m in motivos]) motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_sensor["saude"] = saude_mod dados_sensor["saude"] = saude_mod
for servo_id, dados_servo in dados_sen.get("servos", {}).items(): servos_ativos = dados_sen.get("servos", {}).get("ativos", [])
for key in servos_ativos:
tipo, servo_id = key.split(".")
servos_tipo = dados_sen.get("servos", {}).get(tipo, {})
dados_servo = servos_tipo.get(servo_id)
if not dados_servo:
continue
#for servo_id, dados_servo in dados_sen.get("servos", {}).items():
saude = 100 saude = 100
motivos = [] motivos = []
condicoes_operacionais = [] condicoes_operacionais = []
@ -143,7 +154,14 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
motivos_gerais.extend([f"{chave}: {m}" for m in motivos]) motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_servo["saude"] = saude_mod dados_servo["saude"] = saude_mod
for rele_id, dados_rele in dados_sen.get("reles", {}).items(): reles_ativos = dados_sen.get("reles", {}).get("ativos", [])
for key in reles_ativos:
tipo, rele_id = key.split(".")
reles_tipo = dados_sen.get("reles", {}).get(tipo, {})
dados_rele = reles_tipo.get(rele_id)
if not dados_rele:
continue
#for rele_id, dados_rele in dados_sen.get("reles", {}).items():
saude = 100 saude = 100
motivos = [] motivos = []
condicoes_operacionais = [] condicoes_operacionais = []
@ -186,7 +204,14 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
motivos_gerais.extend([f"{chave}: {m}" for m in motivos]) motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_rele["saude"] = saude_mod dados_rele["saude"] = saude_mod
for led_id, dados_led in dados_sen.get("sinaleiros", {}).items(): leds_ativos = dados_sen.get("sinaleiros", {}).get("ativos", [])
for key in leds_ativos:
tipo, led_id = key.split(".")
leds_tipo = dados_sen.get("sinaleiros", {}).get(tipo, {})
dados_led = leds_tipo.get(led_id)
if not dados_led:
continue
#for led_id, dados_led in dados_sen.get("sinaleiros", {}).items():
saude = 100 saude = 100
motivos = [] motivos = []
condicoes_operacionais = [] condicoes_operacionais = []