interligado telas da ihm Mov, Atu, Nav e Parametrizacao

This commit is contained in:
Diego Freitas 2026-07-21 15:20:08 -03:00
parent 6337847fce
commit ac2a8e249c
29 changed files with 1268 additions and 1078 deletions

View File

@ -513,6 +513,7 @@
<Compile Include="Forms\IHM\frmOperacao.Designer.cs">
<DependentUpon>frmOperacao.cs</DependentUpon>
</Compile>
<Compile Include="Forms\IHM\FuncoesIHM.cs" />
<Compile Include="Forms\IHM\Operacao\HmiCompactMetricCard.cs">
<SubType>UserControl</SubType>
</Compile>

View File

@ -1,4 +1,5 @@
using AgroBase.Forms.IHM.Controls;
using AgroBase.Models;
using System;
using System.ComponentModel;
using System.Drawing;
@ -13,7 +14,7 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
private readonly Button _btnContinuo;
private readonly Button _btnIntermitente;
private string _selectedMode = "Continuo";
private Enums.ModoAgitadorCalda _selectedMode = Enums.ModoAgitadorCalda.SemAgitacao;
public event EventHandler SelectedModeChanged;
@ -50,9 +51,9 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
Controls.Add(layout);
_btnSemAgitacao.Click += delegate { SelectedMode = "SemAgitacao"; };
_btnContinuo.Click += delegate { SelectedMode = "Continuo"; };
_btnIntermitente.Click += delegate { SelectedMode = "Intermitente"; };
_btnSemAgitacao.Click += delegate { SelectedMode = Enums.ModoAgitadorCalda.SemAgitacao; };
_btnContinuo.Click += delegate { SelectedMode = Enums.ModoAgitadorCalda.Continuo; };
_btnIntermitente.Click += delegate { SelectedMode = Enums.ModoAgitadorCalda.Intermitente; };
AtualizarAparencia();
}
@ -80,9 +81,9 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
private void AtualizarAparencia()
{
AplicarEstado(_btnSemAgitacao, _selectedMode == "SemAgitacao");
AplicarEstado(_btnContinuo, _selectedMode == "Continuo");
AplicarEstado(_btnIntermitente, _selectedMode == "Intermitente");
AplicarEstado(_btnSemAgitacao, _selectedMode == Enums.ModoAgitadorCalda.SemAgitacao);
AplicarEstado(_btnContinuo, _selectedMode == Enums.ModoAgitadorCalda.Continuo);
AplicarEstado(_btnIntermitente, _selectedMode == Enums.ModoAgitadorCalda.Intermitente);
}
private static void AplicarEstado(Button button, bool selecionado)
@ -103,24 +104,15 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
[Category("Dados")]
[DefaultValue("Continuo")]
public string SelectedMode
public Enums.ModoAgitadorCalda SelectedMode
{
get { return _selectedMode; }
set
{
string novo;
if (string.Equals(value, "SemAgitacao", StringComparison.OrdinalIgnoreCase))
novo = "SemAgitacao";
else if (string.Equals(value, "Intermitente", StringComparison.OrdinalIgnoreCase))
novo = "Intermitente";
else
novo = "Continuo";
if (_selectedMode == novo)
if (_selectedMode == value)
return;
_selectedMode = novo;
_selectedMode = value;
AtualizarAparencia();
if (SelectedModeChanged != null)

View File

@ -1,4 +1,5 @@
using AgroBase.Forms.IHM.Controls;
using AgroBase.Models;
using System;
using System.ComponentModel;
using System.Drawing;
@ -11,7 +12,7 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
{
private readonly Button _btnMpc;
private readonly Button _btnPid;
private string _selectedMode = "MPC";
private Enums.TiposControladorDirecional _selectedMode = Enums.TiposControladorDirecional.MPC;
public event EventHandler SelectedModeChanged;
@ -60,8 +61,8 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
Controls.Add(root);
_btnMpc.Click += delegate { SelectedMode = "MPC"; };
_btnPid.Click += delegate { SelectedMode = "PID"; };
_btnMpc.Click += delegate { SelectedMode = Enums.TiposControladorDirecional.MPC; };
_btnPid.Click += delegate { SelectedMode = Enums.TiposControladorDirecional.PID; };
AtualizarAparencia();
}
@ -90,8 +91,8 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
private void AtualizarAparencia()
{
AplicarEstado(_btnMpc, _selectedMode == "MPC");
AplicarEstado(_btnPid, _selectedMode == "PID");
AplicarEstado(_btnMpc, _selectedMode == Enums.TiposControladorDirecional.MPC);
AplicarEstado(_btnPid, _selectedMode == Enums.TiposControladorDirecional.PID);
}
private static void AplicarEstado(Button button, bool selected)
@ -112,19 +113,15 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros.Controls
[Category("Dados")]
[DefaultValue("MPC")]
public string SelectedMode
public Enums.TiposControladorDirecional SelectedMode
{
get { return _selectedMode; }
set
{
string novo = string.Equals(value, "PID", StringComparison.OrdinalIgnoreCase)
? "PID"
: "MPC";
if (_selectedMode == novo)
if (_selectedMode == value)
return;
_selectedMode = novo;
_selectedMode = value;
AtualizarAparencia();
if (SelectedModeChanged != null)

View File

@ -15,6 +15,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
DoubleBuffered = true;
BackColor = HmiTheme.Surface;
Height = 24;
Width = 72;
MinimumSize = new Size(105, 22);
Margin = Padding.Empty;
Padding = new Padding(2, 0, 2, 1);
@ -77,5 +78,13 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
get { return _lblValor.ForeColor; }
set { _lblValor.ForeColor = value; }
}
[Category("Layout")]
[DefaultValue(72)]
public int LarguraValor
{
get { return _lblValor.Width; }
set { _lblValor.Width = System.Math.Max(35, value); }
}
}
}

View File

@ -27,12 +27,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
public HmiNozzleCard()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw,
true);
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
DoubleBuffered = true;
BackColor = HmiTheme.SurfaceRaised;
@ -109,12 +104,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
_nozzleGlyph.Click += HandleClick;
}
private static Label MakeLabel(
string text,
float size,
FontStyle style,
Color color,
ContentAlignment align)
private static Label MakeLabel(string text, float size, FontStyle style, Color color, ContentAlignment align)
{
return new Label
{
@ -146,50 +136,16 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
Color border = GetStateColor(_state);
Color border = FuncoesIHM.CorPorStatusModulo(_state);
using (Pen glow = new Pen(
Color.FromArgb(45, border.R, border.G, border.B),
4F))
using (Pen glow = new Pen(Color.FromArgb(45, border.R, border.G, border.B), 4F))
{
e.Graphics.DrawRectangle(
glow,
2,
2,
Math.Max(1, Width - 5),
Math.Max(1, Height - 5));
e.Graphics.DrawRectangle(glow, 2, 2, Math.Max(1, Width - 5), Math.Max(1, Height - 5));
}
using (Pen pen = new Pen(border, 1.3F))
{
e.Graphics.DrawRectangle(
pen,
0,
0,
Math.Max(1, Width - 1),
Math.Max(1, Height - 1));
}
}
private static Color GetStateColor(StatusModulo state)
{
switch (state)
{
case StatusModulo.Desconectado:
return HmiTheme.TextMuted;
case StatusModulo.Conectado:
return HmiTheme.Info;
case StatusModulo.Falha:
return HmiTheme.Danger;
case StatusModulo.Alerta:
return HmiTheme.Warning;
case StatusModulo.Operante:
default:
return HmiTheme.Success;
e.Graphics.DrawRectangle(pen, 0, 0, Math.Max(1, Width - 1), Math.Max(1, Height - 1));
}
}

View File

@ -11,11 +11,13 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
{
private readonly Label _lblTitulo;
private readonly Label _lblDirTitulo;
private readonly CheckBox _chkDir;
private readonly Label _lblDirSp;
private readonly Label _lblDirAtual;
private readonly Label _lblDirStatus;
private readonly Label _lblMovTitulo;
private readonly CheckBox _chkMov;
private readonly Label _lblMovSp;
private readonly Label _lblMovAtual;
@ -25,13 +27,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
public HmiWheelStatusCard()
{
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw,
true
);
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
DoubleBuffered = true;
BackColor = HmiTheme.SurfaceRaised;
@ -50,26 +46,11 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
Padding = Padding.Empty
};
root.ColumnStyles.Add(
new ColumnStyle(SizeType.Percent, 100F)
);
// Título pequeno, liberando espaço para os dados.
root.RowStyles.Add(
new RowStyle(SizeType.Absolute, 18F)
);
root.RowStyles.Add(
new RowStyle(SizeType.Absolute, 1F)
);
root.RowStyles.Add(
new RowStyle(SizeType.Percent, 50F)
);
root.RowStyles.Add(
new RowStyle(SizeType.Percent, 50F)
);
root.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 18F));
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 1F));
root.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
root.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
_lblTitulo = new Label
{
@ -81,11 +62,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
BackColor = Color.FromArgb(28, 34, 38),
ForeColor = HmiTheme.Text,
Font = new Font(
"Segoe UI",
7.8F,
FontStyle.Bold
),
Font = new Font("Segoe UI", 7.8F, FontStyle.Bold),
Text = "EF",
TextAlign = ContentAlignment.MiddleCenter,
@ -101,7 +78,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
Margin = Padding.Empty
};
var pnlDir = CriarBloco(
(Panel pnlDir, Label lblDir) = CriarBloco(
"DIR",
HmiTheme.Manual,
out _chkDir,
@ -110,7 +87,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
out _lblDirStatus
);
var pnlMov = CriarBloco(
(Panel pnlMov, Label lblMov) = CriarBloco(
"MOV",
HmiTheme.Info,
out _chkMov,
@ -119,11 +96,13 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
out _lblMovStatus
);
_lblDirTitulo = lblDir;
_lblDirSp.Text = "SP +0,0°";
_lblDirAtual.Text = "AT +0,0°";
_lblDirStatus.Text = "Parado";
_lblDirStatus.ForeColor = HmiTheme.Success;
_lblMovTitulo = lblMov;
_lblMovSp.Text = "SP 0 rpm";
_lblMovAtual.Text = "AT 0 rpm";
_lblMovStatus.Text = "Sem freio";
@ -142,13 +121,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
_chkMov.BringToFront();
}
private static Panel CriarBloco(
string titulo,
Color corTitulo,
out CheckBox check,
out Label lblSp,
out Label lblAtual,
out Label lblStatus)
private static (Panel, Label) CriarBloco(string titulo, Color corTitulo, out CheckBox check, out Label lblSp, out Label lblAtual, out Label lblStatus)
{
var panel = new Panel
{
@ -168,25 +141,11 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
Padding = Padding.Empty
};
layout.ColumnStyles.Add(
new ColumnStyle(SizeType.Percent, 100F)
);
layout.RowStyles.Add(
new RowStyle(SizeType.Absolute, 18F)
);
layout.RowStyles.Add(
new RowStyle(SizeType.Percent, 30F)
);
layout.RowStyles.Add(
new RowStyle(SizeType.Percent, 30F)
);
layout.RowStyles.Add(
new RowStyle(SizeType.Percent, 40F)
);
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
layout.RowStyles.Add(new RowStyle(SizeType.Absolute, 18F));
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 30F));
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 30F));
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 40F));
var header = new Panel
{
@ -203,11 +162,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
BackColor = Color.Transparent,
ForeColor = corTitulo,
Font = new Font(
"Segoe UI",
6.6F,
FontStyle.Bold
),
Font = new Font("Segoe UI", 6.6F, FontStyle.Bold),
Text = titulo,
TextAlign = ContentAlignment.MiddleLeft,
@ -231,11 +186,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
lblAtual = CriarLabelDado("AT 0");
lblStatus = CriarLabelDado("Parado");
lblStatus.Font = new Font(
"Segoe UI",
5.8F,
FontStyle.Bold
);
lblStatus.Font = new Font("Segoe UI", 5.8F, FontStyle.Bold);
layout.Controls.Add(header, 0, 0);
layout.Controls.Add(lblSp, 0, 1);
@ -244,7 +195,7 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
panel.Controls.Add(layout);
return panel;
return (panel, lblTitulo);
}
private static Label CriarLabelDado(string texto)
@ -333,20 +284,24 @@ namespace AgroBase.Forms.IHM.Controls.Operacao
public void AtualizarDados(
bool dir_em_uso,
StatusModulo dir_status,
double dir_ang_sp,
double dir_ang_at,
Sentido dir_sentido,
bool mov_em_uso,
StatusModulo mov_status,
double mov_vel_sp,
double mov_vel_at,
bool mov_freio
)
{
_lblDirTitulo.ForeColor = FuncoesIHM.CorPorStatusModulo(dir_status);
CheckDir.Checked = dir_em_uso;
DirecionalSp = $"{dir_ang_sp}";
DirecionalAtual = $"{dir_ang_at}";
StatusDirecional = $"{dir_sentido}";
_lblMovTitulo.ForeColor = FuncoesIHM.CorPorStatusModulo(mov_status);
CheckMov.Checked = mov_em_uso;
MovimentoSp = $"{mov_vel_sp}";
MovimentoAtual = $"{mov_vel_at}";

View File

@ -0,0 +1,355 @@
using AgroBase.Forms.IHM.Controls;
using AgroBase.Models;
using System;
using System.Drawing;
using static AgroBase.Models.Enums;
namespace AgroBase.Forms.IHM
{
public class FuncoesIHM
{
public static Color MisturarCores(Color baseColor, Color accentColor, float pesoAccent)
{
pesoAccent = Math.Max(0F, Math.Min(1F, pesoAccent));
float pesoBase = 1F - pesoAccent;
return Color.FromArgb(
(int)(baseColor.R * pesoBase + accentColor.R * pesoAccent),
(int)(baseColor.G * pesoBase + accentColor.G * pesoAccent),
(int)(baseColor.B * pesoBase + accentColor.B * pesoAccent)
);
}
public static Color CorPorPercentual(double percentual)
{
percentual = Limitar(percentual, 0, 100);
if (percentual <= 50)
{
double fator = percentual / 50.0;
return InterpolarCor(HmiTheme.Danger, HmiTheme.Warning, fator);
}
double fatorVerde = (percentual - 50) / 50.0;
return InterpolarCor(HmiTheme.Warning, HmiTheme.Success, fatorVerde);
}
public static Color CorPorValorESaude(double valor, double saude)
{
double notaFinal = Math.Min(Limitar(valor, 0, 100), Limitar(saude, 0, 100));
return CorPorPercentual(notaFinal);
}
public static Color CorTemperatura(double temperatura, double saudeModulo)
{
Color corTemperatura;
if (temperatura <= 45)
{
corTemperatura = HmiTheme.Success;
}
else if (temperatura <= 60)
{
double fator = (temperatura - 45) / (60 - 45);
corTemperatura = InterpolarCor(HmiTheme.Success, HmiTheme.Warning, fator);
}
else if (temperatura <= 75)
{
double fator = (temperatura - 60) / (75 - 60);
corTemperatura = InterpolarCor(HmiTheme.Warning, HmiTheme.Danger, fator);
}
else
{
corTemperatura = HmiTheme.Danger;
}
Color corSaude = CorPorPercentual(saudeModulo);
/*
* Se a saúde estiver muito baixa,
* ela prevalece sobre a temperatura.
*/
if (saudeModulo < 40)
return corSaude;
return corTemperatura;
}
public static Color CorDistanciaBase(double distanciaMetros, double distanciaMaximaMetros)
{
if (double.IsNaN(distanciaMetros) || double.IsInfinity(distanciaMetros) || distanciaMetros < 0)
{
return HmiTheme.Danger;
}
double percentualSaudavel = 100 - (distanciaMetros / distanciaMaximaMetros * 100);
return CorPorPercentual(percentualSaudavel);
}
public static Color InterpolarCor(Color inicial, Color final, double fator)
{
fator = Limitar(fator, 0, 1);
int r = (int)Math.Round(inicial.R + (final.R - inicial.R) * fator);
int g = (int)Math.Round(inicial.G + (final.G - inicial.G) * fator);
int b = (int)Math.Round(inicial.B + (final.B - inicial.B) * fator);
return Color.FromArgb(r, g, b);
}
public static Color CorPorStatusModulo(StatusModulo state)
{
switch (state)
{
case StatusModulo.Desconectado:
return HmiTheme.TextMuted;
case StatusModulo.Conectado:
return HmiTheme.Info;
case StatusModulo.Falha:
return HmiTheme.Danger;
case StatusModulo.Alerta:
return HmiTheme.Warning;
case StatusModulo.Operante:
default:
return HmiTheme.Success;
}
}
public static Color CorPorAutonomia(double distanciaCapaz, double distanciaNecessaria, double limiar)
{
StatusModulo status = CalcularStatusAutonomiaCorredor(distanciaCapaz, distanciaNecessaria, limiar);
switch (status)
{
case StatusModulo.Operante:
return HmiTheme.Success;
case StatusModulo.Alerta:
return HmiTheme.Warning;
case StatusModulo.Falha:
return HmiTheme.Danger;
default:
return HmiTheme.Disabled;
}
}
public static Color CorPorErroNumerico(double atual, double sp, double limiarWarning, double limiarDanger)
{
double erro = Math.Abs(atual - sp);
if (erro >= Math.Abs(limiarDanger))
return HmiTheme.Danger;
if (erro >= Math.Abs(limiarWarning))
return HmiTheme.Warning;
return HmiTheme.Success;
}
public static Color CorPorErroAngular(double atual, double sp, double limiarWarning, double limiarDanger)
{
double erro = Math.Abs(CalcularErroAngular(atual, sp));
if (erro >= Math.Abs(limiarDanger))
return HmiTheme.Danger;
if (erro >= Math.Abs(limiarWarning))
return HmiTheme.Warning;
return HmiTheme.Success;
}
public static double NotaQualidadeGnss(TiposCorrecaoGPS qualidade)
{
switch (qualidade)
{
case TiposCorrecaoGPS.RTKFixo:
return 100;
case TiposCorrecaoGPS.BaseFix:
return 100;
case TiposCorrecaoGPS.RTKFlutuante:
return 78;
case TiposCorrecaoGPS.PPS:
return 65;
case TiposCorrecaoGPS.DGPS:
return 58;
case TiposCorrecaoGPS.DeadReckoing:
return 35;
case TiposCorrecaoGPS.Autonomo:
return 22;
case TiposCorrecaoGPS.SemCorrecao:
default:
return 0;
}
}
public static double NotaPrecisaoGnss(double precisaoCm)
{
if (precisaoCm <= 2)
return 100;
if (precisaoCm <= 5)
return InterpolarValor(precisaoCm, 2, 5, 100, 90);
if (precisaoCm <= 10)
return InterpolarValor(precisaoCm, 5, 10, 90, 75);
if (precisaoCm <= 30)
return InterpolarValor(precisaoCm, 10, 30, 75, 50);
if (precisaoCm <= 100)
return InterpolarValor(precisaoCm, 30, 100, 50, 20);
return 5;
}
public static double CalcularNotaGnss(TiposCorrecaoGPS qualidade, double precisaoCm, double saudeModulo)
{
double notaFix = NotaQualidadeGnss(qualidade);
double notaPrecisao = NotaPrecisaoGnss(precisaoCm);
/*
* O pior dos três critérios define a cor.
*
* RTK Fixo com saúde ruim não fica verde.
* Saúde boa com modo autônomo também não.
*/
return Math.Min(notaFix, Math.Min(notaPrecisao, Limitar(saudeModulo, 0, 100)));
}
public static StatusModulo CalcularStatusAutonomiaCorredor(double distanciaCapaz, double distanciaNecessaria, double limiar)
{
StatusModulo status =
distanciaNecessaria > (distanciaCapaz + limiar) ? StatusModulo.Operante :
distanciaNecessaria > (distanciaCapaz - limiar) ? StatusModulo.Alerta :
StatusModulo.Falha;
return status;
}
public static double CalcularErroAngular(double atual, double sp)
{
double erro = (atual - sp) % 360.0;
if (erro > 180.0)
erro -= 360.0;
else if (erro < -180.0)
erro += 360.0;
return erro;
}
public static string FormatarQualidadeGnss(TiposCorrecaoGPS qualidade)
{
switch (qualidade)
{
case Enums.TiposCorrecaoGPS.SemCorrecao:
return "Sem correção";
case Enums.TiposCorrecaoGPS.Autonomo:
return "Autônomo";
case Enums.TiposCorrecaoGPS.DGPS:
return "DGPS";
case Enums.TiposCorrecaoGPS.PPS:
return "PPS";
case Enums.TiposCorrecaoGPS.RTKFixo:
return "RTK Fixo";
case Enums.TiposCorrecaoGPS.RTKFlutuante:
return "RTK Flutuante";
case Enums.TiposCorrecaoGPS.DeadReckoing:
return "Dead Reckoning";
case Enums.TiposCorrecaoGPS.BaseFix:
return "Base Fix";
default:
return "Desconhecido";
}
}
public static string FormatarDistancia(double distanciaMetros)
{
if (double.IsNaN(distanciaMetros) || double.IsInfinity(distanciaMetros) || distanciaMetros < 0)
{
return "Indisponível";
}
if (distanciaMetros >= 1000)
{
return $"{distanciaMetros / 1000.0:0.00} km";
}
return $"{distanciaMetros:0.0} m";
}
public static string FormatarTempo(TimeSpan tempo)
{
if (tempo < TimeSpan.Zero)
tempo = TimeSpan.Zero;
int horasTotais = (int)tempo.TotalHours;
return string.Format(
"{0:00}:{1:00}:{2:00}",
horasTotais,
tempo.Minutes,
tempo.Seconds
);
}
public static double InterpolarValor(double valor, double origemMinima, double origemMaxima, double destinoInicial, double destinoFinal)
{
if (origemMaxima <= origemMinima)
return destinoInicial;
double fator = (valor - origemMinima) / (origemMaxima - origemMinima);
fator = Limitar(fator, 0, 1);
return destinoInicial + (destinoFinal - destinoInicial) * fator;
}
public static double Limitar(double valor, double minimo, double maximo)
{
return Math.Max(minimo, Math.Min(maximo, valor));
}
public static void AplicarEstadoPainel(HmiRoundedPanel panel, Color color)
{
panel.BorderColor = color;
panel.Invalidate();
}
}
}

View File

@ -1,4 +1,6 @@
namespace AgroBase.Forms.IHM.Operacao.Parametros
using AgroBase.Models;
namespace AgroBase.Forms.IHM.Operacao.Parametros
{
partial class ucParametrosAtuador
{
@ -106,7 +108,7 @@
this.seletorModoAgitador.Margin = new System.Windows.Forms.Padding(0, 3, 0, 5);
this.seletorModoAgitador.MinimumSize = new System.Drawing.Size(0, 40);
this.seletorModoAgitador.Name = "seletorModoAgitador";
this.seletorModoAgitador.SelectedMode = "Continuo";
this.seletorModoAgitador.SelectedMode = Enums.ModoAgitadorCalda.SemAgitacao;
this.seletorModoAgitador.Size = new System.Drawing.Size(282, 42);
this.seletorModoAgitador.TabIndex = 2;
//

View File

@ -1,36 +1,20 @@
using System;
using AgroBase.Models;
using System;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Operacao.Parametros
{
public partial class ucParametrosAtuador : UserControl
{
public event EventHandler ParametrosAlterados;
private OperacaoModel op;
private bool _carregandoDados;
public ucParametrosAtuador()
{
InitializeComponent();
ConfigurarEstadoInicial();
VincularEventos();
}
private void ConfigurarEstadoInicial()
{
seletorModoAgitador.SelectedMode = "Continuo";
paramKp.Value = 1.00M;
paramKi.Value = 0.10M;
paramKd.Value = 0.00M;
paramBicosEmUso.Value = 7M;
paramPressaoLinha.Value = 18M;
paramInicioTela.Value = 85M;
paramAlturaArea.Value = 15M;
paramErvasOn.Value = 25M;
paramErvasOff.Value = 15M;
}
private void VincularEventos()
{
seletorModoAgitador.SelectedModeChanged += Controle_Alterado;
@ -47,70 +31,63 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros
paramErvasOff.ValueChanged += Controle_Alterado;
}
public void DefinirOperacao(OperacaoModel operacao)
{
op = operacao;
CarregarDadosTela();
}
private void CarregarDadosTela()
{
try
{
var parametros = op?.Parametros?.Controle;
var agitador = op?.DispAtu?.Dados?.AgitadorDeCalda?.Controle;
seletorModoAgitador.SelectedMode = parametros?.AtuAgitadorModo ?? Enums.ModoAgitadorCalda.SemAgitacao;
paramKp.Value = (decimal)(agitador?.Kp ?? 0);
paramKi.Value = (decimal)(agitador?.Ki ?? 0);
paramKd.Value = (decimal)(agitador?.Kd ?? 0);
paramBicosEmUso.Value = op?.Parametros?.QtdBicos ?? 0;
paramPressaoLinha.Value = (decimal)(parametros?.AtuPressaoLinha ?? 0);
paramInicioTela.Value = (decimal)(parametros?.AtuPercentualInicioPulverizacao ?? 0);
paramAlturaArea.Value = (decimal)(parametros?.AtuAlturaAreaPulverizacao ?? 0);
paramErvasOn.Value = (decimal)(parametros?.AtuPercentualErvasBicoOn ?? 0);
paramErvasOff.Value = (decimal)(parametros?.AtuPercentualErvasBicoOff ?? 0);
}
finally
{
_carregandoDados = false;
}
}
private void Controle_Alterado(object sender, EventArgs e)
{
if (ParametrosAlterados != null)
ParametrosAlterados(this, EventArgs.Empty);
}
if (_carregandoDados)
return;
public string ModoAgitador
{
get { return seletorModoAgitador.SelectedMode; }
set { seletorModoAgitador.SelectedMode = value; }
}
var parametros = op?.Parametros?.Controle;
var agitador = op?.DispAtu?.Dados?.AgitadorDeCalda?.Controle;
public decimal KpAgitador
{
get { return paramKp.Value; }
set { paramKp.Value = value; }
}
if (parametros == null)
return;
public decimal KiAgitador
{
get { return paramKi.Value; }
set { paramKi.Value = value; }
}
parametros.AtuAgitadorModo = seletorModoAgitador.SelectedMode;
public decimal KdAgitador
{
get { return paramKd.Value; }
set { paramKd.Value = value; }
}
agitador.Kp = (double)paramKp.Value;
agitador.Ki = (double)paramKi.Value;
agitador.Kd = (double)paramKd.Value;
public int QuantidadeBicosEmUso
{
get { return Convert.ToInt32(paramBicosEmUso.Value); }
set { paramBicosEmUso.Value = value; }
}
op.Parametros.QtdBicos = (int)paramBicosEmUso.Value;
parametros.AtuPressaoLinha = (double)paramPressaoLinha.Value;
public decimal PressaoLinhaPsi
{
get { return paramPressaoLinha.Value; }
set { paramPressaoLinha.Value = value; }
}
public int PercentualInicioTela
{
get { return Convert.ToInt32(paramInicioTela.Value); }
set { paramInicioTela.Value = value; }
}
public int PercentualAlturaArea
{
get { return Convert.ToInt32(paramAlturaArea.Value); }
set { paramAlturaArea.Value = value; }
}
public decimal PercentualErvasOn
{
get { return paramErvasOn.Value; }
set { paramErvasOn.Value = value; }
}
public decimal PercentualErvasOff
{
get { return paramErvasOff.Value; }
set { paramErvasOff.Value = value; }
parametros.AtuPercentualInicioPulverizacao = (double)paramInicioTela.Value;
parametros.AtuAlturaAreaPulverizacao = (double)paramAlturaArea.Value;
parametros.AtuPercentualErvasBicoOn = (double)paramErvasOn.Value;
parametros.AtuPercentualErvasBicoOff = (double)paramErvasOff.Value;
}
}
}

View File

@ -1,4 +1,6 @@
namespace AgroBase.Forms.IHM.Operacao.Parametros
using AgroBase.Models;
namespace AgroBase.Forms.IHM.Operacao.Parametros
{
partial class ucParametrosDirecional
{
@ -180,7 +182,7 @@
this.seletorModoControle.Dock = System.Windows.Forms.DockStyle.Fill;
this.seletorModoControle.Margin = new System.Windows.Forms.Padding(0, 1, 3, 0);
this.seletorModoControle.MinimumSize = System.Drawing.Size.Empty;
this.seletorModoControle.SelectedMode = "MPC";
this.seletorModoControle.SelectedMode = Enums.TiposControladorDirecional.MPC;
this.parametroHorizonte.Dock = System.Windows.Forms.DockStyle.Fill;
this.parametroHorizonte.Margin = new System.Windows.Forms.Padding(3, 1, 3, 0);

View File

@ -1,38 +1,20 @@
using System;
using AgroBase.Models;
using System;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Operacao.Parametros
{
public partial class ucParametrosDirecional : UserControl
{
public event EventHandler ParametrosAlterados;
private OperacaoModel op;
private bool _carregandoDados;
public ucParametrosDirecional()
{
InitializeComponent();
ConfigurarEstadoInicial();
VincularEventos();
}
private void ConfigurarEstadoInicial()
{
checkDirecionalAutomatico.Checked = true;
checkAssistidoSonar.Checked = true;
checkAssistidoImu.Checked = true;
checkImuPrefereArco.Checked = false;
sliderAnguloMaximo.Value = 45;
sliderAnguloMaximo.VelocidadeMaximaKmh = 0D;
sliderVelocidadeDirecional.Value = 60;
sliderVelocidadeDirecional.VelocidadeMaximaKmh = 0D;
seletorModoControle.SelectedMode = "MPC";
parametroHorizonte.Value = 4M;
parametroDistanciaSaida.Value = 5M;
}
private void VincularEventos()
{
checkDirecionalAutomatico.CheckedChanged += Controle_Alterado;
@ -48,64 +30,63 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros
parametroDistanciaSaida.ValueChanged += Controle_Alterado;
}
public void DefinirOperacao(OperacaoModel operacao)
{
op = operacao;
CarregarDadosTela();
}
private void CarregarDadosTela()
{
_carregandoDados = true;
try
{
var parametros = op?.Parametros?.Controle;
checkDirecionalAutomatico.Checked = parametros?.DirecionalAutomatico ?? false;
checkAssistidoSonar.Checked = parametros?.DirAuxilioSonar ?? false;
checkAssistidoImu.Checked = parametros?.ImuAuxilioDirecional ?? false;
checkImuPrefereArco.Checked = parametros?.ImuDirecionalPreferirArco ?? false;
sliderAnguloMaximo.Value = parametros?.DirAnguloMaximo ?? 0;
sliderVelocidadeDirecional.Value = (int)(parametros?.DirVelocidadeMovimento ?? 0);
seletorModoControle.SelectedMode = parametros?.DirTipoMovimento ?? Enums.TiposControladorDirecional.MPC;
parametroHorizonte.Value = (decimal)(parametros?.MpcHorizonte ?? 0);
parametroDistanciaSaida.Value = (decimal)(parametros?.DistanciaManobra ?? 0);
}
finally
{
_carregandoDados = false;
}
}
private void Controle_Alterado(object sender, EventArgs e)
{
if (ParametrosAlterados != null)
ParametrosAlterados(this, EventArgs.Empty);
}
if (_carregandoDados)
return;
public bool DirecionalAutomatico
{
get { return checkDirecionalAutomatico.Checked; }
set { checkDirecionalAutomatico.Checked = value; }
}
var parametros = op?.Parametros?.Controle;
public bool AssistidoPorSonar
{
get { return checkAssistidoSonar.Checked; }
set { checkAssistidoSonar.Checked = value; }
}
if (parametros == null)
return;
public bool AssistidoPorImu
{
get { return checkAssistidoImu.Checked; }
set { checkAssistidoImu.Checked = value; }
}
parametros.DirecionalAutomatico = checkDirecionalAutomatico.Checked;
parametros.DirAuxilioSonar = checkAssistidoSonar.Checked;
parametros.ImuAuxilioDirecional = checkAssistidoImu.Checked;
parametros.ImuDirecionalPreferirArco = checkImuPrefereArco.Checked;
public bool ImuPrefereArco
{
get { return checkImuPrefereArco.Checked; }
set { checkImuPrefereArco.Checked = value; }
}
parametros.DirAnguloMaximo = sliderAnguloMaximo.Value;
public int AnguloMaximo
{
get { return sliderAnguloMaximo.Value; }
set { sliderAnguloMaximo.Value = value; }
}
parametros.DirVelocidadeMovimento = sliderVelocidadeDirecional.Value;
public int VelocidadeDirecionalPercentual
{
get { return sliderVelocidadeDirecional.Value; }
set { sliderVelocidadeDirecional.Value = value; }
}
parametros.DirTipoMovimento = seletorModoControle.SelectedMode;
public string ModoControle
{
get { return seletorModoControle.SelectedMode; }
set { seletorModoControle.SelectedMode = value; }
}
public decimal HorizontePredicaoMetros
{
get { return parametroHorizonte.Value; }
set { parametroHorizonte.Value = value; }
}
public decimal DistanciaSaidaCorredorMetros
{
get { return parametroDistanciaSaida.Value; }
set { parametroDistanciaSaida.Value = value; }
parametros.MpcHorizonte = (double)parametroHorizonte.Value;
parametros.DistanciaManobra = (double)parametroDistanciaSaida.Value;
}
}
}

View File

@ -1,20 +1,67 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AgroBase.Models;
using System;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Operacao.Parametros
{
public partial class ucParametrosMapa : UserControl
{
private OperacaoModel op;
private bool _carregandoDados;
public ucParametrosMapa()
{
InitializeComponent();
VincularEventos();
}
private void VincularEventos()
{
seletorModoAgitador.SelectedModeChanged += Controle_Alterado;
paramKp.ValueChanged += Controle_Alterado;
paramKi.ValueChanged += Controle_Alterado;
paramKd.ValueChanged += Controle_Alterado;
paramBicosEmUso.ValueChanged += Controle_Alterado;
paramPressaoLinha.ValueChanged += Controle_Alterado;
paramInicioTela.ValueChanged += Controle_Alterado;
paramAlturaArea.ValueChanged += Controle_Alterado;
paramErvasOn.ValueChanged += Controle_Alterado;
paramErvasOff.ValueChanged += Controle_Alterado;
}
public void DefinirOperacao(OperacaoModel operacao)
{
op = operacao;
CarregarDadosTela();
}
private void CarregarDadosTela()
{
try
{
var parametros = op?.Parametros?.Controle;
// preenchimento dos dados
}
finally
{
_carregandoDados = false;
}
}
private void Controle_Alterado(object sender, EventArgs e)
{
if (_carregandoDados)
return;
var parametros = op?.Parametros?.Controle;
if (parametros == null)
return;
// definicao dos parametros
}
}
}

View File

@ -1,4 +1,4 @@
using AgroBase.Forms.IHM.Operacao.Parametros.Controls;
using AgroBase.Models;
using System;
using System.Windows.Forms;
@ -6,31 +6,15 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros
{
public partial class ucParametrosMovimento : UserControl
{
public event EventHandler ParametrosAlterados;
private OperacaoModel op;
private bool _carregandoDados;
public ucParametrosMovimento()
{
InitializeComponent();
ConfigurarEstadoInicial();
VincularEventos();
}
private void ConfigurarEstadoInicial()
{
checkMovimentoAutomatico.Checked = true;
checkAssistidoSonar.Checked = true;
checkParadaObstaculo.Checked = true;
checkAssistidoImu.Checked = true;
checkParadaInclinacao.Checked = true;
checkFrenagemParar.Checked = true;
sliderSemErvas.Value = 68;
sliderSemErvas.VelocidadeMaximaKmh = 5D;
sliderComErvas.Value = 45;
sliderComErvas.VelocidadeMaximaKmh = 5D;
}
private void VincularEventos()
{
checkMovimentoAutomatico.CheckedChanged += Controle_Alterado;
@ -44,68 +28,58 @@ namespace AgroBase.Forms.IHM.Operacao.Parametros
sliderComErvas.ValueChanged += Controle_Alterado;
}
public void DefinirOperacao(OperacaoModel operacao)
{
op = operacao;
CarregarDadosTela();
}
private void CarregarDadosTela()
{
_carregandoDados = true;
try
{
var parametros = op?.Parametros?.Controle;
checkMovimentoAutomatico.Checked = parametros?.MovimentoAutomatico ?? false;
checkAssistidoSonar.Checked = parametros?.MovAuxilioSonar ?? false;
checkParadaObstaculo.Checked = parametros?.OakParadaPorObstaculo ?? false;
checkAssistidoImu.Checked = parametros?.ImuAuxilioMovimento ?? false;
checkParadaInclinacao.Checked = parametros?.ImuParadaPorInclinacao ?? false;
checkFrenagemParar.Checked = parametros?.FrenagemAutomaticaAoParar ?? false;
sliderSemErvas.VelocidadeMaximaKmh = FuncoesMatematicas.CalculaVelocidadeRPM(VariaveisEquipamento.RPM_Max_Roda);
sliderComErvas.VelocidadeMaximaKmh = FuncoesMatematicas.CalculaVelocidadeRPM(VariaveisEquipamento.RPM_Max_Roda);
sliderSemErvas.Value = parametros?.MovVelocidadeSErvasPercent ?? 0;
sliderComErvas.Value = parametros?.MovVelocidadeCErvasPercent ?? 0;
}
finally
{
_carregandoDados = false;
}
}
private void Controle_Alterado(object sender, EventArgs e)
{
if (ParametrosAlterados != null)
ParametrosAlterados(this, EventArgs.Empty);
}
if (_carregandoDados)
return;
public bool MovimentoAutomatico
{
get { return checkMovimentoAutomatico.Checked; }
set { checkMovimentoAutomatico.Checked = value; }
}
var parametros = op?.Parametros?.Controle;
public bool AssistidoPorSonar
{
get { return checkAssistidoSonar.Checked; }
set { checkAssistidoSonar.Checked = value; }
}
if (parametros == null)
return;
public bool ParadaPorObstaculo
{
get { return checkParadaObstaculo.Checked; }
set { checkParadaObstaculo.Checked = value; }
}
parametros.MovimentoAutomatico = checkMovimentoAutomatico.Checked;
parametros.MovAuxilioSonar = checkAssistidoSonar.Checked;
parametros.OakParadaPorObstaculo = checkParadaObstaculo.Checked;
parametros.ImuAuxilioMovimento = checkAssistidoImu.Checked;
parametros.ImuParadaPorInclinacao = checkParadaInclinacao.Checked;
parametros.FrenagemAutomaticaAoParar = checkFrenagemParar.Checked;
public bool AssistidoPorImu
{
get { return checkAssistidoImu.Checked; }
set { checkAssistidoImu.Checked = value; }
}
public bool ParadaPorInclinacao
{
get { return checkParadaInclinacao.Checked; }
set { checkParadaInclinacao.Checked = value; }
}
public bool FrenagemAoParar
{
get { return checkFrenagemParar.Checked; }
set { checkFrenagemParar.Checked = value; }
}
public int VelocidadeSemErvasPercentual
{
get { return sliderSemErvas.Value; }
set { sliderSemErvas.Value = value; }
}
public int VelocidadeComErvasPercentual
{
get { return sliderComErvas.Value; }
set { sliderComErvas.Value = value; }
}
public double VelocidadeMaximaEquipamentoKmh
{
get { return sliderSemErvas.VelocidadeMaximaKmh; }
set
{
sliderSemErvas.VelocidadeMaximaKmh = value;
sliderComErvas.VelocidadeMaximaKmh = value;
}
parametros.MovVelocidadeSErvasPercent = sliderSemErvas.Value;
parametros.MovVelocidadeCErvasPercent = sliderComErvas.Value;
}
}
}

View File

@ -22,7 +22,7 @@ namespace AgroBase.Forms.IHM.Operacao
private bool _atualizandoSlider = false;
private bool _requisitandoCameraFrame;
private bool _controleDescartado;
OperacaoModel op => Variaveis.OperacaoEmAndamento;
private OperacaoModel op => Variaveis.OperacaoEmAndamento;
public ucOperacaoMovimentacao()
{
@ -236,6 +236,8 @@ namespace AgroBase.Forms.IHM.Operacao
AtualizarDadosImu(dados.IMU);
AtualizarDadosTelemetria(dados);
AtualizarSaudeModulos();
}
public void AtualizarDadosControle(OperacaoControleModel controle, OperacaoParametrosControleModel parametros)
@ -246,9 +248,9 @@ namespace AgroBase.Forms.IHM.Operacao
return;
sliderVelocidadeMax.VelocidadeMaximaKmh = FuncoesMatematicas.CalculaVelocidadeRPM(VariaveisEquipamento.RPM_Max_Roda);
sliderVelocidadeMax.Value = (int)Limitar(controle?.PercentualVelocidadeSP ?? 0, sliderVelocidadeMax.Minimum, sliderVelocidadeMax.Maximum);
sliderAngulo.Value = (int)Limitar(controle?.Angulo ?? 0, sliderAngulo.Minimum, sliderAngulo.Maximum);
sliderVelocidadeDir.Value = (int)Limitar(parametros?.DirVelocidadeMovimento ?? 0, sliderVelocidadeDir.Minimum, sliderVelocidadeDir.Maximum);
sliderVelocidadeMax.Value = (int)FuncoesIHM.Limitar(controle?.PercentualVelocidadeSP ?? 0, sliderVelocidadeMax.Minimum, sliderVelocidadeMax.Maximum);
sliderAngulo.Value = (int)FuncoesIHM.Limitar(controle?.Angulo ?? 0, sliderAngulo.Minimum, sliderAngulo.Maximum);
sliderVelocidadeDir.Value = (int)FuncoesIHM.Limitar(parametros?.DirVelocidadeMovimento ?? 0, sliderVelocidadeDir.Minimum, sliderVelocidadeDir.Maximum);
}
private void AtualizarListaJoysticks()
@ -294,15 +296,20 @@ namespace AgroBase.Forms.IHM.Operacao
if (_modoManualAtivado && !forcar)
return;
var saude_dir = op?.Sensoriamento?.OperadorSaude?.ModulosSaude?.FirstOrDefault(x => x.modulo == T_Code.Dir)?.saude_individual?.FirstOrDefault(x => x.id == card.Tag.ToString());
var saude_mov = op?.Sensoriamento?.OperadorSaude?.ModulosSaude?.FirstOrDefault(x => x.modulo == T_Code.Mov)?.saude_individual?.FirstOrDefault(x => x.id == card.Tag.ToString());
var Dir = Mods.FirstOrDefault(x => x.Modulo_ID == card.Tag.ToString())?.DirMotor;
var Mov = Mods.FirstOrDefault(x => x.Modulo_ID == card.Tag.ToString())?.MovMotor;
card.AtualizarDados(
dir_em_uso: Dir?.Comandar ?? false,
dir_status: saude_dir?.status ?? StatusModulo.Desconectado,
dir_ang_sp: Dir?.Angulo_SP ?? 0,
dir_ang_at: Dir?.AnguloReal ?? 0,
dir_sentido: Dir?.SentidoReal ?? Sentido.Parado,
mov_em_uso: Mov?.Comandar ?? false,
mov_status: saude_mov?.status ?? StatusModulo.Desconectado,
mov_vel_sp: Mov?.RPM_SP ?? 0,
mov_vel_at: Mov?.RPM_Roda ?? 0,
mov_freio: Mov?.UltimoFreioSP ?? false
@ -438,11 +445,17 @@ namespace AgroBase.Forms.IHM.Operacao
}
private static double Limitar(double valor, double minimo, double maximo)
private void AtualizarSaudeModulos()
{
return Math.Max(minimo, Math.Min(maximo, valor));
var saude_m = op?.Sensoriamento?.OperadorSaude?.ModulosSaude;
var saudeCamera = saude_m?.FirstOrDefault(x => x.modulo == T_Code.Snr)?.status ?? StatusModulo.Desconectado;
var saudeImu = saude_m?.FirstOrDefault(x => x.modulo == T_Code.Imu)?.status ?? StatusModulo.Desconectado;
FuncoesIHM.AplicarEstadoPainel(pnlCamera, FuncoesIHM.CorPorStatusModulo(saudeCamera));
FuncoesIHM.AplicarEstadoPainel(pnlRadar, FuncoesIHM.CorPorStatusModulo(saudeCamera));
FuncoesIHM.AplicarEstadoPainel(pnlImu, FuncoesIHM.CorPorStatusModulo(saudeImu));
}
}
}

View File

@ -30,7 +30,8 @@ namespace AgroBase.Forms.IHM.Operacao
this.btnMapaWeb = new System.Windows.Forms.Button();
this.btnMapaDinamico = new System.Windows.Forms.Button();
this.pnlMapaVisual = new AgroBase.Forms.IHM.Controls.HmiRoundedPanel();
this.lblMapaPlaceholder = new System.Windows.Forms.Label();
this.pnlMapaWeb = new System.Windows.Forms.Panel();
this.pnlMapaDinamico = new System.Windows.Forms.Panel();
this.rightTopLayout = new System.Windows.Forms.TableLayoutPanel();
@ -166,21 +167,21 @@ namespace AgroBase.Forms.IHM.Operacao
SetupMapButton(this.btnMapaDinamico, "Trajetória");
this.pnlMapaVisual.BorderColor = AgroBase.Forms.IHM.Controls.HmiTheme.Border;
this.pnlMapaVisual.Controls.Add(this.lblMapaPlaceholder);
this.pnlMapaVisual.CornerRadius = 8;
this.pnlMapaVisual.Dock = System.Windows.Forms.DockStyle.Fill;
this.pnlMapaVisual.FillColor = System.Drawing.Color.FromArgb(18, 29, 22);
this.pnlMapaVisual.Controls.Add(this.pnlMapaWeb);
this.pnlMapaVisual.Controls.Add(this.pnlMapaDinamico);
this.lblMapaPlaceholder.Dock = System.Windows.Forms.DockStyle.Fill;
this.lblMapaPlaceholder.BackColor = System.Drawing.Color.Transparent;
this.lblMapaPlaceholder.ForeColor = AgroBase.Forms.IHM.Controls.HmiTheme.Success;
this.lblMapaPlaceholder.Font = new System.Drawing.Font("Consolas", 9F, System.Drawing.FontStyle.Bold);
this.lblMapaPlaceholder.Text =
"MAPA / TRAJETÓRIA\n\n" +
"Rua atual: 12 / 35\n\n" +
" ○ 125\n │\n ○ 126\n │\n [ROVER]\n │\n ○ 127\n\n" +
"Coordenadas: -23.5621, -46.6542\nAltitude: 812 m";
this.lblMapaPlaceholder.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.pnlMapaWeb.Dock = DockStyle.Fill;
this.pnlMapaWeb.Margin = Padding.Empty;
this.pnlMapaWeb.Padding = Padding.Empty;
this.pnlMapaWeb.BackColor = Color.Black;
this.pnlMapaDinamico.Dock = DockStyle.Fill;
this.pnlMapaDinamico.Margin = Padding.Empty;
this.pnlMapaDinamico.Padding = Padding.Empty;
this.pnlMapaDinamico.BackColor = HmiTheme.Text;
this.rightTopLayout.ColumnCount = 2;
this.rightTopLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 54F));
@ -235,10 +236,10 @@ namespace AgroBase.Forms.IHM.Operacao
this.orientationValuesLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 18F));
this.orientationValuesLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 32F));
SetupHeadingTitle(this.lblRoverTitulo, "Rover", AgroBase.Forms.IHM.Controls.HmiTheme.Success);
SetupHeadingTitle(this.lblRoverTitulo, "Rover", AgroBase.Forms.IHM.Controls.HmiTheme.Text);
SetupHeadingValue(this.lblRoverValor, "128°", AgroBase.Forms.IHM.Controls.HmiTheme.Success);
SetupHeadingTitle(this.lblTrajetoriaTitulo, "Trajetória", AgroBase.Forms.IHM.Controls.HmiTheme.Warning);
SetupHeadingValue(this.lblTrajetoriaValor, "136°", AgroBase.Forms.IHM.Controls.HmiTheme.Warning);
SetupHeadingTitle(this.lblTrajetoriaTitulo, "Trajetória", AgroBase.Forms.IHM.Controls.HmiTheme.Text);
SetupHeadingValue(this.lblTrajetoriaValor, "136°", AgroBase.Forms.IHM.Controls.HmiTheme.Manual);
ConfigurePanel(this.pnlGnss, this.gnssLayout);
this.pnlGnss.Padding = new Padding(6, 4, 6, 4);
@ -253,16 +254,16 @@ namespace AgroBase.Forms.IHM.Operacao
this.gnssLayout.Dock = System.Windows.Forms.DockStyle.Fill;
this.gnssLayout.RowCount = 6;
this.gnssLayout.RowStyles.Clear();
for (int i = 0; i < 6; i++)
this.gnssLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 16.6667F));
for (int i = 0; i < this.gnssLayout.RowCount; i++)
this.gnssLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F / this.gnssLayout.RowCount));
//SetupTitle(this.lblGnssTitulo, "GNSS");
SetupMetric(this.metricSatelites, "Satélites", "18");
SetupMetric(this.metricPrecisao, "Precisão", "0,8 cm");
SetupMetric(this.metricIdadeCorrecao, "Idade correção", "1,2 s");
SetupMetric(this.metricAltitude, "Altitude", "812 m");
SetupMetric(this.metricVelocidade, "Velocidade", "3,4 km/h");
SetupMetric(this.metricHeading, "Heading", "128°");
SetupMetric(this.metricSatelites, "Satélites", "18", 65);
SetupMetric(this.metricPrecisao, "Precisão", "0,8 cm", 72);
SetupMetric(this.metricIdadeCorrecao, "Idade correção", "1,2 s", 72);
SetupMetric(this.metricAltitude, "Altitude", "812 m", 72);
SetupMetric(this.metricVelocidade, "Velocidade", "3,4 km/h", 82);
SetupMetric(this.metricHeading, "Heading", "128°", 65);
ConfigurePanel(this.pnlTrajetoria, this.trajectoryLayout);
this.trajectoryLayout.ColumnCount = 1;
@ -310,6 +311,7 @@ namespace AgroBase.Forms.IHM.Operacao
this.progressRua.Value = 65;
this.progressRua.Margin = new System.Windows.Forms.Padding(1, 1, 1, 1);
this.progressRua.CornerRadius = 5;
this.progressRua.BarColor = HmiTheme.Info;
SetupProgressHeader(
this.progressGeralHeader,
@ -323,6 +325,7 @@ namespace AgroBase.Forms.IHM.Operacao
this.progressGeral.Value = 38;
this.progressGeral.Margin = new System.Windows.Forms.Padding(1, 1, 1, 1);
this.progressGeral.CornerRadius = 5;
this.progressGeral.BarColor = HmiTheme.Success;
this.trajectoryBottomLayout.Controls.Clear();
this.trajectoryBottomLayout.ColumnCount = 2;
@ -456,9 +459,7 @@ namespace AgroBase.Forms.IHM.Operacao
this.ResumeLayout(false);
}
private static void ConfigurePanel(
AgroBase.Forms.IHM.Controls.HmiRoundedPanel panel,
System.Windows.Forms.Control child)
private static void ConfigurePanel(AgroBase.Forms.IHM.Controls.HmiRoundedPanel panel, System.Windows.Forms.Control child)
{
panel.BorderColor = AgroBase.Forms.IHM.Controls.HmiTheme.Border;
panel.Controls.Add(child);
@ -469,9 +470,7 @@ namespace AgroBase.Forms.IHM.Operacao
panel.Padding = new System.Windows.Forms.Padding(7);
}
private static void SetupTitle(
System.Windows.Forms.Label label,
string text)
private static void SetupTitle(System.Windows.Forms.Label label, string text)
{
label.Dock = System.Windows.Forms.DockStyle.Fill;
label.BackColor = System.Drawing.Color.Transparent;
@ -482,9 +481,7 @@ namespace AgroBase.Forms.IHM.Operacao
label.AutoEllipsis = true;
}
private static void SetupMapButton(
System.Windows.Forms.Button button,
string text)
private static void SetupMapButton(System.Windows.Forms.Button button, string text)
{
button.Dock = System.Windows.Forms.DockStyle.Fill;
button.Text = text;
@ -496,10 +493,7 @@ namespace AgroBase.Forms.IHM.Operacao
button.Margin = new System.Windows.Forms.Padding(2);
}
private static void SetupHeadingTitle(
System.Windows.Forms.Label label,
string text,
System.Drawing.Color color)
private static void SetupHeadingTitle(System.Windows.Forms.Label label, string text, System.Drawing.Color color)
{
label.Dock = System.Windows.Forms.DockStyle.Fill;
label.BackColor = System.Drawing.Color.Transparent;
@ -511,10 +505,7 @@ namespace AgroBase.Forms.IHM.Operacao
label.AutoEllipsis = true;
}
private static void SetupHeadingValue(
System.Windows.Forms.Label label,
string text,
System.Drawing.Color color)
private static void SetupHeadingValue(System.Windows.Forms.Label label, string text, System.Drawing.Color color)
{
label.Dock = System.Windows.Forms.DockStyle.Fill;
label.BackColor = System.Drawing.Color.Transparent;
@ -525,14 +516,13 @@ namespace AgroBase.Forms.IHM.Operacao
label.Padding = new Padding(2, 0, 0, 0);
}
private static void SetupMetric(
AgroBase.Forms.IHM.Controls.Operacao.HmiNavigationMetric metric,
string title,
string value)
private static void SetupMetric(AgroBase.Forms.IHM.Controls.Operacao.HmiNavigationMetric metric, string title, string value, int largura)
{
metric.Dock = System.Windows.Forms.DockStyle.Fill;
metric.Titulo = title;
metric.Valor = value;
metric.LarguraValor = largura;
metric.CorValor = HmiTheme.Success;
}
private static void SetupInfoBox(Label label, string text, Color color)
@ -567,12 +557,7 @@ namespace AgroBase.Forms.IHM.Operacao
label.Padding = Padding.Empty;
}
private static void SetupProgressHeader(
System.Windows.Forms.TableLayoutPanel layout,
System.Windows.Forms.Label title,
System.Windows.Forms.Label value,
string titleText,
string valueText)
private static void SetupProgressHeader(System.Windows.Forms.TableLayoutPanel layout, System.Windows.Forms.Label title, System.Windows.Forms.Label value, string titleText, string valueText)
{
layout.ColumnCount = 2;
layout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 45F));
@ -598,11 +583,7 @@ namespace AgroBase.Forms.IHM.Operacao
value.AutoEllipsis = true;
}
private static void SetupAction(
AgroBase.Forms.IHM.Controls.HmiSidebarButton button,
string text,
string icon,
System.Drawing.Color accent)
private static void SetupAction(AgroBase.Forms.IHM.Controls.HmiSidebarButton button, string text, string icon, System.Drawing.Color accent)
{
button.Dock = System.Windows.Forms.DockStyle.Fill;
button.Text = text;
@ -616,11 +597,7 @@ namespace AgroBase.Forms.IHM.Operacao
}
private static void SetupStatusAutonomiaLabel(
Label label,
string text,
Color color,
bool bold)
private static void SetupStatusAutonomiaLabel(Label label, string text, Color color, bool bold)
{
label.Dock = DockStyle.Fill;
label.AutoSize = false;
@ -628,13 +605,7 @@ namespace AgroBase.Forms.IHM.Operacao
label.BackColor = HmiTheme.SurfaceRaised;
label.ForeColor = color;
label.Font = new Font(
"Segoe UI",
6.8F,
bold
? FontStyle.Bold
: FontStyle.Regular
);
label.Font = new Font("Segoe UI", 6.8F, bold ? FontStyle.Bold : FontStyle.Regular);
label.Text = text;
label.TextAlign = ContentAlignment.MiddleCenter;
@ -658,11 +629,7 @@ namespace AgroBase.Forms.IHM.Operacao
label.BackColor = Color.Transparent;
label.ForeColor = accent;
label.Font = new Font(
"Segoe UI",
5.8F,
FontStyle.Bold
);
label.Font = new Font("Segoe UI", 5.8F, FontStyle.Bold);
label.TextAlign = ContentAlignment.MiddleCenter;
label.Margin = Padding.Empty;
@ -683,7 +650,8 @@ namespace AgroBase.Forms.IHM.Operacao
private System.Windows.Forms.Button btnMapaWeb;
private System.Windows.Forms.Button btnMapaDinamico;
private AgroBase.Forms.IHM.Controls.HmiRoundedPanel pnlMapaVisual;
private System.Windows.Forms.Label lblMapaPlaceholder;
private System.Windows.Forms.Panel pnlMapaWeb;
private System.Windows.Forms.Panel pnlMapaDinamico;
private System.Windows.Forms.TableLayoutPanel rightTopLayout;

View File

@ -1,5 +1,5 @@
using AgroBase.Forms.IHM.Controls;
using AgroBase.Forms.IHM.Controls.Operacao;
using AgroBase.Models;
using System;
using System.Drawing;
using System.Windows.Forms;
@ -9,117 +9,125 @@ namespace AgroBase.Forms.IHM.Operacao
public partial class ucOperacaoNavegacao : UserControl
{
private bool _alertaAutonomiaVisivel;
private MapaDinamicoModel _mapaDinamico;
private bool _mapasInicializados;
private bool _exibindoMapaDinamico = true;
private OperacaoModel op => Variaveis.OperacaoEmAndamento;
public ucOperacaoNavegacao()
{
InitializeComponent();
ConfigurarEstadoInicial();
VincularEventos();
MostrarStatusAutonomia();
this.Load += ucOperacaoNavegacao_Load;
}
private void ConfigurarEstadoInicial()
private void ucOperacaoNavegacao_Load(object sender, EventArgs e)
{
SelecionarMapa(btnMapaDinamico);
InicializarMapas();
MostrarMapaDinamico();
}
compassControl.RoverHeading = 128D;
compassControl.TrajectoryHeading = 136D;
private void InicializarMapas()
{
if (_mapasInicializados)
return;
metricSatelites.CorValor = HmiTheme.Success;
metricPrecisao.CorValor = HmiTheme.Success;
metricIdadeCorrecao.CorValor = HmiTheme.Success;
metricAltitude.CorValor = HmiTheme.Success;
metricVelocidade.CorValor = HmiTheme.Success;
metricHeading.CorValor = HmiTheme.Success;
Form formPai = FindForm();
progressRua.Value = 65;
progressRua.BarColor = HmiTheme.Info;
if (formPai == null)
return;
progressGeral.Value = 38;
progressGeral.BarColor = HmiTheme.Success;
_mapasInicializados = true;
_mapaDinamico = new MapaDinamicoModel(formPai, pnlMapaDinamico);
autonomiaBateria.AccentColor = HmiTheme.Warning;
autonomiaHerbicida.AccentColor = HmiTheme.Danger;
if (op == null)
return;
if (op?.Mapa == null)
op.Mapa = new MapasModel();
op.Mapa.pnlMapa = pnlMapaWeb;
CarregarMapaWeb();
}
private void CarregarMapaWeb()
{
var mapa = op?.Mapa;
if (mapa == null)
return;
//mapa.btnCarregar_Click(sender as Control, e);
mapa.CarregarMapaGPS();
MostrarMapaWeb();
}
private void MostrarMapaWeb()
{
_exibindoMapaDinamico = false;
pnlMapaWeb.Visible = true;
pnlMapaDinamico.Visible = true;
pnlMapaWeb.BringToFront();
AtualizarEstadoBotoesMapa(mapaWebSelecionado: true);
}
private void MostrarMapaDinamico()
{
_exibindoMapaDinamico = true;
pnlMapaWeb.Visible = true;
pnlMapaDinamico.Visible = true;
pnlMapaDinamico.BringToFront();
AtualizarEstadoBotoesMapa(mapaWebSelecionado: false);
}
private void VincularEventos()
{
btnMapaWeb.Click += delegate
{
SelecionarMapa(btnMapaWeb);
};
btnMapaDinamico.Click += delegate
{
SelecionarMapa(btnMapaDinamico);
};
btnMapaWeb.Click += btnMapaWeb_Click;
btnMapaDinamico.Click += btnMapaDinamico_Click;
btnAtualizarAutonomia.Click += btnAtualizarAutonomia_Click;
btnLiberarSupervisao.Click += btnLiberarSupervisao_Click;
}
private void SelecionarMapa(Button selecionado)
private void btnMapaWeb_Click(object sender, EventArgs e)
{
AplicarEstiloMapa(btnMapaWeb, false);
AplicarEstiloMapa(btnMapaDinamico, false);
AplicarEstiloMapa(selecionado, true);
MostrarMapaWeb();
}
private static void AplicarEstiloMapa(
Button button,
bool selecionado)
private void btnMapaDinamico_Click(object sender, EventArgs e)
{
if (selecionado)
{
button.BackColor = Color.FromArgb(31, 91, 43);
button.ForeColor = HmiTheme.Text;
button.FlatAppearance.BorderColor = HmiTheme.Success;
}
else
{
button.BackColor = HmiTheme.SurfaceRaised;
button.ForeColor = HmiTheme.TextMuted;
button.FlatAppearance.BorderColor = HmiTheme.Border;
}
MostrarMapaDinamico();
}
public void AtualizarOrientacao(
double headingRover,
double headingTrajetoria,
bool possuiTrajetoria)
private void AtualizarEstadoBotoesMapa(bool mapaWebSelecionado)
{
compassControl.RoverHeading = headingRover;
compassControl.TrajectoryHeading = headingTrajetoria;
compassControl.ShowTrajectory = possuiTrajetoria;
AplicarEstadoBotaoMapa(btnMapaWeb, mapaWebSelecionado);
lblRoverValor.Text =
headingRover.ToString("0") + "°";
lblTrajetoriaValor.Text =
possuiTrajetoria
? headingTrajetoria.ToString("0") + "°"
: "--";
AplicarEstadoBotaoMapa(btnMapaDinamico, !mapaWebSelecionado);
}
public void AtualizarProgresso(
int percentualRua,
string detalheRua,
int percentualGeral,
string detalheGeral)
private static void AplicarEstadoBotaoMapa(Button button, bool selecionado)
{
progressRua.Value = percentualRua;
button.BackColor = selecionado
? HmiTheme.SurfaceRaised
: HmiTheme.Surface;
lblProgressoRuaValor.Text =
percentualRua +
"% · " +
(detalheRua ?? string.Empty);
button.ForeColor = selecionado
? HmiTheme.Info
: HmiTheme.TextMuted;
progressGeral.Value = percentualGeral;
lblProgressoGeralValor.Text =
percentualGeral +
"% · " +
(detalheGeral ?? string.Empty);
button.FlatAppearance.BorderColor = selecionado
? HmiTheme.Info
: HmiTheme.Border;
}
@ -143,7 +151,6 @@ namespace AgroBase.Forms.IHM.Operacao
pnlAlertaAutonomia.BringToFront();
}
private void RecalcularAutonomia()
{
@ -194,31 +201,14 @@ namespace AgroBase.Forms.IHM.Operacao
);
}
private void AtualizarStatusAutonomia(
string bateria,
Color corBateria,
string herbicida,
Color corHerbicida,
string corredor,
Color corCorredor)
private void AtualizarStatusAutonomia(string bateria, Color corBateria, string herbicida, Color corHerbicida, string corredor, Color corCorredor)
{
lblStatusBateria.Text =
bateria;
lblStatusBateria.ForeColor =
corBateria;
lblStatusHerbicida.Text =
herbicida;
lblStatusHerbicida.ForeColor =
corHerbicida;
lblStatusCorredor.Text =
corredor;
lblStatusCorredor.ForeColor =
corCorredor;
lblStatusBateria.Text = bateria;
lblStatusBateria.ForeColor = corBateria;
lblStatusHerbicida.Text = herbicida;
lblStatusHerbicida.ForeColor = corHerbicida;
lblStatusCorredor.Text = corredor;
lblStatusCorredor.ForeColor = corCorredor;
}
public void AtualizarBloqueioAutonomia(bool corredorBloqueado, bool liberadoManualmente)
@ -232,5 +222,218 @@ namespace AgroBase.Forms.IHM.Operacao
MostrarStatusAutonomia();
}
public void AtualizarDadosTela()
{
var dados = op?.Sensoriamento;
AtualizarDadosMapa();
AtualizarDadosAutonomia(dados);
AtualizarDadosOrientacao(dados);
AtualizarDadosGnss(dados?.Gps);
AtualizarDadosCorredor(dados);
AtualizarDadosTelemetria(dados?.Trajetoria?.AutonomiaCorredor);
}
private void AtualizarDadosMapa()
{
AtualizarMapaDinamico();
}
private void AtualizarMapaDinamico()
{
if (!_exibindoMapaDinamico)
return;
var _Sensoriamento = op?.Sensoriamento;
var _Trajetoria = op?.Trajetoria;
if (_Trajetoria != null && _Trajetoria?.CorredorAtual != null)
{
_mapaDinamico.AtualizarDados(
null,
(float)_Trajetoria.AnguloCaminho,
(float)_Sensoriamento.Gps.AnguloCarroDefinido,
_Sensoriamento.Gps,
_Trajetoria._TrajetoriaDinamica,
_Trajetoria.CorredorAtual.Pontos,
op.GPSTrajetoria,
_Trajetoria.RuasPlantacao,
op.Controle.SimulacaoMPC
);
}
}
private void AtualizarDadosAutonomia(OperacaoSensoriamentoConjuntoModel dados)
{
double limiar = 20.0;
double distanciaCorredor = dados?.Trajetoria?.CorredorAtual?.DistanciaTotal ?? 0;
double distanciaBateria = dados?.Bateria?.DistanciaEstimadaRestanteMetros ?? 0;
TimeSpan tempoBateria = TimeSpan.FromMinutes(Math.Max(0, dados?.Bateria?.TempoEstimadoRestanteMinutos ?? 0));
double distanciaHerbicida = dados?.Atuador?.DistanciaEstimadaRestanteMetros ?? 0;
TimeSpan tempoHerbicida = TimeSpan.FromMinutes(Math.Max(0, dados?.Atuador?.TempoEstimadoRestanteMinutos ?? 0));
autonomiaBateria.Distancia = distanciaBateria.ToString("F2") + " m";
autonomiaBateria.Tempo = FuncoesIHM.FormatarTempo(tempoBateria);
autonomiaBateria.AccentColor = FuncoesIHM.CorPorAutonomia(distanciaCorredor, distanciaBateria, limiar);
autonomiaHerbicida.Distancia = distanciaHerbicida.ToString("F2") + " m";
autonomiaHerbicida.Tempo = FuncoesIHM.FormatarTempo(tempoHerbicida);
autonomiaHerbicida.AccentColor = FuncoesIHM.CorPorAutonomia(distanciaCorredor, distanciaHerbicida, limiar);
}
private void AtualizarDadosOrientacao(OperacaoSensoriamentoConjuntoModel dados)
{
double headingCarro = dados?.Gps?.OrientacaoReal ?? 0;
double headingCaminho = dados?.Trajetoria?.AnguloCaminho ?? 0;
bool possuiTrajetoria = dados?.Trajetoria?.QtdPontos > 0;
lblRoverValor.Text = $"{headingCarro:F2}°";
lblRoverValor.ForeColor =
possuiTrajetoria ? FuncoesIHM.CorPorErroAngular(headingCarro, headingCaminho, 5.0, 15.0) :
HmiTheme.Success;
compassControl.RoverHeading = headingCarro;
compassControl.ShowTrajectory = possuiTrajetoria;
lblTrajetoriaValor.Text = possuiTrajetoria ? $"{headingCaminho:F2}°" : "--";
compassControl.TrajectoryHeading = headingCaminho;
}
private void AtualizarDadosGnss(GPSModel dados)
{
metricSatelites.Valor = (dados?.NumeroSatelites ?? 0).ToString();
metricPrecisao.Valor = (dados?.PrecisaoCm ?? 0).ToString();
metricIdadeCorrecao.Valor = ((dados?.Ntrip_ativado ?? false) ? "N" : "B") + " " + (dados?.IdadeCorrecao ?? 0).ToString("F1") + " s";
metricAltitude.Valor = (dados?.Altitude ?? 0).ToString("F2") + " m";
metricVelocidade.Valor = (dados?.Velocidade ?? 0).ToString("F2") + " km/h";
metricHeading.Valor = (dados?.OrientacaoReal ?? 0).ToString("F2") + "°";
}
private void AtualizarDadosCorredor(OperacaoSensoriamentoConjuntoModel dados)
{
var trajetoria = dados?.Trajetoria;
lblRuaAtual.Text = $"Rua {trajetoria?.IdxRuaAtual ?? 0} / {op?.Mapa?.RuasPercorrer?.Count ?? 0}";
lblDentroCorredor.Text = ((trajetoria?.CorredorAtual?.Dentro ?? false) ? "Dentro do Corredor" : "Fora do Corredor");
lblProximoPonto.Text = $"Ponto {trajetoria?.PontoAtual?.idxPonto ?? 0} / {trajetoria?.QtdPontos ?? 0}";
double _progressoRua = trajetoria?.CorredorAtual?.Progresso ?? 0;
double _distanciaPercorridaRua = trajetoria?.CorredorAtual?.DistanciaPercorridaTotal ?? 0;
double _distanciaTotalRua = trajetoria?.CorredorAtual?.DistanciaTotal ?? 0;
lblProgressoRuaValor.Text = $"{_progressoRua:F2}% · {_distanciaPercorridaRua:F2} / {_distanciaTotalRua:F2} m";
progressRua.Value = (int)_progressoRua;
double _progressoGeral = trajetoria?.ProgressoTrajeto ?? 0;
double _distanciaPercorridaGeral = trajetoria?.DistanciaPercorrida ?? 0;
double _distanciaTotalGeral = trajetoria?.DistanciaTotal ?? 0;
progressGeral.Value = (int)_progressoGeral;
lblProgressoGeralValor.Text = $"{_progressoGeral:F2}% · {_distanciaPercorridaGeral:F2} / {_distanciaTotalGeral:F2} m";
string _tempoEstimado = string.IsNullOrEmpty(trajetoria?.TempoEstimadoOperacao) ? "00:00:00" : trajetoria?.TempoEstimadoOperacao;
lblStatusMapa.Text = (trajetoria?.StatusCarro ?? Enums.StatusCarroMapa.Parado).ToString();
lblTempoOperacao.Text = dados?.Operacao?.TempoDecorrido.ToString("HH:mm:ss") + " / " + _tempoEstimado;
lblDistanciaEsq.Text = $"Esquerda {trajetoria?.DistanciaEsquerda ?? 0:F2} m";
lblDistanciaDir.Text = $"Direita {trajetoria?.DistanciaDireita ?? 0:F2} m";
}
private void AtualizarDadosTelemetria(AutonomiaCorredorModel dados)
{
lblStatusBateria.Text = MontarStatusBateria(dados);
lblStatusHerbicida.Text = MontarStatusHerbicida(dados);
lblStatusCorredor.Text = MontarStatusCorredor(dados);
lblStatusAvaliacao.Text = MontarStatusAvaliacao(dados);
}
private static string MontarStatusBateria(AutonomiaCorredorModel autonomia)
{
if (autonomia == null)
return "Bateria: autonomia indisponível";
if (!autonomia.DadosBateriaValidos)
return "Bateria: autonomia indisponível";
if (autonomia.BateriaOverrideAplicado)
{
return string.Format("Bateria: liberada pelo operador · folga {0:F1} m", autonomia.FolgaBateria_m);
}
if (autonomia.BateriaSuficiente)
{
return string.Format("Bateria: suficiente · folga {0:F1} m", autonomia.FolgaBateria_m);
}
return string.Format("Bateria: insuficiente · faltam {0:F1} m", Math.Abs(autonomia.FolgaBateria_m));
}
private static string MontarStatusHerbicida(AutonomiaCorredorModel autonomia)
{
if (autonomia == null)
return "Herbicida: não exigido neste corredor";
if (!autonomia.PulverizacaoExigida)
return "Herbicida: não exigido neste corredor";
if (!autonomia.DadosHerbicidaValidos)
return "Herbicida: autonomia indisponível";
if (autonomia.HerbicidaOverrideAplicado)
{
return string.Format("Herbicida: liberado pelo operador · folga {0:F1} m", autonomia.FolgaHerbicida_m);
}
if (autonomia.HerbicidaSuficiente)
{
return string.Format("Herbicida: suficiente · folga {0:F1} m", autonomia.FolgaHerbicida_m);
}
return string.Format("Herbicida: insuficiente · faltam {0:F1} m", Math.Abs(autonomia.FolgaHerbicida_m));
}
private static string MontarStatusCorredor(AutonomiaCorredorModel autonomia)
{
if (autonomia == null)
return "Corredor: avaliação inativa";
if (!autonomia.Iniciado)
return "Corredor: avaliação inativa";
if (autonomia.ConfirmadoParaEntrada)
return "Corredor: entrada confirmada";
if (autonomia.Liberado)
return "Corredor: liberado";
switch (autonomia.Status)
{
case AutonomiaCorredorStatus.AguardandoLiberacaoManual:
return "Corredor: aguardando liberação manual";
case AutonomiaCorredorStatus.Critico:
return "Corredor: bloqueado por autonomia";
default:
return "Corredor: não liberado";
}
}
private static string MontarStatusAvaliacao(AutonomiaCorredorModel autonomia)
{
if (!string.IsNullOrWhiteSpace(autonomia?.Motivo))
return autonomia.Motivo;
if (autonomia?.Avisos != null && autonomia?.Avisos?.Count > 0)
{
return autonomia.Avisos[0];
}
return "Nova avaliação na próxima troca de rua";
}
}
}

