incluido metodos de fixacao da base

This commit is contained in:
Diego Freitas 2026-03-18 07:40:59 -03:00
parent b3cfd8b7cb
commit a441b3997c
16 changed files with 818 additions and 180 deletions

View File

@ -1813,7 +1813,7 @@ namespace AgroBase.Models
idx++; idx++;
} }
traj[traj.Count - 1].LarguraCorredor = distanciaPararAntecipado; // Considerar que chegou na base a 2,5 m traj[traj.Count - 1].LarguraCorredor = distanciaPararAntecipado;
DistanciaTotal = GPSUtils.DistanciaDoTrecho(traj.Select(x => x.Posicao).ToList()); DistanciaTotal = GPSUtils.DistanciaDoTrecho(traj.Select(x => x.Posicao).ToList());
DistanciaPercorrida = 0.0; DistanciaPercorrida = 0.0;
@ -2839,8 +2839,7 @@ namespace AgroBase.Models
bool herbOk = HerbicidaSuficiente && (_Reservatorio?.Iniciado ?? false); bool herbOk = HerbicidaSuficiente && (_Reservatorio?.Iniciado ?? false);
bool exigirPulverizacaoTotal = bool exigirPulverizacaoTotal =
Variaveis.OperacaoEmAndamento.Parametros?.ModulosMandatorios? Variaveis.OperacaoEmAndamento.Parametros?.ModulosMandatorios?.Any(x => x.Dispositivo == T_Code.Atu && x.Mandatorio && x.Utilizar) ?? false;
.Any(x => x.Dispositivo == T_Code.Atu && x.Mandatorio && x.Utilizar) ?? false;
// ========================== // ==========================
// 1) Calcula status "base" (sem considerar trava) // 1) Calcula status "base" (sem considerar trava)

View File

