2025-11-12 11:15:07 +00:00
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 ;
2025-11-14 17:11:58 +00:00
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 ;
2025-11-24 16:05:50 +00:00
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 ;
2025-11-12 11:15:07 +00:00
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 ( ) ;
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-12 11:15:07 +00:00
public MainWindow ( )
{
InitializeComponent ( ) ;
2025-11-14 17:11:58 +00:00
AtualizarListaDispositivos ( new List < string > ( ) { VariaveisControleOperacao . SelectedRoverId } ) ;
2025-11-12 11:15:07 +00:00
// 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
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-12 11:15:07 +00:00
}
2025-11-24 16:05:50 +00:00
private void MainWindow_Closed ( object? sender , EventArgs e )
{
PararStreamCameraFrontal ( true ) ;
PararStreamCameraErvas ( true ) ;
_libVLC ? . Dispose ( ) ;
}
2025-11-12 11:15:07 +00:00
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): 3– 12 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): 36– 42 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: 0– 1500 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 ( ) ;
}
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 ;
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 ) ;
}
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-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
{
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 ( ( ) = >
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
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}" ) ;
}
} ) ) ;
}
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 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 ,
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}" ) ;
}
} ) ) ;
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 ;
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 )
2025-11-14 17:11:58 +00:00
{
2025-11-24 16:05:50 +00:00
AtualizarDadosTela_ParametrosOperacao ( VariaveisControleOperacao . RoverEmFoco ? . Controle ) ;
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
private void btnB0_Click ( object sender , RoutedEventArgs e )
{
btnB0 . Content = ( btnB0 . Content . ToString ( ) = = "Ligar" ) ? "Desligar" : "Ligar" ;
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
}
#endregion
2025-11-12 11:15:07 +00:00
}
}