View File

@ -1,5 +1,6 @@
using AgroBase.Forms.IHM.Controls;
using AgroBase.Forms.IHM.Operacao.Parametros;
using AgroBase.Models;
using System;
using System.Collections.Generic;
using System.Drawing;
@ -18,10 +19,7 @@ namespace AgroBase.Forms.IHM.Operacao
private readonly ucParametrosAtuador _ucAtuador;
private readonly ucParametrosMapa _ucMapa;
public event EventHandler RedefinirSolicitado;
public event EventHandler SalvarSolicitado;
public event EventHandler ModoOperacaoAlterado;
public event EventHandler RegistrarPosProcessamentoAlterado;
private OperacaoModel operacaoParametrizando;
public ucOperacaoParametros()
{
@ -39,8 +37,8 @@ namespace AgroBase.Forms.IHM.Operacao
_abas.Add(TipoAbaParametros.Mapa, _ucMapa);
ConfigurarSubControles();
ConfigurarEstadoInicial();
VincularEventos();
ConfigurarEstadoInicial();
}
private void ConfigurarSubControles()
@ -59,11 +57,7 @@ namespace AgroBase.Forms.IHM.Operacao
cmbModoOperacao.Items.Clear();
cmbModoOperacao.Items.AddRange(Enum.GetNames(typeof(ModoOperacao)));
if (cmbModoOperacao.Items.Count > 1)
cmbModoOperacao.SelectedIndex = 1;
checkPosProcessamento.Checked = true;
AtualizarAparenciaCheck(checkPosProcessamento);
cmbModoOperacao.SelectedIndex = (int)(Variaveis.OperacaoEmAndamento?.Sensoriamento?.Operacao?.Modo ?? ModoOperacao.NaoDefinido);
AbrirAba(TipoAbaParametros.Movimento);
}
@ -75,33 +69,45 @@ namespace AgroBase.Forms.IHM.Operacao
btnAbaAtuador.Click += delegate { AbrirAba(TipoAbaParametros.Atuador); };
btnAbaMapa.Click += delegate { AbrirAba(TipoAbaParametros.Mapa); };
btnRedefinir.Click += delegate
{
if (RedefinirSolicitado != null)
RedefinirSolicitado(this, EventArgs.Empty);
};
btnSalvar.Click += delegate
{
if (SalvarSolicitado != null)
SalvarSolicitado(this, EventArgs.Empty);
};
cmbModoOperacao.SelectedIndexChanged += delegate
{
if (ModoOperacaoAlterado != null)
ModoOperacaoAlterado(this, EventArgs.Empty);
};
checkPosProcessamento.CheckedChanged += delegate
{
AtualizarAparenciaCheck(checkPosProcessamento);
if (RegistrarPosProcessamentoAlterado != null)
RegistrarPosProcessamentoAlterado(this, EventArgs.Empty);
};
btnRedefinir.Click += BtnRedefinir_Click;
btnSalvar.Click += BtnSalvar_Click;
cmbModoOperacao.SelectedIndexChanged += CmbModoOperacao_SelectedIndexChanged;
}
private void DefinirOperacaoParametrizando(OperacaoModel operacao)
{
operacaoParametrizando = operacao;
_ucMovimento.DefinirOperacao(operacaoParametrizando);
_ucDirecional.DefinirOperacao(operacaoParametrizando);
_ucAtuador.DefinirOperacao(operacaoParametrizando);
_ucMapa.DefinirOperacao(operacaoParametrizando);
}
private void CmbModoOperacao_SelectedIndexChanged(object sender, EventArgs e)
{
ModoOperacao modo = (ModoOperacao)cmbModoOperacao.SelectedIndex;
OperacaoModel novaOperacao = OperacaoModel.CarregarParametrosOperacaoPadrao(modo, true);
DefinirOperacaoParametrizando(novaOperacao);
}
private void BtnSalvar_Click(object sender, EventArgs e)
{
if (operacaoParametrizando == null)
return;
OperacaoModel.CarregarParamerosOperacaoBase(operacaoParametrizando.Parametros);
}
private void BtnRedefinir_Click(object sender, EventArgs e)
{
ModoOperacao modo = (ModoOperacao)cmbModoOperacao.SelectedIndex;
OperacaoModel novaOperacao = OperacaoModel.CarregarParametrosOperacaoPadrao(modo, true);
DefinirOperacaoParametrizando(novaOperacao);
}
private void AbrirAba(TipoAbaParametros aba)
{
_abaAtual = aba;
@ -162,68 +168,7 @@ namespace AgroBase.Forms.IHM.Operacao
}
}
private static void AtualizarAparenciaCheck(CheckBox check)
{
if (check.Checked)
{
check.Text = "✓";
check.ForeColor = HmiTheme.Success;
check.BackColor = Color.FromArgb(30, 90, 46);
check.FlatAppearance.BorderColor = HmiTheme.Success;
}
else
{
check.Text = "×";
check.ForeColor = HmiTheme.Danger;
check.BackColor = HmiTheme.Surface;
check.FlatAppearance.BorderColor = HmiTheme.Danger;
}
}
public string ModoOperacaoSelecionado
{
get { return Convert.ToString(cmbModoOperacao.SelectedItem); }
set
{
if (string.IsNullOrWhiteSpace(value))
return;
int index = cmbModoOperacao.FindStringExact(value);
if (index >= 0)
cmbModoOperacao.SelectedIndex = index;
}
}
public bool RegistrarPosProcessamento
{
get { return checkPosProcessamento.Checked; }
set { checkPosProcessamento.Checked = value; }
}
public TipoAbaParametros AbaAtual
{
get { return _abaAtual; }
}
public ucParametrosMovimento Movimento
{
get { return _ucMovimento; }
}
public ucParametrosDirecional Direcional
{
get { return _ucDirecional; }
}
public ucParametrosAtuador Atuador
{
get { return _ucAtuador; }
}
public ucParametrosMapa Mapa
{
get { return _ucMapa; }
}
}
public enum TipoAbaParametros

