agrobot_base/AgroBase/OperationControl/Models/Variaveis.cs

528 lines
24 KiB
C#

using AgroBase.Models;
using Newtonsoft.Json;
using System.Diagnostics;
using OperationControl.Services;
using AgroMonitor;
using Application = System.Windows.Application;
using AgroBase.Models.Operacoes;
namespace OperationControl.Models
{
public class Variaveis
{
public static MqttService MqttService;
public static GpsService GpsService;
public static UdpReliableChannel UdpChannel;
public static ManualControlSender ControlSenderDir;
public static ManualControlSender ControlSenderMov;
public static void MostrarLog(string message)
{
Debug.WriteLine(message);
}
public static async void IniciarMQTT()
{
if (MqttService != null)
{
foreach (var topico in MqttService.Topicos.Where(x => x.Inscrever))
{
await MqttService.UnsubscribeAsync(topico);
}
MqttService.Topicos.Clear();
}
MqttService = new MqttService("localhost", 1883, "base", true, msg => MostrarLog($"[MQTT localhost:1883] - {msg}"));
await MqttService.AdicionarNovoTopico(VariaveisMonitoramento.TopicoMqttPosicao);
await MqttService.AdicionarNovoTopico(VariaveisMonitoramento.TopicoMqttRTCM);
await MqttService.AdicionarNovoTopico(VariaveisMonitoramento.TopicoMqttDispositivos, true, 1, async (message) =>
{
try
{
var p = message.Mensagem.Split(',');
string device_id = p[0];
string device_ip = p[1];
VariaveisControleOperacao.AdicionarNovoRoverNaRede(device_id, device_ip);
}
catch (Exception ex)
{
MostrarLog($"Erro ao deserializar ping do rover: {ex.Message}");
}
});
GpsService = new GpsService();
}
public static void IniciarUDP()
{
UdpChannel = new UdpReliableChannel
{
EnableHeartbeat = true,
HeartbeatIntervalMs = 1000,
HeartbeatPayload = new byte[] { 0 }
};
UdpChannel.Start(VariaveisPortas.Ethernet_UDP_TX);
ControlSenderDir = new ManualControlSender(UdpChannel, (byte)AgroBase.Models.Enums.T_Code.Dir);
ControlSenderDir.Start();
ControlSenderMov = new ManualControlSender(UdpChannel, (byte)AgroBase.Models.Enums.T_Code.Mov);
ControlSenderMov.Start();
}
}
public class VariaveisControleOperacao
{
public static double LeverArmFrontal { get; } = 0.0; // cm
public static double LeverArmLateral { get; } = 0.0; // cm
public static readonly string BaseMarkerID = "BASE";
private static readonly object _RoversLock = new object();
private static double TempoRoverVivo = 5.0;
private static bool AdicionandoNovoRover = false;
private static bool AtualizandoListaRovers = false;
public static AgroBase.Models.Enums.StatusModulo StatusBase
{
get
{
if ((Variaveis.GpsService?.IsConnected ?? false) && (Variaveis.GpsService?.BaseFix?.CorrecaoAbsoluta ?? false))
return AgroBase.Models.Enums.StatusModulo.Operante;
if (Variaveis.GpsService?.IsConnected ?? false)
return AgroBase.Models.Enums.StatusModulo.Alerta;
return AgroBase.Models.Enums.StatusModulo.Desconectado;
}
}
public static List<OperacaoParametrosModel> RoversNaRede { get; set; } = new List<OperacaoParametrosModel>();
public static string SelectedRoverId { get; set; } = BaseMarkerID;
public static OperacaoParametrosModel? RoverEmFoco => RoversNaRede.FirstOrDefault(x => x.RoverId == SelectedRoverId);
public static bool BaseEmFoco => SelectedRoverId == BaseMarkerID;
public static async void AdicionarNovoRoverNaRede(string device_id, string device_ip)
{
if (AdicionandoNovoRover) return;
AdicionandoNovoRover = true;
try
{
if (string.IsNullOrEmpty(device_id))
return;
bool rover_ja_adicionado = false;
lock (_RoversLock)
{
rover_ja_adicionado = RoversNaRede.Any(x => x.RoverId == device_id);
}
if (!rover_ja_adicionado)
{
lock (_RoversLock)
{
RoversNaRede.Add(new OperacaoParametrosModel()
{
RoverId = device_id,
IP = device_ip,
Configurado = false,
Alive = true,
DadosLeitura = new OperacaoParametrosDadosModel()
{
Momento = DateTime.Now
}
});
}
bool t_hbt_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttHeartbeat.Replace("<id>", device_id));
if (!t_hbt_added)
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttHeartbeat.Replace("<id>", device_id));
bool t_cmd_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", device_id));
if (!t_cmd_added)
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", device_id));
bool t_tel_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttTelemetria.Replace("<id>", device_id));
if (!t_tel_added)
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttTelemetria.Replace("<id>", device_id), true, 1, async (message) =>
{
try
{
string json = message.Mensagem;
if (string.IsNullOrEmpty(json)) return;
var obj = JsonConvert.DeserializeObject<OperacaoParametrosDadosModel>(json);
if (obj == null) return;
lock (_RoversLock)
{
var rover = RoversNaRede.FirstOrDefault(x => x.RoverId == device_id);
if (rover != null)
{
obj.Momento = DateTime.Now;
var logs = rover.DadosLeitura?.Logs ?? new List<OperacaoSensoriamentoLogErrosModel>();
obj.Logs?.InsertRange(0, logs);
rover.DadosLeitura = obj;
rover.UltimoContato = DateTime.Now;
}
}
((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(device_id);
}
catch (Exception ex)
{
Variaveis.MostrarLog($"Erro ao deserializar dados de telemetria do rover {device_id}: {ex.Message}");
}
});
bool t_par_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttParametros.Replace("<id>", device_id));
if (!t_par_added)
await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttParametros.Replace("<id>", device_id), true, 1, async (message) =>
{
try
{
string json = message.Mensagem;
if (string.IsNullOrEmpty(json)) return;
var obj = JsonConvert.DeserializeObject<OperacaoParametrosModel>(json);
lock (_RoversLock)
{
var rover = RoversNaRede.FirstOrDefault(x => x.RoverId == device_id);
if (rover != null)
{
obj.UltimoContato = DateTime.Now;
obj.IP = rover.IP;
RoversNaRede.Remove(rover);
RoversNaRede.Add(obj);
}
}
((App)Application.Current).Shell.Main?.AtualizarDadosTela_ParametrosOperacao(obj.Controle);
((App)Application.Current).Shell.Main?.MAP?.CarregarDadosMapa(obj.Mapa, obj.RuasPercorrer);
}
catch (Exception ex)
{
Variaveis.MostrarLog($"Erro ao deserializar dados de parametros do rover {device_id}: {ex.Message}");
}
});
List<string> dispositivos_ids = new List<string>() { "BASE" };
lock (_RoversLock)
{
dispositivos_ids = dispositivos_ids.Union(RoversNaRede.Select(x => x.RoverId).ToList()).ToList();
}
((App)Application.Current).Shell.Main?.AtualizarListaDispositivos(dispositivos_ids);
RequisitarParametrosOperacao();
}
}
finally
{
AdicionandoNovoRover = false;
}
}
public static async void AtualizarListaRoversNaRede()
{
if (AtualizandoListaRovers) return;
AtualizandoListaRovers = true;
try
{
var rovers_atual = new List<OperacaoParametrosModel>();
lock (_RoversLock)
{
rovers_atual = new List<OperacaoParametrosModel>(RoversNaRede);
}
foreach (var rover in rovers_atual)
{
rover.Alive = (DateTime.Now - rover.UltimoContato).TotalSeconds < TempoRoverVivo;
if (!rover.Alive)
{
//((App)Application.Current).Shell.Main?.MAP?.markers?.UpdateMarkerInfo(rover.RoverId, status: AgroBase.Models.Enums.StatusOperacao.Erro);
rover.DadosLeitura = new OperacaoParametrosDadosModel();
rover.DadosLeitura.Momento = DateTime.Now;
if (rover.DadosLeitura.Operacao == null) rover.DadosLeitura.Operacao = new OperacaoParametrosDadosOperacaoModel();
rover.DadosLeitura.Operacao.Status = AgroBase.Models.Enums.StatusOperacao.Erro;
((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(rover.RoverId);
((App)Application.Current).Shell.Main?.AdicionarAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
}
else
{
((App)Application.Current).Shell.Main?.RemoverAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb);
}
}
}
finally
{
AtualizandoListaRovers = false;
}
}
public static async void EnviarDadosHeartbeat()
{
var topicos = Variaveis.MqttService.Topicos.Where(x => x.Topico.Contains(VariaveisEquipamento.TopicoMqttHeartbeat.Split("/")[VariaveisEquipamento.TopicoMqttHeartbeat.Split("/").Length - 1]));
foreach (var topico in topicos)
{
await Variaveis.MqttService.PublishAsync(topico, "0");
}
}
private static async void EnviarDadosControle(string rover_id, OperacaoComandoBaseModel controle)
{
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == VariaveisEquipamento.TopicoMqttComandos.Replace("<id>", rover_id));
if (topico != null)
{
string json = JsonConvert.SerializeObject(controle);
await Variaveis.MqttService.PublishAsync(topico, json);
}
}
public static async void EnviarDadosPosicao(GPSModel posicao)
{
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == VariaveisMonitoramento.TopicoMqttPosicao);
if (topico != null)
{
string json = JsonConvert.SerializeObject(posicao);
await Variaveis.MqttService.PublishAsync(topico, json);
}
}
public static async void EnviarDadosCorrecaoRTCM(byte[] correcao)
{
var topico = Variaveis.MqttService.Topicos.FirstOrDefault(x => x.Topico == VariaveisMonitoramento.TopicoMqttRTCM);
if (topico != null)
{
await Variaveis.MqttService.PublishAsync(topico, correcao);
}
}
#region Controle
public static void EnviarComandoIniciarUDP(string ipRover, bool iniciar)
{
if (iniciar)
Variaveis.UdpChannel.SetRemote(ipRover, VariaveisPortas.Ethernet_UDP_RX);
else
Variaveis.UdpChannel.SetRemote(null, VariaveisPortas.Ethernet_UDP_RX);
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Ipb,
_comp_value = iniciar
});
}
public static void EnviarComandoIniciarOperacao(bool iniciar, bool simulador = false)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Mod,
Tecla = simulador ? AgroBase.Models.Enums.BotoesJoystick.L1 : iniciar ? AgroBase.Models.Enums.BotoesJoystick.L2 : AgroBase.Models.Enums.BotoesJoystick.L3
});
}
public static void EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code disp, bool ligar, AgroBase.Models.Enums.TipoFrameCamera tipoFrame)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = disp,
Tecla = ligar ? AgroBase.Models.Enums.BotoesJoystick.L1 : AgroBase.Models.Enums.BotoesJoystick.Vazio,
_comp_value = tipoFrame
});
}
public static void EnviarComandoParada(bool? emergencia = null, bool? pausa = null)
{
var cmd = new OperacaoComandoBaseModel() { Momento = DateTime.Now };
if (emergencia != null) cmd.Emergencia = (bool)emergencia;
if (pausa != null) cmd.Pausa = (bool)pausa;
if (emergencia != null || pausa != null)
EnviarDadosControle(SelectedRoverId, cmd);
}
public static Task EnviarComandoParadaUDP(bool emergencia = false, bool pausa = false)
{
var msg = new UdpCtrlMessage
{
Device = (byte)AgroBase.Models.Enums.T_Code.Vzo,
Flags = (emergencia ? UdpCtrlFlags.Emergencia : 0) | (pausa ? UdpCtrlFlags.Pausa : 0)
};
return Variaveis.UdpChannel.SendBurstAsync(0x01, msg.ToBytes(), count: 6, intervalMs: 25, requestAck: false);
}
public static void EnviarComandoReferenciamento(string mod_id = null)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Dir,
Tecla = AgroBase.Models.Enums.BotoesJoystick.R3,
_comp_id = mod_id
});
}
public static void EnviarComandoLeverArm(double? lateral = null, double? frontal = null)
{
var cmd = new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Gps,
_comp_value = (lateral, frontal)
};
EnviarDadosControle(SelectedRoverId, cmd);
}
public static void EnviarParametrosOperacao(OperacaoParametrosModel parametros)
{
bool operacao_iniciada = (RoverEmFoco?.DadosLeitura?.Operacao?.Iniciada ?? false);
bool parametros_parciais = parametros.Modo == null;
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Mod,
Parametros = parametros,
Tecla = (operacao_iniciada || parametros_parciais ? AgroBase.Models.Enums.BotoesJoystick.Touchpad : AgroBase.Models.Enums.BotoesJoystick.Options)
});
}
public static void EnviarConfirmacaoHumanaTrajetoria(int idx_corredor, bool bat_liberada, bool herb_liberado)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Mod,
Tecla = AgroBase.Models.Enums.BotoesJoystick.R1,
_comp_value = (idx_corredor, bat_liberada, herb_liberado)
});
}
public static void EnviarComandoCoolerControl(AgroBase.Services.CoolerControlService.CoolerMode modo, AgroBase.Models.Enums.Estado? entrada = null, AgroBase.Models.Enums.Estado? saida = null, double? temp_on = null, double? temp_turbo = null)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Npc,
_comp_value = (modo, entrada, saida, temp_on, temp_turbo)
});
}
public static void RequisitarParametrosOperacao()
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Mod,
Tecla = AgroBase.Models.Enums.BotoesJoystick.Share
});
}
private static AgroBase.Models.Enums.BotoesJoystick DeParaDirecaoTecla(AgroBase.Models.Enums.Direcao direcao)
{
switch (direcao)
{
case AgroBase.Models.Enums.Direcao.Esquerda:
return AgroBase.GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.key == Keys.Left)?.botaoJoy ?? AgroBase.Models.Enums.BotoesJoystick.Vazio;
case AgroBase.Models.Enums.Direcao.Direita:
return AgroBase.GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.key == Keys.Right)?.botaoJoy ?? AgroBase.Models.Enums.BotoesJoystick.Vazio;
case AgroBase.Models.Enums.Direcao.Cima:
return AgroBase.GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.key == Keys.Up)?.botaoJoy ?? AgroBase.Models.Enums.BotoesJoystick.Vazio;
case AgroBase.Models.Enums.Direcao.Baixo:
return AgroBase.GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.key == Keys.Down)?.botaoJoy ?? AgroBase.Models.Enums.BotoesJoystick.Vazio;
default:
return AgroBase.Models.Enums.BotoesJoystick.Vazio;
}
}
public static void EnviarComandoDirecional(AgroBase.Models.Enums.Direcao direcao, double angulo, AgroBase.Models.Enums.TipoMovimentoDirecional movimento, string mod_id = null)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Dir,
Tecla = DeParaDirecaoTecla(direcao),
_comp_id = mod_id,
Controle = new OperacaoComandoBaseControleModel()
{
AnguloSP = angulo,
TipoMovimentoDirecional = movimento
},
});
}
public static void EnviarComandoDirecionalUDP(AgroBase.Models.Enums.Direcao direcao, double angulo, AgroBase.Models.Enums.TipoMovimentoDirecional tipoMov)
{
var key = DeParaDirecaoTecla(direcao);
var msg = new UdpCtrlMessage
{
Device = (byte)AgroBase.Models.Enums.T_Code.Dir,
Flags = UdpCtrlFlags.HasKey | UdpCtrlFlags.HasPayload,
Key = key,
P1 = (short)Math.Max(short.MinValue, Math.Min(short.MaxValue, (int)Math.Round(angulo * 100.0))),
P2 = (short)tipoMov
};
//return Variaveis.UdpChannel.SendBurstAsync(0x01, msg.ToBytes(), count: 6, intervalMs: 25, requestAck: false);
Variaveis.ControlSenderDir.Update(msg);
}
public static void EnviarComandoMovimentacao(AgroBase.Models.Enums.Direcao direcao, double velocidade)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Mov,
Tecla = DeParaDirecaoTecla(direcao),
Controle = new OperacaoComandoBaseControleModel()
{
PercentualVelocidadeSP = velocidade
}
});
}
public static void EnviarComandoMovimentacaoUDP(AgroBase.Models.Enums.Direcao direcao, double velPct)
{
var key = DeParaDirecaoTecla(direcao);
var msg = new UdpCtrlMessage
{
Device = (byte)AgroBase.Models.Enums.T_Code.Mov,
Flags = UdpCtrlFlags.HasKey | UdpCtrlFlags.HasPayload,
Key = key,
P1 = (short)Math.Max(short.MinValue, Math.Min(short.MaxValue, (int)Math.Round(velPct * 100.0))),
P2 = 0
};
//return Variaveis.UdpChannel.SendBurstAsync(0x01, msg.ToBytes(), count: 6, intervalMs: 25, requestAck: false);
Variaveis.ControlSenderMov.Update(msg);
}
public static void EnviarComandoAtuador(string componente_id, bool? status = null, int? angulo_controle = null, double? angulo_abertura = null, double? altura = null)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Atu,
_comp_id = componente_id,
_comp_value = angulo_abertura,
Controle = new OperacaoComandoBaseControleModel()
{
AnguloSP = angulo_controle,
Estado = status,
Altura = altura,
}
});
}
public static void EnviarComandoSensoriamento(string componente_id, dynamic status)
{
EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel()
{
Momento = DateTime.Now,
Dispositivo = AgroBase.Models.Enums.T_Code.Sen,
_comp_id = componente_id,
_comp_value = status
});
}
#endregion
}
}