incluido ajustes do equipamento na ihm e comecado diagnosticos

This commit is contained in:
Diego Freitas 2026-07-16 17:13:15 -03:00
parent a22ad83812
commit 8327561222
23 changed files with 5546 additions and 3030 deletions

View File

@ -384,9 +384,27 @@
<Compile Include="Forms\frmPinout.Designer.cs">
<DependentUpon>frmPinout.cs</DependentUpon>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiCameraSelector.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiDiagnosticTabButton.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiMenuTile.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiMetricTile.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiModuleBadge.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiNetworkEditor.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiNumericField.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Forms\IHM\Controls\HmiRoundedPanel.cs">
<SubType>UserControl</SubType>
</Compile>
@ -811,6 +829,7 @@
</EmbeddedResource>
<EmbeddedResource Include="Forms\IHM\frmDiagnosticos.resx">
<DependentUpon>frmDiagnosticos.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Forms\IHM\frmMenu.resx">
<DependentUpon>frmMenu.cs</DependentUpon>
@ -830,6 +849,7 @@
</EmbeddedResource>
<EmbeddedResource Include="Forms\IHM\frmAjustes.resx">
<DependentUpon>frmAjustes.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Forms\IHM\frmTestes.resx">
<DependentUpon>frmTestes.cs</DependentUpon>

View File

@ -0,0 +1,250 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Controls
{
/// <summary>
/// Seleção de câmera com porta TCP, status e preview.
/// </summary>
[DefaultEvent("CameraChanged")]
public class HmiCameraSelector : UserControl
{
private readonly TableLayoutPanel _root;
private readonly TableLayoutPanel _info;
private readonly Label _lblTitulo;
private readonly Label _lblStatus;
private readonly ComboBox _cmbCamera;
private readonly NumericUpDown _nudPorta;
private readonly PictureBox _preview;
private readonly HmiSidebarButton _btnTestar;
public event EventHandler CameraChanged;
public event EventHandler TestRequested;
public event EventHandler ValueChanged;
public HmiCameraSelector()
{
DoubleBuffered = true;
BackColor = Color.Transparent;
Height = 86;
MinimumSize = new Size(250, 82);
Margin = new Padding(0, 1, 0, 4);
_root = new TableLayoutPanel
{
Dock = DockStyle.Fill,
BackColor = Color.Transparent,
ColumnCount = 2,
RowCount = 1,
Margin = Padding.Empty,
Padding = Padding.Empty
};
_root.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 67F));
_root.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33F));
_root.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
_info = new TableLayoutPanel
{
Dock = DockStyle.Fill,
BackColor = Color.Transparent,
ColumnCount = 2,
RowCount = 4,
Margin = Padding.Empty,
Padding = new Padding(0, 0, 7, 0)
};
_info.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 65F));
_info.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 35F));
_info.RowStyles.Add(new RowStyle(SizeType.Absolute, 19F));
_info.RowStyles.Add(new RowStyle(SizeType.Absolute, 13F));
_info.RowStyles.Add(new RowStyle(SizeType.Absolute, 27F));
_info.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
_lblTitulo = new Label
{
Dock = DockStyle.Fill,
AutoSize = false,
BackColor = Color.Transparent,
ForeColor = HmiTheme.Info,
Font = new Font("Segoe UI", 9.25F, FontStyle.Bold),
Text = "Câmera",
TextAlign = ContentAlignment.MiddleLeft,
Margin = Padding.Empty
};
_lblStatus = new Label
{
AutoSize = true,
Anchor = AnchorStyles.Right,
BackColor = Color.Transparent,
ForeColor = HmiTheme.TextMuted,
Font = new Font("Segoe UI", 7.5F, FontStyle.Bold),
Text = "Não selecionada",
TextAlign = ContentAlignment.MiddleRight,
Margin = Padding.Empty
};
Label lblDispositivo = CreateCaption("Dispositivo");
Label lblPorta = CreateCaption("Porta TCP");
_cmbCamera = new ComboBox
{
Dock = DockStyle.Fill,
DropDownStyle = ComboBoxStyle.DropDown,
FlatStyle = FlatStyle.Flat,
BackColor = HmiTheme.SurfaceRaised,
ForeColor = HmiTheme.Text,
Font = new Font("Segoe UI", 8.5F),
Margin = new Padding(0, 1, 5, 1)
};
_nudPorta = new NumericUpDown
{
Dock = DockStyle.Fill,
BackColor = HmiTheme.SurfaceRaised,
ForeColor = HmiTheme.Text,
BorderStyle = BorderStyle.FixedSingle,
Font = new Font("Segoe UI", 9F, FontStyle.Bold),
TextAlign = HorizontalAlignment.Center,
Minimum = 1,
Maximum = 65535,
Value = 8554,
Margin = new Padding(0, 1, 0, 1)
};
_btnTestar = new HmiSidebarButton
{
Dock = DockStyle.Left,
Width = 105,
Height = 31,
Text = "TESTAR",
IconText = "▶",
AccentColor = HmiTheme.Info,
BorderColor = HmiTheme.Border,
FillColor = HmiTheme.SurfaceRaised,
Margin = new Padding(0, 3, 0, 0)
};
_preview = new PictureBox
{
Dock = DockStyle.Fill,
BackColor = Color.Black,
BorderStyle = BorderStyle.FixedSingle,
SizeMode = PictureBoxSizeMode.Zoom,
Margin = Padding.Empty
};
_info.Controls.Add(_lblTitulo, 0, 0);
_info.Controls.Add(_lblStatus, 1, 0);
_info.Controls.Add(lblDispositivo, 0, 1);
_info.Controls.Add(lblPorta, 1, 1);
_info.Controls.Add(_cmbCamera, 0, 2);
_info.Controls.Add(_nudPorta, 1, 2);
_info.Controls.Add(_btnTestar, 0, 3);
_info.SetColumnSpan(_btnTestar, 2);
_root.Controls.Add(_info, 0, 0);
_root.Controls.Add(_preview, 1, 0);
Controls.Add(_root);
_cmbCamera.SelectedIndexChanged += delegate
{
if (CameraChanged != null)
CameraChanged(this, EventArgs.Empty);
RaiseValueChanged();
};
_nudPorta.ValueChanged += delegate { RaiseValueChanged(); };
_btnTestar.Click += delegate
{
if (TestRequested != null)
TestRequested(this, EventArgs.Empty);
};
}
private static Label CreateCaption(string text)
{
return new Label
{
Dock = DockStyle.Fill,
AutoSize = false,
BackColor = Color.Transparent,
ForeColor = HmiTheme.TextMuted,
Font = new Font("Segoe UI", 7F),
Text = text,
TextAlign = ContentAlignment.BottomLeft,
Margin = Padding.Empty
};
}
private void RaiseValueChanged()
{
if (ValueChanged != null)
ValueChanged(this, EventArgs.Empty);
}
[Category("Conteúdo")]
public string Titulo
{
get { return _lblTitulo.Text; }
set { _lblTitulo.Text = value ?? string.Empty; }
}
[Category("Conteúdo")]
public string Status
{
get { return _lblStatus.Text; }
set { _lblStatus.Text = value ?? string.Empty; }
}
[Category("Aparência")]
public Color StatusColor
{
get { return _lblStatus.ForeColor; }
set { _lblStatus.ForeColor = value; }
}
[Browsable(false)]
public ComboBox CameraCombo
{
get { return _cmbCamera; }
}
[Category("Dados")]
public int PortaTcp
{
get { return Decimal.ToInt32(_nudPorta.Value); }
set
{
decimal ajustado = Math.Max(_nudPorta.Minimum, Math.Min(_nudPorta.Maximum, value));
_nudPorta.Value = ajustado;
}
}
[Category("Conteúdo")]
public Image Preview
{
get { return _preview.Image; }
set
{
Image anterior = _preview.Image;
_preview.Image = value;
if (anterior != null && anterior != value)
anterior.Dispose();
}
}
public void ClearPreview()
{
Preview = null;
_preview.BackColor = Color.Black;
}
}
}

