782 lines
30 KiB
C#
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);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|