View File

@ -2,8 +2,8 @@
using AgroBase.Forms.IHM.Controls.Operacao;
using AgroBase.Models;
using AgroBase.Models.Operadores;
using AgroBase.Services;
using AgroBase.Services.Operadores;
using Assimp.Unmanaged;
using System;
using System.Collections.Generic;
using System.Drawing;
@ -19,9 +19,14 @@ namespace AgroBase.Forms.IHM.Operacao
private bool _requisitandoCameraFrame;
private bool _controleDescartado;
OperacaoModel op => Variaveis.OperacaoEmAndamento;
private OperacaoModel op => Variaveis.OperacaoEmAndamento;
private readonly List<HmiNozzleCard> _bicos = new List<HmiNozzleCard>();
public IList<HmiNozzleCard> Bicos
{
get { return _bicos.AsReadOnly(); }
}
public ucOperacaoPulverizador()
{
@ -66,44 +71,41 @@ namespace AgroBase.Forms.IHM.Operacao
private void AtualizarSaudeModulos()
{
var saude_m = op?.Sensoriamento?.OperadorSaude?.ModulosSaude;
var saude_i = saude_m?.FirstOrDefault(x => x.modulo == Enums.T_Code.Atu)?.saude_individual;
var saude_i = saude_m?.FirstOrDefault(x => x.modulo == T_Code.Atu)?.saude_individual;
var saudeBomba = saude_i?.FirstOrDefault(x => x.label == op?.DispAtu?.Dados?.BombaPressurizadora?.ID);
var saudeAgitador = saude_i?.FirstOrDefault(x => x.label == op?.DispAtu?.Dados?.AgitadorDeCalda?.ID);
var saudeSensores = saude_i?.Where(x => op?.DispAtu?.Dados?.Sensores?.Where(y => y.Aferir)?.Select(y => y.ID).Contains(x.label) ?? false)?.ToList();
var saudeBicos = saude_i?.Where(x => op?.DispAtu?.Dados?.BicosPulverizadores?.Where(y => y.Comandar)?.Select(y => y.ID).Contains(x.label) ?? false)?.ToList();
var saudeCamera = saude_m?.FirstOrDefault(x => x.modulo == Enums.T_Code.Cam);
var saudeCamera = saude_m?.FirstOrDefault(x => x.modulo == T_Code.Cam);
var saudeSensoresMedia = saudeSensores?.Average(x => x.saude) ?? 0;
Enums.StatusModulo saudeSensoresStatus =
saudeSensoresMedia >= 80 ? Enums.StatusModulo.Operante :
saudeSensoresMedia <= 0 ? Enums.StatusModulo.Falha :
Enums.StatusModulo.Alerta;
StatusModulo saudeSensoresStatus =
saudeSensoresMedia >= 80 ? StatusModulo.Operante :
saudeSensoresMedia <= 0 ? StatusModulo.Falha :
StatusModulo.Alerta;
var saudeBicosMedia = saudeBicos?.Average(x => x.saude) ?? 0;
Enums.StatusModulo saudeBicosStatus =
saudeBicosMedia >= 80 ? Enums.StatusModulo.Operante :
saudeBicosMedia <= 0 ? Enums.StatusModulo.Falha :
Enums.StatusModulo.Alerta;
StatusModulo saudeBicosStatus =
saudeBicosMedia >= 80 ? StatusModulo.Operante :
saudeBicosMedia <= 0 ? StatusModulo.Falha :
StatusModulo.Alerta;
void DefinirSaudeModulo(HmiSprayerModuleHealthRow card, double saude, Enums.StatusModulo status)
void DefinirSaudeModulo(HmiSprayerModuleHealthRow card, HmiRoundedPanel pnl, double saude, StatusModulo status)
{
card.Saude = saude.ToString("F0") + "%";
card.Status = status.ToString();
card.StatusColor =
status == Enums.StatusModulo.Operante ? HmiTheme.Success :
status == Enums.StatusModulo.Alerta ? HmiTheme.Warning :
status == Enums.StatusModulo.Falha ? HmiTheme.Danger :
status == Enums.StatusModulo.Desconectado ? HmiTheme.Disabled :
status == Enums.StatusModulo.Conectado ? HmiTheme.Info :
HmiTheme.Disabled;
card.StatusColor = FuncoesIHM.CorPorStatusModulo(status);
if (pnl != null)
FuncoesIHM.AplicarEstadoPainel(pnl, card.StatusColor);
}
DefinirSaudeModulo(healthBomba, saudeBomba?.saude ?? 0, saudeBomba?.status ?? Enums.StatusModulo.Desconectado);
DefinirSaudeModulo(healthAgitador, saudeAgitador?.saude ?? 0, saudeAgitador?.status ?? Enums.StatusModulo.Desconectado);
DefinirSaudeModulo(healthSensores, saudeSensoresMedia, saudeSensoresStatus);
DefinirSaudeModulo(healthBicos, saudeBicosMedia, saudeBicosStatus);
DefinirSaudeModulo(healthCamera, saudeCamera?.saude ?? 0, saudeCamera?.status ?? Enums.StatusModulo.Desconectado);
DefinirSaudeModulo(healthBomba, pnlBomba, saudeBomba?.saude ?? 0, saudeBomba?.status ?? StatusModulo.Desconectado);
DefinirSaudeModulo(healthAgitador, pnlAgitador, saudeAgitador?.saude ?? 0, saudeAgitador?.status ?? StatusModulo.Desconectado);
DefinirSaudeModulo(healthSensores, pnlTelemetria, saudeSensoresMedia, saudeSensoresStatus);
DefinirSaudeModulo(healthBicos, pnlBicos, saudeBicosMedia, saudeBicosStatus);
DefinirSaudeModulo(healthCamera, pnlVideo, saudeCamera?.saude ?? 0, saudeCamera?.status ?? StatusModulo.Desconectado);
}
public async void AtualizarDadosCamera(CameraWorkerItemModel dados, double saude)
@ -222,11 +224,11 @@ namespace AgroBase.Forms.IHM.Operacao
telemetryPressaoSensor.Valor = (dados?.PressaoSensor ?? 0).ToString("F1") + " psi";
telemetryPressaoBomba.Valor = (dados?.PressaoAtualBomba ?? 0).ToString("F1") + " psi";
telemetryAutonomiaM.Valor = (dados?.DistanciaEstimadaRestanteMetros ?? 0).ToString("F1") + " m";
telemetryAutonomiaTempo.Valor = FormatarTempo(tempoAutonomia);
telemetryAutonomiaTempo.Valor = FuncoesIHM.FormatarTempo(tempoAutonomia);
telemetryVolumeAplicado.Valor = (dados?.VolumeVazaoML ?? 0).ToString("F1") + " L";
telemetryLitroMetro.Valor = (dados?.LPorMetro ?? 0).ToString("F1") + " L/m";
telemetryInfestacao.Valor = (dados?.PercentualErvasTerreno ?? 0).ToString("F1") + "% · Baixa";
telemetryTempoLigado.Valor = FormatarTempo(tempoPulverizador);
telemetryTempoLigado.Valor = FuncoesIHM.FormatarTempo(tempoPulverizador);
}
@ -256,15 +258,90 @@ namespace AgroBase.Forms.IHM.Operacao
telemetryLitroMetro.CorValor = HmiTheme.Info;
telemetryInfestacao.CorValor = HmiTheme.Success;
telemetryTempoLigado.CorValor = HmiTheme.Manual;
AplicarEstadoPainel(pnlBomba, HmiTheme.Warning);
AplicarEstadoPainel(pnlAgitador, HmiTheme.Success);
}
private void VincularEventos()
{
foreach (HmiNozzleCard card in _bicos)
card.NozzleClick += NozzleCard_Click;
btnDesligarAgitador.Click += BtnDesligarAgitador_Click;
btnLigarAgitador.Click += BtnLigarAgitador_Click;
btnDesligarBomba.Click += BtnDesligarBomba_Click;
btnLigarBomba.Click += BtnLigarBomba_Click;
}
private void BtnLigarBomba_Click(object sender, EventArgs e)
{
var Bomba = op?.DispAtu?.Dados?.BombaPressurizadora;
if (Bomba != null)
{
op?.DispAtu?.Dados?.EnviarComandoFisicoBomba(
Bomba,
CanMessagePosicaoDados.Command2,
setarControle: true,
status: true
);
op?.DispAtu?.Dados?.EnviarComandoFisicoBomba(
Bomba,
CanMessagePosicaoDados.Command1,
setarControle: true,
status: true
);
}
}
private void BtnDesligarBomba_Click(object sender, EventArgs e)
{
var Bomba = op?.DispAtu?.Dados?.BombaPressurizadora;
if (Bomba != null)
op?.DispAtu?.Dados?.EnviarComandoFisicoBomba(
Bomba,
CanMessagePosicaoDados.Command1,
setarControle: true,
status: false
);
}
private void BtnLigarAgitador_Click(object sender, EventArgs e)
{
var Agitador = op?.DispAtu?.Dados?.AgitadorDeCalda;
if (Agitador != null)
{
op.Parametros.Controle.AtuAgitadorModo = ModoAgitadorCalda.Manual;
op?.DispAtu?.Dados?.EnviarComandoFisicoBomba(
Agitador,
CanMessagePosicaoDados.Command2,
setarControle: true,
status: true
);
op?.DispAtu?.Dados?.EnviarComandoFisicoBomba(
Agitador,
CanMessagePosicaoDados.Command1,
setarControle: true,
status: true
);
}
}
private void BtnDesligarAgitador_Click(object sender, EventArgs e)
{
if (!(op?.Parametros?.Controle?.ControleManualAcionado ?? false))
return;
op.Parametros.Controle.AtuAgitadorModo = ModoAgitadorCalda.SemAgitacao;
var Agitador = op?.DispAtu?.Dados?.AgitadorDeCalda;
if (Agitador != null)
op?.DispAtu?.Dados?.EnviarComandoFisicoBomba(
Agitador,
CanMessagePosicaoDados.Command1,
setarControle: true,
status: false
);
}
private void NozzleCard_Click(object sender, EventArgs e)
@ -273,36 +350,28 @@ namespace AgroBase.Forms.IHM.Operacao
if (card == null)
return;
if (!(op?.Parametros?.Controle?.ControleManualAcionado ?? false))
return;
var bico = op?.DispAtu?.Dados?.BicosPulverizadores?.FirstOrDefault(x => x.ID == card.Codigo);
if (bico == null)
return;
card.CommandOn = !card.CommandOn;
}
private static void AplicarEstadoPainel(HmiRoundedPanel panel, Color color)
{
panel.BorderColor = color;
panel.Invalidate();
}
public IList<HmiNozzleCard> Bicos
{
get { return _bicos.AsReadOnly(); }
}
private static string FormatarTempo(TimeSpan tempo)
{
if (tempo < TimeSpan.Zero)
tempo = TimeSpan.Zero;
int horasTotais = (int)tempo.TotalHours;
return string.Format(
"{0:00}:{1:00}:{2:00}",
horasTotais,
tempo.Minutes,
tempo.Seconds
op?.DispAtu?.Dados?.EnviarComandoFisicoBico(
bico,
CanMessagePosicaoDados.Command1,
setarControle: true,
status:
card.CommandOn
);
}
}
}