View File

@ -0,0 +1,52 @@
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Controls
{
public class HmiDiagnosticTabButton : Button
{
private bool _selected;
public HmiDiagnosticTabButton()
{
FlatStyle = FlatStyle.Flat;
FlatAppearance.BorderSize = 1;
FlatAppearance.BorderColor = HmiTheme.Border;
BackColor = HmiTheme.Surface;
ForeColor = HmiTheme.TextMuted;
Font = new Font("Segoe UI", 8F);
Cursor = Cursors.Hand;
Height = 32;
Margin = new Padding(1);
UseVisualStyleBackColor = false;
}
[Category("Estado")]
public bool Selected
{
get { return _selected; }
set
{
_selected = value;
AplicarEstado();
}
}
private void AplicarEstado()
{
if (_selected)
{
BackColor = Color.FromArgb(20, 59, 96);
ForeColor = HmiTheme.Text;
FlatAppearance.BorderColor = HmiTheme.Info;
}
else
{
BackColor = HmiTheme.Surface;
ForeColor = HmiTheme.TextMuted;
FlatAppearance.BorderColor = HmiTheme.Border;
}
}
}
}

View File

@ -0,0 +1,72 @@
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Controls
{
public class HmiMetricTile : UserControl
{
private readonly Label _lblCaption;
private readonly Label _lblValue;
public HmiMetricTile()
{
BackColor = HmiTheme.SurfaceRaised;
Margin = new Padding(3);
Padding = new Padding(6, 3, 6, 3);
Height = 48;
MinimumSize = Size.Empty;
_lblCaption = new Label
{
Dock = DockStyle.Top,
Height = 18,
AutoSize = false,
AutoEllipsis = true,
BackColor = Color.Transparent,
ForeColor = HmiTheme.TextMuted,
Font = new Font("Segoe UI", 7F),
Text = "Métrica",
TextAlign = ContentAlignment.MiddleCenter,
Margin = Padding.Empty
};
_lblValue = new Label
{
Dock = DockStyle.Fill,
AutoSize = false,
AutoEllipsis = true,
BackColor = Color.Transparent,
ForeColor = HmiTheme.Info,
Font = new Font("Segoe UI", 10F, FontStyle.Bold),
Text = "0",
TextAlign = ContentAlignment.MiddleCenter,
Margin = Padding.Empty
};
Controls.Add(_lblValue);
Controls.Add(_lblCaption);
}
[Category("Conteúdo")]
public string Caption
{
get { return _lblCaption.Text; }
set { _lblCaption.Text = value ?? string.Empty; }
}
[Category("Conteúdo")]
public string ValueText
{
get { return _lblValue.Text; }
set { _lblValue.Text = value ?? string.Empty; }
}
[Category("Aparência")]
public Color ValueColor
{
get { return _lblValue.ForeColor; }
set { _lblValue.ForeColor = value; }
}
}
}

View File

