diff --git a/AgroBase/AgroBase/AgroBase.csproj b/AgroBase/AgroBase/AgroBase.csproj
index 3d493e77c..313ddf3dd 100644
--- a/AgroBase/AgroBase/AgroBase.csproj
+++ b/AgroBase/AgroBase/AgroBase.csproj
@@ -519,6 +519,7 @@
Form
+
@@ -576,6 +577,7 @@
+
Form
diff --git a/AgroBase/AgroBase/Forms/frmAcompanhamento.Designer.cs b/AgroBase/AgroBase/Forms/frmAcompanhamento.Designer.cs
index 765378384..e9c88d593 100644
--- a/AgroBase/AgroBase/Forms/frmAcompanhamento.Designer.cs
+++ b/AgroBase/AgroBase/Forms/frmAcompanhamento.Designer.cs
@@ -43,6 +43,7 @@ namespace AgroBase.Forms
System.Windows.Forms.DataVisualization.Charting.Series series4 = new System.Windows.Forms.DataVisualization.Charting.Series();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmAcompanhamento));
this.pnlFundo = new System.Windows.Forms.Panel();
+ this.lblSen_Latencia = new System.Windows.Forms.Label();
this.lblB19V = new System.Windows.Forms.Label();
this.lblB24V = new System.Windows.Forms.Label();
this.lblGPSDetalhes = new System.Windows.Forms.Label();
@@ -126,7 +127,7 @@ namespace AgroBase.Forms
this.lblEFA_SP = new System.Windows.Forms.Label();
this.lblM_EF = new System.Windows.Forms.Label();
this.picEF = new System.Windows.Forms.PictureBox();
- this.lblSen_Latencia = new System.Windows.Forms.Label();
+ this.lblVBat = new System.Windows.Forms.Label();
this.pnlFundo.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.chartET)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.chartDT)).BeginInit();
@@ -143,6 +144,7 @@ namespace AgroBase.Forms
//
this.pnlFundo.AutoScroll = true;
this.pnlFundo.BackColor = System.Drawing.Color.White;
+ this.pnlFundo.Controls.Add(this.lblVBat);
this.pnlFundo.Controls.Add(this.lblSen_Latencia);
this.pnlFundo.Controls.Add(this.lblB19V);
this.pnlFundo.Controls.Add(this.lblB24V);
@@ -234,6 +236,17 @@ namespace AgroBase.Forms
this.pnlFundo.Size = new System.Drawing.Size(1473, 811);
this.pnlFundo.TabIndex = 0;
//
+ // lblSen_Latencia
+ //
+ this.lblSen_Latencia.AutoSize = true;
+ this.lblSen_Latencia.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblSen_Latencia.Location = new System.Drawing.Point(656, 608);
+ this.lblSen_Latencia.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.lblSen_Latencia.Name = "lblSen_Latencia";
+ this.lblSen_Latencia.Size = new System.Drawing.Size(87, 12);
+ this.lblSen_Latencia.TabIndex = 193;
+ this.lblSen_Latencia.Text = "Latencia Loop: 0 ms";
+ //
// lblB19V
//
this.lblB19V.AutoSize = true;
@@ -1108,16 +1121,16 @@ namespace AgroBase.Forms
this.picEF.TabIndex = 90;
this.picEF.TabStop = false;
//
- // lblSen_Latencia
+ // lblVBat
//
- this.lblSen_Latencia.AutoSize = true;
- this.lblSen_Latencia.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.lblSen_Latencia.Location = new System.Drawing.Point(656, 608);
- this.lblSen_Latencia.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
- this.lblSen_Latencia.Name = "lblSen_Latencia";
- this.lblSen_Latencia.Size = new System.Drawing.Size(87, 12);
- this.lblSen_Latencia.TabIndex = 193;
- this.lblSen_Latencia.Text = "Latencia Loop: 0 ms";
+ this.lblVBat.AutoSize = true;
+ this.lblVBat.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.lblVBat.Location = new System.Drawing.Point(656, 739);
+ this.lblVBat.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.lblVBat.Name = "lblVBat";
+ this.lblVBat.Size = new System.Drawing.Size(149, 12);
+ this.lblVBat.TabIndex = 194;
+ this.lblVBat.Text = "Bateria: 0,00V 0,00A 0,00% 0,00ºC";
//
// frmAcompanhamento
//
@@ -1234,5 +1247,6 @@ namespace AgroBase.Forms
public System.Windows.Forms.Label lblB24V;
public System.Windows.Forms.Label lblB19V;
public System.Windows.Forms.Label lblSen_Latencia;
+ public System.Windows.Forms.Label lblVBat;
}
}
\ No newline at end of file
diff --git a/AgroBase/AgroBase/Forms/frmAcompanhamento.cs b/AgroBase/AgroBase/Forms/frmAcompanhamento.cs
index c44f836cc..44aeb4684 100644
--- a/AgroBase/AgroBase/Forms/frmAcompanhamento.cs
+++ b/AgroBase/AgroBase/Forms/frmAcompanhamento.cs
@@ -83,6 +83,12 @@ namespace AgroBase.Forms
lblSen_Latencia.Text = $"Latencia de Loop: {Variaveis.OperacaoEmAndamento.DispSen.Dados?.DadosLeitura?.LatenciaLoop ?? 0} ms";
tmrAtualizacao.SetInterval(500);
+
+ if (DalyBMSService.Iniciado)
+ {
+ var Bat = DalyBMSService.DadosLeitura;
+ lblVBat.Text = $"Bateria: {Bat.Pack.TensaoTotal_V:0.00}V {Bat.Pack.Corrente_A:0.00}A {Bat.Pack.SOC_percent:0.00}% {Bat.TemperaturaMax:0.00}ºC";
+ }
}
private void AtualizarDadosSensorCorrente(string id, Label lbl)
diff --git a/AgroBase/AgroBase/Models/DalyBMSModel.cs b/AgroBase/AgroBase/Models/DalyBMSModel.cs
new file mode 100644
index 000000000..519dcc201
--- /dev/null
+++ b/AgroBase/AgroBase/Models/DalyBMSModel.cs
@@ -0,0 +1,238 @@
+using AgroBase.Services;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AgroBase.Models
+{
+ ///
+ /// Snapshot do estado atual do Daly BMS, conforme leituras via CAN.
+ ///
+ public class DalyBmsModel
+ {
+ // ===== Meta / estado interno =====
+ public DateTime Momento { get; set; } = DateTime.UtcNow;
+ public bool Iniciado { get; set; }
+ public DateTime? UltimoComandoRecebido { get; set; }
+
+ ///
+ /// Frames brutos por DataID (0x90..0x98). Útil para debug / logs.
+ /// Key = DataID (ex: 0x90), Value = payload de 8 bytes.
+ ///
+ public Dictionary LeiturasBrutas { get; set; } = new Dictionary();
+
+ public double TensaoMax { get; set; }
+ public double TensaoMin { get; set; }
+ public double TemperaturaMax { get; set; }
+ public double TemperaturaMin { get; set; }
+
+ // ===== Dados principais =====
+
+ ///
+ /// Resumo do pack: tensão total, corrente, SOC, MOS, contagem de células, etc.
+ /// (DataIDs: 0x90, 0x93, 0x94, e futuramente outros)
+ ///
+ public DalyPackStatus Pack { get; set; } = new DalyPackStatus();
+
+ ///
+ /// Tensões de cada célula, além de info de Vmax / Vmin.
+ /// (DataIDs: 0x91 e 0x95)
+ ///
+ public List Celulas { get; set; } = new List();
+
+ ///
+ /// Temperaturas individuais de NTCs / sensores, mais T_max / T_min.
+ /// (DataIDs: 0x92 e 0x96)
+ ///
+ public List Temperaturas { get; set; } = new List();
+
+ ///
+ /// Estado de balanceamento de cada célula.
+ /// (DataID: 0x97)
+ ///
+ public DalyBalanceStatus Balanceamento { get; set; } = new DalyBalanceStatus();
+
+ ///
+ /// Alarmes / falhas ativos no momento.
+ /// (DataID: 0x98)
+ ///
+ public DalyAlarms Alarmes { get; set; } = new DalyAlarms();
+ }
+
+ // ===================== PACK (0x90, 0x93, 0x94, futuros) =====================
+
+ public class DalyPackStatus
+ {
+ ///
+ /// Tensão total do pack (V) – cumulative voltage (0x90).
+ ///
+ public double TensaoTotal_V { get; set; }
+
+ ///
+ /// Tensão medida / de amostragem (V) – gather voltage (0x90).
+ ///
+ public double TensaoMedida_V { get; set; }
+
+ ///
+ /// Corrente do pack (A). Positivo = carga, negativo = descarga. (0x90)
+ ///
+ public double Corrente_A { get; set; }
+
+ ///
+ /// State of Charge (%), com resolução de 0,1% (0x90).
+ ///
+ public double SOC_percent { get; set; }
+
+ ///
+ /// Número de células em série (0x94).
+ ///
+ public int NumeroCelulasSerie { get; set; }
+
+ ///
+ /// Número de sensores de temperatura reportados (0x94).
+ ///
+ public int NumeroSensoresTemperatura { get; set; }
+
+ ///
+ /// Carregador conectado (0x94).
+ ///
+ public bool CarregadorConectado { get; set; }
+
+ ///
+ /// Carga / load conectado (0x94).
+ ///
+ public bool LoadConectado { get; set; }
+
+ ///
+ /// Estado geral do BMS: 0=parado, 1=carga, 2=descarga (0x93).
+ ///
+ public int EstadoGeral { get; set; }
+
+ ///
+ /// MOS de carga ON/OFF (0x93).
+ ///
+ public bool ChargeMosOn { get; set; }
+
+ ///
+ /// MOS de descarga ON/OFF (0x93).
+ ///
+ public bool DischargeMosOn { get; set; }
+
+ ///
+ /// Vida / ciclos (Life). Valor bruto 0–255 (0x93).
+ ///
+ public int CiclosAproximados { get; set; }
+
+ ///
+ /// Capacidade restante estimada (Ah) (0x93 – valor em mAh / 1000).
+ ///
+ public double CapacidadeRestante_Ah { get; set; }
+
+ // Campos futuros (caso você leia via outro DataID / RS485):
+ public double? CapacidadeNominal_Ah { get; set; }
+ public double? CapacidadeReal_Ah { get; set; }
+ public double? SOH_percent { get; set; } // state of health
+
+ ///
+ /// IO digitais brutos (bit0-3 DI, bit4-7 DO) caso queira exibir depois.
+ ///
+ public byte IoStatusRaw { get; set; }
+ }
+
+ // ===================== CÉLULAS (0x91, 0x95) =====================
+
+ public class DalyCellVoltage
+ {
+ ///
+ /// Índice da célula (1-based, igual ao protocolo).
+ ///
+ public int Index { get; set; }
+
+ ///
+ /// Tensão da célula (V).
+ ///
+ public double Tensao_V { get; set; }
+
+ ///
+ /// Flag opcional se esta é a célula de maior tensão no pack.
+ /// (derivado de 0x91)
+ ///
+ public bool EhMaxima { get; set; }
+
+ ///
+ /// Flag opcional se esta é a célula de menor tensão no pack.
+ /// (derivado de 0x91)
+ ///
+ public bool EhMinima { get; set; }
+
+ ///
+ /// Indica se está em balanceamento no momento (derivado de 0x97).
+ ///
+ public bool EmBalanceamento { get; set; }
+ }
+
+ // ===================== TEMPERATURAS (0x92, 0x96) =====================
+
+ public class DalyTemperatureSensor
+ {
+ ///
+ /// Índice do sensor (1-based, igual ao protocolo 0x96).
+ ///
+ public int Index { get; set; }
+
+ ///
+ /// Temperatura em graus Celsius.
+ ///
+ public double Temperatura_C { get; set; }
+
+ ///
+ /// Flag opcional se este é o sensor de maior temperatura.
+ /// (derivado de 0x92)
+ ///
+ public bool EhMaxima { get; set; }
+
+ ///
+ /// Flag opcional se este é o sensor de menor temperatura.
+ /// (derivado de 0x92)
+ ///
+ public bool EhMinima { get; set; }
+ }
+
+ // ===================== BALANCEAMENTO (0x97) =====================
+
+ public class DalyBalanceStatus
+ {
+ ///
+ /// Mapa de células em balanceamento:
+ /// key = índice da célula (1-based), value = true se bit ligado.
+ ///
+ public Dictionary CelulasEmBalanceamento { get; set; } = new Dictionary();
+
+ public int QtdeCelulasEmBalanceamento => CelulasEmBalanceamento.Count(kv => kv.Value);
+ }
+
+ // ===================== ALARMES / FALHAS (0x98) =====================
+
+ public class DalyAlarms
+ {
+ ///
+ /// Lista de descrições de alarmes ativos (já decodificados).
+ ///
+ public List Mensagens { get; set; } = new List();
+
+ ///
+ /// Código de falha bruto (byte 7 do frame 0x98).
+ ///
+ public byte FaultCode { get; set; }
+
+ ///
+ /// Bytes brutos 0..6 de bits de alarme, caso queira debugar depois.
+ ///
+ public byte[] AlarmBytesRaw { get; set; } = Array.Empty();
+
+ ///
+ /// True se existe qualquer alarme ou fault code != 0.
+ ///
+ public bool TemAlarme => (Mensagens?.Count > 0) || FaultCode != 0;
+ }
+}
diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs
index 2fbe3e13c..f3fe43ea5 100644
--- a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs
+++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs
@@ -2307,6 +2307,7 @@ namespace AgroBase.Models
GPSService.AtualizaDadosRedis();
LivoxManagerProcess.AtualizarLeitura();
MovimentacaoMovimentoCompensadoModel.AtualizarDados();
+ DalyBMSService.AtualizarDados();
var _Trajetoria = Variaveis.OperacaoEmAndamento.Trajetoria;
var _DispMvd = Variaveis.OperacaoEmAndamento.DispMvd;
diff --git a/AgroBase/AgroBase/Services/CANService.cs b/AgroBase/AgroBase/Services/CANService.cs
index 1b02ed51a..a7da5278e 100644
--- a/AgroBase/AgroBase/Services/CANService.cs
+++ b/AgroBase/AgroBase/Services/CANService.cs
@@ -25,14 +25,96 @@ namespace AgroBase.Services
}
}
}
+
+
+ public static uint ConverterIdCan(byte[] idBytes)
+ {
+ if (idBytes == null || idBytes.Length == 0)
+ throw new ArgumentException("ID CAN inválido.");
+
+ if (idBytes.Length > 4)
+ throw new ArgumentException("ID CAN não pode ter mais que 4 bytes.");
+
+ uint id = 0;
+
+ foreach (var b in idBytes)
+ {
+ id <<= 8;
+ id |= b;
+ }
+
+ return id;
+ }
+
+ public static byte[] ConverterIdCan(uint canId)
+ {
+ if (canId <= 0xFF)
+ return new byte[] { (byte)(canId & 0xFF) };
+
+ if (canId <= 0xFFFF)
+ return new byte[]
+ {
+ (byte)((canId >> 8) & 0xFF),
+ (byte)(canId & 0xFF)
+ };
+
+ if (canId <= 0xFFFFFF)
+ return new byte[]
+ {
+ (byte)((canId >> 16) & 0xFF),
+ (byte)((canId >> 8) & 0xFF),
+ (byte)(canId & 0xFF)
+ };
+
+ return new byte[]
+ {
+ (byte)((canId >> 24) & 0xFF),
+ (byte)((canId >> 16) & 0xFF),
+ (byte)((canId >> 8) & 0xFF),
+ (byte)(canId & 0xFF)
+ };
+ }
+
+ public static byte CalcularChecksum(uint id, byte[] data)
+ {
+ int soma = 0;
+
+ // Soma os bytes do ID (LSB primeiro, padrão mais comum)
+ soma += (byte)(id & 0xFF);
+ soma += (byte)((id >> 8) & 0xFF);
+ soma += (byte)((id >> 16) & 0xFF);
+ soma += (byte)((id >> 24) & 0xFF);
+
+ if (data != null)
+ {
+ foreach (var b in data)
+ soma += b;
+ }
+
+ return (byte)(soma & 0xFF);
+ }
+
+ public static string GerarChaveMensagem(T_Code Dispositivo, uint Id, byte[] data)
+ {
+ byte parametro = 0x00;
+
+ // Para dispositivos que não sejam MKS, usar DataTx[1] se existir
+ if (Dispositivo != T_Code.Mks && (data?.Length ?? 0) > 1)
+ {
+ parametro = data[1];
+ }
+
+ return $"{Id}_{data[0]}_{parametro}";
+ }
+
}
public class CanMessage
{
public DateTime Momento { get; set; }
public T_Code Dispositivo { get; set; }
- public byte IdTx { get; set; }
- public byte IdRx { get; set; }
+ public uint IdTx { get; set; }
+ public uint IdRx { get; set; }
public byte funcCodeTx { get; set; }
public byte funcCodeRx { get; set; }
public byte[] DataTx { get; set; }
@@ -44,6 +126,7 @@ namespace AgroBase.Services
public DateTime RespondidoEm { get; set; }
public string ChaveInterna { get; set; }
+ public bool IsExtended => IdRx > 0x7FF || IdTx > 0x7FF;
}
public class CanCommandFreqModel
@@ -156,9 +239,9 @@ namespace AgroBase.Services
public interface ICanService : IDisposable
{
bool PortaIsCan(SerialPort Porta = null);
- void RegistrarHandler(byte endereco_rx, ICanMessageHandler handler);
+ void RegistrarHandler(uint endereco_rx, ICanMessageHandler handler);
bool Inicializar(int BitRate = 250);
- void AdicionarMensagemNaFila(T_Code Dispositivo, byte idTx, byte idRx, byte funcCodeTx, byte funcCodeRx, byte[] payload = null, bool get = true);
+ void AdicionarMensagemNaFila(T_Code Dispositivo, byte[] idTx, byte[] idRx, byte funcCodeTx, byte funcCodeRx, byte[] payload = null, bool get = true);
void Fechar();
string _portName { get; set; }
bool Iniciado { get; }
diff --git a/AgroBase/AgroBase/Services/CANServiceSerial.cs b/AgroBase/AgroBase/Services/CANServiceSerial.cs
index 269d5ee56..72430e3ba 100644
--- a/AgroBase/AgroBase/Services/CANServiceSerial.cs
+++ b/AgroBase/AgroBase/Services/CANServiceSerial.cs
@@ -28,9 +28,9 @@ namespace AgroBase.Services
private AsyncTaskTimerModel tmrProcessarCAN;
private ConcurrentQueue FramesRecebidos = new ConcurrentQueue();
private StringBuilder SerialCANBuffer = new StringBuilder();
- private readonly ConcurrentDictionary _roteadores = new ConcurrentDictionary();
- private readonly ConcurrentDictionary _roteadoresRegistrados = new ConcurrentDictionary();
- private byte? _ultimoIdEnviado = null;
+ private readonly ConcurrentDictionary _roteadores = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary _roteadoresRegistrados = new ConcurrentDictionary();
+ private uint? _ultimoIdEnviado = null;
private List Mensagens = new List();
private readonly object _LockMensagens = new object();
@@ -61,9 +61,9 @@ namespace AgroBase.Services
private DateTime _ultimoErroCritico = DateTime.MinValue;
private bool DebugMode = false;
- private void MostrarLog(string message, byte id)
+ private void MostrarLog(string message, uint id)
{
- if (DebugMode && new List() { 0x11 }.Contains(id))
+ if (DebugMode) // && new List() { 0x18100140 }.Contains(id)
{
Console.WriteLine($"[CAN] {message}");
}
@@ -170,7 +170,7 @@ namespace AgroBase.Services
return Iniciado;
}
- public void RegistrarHandler(byte endereco_rx, ICanMessageHandler handler)
+ public void RegistrarHandler(uint endereco_rx, ICanMessageHandler handler)
{
_roteadoresRegistrados.TryGetValue(endereco_rx, out bool registrado);
if (!registrado)
@@ -311,109 +311,142 @@ namespace AgroBase.Services
private void ProcessarFrameCAN(string frame)
{
- // Ex: t00183301020304
- if (!frame.StartsWith("t")) return;
+ // Ex:
+ // t00183301020304
+ // T18904001801234AB
+ if (string.IsNullOrWhiteSpace(frame))
+ return;
+
+ char tipo = frame[0];
+ if (tipo != 't' && tipo != 'T')
+ return; // ignora coisas que não sejam frame CAN
+
+ bool extended = (tipo == 'T');
try
{
- if (frame.Length < 5) return;
+ // t: 3 hex de ID
+ // T: 8 hex de ID
+ int idHexLen = extended ? 8 : 3;
- int id = Convert.ToInt32(frame.Substring(1, 3), 16);
- int len = int.Parse(frame.Substring(4, 1));
+ // precisa ter pelo menos: prefixo + ID + DLC
+ if (frame.Length < 1 + idHexLen + 1)
+ return;
+
+ // pega o ID em texto
+ string idStr = frame.Substring(1, idHexLen);
+ uint id = Convert.ToUInt32(idStr, 16);
+
+ // DLC (1 dígito logo após o ID)
+ int dlcIndex = 1 + idHexLen;
+ int len = int.Parse(frame.Substring(dlcIndex, 1));
+
+ if (len < 0 || len > 8)
+ return;
+
+ // início dos dados em texto (2 chars por byte)
+ int dataStart = dlcIndex + 1;
+ int expectedLen = dataStart + len * 2;
+ if (frame.Length < expectedLen)
+ return; // frame truncado, descarta
byte[] data = new byte[len];
-
- if (data == null || data.Length == 0) return;
-
for (int i = 0; i < len; i++)
{
- data[i] = Convert.ToByte(frame.Substring(5 + i * 2, 2), 16);
+ data[i] = Convert.ToByte(frame.Substring(dataStart + i * 2, 2), 16);
}
- MostrarLog($"Processando frame: {frame}", (byte)id);
+ // Para log interno, usar o LSB do ID como "canal"
+ byte canalLog = (byte)(id & 0xFF);
+ MostrarLog($"Processando frame: {frame}", canalLog);
- _roteadores.TryGetValue((byte)id, out ICanMessageHandler handler);
+ // Agora o roteador é indexado por uint (ID CAN completo)
+ _roteadores.TryGetValue(id, out ICanMessageHandler handler);
T_Code dispositivo = handler?.Dispositivo ?? T_Code.Vzo;
- byte fCodeRx = data.Length > 0 ? data[0] : (byte)0x00;
- byte parametroRx = data.Length > 1 ? data[1] : (byte)0x00;
- string chave = GerarChaveMensagem(dispositivo, (byte)id, data);
+ bool db = dispositivo == T_Code.Bat;
+
+ // Para dispositivos antigos, isso ainda faz sentido.
+ // Para o BMS, o handler simplesmente ignora funcCodeRx / parametroRx.
+ byte fCodeRx = db ? (byte)DalyBMSService.GetDataId(id) : data.Length > 0 ? data[0] : (byte)0x00;
+ byte parametroRx = db ? (byte)0x00 : data.Length > 1 ? data[1] : (byte)0x00;
+
+ // IMPORTANTE: idealmente GerarChaveMensagem aceita uint agora.
+ // Se hoje ela aceita byte, vale criar uma sobrecarga.
+ string chave = CanManager.GerarChaveMensagem(dispositivo, id, data);
CanMessage mensagem = null;
+
lock (_LockMensagens)
{
- mensagem = Mensagens.FirstOrDefault(x => x.Enviado && !x.Respondido && x.Dispositivo == dispositivo && x.IdRx == id && x.DataTx[1] == data[1]);
+ // Aqui você tinha:
+ // x.IdRx == id && x.DataTx[1] == data[1]
+ // Isso é muito específico do protocolo antigo.
+ // Pro BMS, o matching pode ser só por IdRx e Dispositivo.
+ mensagem = Mensagens.FirstOrDefault(x =>
+ x.Enviado &&
+ !x.Respondido &&
+ x.Dispositivo == dispositivo &&
+ x.IdRx == id &&
+ (db ? true : x.DataTx[1] == data[1]) // basteria nao checa o funccode
+ );
}
+
if (mensagem == null)
{
- mensagem = new CanMessage { Dispositivo = dispositivo, IdTx = (byte)id, IdRx = (byte)id, funcCodeRx = fCodeRx, DataRx = data, ChaveInterna = chave };
+ mensagem = new CanMessage
+ {
+ Dispositivo = dispositivo,
+ IdTx = id,
+ IdRx = id,
+ funcCodeRx = fCodeRx,
+ DataRx = data,
+ ChaveInterna = chave
+ };
}
- mensagem.DataRx = data;
+ else
+ {
+ mensagem.DataRx = data;
+ }
+
mensagem.Respondido = true;
mensagem.RespondidoEm = DateTime.Now;
- if ((handler?.Dispositivo ?? T_Code.Vzo) != T_Code.Vzo)
+ if (dispositivo != T_Code.Vzo)
{
handler.ProcessarMensagem(mensagem);
}
else
{
- MostrarLog($"Roteador não registrado! ID_Num não tratado: 0x{id:X2}, fCodeRx: 0x{fCodeRx:X2}, frame: {frame}", (byte)id);
+ MostrarLog(
+ $"Roteador não registrado! ID CAN não tratado: 0x{id:X8}, fCodeRx: 0x{fCodeRx:X2}, frame: {frame}",
+ canalLog
+ );
}
-
-
-
-
- /*byte[] data = new byte[len];
- for (int i = 0; i < len; i++)
- {
- data[i] = Convert.ToByte(frame.Substring(5 + i * 2, 2), 16);
- }
-
- byte funcCodeRx = data[0];
- var mensagem = new CanMessage();
-
- lock (Mensagens)
- {
- mensagem = Mensagens.Where(x => x.IdTx == id).OrderBy(x => x.EnviadoEm).FirstOrDefault(x => x.Enviado && !x.Respondido && x.funcCodeRx == funcCodeRx);
- }
-
- if (mensagem == null)
- {
- mensagem = new CanMessage { IdTx = (byte)id, DataRx = data };
- }
-
- mensagem.DataRx = data;
- mensagem.Respondido = true;
- mensagem.RespondidoEm = DateTime.Now;
-
- if (_roteadores.TryGetValue(mensagem.IdTx, out var handler))
- {
- handler.ProcessarMensagem(mensagem);
- }
- else
- {
- Console.WriteLine($"[CAN] ID_Num não tratado: 0x{funcCodeRx:X2}");
- }*/
}
catch (Exception ex)
{
- Console.WriteLine($"[CAN] Erro ao processar frame: {ex.Message}");
+ Console.WriteLine($"[CAN] Erro ao processar frame: {ex.Message} (frame={frame})");
}
}
- public void AdicionarMensagemNaFila(T_Code Dispositivo, byte idTx, byte idRx, byte funcCodeTx, byte funcCodeRx, byte[] payload = null, bool get = true)
+ public void AdicionarMensagemNaFila(T_Code Dispositivo, byte[] _idTx, byte[] _idRx, byte funcCodeTx, byte funcCodeRx, byte[] payload = null, bool get = true)
{
if (_PortaCAN?.IsOpen != true) return;
- var dados = new List() { funcCodeTx };
+ uint idTx = CanManager.ConverterIdCan(_idTx);
+ uint idRx = CanManager.ConverterIdCan(_idRx);
+
+ var dados = new List();
+ if (Dispositivo != T_Code.Bat)
+ dados.Add(funcCodeTx);
if (payload != null)
dados.AddRange(payload);
if (Dispositivo == T_Code.Mks)
{
- byte crc = CalcularChecksum(idTx, dados.ToArray());
+ byte crc = CanManager.CalcularChecksum(idTx, dados.ToArray());
dados.Add(crc);
}
@@ -427,7 +460,7 @@ namespace AgroBase.Services
funcCodeRx = funcCodeRx,
DataTx = dados.ToArray(),
ComResposta = get,
- ChaveInterna = GerarChaveMensagem(Dispositivo, idRx, dados.ToArray())
+ ChaveInterna = CanManager.GerarChaveMensagem(Dispositivo, idRx, dados.ToArray())
};
bool mensagemNaFila = false;
@@ -482,7 +515,7 @@ namespace AgroBase.Services
.OrderBy(x => x)
.ToList();
- byte proximoId;
+ uint proximoId;
if (!_ultimoIdEnviado.HasValue || !idsDisponiveis.Contains(_ultimoIdEnviado.Value))
{
@@ -541,13 +574,34 @@ namespace AgroBase.Services
private string CriarFrame(CanMessage msg)
{
- string frame = $"t{msg.IdTx:X3}{msg.DataTx.Length}";
- foreach (byte b in msg.DataTx)
- frame += b.ToString("X2");
+ bool isExtended = msg.IdTx > 0x7FF;
- frame += "\r";
+ // Prefixo SLCAN
+ char tipo = isExtended ? 'T' : 't';
- return frame;
+ // ID em hex com largura correta
+ string idHex = isExtended
+ ? msg.IdTx.ToString("X8") // 29 bits → 8 hex
+ : msg.IdTx.ToString("X3"); // 11 bits → 3 hex
+
+ // DLC
+ int dlc = msg.DataTx?.Length ?? 0;
+
+ var sb = new StringBuilder();
+
+ sb.Append(tipo);
+ sb.Append(idHex);
+ sb.Append(dlc);
+
+ if (msg.DataTx != null)
+ {
+ foreach (byte b in msg.DataTx)
+ sb.Append(b.ToString("X2"));
+ }
+
+ sb.Append("\r");
+
+ return sb.ToString();
}
private bool EnviarComando(string comando)
@@ -659,26 +713,7 @@ namespace AgroBase.Services
Fechar();
}
- private byte CalcularChecksum(byte id, byte[] data)
- {
- int soma = id;
- foreach (var b in data)
- soma += b;
- return (byte)(soma & 0xFF);
- }
-
- private string GerarChaveMensagem(T_Code Dispositivo, byte Id, byte[] data)
- {
- byte parametro = 0x00;
-
- // Para dispositivos que não sejam MKS, usar DataTx[1] se existir
- if (Dispositivo != T_Code.Mks && (data?.Length ?? 0) > 1)
- {
- parametro = data[1];
- }
-
- return $"{Id}_{data[0]}_{parametro}";
- }
+
// alvo: ~200 fps (ajuste conforme bitrate/carga)
private const double TARGET_FPS = 200;
diff --git a/AgroBase/AgroBase/Services/CANServiceWaveshare.cs b/AgroBase/AgroBase/Services/CANServiceWaveshare.cs
index 387233710..4aaf93b34 100644
--- a/AgroBase/AgroBase/Services/CANServiceWaveshare.cs
+++ b/AgroBase/AgroBase/Services/CANServiceWaveshare.cs
@@ -29,9 +29,9 @@ namespace AgroBase.Services
private AsyncTaskTimerModel tmrProcessarCAN;
private StringBuilder SerialCANBuffer = new StringBuilder();
private readonly ConcurrentQueue<(uint id, byte[] data)> FramesRecebidos = new ConcurrentQueue<(uint, byte[])>();
- private readonly ConcurrentDictionary _roteadores = new ConcurrentDictionary();
- private readonly ConcurrentDictionary _roteadoresRegistrados = new ConcurrentDictionary();
- private byte? _ultimoIdEnviado = null;
+ private readonly ConcurrentDictionary _roteadores = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary _roteadoresRegistrados = new ConcurrentDictionary();
+ private uint? _ultimoIdEnviado = null;
private List MensagensPendentes = new List();
private readonly object _LockMensagens = new object();
private bool DebugMode = false;
@@ -60,9 +60,9 @@ namespace AgroBase.Services
public double UltimoErroCritico { get; set; } = 0;
private DateTime _ultimoErroCritico = DateTime.MinValue;
- private void MostrarLog(string message, byte id)
+ private void MostrarLog(string message, uint id)
{
- if (DebugMode/* && new List() { 0x01 }.Contains(id)*/)
+ if (DebugMode/* && new List() { 0x01 }.Contains(id)*/)
{
Console.WriteLine($"[CAN] {message}");
}
@@ -73,7 +73,7 @@ namespace AgroBase.Services
return true;
}
- public void RegistrarHandler(byte endereco_rx, ICanMessageHandler handler)
+ public void RegistrarHandler(uint endereco_rx, ICanMessageHandler handler)
{
_roteadoresRegistrados.TryGetValue(endereco_rx, out bool registrado);
if (!registrado)
@@ -186,28 +186,52 @@ namespace AgroBase.Services
uint id = frame.Item1;
byte[] data = frame.Item2;
- if (data == null || data.Length == 0) return;
+ if (data == null || data.Length == 0)
+ return;
+
+ // Aqui você consegue saber se é extended ou standard:
+ bool isExtended = id > 0x7FF;
try
{
- MostrarLog($"Processando frame: {BitConverter.ToString(data)}", (byte)id);
+ // opcional: deixar o log mais informativo
+ string tipoId = isExtended ? "EXT" : "STD";
+ MostrarLog($"Processando frame ({tipoId}) ID=0x{id:X}, Data={BitConverter.ToString(data)}", id);
- _roteadores.TryGetValue((byte)id, out ICanMessageHandler handler);
+ _roteadores.TryGetValue(id, out ICanMessageHandler handler);
T_Code dispositivo = handler?.Dispositivo ?? T_Code.Vzo;
- byte fCodeRx = data[0];
- byte parametroRx = data.Length > 1 ? data[1] : (byte)0x00;
- string chave = GerarChaveMensagem(dispositivo, (byte)id, data);
+ bool db = dispositivo == T_Code.Bat;
+ byte fCodeRx = db ? (byte)DalyBMSService.GetDataId(id) : data.Length > 0 ? data[0] : (byte)0x00;
+ byte parametroRx = db ? (byte)0x00 : data.Length > 1 ? data[1] : (byte)0x00;
+ string chave = CanManager.GerarChaveMensagem(dispositivo, id, data);
CanMessage mensagem = null;
lock (_LockMensagens)
{
- mensagem = MensagensPendentes.FirstOrDefault(x => x.Enviado && !x.Respondido && x.Dispositivo == dispositivo && x.IdRx == id && x.DataTx[1] == data[1]);
+ mensagem = MensagensPendentes.FirstOrDefault(x =>
+ x.Enviado &&
+ !x.Respondido &&
+ x.Dispositivo == dispositivo &&
+ x.IdRx == id && // usa o ID completo (11 ou 29 bits)
+ x.DataTx != null &&
+ x.DataTx.Length > 1 &&
+ (db ? true : x.DataTx[1] == data[1])
+ );
}
+
if (mensagem == null)
{
- mensagem = new CanMessage { Dispositivo = dispositivo, IdTx = (byte)id, IdRx = (byte)id, funcCodeRx = fCodeRx, DataRx = data, ChaveInterna = chave };
+ mensagem = new CanMessage
+ {
+ Dispositivo = dispositivo,
+ IdRx = id,
+ funcCodeRx = fCodeRx,
+ DataRx = data,
+ ChaveInterna = chave
+ };
}
+
mensagem.DataRx = data;
mensagem.Respondido = true;
mensagem.RespondidoEm = DateTime.Now;
@@ -218,27 +242,33 @@ namespace AgroBase.Services
}
else
{
- MostrarLog($"Roteador não registrado! ID_Num não tratado: 0x{id:X2}, fCodeRx: 0x{fCodeRx:X2}, frame: {frame}", (byte)id);
+ MostrarLog($"Roteador não registrado! ID_Num não tratado: 0x{id:X2}, fCodeRx: 0x{fCodeRx:X2}, frame: {BitConverter.ToString(data)}", (byte)id);
}
}
catch (Exception ex)
{
- MostrarLog($"Erro ao processar frame! Frame: {frame}, Erro: {ex.Message}", (byte)id);
+ MostrarLog($"Erro ao processar frame! Frame: {BitConverter.ToString(data)}, Erro: {ex.Message}", (byte)id);
}
}
- public void AdicionarMensagemNaFila(T_Code Dispositivo, byte idTx, byte idRx, byte funcCodeTx, byte funcCodeRx, byte[] payload = null, bool get = true)
+
+ public void AdicionarMensagemNaFila(T_Code Dispositivo, byte[] _idTx, byte[] _idRx, byte funcCodeTx, byte funcCodeRx, byte[] payload = null, bool get = true)
{
if (!Connector.IsOpen) return;
- var dados = new List() { funcCodeTx };
+ uint idTx = CanManager.ConverterIdCan(_idTx);
+ uint idRx = CanManager.ConverterIdCan(_idRx);
+
+ var dados = new List();
+ if (Dispositivo != T_Code.Bat)
+ dados.Add(funcCodeTx);
if (payload != null)
dados.AddRange(payload);
if (Dispositivo == T_Code.Mks)
{
- byte crc = CalcularChecksum(idTx, dados.ToArray());
+ byte crc = CanManager.CalcularChecksum(idTx, dados.ToArray());
dados.Add(crc);
}
@@ -252,7 +282,7 @@ namespace AgroBase.Services
funcCodeRx = funcCodeRx,
DataTx = dados.ToArray(),
ComResposta = get,
- ChaveInterna = GerarChaveMensagem(Dispositivo, idRx, dados.ToArray())
+ ChaveInterna = CanManager.GerarChaveMensagem(Dispositivo, idRx, dados.ToArray())
};
bool mensagemNaFila = false;
@@ -307,7 +337,7 @@ namespace AgroBase.Services
.OrderBy(x => x)
.ToList();
- byte proximoId;
+ uint proximoId;
if (!_ultimoIdEnviado.HasValue || !idsDisponiveis.Contains(_ultimoIdEnviado.Value))
{
@@ -328,7 +358,7 @@ namespace AgroBase.Services
return proximaMsg;
}
- private readonly ConcurrentDictionary _cooldownPorId = new ConcurrentDictionary();
+ private readonly ConcurrentDictionary _cooldownPorId = new ConcurrentDictionary();
private static readonly TimeSpan COOLDOWN_MKS = TimeSpan.FromMilliseconds(6);
private bool PodeEnviarAgora(CanMessage m)
@@ -382,20 +412,42 @@ namespace AgroBase.Services
private string CriarFrame(CanMessage msg)
{
- string frame = $"t{msg.IdTx:X3}{msg.DataTx.Length}";
- foreach (byte b in msg.DataTx)
- frame += b.ToString("X2");
+ // Extended se passar do limite de 11 bits
+ bool isExtended = msg.IdTx > 0x7FF;
- frame += "\r";
+ // Prefixo SLCAN só para LOG
+ // t = standard (11 bits)
+ // T = extended (29 bits)
+ char tipo = isExtended ? 'T' : 't';
- return frame;
+ // ID em hex com largura correta
+ string idHex = isExtended
+ ? msg.IdTx.ToString("X8") // 29 bits → 8 hex
+ : msg.IdTx.ToString("X3"); // 11 bits → 3 hex
+
+ // DLC
+ int dlc = msg.DataTx?.Length ?? 0;
+
+ var sb = new StringBuilder();
+ sb.Append(tipo);
+ sb.Append(idHex);
+ sb.Append(dlc);
+
+ if (msg.DataTx != null)
+ {
+ foreach (byte b in msg.DataTx)
+ sb.Append(b.ToString("X2"));
+ }
+
+ sb.Append('\r');
+ return sb.ToString();
}
private bool EnviarComando(string comando, CanMessage msg = null)
{
if (Connector.IsOpen)
{
- bool sucesso = Connector.Send(msg.IdTx, msg.DataTx);
+ bool sucesso = Connector.Send(msg.IdTx, msg.DataTx, isExtended: msg.IsExtended);
if (sucesso)
{
@@ -485,27 +537,6 @@ namespace AgroBase.Services
Fechar();
}
- private byte CalcularChecksum(byte id, byte[] data)
- {
- int soma = id;
- foreach (var b in data)
- soma += b;
- return (byte)(soma & 0xFF);
- }
-
- private string GerarChaveMensagem(T_Code Dispositivo, byte Id, byte[] data)
- {
- if (data == null || data.Length == 0) return $"{Id}_empty";
-
- // MKS: chaveia por funcCode apenas
- if (Dispositivo == T_Code.Mks)
- return $"{Id}_{data[0]}";
-
- // Outros: mantém param se houver
- byte parametro = (data.Length > 1) ? data[1] : (byte)0x00;
- return $"{Id}_{data[0]}_{parametro}";
- }
-
// alvo: ~200 fps (ajuste conforme bitrate/carga)
diff --git a/AgroBase/AgroBase/Services/DalyBMSService.cs b/AgroBase/AgroBase/Services/DalyBMSService.cs
new file mode 100644
index 000000000..9ec772cac
--- /dev/null
+++ b/AgroBase/AgroBase/Services/DalyBMSService.cs
@@ -0,0 +1,491 @@
+using AgroBase.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using static AgroBase.Models.Enums;
+using static AgroBase.Services.DalyBMSService.BatHandler;
+
+namespace AgroBase.Services
+{
+ public class DalyBMSService
+ {
+ public static DalyBmsModel DadosLeitura { get; set; } = new DalyBmsModel();
+ private static T_Code Dispositivo { get; set; } = T_Code.Bat;
+ public static BatHandler _BatHandler { get; set; } = new BatHandler();
+ public static bool Iniciado
+ {
+ get
+ {
+ return CanManager.CanService.IsConnected && SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Dispositivo) && DadosLeitura.Iniciado;
+ }
+ }
+
+ private static double TempoAtualizacao { get; set; } = 2;
+ private static DateTime UltimaAtualizacao { get; set; } = DateTime.MinValue;
+
+ public static async Task VerificaDispositivoConectado()
+ {
+ if (!CanManager.CanService.IsConnected) return false;
+
+ foreach (BatFuncCode f in Enum.GetValues(typeof(BatFuncCode)))
+ {
+ CanManager.CanService.RegistrarHandler(CanManager.ConverterIdCan(MakeResponseID(f)), _BatHandler);
+ }
+
+ RequisitarDado(BatFuncCode.SOC);
+
+ DateTime Inicio = DateTime.Now;
+ bool Respondido() => DadosLeitura.UltimoComandoRecebido > Inicio;
+ await FuncoesGlobais.AguardarCondicaoAsync(Respondido, 500, 50);
+
+ if (Respondido())
+ {
+ DefinirDispositivo();
+ }
+
+ return DadosLeitura.Iniciado;
+ }
+
+ private static void DefinirDispositivo()
+ {
+ if (!SerialService.DispositivosMapeados.Any(x => x.Dispositivo == Dispositivo))
+ {
+ if (DadosLeitura != null)
+ {
+ SerialService.DispositivosMapeados.Add(new DispositivoDetalhesModel()
+ {
+ Dispositivo = Dispositivo,
+ Endereco = CanManager.CanService._portName,
+ Versao = ("1").ToString()
+ });
+ }
+ }
+ }
+
+
+
+ public static void AtualizarDados()
+ {
+ if (!Iniciado)
+ return;
+
+ double dt = (DateTime.Now - UltimaAtualizacao).TotalSeconds;
+ if (dt < TempoAtualizacao)
+ return;
+
+ RequisitarDado(BatFuncCode.SOC);
+ RequisitarDado(BatFuncCode.TensaoMaxMin);
+ RequisitarDado(BatFuncCode.TensaoCelula);
+ RequisitarDado(BatFuncCode.TemperaturaMaxMin);
+ RequisitarDado(BatFuncCode.TemperaturaCelula);
+ RequisitarDado(BatFuncCode.CargaDescargaMOS);
+ RequisitarDado(BatFuncCode.StatusInformacao);
+ RequisitarDado(BatFuncCode.StatusBalanceamentoCelula);
+ RequisitarDado(BatFuncCode.StatusFalhaBateria);
+
+ UltimaAtualizacao = DateTime.Now;
+ }
+
+ #region Helpers de protocolo (ID, DataID, etc.)
+
+ private static void EnviarComando(T_Code Dispositivo, byte[] idTx, byte[] idRx, byte funcCode, byte[] payload = null)
+ {
+ CanManager.CanService.AdicionarMensagemNaFila(Dispositivo, idTx, idRx, funcCode, funcCode, payload, get: true);
+ }
+
+ // Endereços lógicos que você quiser adotar para PC e BMS.
+ // São os "AddrA" e "AddrB" da fórmula 0x18 [DataID] [AddrA] [AddrB].
+ public static byte PriorityAddr { get; set; } = 0x18;
+ public static byte BmsAddr { get; set; } = 0x01;
+ public static byte PcAddr { get; set; } = 0x40;
+
+ public static BatFuncCode GetDataId(uint canId)
+ {
+ return (BatFuncCode)((canId >> 16) & 0xFF);
+ }
+
+ private static byte[] MakeRequestID(BatFuncCode dado)
+ {
+ return new byte[4] { PriorityAddr, (byte)dado, BmsAddr, PcAddr };
+ //return (uint)((0x18 << 24) | ((byte)dado << 16) | (BmsAddr << 8) | PcAddr);
+ }
+
+ private static byte[] MakeResponseID(BatFuncCode dado)
+ {
+ return new byte[4] { PriorityAddr, (byte)dado, PcAddr, BmsAddr };
+ //return (uint)((0x18 << 24) | ((byte)dado << 16) | (PcAddr << 8) | BmsAddr);
+ }
+
+ private static void RequisitarDado(BatFuncCode dado)
+ {
+ EnviarComando(Dispositivo, MakeRequestID(dado), MakeResponseID(dado), (byte)dado, payload: new byte[8]);
+ }
+
+ private static ushort DecodeUInt16BE(byte hi, byte lo)
+ {
+ return (ushort)((hi << 8) | lo);
+ }
+
+ #endregion
+
+ public class BatHandler : ICanMessageHandler
+ {
+ public T_Code Dispositivo { get; set; } = DalyBMSService.Dispositivo;
+
+ public enum BatFuncCode : byte
+ {
+ SOC = 0x90,
+ TensaoMaxMin = 0x91,
+ TemperaturaMaxMin = 0x92,
+ CargaDescargaMOS = 0x93,
+ StatusInformacao = 0x94,
+ TensaoCelula = 0x95,
+ TemperaturaCelula = 0x96,
+ StatusBalanceamentoCelula = 0x97,
+ StatusFalhaBateria = 0x98
+ }
+
+ public void ProcessarMensagem(CanMessage mensagem)
+ {
+ if (mensagem == null) return;
+ if (mensagem.DataRx == null || mensagem.DataRx.Length < 8) return;
+
+ // TODO: trocar "mensagem.CanId" pelo nome real da propriedade que guarda o ID CAN 29 bits
+ uint canId = mensagem.IdRx;
+
+ BatFuncCode dataId = GetDataId(canId);
+ byte[] data = mensagem.DataRx;
+
+ lock (DadosLeitura)
+ {
+ DadosLeitura.Momento = DateTime.Now;
+ DadosLeitura.Iniciado = true;
+ DadosLeitura.UltimoComandoRecebido = DateTime.Now;
+
+ // Guarda payload bruto por DataID para debug
+ DadosLeitura.LeiturasBrutas[(byte)dataId] = data.ToArray();
+
+ switch (dataId)
+ {
+ case BatFuncCode.SOC:
+ Atualizar090_PackVoltageCurrentSoc(data);
+ break;
+ case BatFuncCode.TensaoMaxMin:
+ Atualizar091_CellMaxMin(data);
+ break;
+ case BatFuncCode.TemperaturaMaxMin:
+ Atualizar092_TempMaxMin(data);
+ break;
+ case BatFuncCode.CargaDescargaMOS:
+ Atualizar093_MosEstadoCapacidade(data);
+ break;
+ case BatFuncCode.StatusInformacao:
+ Atualizar094_StatusGeralIo(data);
+ break;
+ case BatFuncCode.TensaoCelula:
+ Atualizar095_TensoesCelulaFrame(data);
+ break;
+ case BatFuncCode.TemperaturaCelula:
+ Atualizar096_TemperaturasFrame(data);
+ break;
+ case BatFuncCode.StatusBalanceamentoCelula:
+ Atualizar097_Balanceamento(data);
+ break;
+ case BatFuncCode.StatusFalhaBateria:
+ Atualizar098_Alarmes(data);
+ break;
+ default:
+ // Outros DataID (se existirem) podem ser tratados aqui no futuro.
+ break;
+ }
+ }
+ }
+
+ private void Atualizar090_PackVoltageCurrentSoc(byte[] d)
+ {
+ // 0..1: total voltage (0.1 V)
+ // 2..3: gather voltage (0.1 V)
+ // 4..5: current (offset 30000, 0.1 A)
+ // 6..7: SOC (0.1 %)
+ ushort totalVRaw = DecodeUInt16BE(d[0], d[1]);
+ ushort measVRaw = DecodeUInt16BE(d[2], d[3]);
+ ushort currRaw = DecodeUInt16BE(d[4], d[5]);
+ ushort socRaw = DecodeUInt16BE(d[6], d[7]);
+
+ double totalV = totalVRaw / 10.0;
+ double measV = measVRaw / 10.0;
+ double current = (currRaw - 30000) / 10.0;
+ double soc = socRaw / 10.0;
+
+ DadosLeitura.Pack.TensaoTotal_V = totalV;
+ DadosLeitura.Pack.TensaoMedida_V = measV;
+ DadosLeitura.Pack.Corrente_A = current;
+ DadosLeitura.Pack.SOC_percent = soc;
+ }
+
+ private void Atualizar091_CellMaxMin(byte[] d)
+ {
+ // 0..1: Vmax (mV)
+ // 2 : index max
+ // 3..4: Vmin (mV)
+ // 5 : index min
+ ushort vmaxRaw = DecodeUInt16BE(d[0], d[1]);
+ byte idxMax = d[2];
+ ushort vminRaw = DecodeUInt16BE(d[3], d[4]);
+ byte idxMin = d[5];
+
+ double vmax = vmaxRaw / 1000.0;
+ double vmin = vminRaw / 1000.0;
+
+ // Marca flags nas células existentes
+ foreach (var c in DadosLeitura.Celulas)
+ {
+ c.EhMaxima = (c.Index == idxMax);
+ c.EhMinima = (c.Index == idxMin);
+ }
+
+ // Atualiza no modelo principal
+ DadosLeitura.TensaoMax = vmax;
+ DadosLeitura.TensaoMin = vmin;
+ }
+
+ private void Atualizar092_TempMaxMin(byte[] d)
+ {
+ // T = raw - 40
+ int tmax = d[0] - 40;
+ byte idxMax = d[1];
+ int tmin = d[2] - 40;
+ byte idxMin = d[3];
+
+ DadosLeitura.TemperaturaMax = tmax;
+ DadosLeitura.TemperaturaMin = tmin;
+
+ foreach (var t in DadosLeitura.Temperaturas)
+ {
+ t.EhMaxima = (t.Index == idxMax);
+ t.EhMinima = (t.Index == idxMin);
+ }
+ }
+
+ private void Atualizar093_MosEstadoCapacidade(byte[] d)
+ {
+ // 0: state (0=idle,1=charge,2=discharge)
+ // 1: charge MOS
+ // 2: discharge MOS
+ // 3: life (raw)
+ // 4..7: remaining capacity (mAh)
+ byte state = d[0];
+ byte chargeMos = d[1];
+ byte dischgMos = d[2];
+ byte lifeRaw = d[3];
+ uint remainmAh = (uint)((d[4] << 24) | (d[5] << 16) | (d[6] << 8) | d[7]);
+
+ DadosLeitura.Pack.EstadoGeral = state;
+ DadosLeitura.Pack.ChargeMosOn = chargeMos != 0;
+ DadosLeitura.Pack.DischargeMosOn = dischgMos != 0;
+ DadosLeitura.Pack.CiclosAproximados = lifeRaw;
+ DadosLeitura.Pack.CapacidadeRestante_Ah = remainmAh / 1000.0;
+ }
+
+ private void Atualizar094_StatusGeralIo(byte[] d)
+ {
+ // 0: n series cells
+ // 1: n temps
+ // 2: charger conected
+ // 3: load connected
+ // 4: IO bits (0-3 DI, 4-7 DO)
+ byte nSeries = d[0];
+ byte nTemps = d[1];
+ byte charger = d[2];
+ byte load = d[3];
+ byte ioByte = d[4];
+
+ DadosLeitura.Pack.NumeroCelulasSerie = nSeries;
+ DadosLeitura.Pack.NumeroSensoresTemperatura = nTemps;
+ DadosLeitura.Pack.CarregadorConectado = (charger != 0);
+ DadosLeitura.Pack.LoadConectado = (load != 0);
+ DadosLeitura.Pack.IoStatusRaw = ioByte;
+ }
+
+ private void Atualizar095_TensoesCelulaFrame(byte[] d)
+ {
+ // d[0] = frame index
+ // d[1..2], [3..4], [5..6] = até 3 tensões de célula (mV)
+ byte frame = d[0];
+
+ for (int i = 0; i < 3; i++)
+ {
+ int hiIndex = 1 + 2 * i;
+ int loIndex = hiIndex + 1;
+ if (loIndex >= d.Length)
+ break;
+
+ ushort raw = DecodeUInt16BE(d[hiIndex], d[loIndex]);
+ if (raw == 0 || raw == 0xFFFF)
+ continue;
+
+ // índice da célula é frame*3 + i + 1 (1-based)
+ int cellIndex = frame * 3 + i + 1;
+ double v = raw / 1000.0;
+
+ var cell = DadosLeitura.Celulas.FirstOrDefault(c => c.Index == cellIndex);
+ if (cell == null)
+ {
+ cell = new DalyCellVoltage
+ {
+ Index = cellIndex
+ };
+ DadosLeitura.Celulas.Add(cell);
+ }
+
+ cell.Tensao_V = v;
+ }
+ }
+
+ private void Atualizar096_TemperaturasFrame(byte[] d)
+ {
+ // d[0] = frame index
+ // d[1..7] = até 7 sensores (raw = temp + 40, 0xFF=inválido)
+ byte frame = d[0];
+
+ for (int i = 1; i < 8 && i < d.Length; i++)
+ {
+ byte raw = d[i];
+ if (raw == 0xFF)
+ continue;
+
+ int tempC = raw - 40;
+ int sensorIndex = frame * 7 + (i - 1) + 1;
+
+ var sensor = DadosLeitura.Temperaturas.FirstOrDefault(t => t.Index == sensorIndex);
+ if (sensor == null)
+ {
+ sensor = new DalyTemperatureSensor
+ {
+ Index = sensorIndex
+ };
+ DadosLeitura.Temperaturas.Add(sensor);
+ }
+
+ sensor.Temperatura_C = tempC;
+ }
+ }
+
+ private void Atualizar097_Balanceamento(byte[] d)
+ {
+ // 6 bytes (ou 8) de bits: cada bit = 1 célula (até 48 células)
+ // Ex: bit0 do byte0 => célula1, bit1=>célula2, ...
+ var map = new Dictionary();
+
+ for (int byteIndex = 0; byteIndex < d.Length; byteIndex++)
+ {
+ byte b = d[byteIndex];
+ for (int bit = 0; bit < 8; bit++)
+ {
+ int globalBit = byteIndex * 8 + bit;
+ if (globalBit >= 48) continue;
+
+ bool ativo = ((b >> bit) & 0x01) == 1;
+ int cellIndex = globalBit + 1;
+
+ map[cellIndex] = ativo;
+ }
+ }
+
+ DadosLeitura.Balanceamento.CelulasEmBalanceamento = map;
+
+ // Atualiza flag direto nas células
+ foreach (var c in DadosLeitura.Celulas)
+ {
+ c.EmBalanceamento = map.TryGetValue(c.Index, out bool ativo) && ativo;
+ }
+ }
+
+ private void Atualizar098_Alarmes(byte[] d)
+ {
+ // d[0..6] = bits de alarme, d[7] = fault code
+ var mensagens = new List();
+
+ void AddIf(byte b, int bit, string msg)
+ {
+ if (((b >> bit) & 0x01) == 1)
+ mensagens.Add(msg);
+ }
+
+ byte b0 = d[0];
+ AddIf(b0, 0, "Cell volt high level 1");
+ AddIf(b0, 1, "Cell volt high level 2");
+ AddIf(b0, 2, "Cell volt low level 1");
+ AddIf(b0, 3, "Cell volt low level 2");
+ AddIf(b0, 4, "Sum volt high level 1");
+ AddIf(b0, 5, "Sum volt high level 2");
+ AddIf(b0, 6, "Sum volt low level 1");
+ AddIf(b0, 7, "Sum volt low level 2");
+
+ byte b1 = d[1];
+ AddIf(b1, 0, "Chg temp high level 1");
+ AddIf(b1, 1, "Chg temp high level 2");
+ AddIf(b1, 2, "Chg temp low level 1");
+ AddIf(b1, 3, "Chg temp low level 2");
+ AddIf(b1, 4, "Dischg temp high level 1");
+ AddIf(b1, 5, "Dischg temp high level 2");
+ AddIf(b1, 6, "Dischg temp low level 1");
+ AddIf(b1, 7, "Dischg temp low level 2");
+
+ byte b2 = d[2];
+ AddIf(b2, 0, "Chg overcurrent level 1");
+ AddIf(b2, 1, "Chg overcurrent level 2");
+ AddIf(b2, 2, "Dischg overcurrent level 1");
+ AddIf(b2, 3, "Dischg overcurrent level 2");
+ AddIf(b2, 4, "SOC high level 1");
+ AddIf(b2, 5, "SOC high level 2");
+ AddIf(b2, 6, "SOC low level 1");
+ AddIf(b2, 7, "SOC low level 2");
+
+ byte b3 = d[3];
+ AddIf(b3, 0, "Diff volt level 1");
+ AddIf(b3, 1, "Diff volt level 2");
+ AddIf(b3, 2, "Diff temp level 1");
+ AddIf(b3, 3, "Diff temp level 2");
+
+ byte b4 = d[4];
+ AddIf(b4, 0, "Chg MOS temp high alarm");
+ AddIf(b4, 1, "Dischg MOS temp high alarm");
+ AddIf(b4, 2, "Chg MOS temp sensor error");
+ AddIf(b4, 3, "Dischg MOS temp sensor error");
+ AddIf(b4, 4, "Chg MOS adhesion error");
+ AddIf(b4, 5, "Dischg MOS adhesion error");
+ AddIf(b4, 6, "Chg MOS open circuit error");
+ AddIf(b4, 7, "Dischg MOS open circuit error");
+
+ byte b5 = d[5];
+ AddIf(b5, 0, "AFE collect chip error");
+ AddIf(b5, 1, "Voltage collect dropped");
+ AddIf(b5, 2, "Cell temp sensor error");
+ AddIf(b5, 3, "EEPROM error");
+ AddIf(b5, 4, "RTC error");
+ AddIf(b5, 5, "Precharge failure");
+ AddIf(b5, 6, "Communication failure");
+ AddIf(b5, 7, "Internal communication failure");
+
+ byte b6 = d[6];
+ AddIf(b6, 0, "Current module fault");
+ AddIf(b6, 1, "Sum voltage detect fault");
+ AddIf(b6, 2, "Short circuit protect fault");
+ AddIf(b6, 3, "Low volt forbidden chg fault");
+
+ byte faultCode = d[7];
+
+ DadosLeitura.Alarmes.Mensagens = mensagens;
+ DadosLeitura.Alarmes.FaultCode = faultCode;
+ DadosLeitura.Alarmes.AlarmBytesRaw = d.Take(7).ToArray();
+ }
+
+
+
+ }
+ }
+
+
+}
diff --git a/AgroBase/AgroBase/Services/DispositivosService.cs b/AgroBase/AgroBase/Services/DispositivosService.cs
index 35c488e29..289cb41aa 100644
--- a/AgroBase/AgroBase/Services/DispositivosService.cs
+++ b/AgroBase/AgroBase/Services/DispositivosService.cs
@@ -68,13 +68,13 @@ namespace AgroBase.Comum
{
List payload = new List()
{
- (byte)ID_Num,
+ (byte)ID_Num,
};
if (dados != null)
{
payload.AddRange(dados);
}
- CanManager.CanService.AdicionarMensagemNaFila(Dispositivo, Dados._EnderecoCAN_Tx, Dados._EnderecoCAN_Rx, (byte)PosicaoTx, (byte)PosicaoRx, payload.ToArray(), get);
+ CanManager.CanService.AdicionarMensagemNaFila(Dispositivo, new byte[] { Dados._EnderecoCAN_Tx }, new byte[] { Dados._EnderecoCAN_Rx }, (byte)PosicaoTx, (byte)PosicaoRx, payload.ToArray(), get);
}
public Control InstanciarDispositivo(int index)
diff --git a/AgroBase/AgroBase/Services/MKS057DCanService.cs b/AgroBase/AgroBase/Services/MKS057DCanService.cs
index 3632ea469..ee5ad7c79 100644
--- a/AgroBase/AgroBase/Services/MKS057DCanService.cs
+++ b/AgroBase/AgroBase/Services/MKS057DCanService.cs
@@ -125,7 +125,7 @@ namespace AgroBase.Services
private static void EnviarComando(T_Code Dispositivo, byte idTx, byte idRx, byte funcCode, byte[] payload = null, bool get = true)
{
- CanManager.CanService.AdicionarMensagemNaFila(Dispositivo, idTx, idRx, funcCode, funcCode, payload, get);
+ CanManager.CanService.AdicionarMensagemNaFila(Dispositivo, new byte[] { idTx }, new byte[] { idRx }, funcCode, funcCode, payload, get);
}
public static void SetModoOperacao(byte idTx, byte idRx, byte modo)
@@ -283,10 +283,12 @@ namespace AgroBase.Services
}
}
- private MKS057DModel ObterOuCriar(byte idTx, byte idRx)
+ private MKS057DModel ObterOuCriar(uint _idTx, uint _idRx)
{
lock (DadosLeitura)
{
+ byte idTx = CanManager.ConverterIdCan(_idTx)[0];
+ byte idRx = CanManager.ConverterIdCan(_idRx)[0];
var item = DadosLeitura.FirstOrDefault(x => x.EnderecoTx == idTx && x.EnderecoRx == idRx);
if (item == null)
{
diff --git a/AgroBase/AgroBase/Services/OIDCanService.cs b/AgroBase/AgroBase/Services/OIDCanService.cs
index 84c5259d2..7e12a8cdc 100644
--- a/AgroBase/AgroBase/Services/OIDCanService.cs
+++ b/AgroBase/AgroBase/Services/OIDCanService.cs
@@ -108,7 +108,7 @@ namespace AgroBase.Services
private static void EnviarComando(T_Code Dispositivo, byte idTx, byte idRx, byte funcCode, byte[] payload = null, bool get = true)
{
- CanManager.CanService.AdicionarMensagemNaFila(Dispositivo, idTx, idRx, funcCode, funcCode, payload, get);
+ CanManager.CanService.AdicionarMensagemNaFila(Dispositivo, new byte[] { idTx }, new byte[] { idRx }, funcCode, funcCode, payload, get);
}
public static void RequisitarDado(byte idTx, byte idRx, OidParametros dado)
@@ -280,10 +280,12 @@ namespace AgroBase.Services
SinalZNaoEncontrado = 19
}
- private OIDModel ObterOuCriar(byte idTx, byte idRx)
+ private OIDModel ObterOuCriar(uint _idTx, uint _idRx)
{
lock (DadosLeitura)
{
+ byte idTx = CanManager.ConverterIdCan(_idTx)[0];
+ byte idRx = CanManager.ConverterIdCan(_idRx)[0];
var item = DadosLeitura.FirstOrDefault(x => x.EnderecoTx == idTx && x.EnderecoRx == idRx);
if (item == null)
{
diff --git a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs
index 4484cbc5b..9a4e8ee17 100644
--- a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs
+++ b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using static AgroBase.Models.Enums;
using static AgroBase.Models.Operadores.OperadoresModels;
namespace AgroBase.Services.Operadores
@@ -744,6 +745,43 @@ namespace AgroBase.Services.Operadores
("last_ec", DadosCan.UltimoErroCritico)
);
+ var DadosBateria = DalyBMSService.DadosLeitura;
+ RedisService.AtualizarCampos(
+ RedisService.ModKey(T_Code.Bat), // ajusta o T_Code se o seu enum tiver outro nome
+ ("timestamp", agora),
+ ("iniciado", DadosBateria.Iniciado),
+ ("momento_bms", DadosBateria.Momento),
+ // Dados principais do pack
+ ("tensao_total_v", DadosBateria.Pack.TensaoTotal_V),
+ ("tensao_medida_v", DadosBateria.Pack.TensaoMedida_V),
+ ("corrente_a", DadosBateria.Pack.Corrente_A),
+ ("soc_pct", DadosBateria.Pack.SOC_percent),
+ ("num_celulas_serie", DadosBateria.Pack.NumeroCelulasSerie),
+ ("num_sensores_temp", DadosBateria.Pack.NumeroSensoresTemperatura),
+ ("estado_geral", DadosBateria.Pack.EstadoGeral),
+ ("charge_mos_on", DadosBateria.Pack.ChargeMosOn),
+ ("discharge_mos_on", DadosBateria.Pack.DischargeMosOn),
+ ("cap_restante_ah", DadosBateria.Pack.CapacidadeRestante_Ah),
+ ("ciclos_aproximados", DadosBateria.Pack.CiclosAproximados),
+ // Tensão de células
+ ("tensao_min_celula_v", DadosBateria.TensaoMin > 0 ? DadosBateria.TensaoMin : DadosBateria.Celulas.Min(c => c.Tensao_V)),
+ ("tensao_max_celula_v", DadosBateria.TensaoMax > 0 ? DadosBateria.TensaoMax : DadosBateria.Celulas.Max(c => c.Tensao_V)),
+ ("idx_celula_min", DadosBateria.Celulas.FirstOrDefault(c => c.EhMinima)?.Index ?? 0),
+ ("idx_celula_max", DadosBateria.Celulas.FirstOrDefault(c => c.EhMaxima)?.Index ?? 0),
+ // Temperaturas
+ ("temp_min_c", DadosBateria.TemperaturaMin > -200 ? DadosBateria.TemperaturaMin : DadosBateria.Temperaturas.Min(t => t.Temperatura_C)),
+ ("temp_max_c", DadosBateria.TemperaturaMax > -200 ? DadosBateria.TemperaturaMax : DadosBateria.Temperaturas.Max(t => t.Temperatura_C)),
+ // Balanceamento
+ ("celulas_em_balanceamento", DadosBateria.Balanceamento.QtdeCelulasEmBalanceamento),
+ // Alarmes
+ ("tem_alarme", DadosBateria.Alarmes?.TemAlarme ?? false),
+ ("fault_code", DadosBateria.Alarmes?.FaultCode ?? 0x00),
+ ("qtd_alarmes", DadosBateria.Alarmes?.Mensagens?.Count ?? 0),
+ ("alarmes_texto", DadosBateria.Alarmes.Mensagens != null && DadosBateria.Alarmes.Mensagens.Count > 0 ? string.Join(" | ", DadosBateria.Alarmes.Mensagens) : string.Empty),
+ // Opcional: bytes brutos de alarme se quiser debugar depois
+ ("alarm_bytes_raw", DadosBateria.Alarmes.AlarmBytesRaw != null ? BitConverter.ToString(DadosBateria.Alarmes.AlarmBytesRaw) : string.Empty)
+ );
+
var DadosTrj = _Sensoriamento?.Trajetoria;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Trj),
("timestamp", agora),
@@ -759,6 +797,5 @@ namespace AgroBase.Services.Operadores
-
}
}
diff --git a/AgroBase/AgroBase/Services/SerialService.cs b/AgroBase/AgroBase/Services/SerialService.cs
index 5ce229dde..36e1a7501 100644
--- a/AgroBase/AgroBase/Services/SerialService.cs
+++ b/AgroBase/AgroBase/Services/SerialService.cs
@@ -442,6 +442,16 @@ namespace AgroBase.Services
}
}
+ if (true && !DalyBMSService.Iniciado)
+ {
+ AtualizarConsole($"{CanManager.CanService._portName} - Procurando dispositivo BAT");
+ bool DispBat = await DalyBMSService.VerificaDispositivoConectado();
+ if (DispBat)
+ {
+ AtualizarConsole("Dispositivo BAT encontrado");
+ }
+ }
+
return CanManager.CanService.Iniciado;
}
diff --git a/AgroBase/AgroBase/Services/WaveshareCanFDService.cs b/AgroBase/AgroBase/Services/WaveshareCanFDService.cs
index f80286977..743e1fb9b 100644
--- a/AgroBase/AgroBase/Services/WaveshareCanFDService.cs
+++ b/AgroBase/AgroBase/Services/WaveshareCanFDService.cs
@@ -156,22 +156,41 @@ public class WaveshareCANFDService
public bool Send(uint id, byte[] data, bool isExtended = false, bool isRemote = false)
{
- if (!isOpen || data == null || data.Length > 8) return false;
+ if (!isOpen || data == null || data.Length > 8)
+ return false;
- id &= 0x7FF; // <- garante Standard ID
+ // Segurança: garante que o ID está no range certo
+ if (isExtended)
+ {
+ // 29 bits
+ id &= 0x1FFFFFFF;
+ }
+ else
+ {
+ // 11 bits
+ id &= 0x7FF;
+ }
var obj = new VCI_CAN_OBJ
{
ID = id,
- SendType = 0,
- RemoteFlag = (byte)(isRemote ? 1 : 0),
- ExternFlag = (byte)(isExtended ? 1 : 0),
+ SendType = 0, // normal
+ RemoteFlag = (byte)(isRemote ? 1 : 0), // 0 = data frame, 1 = remote frame
+ ExternFlag = (byte)(isExtended ? 1 : 0), // 0 = standard, 1 = extended
DataLen = (byte)data.Length,
Data = new byte[8],
Reserved = new byte[3]
};
+
+ // copia os dados pro buffer fixo de 8 bytes
+ Array.Clear(obj.Data, 0, obj.Data.Length);
Array.Copy(data, obj.Data, data.Length);
- return VCI_Transmit(DEVICE_TYPE, DEVICE_INDEX, channelIndex, ref obj, 1) > 0;
+
+ lock (_canLock)
+ {
+ uint sent = VCI_Transmit(DEVICE_TYPE, DEVICE_INDEX, channelIndex, ref obj, 1);
+ return sent == 1;
+ }
}
private async Task tmrLeitura_Tick()
diff --git a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersAtu-1_1.par b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersAtu-1_1.par
index 9e3014cf4..e2195b793 100644
--- a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersAtu-1_1.par
+++ b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersAtu-1_1.par
@@ -1 +1 @@
-{"tmrRegistrador":{"_uiControl":null,"State":2,"IsRunning":false,"IsStopped":true,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"AtuadorModel.IniciarRegistrador","Id":"tmrRegistrador_Atu","TimeTick":"00:00:00"},"_AtuHandler":{"Dispositivo":103},"ContadorCarga":{"Iniciado":false,"CapacidadeLitros":30.0,"DensidadeProduto":1.0,"MassaAtual_Kg":0.0,"MassaAtual_Kg_Calc":0.0,"VolumeAtual_L":0.0,"VolumeConsumido_L":0.0,"PercentualAtual":0.0,"PercentualConsumido":100.0,"HerbicidaPorAtuacao":0.0,"MargemSegurancaAutonomia":0.3,"LPorMetro":0.0,"LPorMetroBase":0.1188,"LPorMetroHistorico":0.0,"LPorMetroReferencia":0.1188,"DistanciaMaximaTeorica_m":0.0,"DistanciaMaximaSegura_m":0.0,"DistanciaEstimadaRestantePulverizando_m":0.0,"LPorMinuto":0.0,"TempoEstimadoMinutosPulverizando":0.0,"PulverizadorLiberado":false},"Dispositivo":103,"Modulo_ID":"Atu","_EnderecoCAN_Tx":18,"_EnderecoCAN_Rx":18,"_TaxaAmostragem":1000,"FrequenciaBase":1.0,"RequisitarDados":true,"Conectado":false,"ConexaoAtiva":false,"AtuPronto":false,"AnguloBarraEsquerda":0.0,"AnguloBarraDireita":0.0,"AnguloBarraAltura":0.0,"DensidadeHerbicida":1.0,"BicosPulverizadores":[{"ID":"B01","ID_Num":71,"Posicao":1,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":91,"AnguloControle":0.0,"AnguloAbertura":110.0,"ComandoAtuar":false,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[21],"MediaNivelFluxo":0.0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0,"_AnguloBicoLeitura":0,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B02","ID_Num":72,"Posicao":2,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":92,"AnguloControle":0.0,"AnguloAbertura":110.0,"ComandoAtuar":false,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[21],"MediaNivelFluxo":0.0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0,"_AnguloBicoLeitura":0,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B03","ID_Num":73,"Posicao":3,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":93,"AnguloControle":0.0,"AnguloAbertura":110.0,"ComandoAtuar":false,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[21],"MediaNivelFluxo":0.0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0,"_AnguloBicoLeitura":0,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0}],"BombasPressurizadoras":[{"ID":"BOMBA","ID_Num":51,"ComandoAtuar":false,"Componente":14,"Sensor_ID_Num":63,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[14,35,36,37,5],"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":53,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":68,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":24,"posicao":2,"indice":3,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0,"_Potencia":0.0,"_BombaLigada":false,"_PressaoSP":0.0}],"Sensores":[{"ID":"FLXLN","ID_Num":61,"Descricao":"Fluxo na linha principal","Componente":8,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[25],"Parametros":[],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":73,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":74,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":25,"posicao":2,"indice":2,"minimo":0.0,"maximo":20.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mL/s"}]},{"ID":"MASRS","ID_Num":62,"Descricao":"Massa do reservatório de herbicida","Componente":10,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[22,23],"Parametros":[{"Descricao":"Offset","Valor":"0.0","QtdBytes":2,"Escalar":true,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":32,"posicao":2,"indice":1,"minimo":0.0,"maximo":35.0,"nominal":30.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"Kg"}]},{"ID":"PRSLN","ID_Num":63,"Descricao":"Pressão na linha principal","Componente":12,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[24],"Parametros":[{"Descricao":"Vmin","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":false},{"Descricao":"Vmax","Valor":"4.5","QtdBytes":1,"Escalar":true,"Enviar":false},{"Descricao":"Pmax","Valor":"174","QtdBytes":1,"Escalar":false,"Enviar":false}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":24,"posicao":2,"indice":1,"minimo":0.0,"maximo":120.0,"nominal":85.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PSI"}]},{"ID":"MAGESQ","ID_Num":64,"Descricao":"Angulo Barra Esquerda","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDIR","ID_Num":65,"Descricao":"Angulo Barra Direita","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGALT","ID_Num":66,"Descricao":"Angulo Barra Altura","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]}],"Servos":[{"ID":"SRVB1","ID_Num":91,"Descricao":"Articulaccao Bico 01","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":90,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":true,"unidade_medida":null}]},{"ID":"SRVB2","ID_Num":92,"Descricao":"Articulaccao Bico 02","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":90,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":true,"unidade_medida":null}]},{"ID":"SRVB3","ID_Num":93,"Descricao":"Articulaccao Bico 03","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":90,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":true,"unidade_medida":null}]}],"ScriptDeteccaoErvas":"weed_detector_oak-1_0.py","DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Dispositivo":0,"Versao":0,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"BicosPulverizadores":null,"BombasPressurizadoras":null,"Sensores":null,"Servos":null,"UltimoComandoRespondido":"0001-01-01T00:00:00"},"VolumeVazaoAferido":0.0,"_FluxoMlRef":600.0,"_FluxoPulsoRef":538.0,"VazaoFluxoMLpSInstantanea":0.0,"VazaoFluxoMLpSInstantaneaCalc":0.0,"VazaoFluxoMLpSMedia":0.0,"VolumeVazaoML":0.0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0,"_PressaoVmin":0.0,"_PressaoVmax":4.5,"_PressaoMax":174.045,"PressaoLinha":0.0,"PressaoLinhaCalc":0.0,"PercentualErvasTerreno":0.0}
\ No newline at end of file
+{"tmrRegistrador":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"AtuadorModel.IniciarRegistrador","Id":"tmrRegistrador_Atu","TimeTick":"00:00:00"},"_AtuHandler":{"Dispositivo":103},"ContadorCarga":{"Iniciado":false,"CapacidadeLitros":30.0,"DensidadeProduto":1.0,"MassaAtual_Kg":0.0,"MassaAtual_Kg_Calc":0.0,"VolumeAtual_L":0.0,"VolumeConsumido_L":0.0,"PercentualAtual":0.0,"PercentualConsumido":100.0,"HerbicidaPorAtuacao":0.0,"MargemSegurancaAutonomia":0.3,"LPorMetro":0.0,"LPorMetroBase":0.1188,"LPorMetroHistorico":0.0,"LPorMetroReferencia":0.1188,"DistanciaMaximaTeorica_m":0.0,"DistanciaMaximaSegura_m":0.0,"DistanciaEstimadaRestantePulverizando_m":0.0,"LPorMinuto":0.0,"TempoEstimadoMinutosPulverizando":0.0,"PulverizadorLiberado":false},"Dispositivo":103,"Modulo_ID":"Atu","_EnderecoCAN_Tx":18,"_EnderecoCAN_Rx":18,"_TaxaAmostragem":1000,"FrequenciaBase":1.0,"RequisitarDados":true,"Conectado":false,"ConexaoAtiva":false,"AtuPronto":false,"AnguloBarraEsquerda":0.0,"AnguloBarraDireita":0.0,"AnguloBarraAltura":0.0,"DensidadeHerbicida":1.0,"BicosPulverizadores":[{"ID":"B01","ID_Num":71,"Posicao":1,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":91,"AnguloControle":0.0,"AnguloAbertura":110.0,"ComandoAtuar":false,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[21],"VazaoMediaMLs":0.0,"VazaoInstantaneaMLs":0.0,"VolumeVazadoML":0.0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_estadoLeituraAnterior":0,"_EstadoLeitura":0,"_AnguloBicoLeitura":0,"TrechosAtuado":[],"Atuacoes":0,"TempoAtuado":0.0},{"ID":"B02","ID_Num":72,"Posicao":2,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":92,"AnguloControle":0.0,"AnguloAbertura":110.0,"ComandoAtuar":false,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[21],"VazaoMediaMLs":0.0,"VazaoInstantaneaMLs":0.0,"VolumeVazadoML":0.0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_estadoLeituraAnterior":0,"_EstadoLeitura":0,"_AnguloBicoLeitura":0,"TrechosAtuado":[],"Atuacoes":0,"TempoAtuado":0.0},{"ID":"B03","ID_Num":73,"Posicao":3,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":93,"AnguloControle":0.0,"AnguloAbertura":110.0,"ComandoAtuar":false,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[21],"VazaoMediaMLs":0.0,"VazaoInstantaneaMLs":0.0,"VolumeVazadoML":0.0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_estadoLeituraAnterior":0,"_EstadoLeitura":0,"_AnguloBicoLeitura":0,"TrechosAtuado":[],"Atuacoes":0,"TempoAtuado":0.0}],"BombasPressurizadoras":[{"ID":"BOMBA","ID_Num":51,"ComandoAtuar":false,"Componente":14,"Sensor_ID_Num":63,"Comandar":true,"Mandatorio":true,"Liberado":false,"Funcoes":[14,35,36,37,5],"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":53,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":68,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":24,"posicao":2,"indice":3,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0,"_Potencia":0.0,"_BombaLigada":false,"_PressaoSP":0.0}],"Sensores":[{"ID":"FLXLN","ID_Num":61,"Descricao":"Fluxo na linha principal","Componente":8,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[25],"Parametros":[],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":73,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":74,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":25,"posicao":2,"indice":2,"minimo":0.0,"maximo":20.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mL/s"}]},{"ID":"MASRS","ID_Num":62,"Descricao":"Massa do reservatório de herbicida","Componente":10,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[22,23],"Parametros":[{"Descricao":"Offset","Valor":"0.0","QtdBytes":2,"Escalar":true,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":32,"posicao":2,"indice":1,"minimo":0.0,"maximo":35.0,"nominal":30.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"Kg"}]},{"ID":"PRSLN","ID_Num":63,"Descricao":"Pressão na linha principal","Componente":12,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[24],"Parametros":[{"Descricao":"Vmin","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":false},{"Descricao":"Vmax","Valor":"4.5","QtdBytes":1,"Escalar":true,"Enviar":false},{"Descricao":"Pmax","Valor":"174","QtdBytes":1,"Escalar":false,"Enviar":false}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":24,"posicao":2,"indice":1,"minimo":0.0,"maximo":120.0,"nominal":85.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PSI"}]},{"ID":"MAGESQ","ID_Num":64,"Descricao":"Angulo Barra Esquerda","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDIR","ID_Num":65,"Descricao":"Angulo Barra Direita","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGALT","ID_Num":66,"Descricao":"Angulo Barra Altura","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]}],"Servos":[{"ID":"SRVB1","ID_Num":91,"Descricao":"Articulaccao Bico 01","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":90,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":true,"unidade_medida":null}]},{"ID":"SRVB2","ID_Num":92,"Descricao":"Articulaccao Bico 02","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":90,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":true,"unidade_medida":null}]},{"ID":"SRVB3","ID_Num":93,"Descricao":"Articulaccao Bico 03","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":90,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":0.0,"ValorMinimo":0.0},"analise_health":true,"unidade_medida":null}]}],"ScriptDeteccaoErvas":"weed_detector_oak-1_0.py","DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Dispositivo":0,"Versao":0,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"BicosPulverizadores":null,"BombasPressurizadoras":null,"Sensores":null,"Servos":null,"UltimoComandoRespondido":"0001-01-01T00:00:00"},"VolumeVazaoAferido":0.0,"_FluxoMlRef":600.0,"_FluxoPulsoRef":538.0,"VazaoFluxoMLpSInstantanea":0.0,"VazaoFluxoMLpSInstantaneaCalc":0.0,"VazaoMediaMLs":0.0,"VolumeVazadoML":0.0,"TempoAtuado":0.0,"_PressaoVmin":0.0,"_PressaoVmax":4.5,"_PressaoMax":174.045,"PressaoLinha":0.0,"PressaoLinhaCalc":0.0,"PercentualErvasTerreno":0.0}
\ No newline at end of file
diff --git a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par
index adfb78f7d..b994d01ba 100644
--- a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par
+++ b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersMvd-2_0.par
@@ -1 +1 @@
-{"UltimoTickRegistrador":"0001-01-01T00:00:00","tmrRegistrador":{"_uiControl":null,"State":2,"IsRunning":false,"IsStopped":true,"IsCreated":false,"IsDisposed":false,"Interval":250,"IntervalHz":4.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mvd","TimeTick":"00:00:00"},"tmrRegistradorMOV":{"_uiControl":null,"State":2,"IsRunning":false,"IsStopped":true,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mov","TimeTick":"00:00:00"},"tmrRegistradorDIR":{"_uiControl":null,"State":2,"IsRunning":false,"IsStopped":true,"IsCreated":false,"IsDisposed":false,"Interval":500,"IntervalHz":2.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Dir","TimeTick":"00:00:00"},"Dispositivo":109,"_EnderecoCAN_Tx":0,"_EnderecoCAN_Rx":0,"ConexaoAtiva":false,"DirPronto":false,"MovPronto":false,"_TaxaAmostragem":250,"DistanciaPercorridaOperacao":0.0,"TempoEmAtividade":0.0,"DistanciaPercorridaTotal":0.0,"DistanciaPercorridaParcial":0.0,"VelocidadeMedia":0.0,"DiametroRoda":0.355,"ReducaoMotorBLDC":5.0,"RPM_Max_MotorBLDC":500.0,"IP_Mov":"192.168.105.10","IP_Dir":"192.168.105.11","Modulos":[{"Modulo_ID":"ET","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":5,"_EnderecoCAN_Rx":5,"heartBeatValue":0,"Mod_ID":"ET","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"ET","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":0,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":1,"_EnderecoCAN_Rx":1,"Mod_ID":"ET","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":240,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":3,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"EF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":7,"_EnderecoCAN_Rx":7,"heartBeatValue":0,"Mod_ID":"EF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"EF","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":3,"_EnderecoCAN_Rx":3,"Mod_ID":"EF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":240,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":98.35,"UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":-183.25,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":3,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DT","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":6,"_EnderecoCAN_Rx":6,"heartBeatValue":0,"Mod_ID":"DT","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DT","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":180,"UltimoEnvio":"2025-12-17T10:22:54.3157149-03:00","DelayEnvio":500,"Servo":{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":true}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":2,"_EnderecoCAN_Rx":2,"Mod_ID":"DT","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":240,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":3,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":8,"_EnderecoCAN_Rx":8,"heartBeatValue":0,"Mod_ID":"DF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DF","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":4,"_EnderecoCAN_Rx":4,"Mod_ID":"DF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":240,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":3,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}}]}
\ No newline at end of file
+{"UltimoTickRegistrador":"0001-01-01T00:00:00","tmrRegistrador":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":250,"IntervalHz":4.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mvd","TimeTick":"00:00:00"},"tmrRegistradorMOV":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Mov","TimeTick":"00:00:00"},"tmrRegistradorDIR":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":500,"IntervalHz":2.0,"StackTrace":"MovimentacaoUnificadaModel.IniciarRegistrador","Id":"tmrRegistrador_Dir","TimeTick":"00:00:00"},"Dispositivo":109,"_EnderecoCAN_Tx":0,"_EnderecoCAN_Rx":0,"ConexaoAtiva":false,"DirPronto":false,"MovPronto":false,"_TaxaAmostragem":250,"DistanciaPercorridaOperacao":0.0,"TempoEmAtividade":0.0,"DistanciaPercorridaTotal":0.0,"DistanciaPercorridaParcial":0.0,"VelocidadeMedia":0.0,"DiametroRoda":0.355,"ReducaoMotorBLDC":5.0,"RPM_Max_MotorBLDC":500.0,"IP_Mov":"192.168.105.10","IP_Dir":"192.168.105.11","Modulos":[{"Modulo_ID":"ET","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":5,"_EnderecoCAN_Rx":5,"heartBeatValue":0,"Mod_ID":"ET","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"ET","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":0,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":1,"_EnderecoCAN_Rx":1,"Mod_ID":"ET","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"EF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":7,"_EnderecoCAN_Rx":7,"heartBeatValue":0,"Mod_ID":"EF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"EF","Incremental":true,"AnguloInicial":10,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":3,"_EnderecoCAN_Rx":3,"Mod_ID":"EF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":98.35,"UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":-183.25,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DT","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":6,"_EnderecoCAN_Rx":6,"heartBeatValue":0,"Mod_ID":"DT","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DT","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":180,"UltimoEnvio":"2026-02-05T16:35:23.1417988-03:00","DelayEnvio":500,"Servo":{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":true}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":2,"_EnderecoCAN_Rx":2,"Mod_ID":"DT","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":2,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":false,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}},{"Modulo_ID":"DF","Disponivel":false,"RequisitarDados":false,"Conectado":false,"MovMotor":{"ID":"Mov","_EnderecoCAN_Tx":8,"_EnderecoCAN_Rx":8,"heartBeatValue":0,"Mod_ID":"DF","LeituraLigado":true,"LeituraRPM":0.0,"ComandoLigado":false,"CodigoAlarme":0,"AlarmeMotor":false,"RPM_SP":0,"RPM_SP_Controle":0,"RPM_SP_Leitura":0,"Sentido_SP":1,"NumeroPolos":10,"Rampa":0,"CorrenteTorqueMaximo":40,"OffsetLeitura":1.0,"AlarmeComando":false,"RPM_Roda":0.0,"Sentido":0,"Temperatura":0.0,"TemperaturaDriver":0.0,"Tensao":0.0,"Corrente_Barramento":0.0,"Corrente_Motor":0.0,"Potencia":0.0,"CicloTrabalho":0.0,"RPM_Motor":0.0,"VelocidadeInstantanea":0.0,"SensorTemperaturaMotor":{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},"Comandar":true,"AlarmeSensores":false,"Inicializado":false,"Leitura":null,"CompensacaoNecessaria":false,"NovoRPMNecessario":false,"ConfigSentidos":{"RodasDianteiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RodasTraseiras":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoDiagonal":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoArco":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"RotacionarNoEixo":{"Frente":2,"Tras":1,"Esquerda":0,"Direita":0,"Parado":0},"MovimentoLateral":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0},"Diagnostico":{"Frente":1,"Tras":2,"Esquerda":0,"Direita":0,"Parado":0}},"Funcoes":[12,14,9,5,10],"LogGrafico":[],"Alarmes":[],"ConfigFreio":{"Mod_ID":"DF","Incremental":false,"AnguloInicial":170,"Leitura":false,"AnguloControle":-1,"UltimoEnvio":"0001-01-01T00:00:00","DelayEnvio":500,"Servo":{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},"EnviarComando":false}},"DirMotor":{"ID":"Dir","_EnderecoCAN_Tx":4,"_EnderecoCAN_Rx":4,"Mod_ID":"DF","Sentido_SP":0,"Angulo_SP":0.0,"FolgaMecanica":0.0,"Velocidade_Max":600.0,"Velocidade":300,"Sentido":0,"SentidoReal":1,"AnguloDriver":0.0,"AnguloReal":"NaN","UsarAnguloSensor":false,"AnguloLeitura":0.0,"AnguloFolgaCompensar":0.0,"OffsetAnguloReal":0.0,"RPM":0.0,"IN1_Atuado":true,"IN2_Atuado":true,"Referenciando":false,"UltimoReferenciamento":"0001-01-01T00:00:00","Referenciado":false,"SensorAnguloReal":{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},"Comandar":true,"Inicializado":false,"Leitura":null,"UltimaDirecao":0,"UltimoComandoEnviado":"0001-01-01T00:00:00","RetornandoAzero":false,"EmMovimento":false,"AtingiuAnguloSP":true,"ConfigSentidos":{"RodasDianteiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RodasTraseiras":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoDiagonal":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"MovimentoArco":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"RotacionarNoEixo":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":1,"Parado":0},"MovimentoLateral":{"Frente":0,"Tras":0,"Esquerda":1,"Direita":2,"Parado":0},"Diagnostico":{"Frente":0,"Tras":0,"Esquerda":2,"Direita":1,"Parado":0}},"Funcoes":[13,9,14,41]}}]}
\ No newline at end of file
diff --git a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par
index 2e4f8edb1..4aa761e47 100644
--- a/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par
+++ b/AgroBase/AgroBase/bin/x64/Debug/Parametros/parametersSen-1_3.par
@@ -1 +1 @@
-{"ContadorCarga":{"TempoEstimadoMinutos":0.0,"Iniciado":false,"CargaAtualAmp":20.0,"_Consumido":0.0,"ConsumidoAmp":0.0,"PercentualAtual":100.0,"PercentualConsumido":0.0,"PercentualBateria":0.0,"EnergiaConsumida_Wh":0.0,"_dt":0.0,"CorrenteInstantanea":0.0,"TensaoInstantanea":0.0,"PotenciaInstantanea":0.0,"WhRestante":840.0,"WhPorMetro":0.0,"WhPorMetroBase":0.1167,"WhPorMetroHistorico":0.0,"WhPorMetroReferencia":0.1167,"DistanciaMaximaTeorica_m":0.0,"DistanciaMaximaSegura_m":0.0,"DistanciaEstimadaRestante_m":0.0,"MargemSegurancaAutonomia":0.3},"CoolerControl":{"TempOn":55.0,"TempTurbo":65.0,"TempCritical":75.0,"Histerese":1.5,"MinOnTime":"00:00:30","MinOffTime":"00:00:30","AlphaFiltro":0.2,"ModoAtual":0,"CoolerEntradaEstado":0,"CoolerSaidaEstado":0,"CoolerEntradaLeitura":0,"CoolerSaidaLeitura":0,"TemperaturaFiltrada":51.43423044106666,"UltimaMudancaModo":"0001-01-01T00:00:00","AlertaTemperaturaCritica":false},"tmrRegistrador":{"_uiControl":null,"State":2,"IsRunning":false,"IsStopped":true,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"SensoriamentoModel.IniciarRegistrador","Id":"tmrRegistrador_Sen","TimeTick":"00:00:00"},"Dispositivo":102,"Modulo_ID":"Sen","_EnderecoCAN_Tx":17,"_EnderecoCAN_Rx":17,"_TaxaAmostragem":1000,"FrequenciaBase":1.0,"RequisitarDados":true,"Conectado":false,"ConexaoAtiva":false,"DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Dispositivo":0,"Versao":0,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"UltimoComandoRespondido":"0001-01-01T00:00:00","Sensores":null,"Sinaleiros":null,"Reles":null,"Servos":null},"Sensores":[{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TBAT","ID_Num":5,"Descricao":"Temperatura da bateria","Componente":4,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"AB3V","ID_Num":11,"Descricao":"Corrente no Barramento 3V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"5","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":3.0,"maximo":3.4,"nominal":3.3,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":500.0,"nominal":100.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB5V","ID_Num":12,"Descricao":"Corrente no Barramento 5V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":4.9,"maximo":5.2,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":1000.0,"nominal":300.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB7V2","ID_Num":13,"Descricao":"Corrente no Barramento 7,2V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":7.0,"maximo":7.4,"nominal":7.2,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":0.0,"maximo":3000.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB12V","ID_Num":14,"Descricao":"Corrente no Barramento 12V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":11.5,"maximo":12.5,"nominal":12.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":10000.0,"nominal":500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB19V","ID_Num":15,"Descricao":"Corrente no Barramento 19V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":18.8,"maximo":19.2,"nominal":19.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":500.0,"maximo":4000.0,"nominal":1500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB24V","ID_Num":16,"Descricao":"Corrente no Barramento 24V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"6","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":23.8,"maximo":24.3,"nominal":24.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":100.0,"maximo":20000.0,"nominal":700.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB36V","ID_Num":17,"Descricao":"Corrente no Barramento 36V","Componente":6,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"7","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":31.0,"maximo":42.5,"nominal":37.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":200.0,"maximo":75000.0,"nominal":2500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":35.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"LUZABT","ID_Num":31,"Descricao":"Luminosidade Ambiente","Componente":30,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x29","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":55,"posicao":2,"indice":0,"minimo":50.0,"maximo":80000.0,"nominal":10000.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"Lux"}]},{"ID":"IUVABT","ID_Num":32,"Descricao":"Indice de radiacao UV Ambiente","Componente":31,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[51],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":51,"posicao":2,"indice":1,"minimo":0.0,"maximo":11.0,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"IUV"}]},{"ID":"MQ2","ID_Num":33,"Descricao":"Gas e Fumaca","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":600.0,"nominal":50.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"MQ7","ID_Num":34,"Descricao":"Monoxido de carbono","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":400.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"QLDABT","ID_Num":35,"Descricao":"Qualidade do ar","Componente":32,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":57,"posicao":2,"indice":0,"minimo":0.0,"maximo":1000.0,"nominal":150.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPB"},{"funcao":58,"posicao":2,"indice":1,"minimo":400.0,"maximo":2000.0,"nominal":600.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"},{"funcao":59,"posicao":2,"indice":2,"minimo":1.0,"maximo":3.0,"nominal":1.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"AQI"},{"funcao":54,"posicao":3,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":3,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"SHTABT","ID_Num":36,"Descricao":"Temperatura e Umidade Ambiente","Componente":29,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x44","QtdBytes":1,"Escalar":false,"Enviar":false},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":2,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"CHVABT","ID_Num":37,"Descricao":"Chuva","Componente":33,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[52],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":52,"posicao":2,"indice":1,"minimo":0.0,"maximo":100.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]}],"Sinaleiros":[{"ID":"LEDMN","ID_Num":21,"Descricao":"Sinaleiro indicação de modo Manual ativo","Componente":15,"Funcoes":[38],"Comportamento":{"statusLED":2,"QtdPiscadas":1,"TempoMs":1000,"PausaMs":2000},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"LEDAT","ID_Num":22,"Descricao":"Sinaleiro indicação de modo Automático ativo","Componente":15,"Funcoes":[38],"Comportamento":{"statusLED":2,"QtdPiscadas":1,"TempoMs":1000,"PausaMs":2000},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"LEDOP","ID_Num":23,"Descricao":"Sinaleiro indicação do status da operação ativa","Componente":15,"Funcoes":[38],"Comportamento":{"statusLED":2,"QtdPiscadas":1,"TempoMs":1000,"PausaMs":2000},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]}],"Reles":[{"ID":"RLCIN","ID_Num":81,"Descricao":"Rele Cooler Entrada","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0},{"ID":"RLCOUT","ID_Num":82,"Descricao":"Rele Cooler Saida","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0}],"Servos":[{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]}],"CameraCaminho":{"Dispositivo":0,"Index":0,"Id":null,"Name":null,"Description":"(0) ","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":null,"Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}},"CamerasSolo":[{"Dispositivo":0,"Index":0,"Id":null,"Name":null,"Description":"(0) ","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":null,"Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}}],"ConfiguracaoSensorUltrassom":{"Configuracao":0,"Sensores":[{"ID":1,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":2,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":3,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":4,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false}],"_paradaFrontal":false,"_paradaTraseira":false,"_paradaEsquerda":false,"_paradaDireita":false,"DesvioNecessario":false,"ParadaNecessaria":false,"DirecoesObstaculos":[],"DirecaoDesvio":1},"loRaService":{"ID":"LoRa","ID_Num":251,"Componente":26,"Conectado":false,"Configurado":false,"Iniciado":false,"FrequenciaEnvioDadosBase":0.2,"TempoEnvioDadosBase":5000.0,"UltimoRxDados":0.0,"_ultimoRxDados":"0001-01-01T00:00:00","UltimoTxDados":0.0,"_ultimoTxDados":"0001-01-01T00:00:00","ParametrosSet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":192,"power":0,"packetSizeAndPower":192,"tranMode":64,"worCycle":3,"tranModeAndWorCycle":67,"channelRssi":0,"lbt":0,"packetRssi":0,"address":2,"channel":65,"key":0},"ParametrosGet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":0,"airRate":0,"baudAndAirRate":0,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":0,"worCycle":0,"tranModeAndWorCycle":0,"channelRssi":0,"lbt":0,"packetRssi":0,"address":0,"channel":0,"key":0},"Funcoes":[14,47,48,49,3,2],"MensagensRecebidasAvulsas":[]},"LoRaParametrosBase":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":64,"worCycle":7,"tranModeAndWorCycle":71,"channelRssi":0,"lbt":0,"packetRssi":0,"address":1,"channel":23,"key":0}}
\ No newline at end of file
+{"ContadorCarga":{"TempoEstimadoMinutos":0.0,"Iniciado":false,"CargaAtualAmp":20.0,"_Consumido":0.0,"ConsumidoAmp":0.0,"PercentualAtual":100.0,"PercentualConsumido":0.0,"PercentualBateria":0.0,"EnergiaConsumida_Wh":0.0,"_dt":0.0,"CorrenteInstantanea":0.0,"TensaoInstantanea":0.0,"PotenciaInstantanea":0.0,"WhRestante":840.0,"WhPorMetro":0.0,"WhPorMetroBase":0.1167,"WhPorMetroHistorico":0.0,"WhPorMetroReferencia":0.1167,"DistanciaMaximaTeorica_m":0.0,"DistanciaMaximaSegura_m":0.0,"DistanciaEstimadaRestante_m":0.0,"MargemSegurancaAutonomia":0.3},"CoolerControl":{"TempOn":55.0,"TempTurbo":65.0,"TempCritical":75.0,"Histerese":1.5,"MinOnTime":"00:00:30","MinOffTime":"00:00:30","AlphaFiltro":0.2,"ModoAtual":0,"CoolerEntradaEstado":0,"CoolerSaidaEstado":0,"CoolerEntradaLeitura":0,"CoolerSaidaLeitura":0,"TemperaturaFiltrada":48.856718752856395,"UltimaMudancaModo":"2026-02-05T16:23:03.2475687-03:00","AlertaTemperaturaCritica":false},"tmrRegistrador":{"_uiControl":null,"State":1,"IsRunning":true,"IsStopped":false,"IsCreated":false,"IsDisposed":false,"Interval":1000,"IntervalHz":1.0,"StackTrace":"SensoriamentoModel.IniciarRegistrador","Id":"tmrRegistrador_Sen","TimeTick":"00:00:00"},"Dispositivo":102,"Modulo_ID":"Sen","_EnderecoCAN_Tx":17,"_EnderecoCAN_Rx":17,"_TaxaAmostragem":1000,"FrequenciaBase":1.0,"RequisitarDados":true,"Conectado":false,"ConexaoAtiva":false,"DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Dispositivo":0,"Versao":0,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"UltimoComandoRespondido":"0001-01-01T00:00:00","Sensores":null,"Sinaleiros":null,"Reles":null,"Servos":null},"Sensores":[{"ID":"TMVET","ID_Num":1,"Descricao":"Temperatura Motor Esquerdo Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVEF","ID_Num":2,"Descricao":"Temperatura Motor Esquerdo Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDT","ID_Num":3,"Descricao":"Temperatura Motor Direito Trás","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TMVDF","ID_Num":4,"Descricao":"Temperatura Motor Direito Frente","Componente":4,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":80.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"TBAT","ID_Num":5,"Descricao":"Temperatura da bateria","Componente":4,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[12],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":1,"minimo":5.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"}]},{"ID":"AB3V","ID_Num":11,"Descricao":"Corrente no Barramento 3V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"5","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":3.0,"maximo":3.4,"nominal":3.3,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":500.0,"nominal":100.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB5V","ID_Num":12,"Descricao":"Corrente no Barramento 5V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":4.9,"maximo":5.2,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":1000.0,"nominal":300.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB7V2","ID_Num":13,"Descricao":"Corrente no Barramento 7,2V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":7.0,"maximo":7.4,"nominal":7.2,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":0.0,"maximo":3000.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB12V","ID_Num":14,"Descricao":"Corrente no Barramento 12V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":11.5,"maximo":12.5,"nominal":12.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":50.0,"maximo":10000.0,"nominal":500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB19V","ID_Num":15,"Descricao":"Corrente no Barramento 19V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":18.8,"maximo":19.2,"nominal":19.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":500.0,"maximo":4000.0,"nominal":1500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB24V","ID_Num":16,"Descricao":"Corrente no Barramento 24V","Componente":6,"Aferir":true,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"6","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":23.8,"maximo":24.3,"nominal":24.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":100.0,"maximo":20000.0,"nominal":700.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"AB36V","ID_Num":17,"Descricao":"Corrente no Barramento 36V","Componente":6,"Aferir":true,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x40","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Shunt","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"7","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":28,"posicao":2,"indice":0,"minimo":31.0,"maximo":42.5,"nominal":37.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"V"},{"funcao":29,"posicao":2,"indice":1,"minimo":200.0,"maximo":75000.0,"nominal":2500.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"mA"},{"funcao":53,"posicao":2,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW"},{"funcao":61,"posicao":3,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"mW/h"},{"funcao":54,"posicao":3,"indice":1,"minimo":0.0,"maximo":60.0,"nominal":35.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":69,"posicao":3,"indice":2,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}]},{"ID":"LUZABT","ID_Num":31,"Descricao":"Luminosidade Ambiente","Componente":30,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x29","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":55,"posicao":2,"indice":0,"minimo":50.0,"maximo":80000.0,"nominal":10000.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"Lux"}]},{"ID":"IUVABT","ID_Num":32,"Descricao":"Indice de radiacao UV Ambiente","Componente":31,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[51],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":51,"posicao":2,"indice":1,"minimo":0.0,"maximo":11.0,"nominal":5.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"IUV"}]},{"ID":"MQ2","ID_Num":33,"Descricao":"Gas e Fumaca","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"0","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":600.0,"nominal":50.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"MQ7","ID_Num":34,"Descricao":"Monoxido de carbono","Componente":28,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[50],"Parametros":[{"Descricao":"Tipo","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":50,"posicao":2,"indice":1,"minimo":0.0,"maximo":400.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"}]},{"ID":"QLDABT","ID_Num":35,"Descricao":"Qualidade do ar","Componente":32,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":57,"posicao":2,"indice":0,"minimo":0.0,"maximo":1000.0,"nominal":150.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPB"},{"funcao":58,"posicao":2,"indice":1,"minimo":400.0,"maximo":2000.0,"nominal":600.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"PPM"},{"funcao":59,"posicao":2,"indice":2,"minimo":1.0,"maximo":3.0,"nominal":1.5,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"AQI"},{"funcao":54,"posicao":3,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":3,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"SHTABT","ID_Num":36,"Descricao":"Temperatura e Umidade Ambiente","Componente":29,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x44","QtdBytes":1,"Escalar":false,"Enviar":false},{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":54,"posicao":2,"indice":0,"minimo":0.0,"maximo":50.0,"nominal":25.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"ºC"},{"funcao":56,"posicao":2,"indice":1,"minimo":20.0,"maximo":90.0,"nominal":60.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"CHVABT","ID_Num":37,"Descricao":"Chuva","Componente":33,"Aferir":false,"Mandatorio":false,"Liberado":true,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[52],"Parametros":[{"Descricao":"Canal MUX","Valor":"-1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":52,"posicao":2,"indice":1,"minimo":0.0,"maximo":100.0,"nominal":10.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":"%"}]},{"ID":"MAGET","ID_Num":91,"Descricao":"Angulo Direcional ET","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"1","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDT","ID_Num":92,"Descricao":"Angulo Direcional DT","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"2","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGEF","ID_Num":93,"Descricao":"Angulo Direcional EF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"3","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]},{"ID":"MAGDF","ID_Num":94,"Descricao":"Angulo Direcional DF","Componente":13,"Aferir":false,"Mandatorio":true,"Liberado":false,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","Funcoes":[27],"Parametros":[{"Descricao":"Endereço I2C","Valor":"0x36","QtdBytes":1,"Escalar":false,"Enviar":true},{"Descricao":"Canal MUX","Valor":"4","QtdBytes":1,"Escalar":false,"Enviar":true}],"ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":70,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":""},{"funcao":71,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":"°"}]}],"Sinaleiros":[{"ID":"LEDMN","ID_Num":21,"Descricao":"Sinaleiro indicação de modo Manual ativo","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":99,"statusOperacao":null,"statusLED":0,"QtdPiscadas":0,"TempoMs":0,"PausaMs":0},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0},{"ID":"LEDAT","ID_Num":22,"Descricao":"Sinaleiro indicação de modo Automático ativo","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":99,"statusOperacao":null,"statusLED":1,"QtdPiscadas":0,"TempoMs":0,"PausaMs":0},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0},{"ID":"LEDOP","ID_Num":23,"Descricao":"Sinaleiro indicação do status da operação ativa","Componente":15,"Controlar":true,"Mandatorio":false,"Funcoes":[38],"Comportamento":{"id":1,"statusOperacao":1,"statusLED":2,"QtdPiscadas":2,"TempoMs":800,"PausaMs":2000},"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":62,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":63,"posicao":2,"indice":1,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_StatusLedId":99,"_StatusLed":0}],"Reles":[{"ID":"RLCIN","ID_Num":81,"Descricao":"Rele Cooler Entrada","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0},{"ID":"RLCOUT","ID_Num":82,"Descricao":"Rele Cooler Saida","Componente":21,"Funcoes":[72],"Controlar":true,"Mandatorio":false,"Liberado":true,"AtuacaoNivelAlto":true,"StatusControle":0,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":66,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null}],"_EstadoLeitura":0}],"Servos":[{"ID":"FROET","ID_Num":41,"Descricao":"Freio Motor ET","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FROEF","ID_Num":42,"Descricao":"Freio Motor EF","Componente":34,"Funcoes":[45],"Incremental":true,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":0,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODT","ID_Num":43,"Descricao":"Freio Motor DT","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":true,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]},{"ID":"FRODF","ID_Num":44,"Descricao":"Freio Motor DF","Componente":34,"Funcoes":[45],"Incremental":false,"Controlar":false,"Mandatorio":false,"Liberado":true,"_AnguloControle":180,"_AnguloLeiutra":-1,"Inicializado":false,"UltimaLeitura":"0001-01-01T00:00:00","ValoresLeituras":[{"funcao":60,"posicao":0,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":false,"unidade_medida":null},{"funcao":64,"posicao":2,"indice":0,"minimo":0.0,"maximo":0.0,"nominal":0.0,"offset":0.0,"atual":{"valor":null,"lidoEm":"0001-01-01T00:00:00","frequencia":0.0,"dt":0.0,"ValorMaximo":-1.7976931348623157E+308,"ValorMinimo":1.7976931348623157E+308},"analise_health":true,"unidade_medida":null}]}],"CameraCaminho":{"Dispositivo":117,"Index":0,"Id":"14442C10C143E2D600","Name":"OAK-D Lite","Description":"(0) OAK-D Lite","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":"1.1","Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}},"CamerasSolo":[{"Dispositivo":-1,"Index":-1,"Id":null,"Name":"Sem Video","Description":"(-1) Sem Video","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":null,"Memory_Usage":null,"Temperature":null,"Bootloader_Version":null,"Is_Pipeline_Running":false,"fx":0.0,"baseline":0.0,"DistanciaMaximaVisao":5000.0,"DistanciaMinimaVisao":500.0,"PercentualAlturaSolo":30.0,"frames":{}}],"ConfiguracaoSensorUltrassom":{"Configuracao":0,"Sensores":[{"ID":1,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":2,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":3,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false},{"ID":4,"Posicao":0,"LimiteMinimo":false,"LimiteMinimoVal":0.0,"MargemMinimo":0.0,"LimiteMaximo":false,"LimiteMaximoVal":0.0,"MargemMaximo":0.0,"Desvio":false,"Parada":false,"DistanciaIdeal":0.0,"EmUso":false,"LeituraCm":0.0,"SensorAtuado":false}],"_paradaFrontal":false,"_paradaTraseira":false,"_paradaEsquerda":false,"_paradaDireita":false,"DesvioNecessario":false,"ParadaNecessaria":false,"DirecoesObstaculos":[],"DirecaoDesvio":1},"loRaService":{"ID":"LoRa","ID_Num":251,"Componente":26,"Conectado":false,"Configurado":false,"Iniciado":false,"FrequenciaEnvioDadosBase":0.2,"TempoEnvioDadosBase":5000.0,"UltimoRxDados":0.0,"_ultimoRxDados":"0001-01-01T00:00:00","UltimoTxDados":0.0,"_ultimoTxDados":"0001-01-01T00:00:00","ParametrosSet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":192,"power":0,"packetSizeAndPower":192,"tranMode":64,"worCycle":3,"tranModeAndWorCycle":67,"channelRssi":0,"lbt":0,"packetRssi":0,"address":2,"channel":65,"key":0},"ParametrosGet":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":0,"airRate":0,"baudAndAirRate":0,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":0,"worCycle":0,"tranModeAndWorCycle":0,"channelRssi":0,"lbt":0,"packetRssi":0,"address":0,"channel":0,"key":0},"Funcoes":[14,47,48,49,3,2],"MensagensRecebidasAvulsas":[]},"LoRaParametrosBase":{"UltimaLeitura":"0001-01-01T00:00:00","PortaCOM":"","baudRate":96,"airRate":0,"baudAndAirRate":96,"parity":0,"packetSize":0,"power":0,"packetSizeAndPower":0,"tranMode":64,"worCycle":7,"tranModeAndWorCycle":71,"channelRssi":0,"lbt":0,"packetRssi":0,"address":1,"channel":23,"key":0}}
\ No newline at end of file
diff --git a/AgroBase/AgroBase/bin/x64/Debug/Parametros/version_files.vsf b/AgroBase/AgroBase/bin/x64/Debug/Parametros/version_files.vsf
index f790913ab..07afa8da0 100644
--- a/AgroBase/AgroBase/bin/x64/Debug/Parametros/version_files.vsf
+++ b/AgroBase/AgroBase/bin/x64/Debug/Parametros/version_files.vsf
@@ -21,19 +21,19 @@
"id": 3,
"Arquivo": "modelseg",
"Diretorio": "C:\\AgroBaseModels\\Ruas\\",
- "Extensao": ".blob",
- "Versao": "1_2",
+ "Extensao": ".pt",
+ "Versao": "1_3",
"TipoArquivo": 0,
- "ArquivoDownload": "models/street_detector_model_seg-1_2.blob",
+ "ArquivoDownload": "models/street_detector_model_seg-1_3.pt",
},
{
"id": 4,
"Arquivo": "modelseg",
"Diretorio": "C:\\AgroBaseModels\\Ruas\\",
"Extensao": ".txt",
- "Versao": "1_2",
+ "Versao": "1_3",
"TipoArquivo": 0,
- "ArquivoDownload": "models/street_detector_labelmap_seg-1_2.txt"
+ "ArquivoDownload": "models/street_detector_labelmap_seg-1_3.txt"
},
{
"id": 5,
diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py
index 5f820c63f..7833599af 100644
--- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py
+++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/main.py
@@ -19,6 +19,7 @@ def main():
from health_worker.modulos.ponte_ip import ModuloIPBribge
from health_worker.modulos.can import ModuloCAN
from health_worker.modulos.trajetoria import ModuloTrajetorira
+ from health_worker.modulos.bateria import ModuloBateria
from health_worker.config import mostrar_log
from shared.contexto_global_redis import ContextoGlobalRedis, CmdKey, CtxKey
@@ -35,6 +36,7 @@ def main():
T_Code.Ipb: ModuloIPBribge(),
T_Code.Can: ModuloCAN(),
T_Code.Trj: ModuloTrajetorira(),
+ T_Code.Bat: ModuloBateria(),
}
def loop_ativo():
diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/camera_manager.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/camera_manager.py
index c22826370..2cea88bd4 100644
--- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/camera_manager.py
+++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/camera_manager.py
@@ -514,7 +514,7 @@ class CameraManager:
t1 = time.time()
grid_conf["ultima_chamada"] = self._ultima_analise_matriz_confianca.get("ultima_chamada", t0)
self._calcular_performance(t0, t1, grid_conf)
- snapshot = self.data_fuser.update(grid_conf, velocidade_ms=vel)
+ snapshot = self.data_fuser.update(grid_conf, velocidade_ms=vel, status_seg=self._ultima_analise_segmentacao.get("dados_visuais", {}).get("status_corredor"))
self._ultima_analise_matriz_confianca = grid_conf
ContextoGlobalRedis.atualizar_ctx_dict(
diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/costmap_fuser.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/costmap_fuser.py
index e9b4897e5..82a9d6f5a 100644
--- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/costmap_fuser.py
+++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/costmap_fuser.py
@@ -1,6 +1,7 @@
import math
import time
import numpy as np
+from shared.enums import StatusCarroMapa
class CostmapFuser:
@@ -124,7 +125,9 @@ class CostmapFuser:
det_score_f=None, # (H,W) 0..1
det_label_id=None, # (H,W) int, -1 = none
det_strength=None, # (H,W) 0..1 ~ conf*cov dominante
- thr_det_consider=0.15
+ thr_det_consider=0.15,
+
+ status_seg=StatusCarroMapa.Direcionando
):
try:
H, W = custo_f.shape
@@ -402,7 +405,7 @@ class CostmapFuser:
"N_on": N_on,
"N_off": N_off
}
- blocked_out = blocked_raw
+ blocked_out = status_seg == StatusCarroMapa.Parado or blocked_raw
if use_persistence:
v = float(max(0.0, velocidade_mps or 0.0))
@@ -444,13 +447,14 @@ class CostmapFuser:
elif st["latched"] and (st["off"] >= N_off):
st["latched"] = False
+ blocked_out = status_seg == StatusCarroMapa.Parado or bool(st["latched"])
+
decision.update({
- "parar": False, # bool(st["latched"]),
+ "parar": blocked_out,
"v_max_sugerida_mps": v_max_sug,
"frames_on": int(st["on"]),
"frames_off": int(st["off"])
})
- blocked_out = bool(st["latched"])
st["reason"] = reason
# guarda também as duas distâncias pra debug
@@ -494,7 +498,7 @@ class CostmapFuser:
except Exception as e:
mostrar_log("Erro no _row_scale_x")
- def update(self, grid_dict, ts=None, velocidade_ms=0.0):
+ def update(self, grid_dict, ts=None, velocidade_ms=0.0, status_seg=StatusCarroMapa.Direcionando):
"""
grid_dict deve conter (grid_h,grid_w): "custo","conf","anom","navegavel"
opcional: "z_ref" (m) 2D
@@ -598,7 +602,8 @@ class CostmapFuser:
det_score_f = det_score,
det_label_id = det_lbl,
det_strength = det_sdom,
- thr_det_consider = 0.25 # só considera detecção acima desse score
+ thr_det_consider = 0.25,
+ status_seg=status_seg
)
# incrementa seq
diff --git a/Python/OAK/datasets/_5_augmentation_raw.py b/Python/OAK/datasets/_5_augmentation_raw.py
index baa371de6..bc88021f4 100644
--- a/Python/OAK/datasets/_5_augmentation_raw.py
+++ b/Python/OAK/datasets/_5_augmentation_raw.py
@@ -1,41 +1,30 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
-Augmenta imagens/máscaras *por grupo*, agora com suporte a RAW.
+Augmenta imagens/máscaras *por grupo* usando RAW4 (float32, 0..1, R G IR B).
-Modos suportados:
+Novo fluxo (GAL5000):
-1) Modo novo (RAW):
- MODELO/dataset/original/group//previews
- MODELO/dataset/original/group//raws
- MODELO/dataset/original/group//masks
- (opcional) MODELO/dataset/original/group//masks2
+Entrada:
+ MODELO/dataset/original/group//raws (.raw, 4 canais float32)
+ MODELO/dataset/original/group//masks (.png/.jpg)
+ (opcional) MODELO/dataset/original/group//masks2
- Saída:
- MODELO/dataset/augmented/group//previews
- MODELO/dataset/augmented/group//raws
- MODELO/dataset/augmented/group//masks
- MODELO/dataset/augmented/group//masks2 (se existir)
+Saída:
+ MODELO/dataset/augmented/group//previews (RGB gerado do RAW blurado)
+ MODELO/dataset/augmented/group//raws (RAW4 augmentado: geom + blur)
+ MODELO/dataset/augmented/group//masks
+ MODELO/dataset/augmented/group//masks2
-2) Modo antigo (sem RAW, só images/masks):
- MODELO/dataset/original/group//images
- MODELO/dataset/original/group//masks
-
- Saída:
- MODELO/dataset/augmented/group//images
- MODELO/dataset/augmented/group//masks
-
-Fallback legacy:
- MODELO/dataset/original/{images,masks}
- MODELO/dataset/augmented/{images,masks}
-
-Transformações:
-- Geométricas (HorizontalFlip, ShiftScaleRotate) → aplicam em preview, mask, mask2 e RAW.
-- Fotométricas (brightness/contrast, gamma, blur, noise, flare, etc.) → só em preview RGB.
+Regras:
+- GEOMETRIA (flip, shift, rotate) aplicada em RAW + masks (+ masks2).
+- BLUR / MOTION BLUR aplicado no RAW, canal por canal, com o mesmo kernel.
+- Preview é SEMPRE derivado do RAW já transformado (geom + blur).
+- Máscaras não sofrem blur, apenas geom.
Uso:
- python _5_augmentation.py --copies 5
- python _5_augmentation.py --copies 5 --groups chao,chao_erva,cana
+ python _5_augmentation_raw.py --copies 5
+ python _5_augmentation_raw.py --copies 5 --groups chao,chao_erva,cana
"""
import os
import json
@@ -50,6 +39,8 @@ import numpy as np
with open("config.json", "r", encoding="utf-8") as f:
config = json.load(f)
MODELO = config.get("camera", ".")
+RESOLUCAO = config.get("raw_size")
+
USE_MASKS2 = config.get("dual_head", False)
# Pastas base
@@ -57,7 +48,7 @@ DATASET_BASE = os.path.join(MODELO, "dataset")
ORIG_GROUP_ROOT = os.path.join(DATASET_BASE, "original", "group")
AUG_GROUP_ROOT = os.path.join(DATASET_BASE, "augmented", "group")
-# Fallback (modo antigo, sem grupos)
+# Fallback (modo antigo, sem grupos) – mantido por compat
ORIG_OLD_IMG = os.path.join(DATASET_BASE, "original", "images")
ORIG_OLD_MSK = os.path.join(DATASET_BASE, "original", "masks")
ORIG_OLD_MSK2 = os.path.join(DATASET_BASE, "original", "masks2")
@@ -67,16 +58,10 @@ AUG_OLD_MSK2 = os.path.join(DATASET_BASE, "augmented", "masks2")
# Extensões aceitas
IMG_EXTS = (".jpg", ".jpeg", ".png")
-MSK_EXTS = (".png", ".jpg", ".jpeg") # prioriza PNG
+MSK_EXTS = (".png", ".jpg", ".jpeg")
MSK2_EXTS = (".png", ".jpg", ".jpeg")
RAW_EXTS = (".raw",)
-# Config de RAW (mosaico 1 canal; R G / IR B é tratado depois no loader)
-RAW_DTYPE = np.uint16
-RAW_CHANNELS = 1 # tratamos como grayscale (H, W)
-# Se RAW tiver tamanho diferente, ajuste no loader depois.
-# Aqui assumimos que altura/largura batem com preview/mask.
-
def garantir_dir(p):
os.makedirs(p, exist_ok=True)
@@ -86,7 +71,8 @@ def garantir_dir(p):
# Pipelines de augmentations
# ===============================
-# Geométricas: aplicam em preview, mask, mask2 e RAW
+# 1) Geométricas: aplicam em preview “temporário”, mask, mask2 e RAW.
+# RAW é passado como 'raw' em additional_targets para receber só geom.
train_geo = ReplayCompose([
A.HorizontalFlip(p=0.5),
A.ShiftScaleRotate(
@@ -99,32 +85,144 @@ train_geo = ReplayCompose([
),
], additional_targets={
'mask2': 'mask',
- 'raw': 'mask', # tratamos RAW como "mask" pra NÃO sofrer fotométricas
+ 'raw': 'mask', # trata raw como “mask” para receber apenas geom
})
-# Fotométricas: só preview RGB
-train_photo = A.Compose([
- A.OneOf([
- A.RandomBrightnessContrast(0.2, 0.2, p=1.0),
- A.HueSaturationValue(hue_shift_limit=5, sat_shift_limit=20, val_shift_limit=15, p=1.0),
- A.RandomGamma(gamma_limit=(90, 110), p=1.0),
- ], p=0.70),
- A.OneOf([
- A.MotionBlur(blur_limit=3, p=1.0),
- A.GaussianBlur(blur_limit=3, p=1.0),
- ], p=0.20),
+# ===============================
+# Funções de blur físico no RAW
+# ===============================
- A.OneOf([
- A.GaussNoise(var_limit=(5.0, 15.0), p=1.0),
- A.ImageCompression(quality_lower=50, quality_upper=85, p=1.0),
- ], p=0.20),
+def motion_blur_kernel(ksize=5, angle=0.0):
+ """
+ Gera um kernel de motion blur 2D com tamanho ksize e ângulo em graus.
+ Usado tanto para RAW quanto para preview.
+ """
+ ksize = int(ksize)
+ if ksize < 3:
+ ksize = 3
+ if ksize % 2 == 0:
+ ksize += 1
- A.RandomShadow(p=0.10),
- A.RandomSunFlare(p=0.10),
- A.ChannelShuffle(p=0.05),
- A.CoarseDropout(max_holes=6, max_height=16, max_width=16, p=0.10),
-])
+ kernel = np.zeros((ksize, ksize), dtype=np.float32)
+ # linha horizontal no centro
+ kernel[ksize // 2, :] = 1.0
+
+ # rotaciona a linha para o ângulo desejado
+ center = (ksize / 2.0 - 0.5, ksize / 2.0 - 0.5)
+ M = cv2.getRotationMatrix2D(center, angle, 1.0)
+ kernel = cv2.warpAffine(kernel, M, (ksize, ksize))
+
+ s = kernel.sum()
+ if s > 0:
+ kernel /= s
+ return kernel
+
+
+def apply_coherent_blur_raw(raw, p_motion=0.20, p_gauss=0.20):
+ """
+ Aplica blur/motion blur de forma COERENTE no RAW, canal por canal.
+
+ - Mesmo kernel em TODOS os canais.
+ - Máscaras não passam aqui.
+ - Se nada for sorteado, retorna o RAW original.
+ """
+ if raw is None:
+ return None
+
+ r = np.random.rand()
+ if r >= (p_motion + p_gauss):
+ # sem blur nesta amostra
+ return raw
+
+ # escolhe tamanho de kernel
+ k_choices = [3, 5, 7]
+ ksize = int(np.random.choice(k_choices))
+
+ if r < p_motion:
+ # Motion blur com ângulo pequeno (vibração / movimento leve)
+ angle = float(np.random.uniform(-20.0, 20.0))
+ kernel = motion_blur_kernel(ksize=ksize, angle=angle)
+ else:
+ # Gaussian blur (leve desfoque de foco)
+ if ksize % 2 == 0:
+ ksize += 1
+ g1d = cv2.getGaussianKernel(ksize, 0)
+ kernel = g1d @ g1d.T # vira kernel 2D
+
+ # Aplica kernel canal a canal
+ if raw.ndim == 2:
+ raw_blur = cv2.filter2D(raw, ddepth=-1, kernel=kernel)
+ else:
+ raw_blur = np.empty_like(raw)
+ h, w, c = raw.shape
+ for ch in range(c):
+ raw_blur[..., ch] = cv2.filter2D(
+ raw[..., ch],
+ ddepth=-1,
+ kernel=kernel,
+ borderType=cv2.BORDER_REFLECT_101,
+ )
+
+ # Garante que continua em [0,1] para float
+ if np.issubdtype(raw_blur.dtype, np.floating):
+ raw_blur = np.clip(raw_blur, 0.0, 1.0)
+
+ return raw_blur
+
+
+# ===============================
+# IO de imagens / RAW
+# ===============================
+
+def raw_to_preview_rgb(raw_np: np.ndarray) -> np.ndarray:
+ """
+ raw_np: (H,W,C) float32 em 0..1, C=4 ou 5.
+
+ Layout esperado (após _load_raw):
+ - C=4 -> [R,G,B,IR]
+ - C=5 -> [R,G,B,IR,NDVI] (se um dia tiver)
+
+ Usamos sempre R,G,B para o preview e devolvemos (H,W,3) uint8.
+ """
+ assert raw_np.ndim == 3, "raw_np deve ser (H,W,C)"
+
+ H, W, C = raw_np.shape
+ if C not in (4, 5):
+ raise RuntimeError(f"Esperado C=4 ou 5, veio {C} em raw_to_preview_rgb")
+
+ # RAW já vem como [R,G,B,IR] do _load_raw
+ r = raw_np[..., 0].astype(np.float32)
+ g = raw_np[..., 1].astype(np.float32)
+ b = raw_np[..., 2].astype(np.float32)
+
+ # Monta RGB em (H,W,3) para trabalhar
+ rgb = np.stack([r, g, b], axis=-1) # (H,W,3)
+
+ # Auto white balance simples (referenciado no G)
+ means = rgb.reshape(-1, 3).mean(axis=0) # (3,)
+ ref = means[1] # canal G
+ gains = ref / (means + 1e-6)
+ gains = np.clip(gains, 0.5, 2.0)
+ rgb_wb = rgb * gains # broadcasting em (3,)
+
+ # Força do WB
+ alpha = 1.0 # teste 0.4..0.8 se quiser misturar com original
+ if alpha >= 0.999:
+ rgb = rgb_wb
+ else:
+ rgb_orig = rgb.copy()
+ rgb = (1 - alpha) * rgb_orig + alpha * rgb_wb
+
+ rgb = np.clip(rgb, 0.0, 1.0)
+
+ # Gamma mais suave
+ rgb = np.power(rgb, 1/1.9, out=rgb)
+
+ # Converte pra uint8 OpenCV-friendly
+ rgb8 = (rgb * 255.0).clip(0, 255).astype(np.uint8) # (H,W,3)
+
+ return rgb8
def load_rgb(path):
@@ -138,40 +236,101 @@ def save_rgb(path, arr_rgb):
Image.fromarray(arr_rgb).save(path)
-def load_raw_grayscale(path, like_shape=None):
- """
- Carrega RAW como (H, W) em uint8 ou uint16 detectando pelo tamanho do arquivo.
- """
- if like_shape is None:
- raise RuntimeError("like_shape é obrigatório para RAW (preciso do HxW).")
-
- h, w = like_shape[:2]
- npx = h * w
-
- fsize = os.path.getsize(path)
- if fsize == npx: # 1 byte por pixel
- dtype = np.uint8
- elif fsize == npx * 2: # 2 bytes por pixel
- dtype = np.uint16
+def _load_raw(path: str, raw_hw) -> np.ndarray:
+ ext = os.path.splitext(path)[1].lower()
+ if ext == ".npz":
+ z = np.load(path)
+ key = list(z.keys())[0]
+ arr = z[key]
+ elif ext == ".npy":
+ arr = np.load(path)
+ elif ext == ".raw":
+ if raw_hw is None:
+ raise RuntimeError(
+ f"Para ler .raw preciso de raw_hw=(H,W). "
+ f"Passe raw_hw ao criar o dataset."
+ )
+ H, W = raw_hw
+ size_bytes = os.path.getsize(path)
+ mosa_bytes = H * W # mosaico uint8
+ raw4_bytes = 4 * H * W * 4 # 4 canais * H * W * 4 bytes (float32)
+ if size_bytes == mosa_bytes:
+ # MODO ANTIGO: mosaico uint8
+ arr = np.fromfile(path, dtype=np.uint8)
+ raw2d = arr.reshape(H, W)
+ if (H % 2) != 0 or (W % 2) != 0:
+ raise RuntimeError(f"raw_hw deve ser par em H e W p/ mosaico 2x2 (R,G,IR,B), veio H={H}, W={W}")
+ H2, W2 = H // 2, W // 2
+ r_sub = raw2d[0::2, 0::2]
+ g_sub = raw2d[0::2, 1::2]
+ ir_sub = raw2d[1::2, 0::2]
+ b_sub = raw2d[1::2, 1::2]
+ from PIL import Image
+ def upsample(ch_2d: np.ndarray) -> np.ndarray:
+ im = Image.fromarray(ch_2d) # uint8
+ im = im.resize((W, H), resample=Image.BILINEAR)
+ return np.array(im)
+ r_full = upsample(r_sub)
+ g_full = upsample(g_sub)
+ ir_full = upsample(ir_sub)
+ b_full = upsample(b_sub)
+ # (H, W, 4) uint8 [R,G,B,IR]
+ arr = np.stack([r_full, g_full, b_full, ir_full], axis=-1).astype(np.uint8)
+ elif size_bytes == raw4_bytes:
+ # NOVO MODO: RAW4 float32 salvo pelo normalize
+ arr_f32 = np.fromfile(path, dtype=np.float32)
+ raw4 = arr_f32.reshape(4, H, W) # (C,H,W) [R,G,IR,B]
+ arr = np.transpose(raw4, (1, 2, 0)) # (H,W,4) [R,G,IR,B]
+ # REORGANIZA PARA CONTRATO INTERNO: [R,G,B,IR]
+ arr = arr[..., [0, 1, 3, 2]]
+ else:
+ raise RuntimeError(
+ f"Tamanho inesperado em {path}: {size_bytes} bytes "
+ f"(esperado {mosa_bytes} ou {raw4_bytes})"
+ )
else:
- raise RuntimeError(
- f"Tamanho inesperado para RAW {path}: {fsize} bytes "
- f"(esperado {npx} (u8) ou {npx*2} (u16) para {w}x{h})."
- )
+ raise RuntimeError(f"Extensão não suportada para RAW: {ext} ({path})")
+ # Até aqui queremos (H,W,4) base
+ if arr.ndim != 3:
+ raise RuntimeError(f"RAW precisa ser 3D, veio {arr.shape} em {path}")
+ if arr.shape[0] == 4 and arr.shape[-1] != 4:
+ arr = np.transpose(arr, (1, 2, 0)) # (H,W,4)
+ if arr.shape[-1] != 4:
+ raise RuntimeError(f"Esperava 4 canais base, veio shape={arr.shape} em {path}")
+ return arr # (H,W,4)
- data = np.fromfile(path, dtype=dtype)
- if data.size != npx:
- raise RuntimeError(f"RAW {path}: size={data.size} != {npx} (HxW)")
-
- return data.reshape((h, w))
+def _scale_to_float01(raw: np.ndarray, max_value = None) -> np.ndarray:
+ if raw.dtype == np.uint16:
+ mv = float(max_value) if max_value is not None else 65535.0
+ elif raw.dtype == np.uint8:
+ mv = float(max_value) if max_value is not None else 255.0
+ else:
+ # float já vem normalizado ou não; se passar max_value, aplica
+ mv = float(max_value) if max_value is not None else None
+ raw_f = raw.astype(np.float32)
+ if mv is not None and mv > 0:
+ raw_f = raw_f / mv
+ # clip pra não explodir
+ raw_f = np.clip(raw_f, 0.0, 1.0)
+ return raw_f
-def save_raw_grayscale(path, arr):
- np.asarray(arr).tofile(path)
+def save_raw_any(path, arr):
+ arr = np.asarray(arr)
+ arr.tofile(path)
+# ===============================
+# Helpers de diretório / mapeamento
+# ===============================
+
def list_groups(root):
- """Lista grupos válidos (tem subpasta 'masks' e pelo menos 'images' ou 'previews')."""
+ """
+ Lista grupos válidos para o NOVO fluxo:
+ - group//raws
+ - group//masks
+ (previews/images não são mais obrigatórios)
+ """
if not os.path.isdir(root):
return []
grupos = []
@@ -180,8 +339,8 @@ def list_groups(root):
if not os.path.isdir(gdir):
continue
has_masks = os.path.isdir(os.path.join(gdir, "masks"))
- has_imgs = os.path.isdir(os.path.join(gdir, "images")) or os.path.isdir(os.path.join(gdir, "previews"))
- if has_masks and has_imgs:
+ has_raws = os.path.isdir(os.path.join(gdir, "raws"))
+ if has_masks and has_raws:
grupos.append(name)
return grupos
@@ -252,148 +411,167 @@ def ensure_aug_dirs(group_name=None, use_masks2=False, use_raw=False, is_preview
return img_out, msk_out, msk2_out, raw_out
+# ===============================
+# Núcleo: augmentação de um sample
+# ===============================
+
def augment_sample(
- img_path,
+ raw_path,
msk_path,
img_out_dir,
msk_out_dir,
copies,
msk2_path=None,
msk2_out_dir=None,
- raw_path=None,
raw_out_dir=None,
):
- base_img, img_ext = os.path.splitext(os.path.basename(img_path))
- base = base_img
+ """
+ Faz a augmentação a partir de UM RAW4 + máscara (e opcionalmente máscara2).
+
+ Passos:
+ 1) Carrega máscara (para saber HxW).
+ 2) Carrega RAW4 float32 usando HxW da máscara.
+ 3) Gera preview RGB a partir do RAW4 (para servir de "image" no Albumentations).
+ 4) Aplica GEOMETRIA (mesma em preview, mask, mask2 e raw).
+ 5) Aplica BLUR/MOTION BLUR no RAW geométrico, canal a canal, com o mesmo kernel.
+ 6) Gera preview final a partir do RAW blurado.
+ 7) Salva:
+ - preview_n em img_out_dir
+ - mask_n em msk_out_dir
+ - raw_n em raw_out_dir
+ - mask2_n em msk2_out_dir (se houver)
+ """
+ base_raw, raw_ext = os.path.splitext(os.path.basename(raw_path))
+ base = base_raw
base_msk, msk_ext = os.path.splitext(os.path.basename(msk_path))
- msk2_ext = os.path.splitext(os.path.basename(msk2_path))[1] if msk2_path else None
- raw_ext = os.path.splitext(os.path.basename(raw_path))[1] if raw_path else None
+ if base_msk != base:
+ print(f"[WARN] RAW '{base}' e máscara '{base_msk}' com bases diferentes, mas seguindo mesmo assim.")
- img = load_rgb(img_path)
+ msk2_ext = os.path.splitext(os.path.basename(msk2_path))[1] if msk2_path else None
+
+ # 1) Máscaras
msk = load_rgb(msk_path)
msk2 = load_rgb(msk2_path) if msk2_path else None
- if raw_path is not None and raw_out_dir is not None:
- # usa shape do preview pra validar RAW
- raw = load_raw_grayscale(raw_path, like_shape=img.shape)
- else:
- raw = None
+ # 2) RAW4
+ raw = _load_raw(raw_path, raw_hw=(RESOLUCAO[1], RESOLUCAO[0])) # (H,W,4) uint8
+ raw = _scale_to_float01(raw) # float32 0..1
+
+ # 3) Preview inicial derivado do RAW (antes de geom/blur, só referência)
+ img = raw_to_preview_rgb(raw)
gen = 0
for i in range(copies):
- # 1) GEOM: mesma transformação em img, mask, mask2 e raw
- if raw is not None:
- if msk2 is not None and msk2_out_dir:
- aug_geo = train_geo(image=img, mask=msk, mask2=msk2, raw=raw)
- else:
- aug_geo = train_geo(image=img, mask=msk, raw=raw)
+ # 4) GEOMETRIA: mesma transformação em img, mask, mask2 e raw
+ if msk2 is not None and msk2_out_dir:
+ aug_geo = train_geo(image=img, mask=msk, mask2=msk2, raw=raw)
else:
- if msk2 is not None and msk2_out_dir:
- aug_geo = train_geo(image=img, mask=msk, mask2=msk2)
- else:
- aug_geo = train_geo(image=img, mask=msk)
+ aug_geo = train_geo(image=img, mask=msk, raw=raw)
- img_g = aug_geo["image"]
msk_g = aug_geo["mask"]
raw_g = aug_geo.get("raw", None)
msk2_g = aug_geo.get("mask2", None) if (msk2 is not None and msk2_out_dir) else None
- # 2) FOTO: só preview RGB
- img_p = train_photo(image=img_g)["image"]
+ # 5) BLUR FÍSICO: aplica (ou não) o MESMO blur no RAW geométrico
+ raw_b = apply_coherent_blur_raw(raw_g)
- out_img = os.path.join(img_out_dir, f"{base}_aug_{i:02d}{img_ext}")
+ # 6) Preview final derivado do RAW blurado
+ img_b = raw_to_preview_rgb(raw_b)
+
+ # 7) Salva cópias
+ out_img = os.path.join(img_out_dir, f"{base}_aug_{i:02d}.png") # preview em PNG
out_msk = os.path.join(msk_out_dir, f"{base}_aug_{i:02d}{msk_ext}")
- save_rgb(out_img, img_p)
+ save_rgb(out_img, img_b)
save_rgb(out_msk, msk_g)
if msk2_g is not None and msk2_out_dir:
out_msk2 = os.path.join(msk2_out_dir, f"{base}_aug_{i:02d}{msk2_ext}")
save_rgb(out_msk2, msk2_g)
- if raw_g is not None and raw_out_dir:
+ if raw_b is not None and raw_out_dir:
out_raw = os.path.join(raw_out_dir, f"{base}_aug_{i:02d}{raw_ext}")
- save_raw_grayscale(out_raw, raw_g)
+ save_raw_any(out_raw, raw_b)
gen += 1
return gen
+# ===============================
+# Processamento por grupo
+# ===============================
+
def process_group(group_name, copies):
"""
- Processa um grupo único.
- Suporta:
- - group//previews + raws + masks (+ masks2)
- - group//images + masks (+ masks2) [modo antigo]
+ Processa um grupo único usando APENAS:
+ - group//raws
+ - group//masks (+ masks2 opcional)
+
+ Previews de entrada são ignoradas.
+ As de saída são geradas do RAW4 (geom + blur).
"""
gdir = os.path.join(ORIG_GROUP_ROOT, group_name)
- # prioridade para novo modo (previews/raws)
- img_dir_previews = os.path.join(gdir, "previews")
- img_dir_images = os.path.join(gdir, "images")
raw_dir = os.path.join(gdir, "raws")
msk_dir = os.path.join(gdir, "masks")
msk2_dir = os.path.join(gdir, "masks2")
- use_preview_mode = os.path.isdir(img_dir_previews)
- img_dir = img_dir_previews if use_preview_mode else img_dir_images
-
- if not (os.path.isdir(img_dir) and os.path.isdir(msk_dir)):
- print(f"[WARN] Grupo '{group_name}' inválido (sem images/previews ou masks). Pulando.")
+ if not (os.path.isdir(raw_dir) and os.path.isdir(msk_dir)):
+ print(f"[WARN] Grupo '{group_name}' inválido (precisa de 'raws' e 'masks'). Pulando.")
return 0
- use_raw = os.path.isdir(raw_dir)
+ use_raw = True
use_masks2 = USE_MASKS2 and os.path.isdir(msk2_dir)
- imgs = [f for f in os.listdir(img_dir) if os.path.splitext(f.lower())[1] in IMG_EXTS]
- msk_map = map_by_base_priorizando_png(msk_dir, MSK_EXTS)
- raw_map = map_raws_by_base(raw_dir) if use_raw else {}
+ raw_map = map_raws_by_base(raw_dir)
+ msk_map = map_by_base_priorizando_png(msk_dir, MSK_EXTS)
msk2_map = map_by_base_priorizando_png(msk2_dir, MSK2_EXTS) if use_masks2 else {}
img_out_dir, msk_out_dir, msk2_out_dir, raw_out_dir = ensure_aug_dirs(
group_name,
use_masks2=use_masks2,
use_raw=use_raw,
- is_preview_mode=use_preview_mode
+ is_preview_mode=True
)
count = 0
- for img_file in sorted(imgs):
- base, _ = os.path.splitext(img_file)
+ for base, raw_file in sorted(raw_map.items()):
msk_file = msk_map.get(base)
if not msk_file:
- print(f"[WARN] [{group_name}] Máscara não encontrada para {img_file}, pulando.")
+ print(f"[WARN] [{group_name}] Máscara não encontrada para RAW {base}, pulando.")
continue
- raw_file = raw_map.get(base) if use_raw else None
- if use_raw and not raw_file:
- print(f"[WARN] [{group_name}] RAW não encontrado para {img_file}, gerando só preview/mask (+mask2).")
-
msk2_file = msk2_map.get(base) if use_masks2 else None
if use_masks2 and not msk2_file:
- print(f"[WARN] [{group_name}] mask2 não encontrada para {img_file}, gerando só img+mask(+raw).")
+ print(f"[WARN] [{group_name}] mask2 não encontrada para {base}, gerando só RAW+preview+mask.")
try:
count += augment_sample(
- os.path.join(img_dir, img_file),
- msk_file,
- img_out_dir,
- msk_out_dir,
+ raw_path=raw_file,
+ msk_path=msk_file,
+ img_out_dir=img_out_dir,
+ msk_out_dir=msk_out_dir,
copies=copies,
msk2_path=msk2_file,
msk2_out_dir=msk2_out_dir,
- raw_path=raw_file,
raw_out_dir=raw_out_dir,
)
except Exception as e:
- print(f"[ERRO] [{group_name}] {img_file}: {e}")
+ print(f"[ERRO] [{group_name}] {base}: {e}")
print(f"[OK] Grupo '{group_name}' → {count} amostras geradas.")
return count
+# ===============================
+# Fallback legacy (sem RAW)
+# ===============================
+
def process_legacy(copies):
- """Fallback: modo sem grupos (original/images e original/masks)."""
+ """
+ Fallback: modo sem grupos (original/images e original/masks).
+ Mantido por compat, mas não usa RAW.
+ """
if not (os.path.isdir(ORIG_OLD_IMG) and os.path.isdir(ORIG_OLD_MSK)):
print("[WARN] Modo legacy não encontrado. Nada a fazer.")
return 0
@@ -412,7 +590,7 @@ def process_legacy(copies):
count = 0
for img_file in sorted(imgs):
- base, _ = os.path.splitext(img_file)
+ base, img_ext = os.path.splitext(img_file)
msk_file = msk_map.get(base)
if not msk_file:
print(f"[WARN] (legacy) Máscara não encontrada para {img_file}, pulando.")
@@ -422,23 +600,44 @@ def process_legacy(copies):
print(f"[WARN] (legacy) mask2 não encontrada para {img_file}, gerando só img+mask.")
try:
- count += augment_sample(
- os.path.join(ORIG_OLD_IMG, img_file),
- msk_file,
- img_out_dir,
- msk_out_dir,
- copies=copies,
- msk2_path=msk2_file,
- msk2_out_dir=msk2_out_dir,
- raw_path=None,
- raw_out_dir=None,
- )
+ img_path = os.path.join(ORIG_OLD_IMG, img_file)
+ img = load_rgb(img_path)
+ base_msk, msk_ext = os.path.splitext(os.path.basename(msk_file))
+ msk = load_rgb(msk_file)
+ msk2 = load_rgb(msk2_file) if msk2_file else None
+
+ for i in range(copies):
+ if msk2 is not None and msk2_out_dir:
+ aug_geo = train_geo(image=img, mask=msk, mask2=msk2)
+ else:
+ aug_geo = train_geo(image=img, mask=msk)
+
+ img_g = aug_geo["image"]
+ msk_g = aug_geo["mask"]
+ msk2_g = aug_geo.get("mask2", None) if (msk2 is not None and msk2_out_dir) else None
+
+ out_img = os.path.join(img_out_dir, f"{base}_aug_{i:02d}{img_ext}")
+ out_msk = os.path.join(msk_out_dir, f"{base_msk}_aug_{i:02d}{msk_ext}")
+ save_rgb(out_img, img_g)
+ save_rgb(out_msk, msk_g)
+
+ if msk2_g is not None and msk2_out_dir:
+ msk2_ext = os.path.splitext(msk2_file)[1]
+ out_msk2 = os.path.join(msk2_out_dir, f"{base_msk}_aug_{i:02d}{msk2_ext}")
+ save_rgb(out_msk2, msk2_g)
+
+ count += 1
+
except Exception as e:
print(f"[ERRO] (legacy) {img_file}: {e}")
print(f"[OK] Legacy → {count} amostras geradas.")
return count
+# ===============================
+# main
+# ===============================
+
def main(copies=5, groups_csv=None):
total = 0
if os.path.isdir(ORIG_GROUP_ROOT):
@@ -462,7 +661,7 @@ def main(copies=5, groups_csv=None):
if __name__ == "__main__":
- ap = argparse.ArgumentParser(description="Augmentação por grupos (preview/raw/masks ou images/masks)")
+ ap = argparse.ArgumentParser(description="Augmentação por grupos usando RAW4 (preview gerado do RAW).")
ap.add_argument("--copies", type=int, default=5, help="Número de cópias augmentadas por imagem (default=5).")
ap.add_argument("--groups", type=str, default=None, help="Lista de grupos separados por vírgula (ex: chao,erva_cana).")
args = ap.parse_args()
diff --git a/Python/OAK/datasets/_6_normalize_raw.py b/Python/OAK/datasets/_6_normalize_raw.py
index eb914f526..05a374b60 100644
--- a/Python/OAK/datasets/_6_normalize_raw.py
+++ b/Python/OAK/datasets/_6_normalize_raw.py
@@ -35,8 +35,11 @@ with open("config.json", "r", encoding="utf-8") as f:
MODELO = config["camera"]
USE_MASKS2 = config["dual_head"]
RESOLUCAO = tuple(config["resolucao"]) # [W,H]
+MODEL_NAME = config["model_name"]
+CHANNELS = int(config.get("channels", 4))
pasta_base = os.path.join(MODELO, "dataset")
labelmap_path = os.path.join(pasta_base, "labelmap.txt")
+save_path = os.path.join(MODELO, "backup", config["modelo"], MODEL_NAME, f"raw{CHANNELS}")
RESOLUCOES = {f"{RESOLUCAO[0]}x{RESOLUCAO[1]}": (RESOLUCAO[0], RESOLUCAO[1])}
FONTES = ["original", "augmented"]
@@ -98,28 +101,20 @@ def map_raws_by_base(raw_dir: str) -> Dict[str, str]:
by_base[base] = os.path.join(raw_dir, fname)
return by_base
-def load_raw_gray_autodtype(path: str, src_hw: Tuple[int,int]) -> np.ndarray:
- """
- Carrega RAW como (H,W) detectando uint8/uint16 pelo tamanho do arquivo.
- """
+def load_raw4_float(path: str, src_hw: Tuple[int,int]) -> np.ndarray:
h, w = src_hw
npx = h * w
fsize = os.path.getsize(path)
- if fsize == npx:
- dtype = np.uint8
- elif fsize == npx * 2:
- dtype = np.uint16
- else:
+ num_floats = fsize // 4
+ if num_floats != 4 * npx:
raise RuntimeError(
- f"Tamanho inesperado para RAW {path}: {fsize} bytes "
- f"(esperado {npx} (u8) ou {npx*2} (u16) para {w}x{h})."
+ f"RAW {path}: esperado 4 canais float32, "
+ f"mas num_floats={num_floats}, H*W={npx}"
)
- data = np.fromfile(path, dtype=dtype)
- if data.size != npx:
- raise RuntimeError(f"RAW {path}: size={data.size} != {npx} (HxW)")
- return data.reshape((h, w))
+ data = np.fromfile(path, dtype=np.float32)
+ return data.reshape(4, h, w) # (C,H,W)
def save_raw(path: str, arr: np.ndarray):
np.asarray(arr).tofile(path)
@@ -231,9 +226,18 @@ def normalize_group_raw(fonte_root: str, fonte_nome: str, cor_para_id, ignore_id
if usar_raw and out_raw:
if raw_path:
src_h, src_w = prev_bgr.shape[:2]
- mosaic = load_raw_gray_autodtype(raw_path, (src_h, src_w))
- out_w, out_h = dim # dim = (W, H)
- raw4 = mosaic_to_raw4_resized_buf(mosaic, out_h, out_w) # float32, shape (4,H,W) em 0..1
+
+ raw4 = load_raw4_float(raw_path, (src_h, src_w)) # (4, Hsrc, Wsrc)
+ out_w, out_h = dim
+
+ if (src_w, src_h) != (out_w, out_h):
+ # redimensiona cada canal
+ chans = []
+ for k in range(raw4.shape[0]):
+ ch = raw4[k]
+ ch_res = cv2.resize(ch, (out_w, out_h), interpolation=cv2.INTER_AREA)
+ chans.append(ch_res.astype(np.float32))
+ raw4 = np.stack(chans, axis=0) # (4, out_h, out_w)
# Atualiza acumuladores de stats
# raw4: (C,H,W) -> (C,N)
@@ -302,7 +306,8 @@ def main(args):
"pixels_per_channel": int(GLOBAL_PIXELS),
}
- stats_path = os.path.join(pasta_base, "norm_stats.json")
+ garantir_dir(save_path)
+ stats_path = os.path.join(save_path, "norm_stats.json")
with open(stats_path, "w", encoding="utf-8") as f:
json.dump(stats, f, indent=2, ensure_ascii=False)
diff --git a/Python/OAK/datasets/_8_train_segformer_b3_raw.py b/Python/OAK/datasets/_8_train_segformer_b3_raw.py
index 842f7d51d..c22c2f759 100644
--- a/Python/OAK/datasets/_8_train_segformer_b3_raw.py
+++ b/Python/OAK/datasets/_8_train_segformer_b3_raw.py
@@ -1,3 +1,6 @@
+#python _8_train_segformer_b3_raw.py --config config.json --epochs 20 --batch 4 --lr 3e-5 --wd 0.01 --num_workers 4 --amp --amp_val --grad_accum 2 --class_weights auto
+
+
import os
os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "max_split_size_mb:128")
@@ -311,7 +314,7 @@ def main():
# Caminho padrão: dentro do dataset, nome do arquivo de stats
# (ajusta aqui pro nome que você realmente usou: norm_stats.json, por ex.)
- norm_stats_path = os.path.join(dataset_path, "norm_stats.json")
+ norm_stats_path = os.path.join(save_path, "norm_stats.json")
if args.norm_stats is not None:
norm_stats_path = args.norm_stats
diff --git a/Python/OAK/datasets/_9_test_segformer_b3_raw.py b/Python/OAK/datasets/_9_test_segformer_b3_raw.py
index 9a7c12603..aebde4f98 100644
--- a/Python/OAK/datasets/_9_test_segformer_b3_raw.py
+++ b/Python/OAK/datasets/_9_test_segformer_b3_raw.py
@@ -5,19 +5,18 @@ Teste/visualização do SegFormer RAW (4 ou 5 canais) treinado no _8_train_segfo
Modos:
-1) Dataset (padrão):
- - Lê os RAWs + masks da pasta dataset/split/
- - Mostra: [preview RAW (RGB)] | [mask GT] | [mask predita]
- - Navegação:
- D -> próxima
- A -> anterior
- Q -> sair
+1) Dataset (com GT):
+ - Usa RawSegDataset (raws + masks) a partir de split (train/val/test)
+ - Mostra: [preview RAW (RGB)] | [mask GT] | [overlay predito]
-2) Câmera ao vivo (--camera):
+2) Pasta sem máscara (--test_folder sem masks):
+ - Faz inferência só com os RAWs (sem GT)
+ - Mostra: [preview RAW (RGB)] | [overlay predito]
+
+3) Câmera ao vivo (--camera):
- Usa Gal5000Camera para pegar RAW4 (R,G,IR,B)
- - Monta entrada com 4 ou 5 canais (IR bruto / NDVI / IR+NDVI) conforme config
- - Faz inferência com SegFormer
- - Mostra RGB + overlay da segmentação em tempo real
+ - Monta os 4/5 canais conforme config
+ - Mostra overlay em tempo real
"""
import os
@@ -30,29 +29,189 @@ import cv2
import torch
import numpy as np
-from utils import converter_mask_ids_para_rgb, desenhar_legenda_horizontal
+from utils import converter_mask_ids_para_bgr, desenhar_legenda_horizontal
-from raw_segformer_service import RawSegformerService, RawSegDataset
+from raw_segformer_service import RawSegformerService, RawSegDataset # :contentReference[oaicite:0]{index=0}
from gal5000.gal_service import Gal5000Camera
+# ============================================================
+# Helpers para modo "sem máscara"
+# (copia condensada da lógica do RawSegDataset)
+# ============================================================
+
+_RAW_EXTS = (".npy", ".npz", ".raw")
+
+
+def _load_raw_4ch(path: str, raw_hw):
+ """
+ Lê um RAW no formato usado pelo pipeline:
+ - mosaico uint8 antigo, ou
+ - RAW4 float32 novo, shape (4,H,W), salvo pelo normalize
+
+ Retorna: arr (H,W,4) na ordem [R,G,B,IR] em dtype original.
+ """
+ import os
+ H, W = raw_hw
+ ext = os.path.splitext(path)[1].lower()
+
+ if ext == ".npz":
+ z = np.load(path)
+ key = list(z.keys())[0]
+ arr = z[key]
+ elif ext == ".npy":
+ arr = np.load(path)
+ elif ext == ".raw":
+ size_bytes = os.path.getsize(path)
+ mosa_bytes = H * W # mosaico uint8
+ raw4_bytes = 4 * H * W * 4 # 4 canais * H * W * 4 bytes (float32)
+
+ if size_bytes == mosa_bytes:
+ # Modo antigo: mosaico 2x2 uint8
+ arr_flat = np.fromfile(path, dtype=np.uint8)
+ raw2d = arr_flat.reshape(H, W)
+
+ if (H % 2) != 0 or (W % 2) != 0:
+ raise RuntimeError(f"raw_hw deve ser par em H e W (veio H={H}, W={W})")
+
+ H2, W2 = H // 2, W // 2
+ r_sub = raw2d[0::2, 0::2]
+ g_sub = raw2d[0::2, 1::2]
+ ir_sub = raw2d[1::2, 0::2]
+ b_sub = raw2d[1::2, 1::2]
+
+ from PIL import Image
+
+ def upsample(ch_2d: np.ndarray) -> np.ndarray:
+ im = Image.fromarray(ch_2d) # uint8
+ im = im.resize((W, H), resample=Image.BILINEAR)
+ return np.array(im)
+
+ r_full = upsample(r_sub)
+ g_full = upsample(g_sub)
+ ir_full = upsample(ir_sub)
+ b_full = upsample(b_sub)
+
+ # (H, W, 4) uint8 [R,G,B,IR]
+ arr = np.stack([r_full, g_full, b_full, ir_full], axis=-1).astype(np.uint8)
+
+ elif size_bytes == raw4_bytes:
+ # Novo modo: RAW4 float32 salvo pelo normalize_raw
+ arr_f32 = np.fromfile(path, dtype=np.float32)
+ raw4 = arr_f32.reshape(4, H, W) # (C,H,W) [R,G,IR,B]
+ arr = np.transpose(raw4, (1, 2, 0)) # (H,W,4) [R,G,IR,B]
+ # Reorganiza pra contrato interno: [R,G,B,IR]
+ arr = arr[..., [0, 1, 3, 2]]
+ else:
+ raise RuntimeError(
+ f"Tamanho inesperado em {path}: {size_bytes} bytes "
+ f"(esperado {mosa_bytes} ou {raw4_bytes})"
+ )
+ else:
+ raise RuntimeError(f"Extensão não suportada para RAW: {ext} ({path})")
+
+ if arr.ndim != 3:
+ raise RuntimeError(f"RAW precisa ser 3D, veio {arr.shape} em {path}")
+
+ if arr.shape[0] == 4 and arr.shape[-1] != 4:
+ arr = np.transpose(arr, (1, 2, 0)) # (H,W,4)
+
+ if arr.shape[-1] != 4:
+ raise RuntimeError(f"Esperava 4 canais base, veio shape={arr.shape} em {path}")
+
+ return arr # (H,W,4) [R,G,B,IR]
+
+
+def _scale_to_float01(raw: np.ndarray, max_value: float | None = None) -> np.ndarray:
+ """
+ Normaliza para float32 0..1 (igual RawSegDataset._scale_to_float01):
+ - uint8 / uint16: divide por max_value ou 255/65535
+ - float: usa max_value se fornecido; senão assume 0..1
+ """
+ if raw.dtype == np.uint16:
+ mv = float(max_value) if max_value is not None else 65535.0
+ elif raw.dtype == np.uint8:
+ mv = float(max_value) if max_value is not None else 255.0
+ else:
+ mv = float(max_value) if max_value is not None else None
+
+ raw_f = raw.astype(np.float32)
+ if mv is not None and mv > 0:
+ raw_f /= mv
+
+ raw_f = np.clip(raw_f, 0.0, 1.0)
+ return raw_f
+
+
+def _collect_raw_paths(root: str) -> list[str]:
+ """
+ Coleta caminhos de RAWs em 'root' usando a mesma convenção do dataset:
+ - se root/group existe: procura group/*/raws
+ - senão: procura root/raws
+ """
+ paths = []
+
+ dir_group = os.path.join(root, "group")
+ if os.path.isdir(dir_group):
+ # modo com grupos
+ for g in sorted(os.listdir(dir_group)):
+ gdir = os.path.join(dir_group, g)
+ if not os.path.isdir(gdir):
+ continue
+ g_raw = os.path.join(gdir, "raws")
+ if not os.path.isdir(g_raw):
+ continue
+ for fn in sorted(os.listdir(g_raw)):
+ if fn.lower().endswith(_RAW_EXTS):
+ paths.append(os.path.join(g_raw, fn))
+ else:
+ # modo simples
+ dir_raws = os.path.join(root, "raws")
+ if not os.path.isdir(dir_raws):
+ raise RuntimeError(f"Modo sem máscara: não achei pasta 'raws' em {root}")
+ for fn in sorted(os.listdir(dir_raws)):
+ if fn.lower().endswith(_RAW_EXTS):
+ paths.append(os.path.join(dir_raws, fn))
+
+ return paths
+
+
+# ============================================================
+# Script principal
+# ============================================================
+
def main():
parser = argparse.ArgumentParser()
# Config / treino
parser.add_argument("--config", default="config.json", help="Caminho do config.json (mesmo do treino)")
parser.add_argument("--split_folder", type=str, default="val", help="train, val ou test (dentro de dataset/split)")
- parser.add_argument("--root_override", type=str, default=None, help="Se quiser apontar direto para uma pasta split (sobrepõe split_folder)")
- parser.add_argument("--ckpt", type=str, default=None, help="Caminho do .pt (se não informar, usa best_miou.pt da pasta raw4)")
- parser.add_argument("--raw_max", type=float, default=None, help="Mesmo raw_max do treino (se usou). Usado internamente no dataset.")
+ parser.add_argument("--root_override", type=str, default=None, help="Aponta direto para uma pasta split (sobrepõe split_folder)")
+ parser.add_argument(
+ "--test_folder",
+ type=str,
+ default=None,
+ help=(
+ "Pasta de teste para visualização. "
+ "Se tiver masks, usa dataset normal (mostra GT). "
+ "Se tiver apenas raws, entra em modo inferência-only."
+ )
+ )
+ parser.add_argument("--ckpt", type=str, default=None, help="Caminho do .pt (se não informar, usa best_miou.pt da pasta rawX)")
+ parser.add_argument("--raw_max", type=float, default=None, help="Mesmo raw_max do treino (se usou).")
# Modo câmera
parser.add_argument("--camera", action="store_true", help="Usa a GAL5000 ao vivo via DLL (realtime)")
parser.add_argument("--norm_stats", type=str, default=None, help="Caminho para JSON com mean/std por canal (ex: norm_stats.json).")
- parser.add_argument("--dll_dir", type=str, default=r"C:\ZendionInc\agrobot_base\Python\gal5000\dlls", help="Pasta onde fica VT_SDK64.dll e dependências")
+ parser.add_argument(
+ "--dll_dir",
+ type=str,
+ default=r"C:\ZendionInc\agrobot_base\Python\gal5000\dlls",
+ help="Pasta onde fica VT_SDK64.dll e dependências",
+ )
parser.add_argument("--dll_name", type=str, default="VT_SDK64.dll")
- parser.add_argument("--resize_h", type=int, default=None, help="Altura para inferência (velocidade)")
- parser.add_argument("--resize_w", type=int, default=None, help="Largura para inferência (velocidade)")
+ parser.add_argument("--resize_h", type=int, default=None, help="Altura para inferência (override)")
+ parser.add_argument("--resize_w", type=int, default=None, help="Largura para inferência (override)")
parser.add_argument("--alpha", type=float, default=0.45, help="Alpha do overlay da máscara")
parser.add_argument("--fps_win", type=int, default=30, help="Janela para FPS médio")
parser.add_argument("--timeout_ms", type=int, default=2000, help="Timeout da captura da câmera em ms")
@@ -67,16 +226,17 @@ def main():
config = json.load(f)
MODELO = config["camera"] # ex: "gal5000"
- MODEL_NAME = config["model_name"] # ex: "segformer_b3"
- modelo_folder = config["modelo"] # ex: "dif"
+ #MODEL_NAME = config["model_name"] # ex: "segformer_b0"
+ MODEL_NAME = "pulv2_1008x800"
+ modelo_folder = config["modelo"] # ex: "weed_1008x800"
USE_NDVI = bool(config.get("use_ndvi", False))
CHANNELS = int(config.get("channels", 4))
RESOLUCAO = config["resolucao"]
W, H = RESOLUCAO[0], RESOLUCAO[1]
- if (args.resize_h is not None):
+ if args.resize_h is not None:
H = args.resize_h
- if (args.resize_w is not None):
+ if args.resize_w is not None:
W = args.resize_w
print(f"[cfg] resolucao nominal RAW: {W}x{H}")
@@ -86,12 +246,12 @@ def main():
labelmap_path = os.path.join(dataset_path, "labelmap.txt")
# ==========================
- # Normalização fixa (como no treino)
+ # Normalização fixa (igual treino)
# ==========================
norm_mean = None
norm_std = None
- norm_stats_path = os.path.join(dataset_path, "norm_stats.json")
+ norm_stats_path = os.path.join(MODELO, "backup", modelo_folder, MODEL_NAME, f"raw{CHANNELS}", "norm_stats.json")
if args.norm_stats is not None:
norm_stats_path = args.norm_stats
if os.path.isfile(norm_stats_path):
@@ -107,10 +267,8 @@ def main():
print(f"[NORM] mean={stats_mean}")
print(f"[NORM] std ={stats_std}")
- # JSON vem como ["R","G","IR","B"]
idx_by_name = {name: i for i, name in enumerate(stats_channels)}
- # Sempre montamos na ordem interna base [R,G,B,IR]
m_R = stats_mean[idx_by_name["R"]]
m_G = stats_mean[idx_by_name["G"]]
m_IR = stats_mean[idx_by_name["IR"]]
@@ -121,20 +279,13 @@ def main():
s_IR = stats_std[idx_by_name["IR"]]
s_B = stats_std[idx_by_name["B"]]
- # Agora montamos mean/std na ordem REAL dos canais que o modelo vê:
- # - channels=4, use_ndvi=False -> [R,G,B,IR]
- # - channels=4, use_ndvi=True -> [R,G,B,NDVI] (NDVI norm dinâmica)
- # - channels=5, use_ndvi=True -> [R,G,B,IR,NDVI]
if CHANNELS == 4 and not USE_NDVI:
- # [R,G,B,IR]
norm_mean = [m_R, m_G, m_B, m_IR]
norm_std = [s_R, s_G, s_B, s_IR]
elif CHANNELS == 4 and USE_NDVI:
- # [R,G,B,NDVI] -> NDVI fica com normalização identidade (0,1)
norm_mean = [m_R, m_G, m_B, 0.0]
norm_std = [s_R, s_G, s_B, 1.0]
elif CHANNELS == 5 and USE_NDVI:
- # [R,G,B,IR,NDVI]
norm_mean = [m_R, m_G, m_B, m_IR, 0.0]
norm_std = [s_R, s_G, s_B, s_IR, 1.0]
else:
@@ -150,8 +301,6 @@ def main():
if args.ckpt is not None:
ckpt_path = args.ckpt
else:
- # Caminho padrão igual ao treino:
- # save_path = MODELO/backup/modelo/model_name/raw4
save_path = os.path.join(MODELO, "backup", modelo_folder, MODEL_NAME, f"raw{CHANNELS}")
ckpt_path = os.path.join(save_path, "best_miou.pt")
@@ -160,7 +309,7 @@ def main():
print(f"[model] ckpt = {ckpt_path}")
- # ---- Instancia service do modelo RAW (4 ou 5 canais) ----
+ # ---- Instancia service do modelo RAW ----
model_svc = RawSegformerService(
config_path=args.config,
ckpt_path=ckpt_path,
@@ -182,7 +331,13 @@ def main():
# ======================================================================
if args.camera:
print("[mode] Câmera ao vivo (GAL5000 + SegFormer RAW)")
- cam = Gal5000Camera(dll_dir=args.dll_dir, dll_name=args.dll_name, raw_w=W, raw_h=H, use_auto_exposure=True)
+ cam = Gal5000Camera(
+ dll_dir=args.dll_dir,
+ dll_name=args.dll_name,
+ raw_w=W,
+ raw_h=H,
+ use_auto_exposure=True
+ )
win = "GAL5000 RAW + SegFormer (Q=quit)"
cv2.namedWindow(win, cv2.WINDOW_NORMAL)
@@ -194,22 +349,17 @@ def main():
cam.start_streaming()
while True:
t0 = time.time()
- # raw4_base: (4,H,W) float32 0..1 [R,G,IR,B] já redimensionado
raw4_base, dbg = cam.grab_raw4(out_h=H, out_w=W, timeout_ms=args.timeout_ms)
t1 = time.time()
- # Separa canais básicos
r = raw4_base[0]
g = raw4_base[1]
ir = raw4_base[2]
b = raw4_base[3]
- # Deixa o service montar a entrada final com 4 ou 5 canais
- # (R,G,B,IR) | (R,G,B,NDVI) | (R,G,B,IR,NDVI)
- raw_input = model_svc.build_raw_input(r, g, ir, b) # (C,H,W) float32 0..1
+ raw_input = model_svc.build_raw_input(r, g, ir, b)
t2 = time.time()
- # Inferência + previews via service
pred_ids = model_svc.infer_raw(raw_input)
t3 = time.time()
_, _, overlay, _, t_pvw = model_svc.preview_infer_cached(raw_input, pred_ids, alpha=args.alpha)
@@ -225,7 +375,7 @@ def main():
t_ae = dbg.get("t_ae", 0) * 1000
t_raw = (t2 - t1) * 1000
t_inf = (t3 - t2) * 1000
-
+
lines = [
f"{W}x{H} | FPS~{fps:.1f} | {shape}",
f"EX={status['exp_raw']} G={status['gain_a']}/{status['gain_d']}",
@@ -234,7 +384,8 @@ def main():
]
y = 24
for line in lines:
- cv2.putText(overlay, line, (12, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA)
+ cv2.putText(overlay, line, (12, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
+ (255, 255, 255), 1, cv2.LINE_AA)
y += 22
cv2.imshow(win, overlay)
@@ -246,81 +397,122 @@ def main():
return
# ======================================================================
- # MODO DATASET (A/D)
+ # MODO DATASET / TEST_FOLDER
# ======================================================================
- # ---- Define raiz do split ----
- if args.root_override is not None:
+ # ---- Define raiz do split/test ----
+ if args.test_folder is not None:
+ raw_root = args.test_folder
+ elif args.root_override is not None:
raw_root = args.root_override
else:
raw_root = os.path.join(dataset_path, "split", args.split_folder)
print(f"[data] raw_root = {raw_root}")
- # Dataset RAW com 4 ou 5 canais, mesma lógica do treino
- ds = RawSegDataset(
- raw_root,
- labelmap_path=labelmap_path,
- max_value=args.raw_max,
- resize_hw=None,
- raw_hw=(H, W),
- use_ndvi=USE_NDVI,
- channels=CHANNELS,
- )
+ has_gt = True
+ ds = None
+ raw_paths = []
+
+ try:
+ ds = RawSegDataset(
+ raw_root,
+ labelmap_path=labelmap_path,
+ max_value=args.raw_max,
+ resize_hw=None,
+ raw_hw=(H, W),
+ use_ndvi=USE_NDVI,
+ channels=CHANNELS,
+ )
+ print("[mode] Dataset com GT (masks) detectado. Mostrando GT + overlay.")
+ except RuntimeError as e:
+ msg = str(e)
+ if "Nenhum par raw/mask encontrado" in msg:
+ print("[mode] Nenhum par raw/mask encontrado. Entrando em modo inferência-only (sem GT).")
+ has_gt = False
+ raw_paths = _collect_raw_paths(raw_root)
+ if not raw_paths:
+ raise RuntimeError(f"Modo inferência-only: não encontrei nenhum RAW em {raw_root}")
+ print(f"[data] RAWs encontrados: {len(raw_paths)}")
+ else:
+ raise
+
+ if has_gt:
+ n = len(ds)
+ else:
+ n = len(raw_paths)
idx = 0
- n = len(ds)
print(f"[data] total de amostras: {n}")
print("Controles: D=próxima, A=anterior, Q=sair")
- win_name = "RAW | GT | Pred"
- cv2.namedWindow(win_name, cv2.WINDOW_NORMAL) # janela redimensionável
+
+ win_name = "RAW preview | GT | Overlay (SegFormer)" if has_gt else "RAW preview | Overlay (SegFormer)"
+ cv2.namedWindow(win_name, cv2.WINDOW_NORMAL)
while True:
- sample = ds[idx]
- img_raw = sample["image"] # tensor (C,H,W) em 0..1 (C=4 ou 5)
- mask_gt = sample["mask"] # tensor (H,W) long
+ if has_gt:
+ # ------- Caminho com GT -------
+ sample = ds[idx]
+ img_raw = sample["image"] # tensor (C,H,W) em 0..1
+ mask_gt = sample["mask"] # tensor (H,W) long
- # Converte para numpy (C,H,W) float32 0..1
- raw_np = img_raw.cpu().numpy().astype(np.float32)
+ raw_np = img_raw.cpu().numpy().astype(np.float32)
+ pred_ids, preview_rgb, pred_rgb, overlay, t_inf, t_pvw = model_svc.infer_and_preview(
+ raw_np, alpha=args.alpha
+ )
- # Service faz toda a magia (normalização, NDVI, etc) em cima desse raw_np
- pred_ids, preview_rgb, pred_rgb, overlay, t_inf, t_pvw = model_svc.infer_and_preview(raw_np, alpha=args.alpha)
-
- print(f"t_inf: {t_inf:.1f} ms t_pvw: {t_pvw:.1f} ms")
+ mask_gt_np = mask_gt.cpu().numpy().astype(np.uint8)
+ gt_rgb = converter_mask_ids_para_bgr(mask_gt_np, colormap_rgb, ignore_id)
- # GT em RGB
- mask_gt_np = mask_gt.cpu().numpy().astype(np.uint8)
- gt_rgb = converter_mask_ids_para_rgb(mask_gt_np, colormap_rgb, ignore_id)
+ h, w, _ = preview_rgb.shape
+ gt_resized = cv2.resize(gt_rgb, (w, h), interpolation=cv2.INTER_NEAREST)
+ overlay_resized = cv2.resize(overlay, (w, h), interpolation=cv2.INTER_NEAREST)
- # Empilha: [RAW preview | GT | Pred]
- h, w, _ = preview_rgb.shape
- gt_resized = cv2.resize(gt_rgb, (w, h), interpolation=cv2.INTER_NEAREST)
- pred_resized = cv2.resize(pred_rgb, (w, h), interpolation=cv2.INTER_NEAREST)
+ resultado = np.concatenate([preview_rgb, gt_resized, overlay_resized], axis=1)
+ legenda = desenhar_legenda_horizontal(colormap_rgb, classes)
+ legenda_resized = cv2.resize(legenda, (resultado.shape[1], legenda.shape[0]), interpolation=cv2.INTER_NEAREST)
+ resultado_completo = np.concatenate([resultado, legenda_resized], axis=0)
- resultado = np.concatenate([preview_rgb, gt_resized, pred_resized], axis=1)
+ header_txt = f"idx {idx + 1}/{n} | C={CHANNELS} NDVI={int(USE_NDVI)}"
+ else:
+ # ------- Caminho sem GT (só RAW) -------
+ raw_path = raw_paths[idx]
+ raw4 = _load_raw_4ch(raw_path, raw_hw=(H, W)) # (H,W,4) [R,G,B,IR]
+ raw4_f = _scale_to_float01(raw4, max_value=args.raw_max) # float32 0..1
- # Legenda embaixo
- legenda = desenhar_legenda_horizontal(colormap_rgb, classes)
- legenda_resized = cv2.resize(legenda, (resultado.shape[1], legenda.shape[0]), interpolation=cv2.INTER_NEAREST)
- resultado_completo = np.concatenate([resultado, legenda_resized], axis=0)
+ # Monta canais finais para o modelo (4 ou 5) via serviço
+ r = raw4_f[..., 0]
+ g = raw4_f[..., 1]
+ b = raw4_f[..., 2]
+ ir = raw4_f[..., 3]
- # Índice + info de canais
- cv2.putText(resultado_completo, f"idx {idx + 1}/{n} | C={CHANNELS} NDVI={int(USE_NDVI)}", (10, 24), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
+ raw_input = model_svc.build_raw_input(r, g, ir, b) # (C,H,W) float32
+ pred_ids = model_svc.infer_raw(raw_input)
+ _, preview_rgb, _, overlay, _, _ = model_svc.preview_infer_cached(raw_input, pred_ids, alpha=args.alpha)
- # >>> Ajuste dinâmico ao tamanho da janela <<<
+ h, w, _ = preview_rgb.shape
+ overlay_resized = cv2.resize(overlay, (w, h), interpolation=cv2.INTER_NEAREST)
+ resultado = np.concatenate([preview_rgb, overlay_resized], axis=1)
+
+ header_txt = f"idx {idx + 1}/{n} | C={CHANNELS} NDVI={int(USE_NDVI)} | {os.path.basename(raw_path)}"
+
+ resultado_completo = resultado
+
+ # Escreve header
+ cv2.putText(resultado_completo, header_txt, (10, 24), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
+
+ # Ajuste dinâmico da janela
try:
- x, y, win_w, win_h = cv2.getWindowImageRect(win_name)
- except:
+ _x, _y, win_w, win_h = cv2.getWindowImageRect(win_name)
+ except Exception:
win_w, win_h = 0, 0
if win_w > 0 and win_h > 0:
- # Redimensiona o painel todo pra caber na janela atual
display = cv2.resize(resultado_completo, (win_w, win_h), interpolation=cv2.INTER_NEAREST)
else:
display = resultado_completo
- # OpenCV usa BGR
- cv2.imshow(win_name, cv2.cvtColor(display, cv2.COLOR_RGB2BGR))
+ cv2.imshow(win_name, display)
key = cv2.waitKey(0) & 0xFF
if key in (ord("q"), ord("Q"), 27):
diff --git a/Python/OAK/datasets/config.json b/Python/OAK/datasets/config.json
index adb90c7f1..f0e7e9211 100644
--- a/Python/OAK/datasets/config.json
+++ b/Python/OAK/datasets/config.json
@@ -1,17 +1,17 @@
{
- "camera": "oak-d",
+ "camera": "gal5000",
"modelo": "segformer_b0",
- "model_name": "nav",
+ "model_name": "pulv_n_1008x800",
"dual_head": false,
- "main_class_name": "navegavel",
+ "main_class_name": "pulverizar",
"es_classes": "",
"model_to_use": "geral",
"raw_size": [1296, 1028],
- "resolucao": [1024, 576],
+ "resolucao": [1008, 800],
"roi_inicio": 0.0,
"roi_tamanho": 1.0,
"shaves": 3,
- "channels": 3,
+ "channels": 5,
"use_ndvi": true,
"backbone": "nvidia/segformer-b0-finetuned-ade-512-512"
}
\ No newline at end of file
diff --git a/Python/OAK/datasets/config_gal.json b/Python/OAK/datasets/config_oak.json
similarity index 67%
rename from Python/OAK/datasets/config_gal.json
rename to Python/OAK/datasets/config_oak.json
index 41f04133b..adb90c7f1 100644
--- a/Python/OAK/datasets/config_gal.json
+++ b/Python/OAK/datasets/config_oak.json
@@ -1,17 +1,17 @@
{
- "camera": "gal5000",
+ "camera": "oak-d",
"modelo": "segformer_b0",
- "model_name": "ndvi_big",
+ "model_name": "nav",
"dual_head": false,
- "main_class_name": "erva",
+ "main_class_name": "navegavel",
"es_classes": "",
"model_to_use": "geral",
"raw_size": [1296, 1028],
- "resolucao": [1008, 800],
+ "resolucao": [1024, 576],
"roi_inicio": 0.0,
"roi_tamanho": 1.0,
"shaves": 3,
- "channels": 5,
+ "channels": 3,
"use_ndvi": true,
"backbone": "nvidia/segformer-b0-finetuned-ade-512-512"
}
\ No newline at end of file
diff --git a/Python/dalybms/ControlCANFD.dll b/Python/dalybms/ControlCANFD.dll
new file mode 100644
index 000000000..72f88ef96
--- /dev/null
+++ b/Python/dalybms/ControlCANFD.dll
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:990276c7b922b6b40b16c264d198a2035dd5715309f40472760cba8b64cfcf18
+size 354816
diff --git a/Python/dalybms/console.py b/Python/dalybms/console.py
new file mode 100644
index 000000000..3ee118082
--- /dev/null
+++ b/Python/dalybms/console.py
@@ -0,0 +1,465 @@
+import ctypes
+import time
+import os
+from typing import List
+
+# ========= CONFIG BÁSICA =========
+
+DLL_NAME = "ControlCANFD.dll"
+DEVICE_TYPE = 41
+DEVICE_INDEX = 0
+CHANNEL_INDEX = 0 # 0 = CAN1, 1 = CAN2
+
+BMS_ADDR = 0x01
+PC_ADDR = 0x40
+
+# Baud 250 kbps para Waveshare USB-CAN-FD (RefType=0)
+BAUD_250K = 0x1C0008
+
+
+# ========= ESTRUTURAS DA DLL =========
+
+class VCI_INIT_CONFIG(ctypes.Structure):
+ _fields_ = [
+ ("AccCode", ctypes.c_uint),
+ ("AccMask", ctypes.c_uint),
+ ("Reserved", ctypes.c_uint),
+ ("Filter", ctypes.c_ubyte),
+ ("Timing0", ctypes.c_ubyte),
+ ("Timing1", ctypes.c_ubyte),
+ ("Mode", ctypes.c_ubyte),
+ ]
+
+
+class VCI_CAN_OBJ(ctypes.Structure):
+ _fields_ = [
+ ("ID", ctypes.c_uint),
+ ("TimeStamp", ctypes.c_uint),
+ ("TimeFlag", ctypes.c_ubyte),
+ ("SendType", ctypes.c_ubyte),
+ ("RemoteFlag", ctypes.c_ubyte),
+ ("ExternFlag", ctypes.c_ubyte),
+ ("DataLen", ctypes.c_ubyte),
+ ("Data", ctypes.c_ubyte * 8),
+ ("Reserved", ctypes.c_ubyte * 3),
+ ]
+
+
+# ========= HELPERS DE PROTOCOLO DALY =========
+
+def u16_be(hi: int, lo: int) -> int:
+ return ((hi & 0xFF) << 8) | (lo & 0xFF)
+
+
+def bits_set(byte_val: int):
+ return [i for i in range(8) if (byte_val >> i) & 1]
+
+
+def get_data_id_from_can_id(can_id: int) -> int:
+ """
+ Protocolo Daly:
+ ID (29 bits) = [Priority][DataID][AddrA][AddrB]
+ DataID está no segundo byte (bits 16..23)
+ """
+ return (can_id >> 16) & 0xFF
+
+
+def make_request_id(data_id: int) -> int:
+ """
+ PC -> BMS:
+ 0x18 [DataID] [BMS_ADDR] [PC_ADDR]
+ Ex: DataID=0x90 => 0x18900140
+ """
+ return (0x18 << 24) | (data_id << 16) | (BMS_ADDR << 8) | PC_ADDR
+
+
+def expected_response_id(data_id: int) -> int:
+ """
+ BMS -> PC:
+ 0x18 [DataID] [PC_ADDR] [BMS_ADDR]
+ Ex: DataID=0x90 => 0x18904001
+ """
+ return (0x18 << 24) | (data_id << 16) | (PC_ADDR << 8) | BMS_ADDR
+
+
+# ========= PARSERS POR DATAID =========
+
+def parse_0x90(data: List[int]) -> None:
+ total_v_raw = u16_be(data[0], data[1])
+ meas_v_raw = u16_be(data[2], data[3])
+ current_raw = u16_be(data[4], data[5])
+ soc_raw = u16_be(data[6], data[7])
+
+ total_v = total_v_raw / 10.0
+ meas_v = meas_v_raw / 10.0
+ current = (current_raw - 30000) / 10.0
+ soc = soc_raw / 10.0
+
+ print("== 0x90: Tensão / Corrente / SOC ==")
+ print(f" Tensão total (cumulative): {total_v:.1f} V (raw={total_v_raw})")
+ print(f" Tensão medida (gather) : {meas_v:.1f} V (raw={meas_v_raw})")
+ print(f" Corrente : {current:.1f} A (raw={current_raw})")
+ print(f" SOC : {soc:.1f} % (raw={soc_raw})")
+
+
+def parse_0x91(data: List[int]) -> None:
+ vmax_raw = u16_be(data[0], data[1])
+ vmax_idx = data[2]
+ vmin_raw = u16_be(data[3], data[4])
+ vmin_idx = data[5]
+
+ print("== 0x91: Tensão máx/mín de célula ==")
+ print(f" Vmax: {vmax_raw/1000.0:.3f} V (raw={vmax_raw} mV) célula #{vmax_idx}")
+ print(f" Vmin: {vmin_raw/1000.0:.3f} V (raw={vmin_raw} mV) célula #{vmin_idx}")
+
+
+def parse_0x92(data: List[int]) -> None:
+ tmax = data[0] - 40
+ tmax_i = data[1]
+ tmin = data[2] - 40
+ tmin_i = data[3]
+
+ print("== 0x92: Temperatura máx/mín ==")
+ print(f" T_max: {tmax} °C (sensor #{tmax_i})")
+ print(f" T_min: {tmin} °C (sensor #{tmin_i})")
+
+
+def parse_0x93(data: List[int]) -> None:
+ state = data[0]
+ charge_mos = data[1]
+ dischg_mos = data[2]
+ life_raw = data[3]
+ remain_mAh = (
+ (data[4] << 24)
+ | (data[5] << 16)
+ | (data[6] << 8)
+ | data[7]
+ )
+
+ state_map = {0: "parado", 1: "carga", 2: "descarga"}
+
+ print("== 0x93: Estado MOS / capacidade restante ==")
+ print(f" Estado geral : {state} ({state_map.get(state,'desconhecido')})")
+ print(f" Charge MOS state : {charge_mos}")
+ print(f" Discharge MOS state : {dischg_mos}")
+ print(f" BMS life (raw, 'ciclos'): {life_raw}")
+ print(f" Capacidade restante : {remain_mAh} mAh ({remain_mAh/1000.0:.3f} Ah)")
+
+
+def parse_0x94(data: List[int]) -> None:
+ n_series = data[0]
+ n_temps = data[1]
+ charger = data[2]
+ load = data[3]
+ io_byte = data[4]
+
+ di_bits = bits_set(io_byte & 0x0F)
+ do_bits = bits_set((io_byte >> 4) & 0x0F)
+
+ print("== 0x94: Status geral / IO ==")
+ print(f" Nº células em série : {n_series}")
+ print(f" Nº sensores de temp : {n_temps}")
+ print(f" Carregador conectado: {'sim' if charger else 'não'}")
+ print(f" Load conectado : {'sim' if load else 'não'}")
+ print(f" DI ativos (0-3) : {['DI'+str(i+1) for i in di_bits] or ['nenhum']}")
+ print(f" DO ativos (0-3) : {['DO'+str(i+1) for i in do_bits] or ['nenhum']}")
+
+
+def parse_0x95(data: List[int]) -> None:
+ frame = data[0]
+ cells = []
+ for i in range(3):
+ hi = data[1 + 2*i]
+ lo = data[1 + 2*i + 1]
+ raw = u16_be(hi, lo)
+ if raw == 0 or raw == 0xFFFF:
+ continue
+ cell_index = frame * 3 + i + 1 # 1-based
+ cells.append((cell_index, raw))
+
+ print("== 0x95: Tensões individuais de célula (frame múltiplo) ==")
+ print(f" Frame: {frame}")
+ if not cells:
+ print(" (sem células válidas neste frame)")
+ else:
+ for idx, raw in cells:
+ print(f" Célula #{idx:2d}: {raw/1000.0:.3f} V (raw={raw} mV)")
+
+
+def parse_0x96(data: List[int]) -> None:
+ frame = data[0]
+ temps = []
+ for i in range(1, 8):
+ raw = data[i]
+ if raw == 0xFF:
+ continue
+ temp_c = raw - 40
+ sensor_index = frame * 7 + (i - 1) + 1
+ temps.append((sensor_index, temp_c))
+
+ print("== 0x96: Temperaturas individuais (frame múltiplo) ==")
+ print(f" Frame: {frame}")
+ if not temps:
+ print(" (sem temperaturas válidas neste frame)")
+ else:
+ for idx, t in temps:
+ print(f" Temp sensor #{idx:2d}: {t} °C")
+
+
+def parse_0x97(data: List[int]) -> None:
+ active_cells = []
+ for byte_index, b in enumerate(data):
+ for bit in range(8):
+ global_bit = byte_index * 8 + bit
+ if global_bit >= 48:
+ continue
+ if (b >> bit) & 1:
+ cell_idx = global_bit + 1
+ active_cells.append(cell_idx)
+
+ print("== 0x97: Estado de balanceamento das células ==")
+ if not active_cells:
+ print(" Nenhuma célula está em balanceamento (todas 0).")
+ else:
+ print(f" Células em balanceamento ({len(active_cells)}): {active_cells}")
+
+
+def parse_0x98(data: List[int]) -> None:
+ alarms = []
+
+ b = data[0]
+ if b & (1 << 0): alarms.append("Cell volt high level 1")
+ if b & (1 << 1): alarms.append("Cell volt high level 2")
+ if b & (1 << 2): alarms.append("Cell volt low level 1")
+ if b & (1 << 3): alarms.append("Cell volt low level 2")
+ if b & (1 << 4): alarms.append("Sum volt high level 1")
+ if b & (1 << 5): alarms.append("Sum volt high level 2")
+ if b & (1 << 6): alarms.append("Sum volt low level 1")
+ if b & (1 << 7): alarms.append("Sum volt low level 2")
+
+ b = data[1]
+ if b & (1 << 0): alarms.append("Chg temp high level 1")
+ if b & (1 << 1): alarms.append("Chg temp high level 2")
+ if b & (1 << 2): alarms.append("Chg temp low level 1")
+ if b & (1 << 3): alarms.append("Chg temp low level 2")
+ if b & (1 << 4): alarms.append("Dischg temp high level 1")
+ if b & (1 << 5): alarms.append("Dischg temp high level 2")
+ if b & (1 << 6): alarms.append("Dischg temp low level 1")
+ if b & (1 << 7): alarms.append("Dischg temp low level 2")
+
+ b = data[2]
+ if b & (1 << 0): alarms.append("Chg overcurrent level 1")
+ if b & (1 << 1): alarms.append("Chg overcurrent level 2")
+ if b & (1 << 2): alarms.append("Dischg overcurrent level 1")
+ if b & (1 << 3): alarms.append("Dischg overcurrent level 2")
+ if b & (1 << 4): alarms.append("SOC high level 1")
+ if b & (1 << 5): alarms.append("SOC high level 2")
+ if b & (1 << 6): alarms.append("SOC low level 1")
+ if b & (1 << 7): alarms.append("SOC low level 2")
+
+ b = data[3]
+ if b & (1 << 0): alarms.append("Diff volt level 1")
+ if b & (1 << 1): alarms.append("Diff volt level 2")
+ if b & (1 << 2): alarms.append("Diff temp level 1")
+ if b & (1 << 3): alarms.append("Diff temp level 2")
+
+ b = data[4]
+ if b & (1 << 0): alarms.append("Chg MOS temp high alarm")
+ if b & (1 << 1): alarms.append("Dischg MOS temp high alarm")
+ if b & (1 << 2): alarms.append("Chg MOS temp sensor error")
+ if b & (1 << 3): alarms.append("Dischg MOS temp sensor error")
+ if b & (1 << 4): alarms.append("Chg MOS adhesion error")
+ if b & (1 << 5): alarms.append("Dischg MOS adhesion error")
+ if b & (1 << 6): alarms.append("Chg MOS open circuit error")
+ if b & (1 << 7): alarms.append("Dischg MOS open circuit error")
+
+ b = data[5]
+ if b & (1 << 0): alarms.append("AFE collect chip error")
+ if b & (1 << 1): alarms.append("Voltage collect dropped")
+ if b & (1 << 2): alarms.append("Cell temp sensor error")
+ if b & (1 << 3): alarms.append("EEPROM error")
+ if b & (1 << 4): alarms.append("RTC error")
+ if b & (1 << 5): alarms.append("Precharge failure")
+ if b & (1 << 6): alarms.append("Communication failure")
+ if b & (1 << 7): alarms.append("Internal communication failure")
+
+ b = data[6]
+ if b & (1 << 0): alarms.append("Current module fault")
+ if b & (1 << 1): alarms.append("Sum voltage detect fault")
+ if b & (1 << 2): alarms.append("Short circuit protect fault")
+ if b & (1 << 3): alarms.append("Low volt forbidden chg fault")
+
+ fault_code = data[7]
+
+ print("== 0x98: Status de falhas / alarmes ==")
+ if not alarms and fault_code == 0:
+ print(" Nenhum alarme ativo.")
+ else:
+ print(" Alarmes ativos:")
+ for a in alarms:
+ print(" - " + a)
+ print(f" Fault code bruto: 0x{fault_code:02X} ({fault_code})")
+
+
+def parse_daly_frame(can_id: int, data: List[int]) -> None:
+ data_id = get_data_id_from_can_id(can_id)
+ print(f"\n=== Frame recebido ===")
+ print(f" CAN ID : 0x{can_id:08X}")
+ print(f" DataID : 0x{data_id:02X}")
+ print(f" Data : {' '.join(f'{b:02X}' for b in data)}")
+
+ if data_id == 0x90:
+ parse_0x90(data)
+ elif data_id == 0x91:
+ parse_0x91(data)
+ elif data_id == 0x92:
+ parse_0x92(data)
+ elif data_id == 0x93:
+ parse_0x93(data)
+ elif data_id == 0x94:
+ parse_0x94(data)
+ elif data_id == 0x95:
+ parse_0x95(data)
+ elif data_id == 0x96:
+ parse_0x96(data)
+ elif data_id == 0x97:
+ parse_0x97(data)
+ elif data_id == 0x98:
+ parse_0x98(data)
+ else:
+ print(" DataID ainda não implementado neste parser.")
+
+
+# ========= INICIALIZAÇÃO DO CAN =========
+
+def init_can():
+ dll = ctypes.cdll.LoadLibrary(os.path.abspath(DLL_NAME))
+
+ ret = dll.VCI_OpenDevice(DEVICE_TYPE, DEVICE_INDEX, 0)
+ if ret != 1:
+ raise RuntimeError("Falha ao abrir dispositivo CAN")
+
+ baud = ctypes.c_uint(BAUD_250K)
+ ret = dll.VCI_SetReference(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX, 0, ctypes.byref(baud))
+ if ret != 1:
+ raise RuntimeError("Falha ao configurar baudrate 250 kbps")
+
+ cfg = VCI_INIT_CONFIG()
+ cfg.AccCode = 0
+ cfg.AccMask = 0xFFFFFFFF
+ cfg.Reserved = 0
+ cfg.Filter = 0
+ cfg.Timing0 = 0
+ cfg.Timing1 = 0
+ cfg.Mode = 0
+
+ ret = dll.VCI_InitCAN(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX, ctypes.byref(cfg))
+ if ret != 1:
+ raise RuntimeError("Falha ao inicializar CAN")
+
+ ret = dll.VCI_StartCAN(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX)
+ if ret != 1:
+ raise RuntimeError("Falha ao iniciar CAN")
+
+ dll.VCI_ClearBuffer(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX)
+
+ return dll
+
+
+# ========= ENVIO + RECEPÇÃO PARA UM DATAID =========
+
+def send_and_receive(dll, data_id: int, timeout_s: float = 0.5):
+ req_id = make_request_id(data_id)
+ resp_id_expect = expected_response_id(data_id)
+
+ send_obj = VCI_CAN_OBJ()
+ send_obj.ID = req_id
+ send_obj.SendType = 0
+ send_obj.RemoteFlag = 0
+ send_obj.ExternFlag = 1
+ send_obj.TimeFlag = 0
+ send_obj.DataLen = 8
+ for i in range(8):
+ send_obj.Data[i] = 0x00
+
+ ret = dll.VCI_Transmit(
+ DEVICE_TYPE,
+ DEVICE_INDEX,
+ CHANNEL_INDEX,
+ ctypes.byref(send_obj),
+ 1
+ )
+ print(
+ f"\n📤 Enviando DataID=0x{data_id:02X} "
+ f"ID=0x{req_id:08X} DLC=8 Data=00 00 00 00 00 00 00 00 "
+ f"(ret={ret})"
+ )
+
+ recv_buffer = (VCI_CAN_OBJ * 50)()
+ start = time.time()
+ while time.time() - start < timeout_s:
+ count = dll.VCI_Receive(
+ DEVICE_TYPE,
+ DEVICE_INDEX,
+ CHANNEL_INDEX,
+ ctypes.byref(recv_buffer),
+ 50,
+ 50
+ )
+ if count > 0:
+ for i in range(count):
+ obj = recv_buffer[i]
+ if obj.DataLen == 0:
+ continue
+ if obj.ID != resp_id_expect:
+ # outros frames no barramento, se existirem
+ continue
+ data = [obj.Data[j] for j in range(obj.DataLen)]
+ parse_daly_frame(obj.ID, data)
+ return
+ time.sleep(0.05)
+
+ print(f"⚠️ Sem resposta do BMS para DataID 0x{data_id:02X} em {timeout_s:.1f}s.")
+
+
+# ========= MAIN INTERATIVO =========
+
+def main():
+ dll = init_can()
+ print("✅ Dispositivo aberto, CAN iniciado em 250 kbps.\n")
+ print("Daly BMS console:")
+ print(" Digite o DataID (em hex) que deseja ler (90..98),")
+ print(" ou 'q' para sair.")
+ print("Exemplos: 90, 91, 92, 93, 94, 95, 96, 97, 98\n")
+
+ try:
+ while True:
+ s = input("DataID (hex) > ").strip()
+ if not s:
+ continue
+ if s.lower() in ("q", "quit", "exit"):
+ break
+
+ try:
+ if s.lower().startswith("0x"):
+ s = s[2:]
+ data_id = int(s, 16)
+ except ValueError:
+ print("⚠️ Valor inválido. Digite algo como 90, 91, 98, ou 'q' pra sair.")
+ continue
+
+ if not (0x90 <= data_id <= 0x98):
+ print("⚠️ Este console está preparado para 0x90 a 0x98.")
+ continue
+
+ send_and_receive(dll, data_id, timeout_s=0.8)
+
+ except KeyboardInterrupt:
+ print("\n⏹ Interrompido pelo usuário.")
+ finally:
+ # se quiser, poderia chamar VCI_CloseDevice aqui
+ pass
+
+
+if __name__ == "__main__":
+ main()
diff --git a/Python/dalybms/soc_monitor.py b/Python/dalybms/soc_monitor.py
new file mode 100644
index 000000000..7ae93583b
--- /dev/null
+++ b/Python/dalybms/soc_monitor.py
@@ -0,0 +1,141 @@
+import ctypes
+import time
+import os
+
+# Carrega a DLL
+dll = ctypes.cdll.LoadLibrary(os.path.abspath("ControlCANFD.dll"))
+
+DEVICE_TYPE = 41
+DEVICE_INDEX = 0
+CHANNEL_INDEX = 0 # troca pra 1 se estiver usando CAN2
+
+class VCI_INIT_CONFIG(ctypes.Structure):
+ _fields_ = [
+ ("AccCode", ctypes.c_uint),
+ ("AccMask", ctypes.c_uint),
+ ("Reserved", ctypes.c_uint),
+ ("Filter", ctypes.c_ubyte),
+ ("Timing0", ctypes.c_ubyte),
+ ("Timing1", ctypes.c_ubyte),
+ ("Mode", ctypes.c_ubyte),
+ ]
+
+class VCI_CAN_OBJ(ctypes.Structure):
+ _fields_ = [
+ ("ID", ctypes.c_uint),
+ ("TimeStamp", ctypes.c_uint),
+ ("TimeFlag", ctypes.c_ubyte),
+ ("SendType", ctypes.c_ubyte),
+ ("RemoteFlag", ctypes.c_ubyte),
+ ("ExternFlag", ctypes.c_ubyte),
+ ("DataLen", ctypes.c_ubyte),
+ ("Data", ctypes.c_ubyte * 8),
+ ("Reserved", ctypes.c_ubyte * 3),
+ ]
+
+def u16_be(hi, lo):
+ return ((hi & 0xFF) << 8) | (lo & 0xFF)
+
+def parse_0x90(data_bytes):
+ total_v_raw = u16_be(data_bytes[0], data_bytes[1])
+ meas_v_raw = u16_be(data_bytes[2], data_bytes[3])
+ current_raw = u16_be(data_bytes[4], data_bytes[5])
+ soc_raw = u16_be(data_bytes[6], data_bytes[7])
+
+ total_v = total_v_raw / 10.0
+ meas_v = meas_v_raw / 10.0
+ current = (current_raw - 30000) / 10.0
+ soc = soc_raw / 10.0
+
+ print(f"🔋 Tensão total : {total_v:.1f} V (raw={total_v_raw})")
+ print(f" Tensão medida: {meas_v:.1f} V (raw={meas_v_raw})")
+ print(f" Corrente : {current:.1f} A (raw={current_raw})")
+ print(f" SOC : {soc:.1f} % (raw={soc_raw})")
+
+# -------- init device --------
+ret = dll.VCI_OpenDevice(DEVICE_TYPE, DEVICE_INDEX, 0)
+if ret != 1:
+ print("❌ Falha ao abrir dispositivo.")
+ raise SystemExit
+print("✅ Dispositivo aberto.")
+
+# baud 250 kbps
+baud_250k = ctypes.c_uint(0x1C0008)
+ret = dll.VCI_SetReference(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX, 0, ctypes.byref(baud_250k))
+if ret != 1:
+ print("❌ Falha ao configurar baudrate.")
+ raise SystemExit
+print("🔧 Baudrate configurado para 250 kbps.")
+
+config = VCI_INIT_CONFIG()
+config.AccCode = 0
+config.AccMask = 0xFFFFFFFF
+config.Reserved = 0
+config.Filter = 0
+config.Timing0 = 0
+config.Timing1 = 0
+config.Mode = 0
+
+ret = dll.VCI_InitCAN(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX, ctypes.byref(config))
+if ret != 1:
+ print("❌ Falha ao inicializar CAN.")
+ raise SystemExit
+
+ret = dll.VCI_StartCAN(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX)
+if ret != 1:
+ print("❌ Falha ao iniciar CAN.")
+ raise SystemExit
+
+dll.VCI_ClearBuffer(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX)
+print("🚀 Canal iniciado.\n")
+
+recv_buffer = (VCI_CAN_OBJ * 100)()
+
+try:
+ while True:
+ # monta request 0x90
+ send_obj = VCI_CAN_OBJ()
+ send_obj.ID = 0x18900140 # PC -> BMS, DataID 0x90
+ send_obj.SendType = 0
+ send_obj.RemoteFlag = 0
+ send_obj.ExternFlag = 1 # extended
+ send_obj.DataLen = 8
+ for i in range(8):
+ send_obj.Data[i] = 0x00
+
+ dll.VCI_Transmit(DEVICE_TYPE, DEVICE_INDEX, CHANNEL_INDEX,
+ ctypes.byref(send_obj), 1)
+
+ # espera resposta rápida
+ start = time.time()
+ resp_ok = False
+ while time.time() - start < 0.5:
+ count = dll.VCI_Receive(
+ DEVICE_TYPE,
+ DEVICE_INDEX,
+ CHANNEL_INDEX,
+ ctypes.byref(recv_buffer),
+ 100,
+ 50
+ )
+ if count > 0:
+ for i in range(count):
+ obj = recv_buffer[i]
+ if obj.ID == 0x18904001 and obj.DataLen == 8:
+ data = [obj.Data[j] for j in range(8)]
+ print(f"\n📥 RX ID=0x{obj.ID:08X} Data=" +
+ " ".join(f"{b:02X}" for b in data))
+ parse_0x90(data)
+ resp_ok = True
+ break
+ if resp_ok:
+ break
+ time.sleep(0.05)
+
+ if not resp_ok:
+ print("\n⚠️ Sem resposta do BMS para 0x90 nesse ciclo.")
+
+ time.sleep(1.0)
+
+except KeyboardInterrupt:
+ print("\n🧹 Encerrando monitor...")
diff --git a/Python/dalybms/tradutor.py b/Python/dalybms/tradutor.py
new file mode 100644
index 000000000..253e1937c
--- /dev/null
+++ b/Python/dalybms/tradutor.py
@@ -0,0 +1,371 @@
+#!/usr/bin/env python3
+"""
+Parser simples para frames CAN do Daly Smart BMS (protocolo V1.0).
+
+Uso:
+ python daly_can_parser.py
+
+Depois ir colando linhas assim (exemplos):
+
+ 0x18904001 01 94 00 00 75 30 03 B6
+ 0x18914001 0F A0 01 0F 72 02
+ 0x18924001 3C 01 32 02
+ 0x18934001 00 01 02 05 00 01 86 A0
+ 0x18944001 10 03 01 01 03 00 00 00
+ 0x18984001 00 00 00 00 00 00 00 00
+
+Enter vazio ou “q” sai.
+"""
+
+from typing import List, Tuple
+
+# ------------- helpers básicos ----------------
+
+def parse_hex_token(tok: str) -> int:
+ tok = tok.strip()
+ if tok.lower().startswith("0x"):
+ tok = tok[2:]
+ return int(tok, 16)
+
+
+def split_id_and_data(line: str) -> Tuple[int, List[int]]:
+ """
+ Aceita formatos como:
+ 0x18904001 01 94 00 00 75 30 03 B6
+ 18904001 01 94 00 00 75 30 03 B6
+ Ignora lixo no final.
+ """
+ parts = [p for p in line.replace(",", " ").split() if p]
+
+ if len(parts) < 9:
+ raise ValueError("Esperava ID + 8 bytes de dados (mínimo 9 tokens).")
+
+ can_id = parse_hex_token(parts[0])
+ data_bytes = [parse_hex_token(tok) & 0xFF for tok in parts[1:9]]
+
+ return can_id, data_bytes
+
+
+def get_data_id(can_id: int) -> int:
+ """
+ No protocolo Daly:
+ ID = [Priority][DataID][AddrA][AddrB]
+ DataID = segundo byte (bits 16..23)
+ """
+ return (can_id >> 16) & 0xFF
+
+
+def u16_be(b_hi: int, b_lo: int) -> int:
+ return ((b_hi & 0xFF) << 8) | (b_lo & 0xFF)
+
+
+def bits_set(byte_val: int) -> List[int]:
+ """Retorna lista com índices de bits = 1 (0..7)."""
+ return [i for i in range(8) if (byte_val >> i) & 1]
+
+
+# ------------- parsers por DataID ----------------
+
+def parse_0x90(data: List[int]) -> None:
+ """SOC / total voltage / current."""
+ total_v_raw = u16_be(data[0], data[1])
+ meas_v_raw = u16_be(data[2], data[3])
+ current_raw = u16_be(data[4], data[5])
+ soc_raw = u16_be(data[6], data[7])
+
+ total_v = total_v_raw / 10.0
+ meas_v = meas_v_raw / 10.0
+ current = (current_raw - 30000) / 10.0
+ soc = soc_raw / 10.0
+
+ print("== 0x90: Tensão / Corrente / SOC ==")
+ print(f" Tensão total (cumulative): {total_v:.1f} V (raw={total_v_raw})")
+ print(f" Tensão medida (gather) : {meas_v:.1f} V (raw={meas_v_raw})")
+ print(f" Corrente : {current:.1f} A (raw={current_raw})")
+ print(f" SOC : {soc:.1f} % (raw={soc_raw})")
+
+
+def parse_0x91(data: List[int]) -> None:
+ """Maximum & minimum cell voltage."""
+ vmax_raw = u16_be(data[0], data[1])
+ vmax_idx = data[2]
+ vmin_raw = u16_be(data[3], data[4])
+ vmin_idx = data[5]
+
+ print("== 0x91: Tensão máx/mín de célula ==")
+ print(f" Vmax: {vmax_raw/1000.0:.3f} V (raw={vmax_raw} mV) célula #{vmax_idx}")
+ print(f" Vmin: {vmin_raw/1000.0:.3f} V (raw={vmin_raw} mV) célula #{vmin_idx}")
+
+
+def parse_0x92(data: List[int]) -> None:
+ """Maximum & minimum temperature."""
+ tmax = data[0] - 40
+ tmax_i = data[1]
+ tmin = data[2] - 40
+ tmin_i = data[3]
+
+ print("== 0x92: Temperatura máx/mín ==")
+ print(f" T_max: {tmax} °C (sensor #{tmax_i})")
+ print(f" T_min: {tmin} °C (sensor #{tmin_i})")
+
+
+def parse_0x93(data: List[int]) -> None:
+ """Charge / discharge MOS status + remaining capacity."""
+ state = data[0]
+ charge_mos = data[1]
+ dischg_mos = data[2]
+ life_cycles = data[3]
+ remain_mAh = (
+ (data[4] << 24)
+ | (data[5] << 16)
+ | (data[6] << 8)
+ | data[7]
+ )
+
+ state_map = {0: "parado", 1: "carga", 2: "descarga"}
+
+ print("== 0x93: Estado MOS / capacidade restante ==")
+ print(f" Estado geral : {state} ({state_map.get(state,'desconhecido')})")
+ print(f" Charge MOS state : {charge_mos}")
+ print(f" Discharge MOS state : {dischg_mos}")
+ print(f" Vida BMS (ciclos) : {life_cycles}")
+ print(f" Capacidade restante : {remain_mAh} mAh ({remain_mAh/1000.0:.3f} Ah)")
+
+
+def parse_0x94(data: List[int]) -> None:
+ """Status info: nº células, temps, charger/load, DI/DO bits."""
+ n_series = data[0]
+ n_temps = data[1]
+ charger = data[2]
+ load = data[3]
+ io_byte = data[4]
+
+ di_bits = bits_set(io_byte & 0x0F) # bits 0..3
+ do_bits = bits_set((io_byte >> 4) & 0x0F) # bits 4..7
+
+ print("== 0x94: Status geral / IO ==")
+ print(f" Nº células em série : {n_series}")
+ print(f" Nº sensores de temp : {n_temps}")
+ print(f" Carregador conectado: {'sim' if charger else 'não'}")
+ print(f" Load conectado : {'sim' if load else 'não'}")
+ print(f" DI ativos (0-3) : {['DI'+str(i+1) for i in di_bits] or ['nenhum']}")
+ print(f" DO ativos (0-3) : {['DO'+str(i+1) for i in do_bits] or ['nenhum']}")
+
+
+def parse_0x95(data: List[int]) -> None:
+ """
+ Cell voltage frames (1-48).
+ Byte0 = frame number (0..15), Byte1..6 = 3 tensões de célula (mV), Byte7 reservado.
+ Cada célula = 2 bytes, 1 mV.
+ """
+ frame = data[0]
+ cells = []
+ for i in range(3): # 3 células por frame
+ hi = data[1 + 2*i]
+ lo = data[1 + 2*i + 1]
+ raw = u16_be(hi, lo)
+ if raw == 0xFFFF or raw == 0:
+ continue
+ cell_index = frame * 3 + i + 1 # 1-based
+ cells.append((cell_index, raw))
+
+ print("== 0x95: Tensões individuais de célula (frame múltiplo) ==")
+ print(f" Frame: {frame}")
+ if not cells:
+ print(" (sem células válidas neste frame)")
+ else:
+ for idx, raw in cells:
+ print(f" Célula #{idx:2d}: {raw/1000.0:.3f} V (raw={raw} mV)")
+
+
+def parse_0x96(data: List[int]) -> None:
+ """
+ Cell temperatures frames.
+ Byte0 = frame number (0..2), Byte1..7 = temps com offset 40.
+ """
+ frame = data[0]
+ temps = []
+ for i in range(1, 8):
+ raw = data[i]
+ if raw == 0xFF: # vazio
+ continue
+ temp_c = raw - 40
+ sensor_index = frame * 7 + (i - 1) + 1 # 1-based
+ temps.append((sensor_index, temp_c))
+
+ print("== 0x96: Temperaturas individuais (frame múltiplo) ==")
+ print(f" Frame: {frame}")
+ if not temps:
+ print(" (sem temperaturas válidas neste frame)")
+ else:
+ for idx, t in temps:
+ print(f" Temp sensor #{idx:2d}: {t} °C")
+
+
+def parse_0x97(data: List[int]) -> None:
+ """
+ Balance state 1-48.
+ 0 = off, 1 = on.
+ Bits 0..47 mapeiam células 1..48. 48..63 reservados.
+ """
+ active_cells = []
+ for byte_index, b in enumerate(data):
+ for bit in range(8):
+ global_bit = byte_index * 8 + bit
+ if global_bit >= 48:
+ continue
+ if (b >> bit) & 1:
+ cell_idx = global_bit + 1
+ active_cells.append(cell_idx)
+
+ print("== 0x97: Estado de balanceamento das células ==")
+ if not active_cells:
+ print(" Nenhuma célula está em balanceamento (todas 0).")
+ else:
+ print(f" Células em balanceamento ({len(active_cells)}): {active_cells}")
+
+
+def parse_0x98(data: List[int]) -> None:
+ """
+ Battery failure status: mapa de flags.
+ Imprime apenas os alarmes ativos.
+ """
+ alarms = []
+
+ # Byte0
+ b = data[0]
+ if b & (1 << 0): alarms.append("Cell volt high level 1")
+ if b & (1 << 1): alarms.append("Cell volt high level 2")
+ if b & (1 << 2): alarms.append("Cell volt low level 1")
+ if b & (1 << 3): alarms.append("Cell volt low level 2")
+ if b & (1 << 4): alarms.append("Sum volt high level 1")
+ if b & (1 << 5): alarms.append("Sum volt high level 2")
+ if b & (1 << 6): alarms.append("Sum volt low level 1")
+ if b & (1 << 7): alarms.append("Sum volt low level 2")
+
+ # Byte1
+ b = data[1]
+ if b & (1 << 0): alarms.append("Chg temp high level 1")
+ if b & (1 << 1): alarms.append("Chg temp high level 2")
+ if b & (1 << 2): alarms.append("Chg temp low level 1")
+ if b & (1 << 3): alarms.append("Chg temp low level 2")
+ if b & (1 << 4): alarms.append("Dischg temp high level 1")
+ if b & (1 << 5): alarms.append("Dischg temp high level 2")
+ if b & (1 << 6): alarms.append("Dischg temp low level 1")
+ if b & (1 << 7): alarms.append("Dischg temp low level 2")
+
+ # Byte2
+ b = data[2]
+ if b & (1 << 0): alarms.append("Chg overcurrent level 1")
+ if b & (1 << 1): alarms.append("Chg overcurrent level 2")
+ if b & (1 << 2): alarms.append("Dischg overcurrent level 1")
+ if b & (1 << 3): alarms.append("Dischg overcurrent level 2")
+ if b & (1 << 4): alarms.append("SOC high level 1")
+ if b & (1 << 5): alarms.append("SOC high level 2")
+ if b & (1 << 6): alarms.append("SOC low level 1")
+ if b & (1 << 7): alarms.append("SOC low level 2")
+
+ # Byte3
+ b = data[3]
+ if b & (1 << 0): alarms.append("Diff volt level 1")
+ if b & (1 << 1): alarms.append("Diff volt level 2")
+ if b & (1 << 2): alarms.append("Diff temp level 1")
+ if b & (1 << 3): alarms.append("Diff temp level 2")
+
+ # Byte4
+ b = data[4]
+ if b & (1 << 0): alarms.append("Chg MOS temp high alarm")
+ if b & (1 << 1): alarms.append("Dischg MOS temp high alarm")
+ if b & (1 << 2): alarms.append("Chg MOS temp sensor error")
+ if b & (1 << 3): alarms.append("Dischg MOS temp sensor error")
+ if b & (1 << 4): alarms.append("Chg MOS adhesion error")
+ if b & (1 << 5): alarms.append("Dischg MOS adhesion error")
+ if b & (1 << 6): alarms.append("Chg MOS open circuit error")
+ if b & (1 << 7): alarms.append("Dischg MOS open circuit error")
+
+ # Byte5
+ b = data[5]
+ if b & (1 << 0): alarms.append("AFE collect chip error")
+ if b & (1 << 1): alarms.append("Voltage collect dropped")
+ if b & (1 << 2): alarms.append("Cell temp sensor error")
+ if b & (1 << 3): alarms.append("EEPROM error")
+ if b & (1 << 4): alarms.append("RTC error")
+ if b & (1 << 5): alarms.append("Precharge failure")
+ if b & (1 << 6): alarms.append("Communication failure")
+ if b & (1 << 7): alarms.append("Internal communication failure")
+
+ # Byte6
+ b = data[6]
+ if b & (1 << 0): alarms.append("Current module fault")
+ if b & (1 << 1): alarms.append("Sum voltage detect fault")
+ if b & (1 << 2): alarms.append("Short circuit protect fault")
+ if b & (1 << 3): alarms.append("Low volt forbidden chg fault")
+
+ fault_code = data[7]
+
+ print("== 0x98: Status de falhas / alarmes ==")
+ if not alarms and fault_code == 0:
+ print(" Nenhum alarme ativo.")
+ else:
+ print(" Alarmes ativos:")
+ for a in alarms:
+ print(" - " + a)
+ print(f" Fault code bruto: 0x{fault_code:02X} ({fault_code})")
+
+
+# ------------- roteador principal ----------------
+
+def parse_daly_frame(can_id: int, data: List[int]) -> None:
+ data_id = get_data_id(can_id)
+ print(f"\n=== Frame recebido ===")
+ print(f" CAN ID : 0x{can_id:08X}")
+ print(f" DataID : 0x{data_id:02X}")
+ print(f" Data : {' '.join(f'{b:02X}' for b in data)}")
+
+ if data_id == 0x90:
+ parse_0x90(data)
+ elif data_id == 0x91:
+ parse_0x91(data)
+ elif data_id == 0x92:
+ parse_0x92(data)
+ elif data_id == 0x93:
+ parse_0x93(data)
+ elif data_id == 0x94:
+ parse_0x94(data)
+ elif data_id == 0x95:
+ parse_0x95(data)
+ elif data_id == 0x96:
+ parse_0x96(data)
+ elif data_id == 0x97:
+ parse_0x97(data)
+ elif data_id == 0x98:
+ parse_0x98(data)
+ else:
+ print(" DataID ainda não implementado neste parser.")
+
+
+def main():
+ print("Daly BMS CAN parser (teste de bancada)")
+ print("Cole uma linha com ID + 8 bytes (ex.: 0x18904001 01 94 00 00 75 30 03 B6)")
+ print("Enter vazio ou 'q' para sair.\n")
+
+ while True:
+ try:
+ line = input("> ").strip()
+ except (EOFError, KeyboardInterrupt):
+ print("\nSaindo.")
+ break
+
+ if not line or line.lower() in ("q", "quit", "exit"):
+ print("Saindo.")
+ break
+
+ try:
+ can_id, data = split_id_and_data(line)
+ parse_daly_frame(can_id, data)
+ except Exception as e:
+ print(f"Erro ao processar linha: {e}")
+
+
+if __name__ == "__main__":
+ main()