View File

@ -260,31 +260,31 @@ namespace AgroBase.Forms.IHM
// =========================================================
double bateria = operacao?.Sensoriamento?.Bateria?.PercentualBateria ?? 0;
double bateriaSaude = ObterSaudeModulo(saudeModulos, Enums.T_Code.Bat);
Color corBateria = CorPorValorESaude(bateria, bateriaSaude);
AtualizarBateria($"{Limitar(bateria, 0, 100):0}%", corBateria);
Color corBateria = FuncoesIHM.CorPorValorESaude(bateria, bateriaSaude);
AtualizarBateria($"{FuncoesIHM.Limitar(bateria, 0, 100):0}%", corBateria);
// =========================================================
// RESERVATÓRIO
// =========================================================
double reservatorio = operacao?.Sensoriamento?.Atuador?.PercentualReservatorio ?? 0;
double atuadorSaude = ObterSaudeModulo(saudeModulos, Enums.T_Code.Atu);
Color corReservatorio = CorPorValorESaude(reservatorio, atuadorSaude);
AtualizarReservatorio($"{Limitar(reservatorio, 0, 100):0}%", corReservatorio);
Color corReservatorio = FuncoesIHM.CorPorValorESaude(reservatorio, atuadorSaude);
AtualizarReservatorio($"{FuncoesIHM.Limitar(reservatorio, 0, 100):0}%", corReservatorio);
// =========================================================
// TEMPERATURA
// =========================================================
double temperatura = operacao?.Sensoriamento?.CoolerControl?.Temperatura ?? 0;
double temperaturaSaude = ObterSaudeModulo(saudeModulos, Enums.T_Code.Npc);
Color corTemperatura = CorTemperatura(temperatura, temperaturaSaude);
Color corTemperatura = FuncoesIHM.CorTemperatura(temperatura, temperaturaSaude);
AtualizarTemperatura($"{temperatura:0.#} °C", corTemperatura);
// =========================================================
// REDE / IPB
// =========================================================
double redeSaude = ObterSaudeModulo(saudeModulos, Enums.T_Code.Ipb);
Color corRede = CorPorPercentual(redeSaude);
AtualizarRede($"{Limitar(redeSaude, 0, 100):0}%", corRede);
Color corRede = FuncoesIHM.CorPorPercentual(redeSaude);
AtualizarRede($"{FuncoesIHM.Limitar(redeSaude, 0, 100):0}%", corRede);
// =========================================================
// GNSS
@ -300,9 +300,9 @@ namespace AgroBase.Forms.IHM
{
Enums.TiposCorrecaoGPS qualidadeFix = gnss.QualidadeFix;
double precisaoCm = Math.Max(0, gnss.PrecisaoCm);
double notaGnss = CalcularNotaGnss(qualidadeFix, precisaoCm, gnssSaude);
Color corGnss = CorPorPercentual(notaGnss);
string textoGnss = $"{FormatarQualidadeGnss(qualidadeFix)} " + $"{precisaoCm:0.##} cm";
double notaGnss = FuncoesIHM.CalcularNotaGnss(qualidadeFix, precisaoCm, gnssSaude);
Color corGnss = FuncoesIHM.CorPorPercentual(notaGnss);
string textoGnss = $"{FuncoesIHM.FormatarQualidadeGnss(qualidadeFix)} " + $"{precisaoCm:0.##} cm";
AtualizarGnss(textoGnss, corGnss);
}
@ -317,8 +317,8 @@ namespace AgroBase.Forms.IHM
else
{
double distanciaBase = GPSUtils.DistanciaEntrePontos(gnss, VariaveisOperacao.PosicaoBase);
Color corBase = CorDistanciaBase(distanciaBase, 1000);
string distanciaTexto = FormatarDistancia(distanciaBase);
Color corBase = FuncoesIHM.CorDistanciaBase(distanciaBase, 1000);
string distanciaTexto = FuncoesIHM.FormatarDistancia(distanciaBase);
AtualizarDistanciaBase(distanciaTexto, corBase);
}
@ -392,7 +392,7 @@ namespace AgroBase.Forms.IHM
lblIndicadorStatus.ForeColor = corStatus;
pnlStatusOperacao.AccentColor = corStatus;
pnlStatusOperacao.BorderColor = MisturarCores(HmiTheme.BorderSoft, corStatus, 0.35F);
pnlStatusOperacao.BorderColor = FuncoesIHM.MisturarCores(HmiTheme.BorderSoft, corStatus, 0.35F);
});
}
@ -511,205 +511,7 @@ namespace AgroBase.Forms.IHM
acao();
}
private static Color MisturarCores(Color baseColor, Color accentColor, float pesoAccent)
{
pesoAccent = Math.Max(0F, Math.Min(1F, pesoAccent));
float pesoBase = 1F - pesoAccent;
return Color.FromArgb(
(int)(baseColor.R * pesoBase + accentColor.R * pesoAccent),
(int)(baseColor.G * pesoBase + accentColor.G * pesoAccent),
(int)(baseColor.B * pesoBase + accentColor.B * pesoAccent)
);
}
private static Color CorPorPercentual(double percentual)
{
percentual = Limitar(percentual, 0, 100);
if (percentual <= 50)
{
double fator = percentual / 50.0;
return InterpolarCor(HmiTheme.Danger, HmiTheme.Warning, fator);
}
double fatorVerde = (percentual - 50) / 50.0;
return InterpolarCor(HmiTheme.Warning, HmiTheme.Success, fatorVerde);
}
private static Color CorPorValorESaude(double valor, double saude)
{
double notaFinal = Math.Min(Limitar(valor, 0, 100), Limitar(saude, 0, 100));
return CorPorPercentual(notaFinal);
}
private static Color CorTemperatura(double temperatura, double saudeModulo)
{
Color corTemperatura;
if (temperatura <= 45)
{
corTemperatura = HmiTheme.Success;
}
else if (temperatura <= 60)
{
double fator = (temperatura - 45) / (60 - 45);
corTemperatura = InterpolarCor(HmiTheme.Success, HmiTheme.Warning, fator);
}
else if (temperatura <= 75)
{
double fator = (temperatura - 60) / (75 - 60);
corTemperatura = InterpolarCor(HmiTheme.Warning, HmiTheme.Danger, fator);
}
else
{
corTemperatura = HmiTheme.Danger;
}
Color corSaude = CorPorPercentual(saudeModulo);
/*
* Se a saúde estiver muito baixa,
* ela prevalece sobre a temperatura.
*/
if (saudeModulo < 40)
return corSaude;
return corTemperatura;
}
private static double NotaQualidadeGnss(Enums.TiposCorrecaoGPS qualidade)
{
switch (qualidade)
{
case Enums.TiposCorrecaoGPS.RTKFixo:
return 100;
case Enums.TiposCorrecaoGPS.BaseFix:
return 100;
case Enums.TiposCorrecaoGPS.RTKFlutuante:
return 78;
case Enums.TiposCorrecaoGPS.PPS:
return 65;
case Enums.TiposCorrecaoGPS.DGPS:
return 58;
case Enums.TiposCorrecaoGPS.DeadReckoing:
return 35;
case Enums.TiposCorrecaoGPS.Autonomo:
return 22;
case Enums.TiposCorrecaoGPS.SemCorrecao:
default:
return 0;
}
}
private static double NotaPrecisaoGnss(double precisaoCm)
{
if (precisaoCm <= 2)
return 100;
if (precisaoCm <= 5)
return InterpolarValor(precisaoCm, 2, 5, 100, 90);
if (precisaoCm <= 10)
return InterpolarValor(precisaoCm, 5, 10, 90, 75);
if (precisaoCm <= 30)
return InterpolarValor(precisaoCm, 10, 30, 75, 50);
if (precisaoCm <= 100)
return InterpolarValor(precisaoCm, 30, 100, 50, 20);
return 5;
}
private static double CalcularNotaGnss(Enums.TiposCorrecaoGPS qualidade, double precisaoCm, double saudeModulo)
{
double notaFix = NotaQualidadeGnss(qualidade);
double notaPrecisao = NotaPrecisaoGnss(precisaoCm);
/*
* O pior dos três critérios define a cor.
*
* RTK Fixo com saúde ruim não fica verde.
* Saúde boa com modo autônomo também não.
*/
return Math.Min(notaFix, Math.Min(notaPrecisao, Limitar(saudeModulo, 0, 100)));
}
private static string FormatarQualidadeGnss(Enums.TiposCorrecaoGPS qualidade)
{
switch (qualidade)
{
case Enums.TiposCorrecaoGPS.SemCorrecao:
return "Sem correção";
case Enums.TiposCorrecaoGPS.Autonomo:
return "Autônomo";
case Enums.TiposCorrecaoGPS.DGPS:
return "DGPS";
case Enums.TiposCorrecaoGPS.PPS:
return "PPS";
case Enums.TiposCorrecaoGPS.RTKFixo:
return "RTK Fixo";
case Enums.TiposCorrecaoGPS.RTKFlutuante:
return "RTK Flutuante";
case Enums.TiposCorrecaoGPS.DeadReckoing:
return "Dead Reckoning";
case Enums.TiposCorrecaoGPS.BaseFix:
return "Base Fix";
default:
return "Desconhecido";
}
}
private static Color CorDistanciaBase(double distanciaMetros, double distanciaMaximaMetros)
{
if (double.IsNaN(distanciaMetros) || double.IsInfinity(distanciaMetros) || distanciaMetros < 0)
{
return HmiTheme.Danger;
}
double percentualSaudavel = 100 - (distanciaMetros / distanciaMaximaMetros * 100);
return CorPorPercentual(percentualSaudavel);
}
private static string FormatarDistancia(double distanciaMetros)
{
if (double.IsNaN(distanciaMetros) || double.IsInfinity(distanciaMetros) || distanciaMetros < 0)
{
return "Indisponível";
}
if (distanciaMetros >= 1000)
{
return $"{distanciaMetros / 1000.0:0.00} km";
}
return $"{distanciaMetros:0.0} m";
}
private void AtualizarStatusOperacao(Enums.StatusOperacao status, bool pausada, bool emergencia, int? inicio_em = null)
{
string titulo;
@ -843,39 +645,10 @@ namespace AgroBase.Forms.IHM
if (item == null)
return 0;
return Limitar(Convert.ToDouble(item.saude), 0, 100);
}
private static Color InterpolarCor(Color inicial, Color final, double fator)
{
fator = Limitar(fator, 0, 1);
int r = (int)Math.Round(inicial.R + (final.R - inicial.R) * fator);
int g = (int)Math.Round(inicial.G + (final.G - inicial.G) * fator);
int b = (int)Math.Round(inicial.B + (final.B - inicial.B) * fator);
return Color.FromArgb(r, g, b);
}
private static double InterpolarValor(double valor, double origemMinima, double origemMaxima, double destinoInicial, double destinoFinal)
{
if (origemMaxima <= origemMinima)
return destinoInicial;
double fator = (valor - origemMinima) / (origemMaxima - origemMinima);
fator = Limitar(fator, 0, 1);
return destinoInicial + (destinoFinal - destinoInicial) * fator;
}
private static double Limitar(double valor, double minimo, double maximo)
{
return Math.Max(minimo, Math.Min(maximo, valor));
return FuncoesIHM.Limitar(Convert.ToDouble(item.saude), 0, 100);
}
}