@ -0,0 +1,173 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Controls
{
public enum HmiModuleState
{
Operante = 0,
Alerta = 1,
Falha = 2,
Desconectado = 3,
Selecionado = 4
}
[DefaultEvent("Click")]
public class HmiModuleBadge : Control
{
private HmiModuleState _state = HmiModuleState.Operante;
private string _moduleCode = "MOD";
public HmiModuleBadge()
{
SetStyle(
ControlStyles.SupportsTransparentBackColor |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw,
true);
DoubleBuffered = true;
BackColor = Color.Transparent;
ForeColor = HmiTheme.Text;
Cursor = Cursors.Hand;
Font = new Font("Segoe UI", 8F, FontStyle.Bold);
Size = new Size(45, 27);
MinimumSize = new Size(42, 26);
UpdateStyles();
}
[Category("Conteúdo")]
public string ModuleCode
{
get { return _moduleCode; }
set
{
_moduleCode = value ?? string.Empty;
Invalidate();
}
}
[Category("Estado")]
public HmiModuleState State
{
get { return _state; }
set
{
_state = value;
Invalidate();
}
}
private Color Accent
{
get
{
switch (_state)
{
case HmiModuleState.Alerta:
return HmiTheme.Warning;
case HmiModuleState.Falha:
return HmiTheme.Danger;
case HmiModuleState.Desconectado:
return HmiTheme.TextMuted;
case HmiModuleState.Selecionado:
return HmiTheme.Info;
case HmiModuleState.Operante:
default:
return HmiTheme.Success;
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(0, 0, Width - 1, Height - 1);
using (GraphicsPath path = CriarCaminhoArredondado(rect, 7))
{
Color accent = Accent;
using (SolidBrush fill = new SolidBrush(
Color.FromArgb(34, accent.R, accent.G, accent.B)))
{
e.Graphics.FillPath(fill, path);
}
using (Pen border = new Pen(
accent,
_state == HmiModuleState.Selecionado ? 2F : 1.2F))
{
e.Graphics.DrawPath(border, path);
}
}
TextRenderer.DrawText(
e.Graphics,
_moduleCode,
Font,
rect,
_state == HmiModuleState.Desconectado
? HmiTheme.TextMuted
: HmiTheme.Text,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter |
TextFormatFlags.EndEllipsis);
}
private static GraphicsPath CriarCaminhoArredondado(
Rectangle bounds,
int radius)
{
GraphicsPath path = new GraphicsPath();
int diameter = radius * 2;
path.AddArc(
bounds.Left,
bounds.Top,
diameter,
diameter,
180,
90);
path.AddArc(
bounds.Right - diameter,
bounds.Top,
diameter,
diameter,
270,
90);
path.AddArc(
bounds.Right - diameter,
bounds.Bottom - diameter,
diameter,
diameter,
0,
90);
path.AddArc(
bounds.Left,
bounds.Bottom - diameter,
diameter,
diameter,
90,
90);
path.CloseFigure();
return path;
}
}
}

View File

@ -0,0 +1,307 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Controls
{
/// <summary>
/// Editor compacto de interface, IP, máscara e gateway.
/// </summary>
[DefaultEvent("InterfaceChanged")]
public class HmiNetworkEditor : UserControl
{
private readonly TableLayoutPanel _root;
private readonly TableLayoutPanel _fields;
private readonly Label _lblTitulo;
private readonly Label _lblStatus;
private readonly ComboBox _cmbInterface;
private readonly TextBox _txtIp;
private readonly TextBox _txtMask;
private readonly TextBox _txtGateway;
public event EventHandler InterfaceChanged;
public event EventHandler ValueChanged;
public HmiNetworkEditor()
{
DoubleBuffered = true;
BackColor = Color.Transparent;
Height = 67;
MinimumSize = new Size(250, 63);
Margin = new Padding(0, 2, 0, 3);
_root = new TableLayoutPanel
{
Dock = DockStyle.Fill,
BackColor = Color.Transparent,
ColumnCount = 2,
RowCount = 2,
Margin = Padding.Empty,
Padding = Padding.Empty
};
_root.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
_root.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
_root.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F));
_root.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
_lblTitulo = new Label
{
Dock = DockStyle.Fill,
AutoSize = false,
BackColor = Color.Transparent,
ForeColor = HmiTheme.Info,
Font = new Font("Segoe UI", 9.25F, FontStyle.Bold),
Text = "Rede",
TextAlign = ContentAlignment.MiddleLeft,
Margin = Padding.Empty
};
_lblStatus = new Label
{
AutoSize = true,
Anchor = AnchorStyles.Right,
BackColor = Color.Transparent,
ForeColor = HmiTheme.TextMuted,
Font = new Font("Segoe UI", 7.75F, FontStyle.Bold),
Text = "Não testada",
TextAlign = ContentAlignment.MiddleRight,
Margin = new Padding(5, 0, 0, 0)
};
_fields = new TableLayoutPanel
{
Dock = DockStyle.Fill,
BackColor = Color.Transparent,
ColumnCount = 4,
RowCount = 2,
Margin = Padding.Empty,
Padding = Padding.Empty
};
_fields.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 22F));
_fields.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 27F));
_fields.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 27F));
_fields.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 24F));
_fields.RowStyles.Add(new RowStyle(SizeType.Absolute, 18F));
_fields.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
AddCaption("Interface", 0);
AddCaption("IP", 1);
AddCaption("Máscara", 2);
AddCaption("Gateway", 3);
_cmbInterface = CreateCombo();
_txtIp = CreateText();
_txtMask = CreateText();
_txtGateway = CreateText();
_fields.Controls.Add(_cmbInterface, 0, 1);
_fields.Controls.Add(_txtIp, 1, 1);
_fields.Controls.Add(_txtMask, 2, 1);
_fields.Controls.Add(_txtGateway, 3, 1);
_root.Controls.Add(_lblTitulo, 0, 0);
_root.Controls.Add(_lblStatus, 1, 0);
_root.Controls.Add(_fields, 0, 1);
_root.SetColumnSpan(_fields, 2);
Controls.Add(_root);
_cmbInterface.SelectedIndexChanged += delegate
{
if (InterfaceChanged != null)
InterfaceChanged(this, EventArgs.Empty);
RaiseValueChanged();
};
_txtIp.TextChanged += delegate { RaiseValueChanged(); };
_txtMask.TextChanged += delegate { RaiseValueChanged(); };
_txtGateway.TextChanged += delegate { RaiseValueChanged(); };
}
public void DefinirInterfaces(IEnumerable<string> interfaces, string interfaceSelecionada = null)
{
string selecaoAnterior = interfaceSelecionada ?? InterfaceName;
_cmbInterface.BeginUpdate();
try
{
_cmbInterface.Items.Clear();
if (interfaces != null)
{
_cmbInterface.Items.AddRange(
interfaces
.Where(x => !string.IsNullOrWhiteSpace(x))
.Distinct()
.Cast<object>()
.ToArray()
);
}
SelecionarInterface(selecaoAnterior);
}
finally
{
_cmbInterface.EndUpdate();
}
}
private void AddCaption(string text, int column)
{
_fields.Controls.Add(new Label
{
Dock = DockStyle.Fill,
AutoSize = false,
BackColor = Color.Transparent,
ForeColor = HmiTheme.TextMuted,
Font = new Font("Segoe UI", 7F),
Text = text,
TextAlign = ContentAlignment.BottomLeft,
Margin = Padding.Empty
}, column, 0);
}
private static ComboBox CreateCombo()
{
return new ComboBox
{
Dock = DockStyle.Fill,
DropDownStyle = ComboBoxStyle.DropDownList,
FlatStyle = FlatStyle.Flat,
BackColor = HmiTheme.SurfaceRaised,
ForeColor = HmiTheme.Text,
Font = new Font("Segoe UI", 8F),
Margin = new Padding(0, 1, 4, 0)
};
}
private static TextBox CreateText()
{
return new TextBox
{
Dock = DockStyle.Fill,
BackColor = HmiTheme.SurfaceRaised,
ForeColor = HmiTheme.Text,
BorderStyle = BorderStyle.FixedSingle,
Font = new Font("Segoe UI", 7.8F),
TextAlign = HorizontalAlignment.Center,
Margin = new Padding(0, 1, 4, 0)
};
}
private void RaiseValueChanged()
{
if (ValueChanged != null)
ValueChanged(this, EventArgs.Empty);
}
[Category("Conteúdo")]
public string Titulo
{
get { return _lblTitulo.Text; }
set { _lblTitulo.Text = value ?? string.Empty; }
}
[Category("Conteúdo")]
public string Status
{
get { return _lblStatus.Text; }
set { _lblStatus.Text = value ?? string.Empty; }
}
[Category("Aparência")]
public Color StatusColor
{
get { return _lblStatus.ForeColor; }
set { _lblStatus.ForeColor = value; }
}
[Browsable(false)]
public ComboBox InterfaceCombo
{
get { return _cmbInterface; }
}
[Category("Dados")]
public string InterfaceName
{
get
{
return ObterNomeInterface(_cmbInterface.Text);
}
set
{
SelecionarInterface(value);
}
}
private void SelecionarInterface(string interfaceDesejada)
{
interfaceDesejada = ObterNomeInterface(interfaceDesejada);
if (string.IsNullOrWhiteSpace(interfaceDesejada))
{
_cmbInterface.SelectedIndex = -1;
return;
}
for (int i = 0; i < _cmbInterface.Items.Count; i++)
{
string itemCompleto = Convert.ToString(_cmbInterface.Items[i]);
string nomeItem = ObterNomeInterface(itemCompleto);
if (string.Equals(nomeItem, interfaceDesejada, StringComparison.OrdinalIgnoreCase))
{
_cmbInterface.SelectedIndex = i;
return;
}
}
_cmbInterface.SelectedIndex = -1;
}
private static string ObterNomeInterface(string texto)
{
if (string.IsNullOrWhiteSpace(texto))
return string.Empty;
int indiceParenteses = texto.IndexOf('(');
if (indiceParenteses >= 0)
{
texto = texto.Substring(0, indiceParenteses);
}
return texto.Trim();
}
[Category("Dados")]
public string Ip
{
get { return _txtIp.Text; }
set { _txtIp.Text = value ?? string.Empty; }
}
[Category("Dados")]
public string Mask
{
get { return _txtMask.Text; }
set { _txtMask.Text = value ?? string.Empty; }
}
[Category("Dados")]
public string Gateway
{
get { return _txtGateway.Text; }
set { _txtGateway.Text = value ?? string.Empty; }
}
}
}