@ -30,6 +30,9 @@ class ModuloAtuador(ModuloDiagnosticoBase):
FREQ_MIN = FREQ_BASE * 0.5 FREQ_MIN = FREQ_BASE * 0.5
SAUDE_MIN_ALERTA = 80 SAUDE_MIN_ALERTA = 80
mods_mandatorios = ContextoGlobalRedis.get_operacao().get("modulos_mandatorios", [])
atu_mandatorio = self.t_code.value in mods_mandatorios
sensor_massa_em_uso = False sensor_massa_em_uso = False
sensor_massa_conectado = False sensor_massa_conectado = False
@ -48,7 +51,7 @@ class ModuloAtuador(ModuloDiagnosticoBase):
aferir = dados_sensor.get("aferir", False) aferir = dados_sensor.get("aferir", False)
padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {}) padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {})
conectado = dados_sensor.get("conectado", False) conectado = dados_sensor.get("conectado", False)
mandatorio = dados_sensor.get("mandatorio", False) mandatorio = dados_sensor.get("mandatorio", False) if atu_mandatorio else False
if dados_sensor.get("label") == "MASRS": if dados_sensor.get("label") == "MASRS":
sensor_massa_em_uso = mandatorio and aferir sensor_massa_em_uso = mandatorio and aferir
sensor_massa_conectado = conectado sensor_massa_conectado = conectado
@ -56,31 +59,30 @@ class ModuloAtuador(ModuloDiagnosticoBase):
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")
else: else:
for campo in dados_sensor.get("dados", []): for campo in dados_sensor.get("dados", []):
label = campo.get("label") label = campo.get("label")
if label is None: if label is None:
continue continue
freq = campo.get("freq", 0.0) freq = campo.get("freq", 0.0)
if freq == 0: if freq == 0:
saude = 0 saude = 0
motivos.append(f"{label} sem resposta (freq = 0 Hz)") motivos.append(f"{label} sem resposta (freq = 0 Hz)")
else: else:
penalidade = penalizar_frequencia(freq, FREQ_BASE, FREQ_MIN, (100 - SAUDE_MIN_ALERTA)) penalidade = penalizar_frequencia(freq, FREQ_BASE, FREQ_MIN, (100 - SAUDE_MIN_ALERTA))
saude -= penalidade saude -= penalidade
if (freq <= FREQ_MIN): if (freq <= FREQ_MIN):
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)") motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
atual = campo.get("atual")
atual = campo.get("atual") padrao = padroes.get(label) if atual else None
padrao = padroes.get(label) if atual else None if padrao is not None:
if padrao is not None: # Avaliação de condição operacional (sem penalizar saúde)
# Avaliação de condição operacional (sem penalizar saúde) if not padrao.esta_dentro_do_padrao(atual):
if not padrao.esta_dentro_do_padrao(atual): grau = padrao.calcular_quao_anormal(atual)
grau = padrao.calcular_quao_anormal(atual) condicoes_operacionais.append({
condicoes_operacionais.append({ "valor": atual,
"valor": atual, "severidade": grau,
"severidade": grau, "descricao": f"{label} fora do padrão"
"descricao": f"{label} fora do padrão" })
})
saude = max(0, saude) saude = max(0, saude)
chave = f"{S_Code(int(tipo)).name}_{sensor_id}" chave = f"{S_Code(int(tipo)).name}_{sensor_id}"
saude_mod = { saude_mod = {
@ -115,7 +117,7 @@ class ModuloAtuador(ModuloDiagnosticoBase):
comandar = dados_bico.get("comandar", False) comandar = dados_bico.get("comandar", False)
padroes = self.padroes_bicos.get(tipo, {}).get(bico_id, {}) padroes = self.padroes_bicos.get(tipo, {}).get(bico_id, {})
conectado = dados_bico.get("conectado", False) conectado = dados_bico.get("conectado", False)
mandatorio = dados_bico.get("mandatorio", False) mandatorio = dados_bico.get("mandatorio", False) if atu_mandatorio else False
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")
@ -177,7 +179,7 @@ class ModuloAtuador(ModuloDiagnosticoBase):
comandar = dados_bomba.get("comandar", False) comandar = dados_bomba.get("comandar", False)
padroes = self.padroes_bombas.get(tipo, {}).get(bomba_id, {}) padroes = self.padroes_bombas.get(tipo, {}).get(bomba_id, {})
conectado = dados_bomba.get("conectado", False) conectado = dados_bomba.get("conectado", False)
mandatorio = dados_bomba.get("mandatorio", False) mandatorio = dados_bomba.get("mandatorio", False) if atu_mandatorio else False
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")
@ -237,7 +239,7 @@ class ModuloAtuador(ModuloDiagnosticoBase):
condicoes_operacionais = [] condicoes_operacionais = []
controlar = dados_servo.get("controlar", False) controlar = dados_servo.get("controlar", False)
conectado = dados_servo.get("conectado", False) conectado = dados_servo.get("conectado", False)
mandatorio = dados_servo.get("mandatorio", False) mandatorio = dados_servo.get("mandatorio", False) if atu_mandatorio else False
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")

View File

@ -31,6 +31,9 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
FREQ_MIN = FREQ_BASE * 0.5 FREQ_MIN = FREQ_BASE * 0.5
SAUDE_MIN_ALERTA = 80 SAUDE_MIN_ALERTA = 80
mods_mandatorios = ContextoGlobalRedis.get_operacao().get("modulos_mandatorios", [])
sen_mandatorio = self.t_code.value in mods_mandatorios
sensor_bateria_em_uso = False sensor_bateria_em_uso = False
sensor_bateria_conectado = False sensor_bateria_conectado = False
@ -49,7 +52,7 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
aferir = dados_sensor.get("aferir", False) aferir = dados_sensor.get("aferir", False)
padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {}) padroes = self.padroes_sensores.get(tipo, {}).get(sensor_id, {})
conectado = dados_sensor.get("conectado", False) conectado = dados_sensor.get("conectado", False)
mandatorio = dados_sensor.get("mandatorio", False) mandatorio = dados_sensor.get("mandatorio", False) if sen_mandatorio else False
if dados_sensor.get("label") == "AB36V": if dados_sensor.get("label") == "AB36V":
bms_conetado = dados_sen.get("bms_ligado", False) bms_conetado = dados_sen.get("bms_ligado", False)
sensor_bateria_em_uso = not bms_conetado and mandatorio and aferir sensor_bateria_em_uso = not bms_conetado and mandatorio and aferir
@ -116,7 +119,7 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
condicoes_operacionais = [] condicoes_operacionais = []
controlar = dados_servo.get("controlar", False) controlar = dados_servo.get("controlar", False)
conectado = dados_servo.get("conectado", False) conectado = dados_servo.get("conectado", False)
mandatorio = dados_servo.get("mandatorio", False) mandatorio = dados_servo.get("mandatorio", False) if sen_mandatorio else False
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")
@ -179,7 +182,7 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
condicoes_operacionais = [] condicoes_operacionais = []
controlar = dados_rele.get("controlar", False) controlar = dados_rele.get("controlar", False)
conectado = dados_rele.get("conectado", False) conectado = dados_rele.get("conectado", False)
mandatorio = dados_rele.get("mandatorio", False) mandatorio = dados_rele.get("mandatorio", False) if sen_mandatorio else False
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")
@ -232,7 +235,7 @@ class ModuloSensoriamento(ModuloDiagnosticoBase):
condicoes_operacionais = [] condicoes_operacionais = []
controlar = dados_led.get("controlar", False) controlar = dados_led.get("controlar", False)
conectado = dados_led.get("conectado", False) conectado = dados_led.get("conectado", False)
mandatorio = dados_led.get("mandatorio", False) mandatorio = dados_led.get("mandatorio", False) if sen_mandatorio else False
if not conectado: if not conectado:
saude = 0 saude = 0
motivos.append(f"desconectado") motivos.append(f"desconectado")

View File

@ -17,16 +17,16 @@ def verifica_controle_liberado(ignorar_parada=False):
oak_parada_por_bloqueio = _controle.get("oak_parada_por_bloqueio", False) oak_parada_por_bloqueio = _controle.get("oak_parada_por_bloqueio", False)
if oak_parada_por_bloqueio: if oak_parada_por_bloqueio:
_dados_vw = ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {})
_snr = ContextoGlobalRedis.get_modulo(T_Code.Snr) _snr = ContextoGlobalRedis.get_modulo(T_Code.Snr)
_snr_saude = StatusModulo(_snr.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value)) _snr_saude = StatusModulo(_snr.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value))
visual_worker_operante = _snr_saude in [StatusModulo.OPERANTE, StatusModulo.ALERTA] snr_operante = _snr_saude in [StatusModulo.OPERANTE, StatusModulo.ALERTA]
_dados_vw = ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {})
analise_deteccao_atualizada = (time.perf_counter() - _dados_vw.get("matriz_confianca", {}).get("ts", 10.0) <= 1.0) analise_deteccao_atualizada = (time.perf_counter() - _dados_vw.get("matriz_confianca", {}).get("ts", 10.0) <= 1.0)
obstaculo_detectado = _dados_vw.get("matriz_confianca", {}).get("block", {}).get("decision", {}).get("parar", False) if analise_deteccao_atualizada else False obstaculo_detectado = _dados_vw.get("matriz_confianca", {}).get("block", {}).get("decision", {}).get("parar", False) if analise_deteccao_atualizada else False
if (not visual_worker_operante): if (not snr_operante):
motivos.append(f"Sonar mandatório não operante: {_snr_saude.name}") motivos.append(f"Sonar mandatório não operante: {_snr_saude.name}")
elif (visual_worker_operante and obstaculo_detectado): elif (snr_operante and obstaculo_detectado):
motivos.append(f"Obstáculo próximo detectado no sonar") motivos.append(f"Obstáculo próximo detectado no sonar")
imu_parada_por_inclinacao = _controle.get("imu_parada_por_inclinacao", False) imu_parada_por_inclinacao = _controle.get("imu_parada_por_inclinacao", False)

View File

@ -230,7 +230,7 @@ class ContextoGlobalRedis:
continue continue
try: try:
_mod_data = cls.get(cls.ModKey(t_code), {}) _mod_data = cls.get_modulo(t_code)
_saude = _mod_data.get("saude", {}) _saude = _mod_data.get("saude", {})
conectado = _saude.get("conectado", False) conectado = _saude.get("conectado", False)
status = _saude.get("status", (StatusModulo.FALHA.value if conectado else StatusModulo.DESCONECTADO.value)) status = _saude.get("status", (StatusModulo.FALHA.value if conectado else StatusModulo.DESCONECTADO.value))

View File

@ -2,6 +2,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup" Startup="Application_Startup"
ShutdownMode="OnMainWindowClose"
> >
<Application.Resources> <Application.Resources>

View File

@ -16,6 +16,9 @@ namespace OperationControl
// Cria o “controlador”/janela raiz // Cria o “controlador”/janela raiz
Shell = new AppShell(); Shell = new AppShell();
Shell.Inicializar(); Shell.Inicializar();
MainWindow = Shell.Dock;
MainWindow.Show();
} }
} }

View File