View File

@ -56,6 +56,7 @@ namespace AgroBase.Forms.IHM
_ucPulverizador.AtualizarDadosTela();
break;
case AbaOperacaoIHM.Navegacao:
_ucNavegacao.AtualizarDadosTela();
break;
case AbaOperacaoIHM.Parametros:
break;

View File

@ -258,7 +258,7 @@ namespace AgroBase
GeneralJoystick.AtualizaDispositivo();
cmbJoysticks.Items.Clear();
cmbJoysticks.Items.AddRange(GeneralJoystick.JoysticksConectados.ToArray());
cmbJoysticks.SelectedIndex = GeneralJoystick.JoysticksConectados.IndexOf(GeneralJoystick.JoystickConectado.Information.InstanceName);
cmbJoysticks.SelectedIndex = GeneralJoystick.JoysticksConectados.IndexOf(GeneralJoystick.JoystickConectado?.Information?.InstanceName);
}
private void btnJoyEdt_Click(object sender, EventArgs e)

View File

@ -381,6 +381,7 @@
SemAgitacao = 0,
Continuo = 1,
Intermitente = 2,
Manual = 3,
}
public enum ModoControleBomba

View File

@ -45,7 +45,7 @@ namespace AgroBase.Models
private RenderState _state = RenderState.Empty;
private readonly Panel _painel;
private readonly Form _parent;
private readonly Control _parent;
private double _zoom = ZoomInicial;
@ -137,7 +137,7 @@ namespace AgroBase.Models
#endregion
public MapaDinamicoModel(Form parent, Panel painel)
public MapaDinamicoModel(Control parent, Panel painel)
{
if (parent == null)
throw new ArgumentNullException(nameof(parent));

View File

@ -1093,7 +1093,6 @@ namespace AgroBase.Models
if (CarregarModulos)
{
op.DefinirComponentesEmUso();
RedisService.AtualizarCampos(CtxKey.DadosOperacao, ("configurado", false));
op.AtualizarSensoriamentoSeguro();
}
@ -4909,7 +4908,7 @@ namespace AgroBase.Models
DistanciaErroMapaCana = _Trajetoria?.DistanciaErroMapaPlantacao ?? 0,
PrimeiroPontoDentroMapa = _Trajetoria?.PrimeiroPontoDentroMapa?.Clone() ?? new GPSModel(),
PrimeiroPontoDentroCana = _Trajetoria?.PrimeiroPontoDentroCana?.Clone() ?? new GPSModel(),
AutonomiaCooredor = _Trajetoria?.AutonomiaCorredor?.Clone(),
AutonomiaCorredor = _Trajetoria?.AutonomiaCorredor?.Clone(),
};
}
@ -5307,7 +5306,7 @@ namespace AgroBase.Models
public GPSModel PrimeiroPontoDentroCana { get; set; }
public double DistanciaErroMapaCana { get; set; }
public AutonomiaCorredorModel AutonomiaCooredor { get; set; }
public AutonomiaCorredorModel AutonomiaCorredor { get; set; }
public OperacaoSensoriamentoLogTrajetoriaModel Clone()
{
@ -5345,7 +5344,7 @@ namespace AgroBase.Models
PrimeiroPontoDentroCana = PrimeiroPontoDentroCana?.Clone(),
PrimeiroPontoDentroMapa = PrimeiroPontoDentroMapa?.Clone(),
DistanciaErroMapaCana = DistanciaErroMapaCana,
AutonomiaCooredor = AutonomiaCooredor?.Clone()
AutonomiaCorredor = AutonomiaCorredor?.Clone()
};
}
}

