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

805 lines
34 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Windows;
using ScottPlot; // Plot
using ScottPlot.Plottables; // ISignal / IScatter
using System.Timers;
using Colors = ScottPlot.Colors; // Timer
using System.Windows.Threading;
using OperationControl.Controls;
using System.Diagnostics;
using OperationControl.Models;
using AgroBase.Models.Components;
using OperationControl.Services;
using System.Windows.Controls;
using System.Runtime.CompilerServices;
using System.Windows.Media;
using DotSpatial.Projections.Transforms;
using System;
using LibVLCSharp.Shared;
using MediaPlayer = LibVLCSharp.Shared.MediaPlayer;
using System.IO;
using ComboBox = System.Windows.Controls.ComboBox;
using Application = System.Windows.Application;
using MessageBox = System.Windows.MessageBox;
namespace OperationControl.Windows
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
// buffers (X = tempo em segundos)
private readonly List<double> xs = new();
private readonly List<double> ysCorr = new(); // Corrente (A)
private readonly List<double> ysVolt = new(); // Tensão (V)
private readonly List<double> ysTemp = new(); // Temperatura (°C)
private readonly List<double> ysRpm = new(); // RPM
private readonly System.Timers.Timer tmr = new(1000) { AutoReset = true }; // 10 Hz
private double t = 0;
private readonly Random rng = new();
DispatcherTimer _clock = new DispatcherTimer();
Random _rand = new Random();
private LibVLC _libVLC;
private MediaPlayer _playerFront;
private MediaPlayer _playerWeed;
private Media _mediaFront;
private Media _mediaWeed;
public MainWindow()
{
InitializeComponent();
AtualizarListaDispositivos(new List<string>() { VariaveisControleOperacao.SelectedRoverId });
// Título / eixos
Plot.Plot.Title("MOV ET Corrente / Tensão / Temp / RPM (últimos 60s)");
Plot.Plot.Axes.Bottom.Label.Text = "Tempo (s)";
Plot.Plot.Axes.Left.Label.Text = "Unidades (A, V, °C, RPM)";
// inicializa com um ponto para cada série
PushSample(initial: true);
// legenda
Plot.Plot.ShowLegend(Alignment.UpperRight);
// loop
tmr.Elapsed += (_, __) => Dispatcher.Invoke(() => PushSample());
tmr.Start();
DataContext = this;
// atualizar as caixas
//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 },
//});
// 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)
{
}
private void MainWindow_Closed(object? sender, EventArgs e)
{
PararStreamCameraFrontal(true);
PararStreamCameraErvas(true);
_libVLC?.Dispose();
}
private void PushSample(bool initial = false)
{
// avança tempo
if (!initial) t += 1; // 10 Hz
xs.Add(t);
// ------- MOCK de dados plausíveis -------
// Corrente (A): 312 A com ruído
double corr = 8 + 2 * Math.Sin(t * 0.7) + (rng.NextDouble() - 0.5);
corr = Math.Clamp(corr, 0, 30);
// Tensão (V): 3642 V, ripple leve e queda lenta
double volt = 40.5 + 0.6 * Math.Sin(t * 0.15) - 0.002 * t;
volt = Math.Clamp(volt, 30, 42);
// Temperatura (°C): sobe devagar
double temp = 38 + 4 * Math.Sin(t * 0.05) + 0.01 * t;
temp = Math.Clamp(temp, 20, 85);
// RPM: 01500 com variação
double rpm = 1100 + 200 * Math.Sin(t * 0.9) + 80 * (rng.NextDouble() - 0.5);
rpm = Math.Clamp(rpm, 0, 2000);
ysCorr.Add(corr);
ysVolt.Add(volt);
ysTemp.Add(temp);
ysRpm.Add(rpm);
// mantém só últimos 60 s
while (xs.Count > 0 && xs[^1] - xs[0] > 60.0)
{
xs.RemoveAt(0);
ysCorr.RemoveAt(0);
ysVolt.RemoveAt(0);
ysTemp.RemoveAt(0);
ysRpm.RemoveAt(0);
}
// redesenha (v5: passe arrays diretamente)
Plot.Plot.Clear();
// Corrente (A)
var scCorr = Plot.Plot.Add.Scatter(xs.ToArray(), ysCorr.ToArray());
scCorr.Label = "Corrente (A)";
scCorr.Color = ScottPlot.Colors.Cyan;
scCorr.LineWidth = 2;
// Tensão (V)
var scVolt = Plot.Plot.Add.Scatter(xs.ToArray(), ysVolt.ToArray());
scVolt.Label = "Tensão (V)";
scVolt.Color = ScottPlot.Colors.Lime;
scVolt.LineWidth = 2;
// Temperatura (°C)
var scTemp = Plot.Plot.Add.Scatter(xs.ToArray(), ysTemp.ToArray());
scTemp.Label = "Temp (°C)";
scTemp.Color = ScottPlot.Colors.Magenta;
scTemp.LineWidth = 2;
// RPM
var scRpm = Plot.Plot.Add.Scatter(xs.ToArray(), ysRpm.ToArray());
scRpm.Label = "RPM";
scRpm.Color = ScottPlot.Colors.Orange;
scRpm.LineWidth = 2;
// janela de 60 s rolando
double xEnd = xs[^1];
double xStart = Math.Max(0, xEnd - 60.0);
Plot.Plot.Axes.SetLimitsX(xStart, xEnd);
Plot.Plot.Axes.AutoScaleY(); // ajusta Y automaticamente para caber tudo
Plot.Refresh();
}
#region DISPOSITIVOS
public void AtualizarListaDispositivos(List<string> dispositivos)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
cmbDispositivo.Items.Clear();
foreach (var d in dispositivos)
{
cmbDispositivo.Items.Add(d);
if (!MAP.markers.Added(d))
{
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
);
}
}
}
}
int idx_selected = dispositivos.IndexOf(VariaveisControleOperacao.SelectedRoverId);
if (idx_selected > -1)
cmbDispositivo.SelectedIndex = idx_selected;
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI lista dispositivos: {exUi.Message}");
}
}));
}
private void cmbDispositivo_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
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();
}
}
public void LimparDadosTela_Telemetria(string rover_id)
{
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}");
}
}));
}
public void AtualizarDadosTela_Telemetria(string rover_id)
{
bool dados_base = rover_id == VariaveisControleOperacao.BaseMarkerID;
var rover = VariaveisControleOperacao.RoversNaRede.FirstOrDefault(x => x.RoverId == rover_id)?.DadosLeitura;
if (dados_base)
{
MAP.markers.UpdateMarkerPosition(rover_id, lat: Variaveis.GpsService?.UltimaLeitura?.Latitude, lon: Variaveis.GpsService?.UltimaLeitura?.Longitude, heading: Variaveis.GpsService?.UltimaLeitura?.OrientacaoReal);
}
else if (rover != null)
{
var simulacao = rover.Controle?.SimulacaoMPC?.Select(x => new double[] { x.longitude, x.latitude })?.ToList();
MAP.markers.UpdateMarkerPosition(rover_id, lat: rover?.Gps?.Latitude, lon: rover?.Gps?.Longitude, heading: rover?.Gps?.OrientacaoReal, predict: simulacao);
MAP.markers.UpdateMarkerInfo(rover_id, status: rover.StatusOperacao);
}
if (rover_id != VariaveisControleOperacao.SelectedRoverId) return;
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
if (rover_id == VariaveisControleOperacao.BaseMarkerID)
{
Variaveis.MostrarLog($"Atualizando dados da tela para a base");
AtualizarDadosTela_GNSS(Variaveis.GpsService?.UltimaLeitura ?? new AgroBase.Models.GPSModel(), marker_id: VariaveisControleOperacao.BaseMarkerID);
AtualizarDadosTela_Heading(Variaveis.GpsService?.UltimaLeitura?.AnguloCarroDefinido ?? 0);
}
else
{
if (rover == null) return;
Variaveis.MostrarLog($"Atualizando dados da tela para o dispositivo {rover_id}");
if (rover.Trajetoria != null)
AtualizarDadosTela_Resumo(rover);
if (rover.Gps != null)
AtualizarDadosTela_GNSS(rover.Gps, marker_id: rover_id);
if (rover.Controle != null)
AtualizarDadosTela_Controle(rover.Controle, rover.Movimentacao.AnguloMedio, rover.Movimentacao.VelocidadeMedia, rover.Emergencia, !rover.OperacaoIniciada, rover.StatusOperacao == AgroBase.Models.Enums.StatusOperacao.Calibrando);
//if (rover.Value.Controle != null)
// AtualizarDadosTela_ParametrosOperacao(rover.Value.Controle);
if (rover.Trajetoria != null)
AtualizarDadosTela_Mapa(rover.Trajetoria);
if (rover.Gps != null)
AtualizarDadosTela_Heading(rover.Gps.AnguloCarroDefinido, rover.Modo == AgroBase.Models.Enums.ModoOperacao.Manual ? double.NaN : rover.Trajetoria.AnguloCaminho);
if (rover.IMU != null)
AtualizarDadosTela_IMU(rover.IMU.InclinacaoLateral, rover.IMU.InclinacaoFrontal);
if (rover.LivoxLidar != null)
AtualizarDadostela_LIDAR(rover.LivoxLidar.bboxes);
}
}
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(() =>
{
try
{
pgbResumo_RuaAtual.Value = dados.Trajetoria.PercentualRuaAtual;
lblResumo_RuaAtual.Content = $"{dados.Trajetoria.CorredorAtual.DistanciaPercorridaCorredor.ToString("0.00")} / {dados.Trajetoria.CorredorAtual.DistanciaTotal.ToString("0.00")}";
pgbResumo_AreaTotal.Value = dados.Trajetoria.PercentualOperacao;
lblResumo_AreaTotal.Content = $"{dados.Trajetoria.DistanciaPercorrida.ToString("0.00")} / {dados.Trajetoria.DistanciaTotal.ToString("0.00")}";
pgbResumo_Bateria.Value = dados.Bateria.PorcentagemBateria;
lblResumo_Bateria.Content = $"{dados.Bateria.TensaoInstantanea.ToString("0.00")} V ({dados.Bateria.TempoEstimadoRestanteMinutos})";
pgbResumo_Herbicida.Value = dados.Atuador.PercentualReservatorio;
lblResumo_Herbicida.Content = $"{dados.Atuador.VolumeReservatorio.ToString("0.00")} L ({0.ToString("0.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";
lblResumo_OperacaoDuracao.Content = $"Duração {dados.TempoDecorrido.ToString("HH:mm:ss")} / {dados.Trajetoria.TempoEstimadoOperacao}";
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Resumo: {exUi.Message}");
}
}));
}
#endregion
#region POSICAO
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}");
}
}));
}
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";
}
#endregion
#region CONTROLE
public void AtualizarDadosTela_Controle(AgroBase.Models.OperacaoControleModel controle, double angulo, double velocidade, bool emergencia, bool pausa, bool refing)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
CTRL.AtualizarDadosControle(
angSp: controle.Angulo,
angCur: angulo,
tipoMov: controle.TipoMovimento,
velPct: controle.PercentualVelocidadeSP,
velSp: controle.PercentualVelocidadeSPKmh,
velKmh: velocidade,
emg: emergencia,
pause: pausa,
refing: refing
);
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Controle: {exUi.Message}");
}
}));
}
#endregion
#region PARAMETROS DA OPERACAO
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;
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
{
Modo = modo,
Descricao = "Operacao da base",
QtdCamerasSolo = 1,
QtdBicos = 3,
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),
},
ModulosMandatorios = new List<AgroBase.Models.OperacaoModulosMandatoriosModel>(),
ParametrosMandatorios = new List<AgroBase.Models.OperacaoParametrosMandatoriosModel>(),
RuasPercorrer = MAP.RuasMapaCarregado.Where(x => x.Selected).Select(x => x.Id).ToList(),
Mapa = MAP.CriarDadosMapa()
});
}
private void btnParametros_Atualizar_Click(object sender, RoutedEventArgs e)
{
AtualizarDadosTela_ParametrosOperacao(VariaveisControleOperacao.RoverEmFoco?.Controle);
}
#endregion
#region MAPA
private void MAP_MarkerClicked(object? sender, MapMarkerManager.MarkerClickedEventArgs e)
{
if (string.IsNullOrEmpty(e.MarkerId))
{
Variaveis.MostrarLog($"Sem rover em foco");
LimparDadosTela_Telemetria(e.MarkerId);
}
else
{
Variaveis.MostrarLog($"Rover em foco: {e.MarkerId}");
int idx = cmbDispositivo.Items.IndexOf(e.MarkerId);
cmbDispositivo.SelectedIndex = idx;
}
}
private void MAP_StreetMapClicked(object? sender, MapViewControl.StreetMapClickedEventArgs e)
{
Variaveis.MostrarLog($"Rua clicada: {e.StreetId}. Ruas selecionadas: {string.Join(",", e.SelectedStreetsIds)}");
}
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);
}
#endregion
#region HEADING
public void AtualizarDadosTela_Heading(double headingRover, double headingCourse = double.NaN)
{
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}");
}
}));
}
#endregion
#region IMU
public void AtualizarDadosTela_IMU(double? roll = null, double? pitch = null, double? erro_lateral = null)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
if (roll != null) IMU.RollDeg = (double)roll;
if (pitch != null) IMU.PitchDeg = (double)pitch;
if (erro_lateral != null) IMU.LateralError = (double)erro_lateral;
}
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);
}
_mediaFront?.Dispose(); // limpa antigo, se existir
_mediaFront = new Media(_libVLC, path, FromType.FromPath);
// _mediaFront.AddOption(":network-caching=150"); // se quiser por arquivo
_playerFront.Play(_mediaFront);
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, true);
}
private void PararStreamCameraFrontal(bool finalizar = false)
{
_playerFront?.Stop();
if (finalizar)
{
_mediaFront?.Dispose();
_mediaFront = null;
_playerFront?.Dispose();
_playerFront = null;
}
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);
}
_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)
{
_mediaWeed?.Dispose();
_mediaWeed = null;
_playerWeed?.Dispose();
_playerWeed = null;
}
VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Cam, false);
}
#endregion
#region PULVERIZADOR
private void btnB0_Click(object sender, RoutedEventArgs e)
{
btnB0.Content = (btnB0.Content.ToString() == "Ligar") ? "Desligar" : "Ligar";
}
#endregion
#region LIDAR
public void AtualizarDadostela_LIDAR(List<AgroBase.Models.LivoxBboxModel> bboxes)
{
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
BBoxes3D.SetBboxes(bboxes);
}
catch (Exception exUi)
{
Variaveis.MostrarLog($"Erro ao atualizar UI Lidar: {exUi.Message}");
}
}));
}
#endregion
}
}