1263 lines
57 KiB
C#
1263 lines
57 KiB
C#
using AgroBase.Forms;
|
|
using AgroBase.Models;
|
|
using AgroBase.Models.Modules;
|
|
using AgroBase.Services;
|
|
using SharpDX.DirectInput;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using static AgroBase.Models.Enums;
|
|
|
|
namespace AgroBase
|
|
{
|
|
/// <summary>Leitura consolidada e tolerante a falhas do controle manual.</summary>
|
|
public class GeneralJoystick
|
|
{
|
|
public static List<string> JoysticksConectados = new List<string>();
|
|
public static Joystick JoystickConectado = null;
|
|
public static int MargemAnalogico = 100;
|
|
public static int MaximoAnalogico = 65534;
|
|
|
|
public static List<DeParaComandos> DeParaComandos = new List<DeParaComandos>()
|
|
{
|
|
new DeParaComandos() { key = Keys.Left, botaoJoy = BotoesJoystick.SEsquerda, direcao = Direcao.Esquerda, Dispositivo = T_Code.Dir, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Left, botaoJoy = BotoesJoystick.AEEsquerda, direcao = Direcao.Esquerda, Dispositivo = T_Code.Dir, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Right, botaoJoy = BotoesJoystick.SDireita, direcao = Direcao.Direita, Dispositivo = T_Code.Dir, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Right, botaoJoy = BotoesJoystick.AEDireita, direcao = Direcao.Direita, Dispositivo = T_Code.Dir, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.R, botaoJoy = BotoesJoystick.R3, direcao = Direcao.Referenciar, Dispositivo = T_Code.Dir, PararAoSoltar = false },
|
|
new DeParaComandos() { key = Keys.Up, botaoJoy = BotoesJoystick.Xis, direcao = Direcao.Frente, Dispositivo = T_Code.Mov, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Up, botaoJoy = BotoesJoystick.R2A, direcao = Direcao.Frente, Dispositivo = T_Code.Mov, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Down, botaoJoy = BotoesJoystick.Quadrado, direcao = Direcao.Tras, Dispositivo = T_Code.Mov, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Down, botaoJoy = BotoesJoystick.L2A, direcao = Direcao.Tras, Dispositivo = T_Code.Mov, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Space, botaoJoy = BotoesJoystick.Bolinha, direcao = Direcao.EmFreio, Dispositivo = T_Code.Mov, PararAoSoltar = true },
|
|
new DeParaComandos() { key = Keys.Subtract, botaoJoy = BotoesJoystick.L1, Dispositivo = T_Code.Mov, PararAoSoltar = false },
|
|
new DeParaComandos() { key = Keys.Add, botaoJoy = BotoesJoystick.R1, Dispositivo = T_Code.Mov, PararAoSoltar = false },
|
|
|
|
new DeParaComandos() { key = Keys.D1, botaoJoy = BotoesJoystick.Touchpad, Dispositivo = T_Code.Atu, PararAoSoltar = true, IDcontrolar = "B01" },
|
|
new DeParaComandos() { key = Keys.D2, botaoJoy = BotoesJoystick.Touchpad, Dispositivo = T_Code.Atu, PararAoSoltar = true, IDcontrolar = "B02" },
|
|
new DeParaComandos() { key = Keys.D3, botaoJoy = BotoesJoystick.Touchpad, Dispositivo = T_Code.Atu, PararAoSoltar = true, IDcontrolar = "B03" },
|
|
new DeParaComandos() { key = Keys.D4, botaoJoy = BotoesJoystick.Touchpad, Dispositivo = T_Code.Atu, PararAoSoltar = true, IDcontrolar = "B04" },
|
|
new DeParaComandos() { key = Keys.D5, botaoJoy = BotoesJoystick.Touchpad, Dispositivo = T_Code.Atu, PararAoSoltar = true, IDcontrolar = "B05" },
|
|
new DeParaComandos() { key = Keys.D6, botaoJoy = BotoesJoystick.Touchpad, Dispositivo = T_Code.Atu, PararAoSoltar = true, IDcontrolar = "B06" },
|
|
new DeParaComandos() { key = Keys.D7, botaoJoy = BotoesJoystick.Touchpad, Dispositivo = T_Code.Atu, PararAoSoltar = true, IDcontrolar = "B07" },
|
|
};
|
|
public static List<BotoesJoystick> BotoesJoyPressionados = new List<BotoesJoystick>() { };
|
|
private static readonly object _syncJoystick = new object();
|
|
private static readonly SemaphoreSlim _tickGate = new SemaphoreSlim(1, 1);
|
|
private static readonly HashSet<BotoesJoystick> _estadoBotoes = new HashSet<BotoesJoystick>();
|
|
private static DateTime _ultimaTentativaReconexao = DateTime.MinValue;
|
|
private static DateTime _ultimoEnvioMov = DateTime.MinValue;
|
|
private static DateTime _ultimoEnvioDir = DateTime.MinValue;
|
|
private static Direcao _ultimaDirecaoMovEnviada = Direcao.Parado;
|
|
private static double _ultimoValorMovEnviado = double.NaN;
|
|
private static double _ultimoAnguloDirEnviado = double.NaN;
|
|
private const int IntervaloReconexaoMs = 2000;
|
|
private const int HeartbeatComandoMs = 300;
|
|
private const double VariacaoMinimaMov = 0.25;
|
|
private const double VariacaoMinimaDir = 0.20;
|
|
public static List<TipoMovimentoDirecional> MovimentosCombinados = new List<TipoMovimentoDirecional>()
|
|
{
|
|
TipoMovimentoDirecional.MovimentoLateral,
|
|
TipoMovimentoDirecional.RotacionarNoEixo
|
|
};
|
|
|
|
public static Direcao UltimaDirecao = Direcao.Parado;
|
|
public static bool Pressionado = false;
|
|
public static List<IDispositivosService> DispCon;
|
|
|
|
public static AsyncTaskTimerModel tmrJoystick;
|
|
|
|
public static void IniciarRotinas()
|
|
{
|
|
tmrJoystick = new AsyncTaskTimerModel("tmrJoystick", tmrJoystick_Tick, 100);
|
|
tmrJoystick.Start();
|
|
}
|
|
|
|
public static void AtualizaDispositivo()
|
|
{
|
|
Func<bool> funcAtt = new Func<bool>(() =>
|
|
{
|
|
DispCon = Variaveis.DispositivosConectados.Where(x => x.Dados.ConexaoAtiva).ToList();
|
|
frmInstancial.frmJoystick.lblDispositivo.Text = "Dispositivos: " + (DispCon.Count == 0 ? "N/A" : string.Join(", ", DispCon.Select(x => x._Descricao + " (" + Enum.GetName(typeof(T_Code), x.Dispositivo) + ")").ToArray()));
|
|
|
|
AtualizarListaJoysticks();
|
|
|
|
return true;
|
|
});
|
|
FuncoesGlobais.ExecutarMetodoComVerificacaoCrossThread(frmInstancial.frmJoystick.lblDispositivo, funcAtt);
|
|
}
|
|
|
|
public static void InicializarJoysticksConectados()
|
|
{
|
|
lock (_syncJoystick)
|
|
{
|
|
var directInput = new DirectInput();
|
|
var nomes = new List<string>();
|
|
|
|
// Find a Joystick Guid
|
|
var joystickGuid = Guid.Empty;
|
|
|
|
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad, DeviceEnumerationFlags.AllDevices))
|
|
{
|
|
joystickGuid = deviceInstance.InstanceGuid;
|
|
nomes.Add(deviceInstance.InstanceName);
|
|
}
|
|
|
|
// If Gamepad not found, look for a Joystick
|
|
if (joystickGuid == Guid.Empty)
|
|
{
|
|
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices))
|
|
{
|
|
joystickGuid = deviceInstance.InstanceGuid;
|
|
nomes.Add(deviceInstance.InstanceName);
|
|
}
|
|
}
|
|
|
|
// If Joystick not found, throws an error
|
|
if (joystickGuid == Guid.Empty)
|
|
{
|
|
JoysticksConectados = nomes;
|
|
DesconectarJoystickInterno();
|
|
return;
|
|
}
|
|
|
|
// Instantiate the joystick
|
|
DesconectarJoystickInterno();
|
|
JoystickConectado = new Joystick(directInput, joystickGuid);
|
|
JoysticksConectados = nomes;
|
|
|
|
// Query all suported ForceFeedback effects
|
|
var allEffects = JoystickConectado.GetEffects();
|
|
foreach (var effectInfo in allEffects)
|
|
{
|
|
Console.WriteLine("Effect available {0}", effectInfo.Name);
|
|
}
|
|
|
|
// Set BufferSize in order to use buffered data.
|
|
JoystickConectado.Acquire();
|
|
|
|
|
|
if (JoystickConectado != null)
|
|
{
|
|
tmrJoystick?.Start();
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void AtualizarListaJoysticks()
|
|
{
|
|
try
|
|
{
|
|
using (var directInput = new DirectInput())
|
|
{
|
|
var nomes = directInput.GetDevices(DeviceType.Gamepad, DeviceEnumerationFlags.AllDevices)
|
|
.Concat(directInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices))
|
|
.Select(x => x.InstanceName)
|
|
.Distinct()
|
|
.ToList();
|
|
lock (_syncJoystick) JoysticksConectados = nomes;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Variaveis.MostrarLog($"[GeneralJoystick] Falha ao listar joysticks: {ex.GetType().Name}: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static void DesconectarJoystickInterno()
|
|
{
|
|
var antigo = JoystickConectado;
|
|
JoystickConectado = null;
|
|
_estadoBotoes.Clear();
|
|
BotoesJoyPressionados.Clear();
|
|
if (antigo == null) return;
|
|
try { antigo.Unacquire(); } catch { }
|
|
try { antigo.Dispose(); } catch { }
|
|
}
|
|
|
|
private static bool ComparaPosicaoAnalogico(int Atual, ComparativoAnalogico Comparativo)
|
|
{
|
|
int Meio = MaximoAnalogico / 2;
|
|
bool Pressionado = false;
|
|
|
|
if (Comparativo == ComparativoAnalogico.Igual)
|
|
{
|
|
Pressionado = Atual >= (Meio - MargemAnalogico) && Atual <= (Meio + MargemAnalogico);
|
|
}
|
|
else if (Comparativo == ComparativoAnalogico.Maior)
|
|
{
|
|
Pressionado = Atual >= (Meio + MargemAnalogico);
|
|
}
|
|
else if (Comparativo == ComparativoAnalogico.Menor)
|
|
{
|
|
Pressionado = Atual <= (Meio - MargemAnalogico);
|
|
}
|
|
|
|
return Pressionado;
|
|
}
|
|
|
|
private static double DeParaAnanlogico(double Valor, double DeMin, double DeMax, double ParaMin, double ParaMax)
|
|
{
|
|
if (Valor < DeMin)
|
|
{
|
|
Valor = DeMin;
|
|
}
|
|
else if (Valor > DeMax)
|
|
{
|
|
Valor = DeMax;
|
|
}
|
|
|
|
double scale = (Valor - DeMin) / (DeMax - DeMin);
|
|
double mappedValue = scale * (ParaMax - ParaMin) + ParaMin;
|
|
|
|
return mappedValue;
|
|
}
|
|
|
|
private static async Task tmrJoystick_Tick()
|
|
{
|
|
await ProcessarEstadoAtualJoystick();
|
|
return;
|
|
#pragma warning disable CS0162
|
|
if (JoystickConectado == null)
|
|
{
|
|
return;
|
|
}
|
|
JoystickUpdate[] datas;
|
|
try
|
|
{
|
|
JoystickConectado.Poll();
|
|
datas = JoystickConectado.GetBufferedData();
|
|
}
|
|
catch
|
|
{
|
|
//EnviaComandoMotor(Keys.Escape, T_Code.Mov, ForcarComando: true);
|
|
//EnviaComandoMotor(Keys.Escape, T_Code.Dir, ForcarComando: true);
|
|
ProcessarDadosControle(BotoesJoystick.Xis, true);
|
|
ProcessarDadosControle(BotoesJoystick.SEsquerda, true);
|
|
AtualizaDispositivo();
|
|
return;
|
|
}
|
|
|
|
|
|
List<BotoesPressionadosValores> _botoesPressionados = new List<BotoesPressionadosValores>();
|
|
List<BotoesJoystick> _botoesSoltos = new List<BotoesJoystick>();
|
|
|
|
foreach (var state in datas)
|
|
{
|
|
//Console.WriteLine(state);
|
|
if (state.Offset == JoystickOffset.PointOfViewControllers0)
|
|
{
|
|
if (state.Value == -1)
|
|
{
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.SBaixo))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.SBaixo);
|
|
}
|
|
else if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.SCima))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.SCima);
|
|
}
|
|
else if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.SEsquerda))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.SEsquerda);
|
|
}
|
|
else if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.SDireita))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.SDireita);
|
|
}
|
|
}
|
|
else if (state.Value == 0)
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.SCima, valor = state.Value });
|
|
}
|
|
else if (state.Value == 9000)
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.SDireita, valor = state.Value });
|
|
}
|
|
else if (state.Value == 18000)
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.SBaixo, valor = state.Value });
|
|
}
|
|
else if (state.Value == 27000)
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.SEsquerda, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Z)
|
|
{
|
|
if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Igual))
|
|
{
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.ADDireita))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.ADDireita);
|
|
}
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.ADEsquerda))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.ADEsquerda);
|
|
}
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Maior))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.ADDireita, valor = state.Value });
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Menor))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.ADEsquerda, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.X)
|
|
{
|
|
if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Igual))
|
|
{
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.AEEsquerda))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.AEEsquerda);
|
|
}
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.AEDireita))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.AEDireita);
|
|
}
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Maior))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.AEDireita, valor = state.Value });
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Menor))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.AEEsquerda, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Y)
|
|
{
|
|
if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Igual))
|
|
{
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.AECima))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.AECima);
|
|
}
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.AEBaixo))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.AEBaixo);
|
|
}
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Maior))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.AEBaixo, valor = state.Value });
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Menor))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.AECima, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.RotationX)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.L2A))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.L2A);
|
|
}
|
|
}
|
|
else if (state.Value > 0)
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.L2A, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.RotationY)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.R2A))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.R2A);
|
|
}
|
|
}
|
|
else if (state.Value > 0)
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.R2A, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.RotationZ)
|
|
{
|
|
if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Igual))
|
|
{
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.ADCima))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.ADCima);
|
|
}
|
|
if (BotoesJoyPressionados.Any(x => x == BotoesJoystick.ADBaixo))
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.ADBaixo);
|
|
}
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Maior))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.ADBaixo, valor = state.Value });
|
|
}
|
|
else if (ComparaPosicaoAnalogico(state.Value, ComparativoAnalogico.Menor))
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.ADCima, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons0)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.Quadrado);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.Quadrado, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons1)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.Xis);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.Xis, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons2)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.Bolinha);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.Bolinha, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons3)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.Triangulo);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.Triangulo, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons4)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.L1);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.L1, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons5)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.R1);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.R1, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons6)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.L2);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.L2, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons7)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.R2);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.R2, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons8)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.Share);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.Share, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons9)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.Options);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.Options, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons10)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.L3);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.L3, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons11)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.R3);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.R3, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons12)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.PS);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.PS, valor = state.Value });
|
|
}
|
|
}
|
|
else if (state.Offset == JoystickOffset.Buttons13)
|
|
{
|
|
if (state.Value == 0)
|
|
{
|
|
_botoesSoltos.Add(BotoesJoystick.Touchpad);
|
|
}
|
|
else
|
|
{
|
|
_botoesPressionados.Add(new BotoesPressionadosValores() { botao = BotoesJoystick.Touchpad, valor = state.Value });
|
|
}
|
|
}
|
|
}
|
|
|
|
var botoes_pressionados_g = _botoesPressionados
|
|
.GroupBy(x => x.botao)
|
|
.Select(x => new {
|
|
botao = x.Key,
|
|
dados = x
|
|
})
|
|
.ToList();
|
|
botoes_pressionados_g.ForEach(botao =>
|
|
{
|
|
ProcessarDadosControle(botao.botao, false, valorJoy: botao.dados?.LastOrDefault()?.valor ?? 0, ForcarComando: true);
|
|
//Console.WriteLine($"Botao pressionado: {botao.botao}, Valor: {string.Join(", ", botao.dados.Select(y => y.valor))}");
|
|
BotoesJoyPressionados.Add(botao.botao);
|
|
});
|
|
_botoesSoltos.ForEach(botao =>
|
|
{
|
|
ProcessarDadosControle(botao, true, valorJoy: 0, ForcarComando: true);
|
|
//Console.WriteLine($"Botao solto: {botao}");
|
|
BotoesJoyPressionados.Remove(botao);
|
|
});
|
|
#pragma warning restore CS0162
|
|
}
|
|
|
|
private static async Task ProcessarEstadoAtualJoystick()
|
|
{
|
|
if (!await _tickGate.WaitAsync(0)) return;
|
|
try
|
|
{
|
|
Joystick joystick;
|
|
lock (_syncJoystick) joystick = JoystickConectado;
|
|
|
|
if (joystick == null)
|
|
{
|
|
TentarReconectar();
|
|
return;
|
|
}
|
|
|
|
JoystickState estado;
|
|
try
|
|
{
|
|
joystick.Poll();
|
|
estado = joystick.GetCurrentState();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Variaveis.MostrarLog($"[GeneralJoystick] Controle desconectado/falha de leitura: {ex.GetType().Name}: {ex.Message}");
|
|
PararCarroControle("Perda de comunicação com o joystick");
|
|
lock (_syncJoystick) DesconectarJoystickInterno();
|
|
TentarReconectar();
|
|
return;
|
|
}
|
|
|
|
AtualizarEstadoFisico(estado);
|
|
ResolverMovimento(estado);
|
|
ResolverDirecional(estado);
|
|
ResolverComandosDeBorda();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Variaveis.MostrarLog($"[GeneralJoystick] Erro inesperado no tick: {ex.GetType().Name}: {ex.Message}");
|
|
PararCarroControle("Falha interna no processamento do joystick");
|
|
}
|
|
finally
|
|
{
|
|
_tickGate.Release();
|
|
}
|
|
}
|
|
|
|
private static void TentarReconectar()
|
|
{
|
|
if ((DateTime.Now - _ultimaTentativaReconexao).TotalMilliseconds < IntervaloReconexaoMs) return;
|
|
_ultimaTentativaReconexao = DateTime.Now;
|
|
try { InicializarJoysticksConectados(); }
|
|
catch (Exception ex)
|
|
{
|
|
Variaveis.MostrarLog($"[GeneralJoystick] Reconexão falhou: {ex.GetType().Name}: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private static void AtualizarEstadoFisico(JoystickState s)
|
|
{
|
|
var anterior = new HashSet<BotoesJoystick>(_estadoBotoes);
|
|
_estadoBotoes.Clear();
|
|
var buttons = s.Buttons ?? new bool[0];
|
|
Action<int, BotoesJoystick> addButton = (i, b) => { if (i < buttons.Length && buttons[i]) _estadoBotoes.Add(b); };
|
|
addButton(0, BotoesJoystick.Quadrado); addButton(1, BotoesJoystick.Xis);
|
|
addButton(2, BotoesJoystick.Bolinha); addButton(3, BotoesJoystick.Triangulo);
|
|
addButton(4, BotoesJoystick.L1); addButton(5, BotoesJoystick.R1);
|
|
addButton(6, BotoesJoystick.L2); addButton(7, BotoesJoystick.R2);
|
|
addButton(8, BotoesJoystick.Share); addButton(9, BotoesJoystick.Options);
|
|
addButton(10, BotoesJoystick.L3); addButton(11, BotoesJoystick.R3);
|
|
addButton(12, BotoesJoystick.PS); addButton(13, BotoesJoystick.Touchpad);
|
|
|
|
if (s.RotationX > MargemAnalogico) _estadoBotoes.Add(BotoesJoystick.L2A);
|
|
if (s.RotationY > MargemAnalogico) _estadoBotoes.Add(BotoesJoystick.R2A);
|
|
if (s.X < MaximoAnalogico / 2 - 3000) _estadoBotoes.Add(BotoesJoystick.AEEsquerda);
|
|
if (s.X > MaximoAnalogico / 2 + 3000) _estadoBotoes.Add(BotoesJoystick.AEDireita);
|
|
|
|
int pov = s.PointOfViewControllers != null && s.PointOfViewControllers.Length > 0 ? s.PointOfViewControllers[0] : -1;
|
|
if (pov == 27000) _estadoBotoes.Add(BotoesJoystick.SEsquerda);
|
|
if (pov == 9000) _estadoBotoes.Add(BotoesJoystick.SDireita);
|
|
if (pov == 0) _estadoBotoes.Add(BotoesJoystick.SCima);
|
|
if (pov == 18000) _estadoBotoes.Add(BotoesJoystick.SBaixo);
|
|
|
|
_botoesPressionadosNoTick = new HashSet<BotoesJoystick>(_estadoBotoes.Except(anterior));
|
|
_botoesSoltosNoTick = new HashSet<BotoesJoystick>(anterior.Except(_estadoBotoes));
|
|
BotoesJoyPressionados = _estadoBotoes.ToList();
|
|
}
|
|
|
|
private static HashSet<BotoesJoystick> _botoesPressionadosNoTick = new HashSet<BotoesJoystick>();
|
|
private static HashSet<BotoesJoystick> _botoesSoltosNoTick = new HashSet<BotoesJoystick>();
|
|
|
|
private static void ResolverMovimento(JoystickState s)
|
|
{
|
|
bool frenteDigital = _estadoBotoes.Contains(BotoesJoystick.Xis);
|
|
bool trasDigital = _estadoBotoes.Contains(BotoesJoystick.Quadrado);
|
|
double frenteAnalogico = s.RotationY > MargemAnalogico ? s.RotationY : 0;
|
|
double trasAnalogico = s.RotationX > MargemAnalogico ? s.RotationX : 0;
|
|
bool conflito = (frenteDigital || frenteAnalogico > 0) && (trasDigital || trasAnalogico > 0);
|
|
|
|
BotoesJoystick botao;
|
|
double valor;
|
|
Direcao direcao;
|
|
if (conflito)
|
|
{
|
|
botao = BotoesJoystick.Xis; valor = 0; direcao = Direcao.Parado;
|
|
RegistrarMotivoManual("Comandos simultâneos de frente e ré; movimento neutralizado");
|
|
}
|
|
else if (frenteAnalogico > 0) { botao = BotoesJoystick.R2A; valor = frenteAnalogico; direcao = Direcao.Frente; }
|
|
else if (trasAnalogico > 0) { botao = BotoesJoystick.L2A; valor = trasAnalogico; direcao = Direcao.Tras; }
|
|
else if (frenteDigital) { botao = BotoesJoystick.Xis; valor = MaximoAnalogico; direcao = Direcao.Frente; }
|
|
else if (trasDigital) { botao = BotoesJoystick.Quadrado; valor = MaximoAnalogico; direcao = Direcao.Tras; }
|
|
else { botao = BotoesJoystick.Xis; valor = 0; direcao = Direcao.Parado; }
|
|
|
|
var cmd = DeParaComandos.FirstOrDefault(x => x.botaoJoy == botao)?.Clone();
|
|
if (cmd == null) return;
|
|
cmd.CalcularValor(direcao == Direcao.Parado, valorJoy: valor);
|
|
bool mudou = direcao != _ultimaDirecaoMovEnviada || double.IsNaN(_ultimoValorMovEnviado) || Math.Abs(cmd.ValorAplicar - _ultimoValorMovEnviado) >= VariacaoMinimaMov;
|
|
bool combinado = MovimentosCombinados.Contains(Variaveis.OperacaoEmAndamento.Controle.TipoMovimento);
|
|
bool heartbeat = !combinado && (DateTime.Now - _ultimoEnvioDir).TotalMilliseconds >= HeartbeatComandoMs;
|
|
if (!mudou && !heartbeat) return;
|
|
EnviarComandoMotorAtualizado(cmd, ForcarComando: false);
|
|
_ultimaDirecaoMovEnviada = direcao; _ultimoValorMovEnviado = cmd.ValorAplicar; _ultimoEnvioMov = DateTime.Now;
|
|
}
|
|
|
|
private static void ResolverDirecional(JoystickState s)
|
|
{
|
|
bool esqDigital = _estadoBotoes.Contains(BotoesJoystick.SEsquerda);
|
|
bool dirDigital = _estadoBotoes.Contains(BotoesJoystick.SDireita);
|
|
BotoesJoystick botao = BotoesJoystick.SEsquerda;
|
|
double valor = 0;
|
|
bool solto = true;
|
|
if (esqDigital ^ dirDigital) { botao = esqDigital ? BotoesJoystick.SEsquerda : BotoesJoystick.SDireita; solto = false; }
|
|
else if (_estadoBotoes.Contains(BotoesJoystick.AEEsquerda)) { botao = BotoesJoystick.AEEsquerda; valor = s.X; solto = false; }
|
|
else if (_estadoBotoes.Contains(BotoesJoystick.AEDireita)) { botao = BotoesJoystick.AEDireita; valor = s.X; solto = false; }
|
|
|
|
var cmd = DeParaComandos.FirstOrDefault(x => x.botaoJoy == botao)?.Clone();
|
|
if (cmd == null) return;
|
|
cmd.CalcularValor(solto, valorJoy: valor);
|
|
bool mudou = double.IsNaN(_ultimoAnguloDirEnviado) || Math.Abs(cmd.ValorAplicar - _ultimoAnguloDirEnviado) >= VariacaoMinimaDir;
|
|
bool heartbeat = (DateTime.Now - _ultimoEnvioDir).TotalMilliseconds >= HeartbeatComandoMs;
|
|
if (!mudou && !heartbeat) return;
|
|
EnviarComandoMotorAtualizado(cmd, ForcarComando: false);
|
|
_ultimoAnguloDirEnviado = cmd.ValorAplicar; _ultimoEnvioDir = DateTime.Now;
|
|
}
|
|
|
|
private static void ResolverComandosDeBorda()
|
|
{
|
|
foreach (var b in _botoesPressionadosNoTick.Where(x => x == BotoesJoystick.L1 || x == BotoesJoystick.R1 || x == BotoesJoystick.R3 || x == BotoesJoystick.Bolinha))
|
|
ProcessarDadosControle(b, false, ForcarComando: false);
|
|
if (_botoesSoltosNoTick.Contains(BotoesJoystick.Bolinha))
|
|
ProcessarDadosControle(BotoesJoystick.Bolinha, true, ForcarComando: false);
|
|
}
|
|
|
|
public static void ProcessarDadosControle(BotoesJoystick botao, bool solto, Keys? key = null, double? valorJoy = null, double? valorDesejado = null, string ID = "", bool ForcarComando = false)
|
|
{
|
|
var comando = DeParaComandos.FirstOrDefault(x => x.botaoJoy == botao && (key != null ? x.key == key : true))?.Clone();
|
|
comando?.CalcularValor(solto, valorJoy: valorJoy, valorDesejado: valorDesejado);
|
|
|
|
if (comando?.Dispositivo == T_Code.Dir || comando?.Dispositivo == T_Code.Mov)
|
|
{
|
|
EnviarComandoMotorAtualizado(comando, ID: ID, ForcarComando: ForcarComando);
|
|
}
|
|
else if (comando?.Dispositivo == T_Code.Atu)
|
|
{
|
|
EnviarComandoAtuadorAtualizado(comando, ForcarComando: ForcarComando);
|
|
}
|
|
}
|
|
|
|
public static void PararCarroControle(string motivo)
|
|
{
|
|
var op = Variaveis.OperacaoEmAndamento;
|
|
var controle = op?.Controle;
|
|
var pControle = op?.Parametros?.Controle;
|
|
|
|
if (controle == null)
|
|
return;
|
|
|
|
controle.MotivosManual.Clear();
|
|
controle.MotivosManual.Add(motivo);
|
|
|
|
var movimento = controle.TiposControle?.FirstOrDefault(x => x?.Tipo == T_Code.Mov);
|
|
|
|
if (movimento?.DirecaoAtual != Direcao.Parado)
|
|
{
|
|
Variaveis.MostrarLog($"[GeneralJoystick] Parada MOV solicitada. Motivo: {motivo}");
|
|
|
|
ProcessarDadosControle(BotoesJoystick.Xis, true, ForcarComando: true);
|
|
|
|
controle.MotivosManual.Add("Comando de parada MOV enviado");
|
|
|
|
if (pControle?.FrenagemAutomaticaAoParar == true)
|
|
{
|
|
ProcessarDadosControle(BotoesJoystick.Bolinha, false, ForcarComando: true);
|
|
|
|
controle.MotivosManual.Add("Comando de freio enviado");
|
|
}
|
|
}
|
|
|
|
var direcional = controle.TiposControle?.FirstOrDefault(x => x?.Tipo == T_Code.Dir);
|
|
|
|
if (direcional?.UltimaDirecao != Direcao.Parado)
|
|
{
|
|
ProcessarDadosControle(BotoesJoystick.SEsquerda, true, ForcarComando: true);
|
|
|
|
controle.MotivosManual.Add("Comando de parada DIR enviado");
|
|
}
|
|
}
|
|
|
|
private static void EnviarComandoMotorAtualizado(DeParaComandos Comando, string ID = "", bool ForcarComando = false)
|
|
{
|
|
var op = Variaveis.OperacaoEmAndamento;
|
|
|
|
if (op?.Controle == null || op.Parametros?.Controle == null || op.Sensoriamento?.Operacao == null || Comando == null)
|
|
return;
|
|
|
|
bool solicitacaoAtiva = Comando.ValorAplicar != 0 || Comando.EstadoAplicar ||
|
|
Comando.direcao == Direcao.Referenciar;
|
|
|
|
bool bloqueioAutomatico =
|
|
!ForcarComando &&
|
|
((op.Parametros.Controle.MovimentoAutomatico && Comando.Dispositivo == T_Code.Mov) ||
|
|
(op.Parametros.Controle.DirecionalAutomatico && Comando.Dispositivo == T_Code.Dir));
|
|
|
|
bool bloqueioCalibragem =
|
|
op.CalibrandoRuntime;
|
|
|
|
bool bloqueioOperacional =
|
|
!op.Sensoriamento.Operacao.OperacaoLiberada ||
|
|
!op.Sensoriamento.Operacao.OperacaoIniciada;
|
|
|
|
bool comandoParada =
|
|
Comando.ValorAplicar == 0;
|
|
|
|
bool bloqueioSonar = !comandoParada && !VerificaComandoValidoSonar(Comando.key);
|
|
|
|
bool deveInterromper =
|
|
bloqueioAutomatico ||
|
|
(bloqueioCalibragem && !comandoParada) ||
|
|
bloqueioSonar ||
|
|
(!ForcarComando && bloqueioOperacional);
|
|
|
|
var _Controle = op.Controle;
|
|
|
|
if (deveInterromper)
|
|
{
|
|
// MotivosManual descreve somente uma tentativa ativa barrada.
|
|
// Solturas, neutralizações e comandos de parada não sobrescrevem o diagnóstico.
|
|
if (!solicitacaoAtiva) return;
|
|
|
|
_Controle.MotivosManual.Clear();
|
|
|
|
if (bloqueioAutomatico)
|
|
_Controle.MotivosManual.Add("Controle em modo automático");
|
|
|
|
if (bloqueioCalibragem && !comandoParada)
|
|
_Controle.MotivosManual.Add("Calibragem em andamento");
|
|
|
|
if (!ForcarComando && bloqueioOperacional)
|
|
{
|
|
_Controle.MotivosManual.Add(
|
|
$"Operação iniciada: {op.Sensoriamento.Operacao.OperacaoIniciada}, " +
|
|
$"Operação liberada: {op.Sensoriamento.Operacao.OperacaoLiberada}, " +
|
|
$"Erro operação liberada: {op.Sensoriamento.Operacao.ErroOperacaoLiberada}"
|
|
);
|
|
}
|
|
|
|
if (bloqueioSonar)
|
|
_Controle.MotivosManual.Add("Visual Worker impediu o comando");
|
|
|
|
return;
|
|
}
|
|
|
|
// Uma solicitação ativa aceita invalida imediatamente qualquer bloqueio antigo.
|
|
if (solicitacaoAtiva)
|
|
_Controle.MotivosManual.Clear();
|
|
|
|
if (Comando.direcao.HasValue && _Controle.TiposControle.Any(x => x.Tipo == Comando.Dispositivo))
|
|
_Controle.TiposControle.FirstOrDefault(x => x.Tipo == Comando.Dispositivo).DirecaoAtual = Comando.direcao.Value;
|
|
|
|
for (int i = 0; i < 1; i++)
|
|
{
|
|
switch (Comando.Dispositivo)
|
|
{
|
|
case T_Code.Mov:
|
|
if (_Controle.TipoMovimento == TipoMovimentoDirecional.RotacionarNoEixo)
|
|
return;
|
|
|
|
_Controle.PercentualVelocidadeSP = Comando.ValorAplicar;
|
|
_Controle.EmFreio = Comando.EstadoAplicar;
|
|
op.AtualizarDadosControle(ForcarComando, new List<T_Code>() { Comando.Dispositivo });
|
|
break;
|
|
case T_Code.Dir:
|
|
if (MovimentosCombinados.Contains(_Controle.TipoMovimento))
|
|
{
|
|
Task.Run(async () => await op.DispMvd.Dados.ExecutarMovimentoDirecionalCombinado(Comando.direcao.Value));
|
|
}
|
|
else if (Comando.direcao == Direcao.Referenciar)
|
|
{
|
|
List<string> modsControlar = (!string.IsNullOrEmpty(ID)) ? new List<string>() { ID } : null;
|
|
Task.Run(async () => await op.DispMvd.Dados.RealizarReferenciamentoDirecional(ModsReferenciar: modsControlar));
|
|
}
|
|
else
|
|
{
|
|
_Controle.Angulo = Comando.ValorAplicar;
|
|
op.AtualizarDadosControle(ForcarComando, new List<T_Code>() { Comando.Dispositivo });
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_Controle.TiposControle.Any(x => x.Tipo == Comando.Dispositivo))
|
|
AtualizaConsole(_Controle.TiposControle.FirstOrDefault(x => x.Tipo == Comando.Dispositivo).DirecaoAtual.ToString());
|
|
}
|
|
|
|
private static void RegistrarMotivoManual(string motivo)
|
|
{
|
|
var motivos = Variaveis.OperacaoEmAndamento?.Controle?.MotivosManual;
|
|
if (motivos == null) return;
|
|
motivos.Clear();
|
|
motivos.Add(motivo);
|
|
Variaveis.MostrarLog($"[GeneralJoystick] Comando manual não aplicado. Motivo: {motivo}");
|
|
}
|
|
|
|
public static void RemoverMotivoParada(string motivo)
|
|
{
|
|
var motivos = Variaveis.OperacaoEmAndamento?.Controle?.MotivosManual;
|
|
if (motivos == null) return;
|
|
motivos.Remove(motivo);
|
|
Variaveis.MostrarLog($"[GeneralJoystick] Comando manual não aplicado. Motivo: {motivo}");
|
|
}
|
|
|
|
public static void EnviarComandoAtuadorAtualizado(DeParaComandos Comando, bool ForcarComando = false)
|
|
{
|
|
var op = Variaveis.OperacaoEmAndamento;
|
|
|
|
bool bloqueioAutomatico = op.Parametros.Controle.PulverizadorAutomatico;
|
|
|
|
bool bloqueioOperacional =
|
|
op.Sensoriamento.Operacao.Calibrando ||
|
|
!op.Sensoriamento.Operacao.OperacaoLiberada ||
|
|
!op.Sensoriamento.Operacao.OperacaoIniciada;
|
|
|
|
bool deveInterromper =
|
|
bloqueioAutomatico ||
|
|
(!ForcarComando && bloqueioOperacional);
|
|
|
|
if (deveInterromper) return;
|
|
|
|
var _Controle = op.Controle;
|
|
var tipoControle = _Controle?.TiposControle?.FirstOrDefault(x => x?.Tipo == Comando.Dispositivo);
|
|
|
|
var bico = op.DispAtu?.Dados?.BicosPulverizadores?.FirstOrDefault(x => x.ID == Comando.IDcontrolar);
|
|
var bomba = op.DispAtu?.Dados?.BombasPressurizadoras?.FirstOrDefault(x => x.ID == Comando.IDcontrolar);
|
|
S_Code comp = bico?.Componente ?? bomba?.Componente ?? S_Code.sVZO;
|
|
|
|
switch (comp)
|
|
{
|
|
case S_Code.sBIC:
|
|
op?.DispAtu?.Dados?.EnviarComandoFisicoBico(
|
|
bico,
|
|
Comando.Comando,
|
|
setarControle: true,
|
|
status: Comando.EstadoAplicar
|
|
);
|
|
return;
|
|
|
|
case S_Code.sBMB:
|
|
op?.DispAtu?.Dados?.EnviarComandoFisicoBomba(
|
|
bomba,
|
|
Comando.Comando,
|
|
setarControle: true,
|
|
status: Comando.EstadoAplicar
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
|
|
public static void EnviarComandoSensoriamento(S_Code Componente, string ID, dynamic Status) //, bool Forcar = false
|
|
{
|
|
var op = Variaveis.OperacaoEmAndamento;
|
|
|
|
var DispSen = op.DispSen;
|
|
if (!DispSen.Dados.Conectado)
|
|
return;
|
|
|
|
if (false) // !Forcar
|
|
{
|
|
bool componente_em_uso = op.Parametros.ModulosMandatorios.Any(x => x.Dispositivo == T_Code.Sen && (x.ComponentesEmUso?.ContainsKey(ID) ?? false) && x.ComponentesEmUso[ID].Item2);
|
|
if (!componente_em_uso)
|
|
{
|
|
// Impede execucao de comandos que liguem componentes quando estiver marcado para nao utilizar
|
|
if (Componente == S_Code.sRLE && ((Estado)Status) == Estado.Ligado) return;
|
|
if (Componente == S_Code.sSRV && ((int)Status) > 0) return;
|
|
}
|
|
}
|
|
|
|
int id_num = -1;
|
|
CanMessagePosicaoDados posicao = CanMessagePosicaoDados.Command1;
|
|
byte[] data = null;
|
|
|
|
switch (Componente)
|
|
{
|
|
case S_Code.sMOD:
|
|
if (DispSen?.Dados != null && Status == true)
|
|
{
|
|
(id_num, posicao, data) = DispSen.Dados.ProtocoloComandoReset();
|
|
}
|
|
break;
|
|
case S_Code.sLED:
|
|
var Sinaleiro = DispSen?.Dados?.Sinaleiros?.FirstOrDefault(x => x.ID == ID && x.Inicializado);
|
|
if (Sinaleiro != null)
|
|
{
|
|
Sinaleiro.Comportamento = (SensorSinaleiroComportamentoModel)Status;
|
|
(id_num, posicao, data) = Sinaleiro.ProtocoloComando();
|
|
Sinaleiro.UltimoComandoEnviado = DateTime.Now;
|
|
Sinaleiro.UltimoComportamentoDesejado = (SensorSinaleiroComportamentoModel)Status;
|
|
}
|
|
break;
|
|
case S_Code.sRLE:
|
|
var Rele = DispSen?.Dados?.Reles?.FirstOrDefault(x => x.ID == ID && x.Inicializado);
|
|
if (Rele != null)
|
|
{
|
|
Rele.StatusControle = (Estado)Status;
|
|
(id_num, posicao, data) = Rele.ProtocoloComando();
|
|
Rele.UltimoComandoEnviado = DateTime.Now;
|
|
Rele.UltimoEstadoDesejado = (Estado)Status;
|
|
}
|
|
break;
|
|
case S_Code.sSRV:
|
|
var ServoFreio = DispSen?.Dados?.Servos?.FirstOrDefault(x => x.ID == ID && x.Inicializado);
|
|
if (ServoFreio != null)
|
|
{
|
|
ServoFreio._AnguloControle = (int)Status;
|
|
(id_num, posicao, data) = ServoFreio.ProtocoloComando();
|
|
ServoFreio.UltimoComandoEnviado = DateTime.Now;
|
|
ServoFreio.UltimoAnguloDesejado = (int)Status;
|
|
}
|
|
break;
|
|
}
|
|
|
|
DispSen.AdicionarMensagemFila(id_num, posicao, posicao, data, false);
|
|
}
|
|
|
|
private static void AtualizaConsole(string Mensagem)
|
|
{
|
|
if (frmInstancial.frmJoystick.lblConsole.InvokeRequired)
|
|
{
|
|
frmInstancial.frmJoystick.lblConsole.Invoke((MethodInvoker)delegate
|
|
{
|
|
frmInstancial.frmJoystick.lblConsole.Text = Mensagem;
|
|
});
|
|
}
|
|
else
|
|
{
|
|
frmInstancial.frmJoystick.lblConsole.Text = Mensagem;
|
|
}
|
|
}
|
|
|
|
private static bool VerificaComandoValidoSonar(Keys Comando)
|
|
{
|
|
List<Keys> ComandosImpedidos = new List<Keys>();
|
|
var Sonar = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual;
|
|
var DeveParar = Sonar?.StatusValido == true && Sonar?.Resumo?.DeveParar == true;
|
|
if (DeveParar)
|
|
{
|
|
ComandosImpedidos.Add(Keys.Up);
|
|
}
|
|
return !ComandosImpedidos.Any(x => x == Comando);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public class DeParaComandos
|
|
{
|
|
public BotoesJoystick botaoJoy { get; set; }
|
|
public Keys key { get; set; }
|
|
public CanMessagePosicaoDados Comando { get; set; } = CanMessagePosicaoDados.Command1;
|
|
public T_Code Dispositivo { get; set; }
|
|
public bool PararAoSoltar { get; set; }
|
|
public string IDcontrolar { get; set; }
|
|
public Direcao? direcao { get; set; }
|
|
public double ValorAplicar { get; set; }
|
|
public bool EstadoAplicar { get; set; }
|
|
|
|
public void CalcularValor(bool solto, double? valorJoy = null, double? valorDesejado = null)
|
|
{
|
|
var op = Variaveis.OperacaoEmAndamento;
|
|
|
|
double centro = 32767.0;
|
|
double deadzone = 3000.0;
|
|
|
|
var pControle = op.Parametros.Controle;
|
|
var controle = op.Controle;
|
|
|
|
if (pControle == null || controle == null) return;
|
|
|
|
double velMin = pControle.MovVelocidadeCErvasPercent;
|
|
double velMax = pControle.MovVelocidadeSErvasPercent;
|
|
|
|
double valorSaida = 0;
|
|
bool estadoSaida = false;
|
|
|
|
switch (botaoJoy)
|
|
{
|
|
// =========================================================
|
|
// DIREÇÃO ANALÓGICA
|
|
// =========================================================
|
|
case BotoesJoystick.AEEsquerda:
|
|
{
|
|
double percent = 0;
|
|
if (valorJoy != null)
|
|
{
|
|
if (!solto && valorJoy.Value < centro - deadzone)
|
|
percent = (centro - valorJoy.Value) / centro;
|
|
percent = FuncoesMatematicas.Clamp(percent, 0, 1);
|
|
valorSaida = solto ? 0 : -pControle.DirAnguloMaximo * percent;
|
|
}
|
|
else if (valorDesejado != null)
|
|
{
|
|
valorSaida = solto ? 0 : valorDesejado.Value;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case BotoesJoystick.AEDireita:
|
|
{
|
|
if (valorJoy != null)
|
|
{
|
|
double percent = 0;
|
|
if (!solto && valorJoy.Value > centro + deadzone)
|
|
percent = (valorJoy.Value - centro) / (GeneralJoystick.MaximoAnalogico - centro);
|
|
percent = FuncoesMatematicas.Clamp(percent, 0, 1);
|
|
valorSaida = solto ? 0 : pControle.DirAnguloMaximo * percent;
|
|
}
|
|
else if (valorDesejado != null)
|
|
{
|
|
valorSaida = valorDesejado.Value;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Não usados por enquanto
|
|
case BotoesJoystick.AECima:
|
|
case BotoesJoystick.AEBaixo:
|
|
break;
|
|
|
|
// =========================================================
|
|
// DIREÇÃO DIGITAL
|
|
// =========================================================
|
|
case BotoesJoystick.SEsquerda:
|
|
valorSaida = solto ? 0 : valorDesejado ?? -pControle.DirAnguloMaximo;
|
|
break;
|
|
|
|
case BotoesJoystick.SDireita:
|
|
valorSaida = solto ? 0 : valorDesejado ?? pControle.DirAnguloMaximo;
|
|
break;
|
|
|
|
// =========================================================
|
|
// MOVIMENTO ANALÓGICO
|
|
// =========================================================
|
|
case BotoesJoystick.L2A:
|
|
case BotoesJoystick.R2A:
|
|
{
|
|
if (solto)
|
|
{
|
|
valorSaida = 0;
|
|
}
|
|
else if (valorJoy != null)
|
|
{
|
|
double gatilho = FuncoesMatematicas.Clamp(valorJoy.Value / GeneralJoystick.MaximoAnalogico, 0, 1);
|
|
valorSaida = FuncoesMatematicas.Map(gatilho, 0, 1, velMin, velMax);
|
|
}
|
|
else if (valorDesejado != null)
|
|
{
|
|
valorSaida = valorDesejado.Value;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// =========================================================
|
|
// MOVIMENTO DIGITAL FIXO NO MÍNIMO
|
|
// =========================================================
|
|
case BotoesJoystick.Xis:
|
|
case BotoesJoystick.Quadrado:
|
|
valorSaida = solto ? 0 : valorDesejado ?? velMin;
|
|
break;
|
|
|
|
// =========================================================
|
|
// FREIO
|
|
// =========================================================
|
|
case BotoesJoystick.Bolinha:
|
|
valorSaida = 0;
|
|
estadoSaida = !solto;
|
|
break;
|
|
|
|
// =========================================================
|
|
// AJUSTE FINO DE VELOCIDADE
|
|
// Só funciona se já estiver em movimento
|
|
// =========================================================
|
|
case BotoesJoystick.L1:
|
|
{
|
|
if (solto)
|
|
{
|
|
valorSaida = controle.PercentualVelocidadeSP;
|
|
}
|
|
else
|
|
{
|
|
var ultima_direcao = controle.TiposControle?.FirstOrDefault(x => x.Tipo == Dispositivo)?.UltimaDirecao ?? Direcao.Parado;
|
|
bool emMovimento = ultima_direcao == Direcao.Frente || ultima_direcao == Direcao.Tras;
|
|
if (emMovimento && controle.PercentualVelocidadeSP > 0)
|
|
valorSaida = Math.Max(velMin, controle.PercentualVelocidadeSP - 1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case BotoesJoystick.R1:
|
|
{
|
|
if (solto)
|
|
{
|
|
valorSaida = controle.PercentualVelocidadeSP;
|
|
}
|
|
else
|
|
{
|
|
var ultima_direcao = controle.TiposControle?.FirstOrDefault(x => x.Tipo == T_Code.Mov)?.UltimaDirecao ?? Direcao.Parado;
|
|
bool emMovimento = ultima_direcao == Direcao.Frente || ultima_direcao == Direcao.Tras;
|
|
if (emMovimento && controle.PercentualVelocidadeSP > 0)
|
|
valorSaida = Math.Min(velMax, controle.PercentualVelocidadeSP + 1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
// =========================================================
|
|
// BICOS PULVERIZADORES
|
|
// =========================================================
|
|
case BotoesJoystick.Touchpad:
|
|
estadoSaida = !solto;
|
|
break;
|
|
|
|
}
|
|
|
|
if (solto && PararAoSoltar)
|
|
direcao = Direcao.Parado;
|
|
ValorAplicar = valorSaida;
|
|
EstadoAplicar = estadoSaida;
|
|
}
|
|
|
|
public DeParaComandos Clone()
|
|
{
|
|
return new DeParaComandos()
|
|
{
|
|
botaoJoy = botaoJoy,
|
|
key = key,
|
|
Dispositivo = Dispositivo,
|
|
PararAoSoltar = PararAoSoltar,
|
|
IDcontrolar = IDcontrolar,
|
|
Comando = Comando,
|
|
direcao = direcao,
|
|
ValorAplicar = ValorAplicar,
|
|
EstadoAplicar = EstadoAplicar,
|
|
};
|
|
}
|
|
}
|
|
|
|
public enum ComparativoAnalogico
|
|
{
|
|
Igual,
|
|
Maior,
|
|
Menor
|
|
}
|
|
|
|
public class BotoesPressionadosValores
|
|
{
|
|
public BotoesJoystick botao { get; set; }
|
|
public int valor { get; set; }
|
|
}
|
|
|
|
|
|
|
|
}
|