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 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 { string device_id = message.Mensagem; VariaveisControleOperacao.AdicionarNovoRoverNaRede(message.Mensagem); } catch (Exception ex) { MostrarLog($"Erro ao deserializar ping do rover: {ex.Message}"); } }); GpsService = new GpsService(); } } 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 RoversNaRede { get; set; } = new List(); 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) { 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, Configurado = false, Alive = true, DadosLeitura = new OperacaoParametrosDadosModel() { Momento = DateTime.Now } }); } bool t_hbt_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttHeartbeat.Replace("", device_id)); if (!t_hbt_added) await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttHeartbeat.Replace("", device_id)); bool t_cmd_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttComandos.Replace("", device_id)); if (!t_cmd_added) await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttComandos.Replace("", device_id)); bool t_tel_added = Variaveis.MqttService.Topicos.Any(x => x.Topico == VariaveisEquipamento.TopicoMqttTelemetria.Replace("", device_id)); if (!t_tel_added) await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttTelemetria.Replace("", device_id), true, 1, async (message) => { try { string json = message.Mensagem; if (string.IsNullOrEmpty(json)) return; var obj = JsonConvert.DeserializeObject(json); if (obj == null) return; lock (_RoversLock) { var rover = RoversNaRede.FirstOrDefault(x => x.RoverId == device_id); if (rover != null) { obj.Momento = DateTime.Now; 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("", device_id)); if (!t_par_added) await Variaveis.MqttService.AdicionarNovoTopico(VariaveisEquipamento.TopicoMqttParametros.Replace("", device_id), true, 1, async (message) => { try { string json = message.Mensagem; if (string.IsNullOrEmpty(json)) return; var obj = JsonConvert.DeserializeObject(json); lock (_RoversLock) { var rover = RoversNaRede.FirstOrDefault(x => x.RoverId == device_id); if (rover != null) { obj.UltimoContato = DateTime.Now; 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 dispositivos_ids = new List() { "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(); lock (_RoversLock) { rovers_atual = new List(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("", 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 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) { EnviarDadosControle(SelectedRoverId, new OperacaoComandoBaseModel() { Momento = DateTime.Now, Dispositivo = disp, Tecla = ligar ? AgroBase.Models.Enums.BotoesJoystick.L1 : AgroBase.Models.Enums.BotoesJoystick.Vazio }); } 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 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 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 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 } }