View File

@ -591,6 +591,20 @@ namespace AgroBase.Models.Operacoes
}
}
private double _distanciaManobra = 3.0;
public double DistanciaManobra
{
get => _distanciaManobra;
set
{
if (_distanciaManobra != value)
{
_distanciaManobra = value;
OnPropertyChanged(nameof(DistanciaManobra));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string nome)
@ -696,7 +710,7 @@ namespace AgroBase.Models.Operacoes
return;
}
var autonomia = t.AutonomiaCooredor;
var autonomia = t.AutonomiaCorredor;
var corredorAtual = t.CorredorAtual;
var pontoAtual = t.PontoAtual;
var proximoPonto = t.ProximoPonto;

View File

@ -133,7 +133,7 @@ namespace AgroBase.Models
public List<CorredorTrajetoriaModel> _Corredores { get; set; }
public List<GPSModel> TrajetoriaFixa => _TrajetoriaFixa?.ConvertAll(x => x.Posicao);
public List<PontoTrajetoriaModel> _TrajetoriaDinamica { get; private set; }
public List<GPSModel> TrajetoriaDinamica => _TrajetoriaDinamica.ConvertAll(x => x.Posicao);
public List<GPSModel> TrajetoriaDinamica => _TrajetoriaDinamica?.ConvertAll(x => x.Posicao);
public void AtualizarTrajetoriaDinamica()
{
// Cria a lista com a última leitura do robô

View File

@ -84,6 +84,8 @@ namespace AgroBase.Models
_op = value;
_op?.IniciarTimersSistema();
RedisService.AtualizarCampos(CtxKey.DadosOperacao, ("configurado", false));
}
}
}
@ -2355,4 +2357,23 @@ namespace AgroBase.Models
}
public static class CloneHelper
{
public static T DeepClone<T>(T origem)
{
if (object.ReferenceEquals(origem, null))
return default(T);
JsonSerializerSettings settings =
new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Replace,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string json = JsonConvert.SerializeObject(origem, settings);
return JsonConvert.DeserializeObject<T>(json, settings);
}
}
}

