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 _pressedKeys = new(); private BotoesJoystick _lastMovKey = BotoesJoystick.Vazio; private BotoesJoystick _lastDirKey = BotoesJoystick.Vazio; private bool _lastFreio = false; public bool Habilitado { get => _habilitado; set { if (_habilitado != value) { _habilitado = value; OnPropertyChanged(nameof(StatusTexto)); OnPropertyChanged(nameof(TextoAjuda)); OnPropertyChanged(nameof(StatusBrush)); var r = VariaveisControleOperacao.RoverEmFoco; if (r != null) { r.Controle.MovimentoAutomatico = value ? false : r.ControleAutomatico; r.Controle.DirecionalAutomatico = value ? false : r.ControleAutomatico; VariaveisControleOperacao.EnviarParametrosOperacao(new AgroBase.Models.Operacoes.OperacaoParametrosModel() { Controle = VariaveisControleOperacao.RoverEmFoco?.Controle }); } if (!value) { LimparTeclas(); EnviarNeutros(); } else { VariaveisControleOperacao.EnviarComandoIniciarUDP(VariaveisControleOperacao.RoverEmFoco.IP, true); } } } } 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 TiposMovimento { get; } = Enum.GetValues(typeof(TipoMovimentoDirecional)) .Cast() .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() { (BotoesJoystick dir, bool ds) = ObterDirecaoDirecional(); (BotoesJoystick mov, bool ms) = ObterDirecaoMovimentacao(); var freio = FPressionado; if (_lastDirKey != dir || ds) { VariaveisControleOperacao.EnviarComandoDirecionalUDP(dir, ds, Convert.ToInt32(AnguloDirecional), TipoMovimentoSelecionado); _lastDirKey = ds ? BotoesJoystick.Vazio : dir; } if (_lastMovKey != mov || _lastFreio != freio || ms) { VariaveisControleOperacao.EnviarComandoMovimentacaoUDP(mov, ms, Convert.ToInt32(VelocidadePercentual), freio); _lastMovKey = ms ? BotoesJoystick.Vazio : mov; _lastFreio = freio; } } private (BotoesJoystick, bool) ObterDirecaoDirecional() { if (APressionado && !DPressionado) return (BotoesJoystick.SEsquerda, false); if (DPressionado && !APressionado) return (BotoesJoystick.SDireita, false); return (_lastDirKey, _lastDirKey != BotoesJoystick.Vazio); } private (BotoesJoystick, bool) ObterDirecaoMovimentacao() { if (FPressionado) return (BotoesJoystick.Bolinha, false); if (WPressionado && !SPressionado) return (BotoesJoystick.Xis, false); if (SPressionado && !WPressionado) return (BotoesJoystick.Quadrado, false); if (_lastFreio) return (BotoesJoystick.Bolinha, true); else return (_lastMovKey, _lastMovKey != BotoesJoystick.Vazio); } private void EnviarNeutros() { if (_lastDirKey != BotoesJoystick.Vazio) { VariaveisControleOperacao.EnviarComandoDirecionalUDP(BotoesJoystick.SEsquerda, true, Convert.ToInt32(AnguloDirecional), TipoMovimentoSelecionado); _lastDirKey = BotoesJoystick.Vazio; } if (_lastMovKey != BotoesJoystick.Vazio || _lastFreio) { VariaveisControleOperacao.EnviarComandoMovimentacaoUDP(BotoesJoystick.Xis, true, 0, false); _lastMovKey = BotoesJoystick.Vazio; _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)); } } }