From 5e9155c3ed5594241423179502b7b65d723f3dae Mon Sep 17 00:00:00 2001 From: Diego Freitas Date: Thu, 5 Feb 2026 16:39:59 -0300 Subject: [PATCH] Implementado bateria Daly, integrado IA segformer ao visual worker, treinamento raw --- AgroBase/AgroBase/AgroBase.csproj | 2 + .../Forms/frmAcompanhamento.Designer.cs | 34 +- AgroBase/AgroBase/Forms/frmAcompanhamento.cs | 6 + AgroBase/AgroBase/Models/DalyBMSModel.cs | 238 ++++++++ .../Models/Operacoes/OperacaoModel.cs | 1 + AgroBase/AgroBase/Services/CANService.cs | 91 ++- .../AgroBase/Services/CANServiceSerial.cs | 217 +++++--- .../AgroBase/Services/CANServiceWaveshare.cs | 129 +++-- AgroBase/AgroBase/Services/DalyBMSService.cs | 491 ++++++++++++++++ .../AgroBase/Services/DispositivosService.cs | 4 +- .../AgroBase/Services/MKS057DCanService.cs | 6 +- AgroBase/AgroBase/Services/OIDCanService.cs | 6 +- .../Operadores/HealthWorkerService.cs | 39 +- AgroBase/AgroBase/Services/SerialService.cs | 10 + .../Services/WaveshareCanFDService.cs | 31 +- .../Debug/Parametros/parametersAtu-1_1.par | 2 +- .../Debug/Parametros/parametersMvd-2_0.par | 2 +- .../Debug/Parametros/parametersSen-1_3.par | 2 +- .../x64/Debug/Parametros/version_files.vsf | 10 +- .../Scripts/workers/health_worker/main.py | 2 + .../workers/visual_worker/camera_manager.py | 2 +- .../processamento/costmap_fuser.py | 17 +- Python/OAK/datasets/_5_augmentation_raw.py | 523 ++++++++++++------ Python/OAK/datasets/_6_normalize_raw.py | 43 +- .../OAK/datasets/_8_train_segformer_b3_raw.py | 5 +- .../OAK/datasets/_9_test_segformer_b3_raw.py | 374 ++++++++++--- Python/OAK/datasets/config.json | 10 +- .../{config_gal.json => config_oak.json} | 10 +- Python/dalybms/ControlCANFD.dll | 3 + Python/dalybms/console.py | 465 ++++++++++++++++ Python/dalybms/soc_monitor.py | 141 +++++ Python/dalybms/tradutor.py | 371 +++++++++++++ 32 files changed, 2822 insertions(+), 465 deletions(-) create mode 100644 AgroBase/AgroBase/Models/DalyBMSModel.cs create mode 100644 AgroBase/AgroBase/Services/DalyBMSService.cs rename Python/OAK/datasets/{config_gal.json => config_oak.json} (67%) create mode 100644 Python/dalybms/ControlCANFD.dll create mode 100644 Python/dalybms/console.py create mode 100644 Python/dalybms/soc_monitor.py create mode 100644 Python/dalybms/tradutor.py 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()