View File

@ -1616,8 +1616,7 @@ namespace AgroBase.Services
private int AtuAgitadorTempoDesligadoMs = 30000;
private int AtuAgitadorBoostRetomadaMs = 15000;
private double PotenciaLimitePorNivel(
double nivelPct)
private double PotenciaLimitePorNivel(double nivelPct)
{
if (nivelPct <= 5)
return 0;
@ -1634,33 +1633,21 @@ namespace AgroBase.Services
return 100;
}
public void AtualizarAgitadorCalda(
ModoAgitadorCalda modo)
public void AtualizarAgitadorCalda(ModoAgitadorCalda modo)
{
var op =
Variaveis.OperacaoEmAndamento;
var op = Variaveis.OperacaoEmAndamento;
if (
op?
.Sensoriamento?
.Operacao?
.Calibrando == true
)
if (op?.Sensoriamento?.Operacao?.Calibrando == true)
{
return;
}
var agitador =
op?
.DispAtu?
.Dados?
.AgitadorDeCalda;
var agitador = op?.DispAtu?.Dados?.AgitadorDeCalda;
if (!(agitador?.Inicializado ?? false))
return;
var controle =
op.Parametros?.Controle;
var controle = op.Parametros?.Controle;
if (controle == null)
{
@ -1670,12 +1657,10 @@ namespace AgroBase.Services
return;
}
bool operacaoConcluida =
op
.Sensoriamento?
.Operacao?
.StatusOperacaoAtual ==
StatusOperacao.Concluido;
if (controle.AtuAgitadorModo == ModoAgitadorCalda.Manual)
return;
bool operacaoConcluida = op.Sensoriamento?.Operacao?.StatusOperacaoAtual == StatusOperacao.Concluido;
bool operacaoAtiva =
op.Sensoriamento.Operacao.OperacaoIniciada &&
@ -1683,37 +1668,20 @@ namespace AgroBase.Services
!operacaoConcluida &&
PulverizadorLiberado;
bool bicosAtuando =
op
.DispAtu?
.Dados?
.BicosPulverizadores?
.Any(
x =>
x.Comandar &&
x.ComandoAtuar
)
?? false;
bool bicosAtuando = op.DispAtu?.Dados?.BicosPulverizadores?.Any(x => x.Comandar && x.ComandoAtuar) ?? false;
double potenciaFinal = 0;
DateTime agora = DateTime.Now;
if (
operacaoAtiva &&
!_agitadorOperacaoAtivaAnterior
)
if (operacaoAtiva && !_agitadorOperacaoAtivaAnterior)
{
_agitadorBoostAte =
agora.AddMilliseconds(
AtuAgitadorBoostRetomadaMs
);
_agitadorBoostAte = agora.AddMilliseconds(AtuAgitadorBoostRetomadaMs);
_agitadorUltimaTroca = agora;
_agitadorIntermitenteLigado = true;
}
bool emBoost =
agora < _agitadorBoostAte;
bool emBoost = agora < _agitadorBoostAte;
switch (modo)
{
@ -1726,18 +1694,15 @@ namespace AgroBase.Services
{
if (emBoost)
{
potenciaFinal =
AtuAgitadorPotenciaBoost;
potenciaFinal = AtuAgitadorPotenciaBoost;
}
else if (bicosAtuando)
{
potenciaFinal =
AtuAgitadorPotenciaContinua;
potenciaFinal = AtuAgitadorPotenciaContinua;
}
else
{
potenciaFinal =
AtuAgitadorPotenciaManutencao;
potenciaFinal = AtuAgitadorPotenciaManutencao;
}
}
break;
@ -1751,65 +1716,35 @@ namespace AgroBase.Services
}
else if (emBoost)
{
potenciaFinal =
AtuAgitadorPotenciaBoost;
potenciaFinal = AtuAgitadorPotenciaBoost;
}
else
{
int tempoAtualMs =
_agitadorIntermitenteLigado
? AtuAgitadorTempoLigadoMs
: AtuAgitadorTempoDesligadoMs;
int tempoAtualMs = _agitadorIntermitenteLigado ? AtuAgitadorTempoLigadoMs : AtuAgitadorTempoDesligadoMs;
if (
(
agora -
_agitadorUltimaTroca
).TotalMilliseconds >=
tempoAtualMs
)
if ((agora - _agitadorUltimaTroca).TotalMilliseconds >= tempoAtualMs)
{
_agitadorIntermitenteLigado =
!_agitadorIntermitenteLigado;
_agitadorIntermitenteLigado = !_agitadorIntermitenteLigado;
_agitadorUltimaTroca =
agora;
_agitadorUltimaTroca = agora;
}
potenciaFinal =
_agitadorIntermitenteLigado
? AtuAgitadorPotenciaIntermitente
: 0;
potenciaFinal = _agitadorIntermitenteLigado ? AtuAgitadorPotenciaIntermitente : 0;
}
break;
}
potenciaFinal =
Math.Min(
potenciaFinal,
PotenciaLimitePorNivel(
PercentualAtual
)
);
potenciaFinal = Math.Min(potenciaFinal, PotenciaLimitePorNivel(PercentualAtual));
potenciaFinal =
Clamp(
potenciaFinal,
0,
100
);
potenciaFinal = Clamp(potenciaFinal, 0, 100);
agitador.PotenciaSP =
potenciaFinal;
agitador.PotenciaSP = potenciaFinal;
agitador.PressaoSP = -1;
agitador.ComandoAtuar =
agitador.Comandar &&
potenciaFinal > 0;
agitador.ComandoAtuar = agitador.Comandar && potenciaFinal > 0;
_agitadorOperacaoAtivaAnterior =
operacaoAtiva;
_agitadorOperacaoAtivaAnterior = operacaoAtiva;
}
}
}

