agrobot_base/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs

995 lines
51 KiB
C#

using AgroBase.Models;
using AgroBase.Models.Operadores;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static AgroBase.Models.Enums;
using static AgroBase.Models.Operadores.OperadoresModels;
namespace AgroBase.Services.Operadores
{
public class HealthWorkerService : IWorkerModel
{
public HealthWorkerModel DadosLeitura = new HealthWorkerModel();
public SaudeWorkerModel Saude { get; set; } = new SaudeWorkerModel();
public static List<ManagerWorkerMessageResponseModulosPendentesModel> ModulosSaude = new List<ManagerWorkerMessageResponseModulosPendentesModel>();
private bool DebugMode = true;
//private static bool AtualizandoRedis = false;
public void MostrarLog(string message, int limite = 500)
{
if (DebugMode)
{
Console.WriteLine($"[HealthWorker] {message.Substring(0, Math.Min(limite, message.Length))}{(message.Length > limite ? "..." : "")}");
}
}
public async Task<bool> IniciarProcessamento()
{
RedisService.Subscribe(CmdKey.HealthWorkerTx, RedisCallback);
DadosLeitura.IniciadoEm = DateTime.Now;
DadosLeitura.Iniciado = true;
bool pronto() => DadosLeitura.Pronto;
await FuncoesGlobais.AguardarCondicaoAsync(pronto, 5000);
if (pronto())
{
MostrarLog("Processamento iniciado com sucesso");
return true;
}
MostrarLog("Timeout ao iniciar script");
DadosLeitura.ReiniciarEstado();
return false;
}
public void RedisCallback(string mensagem)
{
try
{
var comando = JsonConvert.DeserializeObject<ComandoRedis>(mensagem);
var cmd = (HealthWorkerCommandType)comando.cmd;
//MostrarLog($"Comando recebido: cmd = {cmd.ToString()}");
switch (cmd)
{
case HealthWorkerCommandType.ScriptCarregado:
DadosLeitura.Pronto = true;
DadosLeitura.ProntoEm = DateTime.Now;
MostrarLog($"Comando recebido: cmd = {cmd.ToString()}");
break;
default:
MostrarLog($"Comando não reconhecido: {comando.cmd}");
break;
}
}
catch (Exception ex)
{
MostrarLog($"Erro ao deserializar resposta: {ex.Message}");
}
finally
{
DadosLeitura.UltimaMensagem = DateTime.Now;
}
}
public void AtualizarSaude()
{
try
{
Saude = OperadoresModels.AtualizarSaude(CtxKey.DadosHealthWorker);
}
catch (Exception ex)
{
Variaveis.MostrarLog($"[HealthWorkerService] Erro em AtualizarSaude: {ex.Message}");
}
}
private static void AtualizarDadosContextoLocal()
{
try
{
RedisService.AtualizarCampos(
CtxKey.DadosOperacao,
("debug_mode", Variaveis.DebugMode),
("iniciado", Variaveis.OperacaoEmAndamento.Iniciado),
("finalizando", Variaveis.OperacaoEmAndamento.Finalizando),
("calibrando", Variaveis.OperacaoEmAndamento.Calibrando),
("simulando", Variaveis.OperacaoEmAndamento.Simulando),
("emergencia", Variaveis.OperacaoEmAndamento.Emergencia),
("pausa", Variaveis.OperacaoEmAndamento.Pausa)
);
}
catch (Exception ex)
{
Variaveis.MostrarLog($"[HealthWorkerService] Erro em AtualizarDadosContextoLocal: {ex.Message}");
}
}
public static void AtualizarDadosContexto()
{
try
{
//if (AtualizandoRedis)
// return;
//AtualizandoRedis = true;
AtualizarDadosContextoLocal();
AtualizarDadosModulos();
AtualizarDadosControleOperacao();
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
if (_Sensoriamento == null)
{
//AtualizandoRedis = false;
return;
}
var _t = _Sensoriamento.Trajetoria;
PontoTrajetoriaModel pontoComparar = _t != null ? (_t.PontoAtual.Aproximando ? _t.PontoAtual : _t.ProximoPonto != null ? _t.ProximoPonto : _t.PontoAtual) : null;
int idx_p_alvo = _t != null ?
(pontoComparar.DistanciaAtual > 1.0 ? pontoComparar.idxPonto :
pontoComparar.idxPonto < _t.QtdPontos - 1 ? pontoComparar.idxPonto + 1 :
pontoComparar.idxPonto) : 0;
RedisService.AtualizarCampos(
CtxKey.DadosContexto,
("Trajetoria", _t != null ? new
{
status = (int)_t.StatusCarro,
concluido = _t.TrajetoriaConcluida,
manobrando = _t.ManobrandoEntreRuas,
erro_angular = _t.ErroOrientacaoAngularCombinado,
erro_angular_caminho = _t.ErroOrientacaoAngularCaminho,
erro_angular_proximo_ponto = _t.ErroOrientacaoAngularProximoPonto,
idx_proximo_ponto = _t.ProximoPonto.idxPonto,
idx_ponto_alvo = idx_p_alvo,
CorredorAtual = new
{
concluido = _t.CorredorAtual.Concluido,
dentro = _t.CorredorAtual.Dentro,
ultimo = _t.CorredorAtual.Ultimo,
largura = _t.CorredorAtual.Largura,
progresso = _t.CorredorAtual.Progresso,
dist_esq = _t.DistanciaEsquerda,
dist_dir = _t.DistanciaDireita,
angulo = _t.AnguloMedioCorredor,
pontos_restantes = _t.CorredorAtual.QtdPontos - pontoComparar.idxPontoCorredor,
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
),
("Gerais", new
{
velocidade_ms = Variaveis.OperacaoEmAndamento.Simulando ? FuncoesMatematicas.CalculaVelocidadeMsPercentual(Variaveis.OperacaoEmAndamento.Controle.RPM_SP) : _Sensoriamento.Movimentacao?.VelocidadeMedia ?? 0,
ervas_no_radar = _Sensoriamento.Atuador?.ErvasNoRadar ?? false,
percentual_ervas_no_radar = _Sensoriamento.Atuador?.PercentualErvasNoRadar ?? 0,
percentual_reservatorio = _Sensoriamento.Atuador?.PercentualReservatorio ?? 0,
percentual_bateria = _Sensoriamento.Bateria?.PercentualBateria ?? 0,
}
),
("Atuador", new
{
pressao_linha_regular = _Sensoriamento.Atuador?.PressaoLinha >= ((Variaveis.OperacaoEmAndamento.Parametros.Controle?.AtuPressaoLinha ?? 0) - 20),
pressao_linha = _Sensoriamento.Atuador?.PressaoLinha ?? 0,
potencia_bomba = _Sensoriamento.Atuador?.LeituraPotenciaBomba ?? 0,
estado_bomba = _Sensoriamento.Atuador?.LeituraComandoBomba ?? false,
tempo_bomba_atuada = _Sensoriamento.Atuador?.TempoBombaAtuada ?? 0,
bomba_cavitada = _Sensoriamento.Atuador?.BombaCavitada ?? false,
}
)
);
//AtualizandoRedis = false;
}
catch (Exception ex)
{
Variaveis.MostrarLog($"[HealthWorkerService] Erro em AtualizarDadosContexto: {ex.Message}");
}
}
private static void AtualizarDadosEquipamento()
{
try
{
RedisService.AtualizarCampos(
CtxKey.DadosEquipamento,
("base_ip", VariaveisEquipamento.Parametros.base_ip),
("base_porta_caminho", VariaveisEquipamento.Parametros.base_porta_caminho),
("base_porta_ervas", VariaveisEquipamento.Parametros.base_porta_ervas),
("serial_number", VariaveisEquipamento.Parametros.serial_number),
("pct_vel_min", VariaveisEquipamento.PercentualVelMin),
("largura", VariaveisEquipamento.LarguraEquipamentoMm / 1000.0),
("distancia_entre_eixos", VariaveisEquipamento.DistanciaEntreEixos / 100.0),
("qtd_bicos", VariaveisEquipamento.QuantidadeBicosPulverizadores),
("percentual_reservatorio_min", VariaveisEquipamento.PercentualReservatorioMin),
("percentual_tensao_bateria_min", VariaveisEquipamento.PercentualTensaoBateriaMin),
("camera_caminho_id", VariaveisEquipamento.Parametros.camera_caminhho_id ?? ""),
("camera_solo_id", VariaveisEquipamento.Parametros.camera_ervas_id?.FirstOrDefault() ?? ""),
("path_ia_model_ruas_seg", VersionamentoService.ArquivoModeloSegStreetDetector.CaminhoCompleto),
("path_ia_labelmap_ruas_seg", VersionamentoService.ArquivoLabelmapSegStreetDetector.CaminhoCompleto),
("path_ia_norm_stats_ruas_seg", VersionamentoService.ArquivoModeloNormstatsStreetDetector.CaminhoCompleto),
("ia_backbone_ruas_seg", "C:\\AgroBaseModels\\Backbones\\nvidia_mit_b0"),
("ia_mode_ruas", "dual_label"),
("path_ia_model_ruas_det", VersionamentoService.ArquivoModeloDetStreetDetector.CaminhoCompleto),
("path_ia_model_ervas", VersionamentoService.ArquivoModeloWeedDetector.CaminhoCompleto),
("path_ia_labelmap_ervas", VersionamentoService.ArquivoModeloLabelmapWeedDetector.CaminhoCompleto),
("path_ia_norm_stats_ervas", VersionamentoService.ArquivoModeloNormstatsWeedDetector.CaminhoCompleto),
("path_ia_module_params_ervas", VersionamentoService.ArquivoModeloModuleParamsWeedDetector.CaminhoCompleto),
("ia_backbone_ervas", "C:\\AgroBaseModels\\Backbones\\nvidia_mit_b1"),
("angulo_roll_max", VariaveisEquipamento.AnguloInclinacaoRollMax),
("angulo_pitch_max", VariaveisEquipamento.AnguloInclinacaoPitchMax),
("imu_roll_direita_sinal", 1),
("dir_angulo_direita_sinal", 1),
("imu_dir_roll_min_aux", 6.0),
("imu_dir_bias_attention_deg", 4.0),
("imu_dir_bias_risk_deg", 9.0)
);
}
catch (Exception ex)
{
Variaveis.MostrarLog($"[HealthWorkerService] Erro em AtualizarDadosEquipamento: {ex.Message}");
}
}
public static void AtualizarDadosOperacao(bool forcar = false)
{
try
{
//if (AtualizandoRedis && !forcar)
// return;
//while (AtualizandoRedis && forcar) {}
//AtualizandoRedis = true;
AtualizarDadosEquipamento();
if (Variaveis.OperacaoEmAndamento.DispMvd == null)
{
//AtualizandoRedis = false;
return;
}
var _Parametros = Variaveis.OperacaoEmAndamento.Parametros;
var pControle = _Parametros.Controle;
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
RedisService.AtualizarCampos(
CtxKey.DadosOperacao,
("configurado", true),
("modo", Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido),
("tempo_aguardar_inicio_operacao", Variaveis.OperacaoEmAndamento.TempoIniciarOperacao),
("modulos_mandatorios", _Parametros.ModulosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
("modulos_opcionais", _Parametros.ModulosMandatorios.Where(x => !x.Mandatorio && x.Utilizar).Select(x => (int)x.Dispositivo).ToArray()),
("parametros_mandatorios", _Parametros.ParametrosMandatorios.Where(x => x.Mandatorio && x.Utilizar).Select(x => (int)x.Parametro).ToArray()),
("ponto_mapa_ref", Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?.Select(p => new double[] { p.Posicao.Latitude, p.Posicao.Longitude }).FirstOrDefault()),
("Mov", new
{
percent_vel_max = pControle.MovVelocidadeSErvasPercent,
percent_vel_min = pControle.MovVelocidadeCErvasPercent,
}
),
("Dir", new
{
angulo_max = pControle.DirAnguloMaximo,
vel_movimento = pControle.DirVelocidadeMovimento,
tipo_controle = (int)pControle.DirTipoMovimento,
mpc = new
{
pontos = Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?
.Select(p => new
{
lat = p.Posicao.Latitude,
lon = p.Posicao.Longitude,
tipo = (int)p.Tipo,
distanciaMargem = p.LarguraCorredor * 0.8
})
.ToList(),
angulo_max_graus = pControle.DirAnguloMaximo,
velocidade_min = Math.Round(FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeCErvasPercent), 4),
velocidade_max = Math.Round(FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeSErvasPercent), 4),
tempo_entre_comandos = (Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == Enums.T_Code.Dir)?.DelayEnvioComando ?? 500) / 1000.0,
horizonte = pControle.MpcHorizonte,
passos_atraso = 1,
}
}
),
("Atu", new
{
qtd_bicos = _Parametros.QtdBicos,
tempo_atuacao = pControle.AtuDuracaoAtuacao,
capacidade_reservatorio = _Parametros.CapacidadeReservatorio,
percent_vertical_deteccao = pControle.AtuPercentualInicioPulverizacao / 100.0,
height_area_deteccao = pControle.AtuAlturaAreaPulverizacao / 100.0,
pct_erva_bico_on = pControle.AtuPercentualErvasBicoOn / 100.0,
pct_erva_bico_off = pControle.AtuPercentualErvasBicoOff / 100.0
}
),
("Snr", new
{
percentual_altura_solo = CameraWorkerService.CameraCaminho?.PercentualAlturaSolo ?? 0.1,
distancia_maxima = CameraWorkerService.CameraCaminho?.DistanciaMaximaVisao ?? 5000,
distancia_minima = CameraWorkerService.CameraCaminho?.DistanciaMinimaVisao ?? 300
}
)
);
if ((Variaveis.OperacaoEmAndamento.Parametros?.ControleAutomatico ?? false) && (Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?.Any() ?? false))
{
var comando = new
{
cmd = HealthWorkerCommandType.AtualizarPontosMapa
};
RedisService.Publish(CmdKey.HealthWorkerRx, JsonConvert.SerializeObject(comando));
}
//Console.WriteLine("Dados de operacao atualizados com sucesso!");
//AtualizandoRedis = false;
}
catch (Exception ex)
{
Variaveis.MostrarLog($"[HealthWorkerService] Erro em AtualizarDadosOperacao: {ex.Message}");
}
}
public static void AtualizarDadosControleOperacao()
{
try
{
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
if (pControle == null)
return;
RedisService.AtualizarCampos(
CtxKey.DadosControle,
("pulverizador_automatico", pControle.PulverizadorAutomatico),
("movimento_automatico", pControle.MovimentoAutomatico),
("direcional_automatico", pControle.DirecionalAutomatico),
("frenagem_automatica", pControle.FrenagemAutomaticaAoParar),
("oak_parada_por_bloqueio", pControle.OakParadaPorObstaculo),
("imu_parada_por_inclinacao", pControle.ImuParadaPorInclinacao),
("imu_auxilio_movimento", pControle.ImuAuxilioMovimento),
("imu_auxilio_direcional", pControle.ImuAuxilioDirecional),
("imu_direcional_preferir_arco", pControle.ImuDirecionalPreferirArco),
("dir_auxilio_sonar", pControle.DirAuxilioSonar),
("mov_auxilio_sonar", pControle.MovAuxilioSonar),
("pressao_linha", pControle.AtuPressaoLinha),
("registrar_dados_pos_processamento", pControle.RegistrarDadosPosProcessamento)
);
}
catch (Exception ex)
{
Variaveis.MostrarLog($"[HealthWorkerService] Erro em AtualizarDadosControleOperacao: {ex.Message}");
}
}
private static void AtualizarDadosModulos()
{
try
{
if (Variaveis.OperacaoEmAndamento.DispMvd == null) return;
if (Variaveis.OperacaoEmAndamento.DispAtu == null) return;
if (Variaveis.OperacaoEmAndamento.DispSen == null) return;
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
var agora = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
//Console.WriteLine(RedisService.Get(RedisService.ModKey(Enums.T_Code.Gps)));
//Console.WriteLine(RedisService.Get(RedisService.ModKey(Enums.T_Code.Dir)));
//Console.WriteLine(RedisService.Get(RedisService.ModKey(Enums.T_Code.Mov)));
//Console.WriteLine(RedisService.Get(RedisService.ModKey(Enums.T_Code.Sen)));
//RedisService.SetObject(RedisService.ModKey(Enums.T_Code.Gps), string.Empty);
//RedisService.SetObject(RedisService.ModKey(Enums.T_Code.Dir), string.Empty);
//RedisService.SetObject(RedisService.ModKey(Enums.T_Code.Mov), string.Empty);
//RedisService.SetObject(RedisService.ModKey(Enums.T_Code.Sen), string.Empty);
var dirAtivos = new List<int>();
var movAtivos = new List<int>();
foreach (var mod in Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos)
{
int endereco_dir = mod.DirMotor._EnderecoCAN_Tx;
RedisService.AtualizarCampos(
RedisService.ModKey(Enums.T_Code.Dir),
($"{endereco_dir}.timestamp", agora),
($"{endereco_dir}.conectado", mod.DirMotor.Inicializado),
($"{endereco_dir}.freq_base", Variaveis.OperacaoEmAndamento.DispMvd.Dados.tmrRegistradorDIR.IntervalHz),
($"{endereco_dir}.endereco", mod.DirMotor._EnderecoCAN_Tx),
($"{endereco_dir}.mod_id", mod.Modulo_ID),
($"{endereco_dir}.angulo", mod.DirMotor.AnguloLeitura),
($"{endereco_dir}.angulo_sp", mod.DirMotor.Angulo_SP),
($"{endereco_dir}.comandar", mod.DirMotor.Comandar),
($"{endereco_dir}.referenciado", mod.DirMotor.Referenciado),
($"{endereco_dir}.in1_atuado", mod.DirMotor.IN1_Atuado),
($"{endereco_dir}.sentido", mod.DirMotor.Sentido),
($"{endereco_dir}.sentido_sp", mod.DirMotor.Sentido_SP),
($"{endereco_dir}.sentido_real", mod.DirMotor.SentidoReal),
($"{endereco_dir}.freq.pulsos", mod.DirMotor.Leitura?.NumeroPulsos?.frequencia ?? 0),
($"{endereco_dir}.freq.io", mod.DirMotor.Leitura?.EntradaIN1?.frequencia ?? 0)
);
int endereco_mov = mod.MovMotor._EnderecoCAN_Tx;
var camposMov = new List<(string campo, object valor)>
{
($"{endereco_mov}.timestamp", agora),
($"{endereco_mov}.conectado", mod.MovMotor.Inicializado),
// legado
($"{endereco_mov}.freq_base",
OIDCanService.ObterFreqBaseHz(
OIDCanService.OidHandler.OidParametros.VelocidadeAtual
)),
($"{endereco_mov}.endereco", mod.MovMotor._EnderecoCAN_Tx),
($"{endereco_mov}.mod_id", mod.Modulo_ID),
($"{endereco_mov}.cod_erro", mod.MovMotor.CodigoAlarme),
($"{endereco_mov}.rpm", mod.MovMotor.RPM_Roda),
($"{endereco_mov}.rpm_sp", mod.MovMotor.RPM_SP_Leitura),
($"{endereco_mov}.tensao", mod.MovMotor.Tensao),
($"{endereco_mov}.corrente_motor", mod.MovMotor.Corrente_Motor),
($"{endereco_mov}.corrente_barramento", mod.MovMotor.Corrente_Barramento),
($"{endereco_mov}.temperatura_driver", mod.MovMotor.TemperaturaDriver),
($"{endereco_mov}.temperatura_motor", mod.MovMotor.Temperatura),
($"{endereco_mov}.freado", mod.MovMotor.Leitura?.Freado ?? false),
($"{endereco_mov}.freq.erro", mod.MovMotor.Leitura?.CodigoAlarme?.frequencia ?? 0),
($"{endereco_mov}.freq.rpm", mod.MovMotor.Leitura?.ERPM?.frequencia ?? 0),
($"{endereco_mov}.freq.tensao", mod.MovMotor.Leitura?.Tensao?.frequencia ?? 0),
($"{endereco_mov}.freq.corrente_motor", mod.MovMotor.Leitura?.CorrenteMotor?.frequencia ?? 0),
($"{endereco_mov}.freq.corrente_barramento", mod.MovMotor.Leitura?.CorrenteBarramento?.frequencia ?? 0),
($"{endereco_mov}.freq.temperatura", mod.MovMotor.Leitura?.Temperatura?.frequencia ?? 0),
($"{endereco_mov}.freq.ciclo_trabalho", mod.MovMotor.Leitura?.CicloTrabalho?.frequencia ?? 0),
($"{endereco_mov}.freq.potencia", mod.MovMotor.Leitura?.Potencia?.frequencia ?? 0),
};
camposMov.AddRange(OIDCanService.GerarCamposRedisHealthBase(endereco_mov));
RedisService.AtualizarCampos(
RedisService.ModKey(Enums.T_Code.Mov),
camposMov.ToArray()
);
dirAtivos.Add(endereco_dir);
movAtivos.Add(endereco_mov);
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Dir), ($"ativos", dirAtivos.ToList()));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Mov), ($"ativos", movAtivos.ToList()));
var DadosSen = Variaveis.OperacaoEmAndamento.DispSen.Dados;
//Console.WriteLine("[HEALTH SEN] " + DadosSen.Conectado);
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen),
("timestamp", agora),
("conectado", DadosSen.Conectado),
("freq_base", DadosSen.FrequenciaBase),
("bms_ligado", _Sensoriamento.Bateria?.BmsLigado ?? false)
);
var senSensoresAtualizados = new List<(string caminho, object valor)>();
var senSensoresAtivos = new List<string>();
foreach (var sensor in DadosSen.Sensores)
{
int tipo = (int)sensor.Componente;
int id = sensor.ID_Num;
string basePath = $"sensores.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Sen), $"{basePath}.saude");
var dados = sensor.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
nominal = y.nominal,
maximo = y.maximo,
minimo = y.minimo,
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var sensorObj = new
{
conectado = sensor.Inicializado,
id,
label = sensor.ID,
tipo,
aferir = sensor.Aferir,
mandatorio = sensor.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
senSensoresAtivos.Add($"{tipo}.{id}");
senSensoresAtualizados.Add(($"{basePath}", sensorObj));
}
senSensoresAtualizados.Add(("sensores.ativos", senSensoresAtivos));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen), senSensoresAtualizados.ToArray());
var senServosAtualizados = new List<(string caminho, object valor)>();
var senServosAtivos = new List<string>();
foreach (var servo in DadosSen.Servos)
{
int tipo = (int)servo.Componente;
int id = servo.ID_Num;
string basePath = $"servos.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Sen), $"{basePath}.saude");
var dados = servo.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var servoObj = new
{
conectado = servo.Inicializado,
id,
label = servo.ID,
tipo,
controlar = servo.Controlar,
mandatorio = servo.Mandatorio,
angulo_sp = servo._AnguloControle,
dados,
timestamp = agora,
saude = saude ?? new { }
};
senServosAtivos.Add($"{tipo}.{id}");
senServosAtualizados.Add(($"{basePath}", servoObj));
}
senServosAtualizados.Add(("servos.ativos", senServosAtivos));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen), senServosAtualizados.ToArray());
var senRelesAtualizados = new List<(string caminho, object valor)>();
var senRelesAtivos = new List<string>();
foreach (var rele in DadosSen.Reles)
{
int tipo = (int)rele.Componente;
int id = rele.ID_Num;
string basePath = $"reles.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Sen), $"{basePath}.saude");
var dados = rele.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var releObj = new
{
conectado = rele.Inicializado,
id,
label = rele.ID,
tipo,
controlar = rele.Controlar,
mandatorio = rele.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
senRelesAtivos.Add($"{tipo}.{id}");
senRelesAtualizados.Add(($"{basePath}", releObj));
}
senRelesAtualizados.Add(("reles.ativos", senRelesAtivos));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen), senRelesAtualizados.ToArray());
var senLedsAtualizados = new List<(string caminho, object valor)>();
var senLedsAtivos = new List<string>();
foreach (var led in DadosSen.Sinaleiros)
{
int tipo = (int)led.Componente;
int id = led.ID_Num;
string basePath = $"sinaleiros.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Sen), $"{basePath}.saude");
var dados = led.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var ledObj = new
{
conectado = led.Inicializado,
id,
label = led.ID,
tipo,
controlar = led.Controlar,
mandatorio = led.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
senLedsAtivos.Add($"{tipo}.{id}");
senLedsAtualizados.Add(($"{basePath}", ledObj));
}
senLedsAtualizados.Add(("sinaleiros.ativos", senLedsAtivos));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen), senLedsAtualizados.ToArray());
var DadosAtu = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu),
("timestamp", agora),
("conectado", DadosAtu.Conectado),
("freq_base", DadosAtu.FrequenciaBase)
);
var atuSensoresAtualizados = new List<(string caminho, object valor)>();
var atuSensoresAtivos = new List<string>();
foreach (var sensor in DadosAtu.Sensores)
{
int tipo = (int)sensor.Componente;
int id = sensor.ID_Num;
string basePath = $"sensores.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Atu), $"{basePath}.saude");
var dados = sensor.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
nominal = y.nominal,
maximo = y.maximo,
minimo = y.minimo,
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var sensorObj = new
{
conectado = sensor.Inicializado,
id,
label = sensor.ID,
tipo,
aferir = sensor.Aferir,
mandatorio = sensor.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
atuSensoresAtivos.Add($"{tipo}.{id}");
atuSensoresAtualizados.Add(($"{basePath}", sensorObj));
}
atuSensoresAtualizados.Add(("sensores.ativos", atuSensoresAtivos));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), atuSensoresAtualizados.ToArray());
var atuBicosAtualizados = new List<(string caminho, object valor)>();
var atuBicosAtivos = new List<string>();
foreach (var bico in DadosAtu.BicosPulverizadores)
{
int tipo = (int)bico.Componente;
int id = bico.ID_Num;
string basePath = $"bicos.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Atu), $"{basePath}.saude");
var dados = bico.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
nominal = y.nominal,
maximo = y.maximo,
minimo = y.minimo,
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var bicoObj = new
{
conectado = bico.Inicializado,
id,
label = bico.ID,
tipo,
comandar = bico.Comandar,
mandatorio = bico.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
atuBicosAtualizados.Add(($"{basePath}", bicoObj));
atuBicosAtivos.Add($"{tipo}.{id}");
}
atuBicosAtualizados.Add(("bicos.ativos", atuBicosAtivos));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), atuBicosAtualizados.ToArray());
var atuBombasAtualizados = new List<(string caminho, object valor)>();
var atuBombasAtivos = new List<string>();
foreach (var bomba in DadosAtu.BombasPressurizadoras)
{
int tipo = (int)bomba.Componente;
int id = bomba.ID_Num;
string basePath = $"bombas.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Atu), $"{basePath}.saude");
var dados = bomba.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
nominal = y.nominal,
maximo = y.maximo,
minimo = y.minimo,
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var sensorObj = new
{
conectado = bomba.Inicializado,
id,
label = bomba.ID,
tipo,
comandar = bomba.Comandar,
mandatorio = bomba.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
atuBombasAtivos.Add($"{tipo}.{id}");
atuBombasAtualizados.Add(($"{basePath}", sensorObj));
}
atuBombasAtualizados.Add(("bombas.ativos", atuBombasAtivos));
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), atuBombasAtualizados.ToArray());
var DadosLra = Variaveis.LoraService;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Lra),
("timestamp", agora),
("conectado", DadosLra.Conectado),
("configurado", DadosLra.Configurado),
("tempo_base_tx", DadosLra.TempoEnvioDadosBase / 1000.0),
("tempo_base_rx", VariaveisEquipamento.TempoEntrePingsConexao / 1000.0),
("last_tx", DadosLra.UltimoTxDados),
("last_rx", DadosLra.UltimoRxDados)
);
var DadosMod = _Sensoriamento.DadosPerformance;
RedisService.AtualizarCampos(
RedisService.ModKey(Enums.T_Code.Npc),
// Base / sincronismo
("timestamp", agora),
("timestamp_unix_ms", DadosMod.TimestampUnixMs),
("freq_base", 1.0 / Variaveis.OperacaoEmAndamento.tmrLeiturasInterval),
// CPU
("cpu_load_percent", DadosMod.CPU_load_percent ?? 0),
("cpu_temp_package_c", DadosMod.CPU_temp_package_c ?? 0),
("cpu_power_package_w", DadosMod.CPU_power_package_w ?? 0),
("cpu_power_cores_w", DadosMod.CPU_power_cores_w ?? 0),
("cpu_power_graphics_w", DadosMod.CPU_power_graphics_w ?? 0),
("cpu_power_dram_w", DadosMod.CPU_power_dram_w ?? 0),
("cpu_clock_avg_mhz", DadosMod.CPU_clock_avg_mhz ?? 0),
("cpu_clock_max_mhz", DadosMod.CPU_clock_max_mhz ?? 0),
("cpu_bus_speed_mhz", DadosMod.CPU_bus_speed_mhz ?? 0),
// RAM
("ram_usage_percent", DadosMod.RAM_usage_percent ?? 0),
("ram_used_gb", DadosMod.RAM_used_gb ?? 0),
("ram_available_gb", DadosMod.RAM_available_gb ?? 0),
("ram_total_gb", DadosMod.RAM_total_gb ?? 0),
// GPU loads
("gpu_load_percent", DadosMod.GPU_load_percent ?? 0),
("gpu_core_load_percent", DadosMod.GPU_core_load_percent ?? 0),
("gpu_frame_buffer_load_percent", DadosMod.GPU_frame_buffer_load_percent ?? 0),
("gpu_memory_load_percent", DadosMod.GPU_memory_load_percent ?? 0),
("gpu_video_engine_load_percent", DadosMod.GPU_video_engine_load_percent ?? 0),
("gpu_bus_interface_load_percent", DadosMod.GPU_bus_interface_load_percent ?? 0),
// GPU térmico / energia / clock
("gpu_temp_core_c", DadosMod.GPU_temp_core_c ?? 0),
("gpu_power_w", DadosMod.GPU_power_w ?? 0),
("gpu_core_clock_mhz", DadosMod.GPU_core_clock_mhz ?? 0),
("gpu_memory_clock_mhz", DadosMod.GPU_memory_clock_mhz ?? 0),
("gpu_shader_clock_mhz", DadosMod.GPU_shader_clock_mhz ?? 0),
// GPU fan / PCIe
("gpu_fan_percent", DadosMod.GPU_fan_percent ?? 0),
("gpu_fan_rpm", DadosMod.GPU_fan_rpm ?? 0),
("gpu_pcie_rx", DadosMod.GPU_pcie_rx ?? 0),
("gpu_pcie_tx", DadosMod.GPU_pcie_tx ?? 0),
// VRAM
("gpu_vram_total_mb", DadosMod.GPU_vram_total_mb ?? 0),
("gpu_vram_used_mb", DadosMod.GPU_vram_used_mb ?? 0),
("gpu_vram_free_mb", DadosMod.GPU_vram_free_mb ?? 0),
("gpu_vram_used_percent", DadosMod.GPU_vram_used_percent ?? 0),
// Disco
("disk_used_space_percent", DadosMod.Disk_used_space_percent ?? 0),
// Processo C#
("process_thread_count", DadosMod.Process_thread_count),
("process_working_set_mb", DadosMod.Process_working_set_mb),
("process_private_memory_mb", DadosMod.Process_private_memory_mb),
("process_virtual_memory_mb", DadosMod.Process_virtual_memory_mb),
("process_cpu_time_total_s", DadosMod.Process_cpu_time_total_s),
// ThreadPool
("threadpool_available_worker_threads", DadosMod.ThreadPool_available_worker_threads),
("threadpool_available_completion_port_threads", DadosMod.ThreadPool_available_completion_port_threads),
("threadpool_max_worker_threads", DadosMod.ThreadPool_max_worker_threads),
("threadpool_max_completion_port_threads", DadosMod.ThreadPool_max_completion_port_threads),
("threadpool_used_worker_threads", DadosMod.ThreadPool_used_worker_threads),
("threadpool_used_completion_port_threads", DadosMod.ThreadPool_used_completion_port_threads),
("threadpool_used_worker_percent", DadosMod.ThreadPool_used_worker_percent),
("threadpool_used_completion_port_percent", DadosMod.ThreadPool_used_completion_port_percent)
);
var DadosCan = CanManager.CanService;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Can),
("timestamp", agora),
// Estado básico
("conectado", DadosCan.IsConnected),
("iniciado", DadosCan.Iniciado),
("executando", SerialService.DispositivosMapeados.Any(x => SerialService.DispositivosCan.Contains(x.Dispositivo))),
("fila_liberada", DadosCan.FilaLiberada),
("tipo_servico", CanManager.TipoServico.ToString()),
// Frequências
("freq_tx", DadosCan.FreqTx),
("freq_rx", DadosCan.FreqRx),
("freq_tx_janela", DadosCan.FreqTxJanela),
("freq_rx_janela", DadosCan.FreqRxJanela),
("freq_tx_ewma", DadosCan.FreqTxEwma),
("freq_rx_ewma", DadosCan.FreqRxEwma),
// Timestamps absolutos para o Python
("last_tx_ms", DadosCan.UltimoTxUnixMs),
("last_rx_ms", DadosCan.UltimoRxUnixMs),
("last_ec_ms", DadosCan.UltimoErroCriticoUnixMs),
// Contadores gerais
("tx_total", DadosCan.TxTotal),
("rx_total", DadosCan.RxTotal),
("tx_falha_total", DadosCan.TxFalhaTotal),
("rx_invalido_total", DadosCan.RxInvalidoTotal),
("rx_descartado_total", DadosCan.RxDescartadoFilaCheiaTotal),
("timeouts_resposta_total", DadosCan.TimeoutsRespostaTotal),
("reconexoes_total", DadosCan.ReconexoesTotal),
// Timeouts por origem
("timeouts_por_id_total", DadosCan.TimeoutsRespostaPorId),
("timeouts_por_dispositivo_total", DadosCan.TimeoutsRespostaPorDispositivo),
("timeouts_por_chave_total", DadosCan.TimeoutsRespostaPorChave),
("pendentes_resp_por_id", DadosCan.PendentesAguardandoRespostaPorId),
// Filas
("pendentes_total", DadosCan.PendentesTotal),
("pendentes_nao_enviadas", DadosCan.PendentesNaoEnviadas),
("pendentes_aguardando_resposta", DadosCan.PendentesAguardandoResposta),
("frames_rx_fila", DadosCan.FramesRxNaFila),
// Latência
("latencia_media_ms", DadosCan.LatenciaMediaMs),
("latencia_max_ms", DadosCan.LatenciaMaxMs),
// Compatibilidade com health antigo
("erros_criticos", DadosCan.ErrosCriticos),
("last_tx", DadosCan.UltimoTx),
("last_rx", DadosCan.UltimoRx),
("last_ec", DadosCan.UltimoErroCritico),
("last_ec_motivo", DadosCan.UltimoErroCriticoMotivo)
);
double MinOrDefault(List<double> items)
{
if (items.Count == 0) return 0;
return items.Min();
}
double MaxOrDefault(List<double> items)
{
if (items.Count == 0) return 0;
return items.Max();
}
var DadosBateria = DalyBMSService.DadosLeitura;
RedisService.AtualizarCampos(
RedisService.ModKey(T_Code.Bat), // ajusta o T_Code se o seu enum tiver outro nome
("timestamp", agora),
("iniciado", DadosBateria.Iniciado),
("momento_bms", DadosBateria.Momento),
// Dados principais do pack
("tensao_total_v", DadosBateria.Pack.TensaoTotal_V),
("tensao_medida_v", DadosBateria.Pack.TensaoMedida_V),
("corrente_a", DadosBateria.Pack.Corrente_A),
("soc_pct", DadosBateria.Pack.SOC_percent),
("num_celulas_serie", DadosBateria.Pack.NumeroCelulasSerie),
("num_sensores_temp", DadosBateria.Pack.NumeroSensoresTemperatura),
("estado_geral", DadosBateria.Pack.EstadoGeral),
("charge_mos_on", DadosBateria.Pack.ChargeMosOn),
("discharge_mos_on", DadosBateria.Pack.DischargeMosOn),
("cap_restante_ah", DadosBateria.Pack.CapacidadeRestante_Ah),
("ciclos_aproximados", DadosBateria.Pack.CiclosAproximados),
// Tensão de células
("tensao_min_celula_v", DadosBateria.TensaoMin > 0 ? DadosBateria.TensaoMin : MinOrDefault(DadosBateria.Celulas.Select(c => c.Tensao_V).ToList())),
("tensao_max_celula_v", DadosBateria.TensaoMax > 0 ? DadosBateria.TensaoMax : MaxOrDefault(DadosBateria.Celulas.Select(c => c.Tensao_V).ToList())),
("idx_celula_min", DadosBateria.Celulas.FirstOrDefault(c => c.EhMinima)?.Index ?? 0),
("idx_celula_max", DadosBateria.Celulas.FirstOrDefault(c => c.EhMaxima)?.Index ?? 0),
// Temperaturas
("temp_min_c", DadosBateria.TemperaturaMin > -200 ? DadosBateria.TemperaturaMin : DadosBateria.Temperaturas.Min(t => t.Temperatura_C)),
("temp_max_c", DadosBateria.TemperaturaMax > -200 ? DadosBateria.TemperaturaMax : DadosBateria.Temperaturas.Max(t => t.Temperatura_C)),
// Balanceamento
("celulas_em_balanceamento", DadosBateria.Balanceamento.QtdeCelulasEmBalanceamento),
// Alarmes
("tem_alarme", DadosBateria.Alarmes?.TemAlarme ?? false),
("fault_code", DadosBateria.Alarmes?.FaultCode ?? 0x00),
("qtd_alarmes", DadosBateria.Alarmes?.Mensagens?.Count ?? 0),
("alarmes_texto", DadosBateria.Alarmes.Mensagens != null && DadosBateria.Alarmes.Mensagens.Count > 0 ? string.Join(" | ", DadosBateria.Alarmes.Mensagens) : string.Empty),
// Opcional: bytes brutos de alarme se quiser debugar depois
("alarm_bytes_raw", DadosBateria.Alarmes.AlarmBytesRaw != null ? BitConverter.ToString(DadosBateria.Alarmes.AlarmBytesRaw) : string.Empty)
);
var DadosTrj = _Sensoriamento?.Trajetoria;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Trj),
("timestamp", agora),
("iniciado", DadosTrj?.AutonomiaCooredor?.Iniciado ?? false),
("liberado", DadosTrj?.AutonomiaCooredor?.Liberado ?? false),
("bateria_ok", DadosTrj?.AutonomiaCooredor?.BateriaSuficiente ?? false),
("herbicida_ok", DadosTrj?.AutonomiaCooredor?.HerbicidaSuficiente ?? false),
("motivos", DadosTrj?.AutonomiaCooredor?.Motivos ?? new List<string>())
);
double distanciaBase = -1;
if (VariaveisOperacao.PosicaoBase?.Inicializado == true && _Sensoriamento?.Gps?.Inicializado == true)
{
distanciaBase = GPSUtils.DistanciaEntrePontos(VariaveisOperacao.PosicaoBase, _Sensoriamento.Gps);
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Ipb),
("timestamp", agora),
("iniciado", Variaveis.MqttServiceBase?.StatusConexao() ?? false),
("distancia_base", distanciaBase)
);
}
catch (Exception ex)
{
Variaveis.MostrarLog($"[HealthWorkerService] Erro em AtualizarDadosModulos: {ex.Message}");
}
}
}
}