ajustes na firmware atuador

This commit is contained in:
Diego Freitas 2025-07-23 12:14:50 -03:00
parent 4811e24d9f
commit be6e1696f0
107 changed files with 2571 additions and 943 deletions

Binary file not shown.

View File

@ -33,8 +33,8 @@
this.pnlJoystick = new System.Windows.Forms.Panel();
this.pnlMapaDinamico = new System.Windows.Forms.Panel();
this.pnlCameraCaminho = new System.Windows.Forms.Panel();
this.pnlCameraCaminhoHeat = new System.Windows.Forms.Panel();
this.pnlCameraSoloE = new System.Windows.Forms.Panel();
this.pnlCameraCaminhoSeg = new System.Windows.Forms.Panel();
this.pnlCameraSolo0 = new System.Windows.Forms.Panel();
this.lblMapaCarregado = new System.Windows.Forms.Label();
this.txtStatusAtual = new System.Windows.Forms.TextBox();
this.lblStatusAtual = new System.Windows.Forms.Label();
@ -143,24 +143,27 @@
//
// pnlCameraCaminho
//
this.pnlCameraCaminho.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.pnlCameraCaminho.Location = new System.Drawing.Point(246, 2);
this.pnlCameraCaminho.Name = "pnlCameraCaminho";
this.pnlCameraCaminho.Size = new System.Drawing.Size(210, 150);
this.pnlCameraCaminho.TabIndex = 18;
//
// pnlCameraCaminhoHeat
// pnlCameraCaminhoSeg
//
this.pnlCameraCaminhoHeat.Location = new System.Drawing.Point(484, 2);
this.pnlCameraCaminhoHeat.Name = "pnlCameraCaminhoHeat";
this.pnlCameraCaminhoHeat.Size = new System.Drawing.Size(210, 150);
this.pnlCameraCaminhoHeat.TabIndex = 18;
this.pnlCameraCaminhoSeg.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.pnlCameraCaminhoSeg.Location = new System.Drawing.Point(484, 2);
this.pnlCameraCaminhoSeg.Name = "pnlCameraCaminhoSeg";
this.pnlCameraCaminhoSeg.Size = new System.Drawing.Size(210, 150);
this.pnlCameraCaminhoSeg.TabIndex = 18;
//
// pnlCameraSoloE
// pnlCameraSolo0
//
this.pnlCameraSoloE.Location = new System.Drawing.Point(3, 2);
this.pnlCameraSoloE.Name = "pnlCameraSoloE";
this.pnlCameraSoloE.Size = new System.Drawing.Size(210, 150);
this.pnlCameraSoloE.TabIndex = 17;
this.pnlCameraSolo0.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.pnlCameraSolo0.Location = new System.Drawing.Point(3, 2);
this.pnlCameraSolo0.Name = "pnlCameraSolo0";
this.pnlCameraSolo0.Size = new System.Drawing.Size(210, 150);
this.pnlCameraSolo0.TabIndex = 17;
//
// lblMapaCarregado
//
@ -886,9 +889,9 @@
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.statusStrip1);
this.Controls.Add(this.pnlCameraCaminho);
this.Controls.Add(this.pnlCameraCaminhoHeat);
this.Controls.Add(this.pnlCameraCaminhoSeg);
this.Controls.Add(this.lblMapaCarregado);
this.Controls.Add(this.pnlCameraSoloE);
this.Controls.Add(this.pnlCameraSolo0);
this.Controls.Add(this.pnlMapa);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
@ -948,8 +951,8 @@
private System.Windows.Forms.Panel pnlOrientacao;
private System.Windows.Forms.Panel pnlInclinacao;
private System.Windows.Forms.Panel pnlCameraCaminho;
private System.Windows.Forms.Panel pnlCameraCaminhoHeat;
private System.Windows.Forms.Panel pnlCameraSoloE;
private System.Windows.Forms.Panel pnlCameraCaminhoSeg;
private System.Windows.Forms.Panel pnlCameraSolo0;
private System.Windows.Forms.Label lblModoOperacao;
private System.Windows.Forms.TextBox txtModoOperacao;
private System.Windows.Forms.Panel pnlJoystick;

View File

@ -17,6 +17,7 @@ namespace AgroBase.Forms.IHM
AsyncTaskTimerModel tmrLeitura;
MapaDinamicoModel MapaDinamico;
private ulong CodigoFalha = 0;
private bool ReqFrameCam = false;
private bool ReqFrameSnr = false;
public frmDialogoMapa()
@ -31,12 +32,17 @@ namespace AgroBase.Forms.IHM
pnlJoystick.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlJoystick, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlFreio.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlFreio, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlCameraSolo0.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCameraSolo0, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlCameraCaminho.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCameraCaminho, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlCameraCaminhoSeg.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCameraCaminhoSeg, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
cmbModoControle.Items.Clear();
cmbModoControle.Items.AddRange(Enum.GetNames(typeof(Enums.TipoMovimentoDirecional)));
cmbModoControle.SelectedIndexChanged += CmbModoControle_SelectedIndexChanged;
pnlCameraSolo0.BackgroundImageLayout = ImageLayout.Zoom;
pnlCameraCaminho.BackgroundImageLayout = ImageLayout.Zoom;
pnlCameraCaminhoSeg.BackgroundImageLayout = ImageLayout.Zoom;
AtualizarElementosModoManual();
@ -225,15 +231,33 @@ namespace AgroBase.Forms.IHM
AtualizarMapaDinamico();
}
if (!ReqFrameCam)
{
Task.Run(async () =>
{
ReqFrameCam = true;
OAKCameraFrameModel frame = await WeedWorkerService.GetCameraFrame(CameraFrameType.Rgb);
pnlCameraSolo0.BackgroundImage?.Dispose();
try { pnlCameraSolo0.BackgroundImage = frame?.image(); } catch { }
ReqFrameCam = false;
});
}
if (!ReqFrameSnr)
{
Task.Run(async () =>
{
ReqFrameSnr = true;
OAKCameraFrameModel frame = await VisualWorkerService.GetCameraFrame(CameraFrameType.Rgb);
pnlCameraCaminho.BackgroundImage?.Dispose();
try { pnlCameraCaminho.BackgroundImage = frame?.image(); } catch { }
lblUltimaLeituraCaminho.Text = $"Última Leitura Caminho: " + frame?.timestamp.ToString("HH:mm:ss");
OAKCameraFrameModel frame2 = await VisualWorkerService.GetCameraFrame(CameraFrameType.Segmentacao);
pnlCameraCaminhoSeg.BackgroundImage?.Dispose();
try { pnlCameraCaminhoSeg.BackgroundImage = frame2?.image(); } catch { }
ReqFrameSnr = false;
});
}

View File

@ -35,7 +35,6 @@
this.lblD_Gps = new System.Windows.Forms.Label();
this.lblMqtt = new System.Windows.Forms.Label();
this.lblD_Sen_sCOR_36V = new System.Windows.Forms.Label();
this.lblD_Sen_sLRA = new System.Windows.Forms.Label();
this.lblD_Imu = new System.Windows.Forms.Label();
this.lblD_Mov_DT = new System.Windows.Forms.Label();
this.lblD_Dir_DF = new System.Windows.Forms.Label();
@ -78,6 +77,15 @@
this.lblD_Sen_sCOR_12V = new System.Windows.Forms.Label();
this.lblD_Sen_sCOR_19V = new System.Windows.Forms.Label();
this.lblD_Sen_sCOR_24V = new System.Windows.Forms.Label();
this.lblD_Atu_sPRS = new System.Windows.Forms.Label();
this.lblD_Atu_sBMB = new System.Windows.Forms.Label();
this.lblD_Sen_sLRA = new System.Windows.Forms.Label();
this.lblD_Atu_sMAS = new System.Windows.Forms.Label();
this.lblD_Atu_sFLX = new System.Windows.Forms.Label();
this.lblD_Atu_sBIC_B01 = new System.Windows.Forms.Label();
this.lblD_Atu_sBIC_B02 = new System.Windows.Forms.Label();
this.lblD_Atu_sBIC_B03 = new System.Windows.Forms.Label();
this.lblD_Atu_sBIC_B04 = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.picManual)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picDiagnosticos)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picOperacao)).BeginInit();
@ -103,7 +111,7 @@
//
this.lblD_Atu.AutoSize = true;
this.lblD_Atu.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu.Location = new System.Drawing.Point(211, 483);
this.lblD_Atu.Location = new System.Drawing.Point(415, 550);
this.lblD_Atu.Name = "lblD_Atu";
this.lblD_Atu.Size = new System.Drawing.Size(48, 24);
this.lblD_Atu.TabIndex = 4;
@ -157,24 +165,12 @@
this.lblD_Sen_sCOR_36V.Text = "B_36V";
this.lblD_Sen_sCOR_36V.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Sen_sLRA
//
this.lblD_Sen_sLRA.AutoSize = true;
this.lblD_Sen_sLRA.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.lblD_Sen_sLRA.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Sen_sLRA.Location = new System.Drawing.Point(213, 418);
this.lblD_Sen_sLRA.Name = "lblD_Sen_sLRA";
this.lblD_Sen_sLRA.Size = new System.Drawing.Size(46, 24);
this.lblD_Sen_sLRA.TabIndex = 15;
this.lblD_Sen_sLRA.Text = "LRA";
this.lblD_Sen_sLRA.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Imu
//
this.lblD_Imu.AutoSize = true;
this.lblD_Imu.BackColor = System.Drawing.Color.Lavender;
this.lblD_Imu.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Imu.Location = new System.Drawing.Point(14, 547);
this.lblD_Imu.Location = new System.Drawing.Point(14, 550);
this.lblD_Imu.Name = "lblD_Imu";
this.lblD_Imu.Size = new System.Drawing.Size(43, 24);
this.lblD_Imu.TabIndex = 16;
@ -270,7 +266,7 @@
this.lblD_Cam_0.AutoSize = true;
this.lblD_Cam_0.BackColor = System.Drawing.Color.White;
this.lblD_Cam_0.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Cam_0.Location = new System.Drawing.Point(210, 547);
this.lblD_Cam_0.Location = new System.Drawing.Point(210, 550);
this.lblD_Cam_0.Name = "lblD_Cam_0";
this.lblD_Cam_0.Size = new System.Drawing.Size(52, 24);
this.lblD_Cam_0.TabIndex = 29;
@ -649,12 +645,127 @@
this.lblD_Sen_sCOR_24V.Text = "B_24V";
this.lblD_Sen_sCOR_24V.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Atu_sPRS
//
this.lblD_Atu_sPRS.AutoSize = true;
this.lblD_Atu_sPRS.BackColor = System.Drawing.Color.Lavender;
this.lblD_Atu_sPRS.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sPRS.Location = new System.Drawing.Point(155, 480);
this.lblD_Atu_sPRS.Name = "lblD_Atu_sPRS";
this.lblD_Atu_sPRS.Size = new System.Drawing.Size(47, 24);
this.lblD_Atu_sPRS.TabIndex = 61;
this.lblD_Atu_sPRS.Text = "PRS";
this.lblD_Atu_sPRS.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Atu_sBMB
//
this.lblD_Atu_sBMB.AutoSize = true;
this.lblD_Atu_sBMB.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.lblD_Atu_sBMB.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sBMB.Location = new System.Drawing.Point(196, 418);
this.lblD_Atu_sBMB.Name = "lblD_Atu_sBMB";
this.lblD_Atu_sBMB.Size = new System.Drawing.Size(78, 24);
this.lblD_Atu_sBMB.TabIndex = 62;
this.lblD_Atu_sBMB.Text = "BOMBA";
this.lblD_Atu_sBMB.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Sen_sLRA
//
this.lblD_Sen_sLRA.AutoSize = true;
this.lblD_Sen_sLRA.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Sen_sLRA.Location = new System.Drawing.Point(213, 57);
this.lblD_Sen_sLRA.Name = "lblD_Sen_sLRA";
this.lblD_Sen_sLRA.Size = new System.Drawing.Size(46, 24);
this.lblD_Sen_sLRA.TabIndex = 63;
this.lblD_Sen_sLRA.Text = "LRA";
//
// lblD_Atu_sMAS
//
this.lblD_Atu_sMAS.AutoSize = true;
this.lblD_Atu_sMAS.BackColor = System.Drawing.Color.Lavender;
this.lblD_Atu_sMAS.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sMAS.Location = new System.Drawing.Point(269, 480);
this.lblD_Atu_sMAS.Name = "lblD_Atu_sMAS";
this.lblD_Atu_sMAS.Size = new System.Drawing.Size(51, 24);
this.lblD_Atu_sMAS.TabIndex = 64;
this.lblD_Atu_sMAS.Text = "MAS";
this.lblD_Atu_sMAS.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Atu_sFLX
//
this.lblD_Atu_sFLX.AutoSize = true;
this.lblD_Atu_sFLX.BackColor = System.Drawing.Color.Lavender;
this.lblD_Atu_sFLX.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sFLX.Location = new System.Drawing.Point(212, 480);
this.lblD_Atu_sFLX.Name = "lblD_Atu_sFLX";
this.lblD_Atu_sFLX.Size = new System.Drawing.Size(46, 24);
this.lblD_Atu_sFLX.TabIndex = 65;
this.lblD_Atu_sFLX.Text = "FLX";
this.lblD_Atu_sFLX.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Atu_sBIC_B01
//
this.lblD_Atu_sBIC_B01.AutoSize = true;
this.lblD_Atu_sBIC_B01.BackColor = System.Drawing.Color.Lavender;
this.lblD_Atu_sBIC_B01.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sBIC_B01.Location = new System.Drawing.Point(36, 528);
this.lblD_Atu_sBIC_B01.Name = "lblD_Atu_sBIC_B01";
this.lblD_Atu_sBIC_B01.Size = new System.Drawing.Size(32, 24);
this.lblD_Atu_sBIC_B01.TabIndex = 66;
this.lblD_Atu_sBIC_B01.Text = "B1";
this.lblD_Atu_sBIC_B01.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Atu_sBIC_B02
//
this.lblD_Atu_sBIC_B02.AutoSize = true;
this.lblD_Atu_sBIC_B02.BackColor = System.Drawing.Color.Lavender;
this.lblD_Atu_sBIC_B02.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sBIC_B02.Location = new System.Drawing.Point(142, 528);
this.lblD_Atu_sBIC_B02.Name = "lblD_Atu_sBIC_B02";
this.lblD_Atu_sBIC_B02.Size = new System.Drawing.Size(32, 24);
this.lblD_Atu_sBIC_B02.TabIndex = 67;
this.lblD_Atu_sBIC_B02.Text = "B2";
this.lblD_Atu_sBIC_B02.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Atu_sBIC_B03
//
this.lblD_Atu_sBIC_B03.AutoSize = true;
this.lblD_Atu_sBIC_B03.BackColor = System.Drawing.Color.White;
this.lblD_Atu_sBIC_B03.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sBIC_B03.Location = new System.Drawing.Point(297, 528);
this.lblD_Atu_sBIC_B03.Name = "lblD_Atu_sBIC_B03";
this.lblD_Atu_sBIC_B03.Size = new System.Drawing.Size(32, 24);
this.lblD_Atu_sBIC_B03.TabIndex = 68;
this.lblD_Atu_sBIC_B03.Text = "B3";
this.lblD_Atu_sBIC_B03.Click += new System.EventHandler(this.lblModulo_Click);
//
// lblD_Atu_sBIC_B04
//
this.lblD_Atu_sBIC_B04.AutoSize = true;
this.lblD_Atu_sBIC_B04.BackColor = System.Drawing.Color.White;
this.lblD_Atu_sBIC_B04.Cursor = System.Windows.Forms.Cursors.Hand;
this.lblD_Atu_sBIC_B04.Location = new System.Drawing.Point(398, 528);
this.lblD_Atu_sBIC_B04.Name = "lblD_Atu_sBIC_B04";
this.lblD_Atu_sBIC_B04.Size = new System.Drawing.Size(32, 24);
this.lblD_Atu_sBIC_B04.TabIndex = 69;
this.lblD_Atu_sBIC_B04.Text = "B4";
this.lblD_Atu_sBIC_B04.Click += new System.EventHandler(this.lblModulo_Click);
//
// frmIHM
//
this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(1024, 600);
this.Controls.Add(this.lblD_Atu_sBIC_B04);
this.Controls.Add(this.lblD_Atu_sBIC_B03);
this.Controls.Add(this.lblD_Atu_sBIC_B02);
this.Controls.Add(this.lblD_Atu_sBIC_B01);
this.Controls.Add(this.lblD_Atu_sFLX);
this.Controls.Add(this.lblD_Atu_sMAS);
this.Controls.Add(this.lblD_Sen_sLRA);
this.Controls.Add(this.lblD_Atu_sBMB);
this.Controls.Add(this.lblD_Atu_sPRS);
this.Controls.Add(this.lblD_Sen_sCOR_24V);
this.Controls.Add(this.lblD_Sen_sCOR_19V);
this.Controls.Add(this.lblD_Sen_sCOR_12V);
@ -696,7 +807,6 @@
this.Controls.Add(this.lblD_Dir_DF);
this.Controls.Add(this.lblD_Mov_DT);
this.Controls.Add(this.lblD_Imu);
this.Controls.Add(this.lblD_Sen_sLRA);
this.Controls.Add(this.lblD_Sen_sCOR_36V);
this.Controls.Add(this.lblMqtt);
this.Controls.Add(this.lblD_Gps);
@ -733,7 +843,6 @@
private System.Windows.Forms.Label lblD_Gps;
private System.Windows.Forms.Label lblMqtt;
private System.Windows.Forms.Label lblD_Sen_sCOR_36V;
private System.Windows.Forms.Label lblD_Sen_sLRA;
private System.Windows.Forms.Label lblD_Imu;
private System.Windows.Forms.Label lblD_Mov_DT;
private System.Windows.Forms.Label lblD_Dir_DF;
@ -775,5 +884,14 @@
private System.Windows.Forms.Label lblD_Sen_sCOR_12V;
private System.Windows.Forms.Label lblD_Sen_sCOR_19V;
private System.Windows.Forms.Label lblD_Sen_sCOR_24V;
private System.Windows.Forms.Label lblD_Atu_sPRS;
private System.Windows.Forms.Label lblD_Atu_sBMB;
private System.Windows.Forms.Label lblD_Sen_sLRA;
private System.Windows.Forms.Label lblD_Atu_sMAS;
private System.Windows.Forms.Label lblD_Atu_sFLX;
private System.Windows.Forms.Label lblD_Atu_sBIC_B01;
private System.Windows.Forms.Label lblD_Atu_sBIC_B02;
private System.Windows.Forms.Label lblD_Atu_sBIC_B03;
private System.Windows.Forms.Label lblD_Atu_sBIC_B04;
}
}

View File