View File

@ -0,0 +1,159 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace AgroBase.Forms.IHM.Controls
{
/// <summary>
/// Campo numérico compacto, padronizado e amigável para touchscreen.
/// </summary>
[DefaultEvent("ValueChanged")]
public class HmiNumericField : UserControl
{
private readonly TableLayoutPanel _layout;
private readonly Label _lblTitulo;
private readonly NumericUpDown _numeric;
private readonly Label _lblUnidade;
public event EventHandler ValueChanged;
public HmiNumericField()
{
DoubleBuffered = true;
BackColor = Color.Transparent;
Height = 53;
MinimumSize = Size.Empty;
Dock = DockStyle.Fill;
Margin = new Padding(2);
_layout = new TableLayoutPanel
{
Dock = DockStyle.Fill,
BackColor = Color.Transparent,
ColumnCount = 2,
RowCount = 2,
Margin = Padding.Empty,
Padding = Padding.Empty
};
_layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
_layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
_layout.RowStyles.Add(new RowStyle(SizeType.Absolute, 21F));
_layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
_lblTitulo = new Label
{
Dock = DockStyle.Fill,
AutoSize = false,
AutoEllipsis = true,
BackColor = Color.Transparent,
ForeColor = HmiTheme.TextMuted,
Font = new Font("Segoe UI", 7.6F, FontStyle.Regular),
Text = "Parâmetro",
TextAlign = ContentAlignment.BottomLeft,
Margin = Padding.Empty
};
_numeric = new NumericUpDown
{
Dock = DockStyle.Fill,
BackColor = HmiTheme.SurfaceRaised,
ForeColor = HmiTheme.Text,
BorderStyle = BorderStyle.FixedSingle,
Font = new Font("Segoe UI", 10.5F, FontStyle.Bold),
TextAlign = HorizontalAlignment.Center,
DecimalPlaces = 1,
Minimum = -100000,
Maximum = 100000,
Increment = 1,
Margin = new Padding(0, 2, 4, 0),
ThousandsSeparator = false
};
_lblUnidade = new Label
{
AutoSize = true,
Anchor = AnchorStyles.Right,
BackColor = Color.Transparent,
ForeColor = HmiTheme.TextMuted,
Font = new Font("Segoe UI", 8F, FontStyle.Bold),
Text = string.Empty,
TextAlign = ContentAlignment.MiddleRight,
Margin = new Padding(3, 0, 2, 0)
};
_layout.Controls.Add(_lblTitulo, 0, 0);
_layout.SetColumnSpan(_lblTitulo, 2);
_layout.Controls.Add(_numeric, 0, 1);
_layout.Controls.Add(_lblUnidade, 1, 1);
Controls.Add(_layout);
_numeric.ValueChanged += delegate
{
if (ValueChanged != null)
ValueChanged(this, EventArgs.Empty);
};
}
[Category("Conteúdo")]
public string Titulo
{
get { return _lblTitulo.Text; }
set { _lblTitulo.Text = value ?? string.Empty; }
}
[Category("Conteúdo")]
public string Unidade
{
get { return _lblUnidade.Text; }
set { _lblUnidade.Text = value ?? string.Empty; }
}
[Category("Dados")]
public decimal Value
{
get { return _numeric.Value; }
set
{
decimal ajustado = Math.Max(_numeric.Minimum, Math.Min(_numeric.Maximum, value));
_numeric.Value = ajustado;
}
}
[Category("Dados")]
public decimal Minimum
{
get { return _numeric.Minimum; }
set { _numeric.Minimum = value; }
}
[Category("Dados")]
public decimal Maximum
{
get { return _numeric.Maximum; }
set { _numeric.Maximum = value; }
}
[Category("Dados")]
public decimal Increment
{
get { return _numeric.Increment; }
set { _numeric.Increment = value; }
}
[Category("Dados")]
public int DecimalPlaces
{
get { return _numeric.DecimalPlaces; }
set { _numeric.DecimalPlaces = Math.Max(0, Math.Min(4, value)); }
}
[Browsable(false)]
public NumericUpDown NumericControl
{
get { return _numeric; }
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,193 @@
using System;
using AgroBase.Forms.IHM.Controls;
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 System.Windows.Forms;
namespace AgroBase.Forms.IHM
{
public partial class frmDiagnosticos : Form
public partial class frmDiagnosticos : Form, ITelaNavegavel
{
private readonly List<HmiModuleBadge> _badges = new List<HmiModuleBadge>();
private readonly Dictionary<HmiModuleBadge, HmiModuleState> _estadoOriginalBadges = new Dictionary<HmiModuleBadge, HmiModuleState>();
public event EventHandler VoltarSolicitado;
public frmDiagnosticos()
{
InitializeComponent();
RegistrarBadges();
OrganizarCamadasMapa();
ConfigurarEstadoInicial();
VincularEventos();
}
private void OrganizarCamadasMapa()
{
picRover.SendToBack();
lblMapaTitulo.BringToFront();
pnlImpedimentoMapa.BringToFront();
pnlLegenda.BringToFront();
foreach (Control controle in pnlMapa.Controls)
{
HmiModuleBadge badge = controle as HmiModuleBadge;
if (badge != null)
badge.BringToFront();
}
}
private void RegistrarBadges()
{
_badges.Clear();
_estadoOriginalBadges.Clear();
RegistrarBadge(badgeBat);
RegistrarBadge(badgeB36);
RegistrarBadge(badgeB24);
RegistrarBadge(badgeB19);
RegistrarBadge(badgeB12);
RegistrarBadge(badgeB7);
RegistrarBadge(badgeB5);
RegistrarBadge(badgeB3);
RegistrarBadge(badgeDir);
RegistrarBadge(badgeMov);
RegistrarBadge(badgeTmp);
RegistrarBadge(badgeMag);
RegistrarBadge(badgeImu);
RegistrarBadge(badgeGps);
RegistrarBadge(badgeSen);
RegistrarBadge(badgeNpc);
RegistrarBadge(badgeCan);
RegistrarBadge(badgeLan);
RegistrarBadge(badgeCls);
RegistrarBadge(badgeCle);
RegistrarBadge(badgePrs);
RegistrarBadge(badgeAtu);
RegistrarBadge(badgeAgit);
RegistrarBadge(badgeFlx);
RegistrarBadge(badgeCam);
RegistrarBadge(badgeB01);
RegistrarBadge(badgeB02);
RegistrarBadge(badgeB03);
RegistrarBadge(badgeB04);
RegistrarBadge(badgeB05);
RegistrarBadge(badgeB06);
RegistrarBadge(badgeB07);
}
private void RegistrarBadge(HmiModuleBadge badge)
{
if (badge == null)
return;
_badges.Add(badge);
_estadoOriginalBadges[badge] = badge.State;
}
private void ConfigurarEstadoInicial()
{
tabCondicoes.Selected = false;
tabAcompanhamento.Selected = true;
tabOpcoes.Selected = false;
tabLogs.Selected = false;
metricFrontal.ValueColor = HmiTheme.Info;
metricLateral.ValueColor = HmiTheme.Info;
metricRisk.ValueColor = HmiTheme.Warning;
metricAssistencia.ValueColor = HmiTheme.Success;
SelecionarModulo(badgeImu);
}
private void VincularEventos()
{
btnVoltar.Click += btnVoltar_Click;
tabCondicoes.Click += delegate
{
SelecionarAba(
tabCondicoes,
"Condições operacionais do módulo");
};
tabAcompanhamento.Click += delegate
{
SelecionarAba(
tabAcompanhamento,
"Acompanhamento e histórico em tempo real");
};
tabOpcoes.Click += delegate
{
SelecionarAba(
tabOpcoes,
"Ações locais disponíveis para o módulo");
};
tabLogs.Click += delegate
{
SelecionarAba(
tabLogs,
"Logs recentes do módulo");
};
foreach (HmiModuleBadge badge in _badges)
badge.Click += Badge_Click;
}
private void btnVoltar_Click(object sender, EventArgs e)
{
if (VoltarSolicitado != null)
VoltarSolicitado(this, EventArgs.Empty);
}
private void Badge_Click(object sender, EventArgs e)
{
HmiModuleBadge selecionado = sender as HmiModuleBadge;
if (selecionado == null)
return;
SelecionarModulo(selecionado);
}
private void SelecionarModulo(HmiModuleBadge selecionado)
{
foreach (HmiModuleBadge badge in _badges)
{
HmiModuleState original;
if (_estadoOriginalBadges.TryGetValue(badge, out original))
{
badge.State = original;
}
}
selecionado.State = HmiModuleState.Selecionado;
lblModuloValor.Text = selecionado.ModuleCode;
lblLabelValor.Text = selecionado.ModuleCode;
lblIdVisualValor.Text = selecionado.ModuleCode;
}
private void SelecionarAba(HmiDiagnosticTabButton selecionada, string descricao)
{
tabCondicoes.Selected = false;
tabAcompanhamento.Selected = false;
tabOpcoes.Selected = false;
tabLogs.Selected = false;
selecionada.Selected = true;
lblConteudoAba.Text = descricao;
}
}
}

View File

@ -17,6 +17,10 @@ namespace AgroBase.Forms.IHM
private Form _telaAtual;
public frmMenu frmMenu = new frmMenu();
private frmAjustes _frmAjustes;
private frmDiagnosticos _frmDiagnosticos;
//private frmOperacao _frmOperacao;
//private frmTestes _frmTestes;
private StatusOperacaoControl cardBateria;
private StatusOperacaoControl cardReservatorio;
@ -33,10 +37,59 @@ namespace AgroBase.Forms.IHM
{
InitializeComponent();
VincularNavegacaoMenu();
CriarCardsResumo();
VincularAcoesLaterais();
}
private void VincularNavegacaoMenu()
{
frmMenu.TelaSolicitada += FrmMenu_TelaSolicitada;
}
private void TelaFilha_VoltarSolicitado(object sender, EventArgs e)
{
AbrirTela(frmMenu);
}
private void FrmMenu_TelaSolicitada(object sender, TelaSolicitadaEventArgs e)
{
switch (e.Tela)
{
case TipoTelaIHM.Operacao:
//AbrirOperacao();
break;
case TipoTelaIHM.Ajustes:
if (_frmAjustes == null || _frmAjustes.IsDisposed)
{
_frmAjustes = new frmAjustes();
_frmAjustes.VoltarSolicitado += TelaFilha_VoltarSolicitado;
}
AbrirTela(_frmAjustes);
break;
case TipoTelaIHM.Diagnostico:
if (_frmDiagnosticos == null || _frmDiagnosticos.IsDisposed)
{
_frmDiagnosticos = new frmDiagnosticos();
_frmDiagnosticos.VoltarSolicitado += TelaFilha_VoltarSolicitado;
}
AbrirTela(_frmDiagnosticos);
break;
case TipoTelaIHM.Testes:
//AbrirTestes();
break;
case TipoTelaIHM.Menu:
default:
AbrirTela(frmMenu);
break;
}
}
private void CriarCardsResumo()
{
cardBateria = CriarCard(
@ -446,9 +499,7 @@ namespace AgroBase.Forms.IHM
try
{
if (_telaAtual != null &&
!_telaAtual.IsDisposed &&
_telaAtual != tela)
if (_telaAtual != null && !_telaAtual.IsDisposed && _telaAtual != tela)
{
pnlConteudo.Controls.Remove(_telaAtual);
_telaAtual.Hide();
@ -979,4 +1030,11 @@ namespace AgroBase.Forms.IHM
}
public interface ITelaNavegavel
{
event EventHandler VoltarSolicitado;
}
}

View File

@ -21,63 +21,30 @@ namespace AgroBase.Forms.IHM
/// Estes eventos deixam os atalhos de campo prontos para receber
/// a implementação real sem precisar alterar o componente visual.
/// </summary>
public event EventHandler OperacaoSolicitada;
public event EventHandler AjustarLeverArmSolicitado;
public event EventHandler<TelaSolicitadaEventArgs> TelaSolicitada;
public frmMenu()
{
InitializeComponent();
VincularAcaoAsync(
tileOperacao,
"Erro ao carregar operação!",
AbrirOperacaoAsync);
VincularAcaoAsync(tileOperacao, "Erro ao carregar operação!", AbrirOperacaoAsync);
VincularAcaoAsync(
tileTestes,
"Erro ao processar testes!",
async delegate
{
using (var frm = new frmTestes())
{
frm.ShowDialog(this);
}
VincularAcaoAsync(tileModoManual, "Erro ao carregar modo de controle manual!", AbrirModoManualAsync);
await Task.CompletedTask;
});
VincularAcaoAsync(tileDiagnosticos, "Erro ao processar diagnósticos!", AbrirDiagnosticoAsync);
VincularAcaoAsync(
tileAjustes,
"Erro ao realizar ajustes!",
async delegate
{
using (var frm = new frmAjustes())
{
frm.ShowDialog(this);
}
VincularAcaoAsync(tileAjustes, "Erro ao realizar ajustes!", AbrirAjustesAsync);
await Task.CompletedTask;
});
VincularAcaoAsync(tileTestes, "Erro ao processar testes!", AbrirTestesAsync);
VincularAcaoAsync(
tileModoManual,
"Erro ao carregar modo de controle manual!",
AbrirModoManualAsync);
VincularAcaoAsync(tileDesligar, "Erro ao desligar equipamento!", DesligarEquipamentoAsync);
VincularAcaoAsync(
tileDesligar,
"Erro ao desligar equipamento!",
DesligarEquipamentoAsync);
VincularAcaoAsync(
btnSincronizarArquivos,
"Erro ao procurar por atualizações!",
ProcurarAtualizacoesAsync);
VincularAcaoAsync(btnSincronizarArquivos, "Erro ao procurar por atualizações!", ProcurarAtualizacoesAsync);
VincularAcaoAsync(
pnlAtualizacoes,
"Erro ao procurar por atualizações!",
ProcurarAtualizacoesAsync);
VincularAcaoAsync(pnlAtualizacoes, "Erro ao procurar por atualizações!", ProcurarAtualizacoesAsync);
VincularCliqueRecursivo(
pnlAtualizacoes,
@ -163,26 +130,28 @@ namespace AgroBase.Forms.IHM
}));
}
private async Task AbrirOperacaoAsync()
private Task AbrirAjustesAsync()
{
if (OperacaoSolicitada != null)
{
OperacaoSolicitada(this, EventArgs.Empty);
await Task.CompletedTask;
return;
}
TelaSolicitada?.Invoke(this, new TelaSolicitadaEventArgs(TipoTelaIHM.Ajustes));
return Task.CompletedTask;
}
CustomDialog.ShowDialog(
"Operação",
"A tela de operação será aberta automaticamente quando " +
"os parâmetros forem recebidos da base.",
MessageBoxIcon.Information,
new Dictionary<(string, dynamic), Action>()
{
{ ("OK", null), delegate { } }
});
private Task AbrirDiagnosticoAsync()
{
TelaSolicitada?.Invoke(this, new TelaSolicitadaEventArgs(TipoTelaIHM.Diagnostico));
return Task.CompletedTask;
}
await Task.CompletedTask;
private Task AbrirOperacaoAsync()
{
TelaSolicitada?.Invoke(this, new TelaSolicitadaEventArgs(TipoTelaIHM.Operacao));
return Task.CompletedTask;
}
private Task AbrirTestesAsync()
{
TelaSolicitada?.Invoke(this, new TelaSolicitadaEventArgs(TipoTelaIHM.Testes));
return Task.CompletedTask;
}
private async Task AbrirModoManualAsync()
@ -415,4 +384,26 @@ namespace AgroBase.Forms.IHM
}
}
public enum TipoTelaIHM
{
Menu,
Operacao,
Ajustes,
Diagnostico,
Testes
}
public class TelaSolicitadaEventArgs : EventArgs
{
public TipoTelaIHM Tela { get; private set; }
public TelaSolicitadaEventArgs(TipoTelaIHM tela)
{
Tela = tela;
}
}
}

