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

552 lines
24 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.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()
{
Saude = OperadoresModels.AtualizarSaude(CtxKey.DadosHealthWorker);
}
private static void AtualizarDadosContextoLocal()
{
RedisService.AtualizarCampos(
CtxKey.DadosOperacao,
("debug_mode", Variaveis.DebugMode),
("iniciado", Variaveis.OperacaoEmAndamento.Iniciado),
("finalizando", Variaveis.OperacaoEmAndamento.Finalizando),
("calibrando", Variaveis.OperacaoEmAndamento.Calibrando),
("emergencia", Variaveis.OperacaoEmAndamento.Emergencia)
);
}
public static void AtualizarDadosContexto()
{
if (AtualizandoRedis)
return;
AtualizandoRedis = true;
AtualizarDadosContextoLocal();
AtualizarDadosModulos();
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
if (_Sensoriamento == null)
{
AtualizandoRedis = false;
return;
}
RedisService.AtualizarCampos(
CtxKey.DadosContexto,
("Trajetoria", _Sensoriamento.Trajetoria != null ? new
{
status = (int)_Sensoriamento.Trajetoria.StatusCarro,
manobrando = _Sensoriamento.Trajetoria.ManobrandoEntreRuas,
erro_angular = _Sensoriamento.Trajetoria.ErroOrientacaoAngularCombinado,
idx_proximo_ponto = _Sensoriamento.Trajetoria.ProximoPonto.idxPonto,
CorredorAtual = new
{
concluido = _Sensoriamento.Trajetoria.CorredorAtual.Concluido,
dentro = _Sensoriamento.Trajetoria.CorredorAtual.Dentro,
ultimo = _Sensoriamento.Trajetoria.CorredorAtual.Ultimo,
largura = _Sensoriamento.Trajetoria.CorredorAtual.Largura,
progresso = _Sensoriamento.Trajetoria.CorredorAtual.Progresso,
dist_esq = _Sensoriamento.Trajetoria.DistanciaEsquerda,
dist_dir = _Sensoriamento.Trajetoria.DistanciaDireita,
angulo = _Sensoriamento.Trajetoria.AnguloCaminho,
},
} : null
),
("Gerais", new
{
velocidade_ms = _Sensoriamento.Movimentacao != null ? _Sensoriamento.Movimentacao.VelocidadeMedia : 0,
ervas_no_radar = _Sensoriamento.Atuador != null ? _Sensoriamento.Atuador.ErvasNoRadar : 0,
}
)
);
AtualizandoRedis = false;
}
private static void AtualizarDadosEquipamento()
{
RedisService.AtualizarCampos(
CtxKey.DadosEquipamento,
("largura", VariaveisEquipamento.LarguraEquipamentoMm / 1000.0),
("distancia_entre_eixos", VariaveisEquipamento.DistanciaEntreEixos / 100.0),
("percentual_reservatorio_min", VariaveisEquipamento.PercentualReservatorioMin),
("percentual_tensao_bateria_min", VariaveisEquipamento.PercentualTensaoBateriaMin),
("camera_caminho_id", Variaveis.OperacaoEmAndamento.DispSen?.Dados?.CameraCaminho?.Id ?? ""),
("camera_solo_id", Variaveis.OperacaoEmAndamento.DispSen?.Dados?.CamerasSolo?.FirstOrDefault()?.Id ?? ""),
("path_ia_model_ruas", VersionamentoService.ArquivoModeloStreetDetector.CaminhoCompleto),
("path_ia_model_ervas", VersionamentoService.ArquivoModeloWeedDetector.CaminhoCompleto)
);
}
public static void AtualizarDadosOperacao()
{
if (AtualizandoRedis)
return;
AtualizandoRedis = true;
AtualizarDadosEquipamento();
AtualizarDadosControleOperacao();
if (Variaveis.OperacaoEmAndamento.DispMvd == null)
{
AtualizandoRedis = false;
return;
}
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
RedisService.AtualizarCampos(
CtxKey.DadosOperacao,
("configurado", true),
("modo", Variaveis.OperacaoEmAndamento.Modo),
("tempo_aguardar_inicio_operacao", Variaveis.OperacaoEmAndamento.TempoIniciarOperacao),
("modulos_mandatorios", Variaveis.OperacaoEmAndamento.ModulosMandatorios.Select(x => (int)x.Dispositivo).ToArray()),
("parametros_mandatorios", Variaveis.OperacaoEmAndamento.ParametrosMandatorios.Select(x => (int)x.Parametro).ToArray()),
("Mov", new
{
percent_vel_max = _Controle.PercentualVelocidadeMax,
percent_vel_min = _Controle.PercentualVelocidadeMin,
}
),
("Dir", new
{
angulo_max = _Controle.Angulo_Max,
vel_movimento = _Controle.VelocidadeMP,
tipo_controle = (int)_Controle.TipoControleDirecional,
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(),
horizonte = 2.5,
angulo_max_graus = _Controle.Angulo_Max,
velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Controle.PercentualVelocidadeMin),
velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(_Controle.PercentualVelocidadeMax)
}
}
),
("Atu", new
{
qtd_bicos = Variaveis.OperacaoEmAndamento.DispAtu.Dados.QuantidadeBicos,
percent_vertical_deteccao = _Controle.PercentualInicioPulverizacao,
tempo_atuacao = _Controle.TempoAtuacao,
capacidade_reservatorio = Variaveis.OperacaoEmAndamento.CapacidadeReservatorio,
pressao_linha = _Controle.PressaoLinha
}
),
("Snr", new
{
percentual_altura_solo = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.PercentualAlturaSolo,
distancia_maxima = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.DistanciaMaximaVisao,
distancia_minima = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.DistanciaMinimaVisao,
sonar_ativado = _Controle.SonarAtivado,
}
)
);
if (Variaveis.OperacaoEmAndamento.Modo == Enums.ModoOperacao.MapaGPS && (Variaveis.OperacaoEmAndamento.Trajetoria?._TrajetoriaFixa?.Count() ?? 0) > 0)
{
var comando = new
{
cmd = HealthWorkerCommandType.AtualizarPontosMapa
};
RedisService.Publish(CmdKey.HealthWorkerRx, JsonConvert.SerializeObject(comando));
}
AtualizandoRedis = false;
}
public static void AtualizarDadosControleOperacao()
{
RedisService.AtualizarCampos(
CtxKey.DadosControle,
("pulverizador_automatico", Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico),
("movimento_automatico", Variaveis.OperacaoEmAndamento.Controle.MovimentoAutomatico)
);
}
private static void AtualizarDadosModulos()
{
if (Variaveis.OperacaoEmAndamento.DispMvd == 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);
if (_Sensoriamento.Gps != null)
{
RedisService.AtualizarCampos(
RedisService.ModKey(Enums.T_Code.Gps),
("timestamp", agora),
("conectado", GPSService.Iniciado),
("freq_base", GPSService.TaxaAmostragemHz),
("lat", _Sensoriamento.Gps.Latitude),
("lon", _Sensoriamento.Gps.Longitude),
("theta", _Sensoriamento.Gps.AnguloCarroDefinido),
("fix", (int)_Sensoriamento.Gps.QualidadeFix),
("rtk", GPSService.UltimoEnvioCorrecaoRTK.AddSeconds(5) > DateTime.Now),
("hAcc", _Sensoriamento.Gps.PrecisaoCm),
("nSatelites", _Sensoriamento.Gps.NumeroSatelites.valor),
("freq", _Sensoriamento.Gps.NumeroSatelites.frequencia)
);
}
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.Angulo),
($"{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.io", mod.DirMotor.Leitura?.NumeroPulsos?.frequencia ?? 0),
($"{endereco_dir}.freq.pulsos", mod.DirMotor.Leitura?.EntradaIN1?.frequencia ?? 0)
);
int endereco_mov = mod.MovMotor._EnderecoCAN_Tx;
RedisService.AtualizarCampos(
RedisService.ModKey(Enums.T_Code.Mov),
($"{endereco_mov}.timestamp", agora),
($"{endereco_mov}.conectado", mod.MovMotor.Inicializado),
($"{endereco_mov}.freq_base", Variaveis.OperacaoEmAndamento.DispMvd.Dados.tmrRegistradorMOV.IntervalHz),
($"{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)
);
}
var DadosSen = Variaveis.OperacaoEmAndamento.DispSen.Dados;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen),
("timestamp", agora),
("conectado", DadosSen.Conectado),
("freq_base", DadosSen.FrequenciaBase)
);
var sensoresAtualizados = new List<(string caminho, object valor)>();
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 { }
};
sensoresAtualizados.Add(($"{basePath}", sensorObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen), sensoresAtualizados.ToArray());
var servosAtualizados = new List<(string caminho, object valor)>();
foreach (var servo in DadosSen.Servos)
{
int id = servo.ID_Num;
string basePath = $"servos.{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,
controlar = servo.Controlar,
mandatorio = servo.Mandatorio,
angulo_sp = servo._AnguloControle,
dados,
timestamp = agora,
saude = saude ?? new { }
};
servosAtualizados.Add(($"{basePath}", servoObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen), servosAtualizados.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)>();
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.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 { }
};
atuSensoresAtualizados.Add(($"{basePath}", sensorObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), atuSensoresAtualizados.ToArray());
var bicosAtualizados = new List<(string caminho, object valor)>();
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.Sen), $"{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 sensorObj = new
{
conectado = bico.Inicializado,
id,
label = bico.ID,
tipo,
comandar = bico.Comandar,
mandatorio = bico.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
bicosAtualizados.Add(($"{basePath}", sensorObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), bicosAtualizados.ToArray());
var bombasAtualizados = new List<(string caminho, object valor)>();
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.Sen), $"{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 { }
};
bombasAtualizados.Add(($"{basePath}", sensorObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), bombasAtualizados.ToArray());
}
}
}