@ -35,7 +35,6 @@ namespace OperationControl.Models
// Aqui você decide qual janela é a inicial de fato // Aqui você decide qual janela é a inicial de fato
Main = new MainWindow(); Main = new MainWindow();
Dock = new DockWindow(); Dock = new DockWindow();
Dock.Show();
if (Mock && AddRover) if (Mock && AddRover)
{ {
@ -51,6 +50,7 @@ namespace OperationControl.Models
StatusRover = StatusModulo.Operante, StatusRover = StatusModulo.Operante,
Operacao = new AgroBase.Models.Operacoes.OperacaoParametrosDadosOperacaoModel() Operacao = new AgroBase.Models.Operacoes.OperacaoParametrosDadosOperacaoModel()
{ {
Modo = AgroBase.Models.Enums.ModoOperacao.MapaGPS,
Status = StatusOperacao.Parametrizando, Status = StatusOperacao.Parametrizando,
}, },
Atuador = new AgroBase.Models.Operacoes.OperacaoParametrosDadosAtuadorModel() Atuador = new AgroBase.Models.Operacoes.OperacaoParametrosDadosAtuadorModel()

View File

@ -191,7 +191,7 @@ namespace OperationControl.Models
{ {
var logs = RoversNaRede[index].DadosLeitura?.Logs ?? new List<OperacaoSensoriamentoLogErrosModel>(); var logs = RoversNaRede[index].DadosLeitura?.Logs ?? new List<OperacaoSensoriamentoLogErrosModel>();
obj.UltimoContato = DateTime.Now; obj.UltimoContato = DateTime.Now;
obj.DadosLeitura.Logs.AddRange(logs); obj.DadosLeitura.Logs?.AddRange(logs);
RoversNaRede[index] = obj; RoversNaRede[index] = obj;
} }
} }
@ -244,21 +244,24 @@ namespace OperationControl.Models
rover.DadosLeitura.Momento = DateTime.Now; rover.DadosLeitura.Momento = DateTime.Now;
if (rover.DadosLeitura.Operacao == null) rover.DadosLeitura.Operacao = new OperacaoParametrosDadosOperacaoModel(); if (rover.DadosLeitura.Operacao == null) rover.DadosLeitura.Operacao = new OperacaoParametrosDadosOperacaoModel();
rover.DadosLeitura.Operacao.Status = AgroBase.Models.Enums.StatusOperacao.Erro; rover.DadosLeitura.Operacao.Status = AgroBase.Models.Enums.StatusOperacao.Erro;
((App)Application.Current).Shell.Main?.AtualizarDadosTela_Telemetria(rover.RoverId); ((App)Application.Current)?.Shell?.Main?.AtualizarDadosTela_Telemetria(rover.RoverId);
((App)Application.Current).Shell.Main?.AdicionarAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!"); ((App)Application.Current)?.Shell?.Main?.AdicionarAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
((App)Application.Current).Shell?.AdicionarAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
((App)Application.Current)?.Shell?.AdicionarAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb, SeveridadeAlerta.Critical, "Perda de comunicação com o equipamento!");
((App)Application.Current)?.Shell?.Dock?._vm?._viewOperacaoCenter?.Mapa?.markers?.UpdateMarkerInfo(rover.RoverId, status: AgroBase.Models.Enums.StatusOperacao.Erro);
} }
else else
{ {
((App)Application.Current).Shell.Main?.RemoverAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb); ((App)Application.Current)?.Shell?.Main?.RemoverAlerta(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb);
((App)Application.Current).Shell.RemoverAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb); ((App)Application.Current)?.Shell?.RemoverAlertaDock(rover.RoverId, AgroBase.Models.Enums.T_Code.Ipb);
} }
((App)Application.Current).Shell.Dock?._vm?.AtualizarBarraSuperior(rover); ((App)Application.Current)?.Shell?.Dock?._vm?.AtualizarBarraSuperior(rover);
} }
Application.Current.Dispatcher.BeginInvoke(new Action(() => Application.Current?.Dispatcher?.BeginInvoke(new Action(() =>
{ {
((App)Application.Current).Shell.Dock?._vm?.AtualizarListaRovers(rovers_atual); ((App)Application.Current)?.Shell?.Dock?._vm?.AtualizarListaRovers(rovers_atual);
})); }));
} }
finally finally

View File

