Separação de telas, criado controle manual

This commit is contained in:
Diego Freitas 2026-03-16 21:43:15 -03:00
parent 286e5a62c4
commit 69cef2859b
30 changed files with 1272 additions and 414 deletions

View File

@ -977,6 +977,7 @@ namespace AgroBase.Models
Variaveis.OperacaoEmAndamento.Parametros.RoverId = VariaveisEquipamento.Parametros.serial_number;
Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura = new OperacaoParametrosDadosModel();
Variaveis.OperacaoEmAndamento.Sensoriamento.AtualizarDados();
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.ForEach(m => m.ComponentesEmUso = Variaveis.OperacaoEmAndamento.PreencherComponentesEmUso(m.Dispositivo));
Variaveis.OperacaoEmAndamento.DefinirComponentesEmUso();
Variaveis.OperacaoEmAndamento.Descricao = Parametros.Descricao;
@ -1109,6 +1110,7 @@ namespace AgroBase.Models
Console.WriteLine("Nenhuma calibragem foi iniciada.");
_Controle.TipoMovimento = tipoControle;
Variaveis.OperacaoEmAndamento.Calibrando = false;
Variaveis.OperacaoEmAndamento.Pausa = false;
return;
}

View File

@ -290,6 +290,7 @@ namespace AgroBase.Models
else if (disp == T_Code.Mov)
{
controle.Controle.PercentualVelocidadeSP = msg.P1 / 100.0;
controle.Controle.EmFreio = msg.P2 == 1;
}
}

View File

@ -354,7 +354,7 @@ namespace OperationControl.Controls
if (_lastMovKey != mov)
{
//VariaveisControleOperacao.EnviarComandoMovimentacao(mov, Convert.ToInt32(SpeedControl));
VariaveisControleOperacao.EnviarComandoMovimentacaoUDP(mov, Convert.ToInt32(SpeedControl));
VariaveisControleOperacao.EnviarComandoMovimentacaoUDP(mov, Convert.ToInt32(SpeedControl), false);
_lastMovKey = mov;
}
}

View File

@ -9,6 +9,7 @@ namespace OperationControl.Models
public class AppShell
{
public static readonly bool Mock = true;
private static readonly bool AddRover = false;
private readonly System.Timers.Timer tmrComunicacao = new(1000) { AutoReset = true };
private int tmrComunicacaoTicks = 0;
@ -36,18 +37,21 @@ namespace OperationControl.Models
Dock = new DockWindow();
Dock.Show();
if (Mock && false)
if (Mock && AddRover)
{
Task.Run(async () =>
{
await Task.Delay(1000);
VariaveisControleOperacao.AdicionarNovoRoverNaRede("01", "192.168.1.100");
VariaveisControleOperacao.RoversNaRede.FirstOrDefault().DadosLeitura = new AgroBase.Models.Operacoes.OperacaoParametrosDadosModel()
var r = VariaveisControleOperacao.RoversNaRede.FirstOrDefault();
r.Modo = AgroBase.Models.Enums.ModoOperacao.MapaGPS;
r.Descricao = "Operacao Mockada";
r.DadosLeitura = new AgroBase.Models.Operacoes.OperacaoParametrosDadosModel()
{
StatusRover = StatusModulo.Operante,
Operacao = new AgroBase.Models.Operacoes.OperacaoParametrosDadosOperacaoModel()
{
Status = StatusOperacao.Parametrizando
Status = StatusOperacao.Parametrizando,
},
Atuador = new AgroBase.Models.Operacoes.OperacaoParametrosDadosAtuadorModel()
{
@ -118,8 +122,39 @@ namespace OperationControl.Models
VolumeVazadoML = 325
},
}
},
Controle = new AgroBase.Models.Operacoes.OperacaoParametrosDadosControleModel()
{
AlturaBarra = 50,
Angulo = 0,
PercentualVelocidadeSPKmh = 0,
TipoMovimento = TipoMovimentoDirecional.RodasDianteiras
}
};
r.Controle = new AgroBase.Models.Operacoes.OperacaoParametrosControleModel()
{
AtuAlturaAreaPulverizacao = 10,
AtuDuracaoAtuacao = 200,
AtuPercentualErvasBicoOff = 1,
AtuPercentualErvasBicoOn = 2,
AtuPercentualInicioPulverizacao = 70,
AtuPressaoLinha = 80,
DirAnguloMaximo = 30,
DirecionalAutomatico = true,
MovimentoAutomatico = true,
PulverizadorAutomatico = true,
DirTipoMovimento = TiposControladorDirecional.MPC,
DirVelocidadeMovimento = 40,
FrenagemAutomaticaAoParar = false,
ImuParadaPorInclinacao = false,
MovVelocidadeCErvasPercent = 20,
MovVelocidadeSErvasPercent = 50,
MpcHorizonte = 4,
MpcMatrizCusto = false,
OakParadaPorObstaculo = false,
RegistrarDadosPosProcessamento = false,
SonarAtivado = false
};
});
}
}

View File

@ -5,7 +5,6 @@ using OperationControl.Services;
using AgroMonitor;
using Application = System.Windows.Application;
using AgroBase.Models.Operacoes;
using OperationControl.ViewModels;
namespace OperationControl.Models
{
@ -494,7 +493,7 @@ namespace OperationControl.Models
});
}
public static void EnviarComandoMovimentacaoUDP(AgroBase.Models.Enums.Direcao direcao, double velPct)
public static void EnviarComandoMovimentacaoUDP(AgroBase.Models.Enums.Direcao direcao, double velPct, bool emfreio)
{
var key = DeParaDirecaoTecla(direcao);
@ -504,7 +503,7 @@ namespace OperationControl.Models
Flags = UdpCtrlFlags.HasKey | UdpCtrlFlags.HasPayload,
Key = key,
P1 = (short)Math.Max(short.MinValue, Math.Min(short.MaxValue, (int)Math.Round(velPct * 100.0))),
P2 = 0
P2 = (short)(emfreio ? 1 : 0)
};
//return Variaveis.UdpChannel.SendBurstAsync(0x01, msg.ToBytes(), count: 6, intervalMs: 25, requestAck: false);

View File

@ -46,10 +46,16 @@
<Compile Update="Views\ConfigConexao\ConfigConexaoView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Operacao\DiagnosticoView.xaml.cs">
<Compile Update="Views\Operacao\Monitoramento\ControleManualView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Operacao\MonitoramentoView.xaml.cs">
<Compile Update="Views\Operacao\Monitoramento\DiagnosticoView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Operacao\Monitoramento\MonitoramentoView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Operacao\Monitoramento\ResumoView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Operacao\OperacaoBottomView.xaml.cs">
@ -67,6 +73,9 @@
<Compile Update="Views\Operacao\OperacaoTopView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Operacao\Monitoramento\ParametrizacaoView.xaml.cs">
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\PreparacaoMapa\PreparacaoMapaBottomView.xaml.cs">
<SubType>Code</SubType>
</Compile>
@ -123,10 +132,16 @@
<Page Update="Views\ConfigConexao\ConfigConexaoView.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Operacao\DiagnosticoView.xaml">
<Page Update="Views\Operacao\Monitoramento\ControleManualView.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Operacao\MonitoramentoView.xaml">
<Page Update="Views\Operacao\Monitoramento\DiagnosticoView.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Operacao\Monitoramento\MonitoramentoView.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Operacao\Monitoramento\ResumoView.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Operacao\OperacaoBottomView.xaml">
@ -144,6 +159,9 @@
<Page Update="Views\Operacao\OperacaoTopView.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\Operacao\Monitoramento\ParametrizacaoView.xaml">
<SubType>Designer</SubType>
</Page>
<Page Update="Views\PreparacaoMapa\PreparacaoMapaBottomView.xaml">
<SubType>Designer</SubType>
</Page>

View File

