adicionado modulo can no health worker
This commit is contained in:
parent
7f7ea84bd2
commit
cdbcb8f1d7
|
|
@ -0,0 +1,118 @@
|
||||||
|
import time
|
||||||
|
from shared.contexto_global_redis import ContextoGlobalRedis
|
||||||
|
from shared.enums import StatusModulo, T_Code
|
||||||
|
from health_worker.modulos.base import ModuloDiagnosticoBase
|
||||||
|
|
||||||
|
class ModuloCAN(ModuloDiagnosticoBase):
|
||||||
|
def __init__(self):
|
||||||
|
self.t_code = T_Code.Can
|
||||||
|
self.nome = "CAN"
|
||||||
|
self.timeout = 5
|
||||||
|
|
||||||
|
def atualizar_saude(self):
|
||||||
|
try:
|
||||||
|
now = time.perf_counter()
|
||||||
|
m = ContextoGlobalRedis.get_modulo(self.t_code) or {}
|
||||||
|
|
||||||
|
SAUDE_MIN_ALERTA = 80
|
||||||
|
PESO_POR_ERRO = 10 # cada erro pode pesar até 10%
|
||||||
|
PESO_MAX_ERROS = 40 # máximo 40% de penalização vinda só de erros críticos
|
||||||
|
JANELA_RESET_EC = 600.0 # 10 minutos
|
||||||
|
|
||||||
|
conectado = bool(m.get("conectado", False))
|
||||||
|
inicado = bool(m.get("iniciado", False))
|
||||||
|
executando = bool(m.get("executando", False))
|
||||||
|
erros_criticos = int(m.get("erros_criticos", 0))
|
||||||
|
|
||||||
|
# períodos-alvo (segundos) — se vier 0/None, usa fallback prudente
|
||||||
|
tb_tx = float(m.get("tempo_base_tx", 1.0)) or 1.0
|
||||||
|
tb_rx = float(m.get("tempo_base_rx", 1.0)) or 1.0
|
||||||
|
|
||||||
|
# timestamps monotônicos (segundos)
|
||||||
|
last_tx = float(m.get("last_tx", 0.0))
|
||||||
|
last_rx = float(m.get("last_rx", 0.0))
|
||||||
|
last_ec = float(m.get("last_ec", 0.0))
|
||||||
|
|
||||||
|
age_tx = max(0.0, now - last_tx)
|
||||||
|
age_rx = max(0.0, now - last_rx)
|
||||||
|
age_ec = max(0.0, now - last_ec)
|
||||||
|
|
||||||
|
# tempo-limite pra considerar "morto": 3 períodos ou 3s (o que for maior)
|
||||||
|
timeout_rx = max(30.0, 3.0 * tb_rx)
|
||||||
|
timeout_tx = max(30.0, 3.0 * tb_tx) # informativo (RX é vital)
|
||||||
|
|
||||||
|
saude = 100
|
||||||
|
motivos = []
|
||||||
|
|
||||||
|
if not conectado:
|
||||||
|
saude = 0
|
||||||
|
motivos.append("desconectado")
|
||||||
|
else:
|
||||||
|
if not inicado:
|
||||||
|
saude -= 50
|
||||||
|
motivos.append("não iniciado")
|
||||||
|
|
||||||
|
if executando:
|
||||||
|
# Penalização por atraso relativo ao período-alvo
|
||||||
|
# Ex.: se tb_rx=1s e age_rx=1.5s → atraso_rel=0.5 → penaliza 0.5*70=35%
|
||||||
|
atraso_rel_rx = max(0.0, (age_rx / tb_rx) - 1.0)
|
||||||
|
atraso_rel_tx = max(0.0, (age_tx / tb_tx) - 1.0)
|
||||||
|
|
||||||
|
p_rx = int(min(round(atraso_rel_rx * 60), 60)) # RX pesa mais (até 70%)
|
||||||
|
p_tx = int(min(round(atraso_rel_tx * 40), 40)) # TX pesa menos (até 40%)
|
||||||
|
|
||||||
|
if p_rx > 0:
|
||||||
|
saude -= p_rx
|
||||||
|
motivos.append(f"RX atrasado {age_rx:.2f}s (-{p_rx}%)")
|
||||||
|
if p_tx > 0:
|
||||||
|
saude -= p_tx
|
||||||
|
motivos.append(f"TX atrasado {age_tx:.2f}s (-{p_tx}%)")
|
||||||
|
|
||||||
|
if erros_criticos > 0 and age_ec <= JANELA_RESET_EC:
|
||||||
|
# penalidade base cresce com o número de erros, limitada pelo teto
|
||||||
|
penalidade_base = min(erros_criticos * PESO_POR_ERRO, PESO_MAX_ERROS)
|
||||||
|
|
||||||
|
# fator de recência: 1 se acabou de acontecer, 0 se está no limite da janela
|
||||||
|
fator_recencia = max(0.0, 1.0 - (age_ec / JANELA_RESET_EC))
|
||||||
|
|
||||||
|
p_ec = int(round(penalidade_base * fator_recencia))
|
||||||
|
|
||||||
|
if p_ec > 0:
|
||||||
|
saude -= p_ec
|
||||||
|
motivos.append(f"{erros_criticos} erros críticos, último há {age_ec:.0f}s (-{p_ec}%)")
|
||||||
|
|
||||||
|
saude = max(saude, 0)
|
||||||
|
|
||||||
|
status = StatusModulo.OPERANTE
|
||||||
|
if not conectado:
|
||||||
|
status = StatusModulo.DESCONECTADO
|
||||||
|
elif saude <= 0:
|
||||||
|
status = StatusModulo.FALHA
|
||||||
|
elif saude < SAUDE_MIN_ALERTA:
|
||||||
|
status = StatusModulo.ALERTA
|
||||||
|
|
||||||
|
payload = {
|
||||||
|
"conectado": conectado,
|
||||||
|
"status": status.value,
|
||||||
|
"saude": saude,
|
||||||
|
"motivos": motivos,
|
||||||
|
"saude_individual": [],
|
||||||
|
"condicoes_operacionais": [],
|
||||||
|
"detalhes": {
|
||||||
|
"age_rx_s": age_rx,
|
||||||
|
"age_tx_s": age_tx,
|
||||||
|
"age_ec_s": age_ec,
|
||||||
|
"timeout_rx_s": timeout_rx,
|
||||||
|
"timeout_tx_s": timeout_tx,
|
||||||
|
"periodo_alvo_rx_s": tb_rx,
|
||||||
|
"periodo_alvo_tx_s": tb_tx,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextoGlobalRedis.atualizar_ctx_dict(
|
||||||
|
ContextoGlobalRedis.ModKey(self.t_code),
|
||||||
|
saude=payload
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao atualizar saude do modulo {self.t_code.name}: {e}")
|
||||||
|
|
||||||
Loading…
Reference in New Issue