@ -242,49 +242,133 @@ namespace OperationControl.Services
private List<byte> _rtcmMsg = new(); private List<byte> _rtcmMsg = new();
private int _rtcmTotalBytes = -1; private int _rtcmTotalBytes = -1;
public async Task ConfigurarModulo(bool fixar) public async Task ConfigurarModulo(bool fixar, MetodoFixacaoBase metodo = MetodoFixacaoBase.Ntrip, double? lat = null, double? lon = null, double? alt = null)
{ {
Models.Variaveis.MostrarLog("Iniciando configuração do módulo GPS..."); Models.Variaveis.MostrarLog("Iniciando configuração do módulo GPS...");
LeverArm = new GeoLeverArm(VariaveisControleOperacao.LeverArmFrontal, VariaveisControleOperacao.LeverArmLateral);
LeverArm = new GeoLeverArm(
VariaveisControleOperacao.LeverArmFrontal,
VariaveisControleOperacao.LeverArmLateral);
BaseFix = new BaseFixService(PortaGps, this); BaseFix = new BaseFixService(PortaGps, this);
BaseFix.FixLiberado = fixar; BaseFix.FixLiberado = fixar;
if (fixar)
string portaUsb = "com3";
string portaSaida = "com3";
string portaEntrada = "com3";
string baseId = "957";
if (!fixar)
{ {
bool sucesso = await BaseFix.FixarBaseViaNtripAsync( Models.Variaveis.MostrarLog("Configurando módulo como rover parado...");
portaUsb: "com3", await BaseFix.ConfigurarComoRoverParadoAsync(
portaSaida: "com3", portaUsb: portaUsb,
portaEntrada: "com3", portaEntrada: portaEntrada);
startNtrip: async () => return;
{
Models.Variaveis.MostrarLog("Iniciando correção NTRIP...");
CorrecaoRTK_Ntrip = true;
Task.Run(async () => await AplicarCorrecaoRTK_Ntrip());
},
stopNtrip: async () =>
{
Models.Variaveis.MostrarLog("Parando correção NTRIP...");
CorrecaoRTK_Ntrip = false;
},
segsFixEstavel: TempoSurveryIn
);
if (!sucesso)
{
Models.Variaveis.MostrarLog("Configurando módulo como base survery in...");
BaseFix.fimProcesso = null;
BaseFix.inicioProcesso = DateTime.UtcNow;
await ConfigurarModuloBase(tempo_fixacao: TempoSurveryIn, porta_usb: "com3", porta_saida: "com3");
BaseFix.inicioFix = DateTime.UtcNow;
}
else
{
Models.Variaveis.MostrarLog("Posição fixada utilizando o Ntrip com sucesso!");
}
} }
else
bool sucesso = false;
string mensagem = "";
switch (metodo)
{ {
await BaseFix.ConfigurarComoRoverParadoAsync(portaUsb: "com3", portaEntrada: "com3"); case MetodoFixacaoBase.Ntrip:
{
Models.Variaveis.MostrarLog("Tentando fixação da base via NTRIP...");
sucesso = await BaseFix.FixarBaseViaNtripAsync(
portaUsb: portaUsb,
portaSaida: portaSaida,
portaEntrada: portaEntrada,
startNtrip: () =>
{
Models.Variaveis.MostrarLog("Iniciando correção NTRIP...");
CorrecaoRTK_Ntrip = true;
_ = Task.Run(async () => await AplicarCorrecaoRTK_Ntrip());
return Task.CompletedTask;
},
stopNtrip: () =>
{
Models.Variaveis.MostrarLog("Parando correção NTRIP...");
CorrecaoRTK_Ntrip = false;
return Task.CompletedTask;
},
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...");
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.Manual:
{
if (!lat.HasValue || !lon.HasValue || !alt.HasValue)
throw new ArgumentException("Latitude, longitude e altitude elipsoidal são obrigatórias no modo manual.");
Models.Variaveis.MostrarLog("Aplicando posição manual fixa da base...");
UltimaLeitura.Latitude = lat.Value;
UltimaLeitura.Longitude = lon.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;
}
} }
Models.Variaveis.MostrarLog(mensagem);
((App)Application.Current)?.Shell?.Dock?._vm?._viewPreparacaoMapaBottom?._vm?.FinalizarFixacao(sucesso, mensagem);
} }
private async Task ConfigurarModuloBase(string porta_usb = "com3", string porta_saida = "com2", int tempo_fixacao = 60) private async Task ConfigurarModuloBase(string porta_usb = "com3", string porta_saida = "com2", int tempo_fixacao = 60)
@ -1497,14 +1581,14 @@ namespace OperationControl.Services
$"unlog com2\r\n", $"unlog com2\r\n",
$"unlog com3\r\n" $"unlog com3\r\n"
}; };
foreach (var c in pre) { _Porta.Write(Encoding.ASCII.GetBytes(c), 0, c.Length); await Task.Delay(150); } foreach (var c in pre) { _Porta?.Write(Encoding.ASCII.GetBytes(c), 0, c.Length); await Task.Delay(150); }
var latStr = latDeg.ToString("0.000000000", ci); var latStr = latDeg.ToString("0.000000000", ci);
var lonStr = lonDeg.ToString("0.000000000", ci); var lonStr = lonDeg.ToString("0.000000000", ci);
var hStr = hEllipsM.ToString("0.000", ci); var hStr = hEllipsM.ToString("0.000", ci);
var fix = Encoding.ASCII.GetBytes($"mode base {baseId} {latStr} {lonStr} {hStr}\r\n"); var fix = Encoding.ASCII.GetBytes($"mode base {baseId} {latStr} {lonStr} {hStr}\r\n");
_Porta.Write(fix, 0, fix.Length); _Porta?.Write(fix, 0, fix.Length);
await Task.Delay(250); await Task.Delay(250);
// Reativar RTCM no canal de saída para o LoRa // Reativar RTCM no canal de saída para o LoRa
@ -1521,18 +1605,26 @@ namespace OperationControl.Services
//$"RTCM1230 {portaSaida} 10\r\n",// Bias GLONASS (OBRIGATÓRIO se 1084 estiver ativo) //$"RTCM1230 {portaSaida} 10\r\n",// Bias GLONASS (OBRIGATÓRIO se 1084 estiver ativo)
}; };
foreach (var c in rtcmCmds) { var b = Encoding.ASCII.GetBytes(c); _Porta.Write(b, 0, b.Length); await Task.Delay(200); } foreach (var c in rtcmCmds) { var b = Encoding.ASCII.GetBytes(c); _Porta?.Write(b, 0, b.Length); await Task.Delay(200); }
// NMEA mínimo na USB p/ debug // NMEA mínimo na USB p/ debug
var nmea = $"gngga {portaUsb} 1\r\n"; var nmea = $"gngga {portaUsb} 1\r\n";
_Porta.Write(Encoding.ASCII.GetBytes(nmea), 0, nmea.Length); _Porta?.Write(Encoding.ASCII.GetBytes(nmea), 0, nmea.Length);
await Task.Delay(150); await Task.Delay(150);
// Persistir // Persistir
var save = "saveconfig\r\n"; var save = "saveconfig\r\n";
_Porta.Write(Encoding.ASCII.GetBytes(save), 0, save.Length); _Porta?.Write(Encoding.ASCII.GetBytes(save), 0, save.Length);
} }
public enum MetodoFixacaoBase
{
Automatico = 0,
Ntrip = 1,
SurveyIn = 2,
Manual = 3
}
} }
} }

View File