@ -1,6 +1,7 @@
using AgroBase.Forms.Operacoes;
using AgroBase.Models;
using AgroBase.Models.Components;
using AgroBase.Models.Modules;
using AgroBase.Models.Operadores;
using AgroBase.Properties;
using AgroBase.Services;
@ -202,7 +203,7 @@ namespace AgroBase.Forms.IHM
: saudeImu.status == StatusModulo.Operante ? Color.DarkGreen
: Color.Black;
}
else if (Dispositivo == T_Code.Sen)
else if (Dispositivo == T_Code.Sen || Dispositivo == T_Code.Atu)
{
var Modulo = SerialService.DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == Dispositivo);
bool modDesconectado = Modulo == null || Modulo.Status == StatusModulo.Desconectado;
@ -240,9 +241,37 @@ namespace AgroBase.Forms.IHM
? Color.DarkGreen
: Color.DarkRed;
}
else if (Sensor == S_Code.sBIC)
{
var bico = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BicosPulverizadores.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
lbl.ForeColor = modDesconectado || bico == null
? Color.Black
: bico.Inicializado
? Color.DarkGreen
: Color.DarkRed;
}
else if (Sensor == S_Code.sBMB)
{
var bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
lbl.ForeColor = modDesconectado || bomba == null
? Color.Black
: bomba.Inicializado
? Color.DarkGreen
: Color.DarkRed;
}
else if (Sensor != S_Code.sVZO)
{
var sensor = Variaveis.OperacaoEmAndamento.DispSen.Dados.Sensores.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
SensorModel sensor = null;
if (Dispositivo == T_Code.Sen)
{
sensor = Variaveis.OperacaoEmAndamento.DispSen.Dados.Sensores.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
}
else if (Dispositivo == T_Code.Atu)
{
sensor = Variaveis.OperacaoEmAndamento.DispAtu.Dados.Sensores.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
}
if (sensor != null)
{
lbl.ForeColor = modDesconectado || sensor == null
? Color.Black
: sensor.Inicializado
@ -250,6 +279,7 @@ namespace AgroBase.Forms.IHM
: Color.DarkRed;
}
}
}
}
@ -285,7 +315,6 @@ namespace AgroBase.Forms.IHM
await Task.CompletedTask; // Mantém a assinatura assíncrona
}
private void LblCodigoFalha_Click(object sender, EventArgs e)
{
string DescricaoFalha = Variaveis.OperacaoEmAndamento.ErroOperacaoLiberada;
@ -304,7 +333,7 @@ namespace AgroBase.Forms.IHM
{
Label lbl = (Label)sender;
T_Code Dispositivo = (T_Code)Enum.Parse(typeof(T_Code), lbl.Name.Split('_')[1]);
string Mod_ID = lbl.Name.Split('_').Length == 3 ? lbl.Name.Split('_')[2] : lbl.Name.Split('_')[1];
string Mod_ID = lbl.Name.Split('_').Length >= 3 ? lbl.Name.Split('_')[2] : lbl.Name.Split('_')[1];
var Modulo = SerialService.DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == Dispositivo && (x.Mod_ID == Mod_ID || x.Mod_ID == null));
@ -324,32 +353,82 @@ namespace AgroBase.Forms.IHM
saudeIndividual = saudeGeral.saude_individual.FirstOrDefault(x => Convert.ToByte(x.id) == enderecoMod);
break;
}
case T_Code.Sen:
case T_Code.Atu:
{
bool modDesconectado = Modulo == null || Modulo.Status == StatusModulo.Desconectado;
if (Mod_ID.ToLower() == Dispositivo.ToString().ToLower())
{
saudeIndividual = null;
}
else
{
S_Code Sensor = string.IsNullOrEmpty(Mod_ID) ? S_Code.sVZO : (S_Code)Enum.Parse(typeof(S_Code), Mod_ID);
string modId = lbl.Name.Split('_').Length == 4 ? lbl.Name.Split('_')[3] : "";
if (Sensor == S_Code.sLRA)
{
//saudeIndividual = saudeGeral?.saude_individual.FirstOrDefault(x => x.id == )
}
else if (Sensor == S_Code.sFRO)
{
var freio = Variaveis.OperacaoEmAndamento.DispSen.Dados.Servos.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
saudeIndividual = saudeGeral.saude_individual.FirstOrDefault(x => x.id == freio.ID_Num.ToString());
}
else if (Sensor == S_Code.sBIC)
{
var bico = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BicosPulverizadores.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
saudeIndividual = saudeGeral.saude_individual.FirstOrDefault(x => x.id == bico.ID_Num.ToString());
}
else if (Sensor == S_Code.sBMB)
{
var bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
saudeIndividual = saudeGeral.saude_individual.FirstOrDefault(x => x.id == bomba.ID_Num.ToString());
}
else if (Sensor != S_Code.sVZO)
{
SensorModel sensor = null;
if (Dispositivo == T_Code.Sen)
{
sensor = Variaveis.OperacaoEmAndamento.DispSen.Dados.Sensores.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
}
else if (Dispositivo == T_Code.Atu)
{
sensor = Variaveis.OperacaoEmAndamento.DispAtu.Dados.Sensores.FirstOrDefault(x => x.Componente == Sensor && x.ID.Contains(modId));
}
if (sensor != null)
{
saudeIndividual = saudeGeral.saude_individual.FirstOrDefault(x => x.id == sensor.ID_Num.ToString());
}
}
}
break;
}
}
StatusModulo status = Modulo?.Status ?? StatusModulo.Desconectado;
double saude = Modulo?.Saude ?? 0;
string erros = Modulo?.Erros ?? "desconectado";
if (saudeIndividual != null)
{
status = saudeIndividual.status;
saude = saudeIndividual.saude;
erros = string.Join(Environment.NewLine, saudeIndividual.motivos);
}
string msg =
$"Módulo: {Dispositivo}" +
$"\r\nID: {Mod_ID}" +
$"\r\nStatus: {(Modulo?.Status ?? StatusModulo.Desconectado)}" +
$"\r\nSaude: {(Modulo?.Saude ?? 0)}" +
$"\r\nStatus: {status}" +
$"\r\nSaude: {saude}" +
$"\r\nVersão: {Modulo?.Versao ?? "0"}" +
$"\r\nErro: {Modulo?.Erros}";
if (saudeIndividual != null)
{
msg =
$"Módulo: {Dispositivo}" +
$"\r\nID: {Mod_ID}" +
$"\r\nStatus: {saudeIndividual.status}" +
$"\r\nSaude: {saudeIndividual.saude}" +
$"\r\nVersão: {Modulo?.Versao ?? "0"}" +
$"\r\nErro: {string.Join(Environment.NewLine, saudeIndividual.motivos)}";
}
$"\r\nErro: {erros}";
CustomDialog.ShowDialog(
"Detalhes",
$"{msg}",
Modulo?.Status == StatusModulo.Falha ? MessageBoxIcon.Error : Modulo?.Status == StatusModulo.Operante ? MessageBoxIcon.Information : MessageBoxIcon.Exclamation,
status == StatusModulo.Falha ? MessageBoxIcon.Error : status == StatusModulo.Operante ? MessageBoxIcon.Information : MessageBoxIcon.Exclamation,
new Dictionary<(string, dynamic), Action>()
{
{ ("OK", null), () => { } },

View File

@ -41,6 +41,7 @@
this.lblDir_ET = new System.Windows.Forms.Label();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabMapa = new System.Windows.Forms.TabPage();
this.lblGPSFix = new System.Windows.Forms.Label();
this.lblGPSprecisao = new System.Windows.Forms.Label();
this.lblGPSaltitude = new System.Windows.Forms.Label();
this.lblGPSvelocidade = new System.Windows.Forms.Label();
@ -53,10 +54,7 @@
this.tabInformacoes = new System.Windows.Forms.TabPage();
this.gridDados = new System.Windows.Forms.DataGridView();
this.tabDeteccoes = new System.Windows.Forms.TabPage();
this.chbSonarAtivado = new System.Windows.Forms.CheckBox();
this.chbMostrarGrade = new System.Windows.Forms.CheckBox();
this.pnlDeteccoesRua = new System.Windows.Forms.Panel();
this.chbSonarDesvioAutomatico = new System.Windows.Forms.CheckBox();
this.tabPulverizador = new System.Windows.Forms.TabPage();
this.lblPressaoSP = new System.Windows.Forms.Label();
this.nudPressaoSP = new System.Windows.Forms.NumericUpDown();
@ -82,7 +80,6 @@
this.lblTipoMovimento = new System.Windows.Forms.Label();
this.chbPulverizador = new System.Windows.Forms.CheckBox();
this.flwCamerasSolo = new System.Windows.Forms.FlowLayoutPanel();
this.lblGPSFix = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.chartGraficos)).BeginInit();
this.tabControl1.SuspendLayout();
this.tabMapa.SuspendLayout();
@ -217,6 +214,16 @@
this.tabMapa.TabIndex = 0;
this.tabMapa.Text = "Mapa";
//
// lblGPSFix
//
this.lblGPSFix.AutoSize = true;
this.lblGPSFix.Location = new System.Drawing.Point(4, 129);
this.lblGPSFix.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.lblGPSFix.Name = "lblGPSFix";
this.lblGPSFix.Size = new System.Drawing.Size(71, 13);
this.lblGPSFix.TabIndex = 32;
this.lblGPSFix.Text = "SemCorrecao";
//
// lblGPSprecisao
//
this.lblGPSprecisao.AutoSize = true;
@ -335,10 +342,7 @@
//
// tabDeteccoes
//
this.tabDeteccoes.Controls.Add(this.chbSonarAtivado);
this.tabDeteccoes.Controls.Add(this.chbMostrarGrade);
this.tabDeteccoes.Controls.Add(this.pnlDeteccoesRua);
this.tabDeteccoes.Controls.Add(this.chbSonarDesvioAutomatico);
this.tabDeteccoes.Location = new System.Drawing.Point(4, 22);
this.tabDeteccoes.Margin = new System.Windows.Forms.Padding(2);
this.tabDeteccoes.Name = "tabDeteccoes";
@ -348,50 +352,15 @@
this.tabDeteccoes.Text = "Detecção rua";
this.tabDeteccoes.UseVisualStyleBackColor = true;
//
// chbSonarAtivado
//
this.chbSonarAtivado.AutoSize = true;
this.chbSonarAtivado.Location = new System.Drawing.Point(13, 267);
this.chbSonarAtivado.Margin = new System.Windows.Forms.Padding(2);
this.chbSonarAtivado.Name = "chbSonarAtivado";
this.chbSonarAtivado.Size = new System.Drawing.Size(93, 17);
this.chbSonarAtivado.TabIndex = 37;
this.chbSonarAtivado.Text = "Sonar Ativado";
this.chbSonarAtivado.UseVisualStyleBackColor = true;
this.chbSonarAtivado.CheckedChanged += new System.EventHandler(this.chbSonarAtivado_CheckedChanged);
//
// chbMostrarGrade
//
this.chbMostrarGrade.AutoSize = true;
this.chbMostrarGrade.Location = new System.Drawing.Point(141, 267);
this.chbMostrarGrade.Margin = new System.Windows.Forms.Padding(2);
this.chbMostrarGrade.Name = "chbMostrarGrade";
this.chbMostrarGrade.Size = new System.Drawing.Size(93, 17);
this.chbMostrarGrade.TabIndex = 36;
this.chbMostrarGrade.Text = "Mostrar Grade";
this.chbMostrarGrade.UseVisualStyleBackColor = true;
this.chbMostrarGrade.CheckedChanged += new System.EventHandler(this.chbMostrarGrade_CheckedChanged);
//
// pnlDeteccoesRua
//
this.pnlDeteccoesRua.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.pnlDeteccoesRua.Location = new System.Drawing.Point(13, 13);
this.pnlDeteccoesRua.Margin = new System.Windows.Forms.Padding(2);
this.pnlDeteccoesRua.Name = "pnlDeteccoesRua";
this.pnlDeteccoesRua.Size = new System.Drawing.Size(434, 242);
this.pnlDeteccoesRua.TabIndex = 0;
//
// chbSonarDesvioAutomatico
//
this.chbSonarDesvioAutomatico.AutoSize = true;
this.chbSonarDesvioAutomatico.Location = new System.Drawing.Point(264, 267);
this.chbSonarDesvioAutomatico.Margin = new System.Windows.Forms.Padding(2);
this.chbSonarDesvioAutomatico.Name = "chbSonarDesvioAutomatico";
this.chbSonarDesvioAutomatico.Size = new System.Drawing.Size(183, 17);
this.chbSonarDesvioAutomatico.TabIndex = 28;
this.chbSonarDesvioAutomatico.Text = "Desvio de obstáculos automático";
this.chbSonarDesvioAutomatico.UseVisualStyleBackColor = true;
this.chbSonarDesvioAutomatico.CheckedChanged += new System.EventHandler(this.chbSonarDesvioAutomatico_CheckedChanged);
//
// tabPulverizador
//
this.tabPulverizador.Controls.Add(this.lblPressaoSP);
@ -460,6 +429,7 @@
//
// pnlCameraRua
//
this.pnlCameraRua.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
this.pnlCameraRua.Location = new System.Drawing.Point(140, 23);
this.pnlCameraRua.Margin = new System.Windows.Forms.Padding(2);
this.pnlCameraRua.Name = "pnlCameraRua";
@ -667,16 +637,6 @@
this.flwCamerasSolo.Size = new System.Drawing.Size(597, 172);
this.flwCamerasSolo.TabIndex = 36;
//
// lblGpsFix
//
this.lblGPSFix.AutoSize = true;
this.lblGPSFix.Location = new System.Drawing.Point(4, 129);
this.lblGPSFix.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.lblGPSFix.Name = "lblGpsFix";
this.lblGPSFix.Size = new System.Drawing.Size(71, 13);
this.lblGPSFix.TabIndex = 32;
this.lblGPSFix.Text = "SemCorrecao";
//
// frmOperacaoManual
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -717,7 +677,6 @@
this.tabInformacoes.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.gridDados)).EndInit();
this.tabDeteccoes.ResumeLayout(false);
this.tabDeteccoes.PerformLayout();
this.tabPulverizador.ResumeLayout(false);
this.tabPulverizador.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPressaoSP)).EndInit();
@ -769,7 +728,6 @@
private System.Windows.Forms.Label lblGPSaltitude;
private System.Windows.Forms.Label lblGPSvelocidade;
private System.Windows.Forms.Label lblGPSprecisao;
private System.Windows.Forms.CheckBox chbSonarDesvioAutomatico;
private System.Windows.Forms.Label lblTensao;
private System.Windows.Forms.Label lblCorrente;
private System.Windows.Forms.Label lblRPM;
@ -782,8 +740,6 @@
private System.Windows.Forms.Label lblMov_ET;
private System.Windows.Forms.Label lblMov_DT;
private System.Windows.Forms.Label lblMov_DF;
private System.Windows.Forms.CheckBox chbSonarAtivado;
private System.Windows.Forms.CheckBox chbMostrarGrade;
private System.Windows.Forms.FlowLayoutPanel flwCamerasSolo;
private System.Windows.Forms.Label lblGPSFix;
}

View File

@ -7,12 +7,16 @@ using static AgroBase.Models.Enums;
using AgroBase.Services;
using AgroBase.Models.Modules;
using System.Threading.Tasks;
using AgroBase.Models.Operadores;
using AgroBase.Services.Operadores;
namespace AgroBase.Forms.Operacoes
{
public partial class frmOperacaoManual : Form
{
AsyncTaskTimerModel tmrLeitura;
bool ReqFrameCam = false;
bool ReqFrameSnr = false;
public frmOperacaoManual()
{
@ -31,6 +35,8 @@ namespace AgroBase.Forms.Operacoes
pnlDir_DT.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlDir_DT, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlDir_EF.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlDir_EF, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlDir_ET.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlDir_ET, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlDeteccoesRua.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlDeteccoesRua, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
pnlCameraRua.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCameraRua, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
}
private void frmOperacaoManual_Load(object sender, EventArgs e)
@ -47,15 +53,14 @@ namespace AgroBase.Forms.Operacoes
Name = "pnlCamSolo_" + Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo[i].Name,
Width = 290,
Height = 166,
BackgroundImageLayout = ImageLayout.Stretch,
BackgroundImageLayout = ImageLayout.Zoom,
BackColor = Color.Black,
};
pnlCam.GetType().GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).Invoke(pnlCam, new object[] { ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true });
flwCamerasSolo.Controls.Add(pnlCam);
}
chbPulverizador.Checked = Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico;
chbMostrarGrade.Checked = KinectService.MostrarGrade;
chbSonarAtivado.Checked = Variaveis.OperacaoEmAndamento.Controle.SonarAtivado;
InicializarComandosDirecional();
PopularInformacoesGerais();
@ -158,22 +163,43 @@ namespace AgroBase.Forms.Operacoes
lblRPM.Text = _Sensoriamento.Movimentacao.RPMMedio.ToString("0") + " rpm";
lblVelocidade.Text = _Sensoriamento.Movimentacao.VelocidadeMedia.ToString("0.00");
var Sonar = _Sensoriamento.OperadorVisual;
bool sonarAtivado = Sonar.Iniciado && Variaveis.OperacaoEmAndamento.Controle.SonarAtivado;
chbSonarDesvioAutomatico.Enabled = sonarAtivado;
chbMostrarGrade.Enabled = sonarAtivado;
if (!sonarAtivado)
{
chbSonarDesvioAutomatico.Checked = false;
chbMostrarGrade.Checked = false;
}
bool atuadorAtivado = Variaveis.OperacaoEmAndamento.DispAtu.Dados.ConexaoAtiva || true;
chbPulverizador.Enabled = atuadorAtivado;
if (!atuadorAtivado)
{
chbPulverizador.Checked = false;
}
if (!ReqFrameCam)
{
Task.Run(async () =>
{
ReqFrameCam = true;
OAKCameraFrameModel frame = await WeedWorkerService.GetCameraFrame(CameraFrameType.Rgb);
Panel pnl = FuncoesGlobais.FindControlRecursive<Panel>(flwCamerasSolo, "pnlCamSolo_" + Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo[0].Name);
pnl.BackgroundImage?.Dispose();
try { pnl.BackgroundImage = frame?.image(); } catch { }
ReqFrameCam = false;
});
}
if (!ReqFrameSnr)
{
Task.Run(async () =>
{
ReqFrameSnr = true;
OAKCameraFrameModel frame = await VisualWorkerService.GetCameraFrame(CameraFrameType.Rgb);
pnlCameraRua.BackgroundImage?.Dispose();
try { pnlCameraRua.BackgroundImage = frame?.image(); } catch { }
OAKCameraFrameModel frame2 = await VisualWorkerService.GetCameraFrame(CameraFrameType.Segmentacao);
pnlDeteccoesRua.BackgroundImage?.Dispose();
try { pnlDeteccoesRua.BackgroundImage = frame2?.image(); } catch { }
ReqFrameSnr = false;
});
}
}
@ -611,16 +637,17 @@ namespace AgroBase.Forms.Operacoes
private void chbPulverizador_CheckedChanged(object sender, EventArgs e)
{
Variaveis.OperacaoEmAndamento.Controle.PulverizadorAutomatico = ((CheckBox)sender).Checked;
HealthWorkerService.AtualizarDadosOperacao();
}
private void chbSonarAtivado_CheckedChanged(object sender, EventArgs e)
{
Variaveis.OperacaoEmAndamento.Controle.SonarAtivado = ((CheckBox)sender).Checked;
}
private void chbSonarDesvioAutomatico_CheckedChanged(object sender, EventArgs e)
{
Variaveis.OperacaoEmAndamento.Controle.SonarDesvioAutomatico = ((CheckBox)sender).Checked;
}
private void chbMostrarGrade_CheckedChanged(object sender, EventArgs e)

View File

