agrobot_base/AgroBase/OperationControl/Windows/MainWindow.xaml.cs

1346 lines
61 KiB
C#
Raw Normal View History

using System.Windows;
2025-11-26 20:00:16 +00:00
using ScottPlot;
using System.Windows.Threading;
using OperationControl.Controls;
2025-11-14 17:11:58 +00:00
using OperationControl.Models;
using System.Windows.Controls;
using System.Windows.Media;
2025-11-24 16:05:50 +00:00
using LibVLCSharp.Shared;
2025-11-24 19:58:20 +00:00
using System.Windows.Input;
2025-11-24 16:05:50 +00:00
using System.IO;
2025-11-24 19:58:20 +00:00
using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;
2025-11-24 16:05:50 +00:00
using ComboBox = System.Windows.Controls.ComboBox;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
2025-11-24 19:58:20 +00:00
using Brush = System.Windows.Media.Brush;
using Brushes = System.Windows.Media.Brushes;
using Label = System.Windows.Controls.Label;
namespace OperationControl.Windows
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
// buffers (X = tempo em segundos)
2025-11-26 20:00:16 +00:00
private DateTime? _tempoInicioAcompanhamento;
private List<double> pltAcompanhamento_x = new();
private List<List<double>> pltAcompanhamento_y = new();
2025-11-24 16:05:50 +00:00
private LibVLC _libVLC;
private MediaPlayer _playerFront;
private MediaPlayer _playerWeed;
private Media _mediaFront;
private Media _mediaWeed;
2025-11-24 19:58:20 +00:00
private Label _labelModuloSelecionado;
public MainWindow()
{
InitializeComponent();
2025-11-14 17:11:58 +00:00
AtualizarListaDispositivos(new List<string>() { VariaveisControleOperacao.SelectedRoverId });
2025-11-26 20:00:16 +00:00
2025-11-26 20:00:16 +00:00
//DataContext = this;
// atualizar as caixas
2025-11-14 17:11:58 +00:00
//BBoxes3D.SetBboxes(new[]
//{
// new AgroBase.Models.LivoxBboxModel{ cx=1.2, cy=0.5, cz=0.4, d=0.6, w=0.4, h=0.8 },
// new AgroBase.Models.LivoxBboxModel{ cx=3.0, cy=-0.7, cz=0.6, d=0.8, w=0.5, h=1.2 },
//});
2025-11-24 16:05:50 +00:00
// Opções focadas em baixa latência
_libVLC = new LibVLC(
"--network-caching=1000", // ms (ajusta depois)
"--clock-jitter=0",
"--clock-synchro=0"
);
// Player da câmera frontal
_playerFront = new MediaPlayer(_libVLC);
VideoFront.MediaPlayer = _playerFront;
_playerWeed = new MediaPlayer(_libVLC);
VideoWeed.MediaPlayer = _playerWeed;
Loaded += MainWindow_Loaded;
Closed += MainWindow_Closed;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
}
2025-11-24 16:05:50 +00:00
private void MainWindow_Closed(object? sender, EventArgs e)
{
PararStreamCameraFrontal(true);
PararStreamCameraErvas(true);
_libVLC?.Dispose();
}
2025-11-14 17:11:58 +00:00
#region DISPOSITIVOS
public void AtualizarListaDispositivos(List<string> dispositivos)
{
2025-11-24 16:05:50 +00:00
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
try
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
cmbDispositivo.Items.Clear();
foreach (var d in dispositivos)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
cmbDispositivo.Items.Add(d);
if (!MAP.markers.Added(d))
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
if (d == VariaveisControleOperacao.BaseMarkerID)
{
MAP.markers.AddMarker(
d,
true,
lat: Variaveis.GpsService?.UltimaLeitura?.Latitude ?? 0,
lon: Variaveis.GpsService?.UltimaLeitura?.Longitude ?? 0,
heading: Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal ?? 0,
label: "Base"
);
}
else
{
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == d);
if (rover != null)
{
MAP.markers.AddMarker(
d,
false,
lat: rover.DadosLeitura?.Gps?.Latitude ?? 0,
lon: rover.DadosLeitura?.Gps?.Longitude ?? 0,
heading: rover.DadosLeitura?.Gps?.AnguloCarroDefinido ?? 0
);
}
}
2025-11-14 17:11:58 +00:00
}
}
2025-11-24 16:05:50 +00:00
int idx_selected = dispositivos.IndexOf(VariaveisControleOperacao.SelectedRoverId);
if (idx_selected > -1)
cmbDispositivo.SelectedIndex = idx_selected;
2025-11-14 17:11:58 +00:00
}
2025-11-24 16:05:50 +00:00
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI lista dispositivos: {exUi.Message}");
}
}));
2025-11-14 17:11:58 +00:00
}
private void cmbDispositivo_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
2025-11-24 16:05:50 +00:00
var selecionado = ((ComboBox)sender).SelectedItem;
if (selecionado == null) return;
bool dados_base = selecionado == VariaveisControleOperacao.BaseMarkerID;
if (dados_base && !VariaveisControleOperacao.BaseEmFoco)
{
PararStreamCameraFrontal();
PararStreamCameraErvas();
}
VariaveisControleOperacao.SelectedRoverId = selecionado.ToString();
MAP.markers.SetMarkerFocused(selecionado.ToString(), true);
AtualizarDadosTela_Telemetria(selecionado.ToString());
brdResumo.IsEnabled = !dados_base;
brdDiagnostico.IsEnabled = !dados_base;
brdControle.IsEnabled = !dados_base;
brdAjustesOperacao.IsEnabled = !dados_base;
if (!dados_base)
{
sldGNSS_LeverArm.Value = VariaveisControleOperacao.RoverEmFoco.DadosLeitura?.Gps?.LeverArmLateral ?? 0;
btnParametros_Atualizar_Click(sender, e);
IniciarStreamCameraFrontal();
IniciarStreamCameraErvas();
}
2025-11-14 17:11:58 +00:00
}
2025-11-24 16:05:50 +00:00
public void LimparDadosTela_Telemetria(string rover_id)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
if (!string.IsNullOrEmpty(rover_id))
{
//MAP.markers.RemoveMarker(rover_id);
//cmbDispositivo.Items.Remove(rover_id);
}
else
{
//cmbDispositivo.SelectedIndex = 0;
}
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI telemetria (clear): {exUi.Message}");
}
}));
2025-11-14 17:11:58 +00:00
}
public void AtualizarDadosTela_Telemetria(string rover_id)
{
2025-11-24 16:05:50 +00:00
bool dados_base = rover_id == VariaveisControleOperacao.BaseMarkerID;
2025-11-24 19:58:20 +00:00
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == rover_id);
var dados_leitura = rover?.DadosLeitura;
2025-11-24 16:05:50 +00:00
if (dados_base)
{
MAP.markers.UpdateMarkerPosition(rover_id, lat: Variaveis.GpsService?.UltimaLeitura?.Latitude, lon: Variaveis.GpsService?.UltimaLeitura?.Longitude, heading: Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal);
}
2025-11-24 19:58:20 +00:00
else if (dados_leitura != null)
2025-11-24 16:05:50 +00:00
{
2025-11-24 19:58:20 +00:00
var simulacao = dados_leitura.Controle?.SimulacaoMPC?.Select(x => new double[] { x.longitude, x.latitude })?.ToList();
2025-11-26 20:00:16 +00:00
MAP.markers.UpdateMarkerPosition(rover_id, lat: dados_leitura.Gps?.Latitude, lon: dados_leitura.Gps?.Longitude, heading: dados_leitura.Gps?.OrientacaoReal, predict: simulacao);
2025-11-24 19:58:20 +00:00
MAP.markers.UpdateMarkerInfo(rover_id, status: dados_leitura.StatusOperacao);
2025-11-24 16:05:50 +00:00
}
2025-11-14 17:11:58 +00:00
if (rover_id != VariaveisControleOperacao.SelectedRoverId) return;
2025-11-24 16:05:50 +00:00
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
try
{
if (rover_id == VariaveisControleOperacao.BaseMarkerID)
{
Variaveis.MostrarLog($"Atualizando dados da tela para a base");
2025-11-14 17:11:58 +00:00
2025-11-26 20:00:16 +00:00
lblDispositivos_Status.Content = VariaveisControleOperacao.StatusBase.ToString();
AplicarStatusModuloNaLabel(lblDispositivos_Status, VariaveisControleOperacao.StatusBase, true, false);
2025-11-24 16:05:50 +00:00
AtualizarDadosTela_GNSS(Variaveis.GpsService?.UltimaLeitura ?? new AgroBase.Models.GPSModel(), marker_id: VariaveisControleOperacao.BaseMarkerID);
AtualizarDadosTela_Heading(Variaveis.GpsService?.UltimaLeitura?.AnguloCarroDefinido ?? 0);
}
else
{
2025-11-24 19:58:20 +00:00
if (dados_leitura == null) return;
2025-11-24 16:05:50 +00:00
Variaveis.MostrarLog($"Atualizando dados da tela para o dispositivo {rover_id}");
2025-11-26 20:00:16 +00:00
lblDispositivos_Status.Content = (rover?.DadosLeitura?.Status ?? AgroBase.Models.Enums.StatusModulo.Desconectado).ToString();
AplicarStatusModuloNaLabel(lblDispositivos_Status, rover?.DadosLeitura?.Status ?? AgroBase.Models.Enums.StatusModulo.Desconectado, true, false);
2025-11-24 19:58:20 +00:00
AtualizarDadosTela_Diagnosticos(rover);
if (dados_leitura.Trajetoria != null)
AtualizarDadosTela_Resumo(dados_leitura);
if (dados_leitura.Gps != null)
AtualizarDadosTela_GNSS(dados_leitura.Gps, marker_id: rover_id);
if (dados_leitura.Controle != null)
AtualizarDadosTela_Controle(dados_leitura.Controle, dados_leitura.Movimentacao.AnguloMedio, dados_leitura.Movimentacao.VelocidadeMedia, dados_leitura.Emergencia, !dados_leitura.OperacaoIniciada, dados_leitura.StatusOperacao == AgroBase.Models.Enums.StatusOperacao.Calibrando);
2025-11-24 16:05:50 +00:00
//if (rover.Value.Controle != null)
// AtualizarDadosTela_ParametrosOperacao(rover.Value.Controle);
2025-11-24 19:58:20 +00:00
if (dados_leitura.Trajetoria != null)
AtualizarDadosTela_Mapa(dados_leitura.Trajetoria);
if (dados_leitura.Gps != null)
AtualizarDadosTela_Heading(dados_leitura.Gps.AnguloCarroDefinido, dados_leitura.Modo == AgroBase.Models.Enums.ModoOperacao.Manual ? double.NaN : dados_leitura.Trajetoria.AnguloCaminho);
if (dados_leitura.IMU != null)
AtualizarDadosTela_IMU(dados_leitura.IMU.InclinacaoLateral, dados_leitura.IMU.InclinacaoFrontal);
if (dados_leitura.LivoxLidar != null)
AtualizarDadostela_LIDAR(dados_leitura.LivoxLidar.bboxes);
2025-11-24 16:05:50 +00:00
}
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI telemetria (set): {exUi.Message}");
}
}));
}
#endregion
#region RESUMO OPERACIONAL
public void AtualizarDadosTela_Resumo(AgroBase.Models.OperacaoSensoriamentoLogModel dados)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
try
{
pgbResumo_RuaAtual.Value = dados.Trajetoria.PercentualRuaAtual;
2025-11-26 20:00:16 +00:00
lblResumo_RuaAtual.Content = $"{dados.Trajetoria.CorredorAtual.DistanciaPercorridaCorredor.ToString("0.00")} m / {dados.Trajetoria.CorredorAtual.DistanciaTotal.ToString("0.00")} m ({dados.Trajetoria.CorredorAtual.Idx + 1})";
2025-11-24 16:05:50 +00:00
pgbResumo_AreaTotal.Value = dados.Trajetoria.PercentualOperacao;
2025-11-26 20:00:16 +00:00
lblResumo_AreaTotal.Content = $"{dados.Trajetoria.DistanciaPercorrida.ToString("0.00")} m / {dados.Trajetoria.DistanciaTotal.ToString("0.00")} m";
2025-11-24 16:05:50 +00:00
pgbResumo_Bateria.Value = dados.Bateria.PorcentagemBateria;
2025-11-26 20:00:16 +00:00
lblResumo_Bateria.Content = $"{dados.Bateria.TensaoInstantanea.ToString("0.00")} V ({TimeSpan.FromMinutes(dados.Bateria.TempoEstimadoRestanteMinutos)})";
2025-11-24 16:05:50 +00:00
pgbResumo_Herbicida.Value = dados.Atuador.PercentualReservatorio;
2025-11-26 20:00:16 +00:00
lblResumo_Herbicida.Content = $"{dados.Atuador.VolumeReservatorio.ToString("0.00")} L ({0.ToString("0.00")} m)";
2025-11-24 16:05:50 +00:00
pgbResumo_Infestacao.Value = dados.Atuador.PercentualErvasTerreno;
lblResumo_Infestacao.Content = $"{dados.Atuador.VazaoMedia.ToString("0.00")}";
pgbResumo_Conexao.Value = 0;
lblResumo_Conexao.Content = $"0,0 dBi (0,00 m)";
lblResumo_OperacaoLiberada.Content = $"Operação " + (dados.OperacaoLiberada ? "🔓 Liberada" : "🔒 Bloqueada");
lblResumo_OperacaoModo.Content = $"Modo {dados.Modo}";
lblResumo_OperacaoStatus.Content = $"Status {dados.StatusOperacao}" + (dados.StatusOperacao == AgroBase.Models.Enums.StatusOperacao.Aguardando ? $" ({dados.TempoAguardandoSeg.ToString("0")})" : "");
lblResumo_StatusCarro.Content = $"Carro {dados.Trajetoria.StatusCarro}";
lblResumo_TemperaturaGeral.Content = $"Temperatura {(dados.DadosPerformance.CPU_temp ?? 0).ToString("0.00")} °C";
2025-11-26 20:00:16 +00:00
lblResumo_OperacaoDuracao.Content = $"Duração {dados.TempoDecorrido.ToString("HH:mm:ss")} / " + (string.IsNullOrEmpty(dados.Trajetoria.TempoEstimadoOperacao) ? "00:00:00" : dados.Trajetoria.TempoEstimadoOperacao);
2025-11-24 16:05:50 +00:00
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Resumo: {exUi.Message}");
}
}));
}
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
#endregion
2025-11-14 17:11:58 +00:00
2025-11-24 19:58:20 +00:00
#region DIAGNOSTICOS
private void AtualizarDadosTela_Diagnosticos(AgroBase.Models.Operacoes.OperacaoParametrosModel dados)
{
lblDiagnosticos_Impedimento.Text = "Impedimento: " + (string.IsNullOrEmpty(dados.DadosLeitura.ErroOperacaoLiberada) ? "Nenhum" : dados.DadosLeitura.ErroOperacaoLiberada.Replace("\n\n", "; "));
2025-11-24 19:58:20 +00:00
// Canvas que está dentro do Border
var canvas = brdDiagnostico.Child as Canvas;
if (canvas == null)
return;
// Percorre apenas labels dentro do Canvas com o prefixo desejado
foreach (var lbl in canvas.Children.OfType<Label>().Where(x => x.Name.StartsWith("lblDiagnosticos_")))
{
2025-11-26 20:00:16 +00:00
(var modulo, var mod_label, var s_code) = GetModuleData(lbl);
2025-11-24 19:58:20 +00:00
if (modulo == AgroBase.Models.Enums.T_Code.Vzo)
continue;
// Procura a saúde desse módulo
var saude = dados.DadosLeitura.ModulosSaude.FirstOrDefault(x => x.modulo == modulo);
if (saude == null && false)
2025-11-24 19:58:20 +00:00
continue;
var individual = saude?.saude_individual?.FirstOrDefault(x => x.label == mod_label);
2025-11-24 19:58:20 +00:00
bool em_uso = mod_label != "" ? dados.DadosLeitura.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == modulo)?.ComponentesEmUso?.Any(x => x.Key == mod_label && x.Value) ?? false : dados.ModulosMandatorios?.Any(x => x.Dispositivo == modulo && x.Utilizar) ?? false;
2025-11-24 19:58:20 +00:00
// Aplica cor de acordo com o status
AplicarStatusModuloNaLabel(lbl, individual?.status ?? saude?.status ?? AgroBase.Models.Enums.StatusModulo.Desconectado, em_uso);
2025-11-24 19:58:20 +00:00
}
2025-11-26 20:00:16 +00:00
PreencherAbaAcompanhamento(false);
PreencherAbaOpcoes(false);
2025-11-24 19:58:20 +00:00
}
2025-11-26 20:00:16 +00:00
private void AplicarStatusModuloNaLabel(Label lbl, AgroBase.Models.Enums.StatusModulo status, bool mandatorio, bool icone = true)
2025-11-24 19:58:20 +00:00
{
// você pode ajustar essas cores depois
Brush back;
Brush fore = Brushes.White;
switch (status)
{
case AgroBase.Models.Enums.StatusModulo.Desconectado:
back = mandatorio ? Brushes.Red : Brushes.Gray;
break;
case AgroBase.Models.Enums.StatusModulo.Conectado:
back = Brushes.SteelBlue;
break;
case AgroBase.Models.Enums.StatusModulo.Falha:
back = Brushes.Red;
break;
case AgroBase.Models.Enums.StatusModulo.Alerta:
back = Brushes.Orange;
break;
case AgroBase.Models.Enums.StatusModulo.Operante:
back = Brushes.Green;
break;
default:
back = Brushes.DarkGray;
break;
}
lbl.Background = back;
lbl.Foreground = fore;
2025-11-26 20:00:16 +00:00
if (icone)
{
string text = lbl.Content?.ToString() ?? "";
text = text.Remove(0, 2);
lbl.Content = (mandatorio ? "🔒" : "🔓") + text;
}
2025-11-24 19:58:20 +00:00
}
2025-11-26 20:00:16 +00:00
private (AgroBase.Models.Enums.T_Code, string, AgroBase.Models.Enums.S_Code) GetModuleData(Label lbl)
2025-11-24 19:58:20 +00:00
{
2025-11-26 20:00:16 +00:00
if (lbl == null) return (AgroBase.Models.Enums.T_Code.Vzo, "", AgroBase.Models.Enums.S_Code.sVZO);
2025-11-24 19:58:20 +00:00
string lbl_name = lbl.Name.Replace("lblDiagnosticos_", "");
string[] pts = lbl_name.Split('_');
string mod_name = pts[0];
string mod_label = pts.Length > 1 ? pts[1] : "";
if (!Enum.TryParse<AgroBase.Models.Enums.T_Code>(mod_name, ignoreCase: true, out var modulo))
2025-11-26 20:00:16 +00:00
return (AgroBase.Models.Enums.T_Code.Vzo, "", AgroBase.Models.Enums.S_Code.sVZO);
2025-11-24 19:58:20 +00:00
2025-11-26 20:00:16 +00:00
string tag = (lbl.Tag ?? "sVZO").ToString();
Enum.TryParse<AgroBase.Models.Enums.S_Code>(tag, ignoreCase: true, out var s_code);
return (modulo, mod_label, s_code);
2025-11-24 19:58:20 +00:00
}
private void DiagnosticoModulo_Click(object sender, MouseButtonEventArgs e)
{
if (sender is not Label lbl)
return;
// desfazer seleção antiga
if (_labelModuloSelecionado != null)
{
_labelModuloSelecionado.BorderBrush = Brushes.Transparent;
_labelModuloSelecionado.BorderThickness = new Thickness(1);
_labelModuloSelecionado.Effect = null;
}
// selecionar a nova
_labelModuloSelecionado = lbl;
_labelModuloSelecionado.BorderBrush = Brushes.Yellow;
_labelModuloSelecionado.BorderThickness = new Thickness(2);
// opcional — glow bonito
_labelModuloSelecionado.Effect = new System.Windows.Media.Effects.DropShadowEffect
{
Color = System.Windows.Media.Colors.Yellow,
BlurRadius = 8,
ShadowDepth = 0,
Opacity = 0.9
};
AtualizarDetalhesModulo();
2025-11-25 12:17:19 +00:00
}
private void AtualizarDetalhesModulo()
2025-11-25 12:17:19 +00:00
{
2025-11-26 20:00:16 +00:00
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
2025-11-24 19:58:20 +00:00
if (modulo == AgroBase.Models.Enums.T_Code.Vzo)
return;
2025-11-25 12:17:19 +00:00
var rover = VariaveisControleOperacao.RoverEmFoco;
var saude = rover?.DadosLeitura?.ModulosSaude?.FirstOrDefault(x => x.modulo == modulo);
var dispositivo = rover?.DadosLeitura?.DispositivosMapeados?.FirstOrDefault(x => x.Dispositivo == modulo && x.Mod_ID == label);
if (dispositivo == null && saude == null && false)
2025-11-25 12:17:19 +00:00
{
MessageBox.Show($"Sem dados para o módulo {modulo} ({label})");
return;
}
var individual = saude?.saude_individual?.FirstOrDefault(x => x.label == label);
var status = individual?.status ?? saude?.status ?? AgroBase.Models.Enums.StatusModulo.Desconectado;
var motivos = string.Join(", ", (individual?.motivos ?? saude?.motivos) ?? new List<string>());
2025-11-25 12:17:19 +00:00
lblSaude_Descricao.Content = $"Módulo {modulo} {label}";
lblSaude_Versao.Content = $"Versão {dispositivo?.Versao ?? "-"}";
lblSaude_Status.Content = $"{individual?.status ?? saude?.status ?? AgroBase.Models.Enums.StatusModulo.Desconectado} (Saúde {individual?.saude ?? saude?.saude ?? 0}%)";
lblSaude_CAN.Content = $"CAN {dispositivo?.VelocidadeBarramento ?? 0} ms";
lblSaude_Latencia.Content = $"Latência {dispositivo?.Latencia ?? 0} ms";
lblSaude_Impedimento.Text = $"Impedimento: {motivos ?? "Nenhum"}";
2025-11-25 12:17:19 +00:00
bool mandatorio = rover?.ModulosMandatorios?.Any(x => x.Dispositivo == modulo && x.Mandatorio) ?? false;
//var cu = rover?.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == modulo)?.ComponentesEmUso.FirstOrDefault(x => x.Key == label);
//bool em_uso = individual?.em_uso ?? (cu?.Key != null ? cu?.Value : null) ?? rover?.ModulosMandatorios?.Any(x => x.Dispositivo == modulo && x.Utilizar) ?? false;
//bool em_uso = rover?.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == modulo)?.ComponentesEmUso?.Any(x => x.Key == label) ?? false;
bool em_uso = label != "" ? rover?.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == modulo)?.ComponentesEmUso?.Any(x => x.Key == label && x.Value) ?? false : rover?.ModulosMandatorios?.Any(x => x.Dispositivo == modulo && x.Utilizar) ?? false;
2025-11-25 12:17:19 +00:00
chbSaude_Mandatorio.IsChecked = mandatorio;
chbSaude_EmUso.IsChecked = em_uso;
lstSaude_CondicoesOperacionais.Items.Clear();
if (saude?.condicoes_operacionais != null)
{
foreach (var cond in saude.condicoes_operacionais)
{
lstSaude_CondicoesOperacionais.Items.Add($"{cond.descricao} (Valor: {cond.valor}, Severidade: {cond.severidade:0}%)");
}
}
2025-11-26 20:00:16 +00:00
PreencherAbaAcompanhamento(true);
PreencherAbaOpcoes(true);
}
2025-11-26 20:00:16 +00:00
private void PreencherAbaAcompanhamento(bool inicial)
{
2025-11-26 20:00:16 +00:00
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
if (modulo == AgroBase.Models.Enums.T_Code.Vzo)
return;
2025-11-26 20:00:16 +00:00
var momento = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Momento ?? DateTime.Now;
if (_tempoInicioAcompanhamento is null || inicial)
_tempoInicioAcompanhamento = momento;
bool refresh = true;
double tSegundos = (momento - _tempoInicioAcompanhamento.Value).TotalSeconds;
if (inicial)
{
pltSaude_Acompanhamento.Plot.ShowLegend(Alignment.UpperLeft);
pltAcompanhamento_x = new List<double>();
}
pltAcompanhamento_x.Add(tSegundos);
// mantém só últimos 60 s
while (pltAcompanhamento_x.Count > 60)
{
pltAcompanhamento_x.RemoveAt(0);
pltAcompanhamento_y.ForEach(x => x.RemoveAt(0));
}
switch (modulo)
{
case AgroBase.Models.Enums.T_Code.Sen:
{
if (s_code == AgroBase.Models.Enums.S_Code.sCOR)
{
var sensor = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Bateria?.Barramentos?.FirstOrDefault(x => x.ID == label);
if (sensor == null) return;
if (inicial)
{
pltAcompanhamento_y = new List<List<double>>()
{
new List<double>(), // Corrente
new List<double>(), // Tensao
new List<double>(), // Potencia
new List<double>(), // Energia
new List<double>() // Temperatura
};
}
pltAcompanhamento_y[0].Add(sensor.Corrente);
pltAcompanhamento_y[1].Add(sensor.Tensao);
pltAcompanhamento_y[2].Add(sensor.Potencia);
pltAcompanhamento_y[3].Add(sensor.Energia);
pltAcompanhamento_y[4].Add(sensor.Temperatura);
// redesenha (v5: passe arrays diretamente)
pltSaude_Acompanhamento.Plot.Clear();
// Corrente (A)
var scCorr = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[0].ToArray());
scCorr.Label = $"Corrente {sensor.Corrente:0.00} mA";
scCorr.Color = ScottPlot.Colors.Cyan;
scCorr.LineWidth = 2;
// Tensão (V)
var scVolt = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[1].ToArray());
scVolt.Label = $"Tensão {sensor.Tensao:0.00} V";
scVolt.Color = ScottPlot.Colors.Lime;
scVolt.LineWidth = 2;
// Potencia (W)
var scPot = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[2].ToArray());
scPot.Label = $"Potencia {sensor.Potencia:0.00} mW";
scPot.Color = ScottPlot.Colors.Magenta;
scPot.LineWidth = 2;
// Energia (J)
var scEner = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[3].ToArray());
scEner.Label = $"Energia {sensor.Energia:0.00} J";
scEner.Color = ScottPlot.Colors.Violet;
scEner.LineWidth = 2;
// Temperatura (°C)
var scTemp = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[4].ToArray());
scTemp.Label = $"Temp {sensor.Temperatura} °C";
scTemp.Color = ScottPlot.Colors.Yellow;
scTemp.LineWidth = 2;
}
else if (s_code == AgroBase.Models.Enums.S_Code.sNTC)
{
var sensor = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Temperaturas?.FirstOrDefault(x => x.Key == label).Value;
if (sensor == null) return;
if (inicial)
{
pltAcompanhamento_y = new List<List<double>>()
{
new List<double>() // Temperatura
};
}
pltAcompanhamento_y[0].Add(sensor.Value);
// redesenha (v5: passe arrays diretamente)
pltSaude_Acompanhamento.Plot.Clear();
// Temperatura (°C)
var scTemp = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[0].ToArray());
scTemp.Label = $"Temp {sensor.Value} °C";
scTemp.Color = ScottPlot.Colors.Yellow;
scTemp.LineWidth = 2;
}
else
{
refresh = false;
}
}
break;
case AgroBase.Models.Enums.T_Code.Atu:
{
if (s_code == AgroBase.Models.Enums.S_Code.sMAS)
{
var vol = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Atuador?.VolumeReservatorio ?? -1;
var pct = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Atuador?.PercentualReservatorio ?? -1;
if (inicial)
{
pltAcompanhamento_y = new List<List<double>>()
{
new List<double>(), // Volume
new List<double>(), // Percentual
};
}
pltAcompanhamento_y[0].Add(vol);
pltAcompanhamento_y[1].Add(pct);
// redesenha (v5: passe arrays diretamente)
pltSaude_Acompanhamento.Plot.Clear();
// Volume (L)
var scVol = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[0].ToArray());
scVol.Label = $"Volume {vol:0.00} L";
scVol.Color = ScottPlot.Colors.Cyan;
scVol.LineWidth = 2;
// Percentual (%)
var scPct = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[1].ToArray());
scPct.Label = $"Reservatorio {pct:0.00} %";
scPct.Color = ScottPlot.Colors.Lime;
scPct.LineWidth = 2;
}
else if (s_code == AgroBase.Models.Enums.S_Code.sFLX)
{
double flx = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Atuador?.VazaoInstantanea ?? -1;
if (inicial)
{
pltAcompanhamento_y = new List<List<double>>()
{
new List<double>() // Vazao
};
}
pltAcompanhamento_y[0].Add(flx);
// redesenha (v5: passe arrays diretamente)
pltSaude_Acompanhamento.Plot.Clear();
// Vazao (mL/S)
var scFlx = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[0].ToArray());
scFlx.Label = $"Vazao {flx} mL/s";
scFlx.Color = ScottPlot.Colors.Yellow;
scFlx.LineWidth = 2;
}
else if (s_code == AgroBase.Models.Enums.S_Code.sPRS)
{
double prs = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Atuador?.PressaoLinha ?? -1;
if (inicial)
{
pltAcompanhamento_y = new List<List<double>>()
{
new List<double>() // Pressao
};
}
pltAcompanhamento_y[0].Add(prs);
// redesenha (v5: passe arrays diretamente)
pltSaude_Acompanhamento.Plot.Clear();
// Pressao (psi)
var scPrs = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[0].ToArray());
scPrs.Label = $"Pressao {prs} psi";
scPrs.Color = ScottPlot.Colors.Yellow;
scPrs.LineWidth = 2;
}
else if (s_code == AgroBase.Models.Enums.S_Code.sBMB)
{
var pot = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Atuador?.LeituraPotenciaBomba ?? -1;
var prs = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Atuador?.PressaoLinha ?? -1;
if (inicial)
{
pltAcompanhamento_y = new List<List<double>>()
{
new List<double>(), // Potencia
new List<double>(), // Pressao
};
}
pltAcompanhamento_y[0].Add(pot);
pltAcompanhamento_y[1].Add(prs);
2025-11-26 20:00:16 +00:00
// redesenha (v5: passe arrays diretamente)
pltSaude_Acompanhamento.Plot.Clear();
2025-11-26 20:00:16 +00:00
// Potencia (%)
var scPot = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[0].ToArray());
scPot.Label = $"Potencia {pot:0.00} %";
scPot.Color = ScottPlot.Colors.Cyan;
scPot.LineWidth = 2;
2025-11-26 20:00:16 +00:00
// Pressao (psi)
var scPrs = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[1].ToArray());
scPrs.Label = $"Pressao {prs:0.00} psi";
scPrs.Color = ScottPlot.Colors.Lime;
scPrs.LineWidth = 2;
}
else
{
refresh = false;
}
break;
}
case AgroBase.Models.Enums.T_Code.Mov:
{
var mod = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Movimentacao?.Dados?.FirstOrDefault(x => x.ID == label);
if (mod == null) return;
if (inicial)
{
pltAcompanhamento_y = new List<List<double>>()
{
new List<double>(), // Tensao
new List<double>(), // Corrente Motor
new List<double>(), // Corrente Barramento
new List<double>(), // Ciclo Trabalho
new List<double>(), // Temperatura
new List<double>(), // RPM roda
};
}
pltAcompanhamento_y[0].Add(mod.Tensao);
pltAcompanhamento_y[1].Add(mod.Corrente_Motor);
pltAcompanhamento_y[2].Add(mod.Corrente_Barramento);
pltAcompanhamento_y[3].Add(mod.CicloTrabalho);
pltAcompanhamento_y[4].Add(mod.RPM_Roda);
// redesenha (v5: passe arrays diretamente)
pltSaude_Acompanhamento.Plot.Clear();
// Tensão (V)
var scVolt = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[0].ToArray());
scVolt.Label = $"Tensão {mod.Tensao:0.00} V";
scVolt.Color = ScottPlot.Colors.Lime;
scVolt.LineWidth = 2;
// Corrente (A)
var scCorm = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[1].ToArray());
scCorm.Label = $"Corrente M {mod.Corrente_Motor:0.00} A";
scCorm.Color = ScottPlot.Colors.Cyan;
scCorm.LineWidth = 2;
// Corrente (A)
var scCorb = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[2].ToArray());
scCorb.Label = $"Corrente B {mod.Corrente_Barramento:0.00} A";
scCorb.Color = ScottPlot.Colors.Red;
scCorb.LineWidth = 2;
// Ciclo de Trabalho (%)
var scEner = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[3].ToArray());
scEner.Label = $"Ciclo % {mod.CicloTrabalho:0.00} ";
scEner.Color = ScottPlot.Colors.Violet;
scEner.LineWidth = 2;
// Temperatura (°C)
var scTemp = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[4].ToArray());
scTemp.Label = $"Temp {mod.TemperaturaDriver} °C";
scTemp.Color = ScottPlot.Colors.Yellow;
scTemp.LineWidth = 2;
// RPM roda
var scRpm = pltSaude_Acompanhamento.Plot.Add.Scatter(pltAcompanhamento_x.ToArray(), pltAcompanhamento_y[5].ToArray());
scRpm.Label = $"RPM {mod.RPM_Roda}";
scRpm.Color = ScottPlot.Colors.Blue;
scRpm.LineWidth = 2;
}
break;
default:
pltSaude_Acompanhamento.Plot.Clear();
refresh = false;
break;
}
if (refresh || inicial)
{
2025-11-26 20:00:16 +00:00
// janela de 60 s rolando
double xEnd = pltAcompanhamento_x[^1];
double xStart = Math.Max(0, xEnd - 60.0);
pltSaude_Acompanhamento.Plot.Axes.SetLimitsX(xStart, xEnd);
pltSaude_Acompanhamento.Plot.Axes.AutoScaleY(); // ajusta Y automaticamente para caber tudo
pltSaude_Acompanhamento.Refresh();
}
}
2025-11-26 20:00:16 +00:00
private void PreencherAbaOpcoes(bool inicial)
{
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
if (modulo == AgroBase.Models.Enums.T_Code.Vzo)
return;
if (inicial)
{
txtOpcoes_SemDados.Visibility = Visibility.Collapsed;
panelOpcoes_Bico.Visibility = Visibility.Collapsed;
panelOpcoes_Bomba.Visibility = Visibility.Collapsed;
}
switch (s_code)
{
case AgroBase.Models.Enums.S_Code.sBIC:
{
panelOpcoes_Bico.Visibility = Visibility.Visible;
var rover = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura;
var bico = rover?.Controle?.BicosAtuados?.FirstOrDefault(x => x.ID == label);
bool comando = bico?.ComandoAtuar ?? false;
var leitura = bico?.ValoresLeituras?.FirstOrDefault(x => x.funcao == AgroBase.Models.Modules.FuncoesPinout.EstadoLeitura)?.atual?.valor;
txtBico_Titulo.Text = $"Bico {label} - Testes";
txtBico_Comando.Text = comando ? "Ligado" : "Desligado";
txtBico_StatusReal.Text = leitura != null && (AgroBase.Models.Enums.Estado)Enum.Parse(typeof(AgroBase.Models.Enums.Estado), leitura.ToString(), true) == AgroBase.Models.Enums.Estado.Ligado ? "Ligado" : "Desligado";
txtBico_TempoLigado.Text = (bico?.TempoAtuado ?? 0).ToString("0.00") + " ms";
txtBico_Vazao.Text = (bico?.MediaNivelFluxo ?? 0).ToString("0.00") + " L/min";
txtBico_Pressao.Text = (rover?.Atuador?.PressaoLinha ?? 0).ToString("0.00") + " psi";
txtBico_Atuacoes.Text = (bico?.Atuacoes ?? 0).ToString();
break;
}
case AgroBase.Models.Enums.S_Code.sBMB:
{
panelOpcoes_Bomba.Visibility = Visibility.Visible;
var rover = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura;
bool comando = rover?.Atuador?.ComandoBomba ?? false;
bool leitura = rover?.Atuador?.LeituraComandoBomba ?? false;
var potencia = rover?.Atuador?.LeituraPotenciaBomba ?? 0;
txtBomba_Comando.Text = comando ? "Ligado" : "Desligado";
txtBomba_StatusReal.Text = leitura ? "Ligado" : "Desligado";
txtBomba_PressaoLinha.Text = (rover?.Atuador?.PressaoLinha ?? 0).ToString("0.00") + " psi";
txtBomba_Potencia.Text = potencia.ToString("0") + " %";
break;
}
default:
txtOpcoes_SemDados.Visibility = Visibility.Visible;
break;
}
}
private void sldBico_Angular_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
lblBico_Angulo.Content = $"{Convert.ToInt32(sldBico_Angular.Value)}°";
}
private void btnBico_Ligar_Click(object sender, RoutedEventArgs e)
{
2025-11-26 20:00:16 +00:00
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
if (modulo != AgroBase.Models.Enums.T_Code.Atu && s_code != AgroBase.Models.Enums.S_Code.sBIC)
return;
VariaveisControleOperacao.EnviarComandoAtuador(label, true);
}
private void btnBico_Desligar_Click(object sender, RoutedEventArgs e)
{
2025-11-26 20:00:16 +00:00
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
if (modulo != AgroBase.Models.Enums.T_Code.Atu && s_code != AgroBase.Models.Enums.S_Code.sBIC)
return;
VariaveisControleOperacao.EnviarComandoAtuador(label, false);
2025-11-24 19:58:20 +00:00
}
2025-11-26 20:00:16 +00:00
private void btnBomba_Ligar_Click(object sender, RoutedEventArgs e)
{
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
if (modulo != AgroBase.Models.Enums.T_Code.Atu && s_code != AgroBase.Models.Enums.S_Code.sBMB)
return;
VariaveisControleOperacao.EnviarComandoAtuador(label, true);
}
private void btnBomba_Desligar_Click(object sender, RoutedEventArgs e)
{
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
if (modulo != AgroBase.Models.Enums.T_Code.Atu && s_code != AgroBase.Models.Enums.S_Code.sBMB)
return;
VariaveisControleOperacao.EnviarComandoAtuador(label, false);
}
private void sldBomba_PressaoAlvo_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
lblBomba_PressaoAlvo.Content = $"{e.NewValue:0} psi";
}
2025-11-25 12:17:19 +00:00
private void btnSaude_Salvar_Click(object sender, RoutedEventArgs e)
2025-11-24 19:58:20 +00:00
{
2025-11-26 20:00:16 +00:00
(var modulo, var label, var s_code) = GetModuleData(_labelModuloSelecionado);
2025-11-25 12:17:19 +00:00
if (modulo == AgroBase.Models.Enums.T_Code.Vzo)
return;
2025-11-24 19:58:20 +00:00
var rover = VariaveisControleOperacao.RoverEmFoco;
if (rover == null)
2025-11-24 19:58:20 +00:00
{
MessageBox.Show($"Sem dados para o módulo {modulo} ({label})");
return;
}
var mod = rover.ModulosMandatorios.FirstOrDefault(x => x.Dispositivo == modulo);
if (mod == null)
2025-11-25 12:17:19 +00:00
{
mod = new AgroBase.Models.OperacaoModulosMandatoriosModel()
{
Dispositivo = modulo,
ComponentesEmUso = new Dictionary<string, bool>()
};
rover.ModulosMandatorios.Add(mod);
2025-11-25 12:17:19 +00:00
}
mod.Mandatorio = chbSaude_Mandatorio.IsChecked ?? false;
if (string.IsNullOrEmpty(label))
{
mod.Utilizar = chbSaude_EmUso.IsChecked ?? false;
}
else
{
mod.ComponentesEmUso[label] = chbSaude_EmUso.IsChecked ?? false;
}
2025-11-25 12:17:19 +00:00
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
{
ModulosMandatorios = rover.ModulosMandatorios,
});
2025-11-24 19:58:20 +00:00
}
#endregion
2025-11-24 16:05:50 +00:00
#region POSICAO
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
public void AtualizarDadosTela_GNSS(AgroBase.Models.GPSModel dados, string? marker_id = null, double progresso = double.NaN)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
bool dados_base = marker_id == VariaveisControleOperacao.BaseMarkerID;
lblGNSS_Posicao.Foreground = new SolidColorBrush(dados.Inicializado ? System.Windows.Media.Colors.Green : System.Windows.Media.Colors.Red);
lblGNSS_Correcao.Content = $"Correção {dados.QualidadeFix} " +
(dados.QualidadeFix == AgroBase.Models.Enums.TiposCorrecaoGPS.BaseFix ?
(dados.OrientacaoReal.ToString("0.00") + "°") :
((dados.Ntrip_ativado ? "N" : "B") + $" {dados.IdadeCorrecao.ToString("0.0")} s"));
lblGNSS_Satelites.Content = $"Satélites {dados.NumeroSatelites} ({dados.PrecisaoCm.ToString("0.00")} cm)";
lblGNSS_Altitude.Content = $"Altitude {dados.Altitude.ToString("0.00")} m";
if (dados_base)
{
sldGNSS_LeverArm.Visibility = Visibility.Hidden;
if (double.IsNaN(progresso))
{
lblGNSS_Progresso.Visibility = Visibility.Hidden;
}
else
{
lblGNSS_Progresso.Visibility = Visibility.Visible;
lblGNSS_Progresso.Content = $"{progresso.ToString("0.00")}%";
}
bool gnss_fix_preciso = new List<AgroBase.Models.Enums.TiposCorrecaoGPS>() { AgroBase.Models.Enums.TiposCorrecaoGPS.RTKFixo, AgroBase.Models.Enums.TiposCorrecaoGPS.RTKFlutuante }.Contains(Variaveis.GpsService?.UltimaLeitura?.QualidadeFix ?? AgroBase.Models.Enums.TiposCorrecaoGPS.SemCorrecao);
bool gnss_fixado = Variaveis.GpsService?.BaseFix?.CorrecaoAbsoluta ?? false;
bool gnss_fixando = btnGNSS_FixarBase.Content.ToString() == "Parar";
btnGNSS_FixarBase.IsEnabled = (gnss_fix_preciso && !gnss_fixado) || gnss_fixando || gnss_fixado;
btnGNSS_FixarBase.Content = gnss_fixado || !gnss_fixando ? "Fixar" : "Parar";
}
else
{
btnGNSS_FixarBase.IsEnabled = true;
sldGNSS_LeverArm.Visibility = Visibility.Visible;
lblGNSS_Progresso.Visibility = Visibility.Visible;
lblGNSS_Progresso.Content = $"{(sldGNSS_LeverArm.Value * 10.0).ToString("0")} cm";
lblGNSS_Progresso.Foreground = new SolidColorBrush(Math.Round(sldGNSS_LeverArm.Value * 10.0, 0) == Math.Round(dados.LeverArmLateral, 0) ? System.Windows.Media.Colors.Black : System.Windows.Media.Colors.Red);
btnGNSS_FixarBase.Content = "Aplicar";
}
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI GNSS: {exUi.Message}");
}
}));
2025-11-14 17:11:58 +00:00
}
2025-11-24 16:05:50 +00:00
private void btnGNSS_FixarBase_Click(object sender, RoutedEventArgs e)
{
if (VariaveisControleOperacao.BaseEmFoco)
{
if (!Variaveis.GpsService.BaseFix.FixLiberado)
{
if (Variaveis.GpsService.BaseFix.CorrecaoAbsoluta)
{
var res = MessageBox.Show("Mudar posição da base?", "Tem certeza que deseja fixar a posição da base novamente?", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (res == MessageBoxResult.Yes)
{
btnGNSS_FixarBase.Content = "Parar";
Variaveis.GpsService.BaseFix.FixLiberado = true;
Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo());
}
}
else
{
btnGNSS_FixarBase.Content = "Parar";
Variaveis.GpsService.BaseFix.FixLiberado = true;
}
}
else
{
btnGNSS_FixarBase.Content = "Fixar";
Variaveis.GpsService.BaseFix.FixLiberado = false;
}
}
else
{
VariaveisControleOperacao.EnviarComandoLeverArm(sldGNSS_LeverArm.Value * 10.0);
}
}
private void sldGNSS_LeverArm_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
lblGNSS_Progresso.Content = $"{(sldGNSS_LeverArm.Value * 10.0).ToString("0")} cm";
}
2025-11-14 17:11:58 +00:00
#endregion
2025-11-24 16:05:50 +00:00
#region CONTROLE
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
public void AtualizarDadosTela_Controle(AgroBase.Models.OperacaoControleModel controle, double angulo, double velocidade, bool emergencia, bool pausa, bool refing)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
CTRL.AtualizarDadosControle(
angSp: controle.Angulo,
angCur: angulo,
tipoMov: controle.TipoMovimento,
velSp: controle.PercentualVelocidadeSPKmh,
velKmh: velocidade,
emg: emergencia,
pause: pausa,
refing: refing
);
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Controle: {exUi.Message}");
}
}));
2025-11-14 17:11:58 +00:00
}
#endregion
2025-11-24 16:05:50 +00:00
#region PARAMETROS DA OPERACAO
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
public void AtualizarDadosTela_ParametrosOperacao(AgroBase.Models.Operacoes.OperacaoParametrosControleModel? controle)
{
if (controle == null) return;
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
txtParametros_VelCErvas.Text = controle.MovVelocidadeCErvasPercent.ToString();
txtParametros_VelSErvas.Text = controle.MovVelocidadeSErvasPercent.ToString();
txtParametros_AngMax.Text = controle.DirAnguloMaximo.ToString();
txtParametros_RoiAtuacao.Text = controle.AtuPercentualInicioPulverizacao.ToString();
txtParametros_AreaAtuacao.Text = controle.AtuAlturaAreaPulverizacao.ToString();
txtParametros_PressaoLiha.Text = controle.AtuPressaoLinha.ToString();
txtParametros_PctErvaOn.Text = controle.AtuPercentualErvasBicoOn.ToString();
txtParametros_PctErvaOff.Text = controle.AtuPercentualErvasBicoOff.ToString();
txtParametros_TempoOn.Text = controle.AtuDuracaoAtuacao.ToString();
chbParametros_Pulverizador.IsChecked = controle.PulverizadorAutomatico;
chbParametros_Frenagem.IsChecked = controle.FrenagemAutomatica;
chbParametros_Sonar.IsChecked = controle.SonarAtivado;
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Parametros da Operacao: {exUi.Message}");
}
}));
}
private void btnParametros_Salvar_Click(object sender, RoutedEventArgs e)
{
var modo = (CTRL.TgManual.IsChecked ?? false) ? AgroBase.Models.Enums.ModoOperacao.Manual : AgroBase.Models.Enums.ModoOperacao.MapaGPS;
2025-11-25 12:17:19 +00:00
var rover = VariaveisControleOperacao.RoverEmFoco;
2025-11-24 16:05:50 +00:00
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
{
Modo = modo,
Descricao = "Operacao da base",
QtdCamerasSolo = 1,
2025-11-25 12:17:19 +00:00
QtdBicos = 4,
2025-11-24 16:05:50 +00:00
CapacidadeReservatorio = 45,
Controle = new AgroBase.Models.Operacoes.OperacaoParametrosControleModel()
{
MovimentoAutomatico = modo != AgroBase.Models.Enums.ModoOperacao.Manual,
SonarAtivado = chbParametros_Sonar.IsChecked ?? false,
FrenagemAutomatica = chbParametros_Frenagem.IsChecked ?? false,
MovVelocidadeCErvasPercent = int.Parse(txtParametros_VelCErvas.Text),
MovVelocidadeSErvasPercent = int.Parse(txtParametros_VelSErvas.Text),
DirAnguloMaximo = int.Parse(txtParametros_AngMax.Text),
DirTipoMovimento = AgroBase.Models.Enums.TiposControladorDirecional.MPC,
DirVelocidadeMovimento = 50,
PulverizadorAutomatico = chbParametros_Pulverizador.IsChecked ?? false,
AtuPercentualErvasBicoOn = double.Parse(txtParametros_PctErvaOn.Text),
AtuPercentualErvasBicoOff = double.Parse(txtParametros_PctErvaOff.Text),
AtuDuracaoAtuacao = int.Parse(txtParametros_TempoOn.Text),
AtuAlturaAreaPulverizacao = double.Parse(txtParametros_AreaAtuacao.Text),
AtuPercentualInicioPulverizacao = double.Parse(txtParametros_RoiAtuacao.Text),
AtuPressaoLinha = double.Parse(txtParametros_PressaoLiha.Text),
},
2025-11-25 12:17:19 +00:00
ModulosMandatorios = rover?.ModulosMandatorios,
ParametrosMandatorios = rover?.ParametrosMandatorios,
2025-11-24 16:05:50 +00:00
RuasPercorrer = MAP.RuasMapaCarregado.Where(x => x.Selected).Select(x => x.Id).ToList(),
Mapa = MAP.CriarDadosMapa()
});
}
private void btnParametros_Atualizar_Click(object sender, RoutedEventArgs e)
2025-11-14 17:11:58 +00:00
{
2025-11-24 19:58:20 +00:00
VariaveisControleOperacao.RequisitarParametrosOperacao();
2025-11-14 17:11:58 +00:00
}
#endregion
#region MAPA
private void MAP_MarkerClicked(object? sender, MapMarkerManager.MarkerClickedEventArgs e)
{
if (string.IsNullOrEmpty(e.MarkerId))
{
2025-11-24 16:05:50 +00:00
Variaveis.MostrarLog($"Sem rover em foco");
LimparDadosTela_Telemetria(e.MarkerId);
2025-11-14 17:11:58 +00:00
}
else
{
2025-11-24 16:05:50 +00:00
Variaveis.MostrarLog($"Rover em foco: {e.MarkerId}");
int idx = cmbDispositivo.Items.IndexOf(e.MarkerId);
cmbDispositivo.SelectedIndex = idx;
2025-11-14 17:11:58 +00:00
}
}
private void MAP_StreetMapClicked(object? sender, MapViewControl.StreetMapClickedEventArgs e)
{
Variaveis.MostrarLog($"Rua clicada: {e.StreetId}. Ruas selecionadas: {string.Join(",", e.SelectedStreetsIds)}");
}
2025-11-24 16:05:50 +00:00
private void AtualizarDadosTela_Mapa(AgroBase.Models.OperacaoSensoriamentoLogTrajetoriaModel Trajetoria)
{
lblMapaInfo_Debug.Content = $"" +
$"Próximo Ponto: {Trajetoria.ProximoPonto.idxPonto} | " +
(Trajetoria.ProximoPonto.Aproximando ? "Aproximando" : "Afastando") + " | " +
$"Distância próximo ponto: {Trajetoria.ProximoPonto.DistanciaAtual.ToString("0.00")} m | " +
$"Distância ponto anterior: {Trajetoria.PontoAtual.DistanciaAtual.ToString("0.00")} m | " +
$"Corredor: " + (Trajetoria.CorredorAtual.Dentro ? "Dentro" : "Fora") + " | " +
$"Margem: " + (Trajetoria.NaMargemDoCorredor ? "Sim" : "Não") + " | " +
$"Disância Esquerda: {(Trajetoria.DistanciaEsquerda * 100.0).ToString("0.00")} cm | " +
$"Distância Direita: {(Trajetoria.DistanciaDireita * 100.0).ToString("0.00")} cm | " +
$"Status: {Trajetoria.StatusCarro}";
double erroLateral = (Trajetoria.DistanciaEsquerda - Trajetoria.DistanciaDireita) / 2.0 * 100.0;
AtualizarDadosTela_IMU(erro_lateral: erroLateral);
}
2025-11-14 17:11:58 +00:00
#endregion
2025-11-24 16:05:50 +00:00
#region HEADING
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
public void AtualizarDadosTela_Heading(double headingRover, double headingCourse = double.NaN)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
HDG.Heading = headingRover;
HDG.CourseHeading = headingCourse;
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Heading: {exUi.Message}");
}
}));
2025-11-14 17:11:58 +00:00
}
#endregion
2025-11-24 16:05:50 +00:00
#region IMU
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
public void AtualizarDadosTela_IMU(double? roll = null, double? pitch = null, double? erro_lateral = null)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
try
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
if (roll != null) IMU.RollDeg = (double)roll;
if (pitch != null) IMU.PitchDeg = (double)pitch;
if (erro_lateral != null) IMU.LateralError = (double)erro_lateral;
2025-11-14 17:11:58 +00:00
}
2025-11-24 16:05:50 +00:00
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI IMU: {exUi.Message}");
}
}));
}
#endregion
#region CAMERA FRONTAL
private void IniciarStreamCameraFrontal()
{
var path = @"streams\camera_frontal.sdp";
if (!File.Exists(path))
{
string stream =
"v=0\r\n" +
"o=- 0 0 IN IP4 0.0.0.0\r\n" +
"s=OAK H264\r\n" +
"c=IN IP4 0.0.0.0\r\n" +
"t=0 0\r\n" +
"m=video 5000 RTP/AVP 96\r\n" +
"a=rtpmap:96 H264/90000\r\n" +
"a=fmtp:96 packetization-mode=1\r\n";
File.WriteAllText(path, stream);
2025-11-14 17:11:58 +00:00
}
2025-11-24 16:05:50 +00:00
_mediaFront?.Dispose(); // limpa antigo, se existir
_mediaFront = new Media(_libVLC, path, FromType.FromPath);
// _mediaFront.AddOption(":network-caching=150"); // se quiser por arquivo
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
_playerFront.Play(_mediaFront);
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, true);
}
private void PararStreamCameraFrontal(bool finalizar = false)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
_playerFront?.Stop();
if (finalizar)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
_mediaFront?.Dispose();
_mediaFront = null;
_playerFront?.Dispose();
_playerFront = null;
}
2025-11-14 17:11:58 +00:00
2025-11-24 16:05:50 +00:00
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, false);
}
#endregion
#region CAMERA ERVAS
private void IniciarStreamCameraErvas()
{
var path = @"streams\camera_ervas.sdp";
if (!File.Exists(path))
{
string stream =
"v=0\r\n" +
"o=- 0 0 IN IP4 0.0.0.0\r\n" +
"s=OAK H264\r\n" +
"c=IN IP4 0.0.0.0\r\n" +
"t=0 0\r\n" +
"m=video 5002 RTP/AVP 96\r\n" + // <- porta 5001
"a=rtpmap:96 H264/90000\r\n" +
"a=fmtp:96 packetization-mode=1\r\n";
File.WriteAllText(path, stream);
2025-11-14 17:11:58 +00:00
}
2025-11-24 16:05:50 +00:00
_mediaWeed?.Dispose();
_mediaWeed = new Media(_libVLC, path, FromType.FromPath);
// _mediaWeed.AddOption(":network-caching=150");
_playerWeed.Play(_mediaWeed);
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Cam, true);
}
private void PararStreamCameraErvas(bool finalizar = false)
{
_playerWeed?.Stop();
if (finalizar)
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
_mediaWeed?.Dispose();
_mediaWeed = null;
_playerWeed?.Dispose();
_playerWeed = null;
2025-11-14 17:11:58 +00:00
}
2025-11-24 16:05:50 +00:00
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Cam, false);
}
#endregion
#region PULVERIZADOR
2025-11-14 17:11:58 +00:00
#endregion
#region LIDAR
public void AtualizarDadostela_LIDAR(List<AgroBase.Models.LivoxBboxModel> bboxes)
{
2025-11-24 16:05:50 +00:00
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
BBoxes3D.SetBboxes(bboxes);
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Lidar: {exUi.Message}");
}
}));
2025-11-14 17:11:58 +00:00
}
2025-11-25 12:17:19 +00:00
2025-11-14 17:11:58 +00:00
#endregion
}
}