agrobot_base/AgroBase/AgroBase/Services/LoRaSerializer.cs

387 lines
17 KiB
C#

using AgroBase.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using static AgroBase.Models.Enums;
using static AgroBase.Services.LoRaEspService;
namespace AgroBase.Services
{
public class LoRaSerializer
{
public static byte[] SerializeLoRaProtocoloTransmissaoModel(LoRaProtocoloTransmissaoModel model)
{
List<byte> bytes = new List<byte>();
// Serializar Momento (DateTime)
bytes.AddRange(BitConverter.GetBytes(model.Momento.ToBinary()));
// Serializar EnderecoCarro (byte)
bytes.Add(model.EnderecoCarro);
// Serializar CodigoFalha (ulong)
bytes.AddRange(BitConverter.GetBytes(model.CodigoFalha));
// Serializar Coordenadas (LoRaProtocoloTransmissaoCoordenadasModel)
bytes.AddRange(BitConverter.GetBytes(model.Coordenadas.Latitude));
bytes.AddRange(BitConverter.GetBytes(model.Coordenadas.Longitude));
bytes.AddRange(BitConverter.GetBytes(model.Coordenadas.Orientacao));
// Serializar Sensores (LoRaProtocoloTransmissaoSensoresModel)
bytes.AddRange(BitConverter.GetBytes(model.Sensores.PercentualBateria));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.PercentualReservatorio));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.PressaoLinha));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.DistanciaPercorrida));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.OrientacaoCaminho));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.Velocidade));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.ErvasIdentificadas));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.TemperaturaMotores));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.TemperaturaCampo));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.HerbicidaConsumido));
bytes.AddRange(BitConverter.GetBytes(model.Sensores.HerbicidaPorErva));
// Serializar Operacao (LoRaProtocoloTransmissaoOperacaoModel)
bytes.Add((byte)model.Operacao.statusOperacao);
bytes.Add((byte)model.Operacao.statusCarro);
bytes.AddRange(BitConverter.GetBytes(model.Operacao.idxRuaAtual));
bytes.AddRange(BitConverter.GetBytes(model.Operacao.PercentualOperacao));
bytes.AddRange(BitConverter.GetBytes(model.Operacao.PercentualRua));
bytes.AddRange(BitConverter.GetBytes(model.Operacao.TempoOperacao));
// Serializar TempoEstimado (string)
byte[] tempoEstimadoBytes = Encoding.UTF8.GetBytes(model.Operacao.TempoEstimado);
bytes.AddRange(BitConverter.GetBytes(tempoEstimadoBytes.Length)); // Adiciona o comprimento da string
bytes.AddRange(tempoEstimadoBytes); // Adiciona a string
return bytes.ToArray();
}
public static LoRaProtocoloTransmissaoModel DeserializeLoRaProtocoloTransmissaoModel(byte[] bytes)
{
LoRaProtocoloTransmissaoModel model = new LoRaProtocoloTransmissaoModel();
int index = 0;
// Desserializar Momento (DateTime)
model.Momento = DateTime.FromBinary(BitConverter.ToInt64(bytes, index));
index += sizeof(long);
// Desserializar EnderecoCarro (byte)
model.EnderecoCarro = bytes[index];
index += sizeof(byte);
// Desserializar CodigoFalha (ulong)
model.CodigoFalha = BitConverter.ToUInt64(bytes, index);
index += sizeof(ulong);
// Desserializar Coordenadas (LoRaProtocoloTransmissaoCoordenadasModel)
model.Coordenadas = new LoRaProtocoloTransmissaoCoordenadasModel
{
Latitude = BitConverter.ToDouble(bytes, index),
Longitude = BitConverter.ToDouble(bytes, index + sizeof(double)),
Orientacao = BitConverter.ToDouble(bytes, index + 2 * sizeof(double))
};
index += 3 * sizeof(double);
// Desserializar Sensores (LoRaProtocoloTransmissaoSensoresModel)
model.Sensores = new LoRaProtocoloTransmissaoSensoresModel
{
PercentualBateria = BitConverter.ToDouble(bytes, index),
PercentualReservatorio = BitConverter.ToDouble(bytes, index + sizeof(double)),
PressaoLinha = BitConverter.ToDouble(bytes, index + 2 * sizeof(double)),
DistanciaPercorrida = BitConverter.ToDouble(bytes, index + 3 * sizeof(double)),
OrientacaoCaminho = BitConverter.ToDouble(bytes, index + 4 * sizeof(double)),
Velocidade = BitConverter.ToDouble(bytes, index + 5 * sizeof(double)),
ErvasIdentificadas = BitConverter.ToDouble(bytes, index + 6 * sizeof(double)),
TemperaturaMotores = BitConverter.ToDouble(bytes, index + 7 * sizeof(double)),
TemperaturaCampo = BitConverter.ToDouble(bytes, index + 8 * sizeof(double)),
HerbicidaConsumido = BitConverter.ToDouble(bytes, index + 9 * sizeof(double)),
HerbicidaPorErva = BitConverter.ToDouble(bytes, index + 10 * sizeof(double))
};
index += 11 * sizeof(double);
// Desserializar Operacao (LoRaProtocoloTransmissaoOperacaoModel)
model.Operacao = new LoRaProtocoloTransmissaoOperacaoModel
{
statusOperacao = (StatusOperacao)bytes[index],
statusCarro = (StatusCarroMapa)bytes[index + 1],
idxRuaAtual = BitConverter.ToInt32(bytes, index + 2),
PercentualOperacao = BitConverter.ToDouble(bytes, index + 2 + sizeof(int)),
PercentualRua = BitConverter.ToDouble(bytes, index + 2 + sizeof(int) + sizeof(double)),
TempoOperacao = BitConverter.ToInt32(bytes, index + 2 + sizeof(int) + 2 * sizeof(double))
};
index += 2 + sizeof(int) + 2 * sizeof(double) + sizeof(int);
// Desserializar TempoEstimado (string)
int stringLength = BitConverter.ToInt32(bytes, index);
index += sizeof(int);
model.Operacao.TempoEstimado = Encoding.UTF8.GetString(bytes, index, stringLength);
return model;
}
public static byte[] SerializeGPSModel(byte Endereco, GPSModel model)
{
List<byte> bytes = new List<byte>();
// Serializar Momento (DateTime)
bytes.AddRange(BitConverter.GetBytes(model.Momento.ToBinary()));
// Serializar EnderecoCarro (byte)
bytes.Add(Endereco);
// Serializar Coordenadas (LoRaProtocoloTransmissaoCoordenadasModel)
bytes.AddRange(BitConverter.GetBytes(model.Latitude));
bytes.AddRange(BitConverter.GetBytes(model.Longitude));
bytes.AddRange(BitConverter.GetBytes(model.OrientacaoReal));
return bytes.ToArray();
}
public static (byte, GPSModel) DeserializeGPSModel(byte[] bytes)
{
GPSModel model = new GPSModel();
int index = 0;
// Desserializar Momento (DateTime)
model.Momento = DateTime.FromBinary(BitConverter.ToInt64(bytes, index));
index += sizeof(long);
// Desserializar EnderecoCarro (byte)
byte Endereco = bytes[index];
index += sizeof(byte);
// Desserializar Coordenadas (LoRaProtocoloTransmissaoCoordenadasModel)
model.Latitude = BitConverter.ToDouble(bytes, index);
model.Longitude = BitConverter.ToDouble(bytes, index + sizeof(double));
model.CursoVerdadeiro = BitConverter.ToDouble(bytes, index + 2 * sizeof(double));
return (Endereco, model);
}
public static byte[] SerializeControleModel(OperacaoControleBaseModel model)
{
List<byte> bytes = new List<byte>();
// Serializar Momento (DateTime)
bytes.AddRange(BitConverter.GetBytes(model.Momento.ToBinary()));
// Serializar Tecla (int)
bytes.AddRange(BitConverter.GetBytes((int)model.Tecla));
// Serializar Dispositivo (int)
bytes.AddRange(BitConverter.GetBytes((int)model.Dispositivo));
// Serializar RPM
bytes.AddRange(BitConverter.GetBytes(model.PercentualVelocidadeSP));
// Serializar AnguloMP
bytes.AddRange(BitConverter.GetBytes(model.AnguloMP));
// Serializar VelocidadeMP
bytes.AddRange(BitConverter.GetBytes(model.VelocidadeMP));
// Serializar Emergencia
bytes.AddRange(BitConverter.GetBytes(model.Emergencia));
// Serializar TipoMovimento (int)
bytes.AddRange(BitConverter.GetBytes((int)model.TipoMovimento));
return bytes.ToArray();
}
public static OperacaoControleBaseModel DeserializeControleModel(byte[] bytes)
{
OperacaoControleBaseModel model = new OperacaoControleBaseModel();
int index = 0;
// Desserializar Momento (DateTime)
model.Momento = DateTime.FromBinary(BitConverter.ToInt64(bytes, index));
index += sizeof(long);
// Desserializar Tecla (int)
model.Tecla = (Keys)BitConverter.ToInt32(bytes, index);
index += sizeof(int);
// Desserializar Dispositivo (int)
model.Dispositivo = (T_Code)BitConverter.ToInt32(bytes, index);
index += sizeof(int);
// Desserializar RPM
model.PercentualVelocidadeSP = BitConverter.ToDouble(bytes, index);
index += sizeof(double);
// Desserializar AnguloMP
model.AnguloMP = BitConverter.ToDouble(bytes, index);
index += sizeof(double);
// Desserializar VelocidadeMP
model.VelocidadeMP = BitConverter.ToDouble(bytes, index);
index += sizeof(double);
// Desserializar Emergencia
model.Emergencia = BitConverter.ToBoolean(bytes, index);
index += sizeof(bool);
// Desserializar TipoMovimento (int)
model.TipoMovimento = (TipoMovimentoDirecional)BitConverter.ToInt32(bytes, index);
index += sizeof(int);
return model;
}
public static List<byte> CanPrefix(DadosLoRaParse dado)
{
return new List<byte>()
{
(byte)(CanMessagePosicaoDados)dado,
Variaveis.ID_Num_sLRA
};
}
public static List<byte[]> SerializeGPS(GPSModel Gps)
{
List<byte> _fix = new List<byte>();
_fix.AddRange(CanPrefix(DadosLoRaParse.GpsQualidade));
_fix.Add((byte)(Gps.Inicializado ? 1 : 0)); // 1 byte
_fix.Add((byte)Gps.QualidadeFix); // 1 byte
_fix.Add((byte)Gps.NumeroSatelites); // 1 byte
_fix.AddRange(CompactarDecimal(Gps.PrecisaoHorizontal)); // 2 bytes
List<byte> _lat = new List<byte>();
_lat.AddRange(CanPrefix(DadosLoRaParse.GpsLatitude));
_lat.AddRange(CompactarCoordenada(Gps.Latitude)); // 6 bytes
List<byte> _long = new List<byte>();
_long.AddRange(CanPrefix(DadosLoRaParse.GpsLongitude));
_long.AddRange(CompactarCoordenada(Gps.Longitude)); // 6 bytes
List<byte> _gerais = new List<byte>();
_gerais.AddRange(CanPrefix(DadosLoRaParse.GpsGerais));
_gerais.AddRange(CompactarDecimal(Gps.Altitude)); // 2 bytes
_gerais.AddRange(CompactarDecimal(Gps.Velocidade)); // 2 bytes
_gerais.AddRange(CompactarDecimal(Gps.OrientacaoReal)); // 2 bytes
return new List<byte[]>()
{
_lat.ToArray(),
_long.ToArray(),
_fix.ToArray(),
_gerais.ToArray(),
};
}
public static byte[] SerializeComandoControle(OperacaoControleBaseModel Controle)
{
List<byte> dados = new List<byte>();
dados.AddRange(CanPrefix(DadosLoRaParse.ComandoControle));
dados.Add((byte)Controle.Tecla); // 1 byte
dados.Add((byte)Controle.PercentualVelocidadeSP); // 1 byte
dados.Add((byte)Controle.TipoMovimento); // 1 byte
dados.Add((byte)Controle.AnguloMP); // 1 byte
//dados.Add((byte)Controle.VelocidadeMP); // 1 byte
dados.Add((byte)Controle.Dispositivo); // 1 byte
dados.Add((byte)(Controle.Emergencia ? 1 : 0)); // 1 byte
return dados.ToArray();
}
public static byte[] SerializeControleAtual(OperacaoControleModel Controle)
{
List<byte> dados = new List<byte>();
dados.AddRange(CanPrefix(DadosLoRaParse.DadosControle));
dados.Add((byte)Controle.Direcao); // 1 byte
dados.Add((byte)Controle.PercentualVelocidadeSP); // 1 byte
dados.Add((byte)Controle.TipoMovimento); // 1 byte
dados.Add((byte)Controle.Angulo); // 1 byte
dados.Add((byte)Controle.VelocidadeMP); // 1 byte
return dados.ToArray();
}
public static List<byte[]> SerializeOperacao(OperacaoSensoriamentoLogModel sensoriamento)
{
List<byte> _operacao = new List<byte>();
_operacao.AddRange(CanPrefix(DadosLoRaParse.DadosOperacao));
_operacao.Add((byte)(sensoriamento.StatusOperacao)); // 1 byte
_operacao.Add((byte)sensoriamento.Trajetoria.StatusCarro); // 1 byte
_operacao.Add((byte)Convert.ToInt32(sensoriamento.Trajetoria.PercentualOperacao)); // 1 byte
_operacao.Add((byte)Convert.ToInt32(sensoriamento.Trajetoria.PercentualRuaAtual)); // 1 byte
_operacao.Add((byte)sensoriamento.Trajetoria.IdxRuaAtual); // 1 byte
return new List<byte[]>()
{
_operacao.ToArray(),
};
}
public static List<byte[]> SerializeSensores(OperacaoSensoriamentoLogModel sensoriamento)
{
List<byte> _sensores = new List<byte>();
_sensores.AddRange(CanPrefix(DadosLoRaParse.DadosSensores));
_sensores.Add((byte)Convert.ToInt32(sensoriamento.Bateria.PorcentagemBateria)); // 1 byte
_sensores.Add((byte)Convert.ToInt32(sensoriamento.Movimentacao.TemperaturaMedia)); // 1 byte
_sensores.Add((byte)Convert.ToInt32(sensoriamento.Movimentacao.TemperaturaMedia)); // 1 byte
_sensores.Add((byte)Convert.ToInt32(sensoriamento.Trajetoria.AnguloCaminho)); // 1 byte
_sensores.Add((byte)Convert.ToInt32(sensoriamento.Movimentacao.VelocidadeMedia)); // 1 byte
List<byte> _pulverizador = new List<byte>();
_pulverizador.AddRange(CanPrefix(DadosLoRaParse.DadosPulverizador));
_pulverizador.Add((byte)Convert.ToInt32(sensoriamento.Atuador.PercentualReservatorio)); // 1 byte
_pulverizador.Add((byte)Convert.ToInt32(sensoriamento.Atuador.PressaoLinha)); // 1 byte
//_pulverizador.Add((byte)Convert.ToInt32(sensoriamento.Atuador.ErvasIdentificadas.Sum(x => x.Values.Sum()))); // 1 byte
_pulverizador.Add((byte)Convert.ToInt32(0)); // 1 byte
_pulverizador.Add((byte)Convert.ToInt32(sensoriamento.Atuador.HerbicidaConsumido)); // 1 byte
_pulverizador.Add((byte)Convert.ToInt32(sensoriamento.Atuador.HerbicidaPorErva)); // 1 byte
_pulverizador.Add((byte)Convert.ToInt32(sensoriamento.Atuador.PercentualErvasTerreno)); // 1 byte
return new List<byte[]>()
{
_sensores.ToArray(),
_pulverizador.ToArray(),
};
}
private static byte[] CompactarDecimal(double precisaoCm)
{
ushort valor = (ushort)Math.Round(precisaoCm); // Arredonda para inteiro
return BitConverter.GetBytes(valor); // 2 bytes (little endian)
}
public static double DescompactarDecimal(byte[] payload, int offset)
{
ushort valor = BitConverter.ToUInt16(payload, offset); // Lê 2 bytes
return (double)valor; // Volta para double
}
private static byte[] CompactarCoordenada(double valor)
{
long inteiro = (long)(valor * 1e7); // Precisão de 7 casas decimais
byte[] bytes = BitConverter.GetBytes(inteiro); // 8 bytes little endian
return bytes.Take(6).ToArray(); // Pega só os 6 bytes menos significativos
}
public static double DescompactarCoordenada(byte[] payload)
{
if (payload.Length < 6)
throw new ArgumentException("Payload deve ter pelo menos 6 bytes");
// Monta os 8 bytes de volta, fazendo extensão de sinal manual
byte[] full = new byte[8];
Array.Copy(payload, 0, full, 0, 6);
// Se o bit mais significativo (6º byte) tem sinal negativo, completa com 0xFF
bool negativo = (payload[5] & 0x80) != 0;
full[6] = (byte)(negativo ? 0xFF : 0x00);
full[7] = (byte)(negativo ? 0xFF : 0x00);
long inteiro = BitConverter.ToInt64(full, 0);
return inteiro / 1e7;
}
}
}