926 lines
41 KiB
C#
926 lines
41 KiB
C#
using AgroBase.Models;
|
|
using AgroBase.Models.Components;
|
|
using AgroBase.Models.Operadores;
|
|
using AgroBase.Services;
|
|
using AgroBase.Services.Operadores;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using static AgroBase.Models.Enums;
|
|
|
|
namespace AgroBase.Forms.IHM
|
|
{
|
|
public partial class frmDialogoMapa : Form
|
|
{
|
|
AsyncTaskTimerModel tmrLeitura;
|
|
MapaDinamicoModel MapaDinamico;
|
|
private ulong CodigoFalha = 0;
|
|
private bool ReqFrameCam = false;
|
|
private bool ReqFrameSnr = false;
|
|
private bool _inRefresh;
|
|
private List<ModuloUIItem> _modulosUI = new List<ModuloUIItem>();
|
|
|
|
public frmDialogoMapa()
|
|
{
|
|
InitializeComponent();
|
|
|
|
// Ativa o double buffering
|
|
this.DoubleBuffered = true;
|
|
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
|
this.SetStyle(ControlStyles.UserPaint, true);
|
|
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
|
|
|
pnlJoystick.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlJoystick, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
|
|
pnlFreio.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlFreio, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
|
|
pnlCameraSolo0.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCameraSolo0, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
|
|
pnlCameraCaminho.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCameraCaminho, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
|
|
pnlCameraCaminhoSeg.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCameraCaminhoSeg, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
|
|
|
|
cmbModoControle.Items.Clear();
|
|
cmbModoControle.Items.AddRange(Enum.GetNames(typeof(Enums.TipoMovimentoDirecional)));
|
|
cmbModoControle.SelectedIndexChanged += CmbModoControle_SelectedIndexChanged;
|
|
|
|
pnlCameraSolo0.BackgroundImageLayout = ImageLayout.Zoom;
|
|
pnlCameraCaminho.BackgroundImageLayout = ImageLayout.Zoom;
|
|
pnlCameraCaminhoSeg.BackgroundImageLayout = ImageLayout.Zoom;
|
|
|
|
clbModulos.DrawMode = DrawMode.OwnerDrawFixed; // habilita owner-draw
|
|
clbModulos.ItemHeight = Math.Max(clbModulos.ItemHeight, 20);
|
|
|
|
clbModulos.DrawItem += clbModulos_DrawItem;
|
|
clbModulos.ItemCheck += clbModulos_ItemCheck;
|
|
clbModulos.SelectedIndexChanged += clbModulos_SelectedIndexChanged;
|
|
|
|
AtualizarElementosModoManual();
|
|
|
|
MapaDinamico = new MapaDinamicoModel(this, pnlMapaDinamico);
|
|
|
|
FuncoesGlobais.DefinirEventosPicBtn(picFechar, "", async () =>
|
|
{
|
|
if (Variaveis.OperacaoEmAndamento.Iniciado && !Variaveis.OperacaoEmAndamento.Finalizando)
|
|
{
|
|
var res = CustomDialog.ShowDialog(
|
|
"Interromper Operação",
|
|
"Tem certeza que deseja interromper a operação em andamento?",
|
|
MessageBoxIcon.Question,
|
|
new Dictionary<(string, DialogResult?), Action>()
|
|
{
|
|
{ ("Sim", DialogResult.Yes), () => { } },
|
|
{ ("Não", DialogResult.No), () => { } },
|
|
}
|
|
);
|
|
if (res == DialogResult.Yes)
|
|
{
|
|
Task.Run(async () => await Variaveis.OperacaoEmAndamento.FinalizarOperacao());
|
|
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo == Enums.ModoOperacao.Manual)
|
|
{
|
|
this.Close();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Variaveis.OperacaoEmAndamento.StatusAtual == Enums.StatusOperacao.Parametrizando)
|
|
{
|
|
this.Hide();
|
|
}
|
|
else
|
|
{
|
|
this.Close();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private void frmDialogoMapa_Load(object sender, EventArgs e)
|
|
{
|
|
tmrLeitura?.Dispose();
|
|
tmrLeitura = new AsyncTaskTimerModel("tmrLeitura", tmrLeitura_Tick, 500, this);
|
|
tmrLeitura.Start();
|
|
|
|
if (Variaveis.OperacaoEmAndamento.Mapa.pnlMapa == null)
|
|
{
|
|
Variaveis.OperacaoEmAndamento.Mapa = new MapasModel()
|
|
{
|
|
pnlMapa = pnlMapa,
|
|
lblMapa = lblMapaCarregado
|
|
};
|
|
Variaveis.OperacaoEmAndamento.Mapa.CarregarMapaGPS();
|
|
}
|
|
}
|
|
|
|
private void frmDialogoMapa_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
tmrLeitura?.Dispose();
|
|
}
|
|
|
|
public async Task AtualizarRuasSelecionadas(List<string> ruasSelecionadas)
|
|
{
|
|
await Task.Delay(1000);
|
|
|
|
GPSService.AtualizarRuasSelecionadas(ruasSelecionadas);
|
|
}
|
|
|
|
public void IniciarOperacao()
|
|
{
|
|
Task.Run(async () => {
|
|
await Variaveis.OperacaoEmAndamento.IniciarOperacao();
|
|
|
|
//InicializarModoManual();
|
|
});
|
|
}
|
|
|
|
public void AtualizarMapaDinamico()
|
|
{
|
|
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
|
var _Trajetoria = Variaveis.OperacaoEmAndamento.Trajetoria;
|
|
|
|
if (_Trajetoria != null && _Trajetoria.CorredorAtual != null)
|
|
{
|
|
MapaDinamico.AtualizarDados(
|
|
null,
|
|
(float)_Trajetoria.AnguloCaminho,
|
|
(float)_Sensoriamento.Gps.AnguloCarroDefinido,
|
|
_Sensoriamento.Gps,
|
|
_Trajetoria._TrajetoriaDinamica,
|
|
_Trajetoria.CorredorAtual.Pontos,
|
|
Variaveis.OperacaoEmAndamento.GPSTrajetoria,
|
|
_Trajetoria.RuasPlantacao,
|
|
_Sensoriamento.Controle.SimulacaoMPC
|
|
);
|
|
}
|
|
}
|
|
|
|
private async Task tmrLeitura_Tick()
|
|
{
|
|
pnlOrientacao.Invalidate();
|
|
pnlInclinacao.Invalidate();
|
|
|
|
var _Sensoriamento = Variaveis.OperacaoEmAndamento.Sensoriamento;
|
|
|
|
lblUltimaLeituraSolo.Text = "Última Leitura Solo: " + _Sensoriamento.OperadorErvas.UltimaMensagem.ToString("HH:mm:ss.fff");
|
|
lblUltimaLeituraCaminho.Text = "Última Leitura Caminho: " + _Sensoriamento.OperadorVisual.UltimaMensagem.ToString("HH:mm:ss.fff");
|
|
lblPerformance.Text = _Sensoriamento.DadosPerformance.PerformanceStr;
|
|
|
|
lblMapaCarregado.Text = "Operação: " + Variaveis.OperacaoEmAndamento.Descricao;
|
|
|
|
txtModoOperacao.Text = (Variaveis.OperacaoEmAndamento.Parametros?.Modo ?? ModoOperacao.NaoDefinido).ToString();
|
|
bool opLiberada = _Sensoriamento.OperacaoLiberada;
|
|
txtOperacaoLiberada.Text = opLiberada ? "Sim" : "Não";
|
|
txtOperacaoLiberada.ForeColor = opLiberada ? Color.Black : Color.Red;
|
|
btnCodFalha.Text = CodigoFalha.ToString("0.000");
|
|
txtStatusAtual.Text = _Sensoriamento.StatusOperacao.ToString();
|
|
txtIniciadoEm.Text = _Sensoriamento.DataInicio == DateTime.MinValue ? "Aguardando" : _Sensoriamento.DataInicio.ToString("dd/MM HH:mm:ss");
|
|
txtConcluidoEm.Text = _Sensoriamento.DataFim == DateTime.MinValue ? "-" : _Sensoriamento.DataFim.ToString("dd/MM HH:mm:ss");
|
|
txtDistanciaPercorrida.Text = _Sensoriamento.Trajetoria.DistanciaPercorrida.ToString("0.00") + " m";
|
|
txtTempoOperacao.Text = _Sensoriamento.TempoDecorrido.ToString("HH:mm:ss");
|
|
txtLatenciaControle.Text = _Sensoriamento.Controle.Latencia.ToString();
|
|
txtHerbicidaAplicado.Text = _Sensoriamento.Atuador.HerbicidaConsumido.ToString("0.000") + " L";
|
|
txtBateriaConsumida.Text = _Sensoriamento.Bateria.PercentualBateriaConsumida.ToString("0.00") + " %";
|
|
|
|
FuncoesGlobais.PreencheValorProgressBar(pgbReservatorio, _Sensoriamento.Atuador.PercentualReservatorio);
|
|
lblReservatorio.Text = "Reservatório: " + _Sensoriamento.Atuador.VolumeReservatorio.ToString("0.00") + " l " + _Sensoriamento.Atuador.PercentualReservatorio.ToString("0.00") + "%";
|
|
|
|
FuncoesGlobais.PreencheValorProgressBar(pgbBateria, _Sensoriamento.Bateria.PercentualBateria);
|
|
lblBateria.Text = "Bateria: " + _Sensoriamento.Bateria.TensaoInstantanea.ToString("0.00") + "v " + _Sensoriamento.Bateria.PercentualBateria.ToString("0.00") + "%";
|
|
|
|
FuncoesGlobais.PreencheValorProgressBar(pgbOperacao, _Sensoriamento.Trajetoria.ProgressoTrajeto);
|
|
lblOperacao.Text = "Operação: " + _Sensoriamento.Trajetoria.ProgressoTrajeto.ToString("0.00") + "%";
|
|
|
|
FuncoesGlobais.PreencheValorProgressBar(pgbRuaAtual, _Sensoriamento.Trajetoria.CorredorAtual.Progresso);
|
|
lblRuaAtual.Text = "Rua Atual: " + _Sensoriamento.Trajetoria.CorredorAtual.Progresso.ToString("0.00") + "%";
|
|
|
|
lblCorrecaoGPS.Text = (_Sensoriamento.Gps.Ntrip_ativado ? "N " : "B ") + _Sensoriamento.Gps.IdadeCorrecao + ": " + _Sensoriamento.Gps.QualidadeFix.ToString();
|
|
lblPrecisaoGPS.Text = $"Precisão: {_Sensoriamento.Gps.PrecisaoCm.ToString("0.00")} cm";
|
|
|
|
bool automatico = Variaveis.OperacaoEmAndamento.Parametros?.ControleAutomatico ?? false;
|
|
cmbModoControle.Enabled = !automatico;
|
|
tkbVelocidade.Enabled = !automatico;
|
|
tkbAnguloDirecional.Enabled = !automatico;
|
|
pnlFreio.Enabled = !automatico;
|
|
if (automatico)
|
|
{
|
|
cmbModoControle.SelectedIndex = (int)_Sensoriamento.Controle.TipoMovimento;
|
|
|
|
tkbVelocidade.Value = Convert.ToInt32(_Sensoriamento.Controle.PercentualVelocidadeSP);
|
|
|
|
tkbAnguloDirecional.Minimum = 0;
|
|
tkbAnguloDirecional.Maximum = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo);
|
|
tkbAnguloDirecional.Value = Math.Abs(Convert.ToInt32(_Sensoriamento.Controle.Angulo));
|
|
}
|
|
|
|
txtDistanciasEsqDir.Text = _Sensoriamento.Trajetoria.DistanciaEsquerda.ToString("0.00") + " / " + _Sensoriamento.Trajetoria.DistanciaDireita.ToString("0.00") + " (" + _Sensoriamento.Controle.ErroLateral.ToString("0.00" + ")");
|
|
txtDentroCorredor.Text = _Sensoriamento.Trajetoria.CorredorAtual.Dentro ? "Sim" : "Não";
|
|
txtMargemCorredor.Text = _Sensoriamento.Trajetoria.NaMargemDoCorredor ? "Sim" : "Não";
|
|
txtStatusCarro.Text = _Sensoriamento.Trajetoria.StatusCarro.ToString();
|
|
txtInclinacao.Text = _Sensoriamento.IMU.RollSeguro.ToString("0.00") + "/" + _Sensoriamento.IMU.PitchSeguro.ToString("0.00");
|
|
|
|
var ModET = Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos.FirstOrDefault(x => x.Modulo_ID == "ET");
|
|
txtET.Text = (ModET?.MovMotor?.Corrente_Motor ?? 0).ToString("0.00");
|
|
lblET.ForeColor = (ModET?.Conectado ?? false) ? Color.Green : Color.Red;
|
|
var ModDT = Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos.FirstOrDefault(x => x.Modulo_ID == "DT");
|
|
txtDT.Text = (ModDT?.MovMotor?.Corrente_Motor ?? 0).ToString("0.00");
|
|
lblDT.ForeColor = (ModDT?.Conectado ?? false) ? Color.Green : Color.Red;
|
|
var ModEF = Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos.FirstOrDefault(x => x.Modulo_ID == "EF");
|
|
txtEF.Text = (ModEF?.MovMotor?.Corrente_Motor ?? 0).ToString("0.00");
|
|
lblEF.ForeColor = (ModEF?.Conectado ?? false) ? Color.Green : Color.Red;
|
|
var ModDF = Variaveis.OperacaoEmAndamento.DispMvd.Dados.Modulos.FirstOrDefault(x => x.Modulo_ID == "DF");
|
|
txtDF.Text = (ModDF?.MovMotor?.Corrente_Motor ?? 0).ToString("0.00");
|
|
lblDF.ForeColor = (ModDF?.Conectado ?? false) ? Color.Green : Color.Red;
|
|
|
|
if (!Variaveis.Producao)
|
|
{
|
|
AtualizarMapaDinamico();
|
|
}
|
|
|
|
if (!ReqFrameCam)
|
|
_ = AtualizarCameraSolo();
|
|
|
|
if (!ReqFrameSnr)
|
|
_ = AtualizarCameraCaminho();
|
|
|
|
AtualizarListaModulos();
|
|
}
|
|
|
|
private async Task AtualizarCameraSolo()
|
|
{
|
|
ReqFrameCam = true;
|
|
try
|
|
{
|
|
var frame = await WeedWorkerService.GetCameraFrame(TipoFrameCamera.Rgb);
|
|
AtualizarImagemPainel(pnlCameraSolo0, frame?.image());
|
|
}
|
|
finally
|
|
{
|
|
ReqFrameCam = false;
|
|
}
|
|
}
|
|
|
|
private async Task AtualizarCameraCaminho()
|
|
{
|
|
ReqFrameSnr = true;
|
|
try
|
|
{
|
|
var frameRgb = await VisualWorkerService.GetCameraFrame(TipoFrameCamera.Rgb);
|
|
AtualizarImagemPainel(pnlCameraCaminho, frameRgb?.image());
|
|
|
|
var frameSeg = await VisualWorkerService.GetCameraFrame(TipoFrameCamera.Segmentacao);
|
|
AtualizarImagemPainel(pnlCameraCaminhoSeg, frameSeg?.image());
|
|
}
|
|
finally
|
|
{
|
|
ReqFrameSnr = false;
|
|
}
|
|
}
|
|
|
|
private void AtualizarImagemPainel(Panel panel, Image novaImagem)
|
|
{
|
|
if (panel.InvokeRequired)
|
|
{
|
|
panel.BeginInvoke(new Action(() => AtualizarImagemPainel(panel, novaImagem)));
|
|
return;
|
|
}
|
|
|
|
panel.BackgroundImage?.Dispose();
|
|
panel.BackgroundImage = novaImagem;
|
|
}
|
|
|
|
private void pnlOrientacao_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
double angulo = Variaveis.OperacaoEmAndamento.Sensoriamento?.Gps?.AnguloCarroDefinido ?? 0;
|
|
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)angulo, 90, (float)(Variaveis.OperacaoEmAndamento.Sensoriamento?.Trajetoria?.AnguloCaminho ?? 0));
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void pnlInclinacao_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
FuncoesGlobais.DesenharInclinacao((Panel)sender, e, (float)(Variaveis.OperacaoEmAndamento.Controle.Angulo), 90);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
|
|
#region MODO MANUAL
|
|
|
|
private Point joystickCenter;
|
|
private bool isDragging = false;
|
|
private Keys prevMovKey = Keys.None;
|
|
private Keys prevDirKey = Keys.None;
|
|
|
|
private int joystickRadius;
|
|
private Point joystickPosition;
|
|
|
|
private Point freioPosition;
|
|
private Point freioStartPosition;
|
|
private bool isDraggingFreio = false;
|
|
private bool isBrakeLocked = false;
|
|
|
|
private void AtualizarElementosModoManual()
|
|
{
|
|
cmbModoControle.Enabled = false;
|
|
tkbAnguloDirecional.Enabled = false;
|
|
tkbVelocidade.Enabled = false;
|
|
pnlJoystick.Visible = false;
|
|
tabControl1.TabPages.Remove(tabControle);
|
|
|
|
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
|
|
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
|
|
cmbModoControle.SelectedIndex = (int)_Controle.TipoMovimento;
|
|
chbFrenagemAutomatica.Checked = pControle.FrenagemAutomaticaAoParar;
|
|
nudVelSemErvas.Value = (int)pControle.MovVelocidadeSErvasPercent;
|
|
nudVelComErvas.Value = (int)pControle.MovVelocidadeCErvasPercent;
|
|
chbPulverizadorAutomatico.Checked = pControle.PulverizadorAutomatico;
|
|
nudPercentualAtuacaoBico.Value = (int)pControle.AtuPercentualInicioPulverizacao;
|
|
nudPressaoLinha.Value = (int)pControle.AtuPressaoLinha;
|
|
FuncoesGlobais.PreencheValorTrackBar(tkbAnguloDirecional, _Controle.Angulo);
|
|
FuncoesGlobais.PreencheValorTrackBar(tkbVelocidade, _Controle.PercentualVelocidadeSP);
|
|
|
|
string pesosMpcStr = RedisService.Get(CtxKey.DadosPesosMPC);
|
|
var pesos = JsonConvert.DeserializeObject<MPCPesosModel>(pesosMpcStr);
|
|
txtPesoPosicao.Text = pesos.posicao.ToString();
|
|
txtPesoOrientacao.Text = pesos.orientacao.ToString();
|
|
txtPesoSuavidadeMin.Text = pesos.suavidade_min.ToString();
|
|
txtPesoSuavidadeMax.Text = pesos.suavidade_max.ToString();
|
|
txtPesoFatorRe.Text = pesos.fator_re.ToString();
|
|
txtPesoIdeal.Text = pesos.ideal.ToString();
|
|
txtPesoLateralMin.Text = pesos.lateral_min.ToString();
|
|
txtPesoLateralMax.Text = pesos.lateral_max.ToString();
|
|
|
|
tkbVelocidade_Scroll(null, null);
|
|
tkbAnguloDirecional_Scroll(null, null);
|
|
}
|
|
|
|
public void InicializarModoManual()
|
|
{
|
|
AtualizarElementosModoManual();
|
|
|
|
cmbModoControle.Enabled = true;
|
|
tkbVelocidade.Enabled = true;
|
|
tkbAnguloDirecional.Enabled = true;
|
|
tabControl1.TabPages.Insert(1, tabControle);
|
|
tabControl1.TabPages.Remove(tabMapa);
|
|
|
|
pnlJoystick.Visible = true;
|
|
pnlFreio.Visible = true;
|
|
|
|
// Configurar o painel do joystick
|
|
pnlJoystick.BackColor = Color.LightGray; // Fundo semitransparente
|
|
|
|
// Definir região circular para o painel
|
|
System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
|
|
path.AddEllipse(0, 0, pnlJoystick.Width, pnlJoystick.Height);
|
|
pnlJoystick.Region = new Region(path);
|
|
|
|
// Calcular o centro do joystick
|
|
joystickCenter = new Point(pnlJoystick.Width / 2, pnlJoystick.Height / 2);
|
|
|
|
// Definir o raio do joystick
|
|
joystickRadius = pnlJoystick.Width / 4;
|
|
joystickPosition = joystickCenter;
|
|
|
|
// Evento de pintura do painel
|
|
pnlJoystick.Paint -= PanelJoystickBack_Paint;
|
|
pnlJoystick.Paint += PanelJoystickBack_Paint;
|
|
|
|
// Eventos de toque/mouse
|
|
pnlJoystick.MouseDown -= PanelJoystickBack_MouseDown;
|
|
pnlJoystick.MouseDown += PanelJoystickBack_MouseDown;
|
|
pnlJoystick.MouseMove -= PanelJoystickBack_MouseMove;
|
|
pnlJoystick.MouseMove += PanelJoystickBack_MouseMove;
|
|
pnlJoystick.MouseUp -= PanelJoystickBack_MouseUp;
|
|
pnlJoystick.MouseUp += PanelJoystickBack_MouseUp;
|
|
|
|
pnlFreio.BackColor = Color.LightGray;
|
|
pnlFreio.BorderStyle = BorderStyle.FixedSingle;
|
|
|
|
// Eventos de toque/pressão
|
|
pnlFreio.Paint -= BrakePanel_Paint;
|
|
pnlFreio.Paint += BrakePanel_Paint;
|
|
pnlFreio.MouseDown -= BrakePanel_MouseDown;
|
|
pnlFreio.MouseDown += BrakePanel_MouseDown;
|
|
pnlFreio.MouseMove -= BrakePanel_MouseMove;
|
|
pnlFreio.MouseMove += BrakePanel_MouseMove;
|
|
pnlFreio.MouseUp -= BrakePanel_MouseUp;
|
|
pnlFreio.MouseUp += BrakePanel_MouseUp;
|
|
|
|
// Configuração inicial do freio
|
|
freioStartPosition = new Point(pnlFreio.Width / 2 - 20, 10);
|
|
freioPosition = freioStartPosition;
|
|
|
|
IniciarOperacao();
|
|
}
|
|
|
|
#region JOYSTICK
|
|
private void PanelJoystickBack_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
|
e.Graphics.FillEllipse(Brushes.Red, joystickPosition.X - joystickRadius, joystickPosition.Y - joystickRadius, joystickRadius * 2, joystickRadius * 2);
|
|
}
|
|
|
|
private void PanelJoystickBack_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
isDragging = true;
|
|
}
|
|
|
|
private void PanelJoystickBack_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (isDragging)
|
|
{
|
|
// Calcula a nova posição do joystick
|
|
var mouseX = e.X;
|
|
var mouseY = e.Y;
|
|
|
|
var deltaX = mouseX - joystickCenter.X;
|
|
var deltaY = mouseY - joystickCenter.Y;
|
|
|
|
// Limitar o movimento do joystick ao círculo do painel
|
|
var distance = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
var maxDistance = pnlJoystick.Width / 2;
|
|
|
|
if (distance > maxDistance)
|
|
{
|
|
deltaX = (int)(deltaX / distance * maxDistance);
|
|
deltaY = (int)(deltaY / distance * maxDistance);
|
|
}
|
|
|
|
joystickPosition = new Point(joystickCenter.X + deltaX, joystickCenter.Y + deltaY);
|
|
pnlJoystick.Invalidate(); // Redesenha o painel
|
|
|
|
// Enviar comandos de movimento ao robô
|
|
SendMovementCommand(deltaX, deltaY);
|
|
}
|
|
}
|
|
|
|
private void PanelJoystickBack_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
isDragging = false;
|
|
// Retorna o joystick ao centro
|
|
joystickPosition = joystickCenter;
|
|
pnlJoystick.Invalidate(); // Redesenha o painel
|
|
|
|
// Enviar comando de parada ao robô
|
|
SendMovementCommand(0, 0);
|
|
}
|
|
|
|
private void SendMovementCommand(int deltaX, int deltaY)
|
|
{
|
|
Keys MovKey = Keys.Escape;
|
|
if (deltaY < -10) MovKey = Keys.Up;
|
|
else if (deltaY > 10) MovKey = Keys.Down;
|
|
|
|
Keys DirKey = Keys.Escape;
|
|
if (deltaX < -10) DirKey = Keys.Left;
|
|
else if (deltaX > 10) DirKey = Keys.Right;
|
|
|
|
// Verifica se o estado da tecla de movimento mudou
|
|
if (MovKey != prevMovKey)
|
|
{
|
|
// Lógica para enviar comando ao robô baseado em MovKey
|
|
Console.WriteLine($"Movimento: MovKey={MovKey}");
|
|
//GeneralJoystick.EnviaComandoMotor(MovKey, Enums.T_Code.Mov);
|
|
var comando = GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.key == MovKey);
|
|
GeneralJoystick.ProcessarDadosControle(comando.botaoJoy, false, valorDesejado: Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent);
|
|
prevMovKey = MovKey; // Atualiza o estado anterior
|
|
}
|
|
|
|
// Verifica se o estado da tecla de direção mudou
|
|
if (DirKey != prevDirKey)
|
|
{
|
|
// Lógica para enviar comando ao robô baseado em DirKey
|
|
Console.WriteLine($"Direção: DirKey={DirKey}");
|
|
//GeneralJoystick.EnviaComandoMotor(DirKey, Enums.T_Code.Dir);
|
|
var comando = GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.key == DirKey);
|
|
GeneralJoystick.ProcessarDadosControle(comando.botaoJoy, false, valorDesejado: Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo);
|
|
prevDirKey = DirKey; // Atualiza o estado anterior
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region FREIO
|
|
// Desenho do trilho e trava no painel do freio
|
|
private void BrakePanel_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
Panel panel = sender as Panel;
|
|
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
|
|
|
// Desenhar trilha do freio (trajetória vertical)
|
|
e.Graphics.DrawLine(new Pen(Color.Black, 5), panel.Width / 2, 10, panel.Width / 2, panel.Height - 50);
|
|
|
|
// Desenhar a área de trava (na lateral direita)
|
|
e.Graphics.DrawRectangle(new Pen(Color.Blue, 3), panel.Width - 30, panel.Height - 60, 20, 40);
|
|
|
|
// Desenhar o botão de freio atual
|
|
e.Graphics.FillEllipse(Brushes.Red, freioPosition.X, freioPosition.Y, 40, 40);
|
|
}
|
|
|
|
// Iniciar o arraste
|
|
private void BrakePanel_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo != Enums.ModoOperacao.Manual)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (new Rectangle(freioPosition.X, freioPosition.Y, 40, 40).Contains(e.Location))
|
|
{
|
|
isDraggingFreio = true;
|
|
}
|
|
}
|
|
|
|
// Movimentar o botão de freio
|
|
private void BrakePanel_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo != Enums.ModoOperacao.Manual)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (isDraggingFreio)
|
|
{
|
|
// Calcula a posição ao arrastar
|
|
int deltaY = e.Y - freioPosition.Y;
|
|
int newPosX = freioPosition.X;
|
|
int newPosY = freioPosition.Y + deltaY;
|
|
|
|
// Limitar o movimento do freio ao trilho e destravar se o usuário mover para fora da trava
|
|
if (!isBrakeLocked || (isBrakeLocked && e.X < pnlFreio.Width - 30))
|
|
{
|
|
isBrakeLocked = false; // Destrava o freio se mover para fora
|
|
|
|
// Restringe o movimento vertical dentro da área do trilho
|
|
if (newPosY >= 10 && newPosY <= pnlFreio.Height - 50)
|
|
{
|
|
freioPosition = new Point(newPosX, newPosY);
|
|
pnlFreio.Invalidate(); // Redesenha o painel
|
|
|
|
// Enviar comando de freio
|
|
//GeneralJoystick.EnviaComandoMotor(Keys.Space, Enums.T_Code.Mov);
|
|
GeneralJoystick.ProcessarDadosControle(BotoesJoystick.Bolinha, false);
|
|
}
|
|
}
|
|
|
|
// Verifica se o usuário está na área de trava
|
|
if (freioPosition.Y >= pnlFreio.Height - 90 && e.X >= pnlFreio.Width - 30)
|
|
{
|
|
isBrakeLocked = true; // Freio travado
|
|
freioPosition = new Point(pnlFreio.Width - 40, pnlFreio.Height - 60); // Posiciona o freio na trava
|
|
pnlFreio.Invalidate();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Soltar o botão de freio
|
|
private void BrakePanel_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
if (Variaveis.OperacaoEmAndamento.Parametros?.Modo != Enums.ModoOperacao.Manual)
|
|
{
|
|
return;
|
|
}
|
|
|
|
isDraggingFreio = false;
|
|
|
|
if (!isBrakeLocked)
|
|
{
|
|
// Se o freio não estiver travado, retorna à posição inicial
|
|
freioPosition = freioStartPosition;
|
|
pnlFreio.Invalidate(); // Redesenha o painel
|
|
|
|
// Enviar comando para desativar o freio
|
|
//GeneralJoystick.EnviaComandoMotor(Keys.Escape, Enums.T_Code.Mov);
|
|
GeneralJoystick.ProcessarDadosControle(BotoesJoystick.Bolinha, true);
|
|
}
|
|
else
|
|
{
|
|
// Freio travado, mantém travado
|
|
//GeneralJoystick.EnviaComandoMotor(Keys.Space, Enums.T_Code.Mov);
|
|
GeneralJoystick.ProcessarDadosControle(BotoesJoystick.Bolinha, false);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void CmbModoControle_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
Variaveis.OperacaoEmAndamento.Controle.TipoMovimento = (Enums.TipoMovimentoDirecional)cmbModoControle.SelectedIndex;
|
|
}
|
|
|
|
private void tkbVelocidade_Scroll(object sender, EventArgs e)
|
|
{
|
|
Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP = tkbVelocidade.Value;
|
|
double Velocidade = FuncoesMatematicas.ConverteMsParaKmh(FuncoesMatematicas.CalculaVelocidadeMsPercentual(tkbVelocidade.Value));
|
|
|
|
lblVelocidade.Text = $"Velocidade: {tkbVelocidade.Value}% {Velocidade.ToString("0.00")} km/h";
|
|
}
|
|
|
|
private void tkbAnguloDirecional_Scroll(object sender, EventArgs e)
|
|
{
|
|
Variaveis.OperacaoEmAndamento.Controle.Angulo = tkbAnguloDirecional.Value;
|
|
|
|
lblAnguloDirecional.Text = $"Ângulo Direcional: {tkbAnguloDirecional.Value}°";
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
private void btnCodFalha_Click(object sender, EventArgs e)
|
|
{
|
|
string DescricaoFalha = Variaveis.OperacaoEmAndamento.ErroOperacaoLiberada;
|
|
CustomDialog.ShowDialog(
|
|
"Código de Falha",
|
|
$"{DescricaoFalha}",
|
|
MessageBoxIcon.Question,
|
|
new Dictionary<(string, dynamic), Action>()
|
|
{
|
|
{ ("OK", null), () => { } },
|
|
}
|
|
);
|
|
}
|
|
|
|
private void chbAcompanharCarro_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
MapaDinamico.AlterarTravaRover(chbAcompanharCarro.Checked);
|
|
}
|
|
|
|
|
|
|
|
#region OPERACAO
|
|
|
|
public class ModuloUIItem
|
|
{
|
|
public T_Code Disp { get; set; }
|
|
public bool Mandatorio { get; set; }
|
|
public bool Utilizar { get; set; }
|
|
public bool Conectado { get; set; }
|
|
public StatusModulo Status { get; set; }
|
|
public double Saude { get; set; }
|
|
public string Motivo { get; set; }
|
|
public override string ToString()
|
|
=> $"{Disp}: {Status} ({Saude})";
|
|
}
|
|
|
|
private void AtualizarListaModulos(bool forceRebuild = false)
|
|
{
|
|
if (_inRefresh) return;
|
|
_inRefresh = true;
|
|
|
|
try
|
|
{
|
|
// 1) Pega o estado atual do seu sistema
|
|
var src = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios;
|
|
var saude = HealthWorkerService.ModulosSaude;
|
|
|
|
// 2) Constrói snapshot
|
|
var novos = new List<ModuloUIItem>(src.Count);
|
|
foreach (var mod in src)
|
|
{
|
|
var saudeMod = saude.FirstOrDefault(x => x.modulo.Equals(mod.Dispositivo));
|
|
var item = new ModuloUIItem
|
|
{
|
|
Disp = mod.Dispositivo,
|
|
Mandatorio = mod.Mandatorio,
|
|
Utilizar = mod.Utilizar,
|
|
Conectado = mod.Conectado,
|
|
Status = saudeMod?.status ?? StatusModulo.Desconectado,
|
|
Saude = saudeMod?.saude ?? 0,
|
|
Motivo = saudeMod != null ? string.Join(", ", saudeMod.motivos) : "Sem dados"
|
|
};
|
|
novos.Add(item);
|
|
}
|
|
|
|
// 3) Decide se precisa rebuild (qtd mudou ou forceRebuild)
|
|
bool precisaRebuild = forceRebuild || novos.Count != _modulosUI.Count ||
|
|
!novos.Select(n => n.Disp).SequenceEqual(_modulosUI.Select(o => o.Disp));
|
|
|
|
if (precisaRebuild)
|
|
{
|
|
_modulosUI.Clear();
|
|
_modulosUI.AddRange(novos);
|
|
|
|
clbModulos.BeginUpdate();
|
|
clbModulos.Items.Clear();
|
|
foreach (var it in _modulosUI)
|
|
{
|
|
clbModulos.Items.Add(it, it.Utilizar); // check = Mandatório
|
|
}
|
|
clbModulos.EndUpdate();
|
|
}
|
|
else
|
|
{
|
|
// 4) Só atualiza conteúdo/mandatório e força redraw
|
|
for (int i = 0; i < _modulosUI.Count; i++)
|
|
{
|
|
var novo = novos[i];
|
|
var cur = _modulosUI[i];
|
|
|
|
bool textoMudou =
|
|
cur.Status != novo.Status ||
|
|
Math.Abs(cur.Saude - novo.Saude) > 0.0001 ||
|
|
cur.Motivo != novo.Motivo;
|
|
|
|
cur.Mandatorio = novo.Mandatorio; // mantemos em sincronia
|
|
cur.Utilizar = novo.Utilizar; // mantemos em sincronia
|
|
cur.Conectado = novo.Conectado;
|
|
cur.Status = novo.Status;
|
|
cur.Saude = novo.Saude;
|
|
cur.Motivo = novo.Motivo;
|
|
|
|
// sincroniza o check se mudou externamente
|
|
bool checkAtual = clbModulos.GetItemChecked(i);
|
|
if (checkAtual != cur.Utilizar)
|
|
clbModulos.SetItemChecked(i, cur.Utilizar);
|
|
|
|
if (textoMudou)
|
|
clbModulos.Invalidate(clbModulos.GetItemRectangle(i));
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
_inRefresh = false;
|
|
}
|
|
}
|
|
|
|
private (Color back, Color fore) Cores(StatusModulo st, bool conectado)
|
|
{
|
|
if (!conectado) return (Color.Black, Color.White); // Desconectado = preto
|
|
switch (st)
|
|
{
|
|
case StatusModulo.Falha: return (Color.Red, Color.White); // Falha = vermelho
|
|
case StatusModulo.Alerta: return (Color.Yellow, Color.Black); // Alerta = amarelo
|
|
case StatusModulo.Operante: return (Color.Green, Color.White); // Operante = verde
|
|
default: return (Color.Black, Color.White);
|
|
};
|
|
}
|
|
|
|
private void clbModulos_DrawItem(object sender, DrawItemEventArgs e)
|
|
{
|
|
if (e.Index < 0 || e.Index >= _modulosUI.Count)
|
|
return;
|
|
|
|
var it = _modulosUI[e.Index];
|
|
var (back, fore) = Cores(it.Status, it.Conectado);
|
|
|
|
// base
|
|
e.DrawBackground();
|
|
using (var b = new SolidBrush(back))
|
|
e.Graphics.FillRectangle(b, e.Bounds);
|
|
|
|
// checkbox (usa estilo do sistema, mas garantindo contraste de texto)
|
|
bool isChecked = clbModulos.GetItemChecked(e.Index);
|
|
CheckBoxRenderer.DrawCheckBox(
|
|
e.Graphics,
|
|
new Point(e.Bounds.Left + 4, e.Bounds.Top + (e.Bounds.Height - 14) / 2),
|
|
isChecked ? System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal
|
|
: System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal
|
|
);
|
|
|
|
// texto
|
|
var texto = it.ToString();
|
|
var textRect = new Rectangle(e.Bounds.Left + 24, e.Bounds.Top, e.Bounds.Width - 24, e.Bounds.Height);
|
|
TextRenderer.DrawText(e.Graphics, texto, e.Font, textRect, fore, TextFormatFlags.VerticalCenter | TextFormatFlags.EndEllipsis);
|
|
|
|
// foco
|
|
e.DrawFocusRectangle();
|
|
}
|
|
|
|
private void clbModulos_ItemCheck(object sender, ItemCheckEventArgs e)
|
|
{
|
|
if (_inRefresh) return; // evita loop quando sincronizamos via código
|
|
|
|
var idx = e.Index;
|
|
if (idx < 0 || idx >= _modulosUI.Count) return;
|
|
|
|
// novo valor escolhido pelo usuário
|
|
bool novoUtilizar = e.NewValue == CheckState.Checked;
|
|
|
|
// atualiza UI cache
|
|
_modulosUI[idx].Utilizar = novoUtilizar;
|
|
|
|
// escreve de volta na fonte oficial
|
|
var disp = _modulosUI[idx].Disp;
|
|
var alvo = Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.FirstOrDefault(m => m.Dispositivo.Equals(disp));
|
|
if (alvo != null)
|
|
{
|
|
if (alvo.Utilizar && alvo.Mandatorio && !novoUtilizar)
|
|
{
|
|
CustomDialog.ShowDialog(
|
|
"Confirmação",
|
|
"O módulo selecionado é um item mandatório para a operação atual, tem certeza que deseja desabilitar seu uso?",
|
|
MessageBoxIcon.Information,
|
|
new Dictionary<(string, dynamic), Action>()
|
|
{
|
|
{ ("Sim", null), () => { alvo.Utilizar = novoUtilizar; } },
|
|
{ ("Não", null), () => { _modulosUI[idx].Utilizar = alvo.Utilizar; } }
|
|
}
|
|
);
|
|
}
|
|
else
|
|
{
|
|
alvo.Utilizar = novoUtilizar;
|
|
}
|
|
}
|
|
|
|
// reavaliar liberação da operação
|
|
// (deixa para depois do evento terminar para não travar UI)
|
|
//this.BeginInvoke(new Action(ReavaliarLiberacaoOperacao));
|
|
}
|
|
|
|
private void clbModulos_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (clbModulos.SelectedIndex < 0 || clbModulos.SelectedIndex >= _modulosUI.Count) return;
|
|
txtModuloMotivo.Text = _modulosUI[clbModulos.SelectedIndex].Motivo;
|
|
}
|
|
|
|
private void btnPausarOperacao_Click(object sender, EventArgs e)
|
|
{
|
|
if (!Variaveis.OperacaoEmAndamento.Pausa)
|
|
{
|
|
Variaveis.OperacaoEmAndamento.Pausa = true;
|
|
btnPausarOperacao.Text = "Retomar";
|
|
}
|
|
else
|
|
{
|
|
Variaveis.OperacaoEmAndamento.Pausa = false;
|
|
btnPausarOperacao.Text = "Pausar";
|
|
}
|
|
}
|
|
|
|
private async void btnReferenciar_Click(object sender, EventArgs e)
|
|
{
|
|
await Variaveis.OperacaoEmAndamento.RealizarCalibragemInicialAsync(true);
|
|
}
|
|
|
|
private void btnSalvarParametros_Click(object sender, EventArgs e)
|
|
{
|
|
var res = CustomDialog.ShowDialog(
|
|
"Salvar parâmetros da operação",
|
|
"Deseja aplicar os novos parâmetros para operação atual?",
|
|
MessageBoxIcon.Question,
|
|
new Dictionary<(string, DialogResult?), Action>()
|
|
{
|
|
{ ("Sim", DialogResult.Yes), () => { } },
|
|
{ ("Não", DialogResult.No), () => { } },
|
|
}
|
|
);
|
|
var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle;
|
|
if (res == DialogResult.Yes)
|
|
{
|
|
pControle.FrenagemAutomaticaAoParar = chbFrenagemAutomatica.Checked;
|
|
pControle.MovVelocidadeSErvasPercent = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelSemErvas.Value));
|
|
pControle.MovVelocidadeCErvasPercent = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelComErvas.Value));
|
|
pControle.PulverizadorAutomatico = chbPulverizadorAutomatico.Checked;
|
|
pControle.AtuPercentualInicioPulverizacao = ((double)nudPercentualAtuacaoBico.Value / 100.0);
|
|
pControle.AtuPressaoLinha = (double)nudPressaoLinha.Value;
|
|
|
|
RedisService.AtualizarCampos(
|
|
CtxKey.DadosPesosMPC,
|
|
("posicao", Convert.ToDouble(txtPesoPosicao.Text)),
|
|
("orientacao", Convert.ToDouble(txtPesoOrientacao.Text)),
|
|
("suavidade_min", Convert.ToDouble(txtPesoSuavidadeMin.Text)),
|
|
("suavidade_max", Convert.ToDouble(txtPesoSuavidadeMax.Text)),
|
|
("fator_re", Convert.ToDouble(txtPesoFatorRe.Text)),
|
|
("ideal", Convert.ToDouble(txtPesoIdeal.Text)),
|
|
("lateral_min", Convert.ToDouble(txtPesoLateralMin.Text)),
|
|
("lateral_max", Convert.ToDouble(txtPesoLateralMax.Text))
|
|
);
|
|
|
|
RedisService.AtualizarCampos(CtxKey.DadosOperacao, ("configurado", false));
|
|
}
|
|
else
|
|
{
|
|
chbFrenagemAutomatica.Checked = pControle.FrenagemAutomaticaAoParar;
|
|
nudVelSemErvas.Value = (int)pControle.MovVelocidadeSErvasPercent;
|
|
nudVelComErvas.Value = (int)pControle.MovVelocidadeCErvasPercent;
|
|
chbPulverizadorAutomatico.Checked = pControle.PulverizadorAutomatico;
|
|
nudPercentualAtuacaoBico.Value = (int)pControle.AtuPercentualInicioPulverizacao;
|
|
nudPressaoLinha.Value = (int)pControle.AtuPressaoLinha;
|
|
string pesosMpcStr = RedisService.Get(CtxKey.DadosPesosMPC);
|
|
var pesos = JsonConvert.DeserializeObject<MPCPesosModel>(pesosMpcStr);
|
|
txtPesoPosicao.Text = pesos.posicao.ToString();
|
|
txtPesoOrientacao.Text = pesos.orientacao.ToString();
|
|
txtPesoSuavidadeMin.Text = pesos.suavidade_min.ToString();
|
|
txtPesoSuavidadeMax.Text = pesos.suavidade_max.ToString();
|
|
txtPesoFatorRe.Text = pesos.fator_re.ToString();
|
|
txtPesoIdeal.Text = pesos.ideal.ToString();
|
|
txtPesoLateralMin.Text = pesos.lateral_min.ToString();
|
|
txtPesoLateralMax.Text = pesos.lateral_max.ToString();
|
|
}
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
}
|