179 lines
7.1 KiB
C#
179 lines
7.1 KiB
C#
using AgroBase.Models;
|
|
using AgroBase.Models.Modules;
|
|
using static AgroBase.Models.Enums;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using System.Diagnostics;
|
|
|
|
namespace AgroBase.Services
|
|
{
|
|
public class LoRaEspService
|
|
{
|
|
public string ID { get; set; }
|
|
public int ID_Num { get; set; }
|
|
public S_Code Componente { get; set; }
|
|
public bool Conectado { get; set; }
|
|
public bool Configurado { get; set; }
|
|
public bool Iniciado
|
|
{
|
|
get
|
|
{
|
|
return Conectado && Configurado;
|
|
}
|
|
}
|
|
public double FrequenciaEnvioDadosBase { get; set; } = 0.2;
|
|
public double TempoEnvioDadosBase
|
|
{
|
|
get
|
|
{
|
|
return 1.0 / FrequenciaEnvioDadosBase * 1000.0;
|
|
}
|
|
}
|
|
public double UltimoRxDados { get; set; } = 0;
|
|
public DateTime _ultimoRxDados { get; set; } = DateTime.MinValue;
|
|
public double UltimoTxDados { get; set; } = 0;
|
|
public DateTime _ultimoTxDados { get; set; } = DateTime.MinValue;
|
|
public LoRaParametrosModel ParametrosSet { get; set; } = new LoRaParametrosModel();
|
|
public LoRaParametrosModel ParametrosGet { get; set; } = new LoRaParametrosModel();
|
|
public List<FuncoesPinout> Funcoes { get; set; }
|
|
public List<LoRaMensagemModel> MensagensRecebidasAvulsas { get; set; } = new List<LoRaMensagemModel>();
|
|
|
|
public List<(int, CanMessagePosicaoDados, byte[])> ProtocoloConfiguracao(PinoutDataModel Pinout, bool conectar)
|
|
{
|
|
List<byte> config1 = new List<byte>();
|
|
var _pinout = Pinout.Clone();
|
|
_pinout.Pinos = _pinout.Pinos.Where(x => x.ComponenteID == ID).ToList();
|
|
if (_pinout.Pinos.Count > 0)
|
|
{
|
|
byte[] pinos = PinoutModel.PinoProtocolo(_pinout, Funcoes, false);
|
|
config1.AddRange(pinos);
|
|
}
|
|
|
|
List<byte> config2 = new List<byte>
|
|
{
|
|
Variaveis.LoraBaseParametros?.address ?? 0x01,
|
|
ParametrosSet.address,
|
|
ParametrosSet.baudAndAirRate,
|
|
ParametrosSet.packetSizeAndPower,
|
|
ParametrosSet.channel,
|
|
ParametrosSet.tranModeAndWorCycle
|
|
};
|
|
|
|
//Console.WriteLine($"Parametros de configuracao LoRa: {FuncoesGlobais.ConverterComandoBytesParaTexto(config2.ToArray())}");
|
|
|
|
return new List<(int, CanMessagePosicaoDados, byte[])>()
|
|
{
|
|
(ID_Num, CanMessagePosicaoDados.Config1, config1.ToArray()),
|
|
(ID_Num, CanMessagePosicaoDados.Config2, config2.ToArray()),
|
|
};
|
|
}
|
|
|
|
public async Task<(bool, LoRaParametrosModel)> RequisitarParametrosModulo()
|
|
{
|
|
DateTime inicio = DateTime.Now;
|
|
bool sucesso = false;
|
|
Variaveis.OperacaoEmAndamento.DispSen?.Dados?.RequisitarDadosModulo(Variaveis.ID_Num_sLRA, CanMessagePosicaoDados.Command1, CanMessagePosicaoDados.Dados1, true);
|
|
while (!sucesso && inicio.AddMilliseconds(2000) > DateTime.Now)
|
|
{
|
|
await Task.Delay(10);
|
|
sucesso = ParametrosGet.UltimaLeitura < inicio;
|
|
}
|
|
return (sucesso, ParametrosGet);
|
|
}
|
|
|
|
public async Task<(bool, LoRaParametrosModel)> RedefinirParametros(LoRaParametrosModel parametros)
|
|
{
|
|
ParametrosSet = parametros.Clone();
|
|
Configurado = false;
|
|
|
|
DateTime inicio = DateTime.Now;
|
|
Variaveis.OperacaoEmAndamento.DispSen?.EnviarProtocolosConfiguracao(true);
|
|
bool configurado() => Configurado;
|
|
await FuncoesGlobais.AguardarCondicaoAsync(configurado, 2000, 100);
|
|
return (Configurado, ParametrosGet);
|
|
}
|
|
|
|
public bool EnviarDadosLoRaViaCAN(byte[] payload)
|
|
{
|
|
if (payload == null) return false;
|
|
|
|
if (payload.Length > 8) return false;
|
|
|
|
CanMessagePosicaoDados posicao = ((CanMessagePosicaoDados)payload[0]);
|
|
byte idNum = payload[1];
|
|
|
|
Variaveis.OperacaoEmAndamento.DispSen?.AdicionarMensagemFila(idNum, posicao, posicao, payload.Skip(2).ToArray(), false);
|
|
UltimoTxDados = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
|
|
_ultimoTxDados = DateTime.UtcNow;
|
|
return true;
|
|
}
|
|
|
|
public void EnviarDadosParaBase()
|
|
{
|
|
if (!Iniciado) return;
|
|
|
|
var now = DateTime.UtcNow; // evite DST
|
|
|
|
// --- parâmetros (ajuste) ---
|
|
int minIntervaloTxMs = (int)TempoEnvioDadosBase; // mínimo entre TXs do rover
|
|
int beaconPeriodoMs = VariaveisEquipamento.TempoEntrePingsConexao; // p.ex. 10000
|
|
int janelaMinMs = 1000; // só responda >= 1 s após o beacon
|
|
int guardaProximoMs = 2000; // e não responda nos últimos 2 s antes do próximo beacon
|
|
|
|
// --- idades ---
|
|
double ageTxMs = (now - _ultimoTxDados).TotalMilliseconds;
|
|
double ageRxMs = (now - _ultimoRxDados).TotalMilliseconds;
|
|
|
|
// 1) respeite intervalo mínimo entre TX
|
|
if (ageTxMs < minIntervaloTxMs) return;
|
|
|
|
// 2) valide janela após o último beacon
|
|
if (ageRxMs < janelaMinMs) return; // cedo demais
|
|
if (ageRxMs > beaconPeriodoMs - guardaProximoMs) return; // já muito perto do próximo beacon
|
|
|
|
// (opcional) se o último beacon já “caducou” (perdeu pings), não envie
|
|
if (ageRxMs > beaconPeriodoMs + 2000) return;
|
|
|
|
// --- ENVIO (ideal: agregue em 1-2 frames) ---
|
|
var s = Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura;
|
|
|
|
foreach (var dado in LoRaSerializer.SerializeGPS(s.Gps))
|
|
Variaveis.LoraService?.EnviarDadosLoRaViaCAN(dado);
|
|
|
|
foreach (var dado in LoRaSerializer.SerializeOperacao(s))
|
|
Variaveis.LoraService?.EnviarDadosLoRaViaCAN(dado);
|
|
|
|
foreach (var dado in LoRaSerializer.SerializeSensores(s))
|
|
Variaveis.LoraService?.EnviarDadosLoRaViaCAN(dado);
|
|
|
|
Variaveis.LoraService?.EnviarDadosLoRaViaCAN(LoRaSerializer.SerializeControleAtual(s.Controle));
|
|
}
|
|
|
|
|
|
public enum DadosLoRaParse
|
|
{
|
|
DadosLivre = (int)CanMessagePosicaoDados.Command2,
|
|
GpsQualidade = (int)CanMessagePosicaoDados.Command3,
|
|
GpsLatitude = (int)CanMessagePosicaoDados.Command4,
|
|
GpsLongitude = (int)CanMessagePosicaoDados.Command5,
|
|
GpsGerais = (int)CanMessagePosicaoDados.Command6,
|
|
ComandoControle = (int)CanMessagePosicaoDados.Command7,
|
|
DadosControle = (int)CanMessagePosicaoDados.Command8,
|
|
DadosOperacao = (int)CanMessagePosicaoDados.Command9,
|
|
DadosSensores = (int)CanMessagePosicaoDados.Command10,
|
|
DadosPulverizador = (int)CanMessagePosicaoDados.Command11,
|
|
}
|
|
|
|
public enum LoRaCaracteresEspeciais
|
|
{
|
|
BeginMsg = 0xAA,
|
|
BreakLine = 0xBB,
|
|
EndMsg = 0x55
|
|
}
|
|
|
|
|
|
}
|
|
}
|