corrigido carregamento do mapa na IHM

This commit is contained in:
Diego Freitas 2026-09-22 19:27:11 -03:00
parent 96c5049899
commit db10742954
6 changed files with 326 additions and 54 deletions

View File

@ -46,7 +46,7 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros
op.Mapa = new MapasModel();
_mapa = op.Mapa;
_mapa.pnlMapa = pnlMapaWeb;
_mapa.DefinirPainelMapa(pnlMapaWeb);
_mapa.RuasSelecionadasAlteradas += Mapa_RuasSelecionadasAlteradas;
_mapa.MapaCarregado += Mapa_MapaCarregado;
@ -167,7 +167,7 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros
if (_mapa == null)
return;
_mapa.pnlMapa = pnlMapaWeb;
_mapa.DefinirPainelMapa(pnlMapaWeb);
/*
* Esse método já abre o diálogo, pergunta o tipo
@ -341,7 +341,7 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros
if (object.ReferenceEquals(_mapa.pnlMapa, pnlMapaWeb))
{
_mapa.pnlMapa = null;
_mapa.DefinirPainelMapa(null);
}
_mapa = null;

View File

@ -43,15 +43,26 @@ namespace AgroBase.Forms.IHM.Operacao
return;
_mapasInicializados = true;
_mapaDinamico = new MapaDinamicoModel(formPai, pnlMapaDinamico);
_mapaDinamico =
new MapaDinamicoModel(
formPai,
pnlMapaDinamico
);
if (op == null)
return;
if (op?.Mapa == null)
if (op.Parametros?.Modo != Enums.ModoOperacao.MapaGPS)
{
MostrarMapaDinamico();
return;
}
if (op.Mapa == null)
op.Mapa = new MapasModel();
op.Mapa.pnlMapa = pnlMapaWeb;
op.Mapa.DefinirPainelMapa(pnlMapaWeb);
CarregarMapaWeb();
}
@ -136,6 +147,12 @@ namespace AgroBase.Forms.IHM.Operacao
if (op == null)
return;
if (op.Parametros?.Modo != Enums.ModoOperacao.MapaGPS)
{
MostrarMapaDinamico();
return;
}
MapasModel mapa = op.Mapa;
if (mapa == null)
@ -188,6 +205,12 @@ namespace AgroBase.Forms.IHM.Operacao
}
public void SolicitarAtualizacaoMapaWeb()
{
CarregarMapaWeb();
}
private void MostrarStatusAutonomia()
{
pnlAlertaAutonomia.Visible = false;

View File

@ -120,10 +120,9 @@ namespace AgroBase.Forms.IHM
VoltarSolicitado(this, EventArgs.Empty);
};
_ucParametros.ParametrosSalvos += async delegate
_ucParametros.ParametrosSalvos += delegate
{
_ucNavegacao.AtualizarMapaDinamico(true);
await _ucNavegacao.AtualizarMapaWebAsync();
};
tabMovimentacao.Click += delegate { SelecionarAba(AbaOperacaoIHM.Movimentacao, true); };
@ -152,6 +151,7 @@ namespace AgroBase.Forms.IHM
case AbaOperacaoIHM.Navegacao:
lblContextoAba.Text = "Mapa, GNSS, trajetória e autonomia por corredor";
ExibirConteudo(_ucNavegacao);
_ucNavegacao.SolicitarAtualizacaoMapaWeb();
break;
case AbaOperacaoIHM.Parametros:
lblContextoAba.Text = "Parâmetros da operação atual e configuração local";

View File

@ -8,6 +8,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static AgroBase.Models.Enums;
@ -60,6 +61,10 @@ namespace AgroBase.Models
private TaskCompletionSource<bool> _navegacaoTask;
private readonly SemaphoreSlim _browserInitLock = new SemaphoreSlim(1, 1);
private readonly SemaphoreSlim _navigationLock = new SemaphoreSlim(1, 1);
public MapasModel()
{
mapaService = new MapasService();
@ -245,83 +250,279 @@ namespace AgroBase.Models
private async Task InicializarBrowserAsync()
{
if (_browserInicializado && browser != null && !browser.IsDisposed)
{
if (_disposed)
return;
if (pnlMapa == null)
{
throw new InvalidOperationException(
"O painel de mapa não foi definido.");
}
if (pnlMapa.InvokeRequired)
{
throw new InvalidOperationException("InicializarBrowserAsync deve ser chamado " + "na thread da interface.");
throw new InvalidOperationException(
"InicializarBrowserAsync deve ser chamado na thread da interface.");
}
browser = new WebView2();
browser.Dock = DockStyle.Fill;
browser.Margin = Padding.Empty;
browser.Visible = false;
pnlMapa.Controls.Add(browser);
browser.BringToFront();
await _browserInitLock.WaitAsync();
await browser.EnsureCoreWebView2Async();
try
{
/*
* Outra chamada pode ter inicializado enquanto esta
* aguardava o lock.
*/
if (
_browserInicializado &&
browser != null &&
!browser.IsDisposed &&
browser.CoreWebView2 != null
)
{
return;
}
browser.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
browser.CoreWebView2.Settings.AreDevToolsEnabled = true;
browser.CoreWebView2.Settings.IsStatusBarEnabled = false;
browser.CoreWebView2.WebMessageReceived -= CoreWebView2_WebMessageReceived;
browser.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
browser.NavigationCompleted -= Browser_NavigationCompleted;
browser.NavigationCompleted += Browser_NavigationCompleted;
pnlMapa.Resize -= PnlMapa_Resize;
pnlMapa.Resize += PnlMapa_Resize;
/*
* Remove uma instância anterior incompleta,
* se por algum motivo ela existir.
*/
if (browser != null)
{
try
{
browser.NavigationCompleted -=
Browser_NavigationCompleted;
_browserInicializado = true;
if (browser.CoreWebView2 != null)
{
browser.CoreWebView2.WebMessageReceived -=
CoreWebView2_WebMessageReceived;
}
if (browser.Parent != null)
{
browser.Parent.Controls.Remove(browser);
}
if (!browser.IsDisposed)
{
browser.Dispose();
}
}
catch
{
// Estamos descartando uma instância incompleta.
}
browser = null;
}
_browserInicializado = false;
/*
* IMPORTANTE:
*
* inicializa em variável LOCAL.
*
* Assim nenhuma outra chamada consegue trocar
* a instância que estamos aguardando.
*/
var novoBrowser = new WebView2
{
Dock = DockStyle.Fill,
Margin = Padding.Empty,
Visible = false
};
pnlMapa.Controls.Add(novoBrowser);
novoBrowser.BringToFront();
try
{
await novoBrowser.EnsureCoreWebView2Async();
/*
* A tela/modelo pode ter sido destruída
* durante o await.
*/
if (_disposed || novoBrowser.IsDisposed)
{
if (!novoBrowser.IsDisposed)
{
novoBrowser.Dispose();
}
return;
}
var core = novoBrowser.CoreWebView2;
if (core == null)
{
throw new InvalidOperationException(
"O WebView2 concluiu a inicialização, " +
"mas CoreWebView2 permaneceu indisponível.");
}
core.Settings.AreDefaultContextMenusEnabled = false;
core.Settings.AreDevToolsEnabled = true;
core.Settings.IsStatusBarEnabled = false;
core.WebMessageReceived -=
CoreWebView2_WebMessageReceived;
core.WebMessageReceived +=
CoreWebView2_WebMessageReceived;
novoBrowser.NavigationCompleted -=
Browser_NavigationCompleted;
novoBrowser.NavigationCompleted +=
Browser_NavigationCompleted;
pnlMapa.Resize -=
PnlMapa_Resize;
pnlMapa.Resize +=
PnlMapa_Resize;
/*
* Só agora publicamos a instância
* completamente inicializada.
*/
browser = novoBrowser;
_browserInicializado = true;
}
catch
{
if (novoBrowser.Parent != null)
{
novoBrowser.Parent.Controls.Remove(
novoBrowser);
}
if (!novoBrowser.IsDisposed)
{
novoBrowser.Dispose();
}
throw;
}
}
finally
{
_browserInitLock.Release();
}
}
private async Task NavegarParaMapaAsync()
{
if (browser == null || browser.CoreWebView2 == null)
await _navigationLock.WaitAsync();
TaskCompletionSource<bool> navegacaoAtual = null;
try
{
return;
if (_disposed)
return;
WebView2 browserAtual = browser;
if (
browserAtual == null ||
browserAtual.IsDisposed ||
browserAtual.CoreWebView2 == null
)
{
return;
}
_paginaCarregada = false;
navegacaoAtual =
new TaskCompletionSource<bool>(
TaskCreationOptions.RunContinuationsAsynchronously
);
_navegacaoTask = navegacaoAtual;
string uriComVersao =
new Uri(mapaService.CaminhoHtml).AbsoluteUri +
"?v=" +
DateTime.UtcNow.Ticks;
browserAtual.CoreWebView2.Navigate(uriComVersao);
Task timeout =
Task.Delay(TimeSpan.FromSeconds(10));
Task concluida =
await Task.WhenAny(
navegacaoAtual.Task,
timeout
);
if (concluida == timeout)
{
navegacaoAtual.TrySetCanceled();
throw new TimeoutException(
"O mapa não concluiu o carregamento no tempo esperado.");
}
await navegacaoAtual.Task;
}
_paginaCarregada = false;
_navegacaoTask = new TaskCompletionSource<bool>();
string uriComVersao = new Uri(mapaService.CaminhoHtml).AbsoluteUri + "?v=" + DateTime.UtcNow.Ticks;
browser.CoreWebView2.Navigate(uriComVersao);
Task timeout = Task.Delay(TimeSpan.FromSeconds(10));
Task concluida = await Task.WhenAny(_navegacaoTask.Task, timeout);
if (concluida == timeout)
finally
{
_navegacaoTask.TrySetCanceled();
throw new TimeoutException("O mapa não concluiu o carregamento no tempo esperado.");
}
if (
navegacaoAtual != null &&
ReferenceEquals(
_navegacaoTask,
navegacaoAtual
)
)
{
_navegacaoTask = null;
}
await _navegacaoTask.Task;
_navigationLock.Release();
}
}
private void Browser_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
if (_navegacaoTask == null)
var navegacao = _navegacaoTask;
if (navegacao == null)
return;
if (!(sender is WebView2 browserEvento))
return;
if (browserEvento.IsDisposed)
return;
if (!e.IsSuccess)
{
_navegacaoTask.TrySetException(new InvalidOperationException("Falha ao abrir o HTML do mapa. " + "Erro WebView2: " + e.WebErrorStatus));
navegacao.TrySetException(
new InvalidOperationException(
"Falha ao abrir o HTML do mapa. " +
"Erro WebView2: " +
e.WebErrorStatus
)
);
return;
}
_paginaCarregada = true;
browser.Visible = true;
browser.BringToFront();
_navegacaoTask.TrySetResult(true);
browserEvento.Visible = true;
browserEvento.BringToFront();
navegacao.TrySetResult(true);
}
private async Task EnviarMapaParaJavascriptAsync()
@ -755,6 +956,48 @@ namespace AgroBase.Models
}
public void DefinirPainelMapa(Panel painel)
{
if (_disposed)
return;
pnlMapa = painel;
if (
painel == null ||
painel.IsDisposed ||
browser == null ||
browser.IsDisposed
)
{
return;
}
if (painel.InvokeRequired)
{
painel.BeginInvoke(
new Action<Panel>(DefinirPainelMapa),
painel
);
return;
}
if (!ReferenceEquals(browser.Parent, painel))
{
if (browser.Parent != null)
{
browser.Parent.Controls.Remove(browser);
}
painel.Controls.Add(browser);
}
browser.Dock = DockStyle.Fill;
browser.BringToFront();
}
public void Dispose()
{
if (_disposed)
@ -762,6 +1005,10 @@ namespace AgroBase.Models
_disposed = true;
_browserInicializado = false;
_paginaCarregada = false;
_mapaEnviado = false;
if (pnlMapa != null)
{
pnlMapa.Resize -=

View File

@ -1349,7 +1349,7 @@ namespace AgroBase.Models
var ruasSelecionadas = parametros.RuasPercorrer ?? new List<string>();
if (parametros.Mapa != null)
if (parametros.Mapa != null && parametros.Modo == ModoOperacao.MapaGPS)
{
novaOp.Mapa = new MapasModel();
novaOp.Mapa.DefinirRuasSelecionadas(novaOp, ruasSelecionadas);

View File

@ -867,6 +867,8 @@ namespace AgroBase.Services
let camadaTrajetoriaPlanejada = null;
let camadaRastroRover = null;
let camadaRastroBase = null;
let camadaTrajetoGps = null;
let pontosTrajetoGps = [];
let pontosRastroRover = [];
let pontosRastroBase = [];
let ultimaPosicaoBase = null;