@ -71,11 +71,6 @@ namespace AgroBase.Forms.Operacoes
txtDensidadeherbicida.Text = Variaveis.OperacaoEmAndamento.DispAtu.Dados.DensidadeHerbicida.ToString("0.00");
nudAtuarem.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Controle.PercentualInicioPulverizacao * 100);
cmbScriptErvas.SelectedIndex = cmbScriptErvas.Items.IndexOf(Variaveis.OperacaoEmAndamento.DispAtu.Dados.ScriptDeteccaoErvas.Replace(".py", ""));
chbSegmentacao.Checked = Variaveis.OperacaoEmAndamento.Controle.SegmentacaoSemantica;
chbKnt_Ativado.Checked = Variaveis.OperacaoEmAndamento.Controle.SonarAtivado;
chbKnt_Desvio.Checked = Variaveis.OperacaoEmAndamento.Controle.SonarDesvioAutomatico;
}
private void chbD_CheckedChanged(object sender, EventArgs e)
@ -143,9 +138,6 @@ namespace AgroBase.Forms.Operacoes
Variaveis.OperacaoEmAndamento.DispAtu.Dados.DensidadeHerbicida = Convert.ToDouble(txtDensidadeherbicida.Text.Replace(".", ","));
Variaveis.OperacaoEmAndamento.Controle.PercentualInicioPulverizacao = (double)(nudAtuarem.Value / 100);
Variaveis.OperacaoEmAndamento.DispAtu.Dados.ScriptDeteccaoErvas = cmbScriptErvas.Text + ".py";
Variaveis.OperacaoEmAndamento.Controle.SegmentacaoSemantica = chbSegmentacao.Checked;
Variaveis.OperacaoEmAndamento.Controle.SonarAtivado = chbKnt_Ativado.Checked;
Variaveis.OperacaoEmAndamento.Controle.SonarDesvioAutomatico = chbKnt_Desvio.Checked;
if (chbSalvar.Checked)
{

View File

@ -3,6 +3,7 @@ using AgroBase.Models.Modules;
using AgroBase.Models.Operadores;
using AgroBase.Properties;
using AgroBase.Services;
using AgroBase.Services.Operadores;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@ -23,10 +24,10 @@ namespace AgroBase.Forms.Operacoes
List<MovSensoriamentoLogModel> LogsMovimentacao = new List<MovSensoriamentoLogModel>();
List<AtuSensoriamentoLogModel> LogsAtuador = new List<AtuSensoriamentoLogModel>();
List<SensoriamentoMensagemJsonModel> LogsSensoriamento = new List<SensoriamentoMensagemJsonModel>();
//List<List<CamSoloSensoriamentoLogModel>> LogsCam_Solo = new List<List<CamSoloSensoriamentoLogModel>>();
List<List<CameraWorkerItemModel>> LogsCam_Solo = new List<List<CameraWorkerItemModel>>();
List<string> pathImagensSolo = new List<string>();
List<PictureBox> picsCamSolo = new List<PictureBox>();
//List<CamCaminhoSensoriamentoLogModel> LogsCam_Caminho = new List<CamCaminhoSensoriamentoLogModel>();
List<CameraWorkerItemModel> LogsCam_Caminho = new List<CameraWorkerItemModel>();
string pathImagensCaminho = "";
DateTime MomentoAtual = DateTime.Now;
@ -126,26 +127,27 @@ namespace AgroBase.Forms.Operacoes
LogsMovimentacao = JsonConvert.DeserializeObject<MovSensoriamentoLogModel[]>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, data.mov ?? Enums.T_Code.Mov.ToString())).ToList();
LogsAtuador = JsonConvert.DeserializeObject<AtuSensoriamentoLogModel[]>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, data.atu ?? Enums.T_Code.Atu.ToString())).ToList();
LogsSensoriamento = JsonConvert.DeserializeObject<SensoriamentoMensagemJsonModel[]>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, data.sen ?? Enums.T_Code.Sen.ToString())).ToList();
pathImagensCaminho = ofd.FileName.Replace("data.lgop", data.cam_caminho + "/");
pathImagensCaminho = ofd.FileName.Replace("data.lgop", data.cam_caminho + "\\");
LogsCam_Caminho = JsonConvert.DeserializeObject<List<CameraWorkerItemModel>>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, data.cam_caminho ?? Enums.T_Code.Snr.ToString())).ToList();
//LogsCam_Solo = new List<List<CamSoloSensoriamentoLogModel>>();
pathImagensSolo = new List<string>();
picsCamSolo = new List<PictureBox>();
flwCameras.Controls.Clear();
/*foreach (string cam in data.cam_solo)
foreach (string cam in data.cam_solo)
{
LogsCam_Solo.Add(JsonConvert.DeserializeObject<CamSoloSensoriamentoLogModel[]>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, cam)).ToList());
pathImagensSolo.Add(ofd.FileName.Replace("data.lgop", cam + "/"));
var log = JsonConvert.DeserializeObject<List<CameraWorkerItemModel>>(OperacaoModel.DeserializarDadosOperacao(ofd.FileName, cam)).ToList();
LogsCam_Solo.Add(log);
pathImagensSolo.Add(ofd.FileName.Replace("data.lgop", cam + "\\"));
PictureBox pic = new PictureBox()
{
Name = "picCamSolo_" + cam,
Width = 250,
Height = 166,
SizeMode = PictureBoxSizeMode.StretchImage
SizeMode = PictureBoxSizeMode.Zoom
};
flwCameras.Controls.Add(pic);
picsCamSolo.Add(pic);
}*/
}
Mapa = new MapasModel()
{
@ -770,7 +772,7 @@ namespace AgroBase.Forms.Operacoes
Titulo = "Ervas Identificadas"
};
/*List<GraficoInterativoSerieModel> seriesCamerasSolo = new List<GraficoInterativoSerieModel>();
List<GraficoInterativoSerieModel> seriesCamerasSolo = new List<GraficoInterativoSerieModel>();
foreach (var camSolo in LogsCam_Solo)
{
string camNome = "Solo " + (LogsCam_Solo.IndexOf(camSolo) + 1);
@ -779,34 +781,20 @@ namespace AgroBase.Forms.Operacoes
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} RAM %",
Valores = camSolo.Select(x => (double)(x?.Leitura?.device_data?.Memory_Usage?.Percent ?? 0)).ToList(),
Valores = camSolo.Select(x => (double)(x?.performance?.memoria_usada ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
},
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} CPU Temp",
Valores = camSolo.Select(x => (double)(x?.Leitura?.device_data?.Temperature?.css ?? 0)).ToList(),
Valores = camSolo.Select(x => (double)(x?.performance?.temperatura ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
},
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} RAM Temp",
Valores = camSolo.Select(x => (double)(x?.Leitura?.device_data?.Temperature?.mss ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
},
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} VCC Temp",
Valores = camSolo.Select(x => (double)(x?.Leitura?.device_data?.Temperature?.upa ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
}
});
}
if (LogsCam_Caminho.Any(x => x.Leitura.device_data != null))
if (LogsCam_Caminho.Any(x => x.performance != null))
{
var camCaminho = LogsCam_Caminho;
string camNome = "Caminho";
@ -815,34 +803,20 @@ namespace AgroBase.Forms.Operacoes
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} RAM %",
Valores = camCaminho.Select(x => (double)(x?.Leitura?.device_data?.Memory_Usage?.Percent ?? 0)).ToList(),
Valores = camCaminho.Select(x => (double)(x?.performance?.memoria_usada ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
},
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} CPU Temp",
Valores = camCaminho.Select(x => (double)(x?.Leitura?.device_data?.Temperature?.css ?? 0)).ToList(),
Valores = camCaminho.Select(x => (double)(x?.performance?.temperatura ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
},
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} RAM Temp",
Valores = camCaminho.Select(x => (double)(x?.Leitura?.device_data?.Temperature?.mss ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
},
new GraficoInterativoSerieModel()
{
Titulo = $"{camNome} VCC Temp",
Valores = camCaminho.Select(x => (double)(x?.Leitura?.device_data?.Temperature?.upa ?? 0)).ToList(),
Visivel = true,
MostrarValor = true
}
});
}
graficoCameras = new GraficoInterativoModel(chartCameras, Momentos, seriesCamerasSolo);*/
graficoCameras = new GraficoInterativoModel(chartCameras, Momentos, seriesCamerasSolo);
}
@ -853,7 +827,7 @@ namespace AgroBase.Forms.Operacoes
CarregarInformacoesBusca(gpbMOV_Geral_Filtro, graficoMovGeral.Series.Select(x => x.Titulo).ToArray());
CarregarInformacoesBusca(gpbSEN_Filtro, graficoSen.Series.Select(x => x.Titulo).ToArray());
CarregarInformacoesBusca(gpbCpu_Filtro, graficoCpu.Series.Select(x => x.Titulo).ToArray());
//CarregarInformacoesBusca(gpbCameras_Filtro, graficoCameras.Series.Select(x => x.Titulo).ToArray());
CarregarInformacoesBusca(gpbCameras_Filtro, graficoCameras.Series.Select(x => x.Titulo).ToArray());
}
private void CarregarInformacoesBusca(GroupBox gpb, string[] Componentes)
@ -1001,7 +975,7 @@ namespace AgroBase.Forms.Operacoes
return blackFrame;
}
private Bitmap DesenharDeteccoesErvas(CameraCoordenadasFrameModel frame, Bitmap bitmapOriginal)
private Bitmap DesenharDeteccoesErvas(WeedWorkerAnaliseModel frame, Bitmap bitmapOriginal)
{
// Criar um novo bitmap com base no original para desenhar por cima
Bitmap bitmapComObjetos = new Bitmap(bitmapOriginal);
@ -1010,23 +984,23 @@ namespace AgroBase.Forms.Operacoes
using (Graphics g = Graphics.FromImage(bitmapComObjetos))
{
// Proporção de escala
double scaleX = (double)bitmapComObjetos.Width / frame.x_max;
double scaleY = (double)bitmapComObjetos.Height / frame.y_max;
double scaleX = (double)bitmapComObjetos.Width / frame.frame_width;
double scaleY = (double)bitmapComObjetos.Height / frame.frame_height;
// Iterar sobre os objetos detectados
foreach (var objeto in frame.objetos)
foreach (var objeto in frame.deteccoes)
{
// Ajustar coordenadas e tamanho de acordo com a escala
int xAtual = (int)(objeto.x * scaleX);
int yAtual = (int)(objeto.y * scaleY);
int larguraAtual = (int)(objeto.largura * scaleX);
int alturaAtual = (int)(objeto.altura * scaleY);
int xAtual = (int)(objeto.bbox[0] * scaleX);
int yAtual = (int)(objeto.bbox[1] * scaleY);
int larguraAtual = (int)(objeto.bbox[2] * scaleX);
int alturaAtual = (int)(objeto.bbox[3] * scaleY);
// Desenhar o retângulo ao redor do objeto
g.DrawRectangle(new Pen(Color.Red, 2), xAtual, yAtual, larguraAtual, alturaAtual);
// Desenhar a descrição do objeto (id: descricao)
string descricao = $"{objeto.id}: {objeto.descricao}";
string descricao = $"{objeto.descricao} | {objeto.confianca.ToString("0.00")} | ({objeto.id})";
g.DrawString(descricao, new Font("Arial", 20), Brushes.White, new PointF(xAtual, yAtual - 15));
}
}
@ -1115,18 +1089,7 @@ namespace AgroBase.Forms.Operacoes
pnlOrientacaoCaminho.Invalidate();
pnlOrientacaoDif.Invalidate();
//OperacaoModel.PopularTreeView(tvwFalhas, Log.CodigoFalha);
TreeNode noModulos = new TreeNode("Status Módulos");
tvwFalhas.Nodes.Add(noModulos);
noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.Atu, LogsAtuador[idxMomentoAtual].Inicializado, LogsAtuador[idxMomentoAtual].UltimoComandoRespondido));
noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.Sen, LogsSensoriamento[idxMomentoAtual].Conectado, LogsSensoriamento[idxMomentoAtual].UltimoComandoRespondido));
noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.Mov, LogsMovimentacao[idxMomentoAtual].Inicializado, LogsMovimentacao[idxMomentoAtual].UltimoComandoRespondido));
noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.Dir, LogsDirecional[idxMomentoAtual].Inicializado, LogsDirecional[idxMomentoAtual].UltimoComandoRespondido));
//noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.A05, LogsA05[idxMomentoAtual].Conectado, LogsA05[idxMomentoAtual].UltimoComandoRespondido));
noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.Lra, LogsOperacao[idxMomentoAtual].DadosLoRa.Conectado, LogsOperacao[idxMomentoAtual].DadosLoRa.UltimoComandoRespondido));
noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.Gps, LogsOperacao[idxMomentoAtual].Gps.Inicializado, LogsOperacao[idxMomentoAtual].Gps.UltimoComandoRespondido));
//noModulos.Nodes.Add(AtualizarTextoStatusModulo(Enums.T_Code.Knt, LogsCam_Caminho[idxMomentoAtual].Inicializado, LogsCam_Caminho[idxMomentoAtual].UltimaMensagemRecebida));
OperacaoModel.PopularTreeView(tvwFalhas, Log.ModulosSaude);
tvwFalhas.ExpandAll();
}
@ -1135,15 +1098,15 @@ namespace AgroBase.Forms.Operacoes
picCameraCaminho.Image = CarregarImagemCamera(pathImagensCaminho, "_rgb");
AtualizarInformacoesCameraCaminho();
/*for (int i = 0; i < LogsCam_Solo.Count(); i++)
for (int i = 0; i < LogsOperacao[idxMomentoAtual].Atuador.QtdCamerasSolo; i++)
{
Bitmap bitmapSolo = CarregarImagemCamera(pathImagensSolo[i]);
Bitmap bitmapSolo = CarregarImagemCamera(pathImagensSolo[i], "_rgb");
if (chbDesenharErvas.Checked)
{
var LogCamSolo = LogsCam_Solo[i].FirstOrDefault(x => x.Momento == MomentoAtual);
var LogCamSolo = LogsOperacao[idxMomentoAtual].OperadorErvas;
if (LogCamSolo != null)
{
bitmapSolo = DesenharDeteccoesErvas(LogCamSolo.Leitura, bitmapSolo);
bitmapSolo = DesenharDeteccoesErvas(LogCamSolo.Analise, bitmapSolo);
picsCamSolo[i].Image = bitmapSolo;
}
}
@ -1151,10 +1114,10 @@ namespace AgroBase.Forms.Operacoes
{
picsCamSolo[i].Image = bitmapSolo;
}
}*/
}
//graficoCameras.AtualizarDados(idxMomentoAtual);
graficoCameras.AtualizarDados(idxMomentoAtual);
if (cmbCameras_Componente.SelectedIndex > -1)
{

View File

@ -15,7 +15,6 @@ namespace AgroBase.Forms
private void frmKinect_Load(object sender, EventArgs e)
{
KinectService.InicializarKinect(gridDados, picRGB, picProfundidade, trackBarAngle);
chbAtivado.Checked = Variaveis.OperacaoEmAndamento.Controle.SonarAtivado;
chbGrade.Checked = KinectService.MostrarGrade;
chbTexto.Checked = KinectService.MostrarTexto;
}
@ -37,7 +36,7 @@ namespace AgroBase.Forms
private void chbAtivado_CheckedChanged(object sender, EventArgs e)
{
Variaveis.OperacaoEmAndamento.Controle.SonarAtivado = ((CheckBox)sender).Checked;
}
private void frmKinect_FormClosing(object sender, FormClosingEventArgs e)

View File

@ -457,7 +457,7 @@ namespace AgroBase.Forms
private void chbSonarVirando_CheckedChanged(object sender, EventArgs e)
{
Variaveis.OperacaoEmAndamento.Controle.SonarAtivado = ((CheckBox)sender).Checked;
}
private void chbAutomatico_CheckedChanged(object sender, EventArgs e)

View File

@ -9,7 +9,6 @@ using System.Threading.Tasks;
using AgroBase.Models.Modules;
using SharpDX.DirectInput;
using AgroBase.Services;
using AgroBase.Forms.IHM;
using System.Data;
namespace AgroBase

View File

@ -17,6 +17,13 @@ namespace AgroBase.Models.Modules
public byte _EnderecoCAN_Tx { get; set; } = 0x13;
public byte _EnderecoCAN_Rx { get; set; } = 0x14;
public int _TaxaAmostragem { get; set; } = 1000;
public double FrequenciaBase
{
get
{
return 1.0 / (_TaxaAmostragem / 1000.0);
}
}
public bool RequisitarDados { get; set; } = true;
public static int PingsConsiderarConexao { get; set; } = 5;
public static int TempoLimiteConexao
@ -26,6 +33,13 @@ namespace AgroBase.Models.Modules
return PingsConsiderarConexao * (Variaveis.OperacaoEmAndamento?.DispSen?._TaxaAmostragem ?? 1000);
}
}
public bool Conectado
{
get
{
return DadosLeitura.UltimoComandoRespondido.AddMilliseconds(PingsConsiderarConexao * _TaxaAmostragem) > DateTime.Now;
}
}
public bool ConexaoAtiva
{
get
@ -513,13 +527,13 @@ namespace AgroBase.Models.Modules
bool Respondido() => Variaveis.OperacaoEmAndamento.DispAtu.Dados.DadosLeitura.UltimoComandoRespondido > Inicio;
await FuncoesGlobais.AguardarCondicaoAsync(Respondido, 500, 50);
if (ConexaoAtiva)
if (Conectado)
{
DefinirDispositivo();
Variaveis.OperacaoEmAndamento.DispAtu?.EnviarProtocolosConfiguracao();
}
return ConexaoAtiva;
return Conectado;
}
private void DefinirDispositivo()
@ -572,20 +586,18 @@ namespace AgroBase.Models.Modules
private List<(int, CanMessagePosicaoDados, byte[])> ModConfig(bool Conectar)
{
var config1 = new List<byte>
var config = new List<byte>
{
(byte)(Conectar ? 1 : 0),
(byte)(_TaxaAmostragem / 10),
(byte)(RequisitarDados ? 1 : 0),
};
var config2 = new List<byte>();
config2.AddRange(PinoutModel.PinoProtocolo(Pinout, Funcoes, false));
config.AddRange(PinoutModel.PinoProtocolo(Pinout, Funcoes, false));
return new List<(int, CanMessagePosicaoDados, byte[])>
{
(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Config1, config1.ToArray()),
(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Config2, config2.ToArray()),
(Variaveis.ID_Num_sMOD, CanMessagePosicaoDados.Config1, config.ToArray()),
};
}
@ -1243,7 +1255,7 @@ namespace AgroBase.Models.Modules
return sensor?.Componente ?? bico?.Componente ?? bomba?.Componente ?? S_Code.sVZO;
}
private void DefinirOuCriar(int CompID_Num, CanMessagePosicaoDados Posicao, S_Code componente, List<dynamic> Parametros)
private void AtualizarDados(int CompID_Num, CanMessagePosicaoDados Posicao, S_Code componente, List<dynamic> Parametros)
{
var Dados = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
@ -1259,10 +1271,36 @@ namespace AgroBase.Models.Modules
for (int i = 0; i < valoresLeituras.Where(x => x.posicao == Posicao).Count(); i++)
{
var valor = valoresLeituras.FirstOrDefault(x => x.indice == i);
try
{
var valor = valoresLeituras.FirstOrDefault(x => x.posicao == Posicao && x.indice == i);
if (valor != null)
{
valor.atual.valor = Parametros.Count > i ? (Parametros[i] + valor.offset) : -1;
var v = Parametros.Count > i ? (Parametros[i]) : -1;
if (v is sbyte || v is byte || v is short || v is ushort || v is int || v is uint || v is long || v is ulong || v is float || v is double || v is decimal)
{
v += valor.offset;
valor.atual.valor = v;
}
else
{
valor.atual.valor = v;
}
if (Posicao == CanMessagePosicaoDados.Status)
{
if (sensor != null)
sensor.Inicializado = v;
if (bomba != null)
bomba.Inicializado = v;
if (bico != null)
bico.Inicializado = v;
}
}
}
catch (Exception ex)
{
}
}
}
@ -1273,10 +1311,10 @@ namespace AgroBase.Models.Modules
byte ID_Num = mensagem.DataRx[1];
var data = mensagem.DataRx;
var Dados = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
S_Code componente = DetectarComponenteDoID_Num(ID_Num);
var Dados = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
Console.WriteLine($"[ATU] Componente={componente.ToString()}, ID_Num={ID_Num}, Data={FuncoesGlobais.ConverterComandoBytesParaTexto(data)}");
switch (componente)
@ -1319,10 +1357,16 @@ namespace AgroBase.Models.Modules
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
Estado estado = (Estado)data[2];
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { estado });
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { estado });
break;
}
}
@ -1332,10 +1376,16 @@ namespace AgroBase.Models.Modules
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
double vazao = ConverterByteParaDouble(data, 2);
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { vazao });
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { vazao });
break;
}
}
@ -1345,10 +1395,16 @@ namespace AgroBase.Models.Modules
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
double massa = ConverterByteParaDouble(data, 2);
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { massa });
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { massa });
break;
}
}
@ -1358,10 +1414,16 @@ namespace AgroBase.Models.Modules
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
double pressao = ConverterByteParaDouble(data, 2);
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { pressao });
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { pressao });
break;
}
}
@ -1371,13 +1433,19 @@ namespace AgroBase.Models.Modules
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
Estado estado = (Estado)data[2];
int percentualPotencia = data[3];
int pressaoSp = data[4];
int pressaoAtual = data[5];
DefinirOuCriar(ID_Num, posicao, componente, new List<dynamic>() { estado, percentualPotencia, pressaoSp, pressaoAtual });
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { estado, percentualPotencia, pressaoSp, pressaoAtual });
break;
}
}