@ -0,0 +1,361 @@
using OperationControl.Models;
using System.ComponentModel;
using System.Windows.Media;
using static AgroBase.Models.Enums;
using Brush = System.Windows.Media.Brush;
using Color = System.Windows.Media.Color;
using Key = System.Windows.Input.Key;
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
{
public class ControleManualViewModel : INotifyPropertyChanged
{
private bool _habilitado;
private double _velocidadePercentual = 40;
private double _anguloDirecional = 10;
private TipoMovimentoDirecional _tipoMovimentoSelecionado = TipoMovimentoDirecional.RodasDianteiras;
private bool _wPressionado;
private bool _aPressionado;
private bool _sPressionado;
private bool _dPressionado;
private bool _fPressionado;
private readonly HashSet<Key> _pressedKeys = new();
private Direcao _lastMovKey = Direcao.Parado;
private Direcao _lastDirKey = Direcao.Parado;
private bool _lastFreio = false;
public bool Habilitado
{
get => _habilitado;
set
{
if (_habilitado != value)
{
_habilitado = value;
OnPropertyChanged(nameof(StatusTexto));
OnPropertyChanged(nameof(TextoAjuda));
OnPropertyChanged(nameof(StatusBrush));
if (VariaveisControleOperacao.RoverEmFoco != null)
{
VariaveisControleOperacao.RoverEmFoco.Controle.MovimentoAutomatico = !value;
VariaveisControleOperacao.RoverEmFoco.Controle.DirecionalAutomatico = !value;
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
{
Controle = VariaveisControleOperacao.RoverEmFoco?.Controle
});
}
if (!value)
{
LimparTeclas();
EnviarNeutros();
}
}
}
}
public double VelocidadePercentual
{
get => _velocidadePercentual;
set
{
if (_velocidadePercentual != value)
{
_velocidadePercentual = value;
OnPropertyChanged(nameof(VelocidadePercentualTexto));
if (Habilitado)
RecalcularComandos();
}
}
}
public string VelocidadePercentualTexto => $"{VelocidadePercentual:0}%";
public double AnguloDirecional
{
get => _anguloDirecional;
set
{
if (_anguloDirecional != value)
{
_anguloDirecional = value;
OnPropertyChanged(nameof(AnguloTexto));
if (Habilitado)
RecalcularComandos();
}
}
}
public string AnguloTexto => $"{AnguloDirecional:+0;-0;0}°";
public TipoMovimentoDirecional TipoMovimentoSelecionado
{
get => _tipoMovimentoSelecionado;
set
{
if (_tipoMovimentoSelecionado != value)
{
_tipoMovimentoSelecionado = value;
if (Habilitado)
RecalcularComandos();
}
}
}
public List<TipoMovimentoDirecional> TiposMovimento { get; } =
Enum.GetValues(typeof(TipoMovimentoDirecional))
.Cast<TipoMovimentoDirecional>()
.ToList();
public bool WPressionado
{
get => _wPressionado;
private set
{
if (_wPressionado != value)
{
_wPressionado = value;
OnPropertyChanged(nameof(TeclaWBackground));
OnPropertyChanged(nameof(TeclaWBorder));
OnPropertyChanged(nameof(MovimentoAtualTexto));
}
}
}
public bool APressionado
{
get => _aPressionado;
private set
{
if (_aPressionado != value)
{
_aPressionado = value;
OnPropertyChanged(nameof(TeclaABackground));
OnPropertyChanged(nameof(TeclaABorder));
OnPropertyChanged(nameof(DirecaoAtualTexto));
}
}
}
public bool SPressionado
{
get => _sPressionado;
private set
{
if (_sPressionado != value)
{
_sPressionado = value;
OnPropertyChanged(nameof(TeclaSBackground));
OnPropertyChanged(nameof(TeclaSBorder));
OnPropertyChanged(nameof(MovimentoAtualTexto));
}
}
}
public bool DPressionado
{
get => _dPressionado;
private set
{
if (_dPressionado != value)
{
_dPressionado = value;
OnPropertyChanged(nameof(TeclaDBackground));
OnPropertyChanged(nameof(TeclaDBorder));
OnPropertyChanged(nameof(DirecaoAtualTexto));
}
}
}
public bool FPressionado
{
get => _fPressionado;
private set
{
if (_fPressionado != value)
{
_fPressionado = value;
OnPropertyChanged(nameof(TeclaFBackground));
OnPropertyChanged(nameof(TeclaFBorder));
OnPropertyChanged(nameof(FreioAtivoTexto));
OnPropertyChanged(nameof(FreioCardBackground));
OnPropertyChanged(nameof(FreioCardBorder));
OnPropertyChanged(nameof(MovimentoAtualTexto));
}
}
}
public Brush TeclaWBackground => WPressionado ? BrushFrom("#1D4ED8") : BrushFrom("#2D2D2D");
public Brush TeclaWBorder => WPressionado ? BrushFrom("#60A5FA") : BrushFrom("#555555");
public Brush TeclaABackground => APressionado ? BrushFrom("#1D4ED8") : BrushFrom("#2D2D2D");
public Brush TeclaABorder => APressionado ? BrushFrom("#60A5FA") : BrushFrom("#555555");
public Brush TeclaSBackground => SPressionado ? BrushFrom("#B45309") : BrushFrom("#2D2D2D");
public Brush TeclaSBorder => SPressionado ? BrushFrom("#F59E0B") : BrushFrom("#555555");
public Brush TeclaDBackground => DPressionado ? BrushFrom("#1D4ED8") : BrushFrom("#2D2D2D");
public Brush TeclaDBorder => DPressionado ? BrushFrom("#60A5FA") : BrushFrom("#555555");
public Brush TeclaFBackground => FPressionado ? BrushFrom("#7A2323") : BrushFrom("#2D2D2D");
public Brush TeclaFBorder => FPressionado ? BrushFrom("#D35B5B") : BrushFrom("#555555");
public Brush FreioCardBackground => FPressionado ? BrushFrom("#7A2323") : BrushFrom("#2B2B2B");
public Brush FreioCardBorder => FPressionado ? BrushFrom("#D35B5B") : BrushFrom("#555555");
public string MovimentoAtualTexto
{
get
{
if (FPressionado)
return "Freado";
if (WPressionado && !SPressionado) return "Frente";
if (SPressionado && !WPressionado) return "Ré";
if (WPressionado && SPressionado) return "Conflito";
return "Parado";
}
}
public string DirecaoAtualTexto
{
get
{
if (APressionado && !DPressionado) return "Esquerda";
if (DPressionado && !APressionado) return "Direita";
if (APressionado && DPressionado) return "Conflito";
return "Centralizado";
}
}
public string FreioAtivoTexto => FPressionado ? "Freio Ativo" : "Freio Inativo";
public string StatusTexto => !Habilitado ? "INATIVO" : "PRONTO";
public string TextoAjuda => !Habilitado
? "Habilite o controle por teclado para começar."
: "Clique na tela de operação e use W, A, S, D e F para controlar o rover.";
public Brush StatusBrush => !Habilitado ? BrushFrom("#6B7280") : BrushFrom("#22C55E");
public void HandleKeyDown(Key key)
{
if (!Habilitado)
return;
if (_pressedKeys.Contains(key))
return;
_pressedKeys.Add(key);
AtualizarEstadoTeclas();
RecalcularComandos();
}
public void HandleKeyUp(Key key)
{
if (_pressedKeys.Remove(key))
{
AtualizarEstadoTeclas();
RecalcularComandos();
}
}
public void LimparTeclas()
{
_pressedKeys.Clear();
AtualizarEstadoTeclas();
}
private void AtualizarEstadoTeclas()
{
WPressionado = _pressedKeys.Contains(Key.W) || _pressedKeys.Contains(Key.Up);
APressionado = _pressedKeys.Contains(Key.A) || _pressedKeys.Contains(Key.Left);
SPressionado = _pressedKeys.Contains(Key.S) || _pressedKeys.Contains(Key.Down);
DPressionado = _pressedKeys.Contains(Key.D) || _pressedKeys.Contains(Key.Right);
FPressionado = _pressedKeys.Contains(Key.F) || _pressedKeys.Contains(Key.Space);
}
private void RecalcularComandos()
{
var dir = ObterDirecaoDirecional();
var mov = ObterDirecaoMovimentacao();
var freio = FPressionado;
if (_lastDirKey != dir)
{
VariaveisControleOperacao.EnviarComandoDirecionalUDP(dir, Convert.ToInt32(AnguloDirecional), TipoMovimentoSelecionado);
_lastDirKey = dir;
}
if (_lastMovKey != mov || _lastFreio != freio)
{
VariaveisControleOperacao.EnviarComandoMovimentacaoUDP(mov, Convert.ToInt32(VelocidadePercentual), freio);
_lastMovKey = mov;
_lastFreio = freio;
}
}
private Direcao ObterDirecaoDirecional()
{
if (APressionado && !DPressionado)
return Direcao.Esquerda;
if (DPressionado && !APressionado)
return Direcao.Direita;
return Direcao.Parado;
}
private Direcao ObterDirecaoMovimentacao()
{
if (FPressionado)
return Direcao.Parado;
if (WPressionado && !SPressionado)
return Direcao.Cima;
if (SPressionado && !WPressionado)
return Direcao.Baixo;
return Direcao.Parado;
}
private void EnviarNeutros()
{
if (_lastDirKey != Direcao.Parado)
{
VariaveisControleOperacao.EnviarComandoDirecionalUDP(Direcao.Parado, Convert.ToInt32(AnguloDirecional), TipoMovimentoSelecionado);
_lastDirKey = Direcao.Parado;
}
if (_lastMovKey != Direcao.Parado || _lastFreio)
{
VariaveisControleOperacao.EnviarComandoMovimentacaoUDP(Direcao.Parado, 0, false);
_lastMovKey = Direcao.Parado;
_lastFreio = false;
}
}
private Brush BrushFrom(string hex)
{
return new SolidColorBrush((Color)System.Windows.Media.ColorConverter.ConvertFromString(hex));
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string nome)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
}
}
}

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento.Diagnostico
{
public class DiagnosticoGraficoSerieViewModel : NotifyBase
{

View File

@ -5,7 +5,7 @@ using static AgroBase.Models.Enums;
using Brush = System.Windows.Media.Brush;
using Brushes = System.Windows.Media.Brushes;
namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento.Diagnostico
{
public class DiagnosticoModuloItemViewModel : NotifyBase
{

View File

@ -7,7 +7,7 @@ using System.Windows.Input;
using OperationControl.Helpers;
using static AgroBase.Services.CoolerControlService;
namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento.Diagnostico
{
public class DiagnosticoOpcoesViewModel : NotifyBase
{
@ -187,7 +187,7 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
set
{
if (SetProperty(ref _gpsLeverArmLateral, value))
GpsLeverArmLateralTexto = $"{(value * 10.0):00} cm";
GpsLeverArmLateralTexto = $"{value * 10.0:00} cm";
}
}
@ -201,7 +201,7 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
set
{
if (SetProperty(ref _gpsLeverArmFrontal, value))
GpsLeverArmFrontalTexto = $"{(value * 10.0):00} cm";
GpsLeverArmFrontalTexto = $"{value * 10.0:00} cm";
}
}
@ -550,8 +550,8 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
{
var bico = rover?.Atuador?.Bicos?.FirstOrDefault(x => x.ID == _itemAtual.LabelModulo);
BicoTitulo = $"Bico {_itemAtual.LabelModulo} - Testes";
TxtBicoComando = (bico?.ComandoEstado ?? false) ? "Ligado" : "Desligado";
TxtBicoStatusReal = (bico?.LeituraEstado ?? false) ? "Ligado" : "Desligado";
TxtBicoComando = bico?.ComandoEstado ?? false ? "Ligado" : "Desligado";
TxtBicoStatusReal = bico?.LeituraEstado ?? false ? "Ligado" : "Desligado";
TxtBicoTempoLigado = $"{bico?.TempoAtuado ?? 0:0.##} ms";
TxtBicoVazao = $"{bico?.VazaoInstantaneaMLs ?? 0:0.##} mL/s";
TxtBicoPressao = $"{rover?.Atuador?.PressaoLinhaPsi ?? 0:0.##} psi";
@ -567,8 +567,8 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
{
var bomba = rover?.Atuador?.Bombas?.FirstOrDefault(x => x.ID == _itemAtual.LabelModulo);
BombaTitulo = $"Bomba {_itemAtual.LabelModulo} - Testes";
TxtBombaComando = (bomba?.ComandoEstado ?? false) ? "Ligado" : "Desligado";
TxtBombaStatusReal = (bomba?.LeituraEstado ?? false) ? "Ligado" : "Desligado";
TxtBombaComando = bomba?.ComandoEstado ?? false ? "Ligado" : "Desligado";
TxtBombaStatusReal = bomba?.LeituraEstado ?? false ? "Ligado" : "Desligado";
TxtBombaPressaoLinha = $"{rover?.Atuador?.PressaoLinhaPsi ?? 0:0.##} psi";
TxtBombaPotencia = $"{bomba?.Potencia ?? 0:0.#} %";
if (clicado)
@ -614,8 +614,8 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
TxtTrajetoriaDistBateria = $"{dados?.DistanciaSeguraBateria_m ?? 0:0.00} m";
TxtTrajetoriaDistPulverizador = $"{dados?.DistanciaSeguraHerbicida_m ?? 0:0.00} m";
TxtTrajetoriaStatus = $"{dados?.Status ?? AgroBase.Models.AutonomiaCorredorStatus.Desconhecido}";
TxtTrajetoriaBatOk = (dados?.BateriaSuficiente ?? false) ? "Sim" : "Não";
TxtTrajetoriaHerbOk = (dados?.HerbicidaSuficiente ?? false) ? "Sim" : "Não";
TxtTrajetoriaBatOk = dados?.BateriaSuficiente ?? false ? "Sim" : "Não";
TxtTrajetoriaHerbOk = dados?.HerbicidaSuficiente ?? false ? "Sim" : "Não";
TrajetoriaPodeConfirmar = !(dados?.Liberado ?? false);
if (clicado)
{
@ -628,8 +628,8 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
{
var rele = rover?.Sensoriamento?.Reles?.FirstOrDefault(x => x.ID == _itemAtual.LabelModulo);
ReleTitulo = $"Relé {_itemAtual.LabelModulo} - Testes";
TxtReleComando = (rele?.ComandoEstado ?? false) ? "Ligado" : "Desligado";
TxtReleStatusReal = (rele?.LeituraEstado ?? false) ? "Ligado" : "Desligado";
TxtReleComando = rele?.ComandoEstado ?? false ? "Ligado" : "Desligado";
TxtReleStatusReal = rele?.LeituraEstado ?? false ? "Ligado" : "Desligado";
}
private void PreencherServoSensoriamento(OperacaoParametrosDadosModel rover, bool clicado)
@ -637,7 +637,7 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
var servo = rover?.Sensoriamento?.Servos?.FirstOrDefault(x => x.ID == _itemAtual.LabelModulo);
TxtServoComando = $"{servo?.ComandoAngulo ?? 0}°";
TxtServoLeitura = $"{servo?.LeituraAngulo ?? 0}°";
TxtServoIncremental = (servo?.Incremental ?? false) ? "Incremental" : "Decremental";
TxtServoIncremental = servo?.Incremental ?? false ? "Incremental" : "Decremental";
if (clicado)
{
ServoAngulo = servo?.ComandoAngulo ?? 0;
@ -649,7 +649,7 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
var servo = rover?.Atuador?.Servos?.FirstOrDefault(x => x.ID == _itemAtual.LabelModulo);
TxtServoComando = $"{servo?.ComandoAngulo ?? 0}°";
TxtServoLeitura = $"{servo?.LeituraAngulo ?? 0}°";
TxtServoIncremental = (servo?.Incremental ?? false) ? "Incremental" : "Decremental";
TxtServoIncremental = servo?.Incremental ?? false ? "Incremental" : "Decremental";
if (clicado)
{
ServoAngulo = servo?.ComandoAngulo ?? 0;

View File

@ -7,7 +7,7 @@ using AgroBase.Models.Operacoes;
using OperationControl.Models;
using Newtonsoft.Json.Linq;
namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento.Diagnostico
{
public class DiagnosticoViewModel : NotifyBase
{
@ -595,7 +595,7 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
mod.ComponentesEmUso[label] = (MandatorioSelecionado, EmUsoSelecionado);
}
VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel()
VariaveisControleOperacao.EnviarParametrosOperacao(new OperacaoParametrosModel()
{
ModulosMandatorios = rover.ModulosMandatorios,
});
@ -697,13 +697,13 @@ namespace OperationControl.ViewModels.Views.Operacao.Diagnostico
{
case S_Code.sBIC:
var bico = rover.Atuador?.Bicos?.FirstOrDefault(x => x.ID == item.LabelModulo);
AddOrAppendSerie("Cmd", "", (bico?.ComandoEstado ?? false) ? 100 : 0);
AddOrAppendSerie("Cmd", "", bico?.ComandoEstado ?? false ? 100 : 0);
AddOrAppendSerie("Vazão", "mL/s", bico?.VazaoInstantaneaMLs);
break;
case S_Code.sBMB:
var bomba = rover.Atuador?.Bombas?.FirstOrDefault(x => x.ID == item.LabelModulo);
AddOrAppendSerie("Cmd", "", (bomba?.ComandoEstado ?? false) ? 100 : 0);
AddOrAppendSerie("Cmd", "", bomba?.ComandoEstado ?? false ? 100 : 0);
AddOrAppendSerie("Potência", "%", bomba?.Potencia);
AddOrAppendSerie("Pressão", "psi", rover.Atuador?.PressaoLinhaPsi);
break;

View File

@ -0,0 +1,61 @@
using AgroBase.Models;
using AgroBase.Models.Operacoes;
using OperationControl.Helpers;
using System.ComponentModel;
using System.Windows.Input;
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
{
public class ParametrizacaoViewModel : INotifyPropertyChanged
{
private OperacaoParametrosModel _parametros = new OperacaoParametrosModel();
public OperacaoParametrosModel Parametros
{
get => _parametros;
set
{
if (_parametros != value)
{
_parametros = value;
OnPropertyChanged(nameof(Parametros));
}
}
}
public ParametrizacaoViewModel()
{
CarregarParametrosPadraoCommand = new RelayCommand(p => CarregarParametrosPadrao((AgroBase.Models.Enums.ModoOperacao)p));
LerParametrosCommand = new RelayCommand(_ => LerParametrosSolicitado?.Invoke());
SalvarParametrosCommand = new RelayCommand(_ => SalvarParametrosSolicitado?.Invoke(Parametros));
}
public event Action? LerParametrosSolicitado;
public event Action<OperacaoParametrosModel>? SalvarParametrosSolicitado;
public ICommand LerParametrosCommand { get; }
public ICommand SalvarParametrosCommand { get; }
public ICommand CarregarParametrosPadraoCommand { get; }
public Array ModosOperacaoDisponiveis { get; } = Enum.GetValues(typeof(AgroBase.Models.Enums.ModoOperacao));
private void CarregarParametrosPadrao(AgroBase.Models.Enums.ModoOperacao modo)
{
var p = OperacaoModel.CarregarParametrosOperacaoPadrao(modo, false);
p.Descricao = $"{p.Modo} - Padrão";
Parametros = p;
}
public void AtualizarParametros(OperacaoParametrosModel origem)
{
if (origem == null) return;
Parametros = origem;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string nome)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
}
}
}

View File

@ -0,0 +1,39 @@
using OperationControl.Models.Operacao;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OperationControl.ViewModels.Views.Operacao.Monitoramento
{
public class ResumoViewModel : INotifyPropertyChanged
{
public ResumoOperacionalModel Resumo { get; } = new ResumoOperacionalModel();
public ResumoViewModel()
{
}
public void AtualizarResumo(Action<ResumoOperacionalModel> updateAction)
{
if (!System.Windows.Application.Current.Dispatcher.CheckAccess())
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => updateAction?.Invoke(Resumo)));
return;
}
updateAction?.Invoke(Resumo);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string nome)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nome));
}
}
}

View File

@ -253,7 +253,7 @@ namespace OperationControl.ViewModels.Views.Operacao
OnPropertyChanged(nameof(CorGnss));
}
public void AtualizarRover(string nomeRover, double velocidadeKmh, double anguloDirecionalGraus, TipoMovimentoDirecional tipoMovimento, double temperaturaC, double bateriaPct, double reservatorioPct, string saudeRede, string saudeGnss)
public void AtualizarRover(string nomeRover, double velocidadeKmh, double anguloDirecionalGraus, TipoMovimentoDirecional tipoMovimento, double temperaturaC, double bateriaPct, double reservatorioPct, string saudeRede, string saudeGnss, bool op_iniciada)
{
RoverSelecionado = true;
NomeRover = nomeRover;
@ -271,11 +271,14 @@ namespace OperationControl.ViewModels.Views.Operacao
SaudeRede = saudeRede;
SaudeGnss = saudeGnss;
OperacaoEmExecucao = op_iniciada;
OnPropertyChanged(nameof(CorTemperatura));
OnPropertyChanged(nameof(CorBateria));
OnPropertyChanged(nameof(CorReservatorio));
OnPropertyChanged(nameof(CorRede));
OnPropertyChanged(nameof(CorGnss));
OnPropertyChanged(nameof(OperacaoEmExecucao));
}
private void AlternarOperacao()
@ -300,8 +303,6 @@ namespace OperationControl.ViewModels.Views.Operacao
VariaveisControleOperacao.EnviarComandoIniciarOperacao(true, simulador);
}
}
OperacaoEmExecucao = VariaveisControleOperacao.RoverEmFoco?.DadosLeitura?.Operacao?.Iniciada ?? false;
}
private void ExecutarParadaEmergencia()
@ -317,7 +318,6 @@ namespace OperationControl.ViewModels.Views.Operacao
if (System.Windows.MessageBox.Show("Deseja finalizar a operação em andamento?", "Finalizar Operação", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
{
VariaveisControleOperacao.EnviarComandoIniciarOperacao(false);
OperacaoEmExecucao = false;
}
}

View File

@ -17,21 +17,6 @@ namespace OperationControl.ViewModels.Views.Operacao
{
private bool _isCollapsed;
private RoverCardModel _roverSelecionado;
public ResumoOperacionalModel Resumo { get; } = new ResumoOperacionalModel();
private OperacaoParametrosModel _parametros = new OperacaoParametrosModel();
public OperacaoParametrosModel Parametros
{
get => _parametros;
set
{
if (_parametros != value)
{
_parametros = value;
OnPropertyChanged(nameof(Parametros));
}
}
}
public OperacaoRightViewModel()
{
@ -47,16 +32,11 @@ namespace OperationControl.ViewModels.Views.Operacao
SelecionarSecao(secaoParseada);
});
AcaoBotaoTopoCommand = new RelayCommand(_ => ExecutarAcaoBotaoTopo());
CarregarParametrosPadraoCommand = new RelayCommand(p => CarregarParametrosPadrao((AgroBase.Models.Enums.ModoOperacao)p));
LerParametrosCommand = new RelayCommand(_ => LerParametrosSolicitado?.Invoke());
SalvarParametrosCommand = new RelayCommand(_ => SalvarParametrosSolicitado?.Invoke(Parametros));
}
public event PropertyChangedEventHandler PropertyChanged;
public event Action<SecaoRightBar> SecaoSelecionadaChanged;
public event Action<RoverCardModel> RoverSelecionadoChanged;
public event Action? LerParametrosSolicitado;
public event Action<OperacaoParametrosModel>? SalvarParametrosSolicitado;
public ObservableCollection<RoverCardModel> Rovers { get; }
@ -64,9 +44,6 @@ namespace OperationControl.ViewModels.Views.Operacao
public ICommand SelecionarRoverCommand { get; }
public ICommand SelecionarSecaoCommand { get; }
public ICommand AcaoBotaoTopoCommand { get; }
public ICommand LerParametrosCommand { get; }
public ICommand SalvarParametrosCommand { get; }
public ICommand CarregarParametrosPadraoCommand { get; }
public bool IsCollapsed
{
@ -131,8 +108,6 @@ namespace OperationControl.ViewModels.Views.Operacao
public string TextoBotaoTopo => BotaoTopoEhVoltar ? "◀ Voltar" : "Trocar Rover";
public Array ModosOperacaoDisponiveis { get; } = Enum.GetValues(typeof(AgroBase.Models.Enums.ModoOperacao));
private void ExecutarAcaoBotaoTopo()
{
if (BotaoTopoEhVoltar)
@ -145,12 +120,6 @@ namespace OperationControl.ViewModels.Views.Operacao
}
}
private void CarregarParametrosPadrao(AgroBase.Models.Enums.ModoOperacao modo)
{
var p = OperacaoModel.CarregarParametrosOperacaoPadrao(modo, false);
p.Descricao = $"{p.Modo} - Padrão";
Parametros = p;
}
public void ToggleCollapse()
{
@ -176,13 +145,6 @@ namespace OperationControl.ViewModels.Views.Operacao
public void SelecionarSecao(SecaoRightBar secao)
{
switch (secao)
{
case SecaoRightBar.Parametrizacao:
AtualizarParametros(VariaveisControleOperacao.RoverEmFoco);
break;
}
SecaoAtual = secao;
SecaoSelecionadaChanged?.Invoke(secao);
@ -235,23 +197,6 @@ namespace OperationControl.ViewModels.Views.Operacao
OnPropertyChanged(nameof(ComRoverSelecionado));
}
public void AtualizarResumo(Action<ResumoOperacionalModel> updateAction)
{
if (!System.Windows.Application.Current.Dispatcher.CheckAccess())
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => updateAction?.Invoke(Resumo)));
return;
}
updateAction?.Invoke(Resumo);
}
public void AtualizarParametros(OperacaoParametrosModel origem)
{
if (origem == null) return;
Parametros = origem;
}
private void OnPropertyChanged(string nome)
{

View File

@ -56,8 +56,8 @@ namespace OperationControl.ViewModels
_viewOperacaoRight._vm.PropertyChanged += OperacaoRightVm_PropertyChanged;
_viewOperacaoRight._vm.RoverSelecionadoChanged += OnRoverSelecionadoChanged;
_viewOperacaoRight._vm.SecaoSelecionadaChanged += OnSecaoSelecionadaChanged;
_viewOperacaoRight._vm.LerParametrosSolicitado += OnLerParametrosSolicitado;
_viewOperacaoRight._vm.SalvarParametrosSolicitado += OnSalvarParametrosSolicitado;
_viewOperacaoRight.areaParametrizacao._vm.LerParametrosSolicitado += OnLerParametrosSolicitado;
_viewOperacaoRight.areaParametrizacao._vm.SalvarParametrosSolicitado += OnSalvarParametrosSolicitado;
_viewOperacaoBottom = new OperacaoBottomView();
_viewOperacaoBottom._vm.SolicitarAbrirDiagnostico += AbrirDiagnosticoPeloAlerta;
@ -198,7 +198,7 @@ namespace OperationControl.ViewModels
{
return CurrentStep switch
{
DockStep.ParametrizacaoRover => (_viewOperacaoRight?.DataContext as OperacaoRightViewModel)?.IsCollapsed == true
DockStep.ParametrizacaoRover => _viewOperacaoRight?._vm?.IsCollapsed == true
? new GridLength(44)
: new GridLength(320),
@ -616,7 +616,7 @@ namespace OperationControl.ViewModels
public void AtualizarParametrosRover(OperacaoParametrosModel? rover)
{
_viewOperacaoRight?._vm?.AtualizarParametros(rover);
_viewOperacaoRight?.areaParametrizacao?._vm?.AtualizarParametros(rover);
AtualizarDadosMapa(rover);
}
@ -800,11 +800,12 @@ namespace OperationControl.ViewModels
obj.Bateria?.PercentualBateria ?? 0,
obj.Atuador?.PercentualReservatorio ?? 0,
$"{c}%",
$"{obj.Gnss?.QualidadeFix ?? TiposCorrecaoGPS.SemCorrecao} {obj.Gnss?.PrecisaoCm:F2} cm"
$"{obj.Gnss?.QualidadeFix ?? TiposCorrecaoGPS.SemCorrecao} {obj.Gnss?.PrecisaoCm:F2} cm",
obj.Operacao?.Iniciada ?? false
);
// DIREITA (RESUMO)
_viewOperacaoRight?._vm?.AtualizarResumo(r =>
_viewOperacaoRight?.areaResumo?._vm?.AtualizarResumo(r =>
{
r.Operacao = (obj.Operacao?.Liberada ?? false) ? "🔓 Liberada" : "🔒 Bloqueada";
r.Modo = obj.Operacao == null ? "-" : obj.Operacao.Modo.ToString();
@ -934,7 +935,7 @@ namespace OperationControl.ViewModels
}
else
{
VariaveisControleOperacao.SelectedRoverId = rover.NumeroSerie.ToString();
VariaveisControleOperacao.SelectedRoverId = (rover.NumeroSerie ?? "").ToString();
_viewOperacaoCenter?.Mapa?.markers?.SetMarkerFocused(VariaveisControleOperacao.SelectedRoverId, true);
AtualizarDadosTela(VariaveisControleOperacao.RoverEmFoco);
@ -952,6 +953,8 @@ namespace OperationControl.ViewModels
}
private void OnSecaoSelecionadaChanged(SecaoRightBar secao)
{
if (secao == SecaoRightBar.Parametrizacao)
_viewOperacaoRight?.areaParametrizacao?._vm?.AtualizarParametros(VariaveisControleOperacao.RoverEmFoco);
_viewOperacaoCenter?._vm?.DefinirSecao(secao);
AtualizarDadosMapa(VariaveisControleOperacao.RoverEmFoco);
}

View File

@ -0,0 +1,330 @@
<UserControl x:Class="OperationControl.Views.Operacao.Monitoramento.ControleManualView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Focusable="True">
<Grid>
<Grid.Resources>
<Style x:Key="ControlSectionCardStyle" TargetType="Border">
<Setter Property="Background" Value="#262626"/>
<Setter Property="BorderBrush" Value="#3E3E3E"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="Margin" Value="0,0,0,12"/>
</Style>
<Style x:Key="ControlLabelStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="#D0D0D0"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Margin" Value="0,0,0,6"/>
</Style>
<Style x:Key="ControlValueStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
<Style x:Key="ControlButtonKeyStyle" TargetType="Border">
<Setter Property="Width" Value="50"/>
<Setter Property="Height" Value="50"/>
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Background" Value="#2D2D2D"/>
<Setter Property="BorderBrush" Value="#555555"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Margin" Value="4"/>
</Style>
<Style x:Key="ControlActionButtonStyle" TargetType="Button">
<Setter Property="Height" Value="42"/>
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="8">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<StackPanel Margin="0,0,2,0">
<TextBlock Text="Controle Manual"
Foreground="White"
FontSize="18"
FontWeight="Bold"
Margin="0,0,0,4"/>
<TextBlock Text="Use o teclado ou os comandos abaixo para operar o rover."
Foreground="#A8A8A8"
FontSize="12"
Margin="0,0,0,14"
TextWrapping="Wrap"/>
<!-- STATUS -->
<Border Style="{StaticResource ControlSectionCardStyle}">
<StackPanel>
<TextBlock Text="Status do Controle"
Foreground="White"
FontSize="15"
FontWeight="SemiBold"
Margin="0,0,0,12"/>
<CheckBox Content="Habilitar controle por teclado"
IsChecked="{Binding Habilitado}"
Foreground="White"
Margin="0,0,0,10"/>
<Grid Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Ellipse Width="10"
Height="10"
Fill="{Binding StatusBrush}"
VerticalAlignment="Center"/>
<TextBlock Grid.Column="1"
Text="{Binding StatusTexto}"
Foreground="White"
FontWeight="SemiBold"
Margin="8,0,0,0"
VerticalAlignment="Center"/>
</Grid>
<TextBlock Text="{Binding TextoAjuda}"
Foreground="#B8B8B8"
FontSize="12"
TextWrapping="Wrap"/>
</StackPanel>
</Border>
<!-- TECLAS -->
<Border Style="{StaticResource ControlSectionCardStyle}">
<StackPanel>
<TextBlock Text="Comandos Diretos"
Foreground="White"
FontSize="15"
FontWeight="SemiBold"
Margin="0,0,0,12"/>
<Grid HorizontalAlignment="Center" Margin="0,0,0,10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- W -->
<Border Grid.Row="0" Grid.Column="1"
Style="{StaticResource ControlButtonKeyStyle}"
Background="{Binding TeclaWBackground}"
BorderBrush="{Binding TeclaWBorder}">
<TextBlock Text="W"
Foreground="White"
FontSize="22"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- A -->
<Border Grid.Row="1" Grid.Column="0"
Style="{StaticResource ControlButtonKeyStyle}"
Background="{Binding TeclaABackground}"
BorderBrush="{Binding TeclaABorder}">
<TextBlock Text="A"
Foreground="White"
FontSize="22"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- S -->
<Border Grid.Row="1" Grid.Column="1"
Style="{StaticResource ControlButtonKeyStyle}"
Background="{Binding TeclaSBackground}"
BorderBrush="{Binding TeclaSBorder}">
<TextBlock Text="S"
Foreground="White"
FontSize="22"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- D -->
<Border Grid.Row="1" Grid.Column="2"
Style="{StaticResource ControlButtonKeyStyle}"
Background="{Binding TeclaDBackground}"
BorderBrush="{Binding TeclaDBorder}">
<TextBlock Text="D"
Foreground="White"
FontSize="22"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- F -->
<Border Grid.Row="1" Grid.Column="3"
Style="{StaticResource ControlButtonKeyStyle}"
Background="{Binding TeclaFBackground}"
BorderBrush="{Binding TeclaFBorder}">
<TextBlock Text="F"
Foreground="White"
FontSize="22"
FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</Grid>
<TextBlock Text="W: Frente | S: Ré | A: Esquerda | D: Direita | F: Freio"
Foreground="#B8B8B8"
FontSize="12"
TextWrapping="Wrap"
Margin="0,0,0,8"/>
<Border Background="{Binding FreioCardBackground}"
BorderBrush="{Binding FreioCardBorder}"
BorderThickness="1"
CornerRadius="8"
Padding="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="⛔"
FontSize="16"
Margin="0,0,8,0"
VerticalAlignment="Center"/>
<TextBlock Text="{Binding FreioAtivoTexto}"
Foreground="White"
FontWeight="SemiBold"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
</StackPanel>
</Border>
<!-- AJUSTES -->
<Border Style="{StaticResource ControlSectionCardStyle}">
<StackPanel>
<TextBlock Text="Ajustes de Movimento"
Foreground="White"
FontSize="15"
FontWeight="SemiBold"
Margin="0,0,0,12"/>
<Grid Margin="0,0,0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Velocidade (%)"
Style="{StaticResource ControlLabelStyle}"
Margin="0"/>
<TextBlock Grid.Column="1"
Text="{Binding VelocidadePercentualTexto}"
Style="{StaticResource ControlValueStyle}"/>
</Grid>
<Slider Minimum="0"
Maximum="100"
Value="{Binding VelocidadePercentual, Mode=TwoWay}"
Margin="0,0,0,12"/>
<Grid Margin="0,0,0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Ângulo Direcional (°)"
Style="{StaticResource ControlLabelStyle}"
Margin="0"/>
<TextBlock Grid.Column="1"
Text="{Binding AnguloTexto}"
Style="{StaticResource ControlValueStyle}"/>
</Grid>
<Slider Minimum="-30"
Maximum="30"
Value="{Binding AnguloDirecional, Mode=TwoWay}"
Margin="0,0,0,12"/>
<TextBlock Text="Tipo de Movimento" Style="{StaticResource ControlLabelStyle}"/>
<ComboBox ItemsSource="{Binding TiposMovimento}"
SelectedItem="{Binding TipoMovimentoSelecionado, Mode=TwoWay}"/>
</StackPanel>
</Border>
<!-- ESTADO -->
<Border Style="{StaticResource ControlSectionCardStyle}">
<StackPanel>
<TextBlock Text="Estado Atual"
Foreground="White"
FontSize="15"
FontWeight="SemiBold"
Margin="0,0,0,12"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Movimento" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding MovimentoAtualTexto}" Foreground="White" Margin="10,0,0,8"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Direção" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding DirecaoAtualTexto}" Foreground="White" Margin="10,0,0,8"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Freio" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding FreioAtivoTexto}" Foreground="White" Margin="10,0,0,8"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Velocidade" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding VelocidadePercentualTexto}" Foreground="White" Margin="10,0,0,8"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Ângulo" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding AnguloTexto}" Foreground="White" Margin="10,0,0,8"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Modo" Foreground="#CFCFCF" Margin="0,0,0,0"/>
<TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding TipoMovimentoSelecionado}" Foreground="White" Margin="10,0,0,0"/>
</Grid>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,39 @@
using OperationControl.ViewModels.Views.Operacao.Monitoramento;
namespace OperationControl.Views.Operacao.Monitoramento
{
/// <summary>
/// Interação lógica para ControleManualView.xam
/// </summary>
public partial class ControleManualView : System.Windows.Controls.UserControl
{
public ControleManualViewModel _vm;
public ControleManualView()
{
InitializeComponent();
_vm = new ControleManualViewModel();
DataContext = _vm;
Loaded += (_, __) => Focus();
MouseDown += (_, __) => Focus();
}
protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
_vm.HandleKeyDown(e.Key);
e.Handled = true;
}
protected override void OnPreviewKeyUp(System.Windows.Input.KeyEventArgs e)
{
base.OnPreviewKeyUp(e);
_vm.HandleKeyUp(e.Key);
e.Handled = true;
}
}
}

View File

@ -1,4 +1,4 @@
<UserControl x:Class="OperationControl.Views.Operacao.DiagnosticoView"
<UserControl x:Class="OperationControl.Views.Operacao.Monitoramento.DiagnosticoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View File

@ -1,20 +1,6 @@
using OperationControl.ViewModels.Views.Operacao.Diagnostico;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OperationControl.ViewModels.Views.Operacao.Monitoramento.Diagnostico;
namespace OperationControl.Views.Operacao
namespace OperationControl.Views.Operacao.Monitoramento
{
/// <summary>
/// Interaction logic for DiagnosticoView.xaml

View File

@ -1,4 +1,4 @@
<UserControl x:Class="OperationControl.Views.Operacao.MonitoramentoView"
<UserControl x:Class="OperationControl.Views.Operacao.Monitoramento.MonitoramentoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View File

@ -2,7 +2,7 @@
using OperationControl.Models;
using OperationControl.ViewModels.Views.Operacao.Monitoramento;
namespace OperationControl.Views.Operacao
namespace OperationControl.Views.Operacao.Monitoramento
{
/// <summary>
/// Interaction logic for MonitoramentoView.xaml

View File

@ -0,0 +1,189 @@
<UserControl x:Class="OperationControl.Views.Operacao.Monitoramento.ParametrizacaoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OperationControl.Views.Operacao"
mc:Ignorable="d" >
<Grid>
<Grid.Resources>
<Style x:Key="ParamLabelStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="#D0D0D0"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,0,6"/>
</Style>
<Style x:Key="ParamTextBoxStyle" TargetType="TextBox">
<Setter Property="Height" Value="34"/>
<Setter Property="Margin" Value="0,0,0,12"/>
<Setter Property="Padding" Value="8,4"/>
<Setter Property="Background" Value="#2B2B2B"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#5A5A5A"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
<Style x:Key="SectionCardStyle" TargetType="Border">
<Setter Property="Background" Value="#262626"/>
<Setter Property="BorderBrush" Value="#3E3E3E"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="Margin" Value="0,0,0,12"/>
</Style>
<Style x:Key="ActionButtonStyle" TargetType="Button">
<Setter Property="Height" Value="40"/>
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="8">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ParamCheckBoxStyle" TargetType="CheckBox">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Margin" Value="0,0,0,10"/>
</Style>
</Grid.Resources>
<StackPanel Margin="0,0,2,0">
<TextBlock Text="Parametrização" Foreground="White" FontSize="18" FontWeight="Bold" Margin="0,0,0,4"/>
<TextBlock Text="Configure os parâmetros operacionais do rover." Foreground="#A8A8A8" FontSize="12" Margin="0,0,0,14"/>
<!-- OPERACAO -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Operação" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Modo" Style="{StaticResource ParamLabelStyle}"/>
<ComboBox ItemsSource="{Binding ModosOperacaoDisponiveis}" SelectedItem="{Binding Parametros.Modo, Mode=TwoWay}" SelectionChanged="cmbModoOperacao_SelectionChanged" />
<TextBlock Text="Descrição" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Descricao}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- AUTOMAÇÃO GERAL -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Automação Geral" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<CheckBox Content="Movimento Automático" IsChecked="{Binding Parametros.Controle.MovimentoAutomatico}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Direcional Automático" IsChecked="{Binding Parametros.Controle.DirecionalAutomatico}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Pulverizador Automático" IsChecked="{Binding Parametros.Controle.PulverizadorAutomatico}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Sonar Ativado" IsChecked="{Binding Parametros.Controle.SonarAtivado}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Parada por Obstáculo (OAK)" IsChecked="{Binding Parametros.Controle.OakParadaPorObstaculo}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Parada por Inclinação (IMU)" IsChecked="{Binding Parametros.Controle.ImuParadaPorInclinacao}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Frenagem Automática ao Parar" IsChecked="{Binding Parametros.Controle.FrenagemAutomaticaAoParar}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Registrar Dados Pós-Processamento" IsChecked="{Binding Parametros.Controle.RegistrarDadosPosProcessamento}" Style="{StaticResource ParamCheckBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- MOVIMENTO -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Movimento" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Velocidade sem Ervas (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovVelocidadeSErvasPercent, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Velocidade com Ervas (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovVelocidadeCErvasPercent, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="RPM Máx Calculado" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovRpmMax, Mode=OneWay}" IsReadOnly="True" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="RPM Mín Calculado" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovRpmMin, Mode=OneWay}" IsReadOnly="True" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- DIRECIONAL -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Direcional" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Ângulo Máximo (°)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.DirAnguloMaximo, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Velocidade Movimento" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.DirVelocidadeMovimento, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Tipo de Movimento" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.DirTipoMovimento, Mode=OneWay}" IsReadOnly="True" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- PULVERIZAÇÃO -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Pulverização" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Quantidade de Bicos" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.QtdBicos, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Capacidade do Reservatório (L)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.CapacidadeReservatorio, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Pressão Linha" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPressaoLinha, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Duração Atuação (ms)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuDuracaoAtuacao, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Início Pulverização (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPercentualInicioPulverizacao, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Altura Área Pulverização" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuAlturaAreaPulverizacao, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Ervas Bico On (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPercentualErvasBicoOn, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Ervas Bico Off (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPercentualErvasBicoOff, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- MPC -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="MPC" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<CheckBox Content="Matriz de Custo" IsChecked="{Binding Parametros.Controle.MpcMatrizCusto}" Style="{StaticResource ParamCheckBoxStyle}"/>
<TextBlock Text="Horizonte (m)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MpcHorizonte, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- AÇÕES -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Ações" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<Button Content="↻ Ler do Rover" Command="{Binding LerParametrosCommand}" Background="#2E2E2E" BorderBrush="#5C5C5C" Style="{StaticResource ActionButtonStyle}"/>
<Button Content="💾 Salvar no Rover" Command="{Binding SalvarParametrosCommand}" Background="#2F5D3A" BorderBrush="#4A8A5B" Style="{StaticResource ActionButtonStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,30 @@
using OperationControl.ViewModels.Views.Operacao.Monitoramento;
using System.Windows.Controls;
namespace OperationControl.Views.Operacao.Monitoramento
{
/// <summary>
/// Interação lógica para ParametrizacaoView.xam
/// </summary>
public partial class ParametrizacaoView : System.Windows.Controls.UserControl
{
public ParametrizacaoViewModel _vm;
public ParametrizacaoView()
{
InitializeComponent();
_vm = new ParametrizacaoViewModel();
DataContext = _vm;
}
private void cmbModoOperacao_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (sender is System.Windows.Controls.ComboBox combo && combo.SelectedItem is AgroBase.Models.Enums.ModoOperacao modo)
{
if (_vm.CarregarParametrosPadraoCommand?.CanExecute(modo) == true)
_vm.CarregarParametrosPadraoCommand.Execute(modo);
}
}
}
}

View File

@ -0,0 +1,88 @@
<UserControl x:Class="OperationControl.Views.Operacao.Monitoramento.ResumoView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OperationControl.Views.Operacao.Monitoramento"
mc:Ignorable="d" >
<Grid>
<StackPanel>
<!-- CARD ESTADO GERAL -->
<Border Background="#262626" BorderBrush="#3E3E3E" BorderThickness="1" CornerRadius="10" Padding="12" Margin="0,0,0,10">
<StackPanel>
<TextBlock Text="Estado Geral" Foreground="White" FontSize="16" FontWeight="Bold" Margin="0,0,0,12"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Operação" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Resumo.Operacao}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Modo" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Resumo.Modo}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Status" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Resumo.Status}" Foreground="White" Margin="12,0,0,8" TextWrapping="Wrap"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Carro" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Resumo.Carro}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Temperatura" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding Resumo.Temperatura}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Conexão" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding Resumo.Conexao}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Duração" Foreground="#CFCFCF" Margin="0,0,0,0"/>
<TextBlock Grid.Row="6" Grid.Column="1" Text="{Binding Resumo.Duracao}" Foreground="White" Margin="12,0,0,0"/>
</Grid>
</StackPanel>
</Border>
<!-- CARD PROGRESSO -->
<Border Background="#262626" BorderBrush="#3E3E3E" BorderThickness="1" CornerRadius="10" Padding="12" Margin="0,0,0,10">
<StackPanel>
<TextBlock Text="Progresso e Recursos" Foreground="White" FontSize="16" FontWeight="Bold" Margin="0,0,0,12"/>
<!-- Rua Atual -->
<TextBlock Text="Rua Atual" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.RuaAtualPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.RuaAtual}" Foreground="White" Margin="0,0,0,12"/>
<!-- Área Total -->
<TextBlock Text="Área Total" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.AreaTotalPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.AreaTotal}" Foreground="White" Margin="0,0,0,12"/>
<!-- Bateria -->
<TextBlock Text="Bateria" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.BateriaPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.Bateria}" Foreground="White" Margin="0,0,0,12"/>
<!-- Herbicida -->
<TextBlock Text="Herbicida" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.HerbicidaPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.Herbicida}" Foreground="White" Margin="0,0,0,12"/>
<!-- Infestação -->
<TextBlock Text="Infestação" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.InfestacaoPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.Infestacao}" Foreground="White"/>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</UserControl>

