agrobot_base/AgroBase/AgroBase/Services/Operadores/VisualWorkerService.cs

236 lines
8.1 KiB
C#

using AgroBase.Models;
using AgroBase.Models.Operadores;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
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 VisualWorkerService : IWorkerModel
{
public static VisualWorkerModel DadosLeitura = new VisualWorkerModel();
public SaudeWorkerModel Saude { get; set; } = new SaudeWorkerModel();
private bool DebugMode = true;
static long _lastTsVW = -1;
public void MostrarLog(string message, int limite = 500)
{
if (DebugMode)
{
Console.WriteLine($"[VisualWorker] {message.Substring(0, Math.Min(limite, message.Length))}{(message.Length > limite ? "..." : "")}");
}
}
public async Task<bool> IniciarProcessamento()
{
RedisService.Subscribe(CmdKey.VisualWorkerTx, RedisCallback);
DadosLeitura.IniciadoEm = DateTime.Now;
DadosLeitura.Iniciado = true;
bool pronto() => DadosLeitura.Pronto;
await FuncoesGlobais.AguardarCondicaoAsync(pronto, 5000);
if (pronto())
{
MostrarLog("Processamento iniciado com sucesso");
DadosLeitura.Iniciado = true;
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 = (VisualWorkerCommandType)comando.cmd;
//MostrarLog($"Comando recebido: cmd = {cmd.ToString()}");
switch (cmd)
{
case VisualWorkerCommandType.ScriptCarregado:
DadosLeitura.Pronto = true;
DadosLeitura.ProntoEm = DateTime.Now;
MostrarLog($"Comando recebido: cmd = {cmd.ToString()}");
break;
case VisualWorkerCommandType.GetCameraFrame:
CameraFrameType tipo = (CameraFrameType)Convert.ToInt32(comando.@params["tipo"].ToString());
DadosLeitura.CameraFrames[tipo] = new OAKCameraFrameModel()
{
frame = comando.@params["frame"].ToString(),
timestamp = FuncoesGlobais.UnixToDateTime(comando.@params["timestamp"].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.DadosVisualWorker);
}
public static void RecalibrarGridProfundidade(int qtd_frames = 50)
{
var comando = new {
cmd = VisualWorkerCommandType.CalibrarProfundidade,
@params = qtd_frames
};
RedisService.Publish(CmdKey.VisualWorkerRx, JsonConvert.SerializeObject(comando));
}
public static async Task<OAKCameraFrameModel> GetCameraFrame(CameraFrameType tipo = CameraFrameType.Rgb)
{
DateTime Inicio = DateTime.Now;
var comando = new
{
cmd = VisualWorkerCommandType.GetCameraFrame,
@params = tipo,
};
RedisService.Publish(CmdKey.VisualWorkerRx, JsonConvert.SerializeObject(comando));
bool Frame() => DadosLeitura.CameraFrames.TryGetValue(tipo, out var frame) && (frame?.timestamp ?? DateTime.MinValue) > Inicio;
await FuncoesGlobais.AguardarCondicaoAsync(Frame, 1000, 100);
DadosLeitura.CameraFrames.TryGetValue(tipo, out OAKCameraFrameModel _frame);
return _frame;
}
public static void SaveCameraFrames(List<TipoFrameCamera> frames, string nome, string caminho)
{
var comando = new
{
cmd = VisualWorkerCommandType.SaveCameraFrames,
@params = new
{
nome = nome,
caminho = caminho,
tipos = frames.Select(x => (int)x).ToArray(),
},
};
RedisService.Publish(CmdKey.VisualWorkerRx, JsonConvert.SerializeObject(comando));
}
public static void AtualizarAnalise()
{
// IMU (simples e direto)
string imuJson = RedisService.Get(RedisService.ModKey(Enums.T_Code.Imu));
if (!string.IsNullOrWhiteSpace(imuJson))
{
try
{
DadosLeitura.Imu = JsonConvert.DeserializeObject<VisualWorkerMessageIMUModel>(imuJson);
}
catch { /* opcional: logar erro */ }
}
DadosLeitura.Status = HealthWorkerService.ModulosSaude.FirstOrDefault(x => x.modulo == Enums.T_Code.Snr)?.status ?? Enums.StatusModulo.Desconectado;
// VisualWorker
var json = RedisService.Get(CtxKey.DadosVisualWorker);
if (string.IsNullOrWhiteSpace(json)) return;
JObject root;
try
{
root = JObject.Parse(json);
}
catch
{
return; // payload inválido
}
// ts_analise (Unix)
long tsUnix = root["ts_analise"]?.Value<long>() ?? 0;
if (tsUnix != 0)
{
// atualiza o DateTime sempre que vier um ts válido
DadosLeitura.Analises.timestamp = FuncoesGlobais.UnixToDateTime(tsUnix.ToString());
}
// Se o timestamp não mudou, evita desserializar objetos grandes
if (tsUnix != 0 && tsUnix == _lastTsVW)
return;
_lastTsVW = tsUnix;
// segmentação (sem re-serializar o token)
var segTok = root["segmentacao"];
if (segTok != null)
{
try
{
var seg = segTok.ToObject<VisualWorkerMessageSegmentacaoSemanticaModel>();
if (seg != null) DadosLeitura.Analises.segmentacao = seg;
}
catch { /* opcional: log */ }
}
// matriz de confiança
var mcTok = root["matriz_confianca"];
if (mcTok != null)
{
try
{
var mc = mcTok.ToObject<VisualWorkerMessageMatrizConfiancaModel>();
if (mc != null) DadosLeitura.Analises.matriz_confianca = mc;
}
catch { /* opcional: log */ }
}
// deteccao (sem re-serializar o token)
var detTok = root["deteccao"];
if (detTok != null)
{
try
{
var det = detTok.ToObject<List<VisualWorkerMessageDeteccaoModel>>();
if (det != null) DadosLeitura.Analises.deteccao = det;
}
catch { /* opcional: log */ }
}
}
public static void ReiniciarLeituraAnalise()
{
RedisService.AtualizarCampos(
CtxKey.DadosWeedWorker,
("analise.segmentacao", new VisualWorkerMessageSegmentacaoSemanticaModel()),
("analise.matriz_confianca", new VisualWorkerMessageMatrizConfiancaModel()),
("analise.deteccao", new List<VisualWorkerMessageDeteccaoModel>())
);
}
}
}