View File

@ -16,7 +16,6 @@ using System.Text;
using static AgroBase.Services.OIDCanService.OidHandler;
using AgroBase.Models.Operadores;
using AgroBase.Services.Operadores;
using AgroBase.Forms;
namespace AgroBase.Models
{
@ -230,11 +229,9 @@ namespace AgroBase.Models
PercentualVelocidadeSP = 0,
TiposControle = Variaveis.OperacaoEmAndamento.Controle.TiposControle.ToList(),
SonarAtivado = Parametros.SonarAtivado,
SegmentacaoSemantica = Parametros.Modo == ModoOperacao.MapaGPS,
TipoControleDirecional = Parametros.DirTipoMovimento,
PulverizadorAutomatico = Parametros.Modo == ModoOperacao.MapaGPS,
TipoMovimento = TipoMovimentoDirecional.RodasDianteiras,
SonarDesvioAutomatico = false,
};
Variaveis.OperacaoEmAndamento.Descricao = Parametros.Descricao;
@ -336,8 +333,6 @@ namespace AgroBase.Models
},
},
SonarAtivado = false,
SonarDesvioAutomatico = false,
SegmentacaoSemantica = false,
PulverizadorAutomatico = false,
TipoMovimento = TipoMovimentoDirecional.RodasDianteiras,
TipoControleDirecional = TiposControladorDirecional.Manual
@ -408,14 +403,12 @@ namespace AgroBase.Models
new OperacaoControleTipoModel()
{
Tipo = T_Code.Atu,
DelayEnvioComando = 500,
DelayEnvioComando = 200,
Comandos = new List<string>(),
UltimoComando = DateTime.Now
},
},
SonarAtivado = false,
SonarDesvioAutomatico = false,
SegmentacaoSemantica = false,
SonarAtivado = true,
PulverizadorAutomatico = true,
TipoMovimento = TipoMovimentoDirecional.RodasDianteiras,
TipoControleDirecional = TiposControladorDirecional.MPC,
@ -514,10 +507,8 @@ namespace AgroBase.Models
UltimoComando = DateTime.Now
},
},
SonarAtivado = true,
SonarDesvioAutomatico = true,
SegmentacaoSemantica = true,
PulverizadorAutomatico = true,
SonarAtivado = false,
PulverizadorAutomatico = false,
TipoMovimento = TipoMovimentoDirecional.RodasDianteiras,
TipoControleDirecional = TiposControladorDirecional.IA,
};
@ -649,6 +640,7 @@ namespace AgroBase.Models
GPSTrajetoria = new List<GPSModel>();
Controle.BicosAtuados = DispAtu.Dados.BicosPulverizadores.Select(x => x.Clone()).ToList();
ControleAnterior.BicosAtuados = DispAtu.Dados.BicosPulverizadores.Select(x => x.Clone()).ToList();
await RealizarCalibragemInicialAsync();
@ -754,6 +746,9 @@ namespace AgroBase.Models
Controle.PercentualVelocidadeSP = 0;
GPSTrajetoria = new List<GPSModel>();
Controle.BicosAtuados = DispAtu.Dados.BicosPulverizadores.Select(x => x.Clone()).ToList();
ControleAnterior.BicosAtuados = DispAtu.Dados.BicosPulverizadores.Select(x => x.Clone()).ToList();
}
public void ReiniciarSimulacao()
@ -1161,6 +1156,7 @@ namespace AgroBase.Models
};
SalvarLog(T_Code.Sen.ToString(), logSen, false);
SalvarLogCameraSolo();
SalvarLogCameraCaminho();
string ArquivoOp = Variaveis.CaminhoOperacoes + Variaveis.OperacaoEmAndamento.ID + "/data.lgop";
@ -1175,7 +1171,7 @@ namespace AgroBase.Models
atu = T_Code.Atu.ToString(),
sen = T_Code.Sen.ToString(),
cam_caminho = T_Code.Snr.ToString(),
cam_solo = Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo.Select(x => x.Name).ToList(),
cam_solo = Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo.Select((x, i) => x.Dispositivo.ToString() + i).ToList(),
};
File.WriteAllText(ArquivoOp, JsonConvert.SerializeObject(data));
}
@ -1217,6 +1213,27 @@ namespace AgroBase.Models
}
}
private void SalvarLogCameraSolo()
{
foreach (var Camera in Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo)
{
string camera_name = Camera.Dispositivo.ToString() + Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo.IndexOf(Camera);
string Caminho = Variaveis.CaminhoOperacoes + Variaveis.OperacaoEmAndamento.ID + "/" + camera_name;
if (!Directory.Exists(Caminho))
{
Directory.CreateDirectory(Caminho);
}
string nome = Variaveis.OperacaoEmAndamento.idxLog.ToString();
Camera.SaveFrames(new List<CameraFrameType>() { CameraFrameType.Rgb }, nome, Caminho);
var cam_data = JsonConvert.DeserializeObject<Dictionary<string, object>>(RedisService.Get(CtxKey.DadosCameras));
if (cam_data.ContainsKey(Camera.Id))
SalvarLog(camera_name, cam_data[Camera.Id], false);
}
}
private void SalvarLogCameraCaminho()
{
var Camera = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho;
@ -1230,6 +1247,10 @@ namespace AgroBase.Models
string nome = Variaveis.OperacaoEmAndamento.idxLog.ToString();
Camera.SaveFrames(new List<CameraFrameType>() { CameraFrameType.Rgb, CameraFrameType.Heatmap, CameraFrameType.RadarTopDown, CameraFrameType.Segmentacao }, nome, Caminho);
var cam_data = JsonConvert.DeserializeObject<Dictionary<string, object>>(RedisService.Get(CtxKey.DadosCameras));
if (cam_data.ContainsKey(Camera.Id))
SalvarLog(Camera.Dispositivo.ToString(), cam_data[Camera.Id], false);
}
@ -1429,11 +1450,8 @@ namespace AgroBase.Models
public double PressaoLinha { get; set; } = 85;
public List<OperacaoControleTipoModel> TiposControle { get; set; } = new List<OperacaoControleTipoModel>();
public bool PulverizadorAutomatico { get; set; } = true;
public bool SegmentacaoSemantica { get; set; } = false;
public bool SonarAtivado { get; set; } = false;
public bool SonarDesvioAutomatico { get; set; } = false;
public bool SonarAtivado { get; set; } = true;
public bool PulverizadorAutomatico { get; set; } = false;
public TiposControladorDirecional TipoControleDirecional { get; set; } = TiposControladorDirecional.PID;
public List<MPCSimulacaoModel> SimulacaoMPC { get; set; } = new List<MPCSimulacaoModel>();
@ -1451,18 +1469,16 @@ namespace AgroBase.Models
PercentualVelocidadeSP = PercentualVelocidadeSP,
_tipoMovimento = _tipoMovimento,
PressaoLinha = PressaoLinha,
PulverizadorAutomatico = PulverizadorAutomatico,
RPM_Max = RPM_Max,
RPM_Min = RPM_Min,
SegmentacaoSemantica = SegmentacaoSemantica,
SonarAtivado = SonarAtivado,
SonarDesvioAutomatico = SonarDesvioAutomatico,
TempoAtuacao = TempoAtuacao,
TipoControleDirecional = TipoControleDirecional,
TipoMovimento = TipoMovimento,
TiposControle = new List<OperacaoControleTipoModel>(TiposControle),
VelocidadeMP = VelocidadeMP,
SimulacaoMPC = new List<MPCSimulacaoModel>(SimulacaoMPC),
PulverizadorAutomatico = PulverizadorAutomatico
};
}
}
@ -1589,6 +1605,8 @@ namespace AgroBase.Models
public PerformanceModel DadosPerformance { get; set; } = new PerformanceModel();
public OperacaoControleModel Controle { get; set; }
public VisualWorkerModel OperadorVisual { get; set; }
public WeedWorkerModel OperadorErvas { get; set; }
public List<ManagerWorkerMessageResponseModulosPendentesModel> ModulosSaude { get; set; }
@ -1596,6 +1614,7 @@ namespace AgroBase.Models
{
Variaveis.OperacaoEmAndamento.AtualizarDadosContexto();
VisualWorkerService.AtualizarAnalise();
WeedWorkerService.AtualizarAnalise();
var _Trajetoria = Variaveis.OperacaoEmAndamento.Trajetoria;
var _DispMvd = Variaveis.OperacaoEmAndamento.DispMvd;
@ -1625,11 +1644,12 @@ namespace AgroBase.Models
var dadosAtuador = _DispAtu != null ? new OperacaoSensoriamentoLogAtuModel()
{
QtdCamerasSolo = _DispSen.Dados.CamerasSolo.Count,
HerbicidaConsumido = _DispAtu.Dados.VolumeVazaoML,
PercentualErvasTerreno = _DispAtu.Dados.PercentualErvasTerreno,
HerbicidaPorErva = HerbicidaPorErva,
ErvasNoRadar = 0,
ErvasIdentificadas = new List<Dictionary<string, int>>(),
ErvasNoRadar = WeedWorkerService.DadosLeitura?.Analise?.deteccoes?.Count ?? 0,
ErvasIdentificadas = WeedWorkerService.DadosLeitura?.Analise?.ervas_identificadas ?? new List<Dictionary<string, int>>(),
PercentualReservatorio = FuncoesMatematicas.Clamp(_DispAtu.Dados.PercentualReservatorio, 0, 100),
VolumeReservatorio = _DispAtu.Dados.VolumeReservatorio,
PressaoLinha = _DispAtu.Dados.PressaoLinha,
@ -1722,9 +1742,11 @@ namespace AgroBase.Models
Trajetoria = dadosTrajetoria,
Gps = dadosGps,
OperadorVisual = VisualWorkerService.DadosLeitura.Clone(),
OperadorErvas = WeedWorkerService.DadosLeitura.Clone(),
Controle = dadosControle,
DadosPerformance = dadosPerformance,
DadosLoRa = dadosLora
DadosLoRa = dadosLora,
ModulosSaude = HealthWorkerService.ModulosSaude.ToList(),
};
Variaveis.OperacaoEmAndamento.Sensoriamento = dadosAtualizados;
@ -1733,6 +1755,11 @@ namespace AgroBase.Models
public OperacaoSensoriamentoLogModel Clone(bool comSonar = false)
{
var vw = OperadorVisual?.Clone();
vw.CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
var ww = OperadorErvas?.Clone();
ww.CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
return new OperacaoSensoriamentoLogModel()
{
Momento = Momento,
@ -1747,13 +1774,16 @@ namespace AgroBase.Models
Bateria = Bateria?.Clone(),
Trajetoria = Trajetoria?.Clone(),
Gps = Gps?.Clone(),
OperadorVisual = comSonar ? OperadorVisual?.Clone() : null,
OperadorVisual = vw,
OperadorErvas = ww,
Controle = Controle?.Clone(),
DadosPerformance = DadosPerformance?.Clone(),
IMU = IMU?.Clone(),
DadosLoRa = DadosLoRa?.Clone(),
ModulosSaude = new List<ManagerWorkerMessageResponseModulosPendentesModel>(ModulosSaude),
};
}
}
public class OperacaoSensoriamentoLogImuModel
@ -1785,7 +1815,8 @@ namespace AgroBase.Models
public class OperacaoSensoriamentoLogAtuModel
{
public double HerbicidaConsumido { get; set;}
public int QtdCamerasSolo { get; set; }
public double HerbicidaConsumido { get; set; }
public double PercentualErvasTerreno { get; set; }
public double HerbicidaPorErva { get; set; }
public int ErvasNoRadar { get; set; }
@ -1814,6 +1845,7 @@ namespace AgroBase.Models
{
return new OperacaoSensoriamentoLogAtuModel()
{
QtdCamerasSolo = QtdCamerasSolo,
ErvasIdentificadas = new List<Dictionary<string, int>>(ErvasIdentificadas),
ErvasNoRadar = ErvasNoRadar,
HerbicidaConsumido = HerbicidaConsumido,

View File

@ -39,6 +39,9 @@ namespace AgroBase.Models.Operadores
public string versao { get; set; }
public string modelo { get; set; }
public bool iniciado { get; set; }
public bool rodando { get; set; }
public bool tem_depth { get; set; }
public bool tem_imu { get; set; }
public SaudeWorkerModel saude { get; set; }
public CameraWorkerItemPerformanceModel performance { get; set; }
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace AgroBase.Models.Operadores
{
@ -11,6 +12,7 @@ namespace AgroBase.Models.Operadores
public DateTime ProntoEm { get; set; }
public DateTime UltimaMensagem { get; set; }
public Dictionary<CameraFrameType, OAKCameraFrameModel> CameraFrames { get; set; } = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
public WeedWorkerAnaliseModel Analise { get; set; } = new WeedWorkerAnaliseModel();
public WeedWorkerModel Clone()
@ -22,6 +24,7 @@ namespace AgroBase.Models.Operadores
Pronto = Pronto,
ProntoEm = ProntoEm,
CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>(CameraFrames ?? new Dictionary<CameraFrameType, OAKCameraFrameModel>()),
Analise = Analise.Clone()
};
}
@ -35,6 +38,40 @@ namespace AgroBase.Models.Operadores
}
}
public class WeedWorkerAnaliseModel
{
public DateTime timestamp { get; set; }
public int frame_width { get; set; }
public int frame_height { get; set; }
public List<WeedWorkerAnaliseDeteccaoModel> deteccoes { get; set; }
public Dictionary<int, bool> controle { get; set; }
public List<Dictionary<string, int>> ervas_identificadas { get; set; }
public WeedWorkerAnaliseModel Clone()
{
return new WeedWorkerAnaliseModel()
{
timestamp = timestamp,
deteccoes = new List<WeedWorkerAnaliseDeteccaoModel>(deteccoes),
controle = new Dictionary<int, bool>(controle),
ervas_identificadas = ervas_identificadas?.Select(dict => new Dictionary<string, int>(dict)).ToList()
};
}
}
public class WeedWorkerAnaliseDeteccaoModel
{
public int id { get; set; }
public double[] centro { get; set; }
public double[] bbox { get; set; }
public int class_id { get; set; }
public int ultimo_frame { get; set; }
public int frames_detectada { get; set; }
public string status { get; set; }
public string descricao { get; set; }
public double confianca { get; set; }
}
public enum WeedWorkerCommandType
{
ScriptCarregado = 1,

View File

@ -154,8 +154,8 @@ namespace AgroBase.Services.Operadores
("distancia_entre_eixos", VariaveisEquipamento.DistanciaEntreEixos / 100.0),
("percentual_reservatorio_min", VariaveisEquipamento.PercentualReservatorioMin),
("percentual_tensao_bateria_min", VariaveisEquipamento.PercentualTensaoBateriaMin),
("camera_caminho_id", Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.Id),
("camera_solo_id", Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo.FirstOrDefault()?.Id ?? "")
("camera_caminho_id", Variaveis.OperacaoEmAndamento.DispSen?.Dados?.CameraCaminho?.Id ?? ""),
("camera_solo_id", Variaveis.OperacaoEmAndamento.DispSen?.Dados?.CamerasSolo?.FirstOrDefault()?.Id ?? "")
);
}
@ -213,16 +213,20 @@ namespace AgroBase.Services.Operadores
),
("Atu", new
{
qtd_bicos = Variaveis.OperacaoEmAndamento.DispAtu.Dados.QuantidadeBicos,
percent_vertical_deteccao = _Controle.PercentualInicioPulverizacao,
tempo_atuacao = _Controle.TempoAtuacao,
capacidade_reservatorio = Variaveis.OperacaoEmAndamento.CapacidadeReservatorio,
pressao_linha = _Controle.PressaoLinha,
pulverizador_automatico = _Controle.PulverizadorAutomatico,
}
),
("Snr", new
{
percentual_altura_solo = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.PercentualAlturaSolo,
distancia_maxima = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.DistanciaMaximaVisao,
distancia_minima = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.DistanciaMinimaVisao
distancia_minima = Variaveis.OperacaoEmAndamento.DispSen.Dados.CameraCaminho.DistanciaMinimaVisao,
sonar_ativado = _Controle.SonarAtivado,
}
)
);
@ -403,6 +407,130 @@ namespace AgroBase.Services.Operadores
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Sen), servosAtualizados.ToArray());
var DadosAtu = Variaveis.OperacaoEmAndamento.DispAtu.Dados;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu),
("timestamp", agora),
("conectado", DadosAtu.Conectado),
("freq_base", DadosAtu.FrequenciaBase)
);
var atuSensoresAtualizados = new List<(string caminho, object valor)>();
foreach (var sensor in DadosAtu.Sensores)
{
int tipo = (int)sensor.Componente;
int id = sensor.ID_Num;
string basePath = $"sensores.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Sen), $"{basePath}.saude");
var dados = sensor.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
nominal = y.nominal,
maximo = y.maximo,
minimo = y.minimo,
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var sensorObj = new
{
conectado = sensor.Inicializado,
id,
label = sensor.ID,
tipo,
aferir = sensor.Aferir,
mandatorio = sensor.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
atuSensoresAtualizados.Add(($"{basePath}", sensorObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), atuSensoresAtualizados.ToArray());
var bicosAtualizados = new List<(string caminho, object valor)>();
foreach (var bico in DadosAtu.BicosPulverizadores)
{
int tipo = (int)bico.Componente;
int id = bico.ID_Num;
string basePath = $"bicos.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Sen), $"{basePath}.saude");
var dados = bico.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
nominal = y.nominal,
maximo = y.maximo,
minimo = y.minimo,
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var sensorObj = new
{
conectado = bico.Inicializado,
id,
label = bico.ID,
tipo,
comandar = bico.Comandar,
mandatorio = bico.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
bicosAtualizados.Add(($"{basePath}", sensorObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), bicosAtualizados.ToArray());
var bombasAtualizados = new List<(string caminho, object valor)>();
foreach (var bomba in DadosAtu.BombasPressurizadoras)
{
int tipo = (int)bomba.Componente;
int id = bomba.ID_Num;
string basePath = $"bombas.{tipo}.{id}";
var saude = RedisService.GetField<object>(RedisService.ModKey(Enums.T_Code.Sen), $"{basePath}.saude");
var dados = bomba.ValoresLeituras
.Where(y => y.analise_health)
.Select(y => new
{
label = y.funcao.ToString(),
nominal = y.nominal,
maximo = y.maximo,
minimo = y.minimo,
atual = y.atual.valor,
freq = y.atual.frequencia
})
.ToList();
var sensorObj = new
{
conectado = bomba.Inicializado,
id,
label = bomba.ID,
tipo,
comandar = bomba.Comandar,
mandatorio = bomba.Mandatorio,
dados,
timestamp = agora,
saude = saude ?? new { }
};
bombasAtualizados.Add(($"{basePath}", sensorObj));
}
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Atu), bombasAtualizados.ToArray());
}

View File

@ -13,6 +13,7 @@ namespace AgroBase.Services.Operadores
{
public ManagerWorkerModel DadosLeitura = new ManagerWorkerModel();
public SaudeWorkerModel Saude { get; set; } = new SaudeWorkerModel();
public AsyncTaskTimerModel tmrPooling;
private bool DebugMode = true;
@ -31,6 +32,10 @@ namespace AgroBase.Services.Operadores
DadosLeitura.IniciadoEm = DateTime.Now;
DadosLeitura.Iniciado = true;
tmrPooling?.Dispose();
tmrPooling = new AsyncTaskTimerModel("tmrManagerWorkerPooling", tmrPooling_Tick, 500);
tmrPooling.Start();
bool pronto() => DadosLeitura.Pronto;
await FuncoesGlobais.AguardarCondicaoAsync(pronto, 5000);
if (pronto())
@ -44,6 +49,41 @@ namespace AgroBase.Services.Operadores
return false;
}
private async Task tmrPooling_Tick()
{
var dictParams = JsonConvert.DeserializeObject<Dictionary<string, object>>(RedisService.Get(CtxKey.DadosControle));
AtualizarControle(dictParams);
}
private void AtualizarControle(Dictionary<string, object> dictParams)
{
if (dictParams == null)
return;
dictParams.TryGetValue("angulo_sp", out object _angulo);
dictParams.TryGetValue("velocidade_sp", out object _velocidade);
dictParams.TryGetValue("tipo_movimento_direcional", out object _movimento);
dictParams.TryGetValue("simulacao", out object _simulacao);
var novoComando = new ManagerWorkerMessageResponseComandoModel()
{
angulo = Convert.ToDouble(_angulo),
percentual_velocidade = Convert.ToDouble(_velocidade),
tipo_movimento = (Enums.TipoMovimentoDirecional)Convert.ToInt32(_movimento),
simulacao = JsonConvert.DeserializeObject<List<double[]>>((_simulacao ?? "").ToString())
};
if (novoComando != null)
{
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
_Controle.Angulo = novoComando.angulo;
_Controle.TipoMovimento = novoComando.tipo_movimento;
_Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade;
_Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List<MPCSimulacaoModel>();
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();
}
}
public void RedisCallback(string mensagem)
{
try
@ -66,22 +106,7 @@ namespace AgroBase.Services.Operadores
if (comando.@params == null)
break;
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
var novoComando = new ManagerWorkerMessageResponseComandoModel()
{
angulo = Convert.ToDouble(comando.@params["angulo"]),
percentual_velocidade = Convert.ToDouble(comando.@params["percentual_velocidade"]),
tipo_movimento = (Enums.TipoMovimentoDirecional)Convert.ToInt32(comando.@params["tipo_movimento"]),
simulacao = JsonConvert.DeserializeObject<List<double[]>>(comando.@params["simulacao"].ToString())
};
if (novoComando != null)
{
_Controle.Angulo = novoComando.angulo;
_Controle.TipoMovimento = novoComando.tipo_movimento;
_Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade;
_Controle.SimulacaoMPC = novoComando.simulacao.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList();
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();
}
AtualizarControle(comando.@params);
}
break;

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static AgroBase.Models.Enums;
using static AgroBase.Models.Operadores.OperadoresModels;
@ -94,7 +95,8 @@ namespace AgroBase.Services.Operadores
RedisService.AtualizarCampos(
CtxKey.DadosControle,
("angulo_sp", _Controle.Angulo),
("velocidade_sp", _Controle.PercentualVelocidadeSP)
("velocidade_sp", _Controle.PercentualVelocidadeSP),
("controle_bicos", _Controle.BicosAtuados.ToDictionary(x => x.Posicao - 1, x => false))
);
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();

View File

@ -13,6 +13,7 @@ namespace AgroBase.Services.Operadores
{
public static WeedWorkerModel DadosLeitura = new WeedWorkerModel();
public SaudeWorkerModel Saude { get; set; } = new SaudeWorkerModel();
public AsyncTaskTimerModel tmrPooling;
private bool DebugMode = true;
@ -31,6 +32,10 @@ namespace AgroBase.Services.Operadores
DadosLeitura.IniciadoEm = DateTime.Now;
DadosLeitura.Iniciado = true;
tmrPooling?.Dispose();
tmrPooling = new AsyncTaskTimerModel("tmrWeedWorkerPooling", tmrPooling_Tick, 500);
tmrPooling.Start();
bool pronto() => DadosLeitura.Pronto;
await FuncoesGlobais.AguardarCondicaoAsync(pronto, 5000);
if (pronto())
@ -44,6 +49,35 @@ namespace AgroBase.Services.Operadores
return false;
}
private async Task tmrPooling_Tick()
{
var dictParams = RedisService.GetField<Dictionary<string, object>>(CtxKey.DadosControle, "controle_bicos");
AtualizarControle(dictParams);
}
private void AtualizarControle(Dictionary<string, object> dictParams)
{
if (dictParams == null)
return;
var novoComando = dictParams
.Select(kv => new
{
Key = int.TryParse(kv.Key, out var i) ? (i + 1) : -1,
Value = Convert.ToBoolean(kv.Value)
})
.Where(x => x.Key >= 0)
.ToDictionary(x => x.Key, x => x.Value);
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
foreach (var bico in _Controle.BicosAtuados)
{
novoComando.TryGetValue(bico.Posicao, out bool atuado);
bico.ComandoAtuar = atuado;
}
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();
}
public void RedisCallback(string mensagem)
{
try
@ -77,23 +111,9 @@ namespace AgroBase.Services.Operadores
if (comando.@params == null)
break;
var _Controle = Variaveis.OperacaoEmAndamento.Controle;
if (comando.@params is Dictionary<string, object> dictParams)
{
var novoComando = dictParams
.Select(kv => new
{
Key = int.TryParse(kv.Key, out var i) ? (i + 1) : -1,
Value = Convert.ToBoolean(kv.Value)
})
.Where(x => x.Key >= 0)
.ToDictionary(x => x.Key, x => x.Value);
foreach (var bico in _Controle.BicosAtuados)
{
novoComando.TryGetValue(bico.Posicao, out bool atuado);
bico.ComandoAtuar = atuado;
}
Variaveis.OperacaoEmAndamento.AtualizaInformacoesControleOperacao();
AtualizarControle(dictParams);
}
}
break;
@ -153,6 +173,57 @@ namespace AgroBase.Services.Operadores
RedisService.Publish(CmdKey.WeedWorkerRx, JsonConvert.SerializeObject(comando));
}
public static void AtualizarAnalise()
{
var json = RedisService.Get(CtxKey.DadosWeedWorker);
var dados = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
if (dados.ContainsKey("ts_analise") && dados.ContainsKey("analise"))
{
var analise = JsonConvert.DeserializeObject<Dictionary<string, object>>(dados["analise"].ToString());
// 1. Timestamp (vem como double ou string)
DateTime timestamp = FuncoesGlobais.UnixToDateTime(analise["timestamp"].ToString());
// 2. Deteccoes (vem como List<object> ou string)
var listaDeteccoes = JsonConvert.DeserializeObject<List<WeedWorkerAnaliseDeteccaoModel>>(
analise["deteccoes"].ToString()
);
// 3. Controle: pode vir como Dictionary<string, object>
var controleDict = JsonConvert.DeserializeObject<Dictionary<string, bool>>(
analise["controle"].ToString()
);
var ervasIdentificadas = JsonConvert.DeserializeObject<List<Dictionary<string, int>>>(
analise["ervas_identificadas"].ToString()
);
// 4. Monta o objeto manualmente
var analiseObj = new WeedWorkerAnaliseModel
{
timestamp = timestamp,
frame_height = Convert.ToInt32(analise["frame_height"].ToString()),
frame_width = Convert.ToInt32(analise["frame_width"].ToString()),
deteccoes = listaDeteccoes,
controle = controleDict.ToDictionary(x => Convert.ToInt32(x.Key), x => x.Value),
ervas_identificadas = ervasIdentificadas
};
Variaveis.OperacaoEmAndamento.DispAtu?.Dados?.BicosPulverizadores?.ForEach(bico =>
{
int atuacoes = 0;
var ervas = DadosLeitura?.Analise?.ervas_identificadas ?? new List<Dictionary<string, int>>();
if (ervas.Count < bico.Posicao || bico.Posicao <= 0)
atuacoes = 0;
else
atuacoes = ervas[bico.Posicao - 1]?.Sum(x => x.Value) ?? 0;
bico.Atuacoes = atuacoes;
});
DadosLeitura.Analise = analiseObj;
}
}
}
}