@ -5,6 +5,7 @@ using OperationControl.Models;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using static AgroBase.Models.Enums; using static AgroBase.Models.Enums;
@ -144,9 +145,19 @@ namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
private void ExecutarRetornoBase() private void ExecutarRetornoBase()
{ {
double lat = OperationControl.Models.Variaveis.GpsService.UltimaLeitura.Latitude; if (System.Windows.MessageBox.Show("Deseja solicitar o retorno do equipamento até a base?", "Retorno à base", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
double lon = OperationControl.Models.Variaveis.GpsService.UltimaLeitura.Longitude; {
VariaveisControleOperacao.EnviarComandoRetornoBase(lat, lon); var gps = OperationControl.Models.Variaveis.GpsService.UltimaLeitura;
double? lat = gps?.Latitude;
double? lon = gps?.Longitude;
if (lat == null || lon == null)
{
System.Windows.MessageBox.Show("É necessário que as coordenadas da base estejam definidas para solicitar o retorno", "Base não fixada", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
VariaveisControleOperacao.EnviarComandoRetornoBase(lat, lon);
}
} }
private bool PodeExecutarRetornoBase() private bool PodeExecutarRetornoBase()

View File

@ -1,13 +1,39 @@
using OperationControl.Helpers; using OperationControl.Helpers;
using System;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
namespace OperationControl.ViewModels namespace OperationControl.ViewModels
{ {
public enum MetodoFixacaoBase
{
Ntrip = 0,
SurveyIn = 1,
Manual = 2
}
public class MetodoFixacaoItem
{
public MetodoFixacaoBase Valor { get; set; }
public string Nome { get; set; } = string.Empty;
}
public class PreparacaoMapaBottomViewModel : INotifyPropertyChanged public class PreparacaoMapaBottomViewModel : INotifyPropertyChanged
{ {
public event PropertyChangedEventHandler? PropertyChanged;
public event Action<string>? CarregarMapaSolicitado; public event Action<string>? CarregarMapaSolicitado;
public event Action? FixarBaseSolicitado; public event Action<MetodoFixacaoBase, double?, double?, double?>? FixarBaseSolicitado;
public List<MetodoFixacaoItem> MetodosFixacaoDisponiveis { get; } = new()
{
new MetodoFixacaoItem { Valor = MetodoFixacaoBase.Ntrip, Nome = "Utilizando NTRIP" },
new MetodoFixacaoItem { Valor = MetodoFixacaoBase.SurveyIn, Nome = "Modo Survey-In" },
new MetodoFixacaoItem { Valor = MetodoFixacaoBase.Manual, Nome = "Preenchimento manual" }
};
private bool _fixacaoEmAndamento; private bool _fixacaoEmAndamento;
public bool FixacaoEmAndamento public bool FixacaoEmAndamento
@ -21,12 +47,167 @@ namespace OperationControl.ViewModels
OnPropertyChanged(nameof(FixacaoEmAndamento)); OnPropertyChanged(nameof(FixacaoEmAndamento));
OnPropertyChanged(nameof(PodeCarregarMapa)); OnPropertyChanged(nameof(PodeCarregarMapa));
OnPropertyChanged(nameof(PodeFixarBase)); OnPropertyChanged(nameof(PodeFixarBase));
OnPropertyChanged(nameof(PodeEditarMetodoFixacao));
OnPropertyChanged(nameof(PodeEditarCoordenadasManuais));
} }
} }
} }
public bool PodeCarregarMapa => !FixacaoEmAndamento; public bool PodeCarregarMapa => !FixacaoEmAndamento;
public bool PodeFixarBase => true;
public bool PodeEditarMetodoFixacao => !FixacaoEmAndamento;
public bool PodeEditarCoordenadasManuais =>
!FixacaoEmAndamento && MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual;
public bool PodeFixarBase
{
get
{
if (FixacaoEmAndamento)
return true; // permite "Parar"
if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual)
return true;
return LatitudeManual.HasValue &&
LongitudeManual.HasValue &&
AltitudeManual.HasValue;
}
}
private MetodoFixacaoBase _metodoFixacaoSelecionado = MetodoFixacaoBase.Ntrip;
public MetodoFixacaoBase MetodoFixacaoSelecionado
{
get => _metodoFixacaoSelecionado;
set
{
if (_metodoFixacaoSelecionado != value)
{
_metodoFixacaoSelecionado = value;
OnPropertyChanged(nameof(MetodoFixacaoSelecionado));
OnPropertyChanged(nameof(ExibirCamposManuais));
OnPropertyChanged(nameof(ExibirStatusNormal));
OnPropertyChanged(nameof(ExibirProgresso));
OnPropertyChanged(nameof(PodeEditarCoordenadasManuais));
OnPropertyChanged(nameof(PodeFixarBase));
OnPropertyChanged(nameof(TextoBotaoFixarBase));
if (!FixacaoEmAndamento)
{
StatusTexto = _metodoFixacaoSelecionado switch
{
MetodoFixacaoBase.Ntrip =>
"Método selecionado: NTRIP. A base será fixada via correção RTK pela rede.",
MetodoFixacaoBase.SurveyIn =>
"Método selecionado: Survey-In. A base calculará sua posição média localmente.",
MetodoFixacaoBase.Manual =>
"Método selecionado: Manual. Informe latitude, longitude e altitude conhecidas da base.",
_ =>
"Pronto para fixar a posição da base."
};
}
}
}
}
public bool ExibirCamposManuais => MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual;
public bool ExibirStatusNormal => MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual;
public bool ExibirProgresso => MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual;
private double? _latitudeManual;
public double? LatitudeManual
{
get => _latitudeManual;
private set
{
if (_latitudeManual != value)
{
_latitudeManual = value;
OnPropertyChanged(nameof(LatitudeManual));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private double? _longitudeManual;
public double? LongitudeManual
{
get => _longitudeManual;
private set
{
if (_longitudeManual != value)
{
_longitudeManual = value;
OnPropertyChanged(nameof(LongitudeManual));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private double? _altitudeManual;
public double? AltitudeManual
{
get => _altitudeManual;
private set
{
if (_altitudeManual != value)
{
_altitudeManual = value;
OnPropertyChanged(nameof(AltitudeManual));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private string _latitudeManualTexto = string.Empty;
public string LatitudeManualTexto
{
get => _latitudeManualTexto;
set
{
if (_latitudeManualTexto != value)
{
_latitudeManualTexto = value;
LatitudeManual = TryParseDouble(value);
OnPropertyChanged(nameof(LatitudeManualTexto));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private string _longitudeManualTexto = string.Empty;
public string LongitudeManualTexto
{
get => _longitudeManualTexto;
set
{
if (_longitudeManualTexto != value)
{
_longitudeManualTexto = value;
LongitudeManual = TryParseDouble(value);
OnPropertyChanged(nameof(LongitudeManualTexto));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private string _altitudeManualTexto = string.Empty;
public string AltitudeManualTexto
{
get => _altitudeManualTexto;
set
{
if (_altitudeManualTexto != value)
{
_altitudeManualTexto = value;
AltitudeManual = TryParseDouble(value);
OnPropertyChanged(nameof(AltitudeManualTexto));
OnPropertyChanged(nameof(PodeFixarBase));
}
}
}
private double _progressoFixacao; private double _progressoFixacao;
public double ProgressoFixacao public double ProgressoFixacao
@ -34,7 +215,7 @@ namespace OperationControl.ViewModels
get => _progressoFixacao; get => _progressoFixacao;
set set
{ {
if (_progressoFixacao != value) if (Math.Abs(_progressoFixacao - value) > 0.001)
{ {
_progressoFixacao = value; _progressoFixacao = value;
OnPropertyChanged(nameof(ProgressoFixacao)); OnPropertyChanged(nameof(ProgressoFixacao));
@ -59,17 +240,16 @@ namespace OperationControl.ViewModels
} }
} }
private string _textoBotaoFixarBase = "Fixar posição da base";
public string TextoBotaoFixarBase public string TextoBotaoFixarBase
{ {
get => _textoBotaoFixarBase; get
set
{ {
if (_textoBotaoFixarBase != value) if (FixacaoEmAndamento)
{ return "Parar";
_textoBotaoFixarBase = value;
OnPropertyChanged(nameof(TextoBotaoFixarBase)); return MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual
} ? "Aplicar posição manual"
: "Fixar posição da base";
} }
} }
@ -99,7 +279,36 @@ namespace OperationControl.ViewModels
private void ExecutarFixarBase() private void ExecutarFixarBase()
{ {
FixarBaseSolicitado?.Invoke(); if (FixacaoEmAndamento)
{
FixarBaseSolicitado?.Invoke(
MetodoFixacaoSelecionado,
LatitudeManual,
LongitudeManual,
AltitudeManual);
return;
}
if (MetodoFixacaoSelecionado == MetodoFixacaoBase.Manual)
{
if (!LatitudeManual.HasValue || !LongitudeManual.HasValue || !AltitudeManual.HasValue)
{
System.Windows.MessageBox.Show(
"Preencha latitude, longitude e altitude para aplicar a posição manual da base.",
"Dados incompletos",
MessageBoxButton.OK,
MessageBoxImage.Warning);
return;
}
StatusTexto = "Pronto para aplicar a posição manual da base.";
}
FixarBaseSolicitado?.Invoke(
MetodoFixacaoSelecionado,
LatitudeManual,
LongitudeManual,
AltitudeManual);
} }
public void AtualizarProgresso(double progresso, string status) public void AtualizarProgresso(double progresso, string status)
@ -111,38 +320,80 @@ namespace OperationControl.ViewModels
public void IniciarFixacao() public void IniciarFixacao()
{ {
FixacaoEmAndamento = true; FixacaoEmAndamento = true;
TextoBotaoFixarBase = "Parar"; OnPropertyChanged(nameof(TextoBotaoFixarBase));
ProgressoFixacao = 0; ProgressoFixacao = 0;
StatusTexto = "Iniciando fixação da posição da base...";
StatusTexto = MetodoFixacaoSelecionado switch
{
MetodoFixacaoBase.Ntrip => "Iniciando fixação da base via NTRIP...",
MetodoFixacaoBase.SurveyIn => "Iniciando Survey-In da base...",
MetodoFixacaoBase.Manual => "Aplicando posição manual da base...",
_ => "Iniciando fixação da posição da base..."
};
} }
public void FinalizarFixacao(bool sucesso, string? mensagem = null) public void FinalizarFixacao(bool sucesso, string? mensagem = null)
{ {
FixacaoEmAndamento = false; FixacaoEmAndamento = false;
TextoBotaoFixarBase = "Fixar posição da base"; OnPropertyChanged(nameof(TextoBotaoFixarBase));
ProgressoFixacao = sucesso ? 100 : ProgressoFixacao;
if (MetodoFixacaoSelecionado != MetodoFixacaoBase.Manual)
ProgressoFixacao = sucesso ? 100 : ProgressoFixacao;
if (!string.IsNullOrWhiteSpace(mensagem)) if (!string.IsNullOrWhiteSpace(mensagem))
{
StatusTexto = mensagem; StatusTexto = mensagem;
}
else else
{
StatusTexto = sucesso StatusTexto = sucesso
? "Fixação da base concluída com sucesso." ? "Fixação da base concluída com sucesso."
: "Fixação da base encerrada."; : "Fixação da base encerrada.";
}
} }
public void CancelarFixacao(string? mensagem = null) public void CancelarFixacao(string? mensagem = null)
{ {
FixacaoEmAndamento = false; FixacaoEmAndamento = false;
TextoBotaoFixarBase = "Fixar posição da base"; OnPropertyChanged(nameof(TextoBotaoFixarBase));
StatusTexto = mensagem ?? "Fixação da base cancelada."; StatusTexto = mensagem ?? "Fixação da base cancelada.";
} }
public event PropertyChangedEventHandler? PropertyChanged; public void LimparCamposManuais()
{
LatitudeManualTexto = string.Empty;
LongitudeManualTexto = string.Empty;
AltitudeManualTexto = string.Empty;
LatitudeManual = null;
LongitudeManual = null;
AltitudeManual = null;
}
private double? TryParseDouble(string? texto)
{
if (string.IsNullOrWhiteSpace(texto))
return null;
texto = texto.Trim().Replace(",", ".");
if (double.TryParse(
texto,
NumberStyles.Any,
CultureInfo.InvariantCulture,
out var valor))
{
return valor;
}
return null;
}
private void OnPropertyChanged(string nome) private void OnPropertyChanged(string nome)
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
System.Windows.Input.CommandManager.InvalidateRequerySuggested(); CommandManager.InvalidateRequerySuggested();
} }
} }
} }

View File

@ -19,10 +19,10 @@ namespace OperationControl.ViewModels
private readonly PreparacaoMapaView _viewPreparacaoMapa; private readonly PreparacaoMapaView _viewPreparacaoMapa;
public readonly PreparacaoMapaTopView _viewPreparacaoMapaTop; public readonly PreparacaoMapaTopView _viewPreparacaoMapaTop;
private readonly PreparacaoMapaBottomView _viewPreparacaoMapaBottom; public readonly PreparacaoMapaBottomView _viewPreparacaoMapaBottom;
private readonly OperacaoTopView _viewOperacaoTop; private readonly OperacaoTopView _viewOperacaoTop;
private readonly OperacaoCenterView _viewOperacaoCenter; public readonly OperacaoCenterView _viewOperacaoCenter;
public readonly OperacaoLeftView _viewOperacaoLeft; public readonly OperacaoLeftView _viewOperacaoLeft;
public readonly OperacaoRightView _viewOperacaoRight; public readonly OperacaoRightView _viewOperacaoRight;
public readonly OperacaoBottomView _viewOperacaoBottom; public readonly OperacaoBottomView _viewOperacaoBottom;
@ -638,6 +638,7 @@ namespace OperationControl.ViewModels
{ {
_viewOperacaoRight?.areaParametrizacao?._vm?.AtualizarParametros(rover); _viewOperacaoRight?.areaParametrizacao?._vm?.AtualizarParametros(rover);
AtualizarDadosMapa(rover); AtualizarDadosMapa(rover);
AtualizarDadosTela(rover);
} }
public void AtualizarDadosMapa(OperacaoParametrosModel? dados) public void AtualizarDadosMapa(OperacaoParametrosModel? dados)
@ -682,15 +683,15 @@ namespace OperationControl.ViewModels
} }
} }
private async void OnFixarBaseSolicitado() private async void OnFixarBaseSolicitado(MetodoFixacaoBase metodoFix, double? lat, double? lon, double? alt)
{ {
try try
{ {
if (!Variaveis.GpsService.BaseFix.FixLiberado) if (!(Variaveis.GpsService.BaseFix?.FixLiberado ?? false))
{ {
bool fixar = false; bool fixar = false;
if (Variaveis.GpsService.BaseFix.PosicaoBaseFixada) if (Variaveis.GpsService.BaseFix?.PosicaoBaseFixada ?? false)
{ {
var res = System.Windows.MessageBox.Show( var res = System.Windows.MessageBox.Show(
"Mudar posição da base?", "Mudar posição da base?",
@ -709,7 +710,7 @@ namespace OperationControl.ViewModels
if (fixar) if (fixar)
{ {
_viewPreparacaoMapaBottom?._vm.IniciarFixacao(); _viewPreparacaoMapaBottom?._vm.IniciarFixacao();
await Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo(true)); await Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo(true, metodoFix, lat, lon, alt));
} }
} }
else else
@ -849,8 +850,7 @@ namespace OperationControl.ViewModels
}); });
// DIAGNOSTICO // DIAGNOSTICO
_viewOperacaoCenter?.Diagnostico?._vm?.AtualizarDados(rover); AtualizarDadosDiagnostico(rover);
_viewOperacaoCenter?.Diagnostico?.AtualizarGraficos();
// PULVERIZADOR // PULVERIZADOR
var bomba = obj.Atuador?.Bombas?.FirstOrDefault(); var bomba = obj.Atuador?.Bombas?.FirstOrDefault();
@ -915,6 +915,12 @@ namespace OperationControl.ViewModels
_viewOperacaoCenter?.Diagnostico?._vm?.AbrirModuloPorAlerta(alerta.Modulo, alerta.Mod_ID); _viewOperacaoCenter?.Diagnostico?._vm?.AbrirModuloPorAlerta(alerta.Modulo, alerta.Mod_ID);
} }
public void AtualizarDadosDiagnostico(OperacaoParametrosModel? rover)
{
_viewOperacaoCenter?.Diagnostico?._vm?.AtualizarDados(rover);
_viewOperacaoCenter?.Diagnostico?.AtualizarGraficos();
}
public void AdicionarAlerta(string roverId, AgroBase.Models.Enums.T_Code modulo, SeveridadeAlerta severidade, string mensagem, string modId = null) public void AdicionarAlerta(string roverId, AgroBase.Models.Enums.T_Code modulo, SeveridadeAlerta severidade, string mensagem, string modId = null)
{ {
_viewOperacaoBottom?._vm?.AdicionarAlerta(roverId, modulo, severidade, mensagem, modId); _viewOperacaoBottom?._vm?.AdicionarAlerta(roverId, modulo, severidade, mensagem, modId);
@ -997,10 +1003,146 @@ namespace OperationControl.ViewModels
return; return;
} }
if (VariaveisControleOperacao.RoverEmFoco == null) var rover = VariaveisControleOperacao.RoverEmFoco;
if (rover == null)
return; return;
var rover = VariaveisControleOperacao.RoverEmFoco; if (parametros?.Controle?.MovimentoAutomatico ?? false)
{
var _mov = parametros?.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == T_Code.Mov);
if (_mov == null)
{
_mov = new AgroBase.Models.OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Mov,
Utilizar = true,
Mandatorio = true,
ComponentesEmUso = new Dictionary<string, (bool, bool)>()
{
{ "ET", (true, true) },
{ "DT", (true, true) },
{ "EF", (true, true) },
{ "DF", (true, true) },
}
};
}
else
{
foreach (var key in _mov.ComponentesEmUso?.Keys.ToList() ?? new List<string>())
{
_mov.ComponentesEmUso[key] = (true, true);
}
_mov.Utilizar = true;
_mov.Mandatorio = true;
}
}
if (parametros?.Controle?.DirecionalAutomatico ?? false)
{
var _dir = parametros?.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == T_Code.Dir);
if (_dir == null)
{
_dir = new AgroBase.Models.OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Dir,
Utilizar = true,
Mandatorio = true,
ComponentesEmUso = new Dictionary<string, (bool, bool)>()
{
{ "ET", (true, true) },
{ "DT", (true, true) },
{ "EF", (true, true) },
{ "DF", (true, true) },
}
};
}
else
{
foreach (var key in _dir.ComponentesEmUso?.Keys.ToList() ?? new List<string>())
{
_dir.ComponentesEmUso[key] = (true, true);
}
_dir.Utilizar = true;
_dir.Mandatorio = true;
}
}
if (parametros?.Controle?.PulverizadorAutomatico ?? false)
{
var _atu = parametros?.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == T_Code.Atu);
if (_atu == null)
{
_atu = new AgroBase.Models.OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Atu,
Utilizar = true,
Mandatorio = true,
ComponentesEmUso = new Dictionary<string, (bool, bool)>()
{
{ "MASRS", (true, true) },
{ "FLXLN", (true, true) },
{ "PRSLN", (true, true) },
{ "BOMBA", (true, true) },
{ "B01", (true, true) },
{ "B02", (true, true) },
{ "B03", (true, true) },
{ "B04", (true, true) },
{ "B05", (true, true) },
{ "B06", (true, true) },
{ "B07", (true, true) },
}
};
}
else
{
foreach (var key in _atu.ComponentesEmUso?.Keys.ToList() ?? new List<string>())
{
_atu.ComponentesEmUso[key] = (true, true);
}
_atu.Utilizar = true;
_atu.Mandatorio = true;
}
}
if (parametros?.Controle?.ImuParadaPorInclinacao ?? false)
{
var _imu = parametros.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == T_Code.Imu);
if (_imu == null)
{
_imu = new AgroBase.Models.OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Imu,
Utilizar = true,
Mandatorio = true,
};
parametros?.ModulosMandatorios?.Add(_imu);
}
else
{
_imu.Utilizar = true;
_imu.Mandatorio = true;
}
}
if (parametros?.Controle?.OakParadaPorObstaculo ?? false)
{
var _snr = parametros.ModulosMandatorios?.FirstOrDefault(x => x.Dispositivo == T_Code.Snr);
if (_snr == null)
{
_snr = new AgroBase.Models.OperacaoModulosMandatoriosModel()
{
Dispositivo = T_Code.Snr,
Utilizar = true,
Mandatorio = true,
};
parametros?.ModulosMandatorios?.Add(_snr);
}
else
{
_snr.Utilizar = true;
_snr.Mandatorio = true;
}
}
var novosParametros = new OperacaoParametrosModel() var novosParametros = new OperacaoParametrosModel()
{ {
@ -1021,22 +1163,24 @@ namespace OperationControl.ViewModels
VariaveisControleOperacao.EnviarParametrosOperacao(novosParametros); VariaveisControleOperacao.EnviarParametrosOperacao(novosParametros);
//VariaveisControleOperacao.RoverEmFoco.Modo = novosParametros.Modo; rover.Modo = novosParametros.Modo;
//VariaveisControleOperacao.RoverEmFoco.Descricao = novosParametros.Descricao; rover.Descricao = novosParametros.Descricao;
//VariaveisControleOperacao.RoverEmFoco.QtdCamerasSolo = novosParametros.QtdCamerasSolo; rover.QtdCamerasSolo = novosParametros.QtdCamerasSolo;
//VariaveisControleOperacao.RoverEmFoco.QtdBicos = novosParametros.QtdBicos; rover.QtdBicos = novosParametros.QtdBicos;
//VariaveisControleOperacao.RoverEmFoco.CapacidadeReservatorio = novosParametros.CapacidadeReservatorio; rover.CapacidadeReservatorio = novosParametros.CapacidadeReservatorio;
//VariaveisControleOperacao.RoverEmFoco.Controle = novosParametros.Controle; rover.Controle = novosParametros.Controle;
//VariaveisControleOperacao.RoverEmFoco.ModulosMandatorios = novosParametros.ModulosMandatorios; rover.ModulosMandatorios = novosParametros.ModulosMandatorios;
//VariaveisControleOperacao.RoverEmFoco.ParametrosMandatorios = novosParametros.ParametrosMandatorios; rover.ParametrosMandatorios = novosParametros.ParametrosMandatorios;
//VariaveisControleOperacao.RoverEmFoco.RuasPercorrer = novosParametros.RuasPercorrer; rover.RuasPercorrer = novosParametros.RuasPercorrer;
//VariaveisControleOperacao.RoverEmFoco.Mapa = novosParametros.Mapa; rover.Mapa = novosParametros.Mapa;
//Task.Run(async () => AtualizarDadosDiagnostico(rover);
//{
// await Task.Delay(1000); Task.Run(async () =>
// _viewOperacaoRight?._vm?.SelecionarSecao(SecaoRightBar.Diagnostico); {
//}); await Task.Delay(500);
_viewOperacaoRight?._vm?.SelecionarSecao(SecaoRightBar.Diagnostico);
});
} }

