agrobot_base/AgroBase/AgroBase/Services/LoRaService.cs

782 lines
30 KiB
C#

using AgroBase.Models;
using Emgu.CV;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using Microsoft.DirectX.DirectInput;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static AgroBase.Models.Enuns;
using static Emgu.CV.ML.KNearest;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;
namespace AgroBase.Services
{
public class LoRaService
{
public static SerialPort PortaLoRa;
public static bool Iniciado
{
get
{
if (PortaLoRa != null && !PortaLoRa.IsOpen)
{
try
{
PortaLoRa.Open();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
PortaLoRa = null;
}
}
return PortaLoRa != null && PortaLoRa.IsOpen;
}
}
private static Dictionary<DateTime, List<byte>> bufferRecebido = new Dictionary<DateTime, List<byte>>();
private static List<byte[]> bufferEnvio = new List<byte[]>();
private static LoRaParametrosModel parametrosModel { get; set; } = new LoRaParametrosModel();
public LoRaParametrosModel parametros
{
get
{
return parametrosModel;
}
}
private DateTime UltimaLeituraMensagem = DateTime.Now.AddMinutes(-1);
public static Dictionary<string, byte> CodigosFuncoes = new Dictionary<string, byte>()
{
{ "ComandoConfiguracao", 0xc0 },
{ "RespostaConfiguracao", 0xc1 },
{ "Mensagem", 0xe1 },
};
public static Dictionary<string, byte> CodigosTipoTransmissao = new Dictionary<string, byte>()
{
{ "Normal", 0x00 },
{ "Fixed", 0x40 },
};
public static Dictionary<int, byte> CodigosBaudRates = new Dictionary<int, byte>()
{
{ 1200, 0x00 },
{ 2400, 0x20 },
{ 4800, 0x40 },
{ 9600, 0x60 },
{ 19200, 0x80 },
{ 34800, 0xa0 },
{ 57600, 0xc0 },
{ 115200, 0xe0 },
};
public static Dictionary<double, byte> CodigosAirRates = new Dictionary<double, byte>()
{
{ 2.4, 0x02 },
{ 4.8, 0x03 },
{ 9.6, 0x04 },
{ 19.2, 0x05 },
{ 38.4, 0x06 },
{ 62.5, 0x67 },
};
public static Dictionary<int, byte> CodigosPacketSizes = new Dictionary<int, byte>()
{
{ 200, 0x00 },
{ 128, 0x40 },
{ 64, 0x80 },
{ 32, 0xc0 },
};
public static Dictionary<int, byte> CodigosWorCycles = new Dictionary<int, byte>()
{
{ 500, 0x00 },
{ 1000, 0x01 },
{ 1500, 0x02 },
{ 2000, 0x03 },
{ 2500, 0x04 },
{ 3000, 0x05 },
{ 3500, 0x06 },
{ 4000, 0x07 },
};
public static Dictionary<int, byte> CodigosPowers = new Dictionary<int, byte>()
{
{ 22, 0x00 },
{ 17, 0x01 },
{ 13, 0x02 },
{ 10, 0x03 },
};
private static List<LoRaMensagemModel> MensagensRecebidas = new List<LoRaMensagemModel>();
public LoRaMensagemModel MensagemPendente
{
get
{
if (MensagensRecebidas.Any(x => !x.Lido && x.Momento > UltimaLeituraMensagem))
{
var Mensagem = MensagensRecebidas.OrderBy(x => x.Momento).Where(x => !x.Lido && x.Momento > UltimaLeituraMensagem).FirstOrDefault();
Mensagem.Lido = true;
return Mensagem;
}
return null;
}
}
public static List<LoRaProtocoloTransmissaoModel> LeituraDadosOperacao = new List<LoRaProtocoloTransmissaoModel>();
private static bool RotinaEnvioIniciada = false;
private static bool RotinaPingsIniciada = false;
public static async Task<bool> VerificaPortaLoRa(SerialPort porta)
{
porta.Close();
porta.BaudRate = 9600;
var comando = ComandoRequisitarParametros();
EnviarComando(porta, comando);
await Task.Delay(1000);
var resposta = SerialService.VerificarRespostaPortasDesconhecidas(porta);
if (resposta.Length > 3)
{
var protocolo = new LoRaProtocoloModel()
{
Cabecalho = new List<byte>()
{
resposta[0],
resposta[1],
resposta[2]
},
Dados = new Dictionary<DateTime, List<byte>>()
{
{ DateTime.Now, resposta.ToList() }
}
};
var parametros = DecifrarResposta(protocolo);
if (parametros != null)
{
parametrosModel = parametros;
AtualizarPortaCOM(porta);
return Iniciado;
}
}
porta.Close();
return false;
}
public static void AtualizarPortaCOM(SerialPort Porta)
{
if (PortaLoRa == null)
{
PortaLoRa = new SerialPort()
{
Encoding = Encoding.UTF8,
ReadBufferSize = 8192,
WriteBufferSize = 8192,
};
}
else if (Iniciado)
{
PortaLoRa.Close();
}
PortaLoRa.BaudRate = Porta.BaudRate;
PortaLoRa.PortName = Porta.PortName;
PortaLoRa.DataReceived -= PortaLoRa_DataReceived;
PortaLoRa.DataReceived += PortaLoRa_DataReceived;
Porta.Close();
if (Iniciado)
{
DefinirDispositivo();
if (!RotinaEnvioIniciada)
{
LoopEnvioBuffer().ConfigureAwait(false);
}
if (!RotinaPingsIniciada && !Variaveis.IsAgroMonitor)
{
EnviarPingComunicacao().ConfigureAwait(false);
}
}
}
private static void DefinirDispositivo()
{
if (Iniciado)
{
SerialService.DispositivosMapeados.Add(new SerialService.DispositivoDetalhesModel()
{
PortaCOM = PortaLoRa.PortName,
Dispositivo = T_Code.Lra,
Erro = !Iniciado,
Versao = "220"
});
}
}
private static void PortaLoRa_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (PortaLoRa.IsOpen)
{
VerificaProtocoloCompleto();
/*byte[] buffer;
if (Variaveis.OperacaoEmAndamento.DispSen?.Dados.Conectado ?? false)
{
string line = PortaLoRa.ReadLine();
buffer = Encoding.UTF8.GetBytes(line);
}
else
{
int bytesToRead = PortaLoRa.BytesToRead;
buffer = new byte[bytesToRead];
PortaLoRa.Read(buffer, 0, bytesToRead);
}
//int bytesToRead = PortaLoRa.BytesToRead;
//byte[] buffer = new byte[bytesToRead];
//PortaLoRa.Read(buffer, 0, bytesToRead);
var Res = DecifrarResposta(buffer);
if (Res != null)
{
parametrosModel = Res;
}*/
/*int bytesToRead = PortaLoRa.BytesToRead;
byte[] buffer = new byte[bytesToRead];
PortaLoRa.Read(buffer, 0, bytesToRead);
var Res = DecifrarResposta(buffer);
if (Res != null)
{
parametrosModel = Res;
}*/
/*List<byte> bufferRecebido = new List<byte>();
// Continuar lendo enquanto houver dados disponíveis
while (PortaLoRa.BytesToRead > 0)
{
int bytesToRead = PortaLoRa.BytesToRead;
byte[] buffer = new byte[bytesToRead];
PortaLoRa.Read(buffer, 0, bytesToRead);
// Adiciona os bytes lidos ao buffer global
bufferRecebido.AddRange(buffer);
Task.Delay(10);
}
if (PortaLoRa.BytesToRead == 0)
{
// Processa a mensagem recebida
var Res = DecifrarResposta(bufferRecebido.ToArray());
if (Res != null)
{
parametrosModel = Res;
}
}*/
}
}
private static void VerificaProtocoloCompleto()
{
byte[] buffer = new byte[1];
PortaLoRa.Read(buffer, 0, 1);
byte caractere0 = buffer[0];
if (caractere0 == CodigosFuncoes["RespostaConfiguracao"])
{
//buffer = SerialService.VerificarRespostaPortasDesconhecidas(PortaLoRa);
buffer = SerialService.LerDadosDaPortaSerial(PortaLoRa, 6);
}
else
{
/*string leitura = PortaLoRa.ReadLine();
buffer = Encoding.UTF8.GetBytes(leitura);*/
buffer = SerialService.LerDadosDaPortaSerial(PortaLoRa, 168);
}
// Cria um novo buffer com espaço para o caractere0 no início
byte[] bufferCompleto = new byte[buffer.Length + 1];
bufferCompleto[0] = caractere0;
Array.Copy(buffer, 0, bufferCompleto, 1, buffer.Length);
if (bufferCompleto.Length > 0)
{
bufferRecebido.Add(DateTime.Now.AddMilliseconds(1), bufferCompleto.ToList());
}
var buferEntrada = bufferRecebido.OrderBy(x => x.Key);
var mensagens = new List<LoRaProtocoloModel>();
foreach (var item in buferEntrada)
{
if (item.Value != null && item.Value.Count > 3)
{
List<byte> cabecalho = new List<byte>()
{
//item.Value[0],
item.Value[1],
item.Value[2]
};
var mensagem = mensagens.FirstOrDefault(m => m.Cabecalho[0] == cabecalho[0] && m.Cabecalho[1] == cabecalho[1]);
if (mensagem != null)
{
mensagem.Dados.Add(item.Key, item.Value);
}
else
{
mensagens.Add(new LoRaProtocoloModel()
{
Cabecalho = cabecalho,
Dados = new Dictionary<DateTime, List<byte>>() { { item.Key, item.Value } }
});
}
}
else
{
bufferRecebido.Remove(item.Key);
}
}
foreach (var mensagem in mensagens.Where(x => x.MensagemCompleta))
{
var Res = DecifrarResposta(mensagem);
if (Res != null)
{
parametrosModel = Res;
}
foreach (var item in mensagem.Dados)
{
bufferRecebido.Remove(item.Key);
}
}
}
public static LoRaParametrosModel DecifrarResposta(LoRaProtocoloModel resposta)
{
try
{
if (resposta.Parametrizacao)
{
LoRaParametrosModel modelo = new LoRaParametrosModel()
{
UltimaLeitura = DateTime.Now
};
int numBytes = resposta.Buffer[2];
if (numBytes == 6 || numBytes == 11) // Set ou Get nos parametros
{
modelo.address = resposta.Buffer[4];
string baudAndAirRates = Convert.ToInt32(resposta.Buffer[5].ToString("X")).ToString("00");
modelo.baudRate = Convert.ToByte(baudAndAirRates[0] + "0", 16);
modelo.airRate = Convert.ToByte("0" + baudAndAirRates[1], 16);
string packetSizeAndPower = Convert.ToInt32(resposta.Buffer[6].ToString("X")).ToString("00");
modelo.packetSize = Convert.ToByte(packetSizeAndPower[0] + "0", 16);
modelo.power = Convert.ToByte("0" + packetSizeAndPower[1], 16);
modelo.channel = resposta.Buffer[7];
string tranModeAndWorCycle = Convert.ToInt32(resposta.Buffer[8].ToString("X")).ToString("00");
modelo.tranMode = Convert.ToByte(tranModeAndWorCycle[0] + "0", 16);
modelo.worCycle = Convert.ToByte("0" + tranModeAndWorCycle[1], 16);
return modelo;
}
else
{
Console.WriteLine("Número de bytes de dados não esperado.");
}
}
else
{
switch (resposta.Tipo)
{
case LoRaTipoProtocolo.MensagemTexto:
{
LoRaMensagemModel Mensagem = new LoRaMensagemModel()
{
Momento = DateTime.Now,
channel = parametrosModel.channel,
Remetente = resposta.Remtente,
Destinatario = resposta.Destinatario,
Mensagem = resposta.Mensagem,
Lido = false
};
MensagensRecebidas.Add(Mensagem);
break;
};
case LoRaTipoProtocolo.DadosOperacao:
{
byte[] bufferDados = new byte[resposta.Buffer.Length - 4];
Console.WriteLine("Recebendo log via LoRa... " + bufferDados.Length + " bytes");
Array.Copy(resposta.Buffer, 4, bufferDados, 0, bufferDados.Length);
LoRaProtocoloTransmissaoModel Dados = LoRaSerializer.DeserializeLoRaProtocoloTransmissaoModel(bufferDados);
LeituraDadosOperacao.Add(Dados);
break;
}
}
}
return null;
}
catch (Exception ex)
{
Console.WriteLine("Erro ao receber dados LoRa: " + ex.Message);
}
return null;
}
public async Task<(bool, LoRaParametrosModel)> RequisitarParametrosModuloAsync()
{
byte[] command = ComandoRequisitarParametros();
DateTime inicio = DateTime.Now;
TimeSpan timeout = TimeSpan.FromSeconds(5);
// Envia o comando para a porta COM
EnviarComando(PortaLoRa, command);
// Aguarda a resposta ou até que o timeout seja atingido
while (DateTime.Now - inicio < timeout)
{
// Verifica se a última leitura foi atualizada nos últimos 3 segundos
if (parametrosModel.UltimaLeitura >= DateTime.Now.AddSeconds(-3))
{
return (true, parametrosModel);
}
// Aguarda de forma assíncrona por um curto período de tempo
await Task.Delay(100);
}
// Se o timeout for atingido, retorna o modelo com os dados disponíveis até o momento
return (false, parametrosModel);
}
public async Task<LoRaParametrosModel> ConfigurarModuloAsync(LoRaParametrosModel Parametros)
{
parametrosModel = Parametros;
byte[] command = ComandoConfigurarModulo();
DateTime inicio = DateTime.Now;
TimeSpan timeout = TimeSpan.FromSeconds(5);
// Envia o comando para a porta COM
EnviarComando(PortaLoRa, command);
// Aguarda a resposta ou até que o timeout seja atingido
while (DateTime.Now - inicio < timeout)
{
// Verifica se a última leitura foi atualizada nos últimos 3 segundos
if (parametrosModel.UltimaLeitura >= DateTime.Now.AddSeconds(-3))
{
return parametrosModel;
}
// Aguarda de forma assíncrona por um curto período de tempo
await Task.Delay(100);
}
// Se o timeout for atingido, retorna o modelo com os dados disponíveis até o momento
return null;
}
public static List<byte[]> MontarMensagemEnvio(string texto, byte targetAddress, LoRaTipoProtocolo tipo, bool Enviar)
{
List<byte[]> Partes = new List<byte[]>();
byte[] Cabecalho = new byte[] { parametrosModel.address, targetAddress, (byte)tipo };
int packetSize = CodigosPacketSizes.FirstOrDefault(x => x.Value == parametrosModel.packetSize).Key - 10;
byte addressHigh = 0x00;
int prefixLength = Encoding.UTF8.GetByteCount(SerialService.BeginLine) + Cabecalho.Length;
int maxTextLength = packetSize - prefixLength;
List<string> messageParts = new List<string>();
for (int i = 0; i < texto.Length; i += maxTextLength)
{
int length = Math.Min(maxTextLength, texto.Length - i);
messageParts.Add(texto.Substring(i, length).Replace(SerialService.BeginLine, "?").Replace(SerialService.EndLine, "?").Replace(SerialService.BreakLine, "?"));
}
for (int i = 0; i < messageParts.Count; i++)
{
string Prefixo = (i == 0 ? SerialService.BeginLine : SerialService.BreakLine);
string Sulfixo = (i == messageParts.Count() - 1 ? SerialService.EndLine : SerialService.BreakLine) + "\n";
byte[] prefixoBytes = Encoding.UTF8.GetBytes(Prefixo);
byte[] sulfixoBytes = Encoding.UTF8.GetBytes(Sulfixo);
byte[] Mensagem = Encoding.UTF8.GetBytes(messageParts[i]);
byte[] message = new byte[prefixoBytes.Length + Cabecalho.Length + Mensagem.Length + sulfixoBytes.Length + 3];
message[0] = addressHigh;
message[1] = targetAddress;
message[2] = parametrosModel.channel;
//Array.Copy(Encoding.UTF8.GetBytes(Mensagem), 0, message, 3, Mensagem.Length);
Array.Copy(prefixoBytes, 0, message, 3, prefixoBytes.Length);
Array.Copy(Cabecalho, 0, message, 3 + prefixoBytes.Length, Cabecalho.Length);
Array.Copy(Mensagem, 0, message, 3 + prefixoBytes.Length + Cabecalho.Length, Mensagem.Length);
Array.Copy(sulfixoBytes, 0, message, 3 + prefixoBytes.Length + Cabecalho.Length + Mensagem.Length, sulfixoBytes.Length);
Partes.Add(message);
}
if (Regex.IsMatch(texto, @"[^a-zA-Z0-9\s]"))
{
string mensagemControle = " " + SerialService.EndLine + "\n";
byte[] beginLine = Encoding.UTF8.GetBytes(SerialService.BeginLine);
byte[] mensagemBytes = Encoding.UTF8.GetBytes(mensagemControle);
byte[] message = new byte[beginLine.Length + Cabecalho.Length + mensagemBytes.Length + 3];
message[0] = addressHigh;
message[1] = targetAddress;
message[2] = parametrosModel.channel;
Array.Copy(beginLine, 0, message, 3, beginLine.Length);
Array.Copy(Cabecalho, 0, message, 3 + beginLine.Length, Cabecalho.Length);
Array.Copy(mensagemBytes, 0, message, 3 + beginLine.Length + Cabecalho.Length, mensagemBytes.Length);
Partes.Add(message);
}
if (Enviar)
{
foreach (var parte in Partes)
{
bufferEnvio.Add(parte);
}
}
return Partes;
}
public static List<byte[]> MontarMensagemEnvio(byte[] bytes, byte targetAddress, LoRaTipoProtocolo tipo, bool Enviar)
{
List<byte[]> Partes = new List<byte[]>();
byte[] Cabecalho = new byte[] { parametrosModel.address, targetAddress, (byte)tipo };
int maxPacketSize = CodigosPacketSizes.FirstOrDefault(x => x.Value == parametrosModel.packetSize).Key - 10;
int prefixLength = 5; // Tamanho fixo do cabeçalho (ajuste conforme necessário)
int maxDataLength = maxPacketSize - prefixLength - 1; // Subtrai tamanho do cabeçalho e um byte para o sufixo
byte addressHigh = 0x00; // Endereço alto (pode ajustar conforme necessário)
byte channel = parametrosModel.channel; // Canal do LoRa (ajuste conforme necessário)
for (int i = 0; i < bytes.Length; i += maxDataLength)
{
int length = Math.Min(maxDataLength, bytes.Length - i);
byte[] dataFragment = new byte[length];
Array.Copy(bytes, i, dataFragment, 0, length);
// Montar cabeçalho
string Prefixo = (i == 0 ? SerialService.BeginLine : SerialService.BreakLine);
string Sulfixo = (i + length >= bytes.Length ? SerialService.EndLine : SerialService.BreakLine) + "\n";
byte[] prefixoBytes = Encoding.UTF8.GetBytes(Prefixo);
byte[] sulfixoBytes = Encoding.UTF8.GetBytes(Sulfixo);
byte[] mensagem = new byte[prefixoBytes.Length + Cabecalho.Length + dataFragment.Length + sulfixoBytes.Length + 3];
mensagem[0] = addressHigh;
mensagem[1] = targetAddress;
mensagem[2] = channel;
Array.Copy(prefixoBytes, 0, mensagem, 3, prefixoBytes.Length);
Array.Copy(Cabecalho, 0, mensagem, 3 + prefixoBytes.Length, Cabecalho.Length);
Array.Copy(dataFragment, 0, mensagem, 3 + prefixoBytes.Length + Cabecalho.Length, dataFragment.Length);
Array.Copy(sulfixoBytes, 0, mensagem, 3 + prefixoBytes.Length + Cabecalho.Length + dataFragment.Length, sulfixoBytes.Length);
Partes.Add(mensagem);
}
if (false)
{
string mensagemControle = " " + SerialService.EndLine + "\n";
byte[] beginLine = Encoding.UTF8.GetBytes(SerialService.BeginLine);
byte[] mensagemBytes = Encoding.UTF8.GetBytes(mensagemControle);
byte[] message = new byte[beginLine.Length + Cabecalho.Length + mensagemBytes.Length + 3];
message[0] = addressHigh;
message[1] = targetAddress;
message[2] = parametrosModel.channel;
Array.Copy(beginLine, 0, message, 3, beginLine.Length);
Array.Copy(Cabecalho, 0, message, 3 + beginLine.Length, Cabecalho.Length);
Array.Copy(mensagemBytes, 0, message, 3 + beginLine.Length + Cabecalho.Length, mensagemBytes.Length);
Partes.Add(message);
}
if (Enviar)
{
foreach (var parte in Partes)
{
bufferEnvio.Add(parte);
}
}
return Partes;
}
private static async Task LoopEnvioBuffer()
{
RotinaEnvioIniciada = true;
while (true)
{
var mensagens = bufferEnvio.ToList();
foreach (var buffer in mensagens)
{
EnviarComando(PortaLoRa, buffer);
await Task.Delay(1500);
}
mensagens.ForEach(x => bufferEnvio.Remove(x));
var mensagensAntigas = bufferRecebido.Where(x => x.Key.AddSeconds(10) <= DateTime.Now).ToList();
foreach (var item in mensagensAntigas)
{
bufferRecebido.Remove(item.Key);
}
await Task.Delay(500);
}
}
public static void EnviarComando(SerialPort _Porta, byte[] Comando)
{
if (_Porta != null)
{
if (!_Porta.IsOpen)
{
_Porta.Open();
}
if (_Porta.IsOpen)
{
_Porta.Write(Comando, 0, Comando.Length);
Console.WriteLine($"Dados enviados LoRa: {Comando.Length}");
}
}
}
private static byte[] ComandoConfigurarModulo()
{
byte[] command = new byte[] {
CodigosFuncoes["ComandoConfiguracao"],
0x00,
0x06,
0x00,
parametrosModel.address,
parametrosModel.baudAndAirRate,
parametrosModel.packetSizeAndPower,
parametrosModel.channel,
parametrosModel.tranModeAndWorCycle,
};
return command;
}
public static byte[] ComandoRequisitarParametros()
{
// caractere GET parametros, iniciando em qual registrador, quantidade registros
byte[] command = new byte[] { CodigosFuncoes["RespostaConfiguracao"], 0x00, 0x0b };
return command;
}
public static async Task EnviarPingComunicacao()
{
RotinaPingsIniciada = true;
while (true)
{
await Task.Delay(VariaveisEquipamento.TempoEntrePingsConexao);
if (!Variaveis.OperacaoEmAndamento.Iniciado)
{
Console.WriteLine("Enviando ping de comunicação para a base...");
EnviarDadosParaBase();
}
}
}
public static void EnviarDadosParaBase()
{
if (Iniciado && !Variaveis.IsAgroMonitor)
{
double velocidadeMax = MovimentacaoModel.CalculaVelocidadeRPM(Variaveis.OperacaoEmAndamento.Controle.RPM_Max);
double velocidadeMin = MovimentacaoModel.CalculaVelocidadeRPM(Variaveis.OperacaoEmAndamento.Controle.RPM_Min);
double TemperaturaCampo = WT901CService.Iniciado ? WT901CService.DadosLeitura.Temperatura : 0;
LoRaProtocoloTransmissaoModel dados = new LoRaProtocoloTransmissaoModel()
{
Momento = DateTime.Now,
EnderecoCarro = Variaveis.ConexaoLoRa.parametros.address,
Operacao = new LoRaProtocoloTransmissaoOperacaoModel()
{
idxRuaAtual = Variaveis.OperacaoEmAndamento.Sensoriamento.IdxRuaAtual,
statusOperacao = Variaveis.OperacaoEmAndamento.Sensoriamento.StatusOperacao,
statusCarro = Variaveis.OperacaoEmAndamento.Sensoriamento.StatusCarro,
TempoOperacao = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Tempo.TotalSeconds),
PercentualRua = Variaveis.OperacaoEmAndamento.OpMapaGPS.Sensoriamento.ProgressoRua,
PercentualOperacao = Variaveis.OperacaoEmAndamento.OpMapaGPS.Sensoriamento.ProgressoTrajeto,
TempoEstimado = Variaveis.OperacaoEmAndamento.TempoEstimado(velocidadeMax, velocidadeMin),
},
Coordenadas = new LoRaProtocoloTransmissaoCoordenadasModel()
{
Latitude = GPSService.UltimaLeitura.Latitude,
Longitude = GPSService.UltimaLeitura.Longitude,
},
Sensores = new LoRaProtocoloTransmissaoSensoresModel()
{
DistanciaPercorrida = Math.Round(Variaveis.OperacaoEmAndamento.Sensoriamento.DistanciaPercorrida.Sum(), 2),
ErvasIdentificadas = Variaveis.OperacaoEmAndamento.OpMapaGPS.Sensoriamento.ErvasIdentificadas,
OrientacaoCaminho = Math.Round(Variaveis.OperacaoEmAndamento.Sensoriamento.AnguloRua, 2),
PercentualBateria = Math.Round(Variaveis.OperacaoEmAndamento.Sensoriamento.PorcentagemBateria, 2),
PercentualReservatorio = Math.Round(Variaveis.OperacaoEmAndamento.DispAtu.Dados.PercentualReservatorio, 2),
PressaoLinha = Math.Round(Variaveis.OperacaoEmAndamento.DispAtu.Dados.PressaoLinha, 2),
TemperaturaMotores = Math.Round(Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos.Average(x => x.MovMotor.Temperatura), 2),
TemperaturaCampo = Math.Round(TemperaturaCampo, 2),
Velocidade = Math.Round(Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos.Average(x => x.MovMotor.VelocidadeInstantanea), 2),
HerbicidaConsumido = Math.Round(Variaveis.OperacaoEmAndamento.Sensoriamento.HerbicidaConsumido, 2),
HerbicidaPorErva = Math.Round(Variaveis.OperacaoEmAndamento.Sensoriamento.HerbicidaPorErva, 2),
}
};
byte[] dadosEnvio = LoRaSerializer.SerializeLoRaProtocoloTransmissaoModel(dados);
MontarMensagemEnvio(dadosEnvio, Variaveis.OperacaoEmAndamento.DispSen.Dados.LoRaParametrosBase.address, LoRaTipoProtocolo.DadosOperacao, true);
}
}
}
}