View File

@ -39,7 +39,7 @@ namespace AgroBase.Services
private bool DebugMode = false;
private void MostrarLog(string message, byte id)
{
if (DebugMode && new List<byte>() { 0x01 }.Contains(id))
if (DebugMode && new List<byte>() { 0x12 }.Contains(id))
{
Console.WriteLine($"[CAN] {message}");
}
@ -52,6 +52,8 @@ namespace AgroBase.Services
}
public bool Inicializar(SerialPort Porta = null)
{
try
{
if (Porta == null && (_PortaCAN?.IsOpen ?? false))
{
@ -106,6 +108,12 @@ namespace AgroBase.Services
return IsConnected;
}
catch (Exception ex)
{
_PortaCAN = null;
return false;
}
}
private async Task ProcessarCAN()
{
@ -128,7 +136,7 @@ namespace AgroBase.Services
private async Task OuvirCAN()
{
if (_PortaCAN.BytesToRead > 0)
if ((_PortaCAN?.BytesToRead ?? 0) > 0)
{
byte[] tempBuffer = await SerialService.LerDadosDaPortaSerialAsync(_PortaCAN, _PortaCAN.BytesToRead);

View File

@ -22,5 +22,5 @@
"top_topics_and_observing_domains": [ ]
} ],
"hex_encoded_hmac_key": "40F346D3248C3AFDF2BEE1FE496DBD32F7CED6E5AE98B881ABC421AA7E7B5642",
"next_scheduled_calculation_time": "13397830127957680"
"next_scheduled_calculation_time": "13397830127958004"
}

View File

@ -1,3 +1,3 @@
2025/07/21-15:21:17.549 8344 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001
2025/07/21-15:21:17.555 8344 Recovering log #3
2025/07/21-15:21:17.558 8344 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log
2025/07/22-16:49:20.933 1058 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001
2025/07/22-16:49:20.940 1058 Recovering log #3
2025/07/22-16:49:20.943 1058 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log

View File

@ -1,3 +1,3 @@
2025/07/21-15:10:12.398 7cc4 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001
2025/07/21-15:10:12.406 7cc4 Recovering log #3
2025/07/21-15:10:12.409 7cc4 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log
2025/07/22-16:29:12.424 2bec Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/MANIFEST-000001
2025/07/22-16:29:12.430 2bec Recovering log #3
2025/07/22-16:29:12.434 2bec Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Local Storage\leveldb/000003.log

View File

@ -1 +1 @@
{"net":{"http_server_properties":{"servers":[{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13397682078167259","port":443,"protocol_str":"quic"}],"anonymization":["DAAAAAcAAABmaWxlOi8vAA==",false,0],"network_stats":{"srtt":58184},"server":"https://tile.openstreetmap.org","supports_spdy":true}],"supports_quic":{"address":"2804:d78:69b:cf00:e1c9:9847:8945:20fe","used_quic":true},"version":5},"network_qualities":{"CAASABiAgICA+P////8B":"4G","CAESABiAgICA+P////8B":"4G","CAISABiAgICA+P////8B":"4G","CAYSABiAgICA+P////8B":"Offline"}}}
{"net":{"http_server_properties":{"servers":[{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13397773761325995","port":443,"protocol_str":"quic"}],"anonymization":["DAAAAAcAAABmaWxlOi8vAA==",false,0],"network_stats":{"srtt":6761},"server":"https://tile.openstreetmap.org","supports_spdy":true}],"supports_quic":{"address":"2804:d78:69b:cf00:7cbf:e352:1909:3adf","used_quic":true},"version":5},"network_qualities":{"CAASABiAgICA+P////8B":"4G","CAESABiAgICA+P////8B":"4G","CAISABiAgICA+P////8B":"4G","CAYSABiAgICA+P////8B":"Offline"}}}

View File

@ -1 +1 @@
{"sts":[{"expiry":1784401820.415379,"host":"bWGAftl61rqoc0YzqPncsLvQQh/iC2Bdp3ejUeGC83w=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1752865820.415381}],"version":2}
{"sts":[{"expiry":1784719491.173963,"host":"bWGAftl61rqoc0YzqPncsLvQQh/iC2Bdp3ejUeGC83w=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1753183491.173973}],"version":2}

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
2025/07/21-15:34:33.516 8344 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001
2025/07/21-15:34:33.517 8344 Recovering log #3
2025/07/21-15:34:33.520 8344 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log
2025/07/22-16:54:21.213 1058 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001
2025/07/22-16:54:21.215 1058 Recovering log #3
2025/07/22-16:54:21.219 1058 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log

View File

@ -1,3 +1,3 @@
2025/07/21-15:18:09.336 7cc4 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001
2025/07/21-15:18:09.338 7cc4 Recovering log #3
2025/07/21-15:18:09.342 7cc4 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log
2025/07/22-16:36:35.720 2bec Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/MANIFEST-000001
2025/07/22-16:36:35.722 2bec Recovering log #3
2025/07/22-16:36:35.724 2bec Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Session Storage/000003.log

View File

@ -1,3 +1,3 @@
2025/07/21-15:21:17.473 813c Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001
2025/07/21-15:21:17.474 813c Recovering log #7
2025/07/21-15:21:17.475 813c Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log
2025/07/22-16:49:20.855 17f8 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001
2025/07/22-16:49:20.856 17f8 Recovering log #7
2025/07/22-16:49:20.856 17f8 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log

View File

@ -1,3 +1,3 @@
2025/07/21-15:10:12.318 189c Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001
2025/07/21-15:10:12.320 189c Recovering log #7
2025/07/21-15:10:12.320 189c Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log
2025/07/22-16:29:12.355 21c8 Reusing MANIFEST C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/MANIFEST-000001
2025/07/22-16:29:12.356 21c8 Recovering log #7
2025/07/22-16:29:12.357 21c8 Reusing old log C:\ZendionInc\agrobot_base\AgroBase\AgroBase\bin\x64\Debug\AgroBase.exe.WebView2\EBWebView\Default\Site Characteristics Database/000007.log

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,7 @@
<meta name="viewport" content="width=device-width,
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<style>
#map_9167a3f59236bbe3ca57b08de1d97258 {
#map_a1e0e55f1aa8221816909f40117511ed {
position: relative;
width: 100.0%;
height: 100.0%;
@ -54,14 +54,14 @@
<body>
<div class="folium-map" id="map_9167a3f59236bbe3ca57b08de1d97258" ></div>
<div class="folium-map" id="map_a1e0e55f1aa8221816909f40117511ed" ></div>
</body>
<script>
var map_9167a3f59236bbe3ca57b08de1d97258 = L.map(
"map_9167a3f59236bbe3ca57b08de1d97258",
var map_a1e0e55f1aa8221816909f40117511ed = L.map(
"map_a1e0e55f1aa8221816909f40117511ed",
{
center: [0.0, 0.0],
crs: L.CRS.EPSG3857,
@ -78,7 +78,7 @@
var tile_layer_d32108711f97218804be105ee489826b = L.tileLayer(
var tile_layer_39f0b8ff9e639c0b7edd913d12c51e75 = L.tileLayer(
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
{
"minZoom": 0,
@ -95,7 +95,7 @@
);
tile_layer_d32108711f97218804be105ee489826b.addTo(map_9167a3f59236bbe3ca57b08de1d97258);
tile_layer_39f0b8ff9e639c0b7edd913d12c51e75.addTo(map_a1e0e55f1aa8221816909f40117511ed);
</script>
@ -116,7 +116,7 @@
}
trajeto_json_add({"features": []});
trajeto_json.addTo(map_9167a3f59236bbe3ca57b08de1d97258);
trajeto_json.addTo(map_a1e0e55f1aa8221816909f40117511ed);
function adicionarGeometria(novaGeometria) {
trajeto_json.addData(novaGeometria);
@ -179,9 +179,9 @@
var marcadorEquipamento = L.marker([0, 0], {
icon: customIcon
}).addTo(map_9167a3f59236bbe3ca57b08de1d97258);
}).addTo(map_a1e0e55f1aa8221816909f40117511ed);
var marcadorBase = L.marker([0, 0], {}).addTo(map_9167a3f59236bbe3ca57b08de1d97258);
var marcadorBase = L.marker([0, 0], {}).addTo(map_a1e0e55f1aa8221816909f40117511ed);
var icon = L.AwesomeMarkers.icon(
{"extraClasses": "fa-rotate-0", "icon": "info-sign", "iconColor": "white", "markerColor": "red", "prefix": "glyphicon"}
);
@ -246,7 +246,7 @@
}
if (foco) {
map_9167a3f59236bbe3ca57b08de1d97258.setView(novaPosicao, map_9167a3f59236bbe3ca57b08de1d97258.getZoom());
map_a1e0e55f1aa8221816909f40117511ed.setView(novaPosicao, map_a1e0e55f1aa8221816909f40117511ed.getZoom());
}
}
@ -268,7 +268,7 @@
marcadorDinamico.setRotationAngle(angulo);
adicionarCoordenada("Tj", [novaLongitude, novaLatitude]);
map_9167a3f59236bbe3ca57b08de1d97258.setView(novaPosicao, map_9167a3f59236bbe3ca57b08de1d97258.getZoom());*/
map_a1e0e55f1aa8221816909f40117511ed.setView(novaPosicao, map_a1e0e55f1aa8221816909f40117511ed.getZoom());*/
});
function calcularOrientacao(P1latitude, P1longitude, P2latitude, P2longitude) {

File diff suppressed because one or more lines are too long

View File

@ -80,6 +80,7 @@ class CameraOak:
self.imu = IMUCamera(self.q_imu)
if self.dispositivo == T_Code.Snr:
dadosSnr = ContextoGlobalRedis.get_operacao().get("Snr", {})
self.parametros = {
"rgb_width": 1920,
"rgb_height": 1080,
@ -90,16 +91,32 @@ class CameraOak:
"baseline": 0.075,
"fov_h": 1.0,
"fov_v": 1.0,
"distancia_maxima": ContextoGlobalRedis.get_operacao().get("Snr", {}).get("distancia_maxima", 5000),
"distancia_minima": ContextoGlobalRedis.get_operacao().get("Snr", {}).get("distancia_minima", 500),
"percentual_altura_solo": ContextoGlobalRedis.get_operacao().get("Snr", {}).get("percentual_altura_solo", 30),
"distancia_maxima": dadosSnr.get("distancia_maxima", 5000),
"distancia_minima": dadosSnr.get("distancia_minima", 500),
"percentual_altura_solo": dadosSnr.get("percentual_altura_solo", 30),
}
self._set_calib()
_camera["parametros"] = self.parametros
elif self.dispositivo == T_Code.Cam:
rgb_width = 1920
rgb_height = 1080
altura_camera = 85
fov_h = 95
fov_v = 70
largura_real = 2 * altura_camera * np.tan(np.radians(fov_h) / 2)
altura_real = 2 * altura_camera * np.tan(np.radians(fov_v) / 2)
cm_por_px_x = largura_real / rgb_width
cm_por_px_y = altura_real / rgb_height
self.parametros = {
"rgb_width": 1920,
"rgb_height": 1080,
"rgb_width": rgb_width,
"rgb_height": rgb_height,
"fov_h": np.radians(fov_h),
"fov_v": np.radians(fov_v),
"altura_camera": altura_camera,
"largura_real": largura_real,
"altura_real": altura_real,
"cm_por_px_x": cm_por_px_x,
"cm_por_px_y": cm_por_px_y,
}
_camera["parametros"] = self.parametros

View File

@ -11,7 +11,7 @@ def main():
from health_worker.modulos.direcional import ModuloDirecional
from health_worker.modulos.movimentacao import ModuloMovimentacao
from health_worker.modulos.sensoriamento import ModuloSensoriamento
from health_worker.modulos.imu import IMUCamera
from health_worker.modulos.atuador import ModuloAtuador
from health_worker.config import mostrar_log
from shared.contexto_global_redis import ContextoGlobalRedis, CmdKey, CtxKey
@ -19,7 +19,8 @@ def main():
T_Code.Gps: ModuloGPS(),
T_Code.Dir: ModuloDirecional(),
T_Code.Mov: ModuloMovimentacao(),
T_Code.Sen: ModuloSensoriamento()
T_Code.Sen: ModuloSensoriamento(),
T_Code.Atu: ModuloAtuador()
}
def loop_ativo():

View File

@ -0,0 +1,224 @@
import time
from shared.enums import T_Code, S_Code, StatusModulo
from shared.utils import penalizar_frequencia
from health_worker.modulos.base import ModuloDiagnosticoBase
from health_worker.aprendizado.padrao_dinamico import PadraoDinamico
from shared.contexto_global_redis import ContextoGlobalRedis
class ModuloAtuador(ModuloDiagnosticoBase):
def __init__(self):
super().__init__() # ✅ garante que a classe base é corretamente iniciada
self.t_code = T_Code.Atu
self.nome = "Atuador"
self.padroes_sensores = {}
self.padroes_bicos = {}
self.padroes_bombas = {}
self.timeout = 3 # pode ser usado para validar timestamp
def atualizar_saude(self):
try:
agora = time.time()
motivos_gerais = []
saude_total = 0
total_ativos = 0
saude_individual = []
dados_atu = ContextoGlobalRedis.get_modulo(self.t_code)
mod_conectado = dados_atu.get("conectado", False)
FREQ_BASE = dados_atu.get("freq_base", 1)
FREQ_MIN = FREQ_BASE * 0.5
SAUDE_MIN_ALERTA = 80
for tipo, sensores in dados_atu.get("sensores", {}).items():
for bico_id, dados_bico in sensores.items():
saude = 100
motivos = []
condicoes_operacionais = []
aferir = dados_bico.get("aferir", False)
padroes = self.padroes_sensores.get(tipo, {}).get(bico_id, {})
conectado = dados_bico.get("conectado", False)
mandatorio = dados_bico.get("mandatorio", False)
if not conectado:
saude = 0
motivos.append(f"desconectado")
else:
for campo in dados_bico.get("dados", []):
label = campo.get("label")
if label is None:
continue
freq = campo.get("freq", 0.0)
if freq == 0:
saude = 0
motivos.append(f"{label} sem resposta (freq = 0 Hz)")
else:
penalidade = penalizar_frequencia(freq, FREQ_BASE, FREQ_MIN, (100 - SAUDE_MIN_ALERTA))
saude -= penalidade
if (freq <= FREQ_MIN):
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
atual = campo.get("atual")
padrao = padroes.get(label) if atual else None
if padrao is not None:
# Avaliação de condição operacional (sem penalizar saúde)
if not padrao.esta_dentro_do_padrao(atual):
grau = padrao.calcular_quao_anormal(atual)
condicoes_operacionais.append({
"valor": atual,
"severidade": grau,
"descricao": f"{label} fora do padrão"
})
saude = max(0, saude)
chave = f"{S_Code(int(tipo)).name}_{bico_id}"
saude_mod = {
"id": bico_id,
"label": dados_bico.get("label"),
"status": (StatusModulo.DESCONECTADO if not conectado else StatusModulo.OPERANTE if saude >= SAUDE_MIN_ALERTA else StatusModulo.ALERTA if saude > 0 else StatusModulo.FALHA).value,
"saude": saude,
"motivos": motivos,
"condicoes_operacionais": condicoes_operacionais,
"em_uso": aferir
}
saude_individual.append(saude_mod)
if mandatorio:
total_ativos += 1
saude_total += saude
motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_bico["saude"] = saude_mod
for tipo, bicos in dados_atu.get("bicos", {}).items():
for bico_id, dados_bico in bicos.items():
saude = 100
motivos = []
condicoes_operacionais = []
comandar = dados_bico.get("comandar", False)
padroes = self.padroes_bicos.get(tipo, {}).get(bico_id, {})
conectado = dados_bico.get("conectado", False)
mandatorio = dados_bico.get("mandatorio", False)
if not conectado:
saude = 0
motivos.append(f"desconectado")
else:
for campo in dados_bico.get("dados", []):
label = campo.get("label")
if label is None:
continue
freq = campo.get("freq", 0.0)
if freq == 0:
saude = 0
motivos.append(f"{label} sem resposta (freq = 0 Hz)")
else:
penalidade = penalizar_frequencia(freq, FREQ_BASE, FREQ_MIN, (100 - SAUDE_MIN_ALERTA))
saude -= penalidade
if (freq <= FREQ_MIN):
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
atual = campo.get("atual")
padrao = padroes.get(label) if atual else None
if padrao is not None:
# Avaliação de condição operacional (sem penalizar saúde)
if not padrao.esta_dentro_do_padrao(atual):
grau = padrao.calcular_quao_anormal(atual)
condicoes_operacionais.append({
"valor": atual,
"severidade": grau,
"descricao": f"{label} fora do padrão"
})
saude = max(0, saude)
chave = f"{S_Code(int(tipo)).name}_{bico_id}"
saude_mod = {
"id": bico_id,
"label": dados_bico.get("label"),
"status": (StatusModulo.DESCONECTADO if not conectado else StatusModulo.OPERANTE if saude >= SAUDE_MIN_ALERTA else StatusModulo.ALERTA if saude > 0 else StatusModulo.FALHA).value,
"saude": saude,
"motivos": motivos,
"condicoes_operacionais": condicoes_operacionais,
"em_uso": comandar
}
saude_individual.append(saude_mod)
if mandatorio:
total_ativos += 1
saude_total += saude
motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_bico["saude"] = saude_mod
for tipo, bombas in dados_atu.get("bombas", {}).items():
for bomba_id, dados_bomba in bombas.items():
saude = 100
motivos = []
condicoes_operacionais = []
comandar = dados_bomba.get("comandar", False)
padroes = self.padroes_bombas.get(tipo, {}).get(bomba_id, {})
conectado = dados_bomba.get("conectado", False)
mandatorio = dados_bomba.get("mandatorio", False)
if not conectado:
saude = 0
motivos.append(f"desconectado")
else:
for campo in dados_bomba.get("dados", []):
label = campo.get("label")
if label is None:
continue
freq = campo.get("freq", 0.0)
if freq == 0:
saude = 0
motivos.append(f"{label} sem resposta (freq = 0 Hz)")
else:
penalidade = penalizar_frequencia(freq, FREQ_BASE, FREQ_MIN, (100 - SAUDE_MIN_ALERTA))
saude -= penalidade
if (freq <= FREQ_MIN):
motivos.append(f"{label} frequência baixa ({freq:.2f}/{FREQ_BASE} Hz, penalidade {penalidade}%)")
atual = campo.get("atual")
padrao = padroes.get(label) if atual else None
if padrao is not None:
# Avaliação de condição operacional (sem penalizar saúde)
if not padrao.esta_dentro_do_padrao(atual):
grau = padrao.calcular_quao_anormal(atual)
condicoes_operacionais.append({
"valor": atual,
"severidade": grau,
"descricao": f"{label} fora do padrão"
})
saude = max(0, saude)
chave = f"{S_Code(int(tipo)).name}_{bomba_id}"
saude_mod = {
"id": bomba_id,
"label": dados_bomba.get("label"),
"status": (StatusModulo.DESCONECTADO if not conectado else StatusModulo.OPERANTE if saude >= SAUDE_MIN_ALERTA else StatusModulo.ALERTA if saude > 0 else StatusModulo.FALHA).value,
"saude": saude,
"motivos": motivos,
"condicoes_operacionais": condicoes_operacionais,
"em_uso": comandar
}
saude_individual.append(saude_mod)
if mandatorio:
total_ativos += 1
saude_total += saude
motivos_gerais.extend([f"{chave}: {m}" for m in motivos])
dados_bomba["saude"] = saude_mod
saude_final = (saude_total // total_ativos) if total_ativos > 0 else 100
status = StatusModulo.OPERANTE
if not mod_conectado:
status = StatusModulo.DESCONECTADO
elif saude_final <= 0:
status = StatusModulo.FALHA
elif saude_final < SAUDE_MIN_ALERTA or any(s["em_uso"] is True and s["saude"] < SAUDE_MIN_ALERTA for s in saude_individual):
status = StatusModulo.ALERTA
saude_geral = {
"conectado": mod_conectado,
"status": status.value,
"saude": saude_final,
"motivos": motivos_gerais,
"saude_individual": saude_individual
}
ContextoGlobalRedis.atualizar_ctx_dict(
ContextoGlobalRedis.ModKey(self.t_code),
saude=saude_geral
)
except Exception as e:
print(f"Erro ao atualizar saude do modulo {self.t_code.name}: {e}")

View File

@ -36,6 +36,7 @@ def definir_comando():
"AnguloCaminho": _trajetoria.get("angulo", 0.0),
},
"VisualWorker": {
"Ativado": _operacao.get("Snr", {}).get("sonar_ativado", False),
"Operante": visual_worker_operante,
"Camera": {
"FovH": ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {}).get("parametros", {}).get("fov_h", 0.7),
@ -45,7 +46,8 @@ def definir_comando():
"MatrizCusto": [[]],
},
"RegrasAtivas": {
"matriz_custo": visual_worker_operante and True,
"matriz_custo": True,
"deteccao_obstaculos": True,
},
"Equipamento": {
"largura": _equipamento.get("largura", 0.85),
@ -84,9 +86,15 @@ def regras_taticas(contexto):
mostrar_log("🟥 Direcional parado: operação não está em andamento ou está finalizando.")
return comando_direcional_parado(True)
velocidade_media = contexto.get("Carro", {}).get("Velocidade", 0.0)
if velocidade_media < 0.01:
mostrar_log("⚠️ Possível travamento detectado (velocidade quase zero).")
# Pode evoluir para uma lógica de recuperação no futuro
vw_ativado = contexto.get("VisualWorker", {}).get("Ativado", False)
vw_operante = contexto.get("VisualWorker", {}).get("Operante", False)
if not vw_operante:
if vw_ativado and not vw_operante:
mostrar_log("⚠️ Sensores principais inativos. Rodando MPC no modo básico.")
return comando_direcional_parado(False)
@ -96,12 +104,11 @@ def regras_taticas(contexto):
mostrar_log(f"🟥 Inclinação perigosa detectada. Parando movimentação. roll: {imu.get('roll')}, pitch: {imu.get('pitch')}, yaw: {imu.get('yaw')}")
return comando_direcional_parado(True)
velocidade_media = contexto["Carro"]["Velocidade"]
if velocidade_media < 0.01:
mostrar_log("⚠️ Possível travamento detectado (velocidade quase zero).")
# Pode evoluir para uma lógica de recuperação no futuro
if not vw_ativado:
mostrar_log("Visual Worker desativado. Rodando MPC no modo básico.")
return comando_direcional_parado(False)
if contexto.get("RegrasAtivas", {}).get("matriz_custo", False):
if vw_operante and contexto.get("RegrasAtivas", {}).get("deteccao_obstaculos", False):
analise = ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {})
obstaculos = analise.get("anomalias", {}).get("deteccoes", [])
if obstaculos:

View File

@ -1195,10 +1195,15 @@ class ControladorMPC:
else:
tipos_validos = [ TipoMovimentoDirecional.RodasDianteiras ]
com_matriz_custo = contexto.get("VisualWorker", {}).get("Operante", False)
angulos_raw = self._gerar_candidatos_brutos(angulo_ideal_deg, com_matriz_custo)
ctx_vw = contexto.get("VisualWorker", {})
vw_ativado = ctx_vw.get("Ativado", False)
vw_operante = ctx_vw.get("Operante", False)
com_matriz_custo = contexto.get("RegrasAtivas", {}).get("matriz_custo", False)
filtrar_matriz = vw_ativado and vw_operante and com_matriz_custo
angulos_raw = self._gerar_candidatos_brutos(angulo_ideal_deg, filtrar_matriz)
#print(f"Angulos Brutos: {[round(float(a), 2) for a in angulos_raw]}")
tipos_final, angulos_final, custos_candidatos = self._filtrar_candidatos_validos_por_matriz(tipos_validos, angulos_raw, angulo_ideal_rad, ponto_atual, ponto_ref, contexto)
tipos_final, angulos_final, custos_candidatos = self._filtrar_candidatos_validos_por_matriz(filtrar_matriz, tipos_validos, angulos_raw, angulo_ideal_rad, ponto_atual, ponto_ref, contexto)
#print(f"Angulos Filtrados Matriz: {[round(float(np.degrees(a)), 2) for a in angulos_final]}")
angulos_final = self._uniformizar_angulos_candidatos(angulos_final, angulo_ideal_rad, 10)
#print(f"Angulos Uniformizados: {[round(float(np.degrees(a)), 2) for a in angulos_final]}")
@ -1208,7 +1213,7 @@ class ControladorMPC:
mostrar_log(f"❌ Erro ao gerar candidatos receding com contexto visual: {e}")
return [], []
def _gerar_candidatos_brutos(self, angulo_ideal_deg, com_matriz_custo=False):
def _gerar_candidatos_brutos(self, angulo_ideal_deg, filtrar_matriz_custo):
try:
# 1. Geração em torno do ideal
if abs(angulo_ideal_deg) > 10:
@ -1232,7 +1237,7 @@ class ControladorMPC:
#print(f"Angulos ideais: {[f'{float(a):.2f}' for a in angulos_ideais]}")
# 2. Se for com matriz de custo, gera todo o sweep
if com_matriz_custo:
if filtrar_matriz_custo:
sweep = list(np.arange(-self.angulo_max_graus, self.angulo_max_graus + 0.1, passo_total))
# 3. Remove ângulos muito próximos dos ideais
@ -1252,15 +1257,14 @@ class ControladorMPC:
mostrar_log(f"❌ Erro ao gerar candidatos brutos: {e}")
return []
def _filtrar_candidatos_validos_por_matriz(self, tipos, angulos_deg, angulo_ideal_rad, p_atual, p_ref, contexto):
def _filtrar_candidatos_validos_por_matriz(self, filtrar_matriz, tipos, angulos_deg, angulo_ideal_rad, p_atual, p_ref, contexto):
pesos = self._calcular_pesos_movimento(contexto, abs(angulo_ideal_rad))
peso_angulo_ideal = pesos[4]
try:
angulos_rad = [np.radians(g) for g in angulos_deg]
matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", [[]])
com_matriz_custo = contexto.get("VisualWorker", {}).get("Operante", False)
filtrar_candidatos = True
if not filtrar_candidatos or not com_matriz_custo or len(matriz_custo[0]) == 0:
if not filtrar_matriz or len(matriz_custo[0]) == 0:
custos_candidatos = {}
for tipo in tipos:
for ang in angulos_rad:
@ -1271,10 +1275,12 @@ class ControladorMPC:
tipos_validos = []
angulos_validos = []
linhas_info = analisar_linhas_por_profundidade(matriz_custo, "distancia_m", contexto.get("VisualWorker", {}).get("Camera", {}).get("FovH", 0.7))
ctx_camera = contexto.get("VisualWorker", {}).get("Camera", {})
linhas_info = analisar_linhas_por_profundidade(matriz_custo, "distancia_m", ctx_camera.get("FovH", 0.7))
linhas_ordenadas = sorted(linhas_info.values(), key=lambda item: item["distancia"])
distancia_min_m = linhas_ordenadas[0]["distancia"]
distancia_sim_m = np.clip(linhas_ordenadas[1]["distancia"], contexto.get("VisualWorker", {}).get("Camera", {}).get("DistanciaMin", 0.5), contexto.get("VisualWorker", {}).get("Camera", {}).get("DistanciaMax", 5.0))
distancia_sim_m = np.clip(linhas_ordenadas[1]["distancia"], ctx_camera.get("DistanciaMin", 0.5), ctx_camera.get("DistanciaMax", 5.0))
largura = contexto.get("Equipamento", {}).get("largura", 0.85)
velocidade = contexto.get("Carro", {}).get("Velocidade", 1.0)

View File

@ -16,7 +16,8 @@ class ProcessadorEmAndamento(ProcessadorBase):
CtxKey.DadosControle,
angulo_sp=angulo_sp,
tipo_movimento_direcional=tipo_dir,
velocidade_sp=velocidade_sp
velocidade_sp=velocidade_sp,
simulacao=simulacao
)
return comando_controle(percentual_velocidade=velocidade_sp, angulo=angulo_sp, tipo_movimento=tipo_dir, simulacao=simulacao)
return None

View File

@ -5,9 +5,9 @@ from shared.contexto_global_redis import ContextoGlobalRedis
def comando_controle(percentual_velocidade: float, angulo: float, tipo_movimento: int, simulacao = []):
return {
"percentual_velocidade": percentual_velocidade,
"angulo": angulo,
"tipo_movimento": tipo_movimento,
"velocidade_sp": percentual_velocidade,
"angulo_sp": angulo,
"tipo_movimento_direcional": tipo_movimento,
"simulacao": simulacao
}

View File

@ -27,6 +27,13 @@ class CameraManager:
self.iniciando = False
self.calibrando = False
self._ultima_analise_anomalias = {}
self._ultima_analise_solo = {}
self._ultima_analise_radar = {}
self._ultima_analise_segmentacao = {}
self._ultima_analise_matriz_confianca = {}
self._ultima_analise_matriz_custo = {}
def inicializar(self, mx_id):
if self.iniciando:
return
@ -135,9 +142,11 @@ class CameraManager:
t = None
if tipo == CameraFrameType.Rgb:
f, t, _ = self.get_rgb_frame()
if f is not None:
f = encode_image_base64(f)
elif tipo == CameraFrameType.Heatmap:
f, t, _ = self.get_heatmap_frame()
if f is not None:
f = encode_image_base64(f)
elif tipo == CameraFrameType.RadarTopDown:
f = self._ultima_analise_radar.get("frame", {}).get("frame")

View File

@ -486,9 +486,9 @@
this.chbSonarAtivado.AutoSize = true;
this.chbSonarAtivado.Location = new System.Drawing.Point(9, 90);
this.chbSonarAtivado.Name = "chbSonarAtivado";
this.chbSonarAtivado.Size = new System.Drawing.Size(93, 17);
this.chbSonarAtivado.Size = new System.Drawing.Size(170, 17);
this.chbSonarAtivado.TabIndex = 13;
this.chbSonarAtivado.Text = "Sonar Ativado";
this.chbSonarAtivado.Text = "Utilizar dados visuais do Sonar";
this.chbSonarAtivado.UseVisualStyleBackColor = true;
//
// rtbDescricao

View File

@ -0,0 +1,8 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
"version": "0.2.0",
"configurations": [
]
}

View File

@ -0,0 +1,307 @@
// Dispositivo: Atuador
// Versão Firmware: 10
// Ultima atualização: 23/07/2025
// Atualização: Padronizacao CAN
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\I2CService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ReleModel.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\BombaPressurizadoraModel.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorFluxoModel.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorMassaModel.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorPressaoModel.h"
// Configurações do CAN
uint8_t CanID = 0x12;
CanService canService = CanService(CanID);
#define D_Code Atu
int VERSION = 10;
const String Mod_ID = "Atu";
#define _pinoLED RGB_BUILTIN
bool Conectado = false;
bool Conectar = false;
int _TaxaAmostragem = 1000;
volatile bool RequisitarDados = false;
int latenciaLoop = 0;
int qtdEnviosStatus = 0;
int maxEnviosStatus = 5;
std::vector<Rele*> listaBicos;
std::vector<BombaPressurizadora*> listaBombas;
std::vector<SensorFluxo*> listaSensoresFluxo;
std::vector<SensorMassa*> listaSensoresMassa;
std::vector<SensorPressao*> listaSensoresPressao;
void setup() {
delay(5000);
// Registrar callback para processar mensagens CAN recebidas
canService.setReceiveCallback([](int packetSize, int senderId, CanMessagePosicaoDados posicao, byte* data, int dataLength) {
std::vector<uint8_t> fullData;
fullData.push_back(static_cast<uint8_t>(posicao)); // Primeiro byte é sempre a posicao
for (int i = 0; i < dataLength; i++) {
fullData.push_back(data[i]);
}
ProcessarFrameCAN(posicao, fullData);
});
canService.begin();
}
void loop() {
if (!RequisitarDados) {
enviarLogsPeriodicamente();
}
for (auto* bomba : listaBombas) {
bomba->Loop();
}
for (auto* sensor : listaSensoresFluxo) {
sensor->Loop();
}
delay(1);
}
// Função para enviar logs do sensor periodicamente
unsigned long ultimoEnvioLogs = 0;
const unsigned long intervaloEnvioLogs = 1000; // 1 segundo
void enviarLogsPeriodicamente() {
unsigned long tempoAtual = millis();
// Verifica se o intervalo de 5 segundos já passou
if (tempoAtual - ultimoEnvioLogs >= intervaloEnvioLogs) {
ultimoEnvioLogs = tempoAtual; // Atualiza o tempo do último envio
enviarDadosSensores(canService.ID_Num_sTOD, CanMessagePosicaoDados::DadosAll);
}
}
void enviarDadosSensores(uint8_t id_num, CanMessagePosicaoDados posicao) {
if (Conectado || posicao == CanMessagePosicaoDados::Status) {
unsigned long startLoop = millis();
bool enviarStatus = qtdEnviosStatus >= maxEnviosStatus && posicao != CanMessagePosicaoDados::Status;
bool todosDados = posicao == CanMessagePosicaoDados::DadosAll;
bool todosIDs = id_num == canService.ID_Num_sTOD;
if (id_num == canService.ID_Num_sMOD) {
EnviarDadosCAN(canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION));
return;
}
PrintTela("[ATU] Atualizando dados dos sensores...");
if (todosIDs && enviarStatus) {
EnviarDadosCAN(canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION));
}
ComponenteCAN::ProcessarComponentesCAN(listaBombas, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponentesCAN(listaBicos, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponentesCAN(listaSensoresFluxo, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponentesCAN(listaSensoresMassa, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponentesCAN(listaSensoresPressao, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
if (enviarStatus) {
qtdEnviosStatus = 0;
}
else {
qtdEnviosStatus++;
}
latenciaLoop = millis() - startLoop;
if (posicao == CanMessagePosicaoDados::DadosAll) {
EnviarDadosCAN(canService.MontarFrameReqDadosFim(latenciaLoop));
}
PrintTela("[ATU] Ciclo concluido, latencia de loop: " + String(latenciaLoop));
}
}
void EnviarDadosCAN(std::vector<uint8_t> data) {
if (data.size() > 2) {
canService.adicionarMensagemFila(data);
}
}
void ProcessarFrameCAN(CanMessagePosicaoDados posicao, std::vector<uint8_t> data) {
if (data.size() < 1) return;
F_Code funcao = canService.FuncaoPorPosicao(posicao);
switch (funcao) {
case F_Code::ReqTx: ProcessarReq(data); break;
case F_Code::CmdTx: ProcessarCmd(data); break;
case F_Code::CfgTx: ProcessarCfg(data); break;
}
}
void ProcessarReq(std::vector<uint8_t> data) {
if (data.size() < 2) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
enviarDadosSensores(id, posicao);
}
void ProcessarCfg(std::vector<uint8_t> data) {
if (data.size() < 4) return;
std::vector<uint8_t> _chkRx;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
S_Code componente = DetectarComponente(id);
if (componente == S_Code::sMOD) {
switch (posicao) {
case CanMessagePosicaoDados::Config1: {
if (data.size() < 7) return;
bool conectar = data[2] == 1;
int taxa = data[3] * 10;
bool requisitar = data[4] == 1;
int pinoSDA = data[5];
int pinoSCL = data[6];
_TaxaAmostragem = taxa;
RequisitarDados = requisitar;
LimparListasComponentes();
if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) {
if (I2CService::DefinirPinos(pinoSDA, pinoSCL) || !I2CService::I2CIniciado) {
//inicializarDependenciasI2C();
}
}
vTaskDelay(pdMS_TO_TICKS(100));
Conectado = conectar;
_chkRx = canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION);
PrintTela("[ATU] Configuracao do modulo concluida");
break;
}
}
}
else {
componente = (S_Code)data[2];
switch (componente) {
case sBIC: {
_chkRx = Rele::ConfigurarRele(listaBicos, data, Mod_ID);
break;
}
case sFLX: {
_chkRx = SensorFluxo::ConfigurarSensor(listaSensoresFluxo, data, Mod_ID);
break;
}
case sPRS: {
_chkRx = SensorPressao::ConfigurarSensor(listaSensoresPressao, data, Mod_ID);
break;
}
case sMAS: {
_chkRx = SensorMassa::ConfigurarSensor(listaSensoresMassa, data, Mod_ID);
break;
}
case sBMB: {
_chkRx = BombaPressurizadora::ConfigurarBomba(listaBombas, data, Mod_ID, listaSensoresPressao);
break;
}
}
}
EnviarDadosCAN(_chkRx);
}
void ProcessarCmd(std::vector<uint8_t> data) {
if (data.size() < 2) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
S_Code componente = DetectarComponente(id);
switch (componente) {
case sBIC: {
Rele::ComandarRele(listaBicos, data);
break;
}
case sBMB: {
BombaPressurizadora::ComandarBomba(listaBombas, data);
break;
}
default:
break;
}
}
void LimparListasComponentes() {
for (auto* bico : listaBicos) {
if (bico) {
bico->Desligar();
PrintTela("[ATU] Bico " + bico->_ID + " desligado.");
delete bico;
}
}
listaBicos.clear();
for (auto* bomba : listaBombas) {
if (bomba) {
bomba->Desligar();
PrintTela("[ATU] Bomba Pressurizadora " + bomba->_ID + " desligada.");
delete bomba;
}
}
listaBombas.clear();
for (auto* sensor : listaSensoresFluxo) {
if (sensor) {
sensor->Desligar();
PrintTela("[ATU] Sensor de Fluxo " + sensor->_ID + " desligado.");
delete sensor;
}
}
listaSensoresFluxo.clear();
for (auto* sensor : listaSensoresMassa) {
if (sensor) {
sensor->Desligar();
PrintTela("[ATU] Sensor de Massa " + sensor->_ID + " desligado.");
delete sensor;
}
}
listaSensoresMassa.clear();
for (auto* sensor : listaSensoresPressao) {
if (sensor) {
sensor->Desligar();
PrintTela("[ATU] Sensor de Pressao " + sensor->_ID + " desligado.");
delete sensor;
}
}
listaSensoresPressao.clear();
}
S_Code DetectarComponente(uint8_t idNum) {
if (idNum == canService.ID_Num_sMOD) return S_Code::sMOD;
for (auto* s : listaBicos) {
if (s->ID_Num == idNum) return S_Code::sBIC;
}
for (auto* s : listaBombas) {
if (s->ID_Num == idNum) return S_Code::sBMB;
}
for (auto* s : listaSensoresFluxo) {
if (s->ID_Num == idNum) return S_Code::sFLX;
}
for (auto* s : listaSensoresMassa) {
if (s->ID_Num == idNum) return S_Code::sMAS;
}
for (auto* s : listaSensoresPressao) {
if (s->ID_Num == idNum) return S_Code::sPRS;
}
return S_Code::sVZO;
}

View File

@ -1,13 +1,12 @@
// Dispositivo: Atuador
// Versão Firmware: 8
// Ultima atualização: 29/11/2024
// Atualização: Implementado MQTT
// Versão Firmware: 9
// Ultima atualização: 10/04/2025
// Atualização: Implementado comunicacao CAN
#include <ArduinoJson.h>
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\MqttService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\WifiService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\I2CService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ReleModel.h"
@ -17,30 +16,24 @@
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorPressaoModel.h"
// Configurações do IP estático
IPAddress local_IP(192, 168, String(WIFI_FAIXA).toInt(), 13); // IP fixo para o ESP
IPAddress gateway(192, 168, String(WIFI_FAIXA).toInt(), 1); // Gateway padrão
IPAddress subnet(255, 255, 255, 0); // Máscara de sub-rede
IPAddress primaryDNS(8, 8, 8, 8); // Servidor DNS primário (opcional)
// Instancia o serviço MQTT
MqttService mqttService;
// Configurações do CAN
uint8_t CanID = 0x12;
CanService canService = CanService(CanID);
#define D_Code Atu
#define VERSION 8
int VERSION = 9;
const String Mod_ID = "Atu";
#define _pinoLED RGB_BUILTIN
long _baudRate = 115200;
bool Conectado = false;
bool Verificando = false;
bool Conectar = false;
int _TaxaAmostragem = 1000;
volatile bool RequisitarDados = false;
int latenciaLoop = 0;
int qtdEnviosStatus = 0;
int maxEnviosStatus = 5;
std::vector<Rele*> listaBicos;
std::vector<BombaPressurizadora*> listaBombas;
@ -49,40 +42,21 @@ std::vector<SensorMassa*> listaSensoresMassa;
std::vector<SensorPressao*> listaSensoresPressao;
void InicializarComunicacaoMQTT(bool RenovarConexao) {
if (RenovarConexao) {
mqttService.unsubscribe(TopicoRecepcao);
delay(1000);
}
mqttService.setModID(Mod_ID);
mqttService.InicializarComunicacaoMqtt();
mqttService.setMessageCallback(ProcessarProtocolo);
}
void setup() {
Serial.begin(_baudRate);
delay(5000);
InicializarConexaoWifi(local_IP, gateway, subnet, primaryDNS);
if (!WifiIsConnected) {
connectToWiFi();
if (WifiIsConnected) {
PrintTela("Conectado com sucesso");
}
else {
PrintTela("Erro ao se conectar ao wifi");
ESP.restart();
}
// Registrar callback para processar mensagens CAN recebidas
canService.setReceiveCallback([](int packetSize, int senderId, byte funcCode, byte* data, int dataLength) {
std::vector<uint8_t> fullData;
fullData.push_back(funcCode); // Primeiro byte é sempre o funcCode
for (int i = 0; i < dataLength; i++) {
fullData.push_back(data[i]);
}
delay(100);
ProcessarFrameCAN(fullData);
});
if (WifiIsConnected) {
InicializarComunicacaoMQTT(false);
}
canService.begin();
}
void loop() {
@ -92,7 +66,7 @@ void loop() {
enviarLogsPeriodicamente();
}
mqttService.loop();
canService.loop();
for (auto* bomba : listaBombas) {
bomba->Loop();
@ -106,8 +80,7 @@ void loop() {
latenciaLoop = millis() - startLoop;
}
// Função para enviar logs do sensor periodicamente via MQTT
// Função para enviar logs do sensor periodicamente
unsigned long ultimoEnvioLogs = 0;
const unsigned long intervaloEnvioLogs = 1000; // 1 segundo
void enviarLogsPeriodicamente() {
@ -121,209 +94,240 @@ void enviarLogsPeriodicamente() {
}
void enviarDadosSensores() {
if (Conectado && !Verificando) {
if (Conectado) {
PrintTela("Atualizando dados dos sensores...");
bool enviarStatus = qtdEnviosStatus >= maxEnviosStatus;
// Aferir dados dos sensores
for (auto* bico : listaBicos) {
bico->AtualizarLeitura();
if (bico != nullptr) {
bico->RequisitarDados();
if (enviarStatus) {
EnviarDadosCAN(bico->MontarMensagemCAN(CanMessagePosicaoDados::Status));
}
EnviarDadosCAN(bico->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
}
}
// Aferir dados dos sensores
for (auto* sensor : listaSensoresFluxo) {
sensor->AtualizarLeitura();
if (sensor != nullptr) {
sensor->RequisitarDados();
if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
}
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
}
}
// Aferir dados dos sensores
for (auto* sensor : listaSensoresMassa) {
if (sensor != nullptr) {
sensor->RequisitarDados();
if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
}
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
}
}
// Aferir dados dos sensores
for (auto* sensor : listaSensoresPressao) {
if (sensor != nullptr) {
sensor->RequisitarDados();
if (enviarStatus) {
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status));
}
EnviarDadosCAN(sensor->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
}
}
String jsonString = MontarMensagemSensores() + String(EndLine);
mqttService.EnviarDados(Mod_ID, jsonString);
// Aferir dados dos sensores
for (auto* bomba : listaBombas) {
if (bomba != nullptr) {
bomba->RequisitarDados();
if (enviarStatus) {
EnviarDadosCAN(bomba->MontarMensagemCAN(CanMessagePosicaoDados::Status));
}
EnviarDadosCAN(bomba->MontarMensagemCAN(CanMessagePosicaoDados::Dados1));
}
}
String MontarMensagemSensores() {
// Criação de um objeto JSON dinâmico com tamanho adequado
DynamicJsonDocument jsonDoc(2048);
// Adicionar campos gerais
jsonDoc["Conectado"] = Conectado;
jsonDoc["Mod_ID"] = Mod_ID;
jsonDoc["QualidadeWifi"] = WiFi.RSSI();
jsonDoc["LatenciaLoop"] = latenciaLoop;
// Array JSON para bicos pulverizadores
JsonArray bicosArray = jsonDoc.createNestedArray("BicosPulverizadores");
for (const auto* sensor : listaBicos) {
JsonObject sensorData = bicosArray.createNestedObject();
sensorData["Id"] = sensor->_ID;
sensorData["Iniciado"] = sensor->Iniciado;
sensorData["Leitura"] = sensor->_Status;
}
// Array JSON para bombas pressurizadoras
JsonArray bombasArray = jsonDoc.createNestedArray("BombasPressurizadoras");
for (const auto* sensor : listaBombas) {
JsonObject sensorData = bombasArray.createNestedObject();
sensorData["Id"] = sensor->_ID;
sensorData["Iniciado"] = sensor->Iniciado;
sensorData["Estado"] = sensor->EstadoLeitura;
sensorData["Potencia"] = sensor->PercentualPotenciaLeitura;
sensorData["PressaoSP"] = sensor->_PressaoSP;
sensorData["Pressao"] = sensor->sensorPressao->Pressao;
}
// Array JSON para sensores de fluxo
JsonArray sensoresFluxoArray = jsonDoc.createNestedArray("SensoresFluxo");
for (const auto* sensor : listaSensoresFluxo) {
JsonObject sensorData = sensoresFluxoArray.createNestedObject();
sensorData["Id"] = sensor->_ID;
sensorData["Iniciado"] = sensor->Iniciado;
sensorData["Pulsos"] = sensor->_PulsosLeitura;
sensorData["Periodo"] = sensor->_PeriodoTotalLeitura;
}
// Array JSON para sensores de massa
JsonArray sensoresMassaArray = jsonDoc.createNestedArray("SensoresMassa");
for (const auto* sensor : listaSensoresMassa) {
JsonObject sensorData = sensoresMassaArray.createNestedObject();
sensorData["Id"] = sensor->_ID;
sensorData["Iniciado"] = sensor->Iniciado;
sensorData["Leitura"] = sensor->leituraMassa;
}
// Array JSON para sensores de pressao
JsonArray sensoresPressaoArray = jsonDoc.createNestedArray("SensoresPressao");
for (const auto* sensor : listaSensoresPressao) {
JsonObject sensorData = sensoresPressaoArray.createNestedObject();
sensorData["Id"] = sensor->_ID;
sensorData["Iniciado"] = sensor->Iniciado;
sensorData["Pressao"] = sensor->Pressao;
sensorData["Leitura"] = sensor->leitura;
}
// Serializa o JSON para uma string
String jsonString;
serializeJson(jsonDoc, jsonString);
int messageSize = jsonString.length();
PrintTela("Tamanho da mensagem: ", false);
PrintTela((String)messageSize);
return jsonString;
}
void ProcessarProtocolo(ProtocoloSerial Mensagem) {
switch (Mensagem.funcao) {
case Chk:
ProcessarChk(Mensagem);
break;
case Cfg:
ProcessarCfg(Mensagem);
break;
case Cmd:
ProcessarCmd(Mensagem);
break;
case Req:
ProcessarReq(Mensagem);
break;
}
if (Mensagem.idMensagem > 0) {
EnviarDadosSerial(Mod_ID, MontarProtocoloMensagemRecebida(Mensagem.idMensagem));
}
}
void ProcessarChk(ProtocoloSerial Mensagem) {
Verificando = true;
mqttService.EnviarDados(Mod_ID, MontarProtocoloVerificacao(D_Code, VERSION, Conectado));
delay(2000);
Verificando = false;
}
void ProcessarCfg(ProtocoloSerial Mensagem) {
std::vector<String> Partes = SplitString(Mensagem.protocolo, SplitParams);
T_Code Tipo = (T_Code)(Partes[0].toInt());
if (Tipo == Mod) {
bool Conectar = Partes[1] == "1";
_TaxaAmostragem = Partes[2].toInt();
RequisitarDados = Partes[3] == "1";
vTaskDelay(pdMS_TO_TICKS(100));
Conectado = Conectar;
Verificando = false;
enviarDadosSensores();
if (enviarStatus) {
qtdEnviosStatus = 0;
}
else {
S_Code componente = (S_Code)Partes[1].toInt();
String config = Partes[2];
qtdEnviosStatus++;
}
}
}
void EnviarDadosCAN(std::vector<uint8_t> data) {
if (data.size() > 0) {
canService.enviarMensagem(data);
}
}
void ProcessarFrameCAN(std::vector<uint8_t> data) {
if (data.size() < 1) return;
F_Code funcao = (F_Code)data[0];
switch (funcao) {
case ChkTx: ProcessarChk(); break;
case ReqTx: ProcessarReq(); break;
case CmdTx: ProcessarCmd(data); break;
case CfgTx: ProcessarCfg(data); break;
}
}
void ProcessarChk() {
std::vector<uint8_t> data = canService.MontarFrameChk(D_Code, Conectado, VERSION);
EnviarDadosCAN(data);
}
void ProcessarReq() {
enviarDadosSensores();
}
void ProcessarCfg(std::vector<uint8_t> data) {
if (data.size() < 4) return;
std::vector<uint8_t> _chkRx;
uint8_t id = data[1];
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[2];
S_Code componente = (S_Code)data[3];
switch (componente) {
case sBIC: {
Rele::InicializarLista(listaBicos, config, Mod_ID);
case sMOD: {
switch (posicao) {
case CanMessagePosicaoDados::Config1: {
if (data.size() < 7) return;
bool conectar = data[4] == 1;
int taxa = data[5] * 10;
bool requisitar = data[6] == 1;
_TaxaAmostragem = taxa;
RequisitarDados = requisitar;
Conectar = conectar;
break;
}
case sBMB: {
BombaPressurizadora::InicializarLista(listaBombas, config, Mod_ID, listaSensoresPressao);
case CanMessagePosicaoDados::Config2: {
if (data.size() < 6) return;
int pinoSDA = data[4];
int pinoSCL = data[5];
if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) {
I2CService::DefinirPinos(pinoSDA, pinoSCL);
I2CService::IniciarI2C();
}
vTaskDelay(pdMS_TO_TICKS(100));
Conectado = Conectar;
_chkRx = canService.MontarFrameChk(D_Code, Conectado, VERSION);
LimparListasComponentes();
PrintTela("Configuracao do modulo concluida");
break;
}
}
break;
}
case sBIC: {
_chkRx = Rele::ConfigurarRele(listaBicos, data, Mod_ID);
break;
}
case sFLX: {
SensorFluxo::InicializarLista(listaSensoresFluxo, config, Mod_ID);
break;
}
case sMAS: {
SensorMassa::InicializarLista(listaSensoresMassa, config, Mod_ID);
_chkRx = SensorFluxo::ConfigurarSensor(listaSensoresFluxo, data, Mod_ID);
break;
}
case sPRS: {
SensorPressao::InicializarLista(listaSensoresPressao, config, Mod_ID);
_chkRx = SensorPressao::ConfigurarSensor(listaSensoresPressao, data, Mod_ID);
break;
}
}
}
}
void ProcessarCmd(ProtocoloSerial Mensagem) {
std::vector<String> Partes = SplitString(Mensagem.protocolo, SplitParams);
String ID = Partes[0];
S_Code componente = (S_Code)Partes[1].toInt();
switch (componente) {
case sBIC: {
for (auto* _rele : listaBicos) {
if (_rele->_ID == ID) {
Estado novoEstado = (Estado)Partes[2].toInt();
_rele->AtualizarStatus(novoEstado);
}
}
case sMAS: {
_chkRx = SensorMassa::ConfigurarSensor(listaSensoresMassa, data, Mod_ID);
break;
}
case sBMB: {
for (auto* _bomba : listaBombas) {
if (_bomba->_ID == ID) {
_bomba->_EstadoControle = (Estado)(Partes[2].toInt());
_bomba->_PressaoSP = Partes[3].toDouble();
_bomba->AlterarStatusBomba();
}
}
_chkRx = BombaPressurizadora::ConfigurarBomba(listaBombas, data, Mod_ID, listaSensoresPressao);
break;
}
}
EnviarDadosCAN(_chkRx);
}
void ProcessarReq(ProtocoloSerial Mensagem) {
enviarDadosSensores();
void ProcessarCmd(std::vector<uint8_t> data) {
if (data.size() < 4) return;
uint8_t id = data[1];
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[2];
S_Code componente = DetectarComponente(id);
switch (componente) {
case sBIC: {
Rele::ComandarRele(listaBicos, data, id);
break;
}
case sBMB: {
BombaPressurizadora::ComandarBomba(listaBombas, data, id);
break;
}
default:
break;
}
}
void LimparListasComponentes() {
for (auto* bico : listaBicos) {
bico->Desligar();
PrintTela("Bico " + bico->_ID + " desligado.");
delete bico;
}
listaBicos.clear();
for (auto* bomba : listaBombas) {
bomba->Desligar();
PrintTela("Bomba Pressurizadora " + bomba->_ID + " desligada.");
delete bomba;
}
listaBombas.clear();
for (auto* sensor : listaSensoresFluxo) {
sensor->Desligar();
PrintTela("Sensor de Fluxo " + sensor->_ID + " desligado.");
delete sensor;
}
listaSensoresFluxo.clear();
for (auto* sensor : listaSensoresMassa) {
sensor->Desligar();
PrintTela("Sensor de Massa " + sensor->_ID + " desligado.");
delete sensor;
}
listaSensoresMassa.clear();
for (auto* sensor : listaSensoresPressao) {
sensor->Desligar();
PrintTela("Sensor de Pressao " + sensor->_ID + " desligado.");
delete sensor;
}
listaSensoresPressao.clear();
}
S_Code DetectarComponente(uint8_t idNum) {
if (idNum == canService.ID_Num_sMOD) return S_Code::sMOD;
for (auto* s : listaBicos) {
if (s->ID_Num == idNum) return S_Code::sBIC;
}
for (auto* s : listaBombas) {
if (s->ID_Num == idNum) return S_Code::sBMB;
}
for (auto* s : listaSensoresFluxo) {
if (s->ID_Num == idNum) return S_Code::sFLX;
}
for (auto* s : listaSensoresMassa) {
if (s->ID_Num == idNum) return S_Code::sMAS;
}
for (auto* s : listaSensoresPressao) {
if (s->ID_Num == idNum) return S_Code::sPRS;
}
return S_Code::sVZO;
}

View File

@ -1,18 +1,16 @@
#include "SerialService.h"
#include "SensorPressaoModel.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include "SensorPressaoModel.h"
#include <PID_v1.h>
#ifndef BombaPressurizadoraModel
#define BombaPressurizadoraModel
class BombaPressurizadora {
class BombaPressurizadora : public ComponenteCAN {
public:
static std::vector<uint8_t> ConfigurarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, const String& Mod_ID, std::vector<SensorPressao*>& sensoresPressao);
static void ComandarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, uint8_t& id);
BombaPressurizadora(String _modID, String _id) {
Mod_ID = _modID;
_ID = _id;
@ -100,7 +98,7 @@ class BombaPressurizadora {
delete _PID;
_PID = nullptr;
delete sensorPressao;
//delete sensorPressao;
sensorPressao = nullptr;
// Redefinir as configurações para os valores iniciais
@ -175,21 +173,7 @@ class BombaPressurizadora {
return data;
}
private:
void AtualizarLeitura() {
if (Iniciado) {
EstadoLeitura = _pinoEN.get() == 1 ? Ligado : Desligado;
PercentualPotenciaLeitura = (PotenciaLeitura / RampaMax) * 100;
}
}
};
std::vector<uint8_t> BombaPressurizadora::ConfigurarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, const String& Mod_ID, std::vector<SensorPressao*>& sensoresPressao) {
static std::vector<uint8_t> ConfigurarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, const String& Mod_ID, std::vector<SensorPressao*>& sensoresPressao) {
std::vector<uint8_t> status;
if (data.size() < 2) return status;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
@ -265,20 +249,38 @@ std::vector<uint8_t> BombaPressurizadora::ConfigurarBomba(std::vector<BombaPress
}
}
return status;
}
}
void BombaPressurizadora::ComandarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, uint8_t& id) {
if (data.size() < 5) return;
Estado novoEstado = (Estado)data[3];
int pressao = (int)data[4];
static void ComandarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data) {
if (data.size() < 4) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t idNum = data[1];
Estado novoEstado = (Estado)data[2];
int pressao = (int)data[3];
for (auto* _bomba : lista) {
if (_bomba->ID_Num == id) {
if (_bomba->ID_Num == idNum) {
_bomba->_EstadoControle = novoEstado;
_bomba->_PressaoSP = (double)pressao;
_bomba->AlterarStatusBomba();
}
}
}
}
private:
void AtualizarLeitura() {
if (Iniciado) {
EstadoLeitura = _pinoEN.get() == 1 ? Ligado : Desligado;
PercentualPotenciaLeitura = (PotenciaLeitura / RampaMax) * 100;
}
}
};
#endif

View File

@ -0,0 +1,46 @@
#include "Enuns.h"
#ifndef ICOMPONENTECAN_H
#define ICOMPONENTECAN_H
class ComponenteCAN {
public:
int ID_Num = 0;
bool Iniciado = false;
virtual void RequisitarDados() = 0;
virtual std::vector<uint8_t> MontarMensagemCAN(CanMessagePosicaoDados posicao) = 0;
template<typename T>
static void ProcessarComponentesCAN(
const std::vector<T*>& listaComponentes,
std::vector<CanMessagePosicaoDados> posicoes,
bool todosIDs,
int id_num,
bool enviarStatus,
bool todosDados,
CanMessagePosicaoDados posicao,
std::function<void(const std::vector<uint8_t>&)> enviarDadosFunc
) {
for (auto* componente : listaComponentes) {
if (componente != nullptr && (todosIDs || componente->ID_Num == id_num)) {
componente->RequisitarDados();
if (enviarStatus) {
enviarDadosFunc(componente->MontarMensagemCAN(CanMessagePosicaoDados::Status));
}
if (componente->Iniciado) {
if (todosDados) {
for (auto p : posicoes) {
if (p == CanMessagePosicaoDados::Status) continue; // Evita enviar status duas vezes
enviarDadosFunc(componente->MontarMensagemCAN(p));
}
} else {
enviarDadosFunc(componente->MontarMensagemCAN(posicao));
}
}
}
}
}
};
#endif

View File

@ -1,11 +1,12 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#ifndef ReleModel
#define ReleModel
class Rele {
class Rele : public ComponenteCAN {
public:
Rele(String _modID, String _id) {

View File

@ -4,8 +4,9 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
class SensorChuva {
class SensorChuva : public ComponenteCAN {
public:
SensorChuva(String _modID, String _id) {

View File

@ -4,13 +4,14 @@
#include "SerialService.h"
#include "I2CService.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include <Wire.h>
#include <vector>
#include <Adafruit_INA219.h>
#include <Adafruit_INA228.h>
#include <SimpleKalmanFilter.h>
class SensorCorrente {
class SensorCorrente : public ComponenteCAN {
public:
SensorCorrente(String _modID, String _id) {
Mod_ID = _modID;

View File

@ -1,14 +1,13 @@
#include "SerialService.h"
#include "Pinout.h"
#include "IComponenteCAN.h"
#ifndef SensorFluxoModel
#define SensorFluxoModel
class SensorFluxo {
class SensorFluxo : public ComponenteCAN {
public:
static std::vector<uint8_t> ConfigurarSensor(std::vector<SensorFluxo*>& lista, std::vector<uint8_t>& data, const String& Mod_ID);
SensorFluxo(String _modID, String _id) {
Mod_ID = _modID;
_ID = _id;
@ -110,6 +109,51 @@ class SensorFluxo {
return data;
}
static std::vector<uint8_t> ConfigurarSensor(std::vector<SensorFluxo*>& lista, std::vector<uint8_t>& data, const String& Mod_ID) {
std::vector<uint8_t> status;
if (data.size() < 2) return status;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t idNum = data[1];
auto it = std::find_if(lista.begin(), lista.end(), [idNum](SensorFluxo* s) { return s->ID_Num == idNum; });
bool jaExiste = it != lista.end();
SensorFluxo* sensor;
switch (posicao) {
case CanMessagePosicaoDados::Config1: {
if (data.size() < 5) return status;
bool conectar = data[3] == 1;
int pino = data[4];
if (conectar) {
if (!jaExiste) {
sensor = new SensorFluxo(Mod_ID, "sFLX_" + String(idNum));
}
else {
sensor = *it;
}
if (!sensor->Iniciado) {
sensor->ID_Num = idNum;
sensor->_pino = PinoModel(pino, CONTROLADOR, _INPUT, DIGITAL);
sensor->Inicializar();
if (!jaExiste) {
lista.push_back(sensor);
PrintTela("Sensor de Fluxo adicionado via CAN: sFLX_" + String(idNum));
}
}
status = sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status);
} else {
if (jaExiste) {
sensor = *it;
sensor->Desligar();
status = sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status);
delete sensor;
lista.erase(it);
PrintTela("Sensor de Fluxo removido via CAN: sFLX_" + String(idNum));
}
}
break;
}
}
return status;
}
private:
@ -154,51 +198,7 @@ class SensorFluxo {
};
std::vector<uint8_t> SensorFluxo::ConfigurarSensor(std::vector<SensorFluxo*>& lista, std::vector<uint8_t>& data, const String& Mod_ID) {
std::vector<uint8_t> status;
if (data.size() < 2) return status;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[2];
uint8_t idNum = data[1];
auto it = std::find_if(lista.begin(), lista.end(), [idNum](SensorFluxo* s) { return s->ID_Num == idNum; });
bool jaExiste = it != lista.end();
SensorFluxo* sensor;
switch (posicao) {
case CanMessagePosicaoDados::Config1: {
if (data.size() < 5) return status;
bool conectar = data[3] == 1;
int pino = data[4];
if (conectar) {
if (!jaExiste) {
sensor = new SensorFluxo(Mod_ID, "sFLX_" + String(idNum));
}
else {
sensor = *it;
}
if (!sensor->Iniciado) {
sensor->ID_Num = idNum;
sensor->_pino = PinoModel(pino, CONTROLADOR, _INPUT, DIGITAL);
sensor->Inicializar();
if (!jaExiste) {
lista.push_back(sensor);
PrintTela("Sensor de Fluxo adicionado via CAN: sFLX_" + String(idNum));
}
}
status = sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status);
} else {
if (jaExiste) {
sensor = *it;
sensor->Desligar();
status = sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status);
delete sensor;
lista.erase(it);
PrintTela("Sensor de Fluxo removido via CAN: sFLX_" + String(idNum));
}
}
break;
}
}
return status;
}
#endif

View File

@ -4,8 +4,9 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
class SensorGas {
class SensorGas : public ComponenteCAN {
public:
enum class TipoSensorGas : uint8_t {
MQ2 = 0,

View File

@ -3,12 +3,13 @@
#include "SerialService.h"
#include "I2CService.h"
#include "IComponenteCAN.h"
#include <MPU9250_asukiaaa.h>
#include <Adafruit_BMP280.h>
#include <MahonyAHRS.h>
#include <Wire.h>
class SensorIMU {
class SensorIMU : public ComponenteCAN {
public:
String Mod_ID;

View File

@ -4,10 +4,11 @@
#include "SerialService.h"
#include "I2CService.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include <vector>
#include <Adafruit_TSL2591.h>
class SensorLuminosidade {
class SensorLuminosidade : public ComponenteCAN {
public:
SensorLuminosidade(String _modID, String _id) {
Mod_ID = _modID;

View File

@ -4,8 +4,9 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
class SensorLuzUV {
class SensorLuzUV : public ComponenteCAN {
public:
SensorLuzUV(String _modID, String _id) {

View File

@ -1,17 +1,16 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include "HX711.h"
#include <SimpleKalmanFilter.h>
#ifndef SensorMassaModel
#define SensorMassaModel
class SensorMassa {
class SensorMassa : public ComponenteCAN {
public:
static std::vector<uint8_t> ConfigurarSensor(std::vector<SensorMassa*>& lista, std::vector<uint8_t>& data, const String& Mod_ID);
SensorMassa(String _modID, String _id) {
Mod_ID = _modID;
_ID = _id;
@ -93,31 +92,7 @@ class SensorMassa {
return data;
}
private:
void AferirMassa() {
if (Iniciado) {
float leitura = balanca.get_units(5);
leituraMassa = filtro.updateEstimate(leitura);
Massa = CalcularMassa(leituraMassa);
}
}
float CalcularMassa(float _leitura) {
double leituraMassa = _leitura * -1;
leituraMassa += _Offset;
float FatorLeitura = _MassaRef / _MassaLeituraRef;
float massa = FatorLeitura * leituraMassa;
return massa;
}
};
std::vector<uint8_t> SensorMassa::ConfigurarSensor(std::vector<SensorMassa*>& lista, std::vector<uint8_t>& data, const String& Mod_ID) {
static std::vector<uint8_t> ConfigurarSensor(std::vector<SensorMassa*>& lista, std::vector<uint8_t>& data, const String& Mod_ID) {
std::vector<uint8_t> status;
if (data.size() < 2) return status;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
@ -166,6 +141,29 @@ std::vector<uint8_t> SensorMassa::ConfigurarSensor(std::vector<SensorMassa*>& li
}
}
return status;
}
}
private:
void AferirMassa() {
if (Iniciado) {
float leitura = balanca.get_units(5);
leituraMassa = filtro.updateEstimate(leitura);
Massa = CalcularMassa(leituraMassa);
}
}
float CalcularMassa(float _leitura) {
double leituraMassa = _leitura * -1;
leituraMassa += _Offset;
float FatorLeitura = _MassaRef / _MassaLeituraRef;
float massa = FatorLeitura * leituraMassa;
return massa;
}
};
#endif

View File

@ -1,11 +1,12 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#ifndef SensorNivelModel
#define SensorNivelModel
class SensorNivel {
class SensorNivel : public ComponenteCAN {
public:
SensorNivel(String _modID, String _id, int _taxaAmostragem = 2000) {

View File

@ -2,12 +2,13 @@
#include "ReleModel.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include <SimpleKalmanFilter.h>
#ifndef SensorPotenciometroModel
#define SensorPotenciometroModel
class SensorPotenciometro {
class SensorPotenciometro : public ComponenteCAN {
public:
static void InicializarLista(std::vector<SensorPotenciometro*>& lista, const String& parametros, const String& Mod_ID, std::vector<Rele*>& listaReles);

View File

@ -1,16 +1,15 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include <SimpleKalmanFilter.h>
#ifndef SensorPressaoModel
#define SensorPressaoModel
class SensorPressao {
class SensorPressao : public ComponenteCAN {
public:
static std::vector<uint8_t> ConfigurarSensor(std::vector<SensorPressao*>& lista, std::vector<uint8_t>& data, const String& Mod_ID);
SensorPressao(String _modID, String _id) {
Mod_ID = _modID;
_ID = _id;
@ -89,23 +88,7 @@ class SensorPressao {
return data;
}
private:
void AferirPressao() {
if (Iniciado) {
leitura = _pino.get();
double leituraPressao = filtro.updateEstimate(leitura);
double tensao = fmap(leituraPressao, 0.0, 4095.0, 0.0, 3300.0) / 1000.0;
Pressao = fmap(tensao, _Vmin, _Vmax, 0.0, _Pmax);
}
}
};
std::vector<uint8_t> SensorPressao::ConfigurarSensor(std::vector<SensorPressao*>& lista, std::vector<uint8_t>& data, const String& Mod_ID) {
static std::vector<uint8_t> ConfigurarSensor(std::vector<SensorPressao*>& lista, std::vector<uint8_t>& data, const String& Mod_ID) {
std::vector<uint8_t> status;
if (data.size() < 2) return status;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
@ -149,6 +132,22 @@ std::vector<uint8_t> SensorPressao::ConfigurarSensor(std::vector<SensorPressao*>
}
}
return status;
}
}
private:
void AferirPressao() {
if (Iniciado) {
leitura = _pino.get();
double leituraPressao = filtro.updateEstimate(leitura);
double tensao = fmap(leituraPressao, 0.0, 4095.0, 0.0, 3300.0) / 1000.0;
Pressao = fmap(tensao, _Vmin, _Vmax, 0.0, _Pmax);
}
}
};
#endif

View File

@ -4,11 +4,12 @@
#include "SerialService.h"
#include "I2CService.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include <vector>
#include "ScioSense_ENS160.h"
#include <Adafruit_AHTX0.h>
class SensorQualidadeAr {
class SensorQualidadeAr : public ComponenteCAN {
public:
SensorQualidadeAr(String _modID, String _id) {
Mod_ID = _modID;

View File

@ -1,11 +1,12 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#ifndef SensorSonarModel
#define SensorSonarModel
class SensorSonar {
class SensorSonar : public ComponenteCAN {
public:
SensorSonar(String _modID, String _id) {

View File

@ -1,12 +1,13 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include <SimpleKalmanFilter.h>
#ifndef SensorTemperaturaModel
#define SensorTemperaturaModel
class SensorTemperatura {
class SensorTemperatura : public ComponenteCAN {
public:
SensorTemperatura(String _modID, String _id) {

View File

@ -4,10 +4,11 @@
#include "SerialService.h"
#include "I2CService.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#include <vector>
#include <Adafruit_SHT4x.h>
class SensorTemperaturaSHT {
class SensorTemperaturaSHT : public ComponenteCAN {
public:
SensorTemperaturaSHT(String _modID, String _id) {
Mod_ID = _modID;

Some files were not shown because too many files have changed in this diff Show More