View File

@ -2,27 +2,43 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OperationControl.Views" mc:Ignorable="d">
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"> <UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
<Style x:Key="BottomLabelStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="#AAAAAA"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,6,0"/>
</Style>
<Style x:Key="BottomTextBoxStyle" TargetType="TextBox">
<Setter Property="Height" Value="30"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="8,2"/>
<Setter Property="Margin" Value="0,0,10,0"/>
<Setter Property="MinWidth" Value="110"/>
</Style>
</UserControl.Resources>
<Grid Background="#181818" Margin="0"> <Grid Background="#181818" Margin="0">
<!-- Duas linhas -->
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Linha 1 --> <!-- LINHA 1 -->
<Grid Grid.Row="0"> <Grid Grid.Row="0">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="240"/>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="320"/> <ColumnDefinition Width="12"/>
<ColumnDefinition Width="70"/>
<!-- Área dinâmica -->
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
@ -35,45 +51,142 @@
Command="{Binding CarregarMapaCommand}" Command="{Binding CarregarMapaCommand}"
IsEnabled="{Binding PodeCarregarMapa}"/> IsEnabled="{Binding PodeCarregarMapa}"/>
<!-- Botão fixar base --> <!-- Botão fixar -->
<Button Grid.Column="1" <Button Grid.Column="2"
Content="{Binding TextoBotaoFixarBase}" Content="{Binding TextoBotaoFixarBase}"
Margin="8,12,12,6" Margin="8,12,12,6"
Padding="18,10" Padding="18,10"
MinWidth="180" MinWidth="180"
Command="{Binding FixarBaseCommand}"/> Command="{Binding FixarBaseCommand}"
IsEnabled="{Binding PodeFixarBase}"/>
<!-- Barra de progresso --> <!-- Combo método -->
<ProgressBar Grid.Column="2" <ComboBox Grid.Column="1"
Margin="12,20,8,8" Margin="8,12,8,6"
Height="22" VerticalContentAlignment="Center"
Minimum="0" ItemsSource="{Binding MetodosFixacaoDisponiveis}"
Maximum="100" DisplayMemberPath="Nome"
Value="{Binding ProgressoFixacao}"/> SelectedValuePath="Valor"
SelectedValue="{Binding MetodoFixacaoSelecionado, Mode=TwoWay}"
IsEnabled="{Binding PodeEditarMetodoFixacao}"/>
<!-- Texto % --> <!-- ÁREA DINÂMICA -->
<TextBlock Grid.Column="3" <Grid Grid.Column="4" Margin="0,12,12,6">
Text="{Binding ProgressoFixacaoTexto}"
VerticalAlignment="Center" <!-- Progresso normal -->
HorizontalAlignment="Center" <Grid Visibility="{Binding ExibirProgresso, Converter={StaticResource BoolToVisibilityConverter}}">
Foreground="White" <Grid.ColumnDefinitions>
FontWeight="SemiBold" <ColumnDefinition Width="320"/>
FontSize="14" <ColumnDefinition Width="70"/>
Margin="0,0,8,0"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ProgressBar Grid.Column="0"
Margin="0,8,8,0"
Height="22"
Minimum="0"
Maximum="100"
Value="{Binding ProgressoFixacao}"/>
<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 -->
<Grid Visibility="{Binding ExibirCamposManuais, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="125"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="125"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="110"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<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}"/>
<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}"/>
<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}"/>
</Grid>
</Grid>
</Grid> </Grid>
<!-- Linha 2 : Status --> <!-- LINHA 2 -->
<Border Grid.Row="1" <Grid Grid.Row="1" Margin="12,4,12,10">
Margin="12,4,12,10" <Grid.RowDefinitions>
Padding="8" <RowDefinition Height="Auto"/>
Background="#222" <RowDefinition Height="Auto"/>
CornerRadius="6"> </Grid.RowDefinitions>
<StackPanel> <Border Grid.Row="0"
<TextBlock Text="Status da operação" Foreground="#AAAAAA" FontSize="11"/> Padding="8"
<TextBlock Text="{Binding StatusTexto}" Foreground="White" FontSize="14" TextWrapping="Wrap"/> Background="#222"
</StackPanel> CornerRadius="6">
</Border>
<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>
<!-- 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> </Grid>
</UserControl> </UserControl>