View File

@ -181,15 +181,15 @@ namespace AgroBase.Services.Operadores
dist_dir = _t.DistanciaDireita,
angulo = _t.AnguloMedioCorredor,
pontos_restantes = _t.CorredorAtual.QtdPontos - pontoComparar.idxPontoCorredor,
liberado = _t.AutonomiaCooredor?.Liberado ?? false,
motivo_bat = _t.AutonomiaCooredor?.Motivos?.FirstOrDefault(x => x.Contains("Bateria")) ?? "",
bateria_ok = _t.AutonomiaCooredor?.BateriaSuficiente ?? false,
motivo_hrb = _t.AutonomiaCooredor?.Motivos?.FirstOrDefault(x => x.Contains("Herbicida")) ?? "",
herbicida_ok = _t.AutonomiaCooredor?.HerbicidaSuficiente ?? false,
autonomia_liberada = _t.AutonomiaCooredor?.Liberado ?? false,
autonomia_status = (int)(_t.AutonomiaCooredor?.Status ?? AutonomiaCorredorStatus.Desconhecido),
autonomia_motivo = _t.AutonomiaCooredor?.Motivo ?? "",
autonomia_ok_supervisionado = _t.AutonomiaCooredor?.Status == AutonomiaCorredorStatus.OkSupervisionado,
liberado = _t.AutonomiaCorredor?.Liberado ?? false,
motivo_bat = _t.AutonomiaCorredor?.Motivos?.FirstOrDefault(x => x.Contains("Bateria")) ?? "",
bateria_ok = _t.AutonomiaCorredor?.BateriaSuficiente ?? false,
motivo_hrb = _t.AutonomiaCorredor?.Motivos?.FirstOrDefault(x => x.Contains("Herbicida")) ?? "",
herbicida_ok = _t.AutonomiaCorredor?.HerbicidaSuficiente ?? false,
autonomia_liberada = _t.AutonomiaCorredor?.Liberado ?? false,
autonomia_status = (int)(_t.AutonomiaCorredor?.Status ?? AutonomiaCorredorStatus.Desconhecido),
autonomia_motivo = _t.AutonomiaCorredor?.Motivo ?? "",
autonomia_ok_supervisionado = _t.AutonomiaCorredor?.Status == AutonomiaCorredorStatus.OkSupervisionado,
},
} : null
),
@ -1290,11 +1290,11 @@ namespace AgroBase.Services.Operadores
var DadosTrj = _Sensoriamento?.Trajetoria;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Trj),
("timestamp", agora),
("iniciado", DadosTrj?.AutonomiaCooredor?.Iniciado ?? false),
("liberado", DadosTrj?.AutonomiaCooredor?.Liberado ?? false),
("bateria_ok", DadosTrj?.AutonomiaCooredor?.BateriaSuficiente ?? false),
("herbicida_ok", DadosTrj?.AutonomiaCooredor?.HerbicidaSuficiente ?? false),
("motivos", DadosTrj?.AutonomiaCooredor?.Motivos ?? new List<string>())
("iniciado", DadosTrj?.AutonomiaCorredor?.Iniciado ?? false),
("liberado", DadosTrj?.AutonomiaCorredor?.Liberado ?? false),
("bateria_ok", DadosTrj?.AutonomiaCorredor?.BateriaSuficiente ?? false),
("herbicida_ok", DadosTrj?.AutonomiaCorredor?.HerbicidaSuficiente ?? false),
("motivos", DadosTrj?.AutonomiaCorredor?.Motivos ?? new List<string>())
);
double distanciaBase = -1;