metodo para fixação da base e aplicação de offset global

This commit is contained in:
Diego Freitas 2026-03-25 07:52:19 -03:00
parent f3476d6773
commit a6d9a7271a
5 changed files with 187 additions and 298 deletions

View File

@ -9,8 +9,7 @@ using AgroBase.Models;
using static AgroBase.Models.Enums;
using OperationControl.Models;
using Application = System.Windows.Application;
using Mapsui.Animations;
using OperationControl.ViewModels;
using static OperationControl.Services.BaseFixService;
namespace OperationControl.Services
{
@ -233,7 +232,7 @@ namespace OperationControl.Services
private int rtk_timeout = 60;
public GPSModel UltimaLeitura = new GPSModel();
public BaseFixService BaseFix;
private GeoLeverArm LeverArm;
public GeoLeverArm LeverArm = new GeoLeverArm();
private readonly StringBuilder _nmeaBuffer = new();
private bool _nmeaInSentence = false;
@ -242,13 +241,14 @@ namespace OperationControl.Services
private List<byte> _rtcmMsg = new();
private int _rtcmTotalBytes = -1;
public async Task ConfigurarModulo(bool fixar, MetodoFixacaoBase metodo = MetodoFixacaoBase.Ntrip, double? lat = null, double? lon = null, double? alt = null)
public async Task ConfigurarModulo(bool fixar, MetodoFixacaoBase metodo = MetodoFixacaoBase.Ntrip, double? lat = null, double? lon = null, double? alt = null, bool? offset = false)
{
Models.Variaveis.MostrarLog("Iniciando configuração do módulo GPS...");
LeverArm = new GeoLeverArm(VariaveisControleOperacao.LeverArmFrontal, VariaveisControleOperacao.LeverArmLateral);
if (!(offset ?? false))
{
BaseFix = new BaseFixService(PortaGps, this);
}
BaseFix.FixLiberado = fixar;
string portaUsb = "com3";
@ -268,12 +268,16 @@ namespace OperationControl.Services
bool sucesso = false;
string mensagem = "";
BaseFix.fimProcesso = null;
BaseFix.inicioProcesso = DateTime.UtcNow;
BaseFix.inicioFix = DateTime.UtcNow;
Models.Variaveis.MostrarLog($"Aplicando posição fixa da base com o método {metodo}...");
switch (metodo)
{
case MetodoFixacaoBase.Ntrip:
{
Models.Variaveis.MostrarLog("Tentando fixação da base via NTRIP...");
sucesso = await BaseFix.FixarBaseViaNtripAsync(
portaUsb: portaUsb,
portaSaida: portaSaida,
@ -293,75 +297,43 @@ namespace OperationControl.Services
},
segsFixEstavel: TempoSurveryIn
);
if (sucesso)
{
mensagem = "Posição fixada utilizando NTRIP com sucesso!";
}
else
{
Models.Variaveis.MostrarLog("Falha na fixação via NTRIP. Iniciando Survey-In...");
BaseFix.fimProcesso = null;
BaseFix.inicioProcesso = DateTime.UtcNow;
BaseFix.inicioFix = DateTime.UtcNow;
await ConfigurarModuloBase(
tempo_fixacao: TempoSurveryIn,
porta_usb: portaUsb,
porta_saida: portaSaida);
BaseFix.fimProcesso = DateTime.UtcNow;
sucesso = true;
mensagem = "Posição survery in da base aplicada com sucesso.";
}
break;
}
case MetodoFixacaoBase.SurveyIn:
{
Models.Variaveis.MostrarLog("Configurando módulo como base em Survey-In...");
await ConfigurarModuloBase(tempo_fixacao: TempoSurveryIn, porta_usb: portaUsb, porta_saida: portaSaida);
break;
BaseFix.fimProcesso = null;
BaseFix.inicioProcesso = DateTime.UtcNow;
BaseFix.inicioFix = DateTime.UtcNow;
await ConfigurarModuloBase(
tempo_fixacao: TempoSurveryIn,
porta_usb: portaUsb,
porta_saida: portaSaida);
BaseFix.fimProcesso = DateTime.UtcNow;
sucesso = true;
mensagem = "Posição survery in da base aplicada com sucesso.";
case MetodoFixacaoBase.Manual:
if (lat.HasValue && lon.HasValue && alt.HasValue)
await BaseFix.AplicarBaseFixAsync(portaUsb, portaSaida, baseId, lat.Value, lon.Value, alt.Value);
break;
}
case MetodoFixacaoBase.Manual:
// Aguarda 10 segundos para ver se o UM982 pegou o BaseFix
while (sucesso && UltimaLeitura.QualidadeFix != TiposCorrecaoGPS.BaseFix && BaseFix.inicioFix != null && (DateTime.UtcNow - BaseFix.inicioFix).Value.TotalSeconds < 10)
{
if (!lat.HasValue || !lon.HasValue || !alt.HasValue)
throw new ArgumentException("Latitude, longitude e altitude elipsoidal são obrigatórias no modo manual.");
await Task.Delay(1000);
}
Models.Variaveis.MostrarLog("Aplicando posição manual fixa da base...");
BaseFix.fimProcesso = DateTime.UtcNow;
BaseFix.FixLiberado = false;
sucesso = UltimaLeitura.QualidadeFix == TiposCorrecaoGPS.BaseFix;
mensagem = sucesso ? $"Posição da base aplicada com sucesso com o método {metodo}." : $"Falha ao aplicar posição da base com o método {metodo}.";
if (sucesso && !(offset ?? false))
{
BaseFix.LatitudeFix = UltimaLeitura.Latitude;
BaseFix.LongitudeFix = UltimaLeitura.Longitude;
BaseFix.AltitudeElpsoidalFix = UltimaLeitura.AltitudeElipsoidal;
BaseFix.OrientacaoFix = UltimaLeitura.OrientacaoReal;
if (AppShell.Mock)
{
UltimaLeitura.Latitude = lat.Value;
UltimaLeitura.Longitude = lon.Value;
UltimaLeitura.AltitudeElipsoidal = alt.Value;
AtualizarCoordenadasGPS();
await BaseFix.AplicarBaseFixAsync(
portaUsb,
portaSaida,
baseId,
lat.Value,
lon.Value,
alt.Value);
sucesso = true;
mensagem = "Posição manual da base aplicada com sucesso.";
break;
}
}
@ -1304,6 +1276,10 @@ namespace OperationControl.Services
public bool CorrecaoAbsoluta = false;
public bool CorrecaoEmAndamento = false;
public bool FixLiberado = false;
public double LatitudeFix { get; set; }
public double LongitudeFix { get; set; }
public double AltitudeElpsoidalFix { get; set; }
public double OrientacaoFix { get; set; }
public void ReiniciarFix()
{
@ -1321,7 +1297,6 @@ namespace OperationControl.Services
return false;
CorrecaoEmAndamento = true;
fimProcesso = null;
segundosFixEstavel = segsFixEstavel;
maxJanelaSegundos = maxJanelaSegs;
@ -1349,26 +1324,22 @@ namespace OperationControl.Services
{
Models.Variaveis.MostrarLog("Poucas amostras de RTK FIX coletadas. Tente aumentar o tempo ou verificar sinais.");
CorrecaoAbsoluta = false;
FixLiberado = false;
return CorrecaoAbsoluta;
}
// 3) Filtro robusto (MAD) + média final
var (lat, lon, h, nAmostras) = FiltrarEAgrupar(amostras, madK);
var (lat, lon, h, heading, nAmostras) = FiltrarEAgrupar(amostras, madK);
// 4) Alternar para base FIX + perfil RTCM
await AplicarBaseFixAsync(portaUsb, portaSaida, baseId, lat, lon, h);
Models.Variaveis.MostrarLog($"[BASE/FIX] Coordenadas aplicadas (n={nAmostras}):");
Models.Variaveis.MostrarLog($" lat = {lat:0.000000000}, lon = {lon:0.000000000}, h = {h:0.000}");
Models.Variaveis.MostrarLog($"[BASE/FIX] Coordenadas aplicadas (n={nAmostras}): lat = {lat:0.000000000}, lon = {lon:0.000000000}, h = {h:0.000}");
CorrecaoAbsoluta = true;
FixLiberado = false;
return CorrecaoAbsoluta;
}
finally
{
if (stopNtrip != null) await stopNtrip();
fimProcesso = DateTime.UtcNow;
CorrecaoEmAndamento = false;
}
}
@ -1499,6 +1470,7 @@ namespace OperationControl.Services
double lat = ultimaLeitura.Latitude;
double lon = ultimaLeitura.Longitude;
double altElips = ultimaLeitura.AltitudeElipsoidal; // garanta que já é elipsoidal no parser
double heading = ultimaLeitura.OrientacaoReal;
var fixQual = ultimaLeitura.QualidadeFix; // enum? ok.
int hbAfter = ultimaLeitura.Heartbeat;
@ -1515,6 +1487,7 @@ namespace OperationControl.Services
latDeg: lat,
lonDeg: lon,
altElipsoidalM: altElips,
headingDeg: heading,
fixQuality: fixQual
);
}
@ -1525,40 +1498,46 @@ namespace OperationControl.Services
}
// ===== 3) Filtro robusto (MAD) + média =====
private (double lat, double lon, double h, int n) FiltrarEAgrupar(List<GgaFix> amostras, double madK = 3.5)
private (double lat, double lon, double h, double hdg, int n) FiltrarEAgrupar(List<GgaFix> amostras, double madK = 3.5)
{
Models.Variaveis.MostrarLog("Filtrando dados aferidos...");
// Medianas
var lats = amostras.Select(a => a.LatDeg).OrderBy(x => x).ToArray();
var lons = amostras.Select(a => a.LonDeg).OrderBy(x => x).ToArray();
var hs = amostras.Select(a => a.AltElipsoidalM).OrderBy(x => x).ToArray();
var hdgs = amostras.Select(a => a.HeadingDeg).OrderBy(x => x).ToArray();
double medLat = Mediana(lats);
double medLon = Mediana(lons);
double medH = Mediana(hs);
double medHdg = Mediana(hdgs);
// Desvios absolutos da mediana (MAD)
var dLat = amostras.Select(a => Math.Abs(a.LatDeg - medLat)).OrderBy(x => x).ToArray();
var dLon = amostras.Select(a => Math.Abs(a.LonDeg - medLon)).OrderBy(x => x).ToArray();
var dH = amostras.Select(a => Math.Abs(a.AltElipsoidalM - medH)).OrderBy(x => x).ToArray();
var dHdg = amostras.Select(a => Math.Abs(a.HeadingDeg - medH)).OrderBy(x => x).ToArray();
double madLat = Mediana(dLat) + 1e-12;
double madLon = Mediana(dLon) + 1e-12;
double madHgt = Mediana(dH) + 1e-12;
double madHdg = Mediana(dHdg) + 1e-12;
// Filtra outliers (|x - med| / MAD <= madK)
var filtradas = amostras.Where(a =>
(Math.Abs(a.LatDeg - medLat) / madLat) <= madK &&
(Math.Abs(a.LonDeg - medLon) / madLon) <= madK &&
(Math.Abs(a.AltElipsoidalM - medH) / madHgt) <= madK
(Math.Abs(a.AltElipsoidalM - medH) / madHgt) <= madK &&
(Math.Abs(a.HeadingDeg - medHdg) / madHdg) <= madK
).ToList();
// Média final
double lat = filtradas.Average(a => a.LatDeg);
double lon = filtradas.Average(a => a.LonDeg);
double h = filtradas.Average(a => a.AltElipsoidalM);
double hdg = filtradas.Average(a => a.HeadingDeg);
return (lat, lon, h, filtradas.Count);
return (lat, lon, h, hdg, filtradas.Count);
double Mediana(double[] arr)
{
@ -1618,10 +1597,9 @@ namespace OperationControl.Services
public enum MetodoFixacaoBase
{
Automatico = 0,
Ntrip = 1,
SurveyIn = 2,
Manual = 3
Ntrip = 0,
SurveyIn = 1,
Manual = 2
}
}

View File

@ -1,20 +1,12 @@
using Microsoft.Win32;
using OperationControl.Helpers;
using System;
using System.Collections.Generic;
using OperationControl.Helpers;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Input;
using static OperationControl.Services.BaseFixService;
namespace OperationControl.ViewModels
{
public enum MetodoFixacaoBase
{
Ntrip = 0,
SurveyIn = 1,
Manual = 2
}
public class MetodoFixacaoItem
{
@ -29,7 +21,9 @@ namespace OperationControl.ViewModels
public event Action<string>? CarregarMapaSolicitado;
// Método, latitude, longitude, altitude, offset frontal cm, offset lateral cm
public event Action<MetodoFixacaoBase, double?, double?, double?, double?, double?>? FixarBaseSolicitado;
public event Action<MetodoFixacaoBase, double?, double?, double?>? FixarBaseSolicitado;
// Offset frontal cm, offset lateral cm
public event Action<double?, double?>? AplicarOffsetSolicitado;
public List<MetodoFixacaoItem> MetodosFixacaoDisponiveis { get; } = new()
{
@ -40,11 +34,13 @@ namespace OperationControl.ViewModels
public ICommand CarregarMapaCommand { get; }
public ICommand FixarBaseCommand { get; }
public ICommand AplicarOffsetCommand { get; }
public PreparacaoMapaBottomViewModel()
{
CarregarMapaCommand = new RelayCommand(_ => ExecutarCarregarMapa(), _ => PodeCarregarMapa);
FixarBaseCommand = new RelayCommand(_ => ExecutarFixarBase(), _ => PodeFixarBase);
AplicarOffsetCommand = new RelayCommand(_ => ExecutarAplicarOffset(), _ => PodeEditarOffsetBase);
MetodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip;
OffsetFrontalBaseTexto = "0";
@ -121,6 +117,17 @@ namespace OperationControl.ViewModels
public bool ExibirProgresso => MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual;
private bool _exibirOffsets;
public bool ExibirOffsets
{
get { return _exibirOffsets; }
set
{
_exibirOffsets = value;
OnPropertyChanged(nameof(ExibirOffsets));
}
}
public bool PodeFixarBase
{
get
@ -356,13 +363,7 @@ namespace OperationControl.ViewModels
{
if (FixacaoEmAndamento)
{
FixarBaseSolicitado?.Invoke(
MetodoFixacaoSelecionado,
LatitudeManual,
LongitudeManual,
AltitudeManual,
OffsetFrontalBaseCm,
OffsetLateralBaseCm);
FixarBaseSolicitado?.Invoke(MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, AltitudeManual);
return;
}
@ -381,13 +382,12 @@ namespace OperationControl.ViewModels
StatusTexto = "Pronto para aplicar a posição manual da base.";
}
FixarBaseSolicitado?.Invoke(
MetodoFixacaoSelecionado,
LatitudeManual,
LongitudeManual,
AltitudeManual,
OffsetFrontalBaseCm,
OffsetLateralBaseCm);
FixarBaseSolicitado?.Invoke(MetodoFixacaoSelecionado, LatitudeManual, LongitudeManual, AltitudeManual);
}
private void ExecutarAplicarOffset()
{
AplicarOffsetSolicitado?.Invoke(OffsetFrontalBaseCm, OffsetLateralBaseCm);
}
public void IniciarFixacao()
@ -412,10 +412,9 @@ namespace OperationControl.ViewModels
public void FinalizarFixacao(bool sucesso, string? mensagem = null)
{
ExibirOffsets = sucesso;
FixacaoEmAndamento = false;
if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual && sucesso)
ProgressoFixacao = 100;
if (sucesso) ProgressoFixacao = 100;
StatusTexto = !string.IsNullOrWhiteSpace(mensagem)
? mensagem

View File

@ -1,15 +1,19 @@
using System.ComponentModel;
using System.Windows.Input;
using OperationControl.Views;
using OperationControl.Helpers;
using System.Windows;
using OperationControl.Models;
using OperationControl.Views.Operacao;
using AgroBase.Models.Operacoes;
using AgroBase.Models.Operacoes;
using AgroBase.Services;
using Microsoft.VisualBasic.Logging;
using Newtonsoft.Json.Linq;
using OperationControl.ViewModels.Views.Operacao;
using OpenTK.Windowing.Common.Input;
using OperationControl.Controls;
using OperationControl.Helpers;
using OperationControl.Models;
using OperationControl.ViewModels.Views.Operacao;
using OperationControl.Views;
using OperationControl.Views.Operacao;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using static AgroBase.Models.Enums;
using static OperationControl.Services.BaseFixService;
namespace OperationControl.ViewModels
{
@ -44,6 +48,7 @@ namespace OperationControl.ViewModels
_viewPreparacaoMapaBottom = new PreparacaoMapaBottomView();
_viewPreparacaoMapaBottom._vm.CarregarMapaSolicitado += OnCarregarMapaSolicitado;
_viewPreparacaoMapaBottom._vm.FixarBaseSolicitado += OnFixarBaseSolicitado;
_viewPreparacaoMapaBottom._vm.AplicarOffsetSolicitado += OnAplicarOffsetSolicitado;
_viewOperacaoTop = new OperacaoTopView();
@ -683,8 +688,6 @@ namespace OperationControl.ViewModels
if (string.IsNullOrWhiteSpace(linha2))
linha2 = "Sem detalhes adicionais.";
Models.Variaveis.MostrarLog($"LINHA 1: {linha1}");
// ============================
// 8) Atualiza UI
// ============================
@ -776,7 +779,7 @@ namespace OperationControl.ViewModels
}
}
private async void OnFixarBaseSolicitado(MetodoFixacaoBase metodoFix, double? lat, double? lon, double? alt, double? offsetFrontalCm, double? offsetLateralCm)
private async void OnFixarBaseSolicitado(MetodoFixacaoBase metodoFix, double? lat, double? lon, double? alt)
{
try
{
@ -803,14 +806,13 @@ namespace OperationControl.ViewModels
if (fixar)
{
_viewPreparacaoMapaBottom?._vm.IniciarFixacao();
await Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo(true, metodoFix, lat, lon, alt));
await Variaveis.GpsService.ConfigurarModulo(true, metodoFix, lat, lon, alt);
}
}
else
{
Variaveis.GpsService.BaseFix.ReiniciarFix();
BaseFixada = false;
_viewPreparacaoMapaBottom?._vm.CancelarFixacao("Fixação da base interrompida pelo operador.");
}
}
catch (Exception ex)
@ -845,6 +847,17 @@ namespace OperationControl.ViewModels
}));
}
private async void OnAplicarOffsetSolicitado(double? offsetFrontalCm, double? offsetLateralCm)
{
if (offsetFrontalCm == null || offsetLateralCm == null) return;
_viewPreparacaoMapaBottom?._vm.IniciarFixacao();
var gps = Variaveis.GpsService;
gps.LeverArm = new GeoLeverArm(offsetCampoFrontalCm: offsetFrontalCm.Value, offsetCampoLateralCm: offsetLateralCm.Value);
(double lat, double lon) = gps.LeverArm.FixLeverArmLatLon_Fast(gps.BaseFix.LatitudeFix, gps.BaseFix.LongitudeFix, gps.BaseFix.OrientacaoFix);
await Variaveis.GpsService.ConfigurarModulo(true, MetodoFixacaoBase.Manual, lat, lon, gps.BaseFix.AltitudeElpsoidalFix, offset: true);
}
#endregion
#region TELA 3