View File

@ -1,4 +1,5 @@
using OperationControl.ViewModels; using OperationControl.ViewModels;
using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
@ -15,11 +16,26 @@ namespace OperationControl.Windows
InitializeComponent(); InitializeComponent();
_vm = new DockWindowViewModel(); _vm = new DockWindowViewModel();
DataContext = _vm; DataContext = _vm;
Closing += DockWindow_Closing;
}
private void DockWindow_Closing(object? sender, CancelEventArgs e)
{
if (System.Windows.MessageBox.Show("Tem certeza que deseja sair?", "Encerrar a aplicação", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
{
e.Cancel = true;
return;
}
_vm?._viewOperacaoCenter?.Monitoramento?.PararStreamCameraFrontal(true);
_vm?._viewOperacaoCenter?.Monitoramento?.PararStreamCameraErvas(true);
} }
private void ToastAlerta_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) private void ToastAlerta_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{ {
_vm.BottomVM?.ClicarNoToast(); _vm.BottomVM?.ClicarNoToast();
} }
} }
} }

View File

@ -1724,7 +1724,7 @@ namespace OperationControl.Windows
if (fixar) if (fixar)
{ {
btnGNSS_FixarBase.Content = "Parar"; btnGNSS_FixarBase.Content = "Parar";
Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo(true)); Task.Run(async () => await Variaveis.GpsService.ConfigurarModulo(true, ViewModels.MetodoFixacaoBase.Ntrip));
} }
} }
else else