View File

@ -372,7 +372,7 @@ namespace AgroBase.Forms
velocidadeMs,
tempoGps,
anguloAtual,
VariaveisEquipamento.DistanciaEntreEixos
VariaveisEquipamento.DistanciaEntreEixosCm
);
// Atualiza a interface gráfica

View File

@ -79,7 +79,7 @@ public class MPCController
.ToList(),
horizonte = Horizonte,
angulo_max_graus = pControle.DirAnguloMaximo,
distancia_entre_eixos = (VariaveisEquipamento.DistanciaEntreEixos / 100.0),
distancia_entre_eixos = (VariaveisEquipamento.DistanciaEntreEixosCm / 100.0),
velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeCErvasPercent),
velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeSErvasPercent)
};

View File

@ -820,7 +820,7 @@ namespace AgroBase.Models.Modules
indice = 1,
analise_health = true,
maximo = VariaveisEquipamento.CapacidadeReservatorio + 10.0,
minimo = VariaveisEquipamento.PercentualReservatorioMinCritio,
minimo = VariaveisEquipamento.PercentualReservatorioMinCritico,
nominal = VariaveisEquipamento.CapacidadeReservatorio,
unidade_medida = "Kg"
}

View File

@ -669,7 +669,7 @@ namespace AgroBase.Models.Modules
public class MovimentacaoMovimentoCompensadoModel
{
static List<TipoMovimentoDirecional> MovimentosCompensar = new List<TipoMovimentoDirecional>() { TipoMovimentoDirecional.RodasDianteiras, TipoMovimentoDirecional.RodasTraseiras, TipoMovimentoDirecional.MovimentoArco };
static GeometriaRobo g = new GeometriaRobo { L = VariaveisEquipamento.DistanciaEntreEixos / 100.0, W = VariaveisEquipamento.LarguraEquipamentoMm / 1000.0 };
static GeometriaRobo g = new GeometriaRobo { L = VariaveisEquipamento.DistanciaEntreEixosCm / 100.0, W = VariaveisEquipamento.LarguraEquipamentoMm / 1000.0 };
public static Dictionary<string, double> compensacoes { get; set; } = new Dictionary<string, double>();
public static Dictionary<string, double> _compAnt { get; set; }

View File

@ -1634,7 +1634,7 @@ namespace AgroBase.Models
bool dirSaudavel = statusValidos.Contains(saude.FirstOrDefault(x => x.modulo == T_Code.Dir)?.status ?? StatusModulo.Desconectado);
bool movSaudavel = statusValidos.Contains(saude.FirstOrDefault(x => x.modulo == T_Code.Mov)?.status ?? StatusModulo.Desconectado);
bool reservatorioOk = (op.Sensoriamento?.Atuador?.PercentualReservatorio ?? 0) > VariaveisEquipamento.PercentualReservatorioMinCritio;
bool reservatorioOk = (op.Sensoriamento?.Atuador?.PercentualReservatorio ?? 0) > VariaveisEquipamento.PercentualReservatorioMinCritico;
bool bombaOk = dispAtu?.Dados?.BombaPressurizadora?.Inicializado ?? false;

View File

@ -22,7 +22,7 @@ namespace AgroBase.Models
#region PARAMETROS
public double AnguloAberturaCurva { get; set; } = 25; // Angulo usado para deslocar o ponto de curva
public double DistanciaProjecaoRua { get; set; } = (VariaveisEquipamento.DistanciaEntreEixos / 100.0 / 2.0) + 3.0; // Distancia para projetar o primeiro ponto para fora do corredor
public double DistanciaProjecaoRua { get; set; } = (VariaveisEquipamento.DistanciaEntreEixosCm / 100.0 / 2.0) + 3.0; // Distancia para projetar o primeiro ponto para fora do corredor
public static double DistanciaEntrePontos { get; set; } = 0.8; // Distancia entre os pontos dentro do corredor
public static double DistanciaEntrePontosCurva { get; set; } = 0.25; // Distancia entre os pontos durante a curva entre corredores
private double DistanciaManobraEntreRuas { get; set; } = 3.0; // Distancia máxima para gerar a curva de conexão entre os corredores

View File

@ -27,7 +27,7 @@ namespace AgroBase.Models
{
public class Variaveis
{
public static readonly bool IniciarWorkers = true;
public static readonly bool IniciarWorkers = false;
public static readonly bool UsarIHM = true;
public static readonly bool Producao = false;
public static bool DebugMode { get; set; } = false;
@ -862,9 +862,9 @@ namespace AgroBase.Models
public static double LarguraDireita { get; } = 44.0; // 22
public static double ComprimentoFrente { get; } = 90.0; // 7
public static double ComprimentoTras { get; } = 40.0; // 107
public static double DistanciaEntreEixos { get; } = 92.0;
public static double LeverArmFrontalCm { get; } = 37.0; // cm
public static double LeverArmLateralCm { get; } = 0.0; // cm
public static double DistanciaEntreEixosCm { get; set; } = 92.0;
public static double LeverArmFrontalCm { get; set; } = 37.0; // cm
public static double LeverArmLateralCm { get; set; } = 0.0; // cm
public static double LarguraEquipamentoMm
{
get
@ -877,7 +877,7 @@ namespace AgroBase.Models
public static double CorrenteMaximaBateria { get; set; } = 100.0;
public static double PercentualTensaoBateriaMin { get; set; } = 25.0;
public static double PercentualReservatorioMin { get; set; } = 8.0;
public static double PercentualReservatorioMinCritio { get; set; } = 5.0;
public static double PercentualReservatorioMinCritico { get; set; } = 5.0;
public static double PercentualToleranciaPressaoLinha { get; set; } = 0.15;
public static int QuantidadeCamerasSolo { get; set; } = 1;
public static int QuantidadeBicosPulverizadores { get; set; } = 7;
@ -1045,7 +1045,7 @@ namespace AgroBase.Models
double anguloControleRad = anguloControle * (Math.PI / 180.0);
// Evita divisão por zero (caso o ângulo seja muito pequeno)
double R = Math.Abs(anguloControleRad) < 0.01 ? 99999 : (DistanciaEntreEixos / 100.0) / Math.Tan(anguloControleRad);
double R = Math.Abs(anguloControleRad) < 0.01 ? 99999 : (DistanciaEntreEixosCm / 100.0) / Math.Tan(anguloControleRad);
// Ajusta o raio de curva de acordo com o tipo de movimento
switch (tipoMovimento)
@ -1121,7 +1121,7 @@ namespace AgroBase.Models
public static GPSModel SimularNovaPosicao(TipoMovimentoDirecional tipoMovimento, double anguloControleDeg, double velocidadeMs, double tempoDelta, double anguloAtualDeg, GPSModel pos)
{
double L = DistanciaEntreEixos / 100.0;
double L = DistanciaEntreEixosCm / 100.0;
// Defina deltas por modo
double dfDeg = 0, drDeg = 0;

View File

@ -128,7 +128,7 @@ namespace AgroBase.Services
get
{
double percentualMinimo = Clamp(
VariaveisEquipamento.PercentualReservatorioMinCritio,
VariaveisEquipamento.PercentualReservatorioMinCritico,
0,
100
);

View File

@ -242,7 +242,7 @@ namespace AgroBase.Services.Operadores
("serial_number", VariaveisEquipamento.Parametros.serial_number),
("pct_vel_min", VariaveisEquipamento.PercentualVelMin),
("largura", VariaveisEquipamento.LarguraEquipamentoMm / 1000.0),
("distancia_entre_eixos", VariaveisEquipamento.DistanciaEntreEixos / 100.0),
("distancia_entre_eixos", VariaveisEquipamento.DistanciaEntreEixosCm / 100.0),
("qtd_bicos", VariaveisEquipamento.QuantidadeBicosPulverizadores),
("percentual_reservatorio_min", VariaveisEquipamento.PercentualReservatorioMin),
("percentual_tensao_bateria_min", VariaveisEquipamento.PercentualTensaoBateriaMin),