View File

@ -36,90 +36,39 @@
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="240"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="12"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Botão carregar mapa -->
<Button Grid.Column="0"
Content="Carregar mapa"
Margin="12,12,8,6"
Padding="18,10"
MinWidth="150"
Command="{Binding CarregarMapaCommand}"
IsEnabled="{Binding PodeCarregarMapa}"/>
<Button Grid.Column="0" Content="Carregar mapa" Margin="12,12,8,6" Padding="18,10" MinWidth="150" Command="{Binding CarregarMapaCommand}" IsEnabled="{Binding PodeCarregarMapa}"/>
<!-- Combo método -->
<ComboBox Grid.Column="1"
Margin="8,12,8,6"
VerticalContentAlignment="Center"
ItemsSource="{Binding MetodosFixacaoDisponiveis}"
DisplayMemberPath="Nome"
SelectedValuePath="Valor"
SelectedValue="{Binding MetodoFixacaoSelecionado, Mode=TwoWay}"
IsEnabled="{Binding PodeEditarMetodoFixacao}"/>
<ComboBox Grid.Column="1" Margin="8,12,8,6" VerticalContentAlignment="Center" ItemsSource="{Binding MetodosFixacaoDisponiveis}" DisplayMemberPath="Nome" SelectedValuePath="Valor" SelectedValue="{Binding MetodoFixacaoSelecionado, Mode=TwoWay}" IsEnabled="{Binding PodeEditarMetodoFixacao}"/>
<!-- Botão fixar -->
<Button Grid.Column="2"
Content="{Binding TextoBotaoFixarBase}"
Margin="8,12,12,6"
Padding="18,10"
MinWidth="180"
Command="{Binding FixarBaseCommand}"
IsEnabled="{Binding PodeFixarBase}"/>
<Button Grid.Column="2" Content="{Binding TextoBotaoFixarBase}" Margin="8,12,12,6" Padding="18,10" MinWidth="180" Command="{Binding FixarBaseCommand}" IsEnabled="{Binding PodeFixarBase}"/>
<!-- ÁREA DINÂMICA -->
<Grid Grid.Column="4" Margin="0,12,12,6">
<!-- Progresso normal + offsets -->
<Grid Visibility="{Binding ExibirProgresso, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid Grid.Column="3" Margin="0,12,12,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="320"/>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ProgressBar Grid.Column="0"
Margin="0,8,8,0"
Height="22"
Minimum="0"
Maximum="100"
Value="{Binding ProgressoFixacao}"/>
<!-- Progresso normal -->
<Grid Grid.Column="0" Visibility="{Binding ExibirProgresso, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="320"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1"
Text="{Binding ProgressoFixacaoTexto}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Foreground="White"
FontWeight="SemiBold"
FontSize="14"
Margin="0,0,8,0"/>
<ProgressBar Grid.Column="0" Margin="0,8,8,0" Height="22" Minimum="0" Maximum="100" Value="{Binding ProgressoFixacao}"/>
<TextBlock Grid.Column="2"
Text="Offset frontal (cm):"
Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="3"
Text="{Binding OffsetFrontalBaseTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource BottomTextBoxStyle}"
IsEnabled="{Binding PodeEditarOffsetBase}"/>
<TextBlock Grid.Column="4"
Text="Offset lateral (cm):"
Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="5"
Text="{Binding OffsetLateralBaseTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource BottomTextBoxStyle}"
IsEnabled="{Binding PodeEditarOffsetBase}"/>
<TextBlock Grid.Column="1" Text="{Binding ProgressoFixacaoTexto}" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontWeight="SemiBold" FontSize="14" Margin="0,0,8,0"/>
</Grid>
<!-- Campos manuais + offsets -->
<Grid Visibility="{Binding ExibirCamposManuais, Converter={StaticResource BoolToVisibilityConverter}}">
<!-- Campos manuais -->
<Grid Grid.Column="0" Visibility="{Binding ExibirCamposManuais, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="125"/>
@ -127,108 +76,57 @@
<ColumnDefinition Width="125"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="110"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="Latitude (º):"
Style="{StaticResource BottomLabelStyle}"/>
<TextBlock Grid.Column="0" Text="Latitude (º):" Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="1"
Text="{Binding LatitudeManualTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource BottomTextBoxStyle}"
IsEnabled="{Binding PodeEditarCoordenadasManuais}"/>
<TextBox Grid.Column="1" Text="{Binding LatitudeManualTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource BottomTextBoxStyle}" IsEnabled="{Binding PodeEditarCoordenadasManuais}"/>
<TextBlock Grid.Column="2"
Text="Longitude (º):"
Style="{StaticResource BottomLabelStyle}"/>
<TextBlock Grid.Column="2" Text="Longitude (º):" Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="3"
Text="{Binding LongitudeManualTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource BottomTextBoxStyle}"
IsEnabled="{Binding PodeEditarCoordenadasManuais}"/>
<TextBox Grid.Column="3" Text="{Binding LongitudeManualTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource BottomTextBoxStyle}" IsEnabled="{Binding PodeEditarCoordenadasManuais}"/>
<TextBlock Grid.Column="4"
Text="Altitude elipsoidal (m):"
Style="{StaticResource BottomLabelStyle}"/>
<TextBlock Grid.Column="4" Text="Altitude elipsoidal (m):" Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="5"
Text="{Binding AltitudeManualTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource BottomTextBoxStyle}"
IsEnabled="{Binding PodeEditarCoordenadasManuais}"/>
<TextBlock Grid.Column="6"
Text="Offset frontal (cm):"
Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="7"
Text="{Binding OffsetFrontalBaseTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource BottomTextBoxStyle}"
IsEnabled="{Binding PodeEditarOffsetBase}"/>
<TextBlock Grid.Column="8"
Text="Offset lateral (cm):"
Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="9"
Text="{Binding OffsetLateralBaseTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource BottomTextBoxStyle}"
IsEnabled="{Binding PodeEditarOffsetBase}"/>
<TextBox Grid.Column="5" Text="{Binding AltitudeManualTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource BottomTextBoxStyle}" IsEnabled="{Binding PodeEditarCoordenadasManuais}"/>
</Grid>
<!-- offsets -->
<Grid Grid.Column="1" Visibility="{Binding ExibirOffsets, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="90"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Offset frontal (cm):" Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="1" Text="{Binding OffsetFrontalBaseTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource BottomTextBoxStyle}" IsEnabled="{Binding PodeEditarOffsetBase}"/>
<TextBlock Grid.Column="2" Text="Offset lateral (cm):" Style="{StaticResource BottomLabelStyle}"/>
<TextBox Grid.Column="3" Text="{Binding OffsetLateralBaseTexto, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource BottomTextBoxStyle}" IsEnabled="{Binding PodeEditarOffsetBase}"/>
<Button Grid.Column="4" Content="Aplicar Offset" Margin="12,0,12,0" Padding="5,5" MinWidth="120" Command="{Binding AplicarOffsetCommand}" />
</Grid>
</Grid>
</Grid>
<!-- LINHA 2 -->
<Grid Grid.Row="1" Margin="12,4,12,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0"
Padding="8"
Background="#222"
CornerRadius="6">
<Border Grid.Row="0" Padding="2" Background="#222" CornerRadius="6">
<Grid>
<!-- Status normal -->
<StackPanel Visibility="{Binding ExibirStatusNormal, Converter={StaticResource BoolToVisibilityConverter}}">
<TextBlock Text="Status da operação"
Foreground="#AAAAAA"
FontSize="11"/>
<TextBlock Text="{Binding StatusTexto}"
Foreground="White"
FontSize="14"
TextWrapping="Wrap"/>
<StackPanel Grid.Column="0" Visibility="{Binding ExibirStatusNormal, Converter={StaticResource BoolToVisibilityConverter}}">
<TextBlock Text="{Binding StatusTexto}" Foreground="White" FontSize="14" TextWrapping="Wrap"/>
</StackPanel>
<!-- Texto orientativo manual -->
<StackPanel Visibility="{Binding ExibirCamposManuais, Converter={StaticResource BoolToVisibilityConverter}}">
<TextBlock Text="Preenchimento manual da base"
Foreground="#AAAAAA"
FontSize="11"/>
<TextBlock Text="Informe latitude, longitude e altitude elipsoidal conhecidas da base para aplicar a posição fixa manualmente."
Foreground="White"
FontSize="13"
TextWrapping="Wrap"/>
</StackPanel>
</Grid>
</Border>
<!-- Status complementar no manual -->
<Border Grid.Row="1"
Padding="8,6,8,0"
Background="Transparent"
Visibility="{Binding ExibirCamposManuais, Converter={StaticResource BoolToVisibilityConverter}}">
<TextBlock Text="{Binding StatusTexto}"
Foreground="#D8D8D8"
FontSize="12"
TextWrapping="Wrap"/>
</Border>
</Grid>
</Grid>
</UserControl>

View File

@ -16,6 +16,7 @@ using AgroBase.Models.Operadores;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Threading;
using static OperationControl.Services.BaseFixService;
namespace OperationControl.Windows
{
@ -1725,7 +1726,7 @@ namespace OperationControl.Windows
if (fixar)
{
btnGNSS_FixarBase.Content = "Parar";
Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo(true, ViewModels.MetodoFixacaoBase.Ntrip));
Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo(true, MetodoFixacaoBase.Ntrip));
}
}
else