View File

@ -0,0 +1,20 @@
using OperationControl.ViewModels.Views.Operacao.Monitoramento;
namespace OperationControl.Views.Operacao.Monitoramento
{
/// <summary>
/// Interação lógica para ResumoView.xam
/// </summary>
public partial class ResumoView : System.Windows.Controls.UserControl
{
public ResumoViewModel _vm;
public ResumoView()
{
InitializeComponent();
_vm = new ResumoViewModel();
DataContext = _vm;
}
}
}

View File

@ -5,8 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OperationControl.Views.Operacao"
xmlns:controls="clr-namespace:OperationControl.Controls"
xmlns:views="clr-namespace:OperationControl.Views.Operacao"
xmlns:scott="clr-namespace:ScottPlot.WPF;assembly=ScottPlot.WPF"
xmlns:views="clr-namespace:OperationControl.Views.Operacao.Monitoramento"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">

View File

@ -1,5 +1,6 @@
using OperationControl.Controls;
using OperationControl.ViewModels.Views.Operacao;
using OperationControl.Views.Operacao.Monitoramento;
namespace OperationControl.Views.Operacao
{

View File

@ -3,9 +3,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:OperationControl.Views.Operacao"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:views="clr-namespace:OperationControl.Views.Operacao.Monitoramento"
mc:Ignorable="d">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
@ -218,270 +217,15 @@
<ScrollViewer.Resources>
<Style TargetType="ScrollBar" BasedOn="{StaticResource ThinScrollBar}" />
</ScrollViewer.Resources>
<StackPanel>
<!-- CARD ESTADO GERAL -->
<Border Background="#262626" BorderBrush="#3E3E3E" BorderThickness="1" CornerRadius="10" Padding="12" Margin="0,0,0,10">
<StackPanel>
<TextBlock Text="Estado Geral" Foreground="White" FontSize="16" FontWeight="Bold" Margin="0,0,0,12"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Operação" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Resumo.Operacao}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Modo" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Resumo.Modo}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Status" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Resumo.Status}" Foreground="White" Margin="12,0,0,8" TextWrapping="Wrap"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Carro" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Resumo.Carro}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Temperatura" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="4" Grid.Column="1" Text="{Binding Resumo.Temperatura}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Conexão" Foreground="#CFCFCF" Margin="0,0,0,8"/>
<TextBlock Grid.Row="5" Grid.Column="1" Text="{Binding Resumo.Conexao}" Foreground="White" Margin="12,0,0,8"/>
<TextBlock Grid.Row="6" Grid.Column="0" Text="Duração" Foreground="#CFCFCF" Margin="0,0,0,0"/>
<TextBlock Grid.Row="6" Grid.Column="1" Text="{Binding Resumo.Duracao}" Foreground="White" Margin="12,0,0,0"/>
</Grid>
</StackPanel>
</Border>
<!-- CARD PROGRESSO -->
<Border Background="#262626" BorderBrush="#3E3E3E" BorderThickness="1" CornerRadius="10" Padding="12" Margin="0,0,0,10">
<StackPanel>
<TextBlock Text="Progresso e Recursos" Foreground="White" FontSize="16" FontWeight="Bold" Margin="0,0,0,12"/>
<!-- Rua Atual -->
<TextBlock Text="Rua Atual" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.RuaAtualPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.RuaAtual}" Foreground="White" Margin="0,0,0,12"/>
<!-- Área Total -->
<TextBlock Text="Área Total" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.AreaTotalPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.AreaTotal}" Foreground="White" Margin="0,0,0,12"/>
<!-- Bateria -->
<TextBlock Text="Bateria" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.BateriaPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.Bateria}" Foreground="White" Margin="0,0,0,12"/>
<!-- Herbicida -->
<TextBlock Text="Herbicida" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.HerbicidaPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.Herbicida}" Foreground="White" Margin="0,0,0,12"/>
<!-- Infestação -->
<TextBlock Text="Infestação" Foreground="#CFCFCF"/>
<ProgressBar Value="{Binding Resumo.InfestacaoPercentual}" Maximum="100" Height="12" Margin="0,6,0,4"/>
<TextBlock Text="{Binding Resumo.Infestacao}" Foreground="White"/>
</StackPanel>
</Border>
</StackPanel>
<views:ResumoView x:Name="areaResumo" />
</ScrollViewer>
<!-- PARAMETRIZAÇÃO -->
<ScrollViewer Visibility="{Binding EmParametrizacao, Converter={StaticResource BoolToVisibilityConverter}}" VerticalScrollBarVisibility="Auto">
<ScrollViewer.Resources>
<Style TargetType="ScrollBar" BasedOn="{StaticResource ThinScrollBar}" />
<Style x:Key="ParamLabelStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="#D0D0D0"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,0,6"/>
</Style>
<Style x:Key="ParamTextBoxStyle" TargetType="TextBox">
<Setter Property="Height" Value="34"/>
<Setter Property="Margin" Value="0,0,0,12"/>
<Setter Property="Padding" Value="8,4"/>
<Setter Property="Background" Value="#2B2B2B"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#5A5A5A"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
<Style x:Key="SectionCardStyle" TargetType="Border">
<Setter Property="Background" Value="#262626"/>
<Setter Property="BorderBrush" Value="#3E3E3E"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CornerRadius" Value="10"/>
<Setter Property="Padding" Value="12"/>
<Setter Property="Margin" Value="0,0,0,12"/>
</Style>
<Style x:Key="ActionButtonStyle" TargetType="Button">
<Setter Property="Height" Value="40"/>
<Setter Property="Margin" Value="0,0,0,10"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="8">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ParamCheckBoxStyle" TargetType="CheckBox">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Margin" Value="0,0,0,10"/>
</Style>
</ScrollViewer.Resources>
<StackPanel Margin="0,0,2,0">
<TextBlock Text="Parametrização" Foreground="White" FontSize="18" FontWeight="Bold" Margin="0,0,0,4"/>
<TextBlock Text="Configure os parâmetros operacionais do rover." Foreground="#A8A8A8" FontSize="12" Margin="0,0,0,14"/>
<!-- OPERACAO -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Operação" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Modo" Style="{StaticResource ParamLabelStyle}"/>
<ComboBox ItemsSource="{Binding ModosOperacaoDisponiveis}" SelectedItem="{Binding Parametros.Modo, Mode=TwoWay}" SelectionChanged="cmbModoOperacao_SelectionChanged" />
<TextBlock Text="Descrição" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Descricao}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- AUTOMAÇÃO GERAL -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Automação Geral" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<CheckBox Content="Movimento Automático" IsChecked="{Binding Parametros.Controle.MovimentoAutomatico}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Direcional Automático" IsChecked="{Binding Parametros.Controle.DirecionalAutomatico}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Pulverizador Automático" IsChecked="{Binding Parametros.Controle.PulverizadorAutomatico}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Sonar Ativado" IsChecked="{Binding Parametros.Controle.SonarAtivado}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Parada por Obstáculo (OAK)" IsChecked="{Binding Parametros.Controle.OakParadaPorObstaculo}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Parada por Inclinação (IMU)" IsChecked="{Binding Parametros.Controle.ImuParadaPorInclinacao}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Frenagem Automática ao Parar" IsChecked="{Binding Parametros.Controle.FrenagemAutomaticaAoParar}" Style="{StaticResource ParamCheckBoxStyle}"/>
<CheckBox Content="Registrar Dados Pós-Processamento" IsChecked="{Binding Parametros.Controle.RegistrarDadosPosProcessamento}" Style="{StaticResource ParamCheckBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- MOVIMENTO -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Movimento" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Velocidade sem Ervas (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovVelocidadeSErvasPercent, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Velocidade com Ervas (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovVelocidadeCErvasPercent, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="RPM Máx Calculado" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovRpmMax, Mode=OneWay}" IsReadOnly="True" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="RPM Mín Calculado" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MovRpmMin, Mode=OneWay}" IsReadOnly="True" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- DIRECIONAL -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Direcional" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Ângulo Máximo (°)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.DirAnguloMaximo, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Velocidade Movimento" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.DirVelocidadeMovimento, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Tipo de Movimento" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.DirTipoMovimento, Mode=OneWay}" IsReadOnly="True" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- PULVERIZAÇÃO -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Pulverização" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<TextBlock Text="Quantidade de Bicos" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.QtdBicos, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Capacidade do Reservatório (L)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.CapacidadeReservatorio, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Pressão Linha" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPressaoLinha, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Duração Atuação (ms)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuDuracaoAtuacao, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Início Pulverização (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPercentualInicioPulverizacao, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Altura Área Pulverização" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuAlturaAreaPulverizacao, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Ervas Bico On (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPercentualErvasBicoOn, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}"/>
<TextBlock Text="Ervas Bico Off (%)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.AtuPercentualErvasBicoOff, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- MPC -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="MPC" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<CheckBox Content="Matriz de Custo" IsChecked="{Binding Parametros.Controle.MpcMatrizCusto}" Style="{StaticResource ParamCheckBoxStyle}"/>
<TextBlock Text="Horizonte (m)" Style="{StaticResource ParamLabelStyle}"/>
<TextBox Text="{Binding Parametros.Controle.MpcHorizonte, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource ParamTextBoxStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
<!-- AÇÕES -->
<Border Style="{StaticResource SectionCardStyle}">
<StackPanel>
<TextBlock Text="Ações" Foreground="White" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
<Button Content="↻ Ler do Rover" Command="{Binding LerParametrosCommand}" Background="#2E2E2E" BorderBrush="#5C5C5C" Style="{StaticResource ActionButtonStyle}"/>
<Button Content="💾 Salvar no Rover" Command="{Binding SalvarParametrosCommand}" Background="#2F5D3A" BorderBrush="#4A8A5B" Style="{StaticResource ActionButtonStyle}" Margin="0,0,0,0"/>
</StackPanel>
</Border>
</StackPanel>
<views:ParametrizacaoView x:Name="areaParametrizacao" />
</ScrollViewer>
<!-- CONTROLE -->
@ -489,9 +233,7 @@
<ScrollViewer.Resources>
<Style TargetType="ScrollBar" BasedOn="{StaticResource ThinScrollBar}" />
</ScrollViewer.Resources>
<StackPanel>
<TextBlock Text="Controle" Foreground="White" FontSize="16" FontWeight="Bold"/>
</StackPanel>
<views:ControleManualView x:Name="areaControle" />
</ScrollViewer>
</Grid>

View File

@ -1,18 +1,4 @@
using OperationControl.ViewModels.Views.Operacao;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OperationControl.Views.Operacao
{
@ -29,21 +15,5 @@ namespace OperationControl.Views.Operacao
_vm = new OperacaoRightViewModel();
DataContext = _vm;
}
public OperacaoRightView(OperacaoRightViewModel vm)
{
InitializeComponent();
_vm = vm;
DataContext = _vm;
}
private void cmbModoOperacao_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (DataContext is OperacaoRightViewModel vm && sender is System.Windows.Controls.ComboBox combo && combo.SelectedItem is AgroBase.Models.Enums.ModoOperacao modo)
{
if (vm.CarregarParametrosPadraoCommand?.CanExecute(modo) == true)
vm.CarregarParametrosPadraoCommand.Execute(modo);
}
}
}
}