227 lines
8.5 KiB
C#
227 lines
8.5 KiB
C#
using AgroBase.Models.Operadores;
|
|
using AgroBase.Models;
|
|
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 WeedWorkerService : IWorkerModel
|
|
{
|
|
public static WeedWorkerModel DadosLeitura = new WeedWorkerModel();
|
|
public SaudeWorkerModel Saude { get; set; } = new SaudeWorkerModel();
|
|
public AsyncTaskTimerModel tmrPooling;
|
|
|
|
private bool DebugMode = true;
|
|
|
|
public void MostrarLog(string message, int limite = 500)
|
|
{
|
|
if (DebugMode)
|
|
{
|
|
Console.WriteLine($"[WeedWorker] {message.Substring(0, Math.Min(limite, message.Length))}{(message.Length > limite ? "..." : "")}");
|
|
}
|
|
}
|
|
|
|
public async Task<bool> IniciarProcessamento()
|
|
{
|
|
RedisService.Subscribe(CmdKey.WeedWorkerTx, RedisCallback);
|
|
|
|
DadosLeitura.IniciadoEm = DateTime.Now;
|
|
DadosLeitura.Iniciado = true;
|
|
|
|
tmrPooling?.Dispose();
|
|
tmrPooling = new AsyncTaskTimerModel("tmrWeedWorkerPooling", tmrPooling_Tick, 500);
|
|
tmrPooling.Start();
|
|
|
|
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;
|
|
}
|
|
|
|
private async Task tmrPooling_Tick()
|
|
{
|
|
if (Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico)
|
|
{
|
|
var dictParams = RedisService.GetField<Dictionary<string, object>>(CtxKey.DadosControle, "controle_bicos");
|
|
AtualizarControle(dictParams);
|
|
}
|
|
}
|
|
|
|
private void AtualizarControle(Dictionary<string, object> dictParams)
|
|
{
|
|
if (dictParams == null)
|
|
return;
|
|
|
|
var novoComando = dictParams
|
|
.Select(kv => new
|
|
{
|
|
Key = int.TryParse(kv.Key, out var i) ? (i + 1) : -1,
|
|
Value = Convert.ToBoolean(kv.Value)
|
|
})
|
|
.Where(x => x.Key >= 0)
|
|
.ToDictionary(x => x.Key, x => x.Value);
|
|
|
|
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
|
|
foreach (var bico in _Controle.BicosAtuados)
|
|
{
|
|
novoComando.TryGetValue(bico.Posicao, out bool atuado);
|
|
bico.ComandoAtuar = atuado;
|
|
}
|
|
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();
|
|
}
|
|
|
|
public void RedisCallback(string mensagem)
|
|
{
|
|
try
|
|
{
|
|
var comando = JsonConvert.DeserializeObject<ComandoRedis>(mensagem);
|
|
|
|
var cmd = (WeedWorkerCommandType)comando.cmd;
|
|
|
|
//MostrarLog($"Comando recebido: cmd = {cmd.ToString()}");
|
|
|
|
switch (cmd)
|
|
{
|
|
case WeedWorkerCommandType.ScriptCarregado:
|
|
DadosLeitura.Pronto = true;
|
|
DadosLeitura.ProntoEm = DateTime.Now;
|
|
MostrarLog($"Comando recebido: cmd = {cmd.ToString()}");
|
|
break;
|
|
|
|
case WeedWorkerCommandType.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;
|
|
|
|
case WeedWorkerCommandType.EnviarDadosControle:
|
|
if (Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico)
|
|
{
|
|
AtualizarControle(comando.@params);
|
|
}
|
|
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.DadosWeedWorker);
|
|
}
|
|
|
|
public static async Task<OAKCameraFrameModel> GetCameraFrame(CameraFrameType tipo = CameraFrameType.Rgb)
|
|
{
|
|
DateTime Inicio = DateTime.Now;
|
|
|
|
var comando = new
|
|
{
|
|
cmd = WeedWorkerCommandType.GetCameraFrame,
|
|
@params = tipo,
|
|
};
|
|
RedisService.Publish(CmdKey.WeedWorkerRx, 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<CameraFrameType> frames, string nome, string caminho)
|
|
{
|
|
var comando = new
|
|
{
|
|
cmd = WeedWorkerCommandType.SaveCameraFrames,
|
|
@params = new
|
|
{
|
|
nome = nome,
|
|
caminho = caminho,
|
|
tipos = frames.Select(x => (int)x).ToArray(),
|
|
},
|
|
};
|
|
RedisService.Publish(CmdKey.WeedWorkerRx, JsonConvert.SerializeObject(comando));
|
|
}
|
|
|
|
public static void AtualizarAnalise()
|
|
{
|
|
var json = RedisService.Get(CtxKey.DadosWeedWorker);
|
|
var dados = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
|
|
|
|
if (dados.ContainsKey("ts_analise") && dados.ContainsKey("analise"))
|
|
{
|
|
var analise = JsonConvert.DeserializeObject<Dictionary<string, object>>(dados["analise"].ToString());
|
|
|
|
// 1. Timestamp (vem como double ou string)
|
|
DateTime timestamp = FuncoesGlobais.UnixToDateTime(analise["timestamp"].ToString());
|
|
|
|
// 2. Deteccoes (vem como List<object> ou string)
|
|
var listaDeteccoes = JsonConvert.DeserializeObject<List<WeedWorkerAnaliseDeteccaoModel>>(
|
|
analise["deteccoes"].ToString()
|
|
);
|
|
|
|
// 3. Controle: pode vir como Dictionary<string, object>
|
|
var controleDict = JsonConvert.DeserializeObject<Dictionary<string, bool>>(
|
|
analise["controle"].ToString()
|
|
);
|
|
|
|
var ervasIdentificadas = JsonConvert.DeserializeObject<List<Dictionary<string, int>>>(
|
|
analise["ervas_identificadas"].ToString()
|
|
);
|
|
|
|
// 4. Monta o objeto manualmente
|
|
var analiseObj = new WeedWorkerAnaliseModel
|
|
{
|
|
timestamp = timestamp,
|
|
frame_height = Convert.ToInt32(analise["frame_height"].ToString()),
|
|
frame_width = Convert.ToInt32(analise["frame_width"].ToString()),
|
|
deteccoes = listaDeteccoes,
|
|
controle = controleDict.ToDictionary(x => Convert.ToInt32(x.Key), x => x.Value),
|
|
ervas_identificadas = ervasIdentificadas
|
|
};
|
|
|
|
Variaveis.OperacaoEmAndamento.DispAtu?.Dados?.BicosPulverizadores?.ForEach(bico =>
|
|
{
|
|
int atuacoes = 0;
|
|
var ervas = DadosLeitura?.Analise?.ervas_identificadas ?? new List<Dictionary<string, int>>();
|
|
if (ervas.Count < bico.Posicao || bico.Posicao <= 0)
|
|
atuacoes = 0;
|
|
else
|
|
atuacoes = ervas[bico.Posicao - 1]?.Sum(x => x.Value) ?? 0;
|
|
bico.Atuacoes = atuacoes;
|
|
});
|
|
|
|
DadosLeitura.Analise = analiseObj;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|