From 89e5f1ae41ddea37244900f238e85cb34c0c5f02 Mon Sep 17 00:00:00 2001 From: Diego Freitas Date: Thu, 26 Feb 2026 16:57:22 -0300 Subject: [PATCH] Ajustes de logica do MPC e definicao de comandos --- AgroBase/AgroBase/Forms/IHM/frmDialogoMapa.cs | 12 +- .../Forms/Operacoes/frmOperacaoManual.cs | 4 +- .../Forms/Operacoes/frmResultadosOperacao.cs | 12 +- .../frmSimulacaoMapaGPS.Designer.cs | 100 ++-- .../Forms/Simuladores/frmSimulacaoMapaGPS.cs | 36 +- .../frmSimulacaoMapeamentoVisual.cs | 3 +- AgroBase/AgroBase/Forms/frmOperarioSonar.cs | 37 +- AgroBase/AgroBase/Models/Enums.cs | 1 + .../AgroBase/Models/Modules/AtuadorModel.cs | 12 +- .../Models/Modules/SensoriamentoModel.cs | 4 +- AgroBase/AgroBase/Models/OAKCameraModel.cs | 6 +- .../Models/Operacoes/OperacaoModel.cs | 55 ++- .../Operacoes/OperacaoParametrosModel.cs | 7 +- .../Models/Operadores/CameraWorkerModel.cs | 8 - .../Models/Operadores/VisualWorkerModel.cs | 6 +- .../Models/Operadores/WeedWorkerModel.cs | 7 +- .../Models/TrajetoriaMapaOperacaoModel.cs | 322 ++++++++---- AgroBase/AgroBase/Models/Variaveis.cs | 2 +- .../Operadores/CameraWorkerService.cs | 1 + .../Operadores/HealthWorkerService.cs | 12 +- .../Operadores/ManagerWorkerService.cs | 20 +- .../Services/Operadores/OperadoresService.cs | 21 +- .../Operadores/VisualWorkerService.cs | 4 +- .../Services/Operadores/WeedWorkerService.cs | 5 +- .../Debug/Parametros/parametersAtu-1_1.par | 2 +- .../Debug/Parametros/parametersMvd-2_0.par | 2 +- .../Debug/Parametros/parametersSen-1_3.par | 2 +- .../workers/camera_worker/camera_gal.py | 123 ++++- .../workers/camera_worker/camera_oak.py | 104 +++- .../workers/health_worker/modulos/bateria.py | 352 +++++++++++++ .../workers/manager_worker/gerenciador.py | 16 +- .../manager_worker/modulos/direcional.py | 123 ++--- .../manager_worker/modulos/movimentacao.py | 41 +- .../workers/manager_worker/modulos/mpc.py | 465 +++--------------- .../manager_worker/modulos/regras_taticas.py | 51 ++ .../processadores/_0_nao_iniciado.py | 3 +- .../processadores/_1_parametrizando.py | 3 +- .../processadores/_2_calibrando.py | 3 +- .../processadores/_3_aguardando.py | 3 +- .../processadores/_4_em_andamento.py | 53 +- .../manager_worker/processadores/_5_parado.py | 3 +- .../processadores/_6_concluido.py | 3 +- .../manager_worker/processadores/padroes.py | 14 +- .../workers/shared/contexto_global_redis.py | 18 +- .../Python/Scripts/workers/shared/enums.py | 8 +- .../Python/Scripts/workers/shared/utils.py | 20 + .../workers/visual_worker/camera_manager.py | 22 +- .../Scripts/workers/visual_worker/main.py | 19 +- .../processamento/segmentacao_semantica.py | 8 +- .../workers/weed_worker/camera_manager.py | 65 ++- .../Scripts/workers/weed_worker/config.py | 3 +- .../Scripts/workers/weed_worker/main.py | 19 +- .../workers/weed_worker/weed_detector.py | 3 +- .../Models/TcpVideoReceiver.cs | 151 ++++++ .../OperationControl/Windows/MainWindow.xaml | 16 +- .../Windows/MainWindow.xaml.cs | 171 ++++--- Firmware/Modulos/BicoPulverizadorModel.h | 6 +- 57 files changed, 1567 insertions(+), 1025 deletions(-) create mode 100644 AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/bateria.py create mode 100644 AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py create mode 100644 AgroBase/OperationControl/Models/TcpVideoReceiver.cs diff --git a/AgroBase/AgroBase/Forms/IHM/frmDialogoMapa.cs b/AgroBase/AgroBase/Forms/IHM/frmDialogoMapa.cs index 2845a4db8..79a54806b 100644 --- a/AgroBase/AgroBase/Forms/IHM/frmDialogoMapa.cs +++ b/AgroBase/AgroBase/Forms/IHM/frmDialogoMapa.cs @@ -251,7 +251,7 @@ namespace AgroBase.Forms.IHM ReqFrameCam = true; try { - var frame = await WeedWorkerService.GetCameraFrame(CameraFrameType.Rgb); + var frame = await WeedWorkerService.GetCameraFrame(TipoFrameCamera.Rgb); AtualizarImagemPainel(pnlCameraSolo0, frame?.image()); } finally @@ -265,10 +265,10 @@ namespace AgroBase.Forms.IHM ReqFrameSnr = true; try { - var frameRgb = await VisualWorkerService.GetCameraFrame(CameraFrameType.Rgb); + var frameRgb = await VisualWorkerService.GetCameraFrame(TipoFrameCamera.Rgb); AtualizarImagemPainel(pnlCameraCaminho, frameRgb?.image()); - var frameSeg = await VisualWorkerService.GetCameraFrame(CameraFrameType.Segmentacao); + var frameSeg = await VisualWorkerService.GetCameraFrame(TipoFrameCamera.Segmentacao); AtualizarImagemPainel(pnlCameraCaminhoSeg, frameSeg?.image()); } finally @@ -336,7 +336,7 @@ namespace AgroBase.Forms.IHM var _Controle = Variaveis.OperacaoEmAndamento.Controle; cmbModoControle.SelectedIndex = (int)_Controle.TipoMovimento; chbSonarAtivado.Checked = pControle.SonarAtivado; - chbFrenagemAutomatica.Checked = pControle.FrenagemAutomatica; + chbFrenagemAutomatica.Checked = pControle.FrenagemAutomaticaAoParar; nudVelSemErvas.Value = (int)pControle.MovVelocidadeSErvasPercent; nudVelComErvas.Value = (int)pControle.MovVelocidadeCErvasPercent; chbPulverizadorAutomatico.Checked = pControle.PulverizadorAutomatico; @@ -870,7 +870,7 @@ namespace AgroBase.Forms.IHM if (res == DialogResult.Yes) { pControle.SonarAtivado = chbSonarAtivado.Checked; - pControle.FrenagemAutomatica = chbFrenagemAutomatica.Checked; + pControle.FrenagemAutomaticaAoParar = chbFrenagemAutomatica.Checked; pControle.MovVelocidadeSErvasPercent = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelSemErvas.Value)); pControle.MovVelocidadeCErvasPercent = (int)FuncoesMatematicas.CalculaRPMVelocidade(FuncoesMatematicas.CalculaVelocidadeMsPercentual((int)nudVelComErvas.Value)); pControle.PulverizadorAutomatico = chbPulverizadorAutomatico.Checked; @@ -894,7 +894,7 @@ namespace AgroBase.Forms.IHM else { chbSonarAtivado.Checked = pControle.SonarAtivado; - chbFrenagemAutomatica.Checked = pControle.FrenagemAutomatica; + chbFrenagemAutomatica.Checked = pControle.FrenagemAutomaticaAoParar; nudVelSemErvas.Value = (int)pControle.MovVelocidadeSErvasPercent; nudVelComErvas.Value = (int)pControle.MovVelocidadeCErvasPercent; chbPulverizadorAutomatico.Checked = pControle.PulverizadorAutomatico; diff --git a/AgroBase/AgroBase/Forms/Operacoes/frmOperacaoManual.cs b/AgroBase/AgroBase/Forms/Operacoes/frmOperacaoManual.cs index 351a35c5a..f0ff6af2d 100644 --- a/AgroBase/AgroBase/Forms/Operacoes/frmOperacaoManual.cs +++ b/AgroBase/AgroBase/Forms/Operacoes/frmOperacaoManual.cs @@ -198,7 +198,7 @@ namespace AgroBase.Forms.Operacoes ReqFrameCam = true; try { - var frame = await WeedWorkerService.GetCameraFrame(CameraFrameType.Debug); + var frame = await WeedWorkerService.GetCameraFrame(TipoFrameCamera.Debug); Panel pnl = FuncoesGlobais.FindControlRecursive(flwCamerasSolo, "pnlCamSolo_" + Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo[0].Name); AtualizarImagemPainel(pnl, frame?.image()); } @@ -213,7 +213,7 @@ namespace AgroBase.Forms.Operacoes ReqFrameSnr = true; try { - var frameRgb = await VisualWorkerService.GetCameraFrame(CameraFrameType.Debug); + var frameRgb = await VisualWorkerService.GetCameraFrame(TipoFrameCamera.Overlay); AtualizarImagemPainel(pnlCameraRua, frameRgb?.image()); //var frameSeg = await VisualWorkerService.GetCameraFrame(CameraFrameType.Segmentacao); diff --git a/AgroBase/AgroBase/Forms/Operacoes/frmResultadosOperacao.cs b/AgroBase/AgroBase/Forms/Operacoes/frmResultadosOperacao.cs index a0641b609..1168fbd5e 100644 --- a/AgroBase/AgroBase/Forms/Operacoes/frmResultadosOperacao.cs +++ b/AgroBase/AgroBase/Forms/Operacoes/frmResultadosOperacao.cs @@ -1591,12 +1591,12 @@ namespace AgroBase.Forms.Operacoes txtCamCaminhoErroLateral.Text = (Log.OperadorVisual?.Analises?.segmentacao?.erro_lateral_pct ?? 0).ToString("0.00"); txtCamCaminhoStatusCarro.Text = (Log.OperadorVisual?.Analises?.segmentacao?.status_corredor ?? Enums.StatusCarroMapa.Parado).ToString(); - txtTempoEntrandoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.EntrandoRua).Value.ToString("0.00") + " s"; - txtTempoCaminhandoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.CaminhandoRua).Value.ToString("0.00") + " s"; - txtTempoSaindoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.SaindoRua).Value.ToString("0.00") + " s"; - txtTempoParado.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.Parado).Value.ToString("0.00") + " s"; - txtTempoDirecionando.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.Direcionando).Value.ToString("0.00") + " s"; - txtTempoManobrando.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.Manobrando).Value.ToString("0.00") + " s"; + //txtTempoEntrandoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.EntrandoRua).Value.ToString("0.00") + " s"; + //txtTempoCaminhandoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.CaminhandoRua).Value.ToString("0.00") + " s"; + //txtTempoSaindoRua.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.SaindoRua).Value.ToString("0.00") + " s"; + //txtTempoParado.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.Parado).Value.ToString("0.00") + " s"; + //txtTempoDirecionando.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.Direcionando).Value.ToString("0.00") + " s"; + //txtTempoManobrando.Text = Log.Trajetoria.CorredorAtual.TempoPorStatus.FirstOrDefault(x => x.Key == Enums.StatusCarroMapa.Manobrando).Value.ToString("0.00") + " s"; pnlCaminho.BackgroundImage = CarregarImagemCamera(pathImagensCaminho, "_segmentacao"); pnlCaminho.BackgroundImageLayout = ImageLayout.Zoom; diff --git a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.Designer.cs b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.Designer.cs index 72463f329..0340bc571 100644 --- a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.Designer.cs +++ b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.Designer.cs @@ -30,6 +30,9 @@ { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmSimulacaoMapaGPS)); this.pnlOpcoes = new System.Windows.Forms.Panel(); + this.btnLiberarCorredor = new System.Windows.Forms.Button(); + this.btnFixarBase = new System.Windows.Forms.Button(); + this.btnRetornarBase = new System.Windows.Forms.Button(); this.lblDelayPosicao = new System.Windows.Forms.Label(); this.txtDelayPosicao = new System.Windows.Forms.TextBox(); this.lblCarregado = new System.Windows.Forms.Label(); @@ -105,9 +108,6 @@ this.lblTempoRestante = new System.Windows.Forms.Label(); this.lblPercentualRua = new System.Windows.Forms.Label(); this.lblPercentualOperacao = new System.Windows.Forms.Label(); - this.btnRetornarBase = new System.Windows.Forms.Button(); - this.btnFixarBase = new System.Windows.Forms.Button(); - this.btnLiberarCorredor = new System.Windows.Forms.Button(); this.pnlOpcoes.SuspendLayout(); this.gpbSonar.SuspendLayout(); this.gpbGPS.SuspendLayout(); @@ -151,6 +151,39 @@ this.pnlOpcoes.Size = new System.Drawing.Size(1379, 100); this.pnlOpcoes.TabIndex = 0; // + // btnLiberarCorredor + // + this.btnLiberarCorredor.Location = new System.Drawing.Point(388, 75); + this.btnLiberarCorredor.Margin = new System.Windows.Forms.Padding(2); + this.btnLiberarCorredor.Name = "btnLiberarCorredor"; + this.btnLiberarCorredor.Size = new System.Drawing.Size(55, 20); + this.btnLiberarCorredor.TabIndex = 48; + this.btnLiberarCorredor.Text = "Liberar"; + this.btnLiberarCorredor.UseVisualStyleBackColor = true; + this.btnLiberarCorredor.Click += new System.EventHandler(this.btnLiberarCorredor_Click); + // + // btnFixarBase + // + this.btnFixarBase.Location = new System.Drawing.Point(388, 13); + this.btnFixarBase.Margin = new System.Windows.Forms.Padding(2); + this.btnFixarBase.Name = "btnFixarBase"; + this.btnFixarBase.Size = new System.Drawing.Size(55, 27); + this.btnFixarBase.TabIndex = 47; + this.btnFixarBase.Text = "F Base"; + this.btnFixarBase.UseVisualStyleBackColor = true; + this.btnFixarBase.Click += new System.EventHandler(this.btnFixarBase_Click); + // + // btnRetornarBase + // + this.btnRetornarBase.Location = new System.Drawing.Point(388, 44); + this.btnRetornarBase.Margin = new System.Windows.Forms.Padding(2); + this.btnRetornarBase.Name = "btnRetornarBase"; + this.btnRetornarBase.Size = new System.Drawing.Size(55, 27); + this.btnRetornarBase.TabIndex = 46; + this.btnRetornarBase.Text = "R Base"; + this.btnRetornarBase.UseVisualStyleBackColor = true; + this.btnRetornarBase.Click += new System.EventHandler(this.btnRetornarBase_Click); + // // lblDelayPosicao // this.lblDelayPosicao.AutoSize = true; @@ -692,7 +725,7 @@ this.lblTempoOperacao.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblTempoOperacao.AutoSize = true; this.lblTempoOperacao.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblTempoOperacao.Location = new System.Drawing.Point(232, 460); + this.lblTempoOperacao.Location = new System.Drawing.Point(232, 457); this.lblTempoOperacao.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblTempoOperacao.Name = "lblTempoOperacao"; this.lblTempoOperacao.Size = new System.Drawing.Size(148, 13); @@ -704,7 +737,7 @@ this.lblStatusOperacao.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblStatusOperacao.AutoSize = true; this.lblStatusOperacao.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblStatusOperacao.Location = new System.Drawing.Point(232, 443); + this.lblStatusOperacao.Location = new System.Drawing.Point(232, 437); this.lblStatusOperacao.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblStatusOperacao.Name = "lblStatusOperacao"; this.lblStatusOperacao.Size = new System.Drawing.Size(133, 13); @@ -728,7 +761,7 @@ this.lblDistanciaFinal.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblDistanciaFinal.AutoSize = true; this.lblDistanciaFinal.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblDistanciaFinal.Location = new System.Drawing.Point(10, 460); + this.lblDistanciaFinal.Location = new System.Drawing.Point(10, 457); this.lblDistanciaFinal.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblDistanciaFinal.Name = "lblDistanciaFinal"; this.lblDistanciaFinal.Size = new System.Drawing.Size(135, 13); @@ -740,7 +773,7 @@ this.lblDistanciaOperacao.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblDistanciaOperacao.AutoSize = true; this.lblDistanciaOperacao.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblDistanciaOperacao.Location = new System.Drawing.Point(10, 443); + this.lblDistanciaOperacao.Location = new System.Drawing.Point(10, 437); this.lblDistanciaOperacao.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblDistanciaOperacao.Name = "lblDistanciaOperacao"; this.lblDistanciaOperacao.Size = new System.Drawing.Size(189, 13); @@ -752,7 +785,7 @@ this.lblDirecao.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblDirecao.AutoSize = true; this.lblDirecao.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblDirecao.Location = new System.Drawing.Point(390, 443); + this.lblDirecao.Location = new System.Drawing.Point(390, 437); this.lblDirecao.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblDirecao.Name = "lblDirecao"; this.lblDirecao.Size = new System.Drawing.Size(84, 13); @@ -764,7 +797,7 @@ this.lblStatus.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblStatus.AutoSize = true; this.lblStatus.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblStatus.Location = new System.Drawing.Point(390, 418); + this.lblStatus.Location = new System.Drawing.Point(390, 417); this.lblStatus.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblStatus.Name = "lblStatus"; this.lblStatus.Size = new System.Drawing.Size(96, 13); @@ -879,7 +912,7 @@ this.lblRua.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblRua.AutoSize = true; this.lblRua.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblRua.Location = new System.Drawing.Point(11, 398); + this.lblRua.Location = new System.Drawing.Point(11, 397); this.lblRua.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblRua.Name = "lblRua"; this.lblRua.Size = new System.Drawing.Size(74, 13); @@ -891,7 +924,7 @@ this.lblMargem.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblMargem.AutoSize = true; this.lblMargem.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblMargem.Location = new System.Drawing.Point(99, 398); + this.lblMargem.Location = new System.Drawing.Point(99, 397); this.lblMargem.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblMargem.Name = "lblMargem"; this.lblMargem.Size = new System.Drawing.Size(71, 13); @@ -903,7 +936,7 @@ this.lblProximoPonto.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblProximoPonto.AutoSize = true; this.lblProximoPonto.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblProximoPonto.Location = new System.Drawing.Point(183, 398); + this.lblProximoPonto.Location = new System.Drawing.Point(183, 397); this.lblProximoPonto.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblProximoPonto.Name = "lblProximoPonto"; this.lblProximoPonto.Size = new System.Drawing.Size(87, 13); @@ -915,7 +948,7 @@ this.lblAproximando.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblAproximando.AutoSize = true; this.lblAproximando.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblAproximando.Location = new System.Drawing.Point(285, 398); + this.lblAproximando.Location = new System.Drawing.Point(285, 397); this.lblAproximando.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblAproximando.Name = "lblAproximando"; this.lblAproximando.Size = new System.Drawing.Size(68, 13); @@ -927,7 +960,7 @@ this.lblDistProx.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblDistProx.AutoSize = true; this.lblDistProx.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblDistProx.Location = new System.Drawing.Point(11, 418); + this.lblDistProx.Location = new System.Drawing.Point(11, 417); this.lblDistProx.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblDistProx.Name = "lblDistProx"; this.lblDistProx.Size = new System.Drawing.Size(160, 13); @@ -939,7 +972,7 @@ this.lblDistAnt.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblDistAnt.AutoSize = true; this.lblDistAnt.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblDistAnt.Location = new System.Drawing.Point(183, 418); + this.lblDistAnt.Location = new System.Drawing.Point(183, 417); this.lblDistAnt.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblDistAnt.Name = "lblDistAnt"; this.lblDistAnt.Size = new System.Drawing.Size(159, 13); @@ -951,7 +984,7 @@ this.lblTipoMovimento.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblTipoMovimento.AutoSize = true; this.lblTipoMovimento.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblTipoMovimento.Location = new System.Drawing.Point(390, 398); + this.lblTipoMovimento.Location = new System.Drawing.Point(390, 397); this.lblTipoMovimento.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblTipoMovimento.Name = "lblTipoMovimento"; this.lblTipoMovimento.Size = new System.Drawing.Size(75, 13); @@ -975,7 +1008,7 @@ this.lblPercentualRua.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblPercentualRua.AutoSize = true; this.lblPercentualRua.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F); - this.lblPercentualRua.Location = new System.Drawing.Point(390, 460); + this.lblPercentualRua.Location = new System.Drawing.Point(390, 457); this.lblPercentualRua.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.lblPercentualRua.Name = "lblPercentualRua"; this.lblPercentualRua.Size = new System.Drawing.Size(62, 13); @@ -994,39 +1027,6 @@ this.lblPercentualOperacao.TabIndex = 42; this.lblPercentualOperacao.Text = "Operação: 0,00%"; // - // btnRetornarBase - // - this.btnRetornarBase.Location = new System.Drawing.Point(388, 44); - this.btnRetornarBase.Margin = new System.Windows.Forms.Padding(2); - this.btnRetornarBase.Name = "btnRetornarBase"; - this.btnRetornarBase.Size = new System.Drawing.Size(55, 27); - this.btnRetornarBase.TabIndex = 46; - this.btnRetornarBase.Text = "R Base"; - this.btnRetornarBase.UseVisualStyleBackColor = true; - this.btnRetornarBase.Click += new System.EventHandler(this.btnRetornarBase_Click); - // - // btnFixarBase - // - this.btnFixarBase.Location = new System.Drawing.Point(388, 13); - this.btnFixarBase.Margin = new System.Windows.Forms.Padding(2); - this.btnFixarBase.Name = "btnFixarBase"; - this.btnFixarBase.Size = new System.Drawing.Size(55, 27); - this.btnFixarBase.TabIndex = 47; - this.btnFixarBase.Text = "F Base"; - this.btnFixarBase.UseVisualStyleBackColor = true; - this.btnFixarBase.Click += new System.EventHandler(this.btnFixarBase_Click); - // - // btnLiberarCorredor - // - this.btnLiberarCorredor.Location = new System.Drawing.Point(388, 75); - this.btnLiberarCorredor.Margin = new System.Windows.Forms.Padding(2); - this.btnLiberarCorredor.Name = "btnLiberarCorredor"; - this.btnLiberarCorredor.Size = new System.Drawing.Size(55, 20); - this.btnLiberarCorredor.TabIndex = 48; - this.btnLiberarCorredor.Text = "Liberar"; - this.btnLiberarCorredor.UseVisualStyleBackColor = true; - this.btnLiberarCorredor.Click += new System.EventHandler(this.btnLiberarCorredor_Click); - // // frmSimulacaoMapaGPS // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); diff --git a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs index 6737f8da3..a7698e7e4 100644 --- a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs +++ b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapaGPS.cs @@ -125,7 +125,8 @@ namespace AgroBase.Forms return; } - lblStatusOperacao.Text = "Operação: " + Enum.GetName(typeof(StatusOperacao), _Sensoriamento.StatusOperacao); + lblStatusOperacao.Text = $"Operação: {_Sensoriamento.StatusOperacao}"; + if (_Sensoriamento.StatusOperacao == StatusOperacao.Aguardando) lblStatusOperacao.Text += $" ({_Sensoriamento.TempoAguardandoSeg:0})"; lblTipoMovimento.Text = (_Sensoriamento.Controle?.TipoMovimento ?? TipoMovimentoDirecional.Diagnostico).ToString(); if (_Trajetoria == null) @@ -136,21 +137,21 @@ namespace AgroBase.Forms if (_Sensoriamento.Trajetoria == null) return; - lblStatus.Text = "Carro: " + Enum.GetName(typeof(StatusCarroMapa), _Sensoriamento.Trajetoria.StatusCarro); - lblDirecao.Text = "Direção: " + Enum.GetName(typeof(DirecaoCarroRua), _Sensoriamento.Trajetoria.DirecaoCaminho); - lblDistanciaOperacao.Text = "Distância Operação: " + _Sensoriamento.Trajetoria.DistanciaPercorrida.ToString("0.00") + " m de " + _Sensoriamento.Trajetoria.DistanciaTotal.ToString("0.00") + " m"; - lblDistanciaFinal.Text = "Distância Restante: " + _Sensoriamento.Trajetoria.DistanciaRestante.ToString("0.00") + " m"; - lblDistanciaLateral.Text = "Esq: " + _Sensoriamento.Trajetoria.DistanciaEsquerda.ToString("0.00") + " m - Dir: " + _Sensoriamento.Trajetoria.DistanciaDireita.ToString("0.00") + " m " + Variaveis.OperacaoEmAndamento.Controle.ErroLateral.ToString("0.00") + " m"; - lblRua.Text = "Corredor: " + (_Sensoriamento.Trajetoria.CorredorAtual.Dentro ? "Dentro" : "Fora"); - lblMargem.Text = "Margem: " + (_Sensoriamento.Trajetoria.NaMargemDoCorredor ? "Sim" : "Não"); - lblProximoPonto.Text = "Próximo Ponto: " + (_Sensoriamento.Trajetoria.ProximoPonto.idxPonto); + lblStatus.Text = $"Carro: {_Sensoriamento.Trajetoria.StatusCarro} ({_Sensoriamento.OperadorVisual.Analises.segmentacao.status_corredor})"; + lblDirecao.Text = $"Direção: {_Sensoriamento.Trajetoria.DirecaoCaminho}"; + lblDistanciaOperacao.Text = $"Distância Operação: {_Sensoriamento.Trajetoria.DistanciaPercorrida:F2} m de {_Sensoriamento.Trajetoria.DistanciaTotal:F2} m"; + lblDistanciaFinal.Text = $"Distância Restante: {_Sensoriamento.Trajetoria.DistanciaRestante:F2} m"; + lblDistanciaLateral.Text = $"Esq: {_Sensoriamento.Trajetoria.DistanciaEsquerda:F2} m - Dir: {_Sensoriamento.Trajetoria.DistanciaDireita:F2} m {Variaveis.OperacaoEmAndamento.Controle.ErroLateral:F2} m"; + lblRua.Text = $"Corredor: " + (_Sensoriamento.Trajetoria.CorredorAtual.Dentro ? "Dentro" : "Fora"); + lblMargem.Text = $"Margem: " + (_Sensoriamento.Trajetoria.NaMargemDoCorredor ? "Sim" : "Não"); + lblProximoPonto.Text = $"Próximo Ponto: {_Sensoriamento.Trajetoria.ProximoPonto.idxPonto}"; lblAproximando.Text = (_Sensoriamento.Trajetoria.ProximoPonto.Aproximando ? "Aproximando" : "Afastando"); - lblDistProx.Text = "Distância Próximo Ponto: " + _Sensoriamento.Trajetoria.ProximoPonto.DistanciaTrajeto.ToString("0.00") + " m"; - lblDistAnt.Text = "Distância Ponto Anterior: " + _Sensoriamento.Trajetoria.PontoMaisProximo.DistanciaTrajeto.ToString("0.00") + " m"; - lblTempoRestante.Text = "Tempo Restante: " + _Sensoriamento.Trajetoria.TempoEstimadoRestante; - lblTempoOperacao.Text = "Tempo: " + _Sensoriamento.TempoDecorrido.ToString("HH:mm:ss") + " de " + _Sensoriamento.Trajetoria.TempoEstimadoOperacao; - lblPercentualRua.Text = "Rua: " + _Sensoriamento.Trajetoria.CorredorAtual.Progresso.ToString("0.00") + "%"; - lblPercentualOperacao.Text = "Operação: " + _Sensoriamento.Trajetoria.ProgressoTrajeto.ToString("0.00") + "%"; + lblDistProx.Text = $"Distância Próximo Ponto: {_Sensoriamento.Trajetoria.ProximoPonto.DistanciaTrajeto:F2} m"; + lblDistAnt.Text = $"Distância Ponto Anterior: {_Sensoriamento.Trajetoria.PontoMaisProximo.DistanciaTrajeto:F2} m"; + lblTempoRestante.Text = $"Tempo Restante: {_Sensoriamento.Trajetoria.TempoEstimadoRestante}"; + lblTempoOperacao.Text = $"Tempo: " + _Sensoriamento.TempoDecorrido.ToString("HH:mm:ss") + $" de {_Sensoriamento.Trajetoria.TempoEstimadoOperacao}"; + lblPercentualRua.Text = $"Rua: {_Sensoriamento.Trajetoria.CorredorAtual.Progresso:F2}%"; + lblPercentualOperacao.Text = $"Operação: {_Sensoriamento.Trajetoria.ProgressoTrajeto:F2}%"; pnlOrientacaoTrajeto.Invalidate(); @@ -544,6 +545,11 @@ namespace AgroBase.Forms private void btnRetornarBase_Click(object sender, EventArgs e) { Variaveis.OperacaoEmAndamento.Trajetoria.IniciarRetornoBase(VariaveisOperacao.PosicaoBase); + if (!Variaveis.OperacaoEmAndamento.Iniciado) + { + Variaveis.OperacaoEmAndamento.Iniciado = true; + Variaveis.OperacaoEmAndamento.Simulando = true; + } } private void btnFixarBase_Click(object sender, EventArgs e) diff --git a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapeamentoVisual.cs b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapeamentoVisual.cs index e4390b433..10e71dc97 100644 --- a/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapeamentoVisual.cs +++ b/AgroBase/AgroBase/Forms/Simuladores/frmSimulacaoMapeamentoVisual.cs @@ -14,6 +14,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using static AgroBase.Models.Enums; namespace AgroBase.Forms.Simuladores { @@ -68,7 +69,7 @@ namespace AgroBase.Forms.Simuladores { Task.Run(async () => { - OAKCameraFrameModel frame = await VisualWorkerService.GetCameraFrame(CameraFrameType.Segmentacao); + OAKCameraFrameModel frame = await VisualWorkerService.GetCameraFrame(TipoFrameCamera.Segmentacao); var dadosSeg = Variaveis.OperacaoEmAndamento.Sensoriamento.OperadorVisual.Analises.segmentacao; DesenharCorredor(frame?.image(), dadosSeg.centros_corredor, dadosSeg.width, dadosSeg.height, 80); diff --git a/AgroBase/AgroBase/Forms/frmOperarioSonar.cs b/AgroBase/AgroBase/Forms/frmOperarioSonar.cs index 8d4f24fdb..a3581a13d 100644 --- a/AgroBase/AgroBase/Forms/frmOperarioSonar.cs +++ b/AgroBase/AgroBase/Forms/frmOperarioSonar.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using System.Windows.Forms.DataVisualization.Charting; +using static AgroBase.Models.Enums; namespace AgroBase.Forms { @@ -79,51 +80,51 @@ namespace AgroBase.Forms private async void btnLeituraRGB_Click(object sender, EventArgs e) { - EnviarComandoReqFrame(CameraFrameType.Rgb); + EnviarComandoReqFrame(TipoFrameCamera.Rgb); } private void btnLeituraHeatmap_Click(object sender, EventArgs e) { - EnviarComandoReqFrame(CameraFrameType.Heatmap); + EnviarComandoReqFrame(TipoFrameCamera.Heatmap); } private void btnLeituraRadar2D_Click(object sender, EventArgs e) { - EnviarComandoReqFrame(CameraFrameType.RadarTopDown); + //EnviarComandoReqFrame(TipoFrameCamera.RadarTopDown); } private void btnLeituraSegmentacaoSemantica_Click(object sender, EventArgs e) { - EnviarComandoReqFrame(CameraFrameType.Segmentacao); + EnviarComandoReqFrame(TipoFrameCamera.Segmentacao); } - private async void EnviarComandoReqFrame(CameraFrameType tipo) + private async void EnviarComandoReqFrame(TipoFrameCamera tipo) { OAKCameraFrameModel frame = await VisualWorkerService.GetCameraFrame(tipo); PictureBox pic = - tipo == CameraFrameType.Rgb ? picRGB : - tipo == CameraFrameType.Heatmap ? picHeatmap : - tipo == CameraFrameType.RadarTopDown ? picRadar2D : - tipo == CameraFrameType.Segmentacao ? picSegmentacaoSemantica : + tipo == TipoFrameCamera.Rgb ? picRGB : + tipo == TipoFrameCamera.Heatmap ? picHeatmap : + //tipo == TipoFrameCamera.RadarTopDown ? picRadar2D : + tipo == TipoFrameCamera.Segmentacao ? picSegmentacaoSemantica : new PictureBox(); Label lbl = - tipo == CameraFrameType.Rgb ? lblLeituraRGB : - tipo == CameraFrameType.Heatmap ? lblLeituraHeatmap : - tipo == CameraFrameType.RadarTopDown ? lblLeituraRadar2D : - tipo == CameraFrameType.Segmentacao ? lblLeituraSegmentacaoSemantica : + tipo == TipoFrameCamera.Rgb ? lblLeituraRGB : + tipo == TipoFrameCamera.Heatmap ? lblLeituraHeatmap : + //tipo == TipoFrameCamera.RadarTopDown ? lblLeituraRadar2D : + tipo == TipoFrameCamera.Segmentacao ? lblLeituraSegmentacaoSemantica : new Label(); pic.Image?.Dispose(); try { pic.Image = frame?.image(); } catch { } lbl.Text = $"Leitura em: " + frame?.timestamp.ToString("dd/MM/yyyy HH:mm:ss"); - if (tipo == CameraFrameType.RadarTopDown && VisualWorkerService.DadosLeitura.Analises != null) + /*if (tipo == TipoFrameCamera.RadarTopDown && VisualWorkerService.DadosLeitura.Analises != null) { - //pic.Image = VariaveisOperacao.Operadores.VisualWorker.DadosLeitura.Leitura.obj.radar_2d.PlotarAnalsie(frame.image); + pic.Image = VariaveisOperacao.Operadores.VisualWorker.DadosLeitura.Leitura.obj.radar_2d.PlotarAnalsie(frame.image); - //PlotarGraficoPerfilCorredor(VisualWorkerService.DadosLeitura.Analises.corredor_prof); - } + PlotarGraficoPerfilCorredor(VisualWorkerService.DadosLeitura.Analises.corredor_prof); + }*/ } private void btnReqStatusDispositivo_Click(object sender, EventArgs e) @@ -152,7 +153,7 @@ namespace AgroBase.Forms var analise = VisualWorkerService.DadosLeitura.Analises; lblLeituraDebug.Text = $"Leitura em: " + (analise?.timestamp ?? DateTime.MinValue).ToString("dd/MM/yyyy HH:mm:ss"); - OAKCameraFrameModel frame = VisualWorkerService.DadosLeitura.CameraFrames[CameraFrameType.Heatmap]; + OAKCameraFrameModel frame = VisualWorkerService.DadosLeitura.CameraFrames[TipoFrameCamera.Heatmap]; picDebug.Image?.Dispose(); picDebug.Image = analise.PlotarAnalise(frame); diff --git a/AgroBase/AgroBase/Models/Enums.cs b/AgroBase/AgroBase/Models/Enums.cs index ac19ab07e..1c448aa84 100644 --- a/AgroBase/AgroBase/Models/Enums.cs +++ b/AgroBase/AgroBase/Models/Enums.cs @@ -370,6 +370,7 @@ MatrizCusto = 5, Deteccoes = 6, Corredor = 7, + Raw4 = 8, } } diff --git a/AgroBase/AgroBase/Models/Modules/AtuadorModel.cs b/AgroBase/AgroBase/Models/Modules/AtuadorModel.cs index 2a0193d27..ebf44ae6a 100644 --- a/AgroBase/AgroBase/Models/Modules/AtuadorModel.cs +++ b/AgroBase/AgroBase/Models/Modules/AtuadorModel.cs @@ -260,7 +260,7 @@ namespace AgroBase.Models.Modules _EnderecoCAN_Rx = 0x12, _TaxaAmostragem = 1000, RequisitarDados = true, - // 71 ~ 73 + // 71 ~ 77 BicosPulverizadores = new List(), // 51 ~ 51 BombasPressurizadoras = new List() @@ -649,10 +649,10 @@ namespace AgroBase.Models.Modules } }, }, - // 91 ~ 93 + // 91 ~ 97 Servos = new List() { - new SensorServoModel() + /*new SensorServoModel() { ID = "SRVB1", ID_Num = 91, @@ -744,7 +744,7 @@ namespace AgroBase.Models.Modules analise_health = true }, } - }, + },*/ }, }; for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdBicos; i++) @@ -754,12 +754,12 @@ namespace AgroBase.Models.Modules { ID = "B" + posicao.ToString("00"), ID_Num = 70 + posicao, - Servo_ID_Num = 90 + posicao, + Servo_ID_Num = Atuador.Servos.FirstOrDefault(x => (x.ID_Num - 20) == 70 + posicao)?.ID_Num ?? -1, Componente = S_Code.sBIC, Posicao = posicao, Inicializado = false, AnguloControle = 0, - AnguloAbertura = 110, + AnguloAbertura = 30, Comandar = true, Mandatorio = true, ComandoAtuar = false, diff --git a/AgroBase/AgroBase/Models/Modules/SensoriamentoModel.cs b/AgroBase/AgroBase/Models/Modules/SensoriamentoModel.cs index 4bf933f1c..f059e1113 100644 --- a/AgroBase/AgroBase/Models/Modules/SensoriamentoModel.cs +++ b/AgroBase/AgroBase/Models/Modules/SensoriamentoModel.cs @@ -2055,8 +2055,8 @@ namespace AgroBase.Models.Modules loRaService.Configurado = false; loRaService.ParametrosGet.UltimaLeitura = DateTime.MinValue; loRaService.MensagensRecebidasAvulsas = new List(); - VisualWorkerService.DadosLeitura.CameraFrames = new Dictionary(); - WeedWorkerService.DadosLeitura.CameraFrames = new Dictionary(); + VisualWorkerService.DadosLeitura.CameraFrames = new Dictionary(); + WeedWorkerService.DadosLeitura.CameraFrames = new Dictionary(); ReiniciarLeituras(Dados); } diff --git a/AgroBase/AgroBase/Models/OAKCameraModel.cs b/AgroBase/AgroBase/Models/OAKCameraModel.cs index f7dbfff8f..ddef35f80 100644 --- a/AgroBase/AgroBase/Models/OAKCameraModel.cs +++ b/AgroBase/AgroBase/Models/OAKCameraModel.cs @@ -36,7 +36,7 @@ namespace AgroBase.Models public double DistanciaMinimaVisao { get; set; } = 500; public double PercentualAlturaSolo { get; set; } = 30; - public Dictionary frames + public Dictionary frames { get { @@ -47,13 +47,13 @@ namespace AgroBase.Models case T_Code.Cam: return WeedWorkerService.DadosLeitura.CameraFrames; default: - return new Dictionary(); + return new Dictionary(); } } } - public async Task GetNewFrame(CameraFrameType tipo = CameraFrameType.Rgb) + public async Task GetNewFrame(TipoFrameCamera tipo = TipoFrameCamera.Rgb) { OAKCameraFrameModel frame = null; switch (Dispositivo) diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs index 8905df018..d13609db0 100644 --- a/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs +++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoModel.cs @@ -203,6 +203,7 @@ namespace AgroBase.Models int qtdCamerasSolo, TiposControladorDirecional tipoControleDirecional, bool movimentoAutomatico, + bool direcionalAutomatico, bool pulverizadorAutomatico, bool frenagemAutomatica) { @@ -227,8 +228,9 @@ namespace AgroBase.Models { SonarAtivado = sonarAtivado, MovimentoAutomatico = movimentoAutomatico, + DirecionalAutomatico = direcionalAutomatico, PulverizadorAutomatico = pulverizadorAutomatico, - FrenagemAutomatica = frenagemAutomatica, + FrenagemAutomaticaAoParar = frenagemAutomatica, AtuDuracaoAtuacao = duracaoAtuacao, AtuPercentualInicioPulverizacao = percentualAtuacao, AtuPressaoLinha = pressaoLinha, @@ -364,8 +366,9 @@ namespace AgroBase.Models Controle = new OperacaoParametrosControleModel() { MovimentoAutomatico = false, + DirecionalAutomatico = false, PulverizadorAutomatico = false, - FrenagemAutomatica = true, + FrenagemAutomaticaAoParar = true, MovVelocidadeSErvasPercent = 100, MovVelocidadeCErvasPercent = 15, DirAnguloMaximo = 25, @@ -472,8 +475,9 @@ namespace AgroBase.Models Controle = new OperacaoParametrosControleModel() { MovimentoAutomatico = true, + DirecionalAutomatico = true, PulverizadorAutomatico = true, - FrenagemAutomatica = true, + FrenagemAutomaticaAoParar = true, MovVelocidadeSErvasPercent = 50, MovVelocidadeCErvasPercent = 20, DirAnguloMaximo = 30, @@ -622,8 +626,9 @@ namespace AgroBase.Models Controle = new OperacaoParametrosControleModel() { MovimentoAutomatico = true, + DirecionalAutomatico = true, PulverizadorAutomatico = false, - FrenagemAutomatica = false, + FrenagemAutomaticaAoParar = false, MovVelocidadeSErvasPercent = 50, MovVelocidadeCErvasPercent = 20, DirAnguloMaximo = 30, @@ -753,8 +758,9 @@ namespace AgroBase.Models Controle = new OperacaoParametrosControleModel() { MovimentoAutomatico = true, + DirecionalAutomatico = true, PulverizadorAutomatico = false, - FrenagemAutomatica = true, + FrenagemAutomaticaAoParar = true, MovVelocidadeSErvasPercent = 40, MovVelocidadeCErvasPercent = 20, DirAnguloMaximo = 30, @@ -1258,7 +1264,11 @@ namespace AgroBase.Models var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle; if (pControle.MovimentoAutomatico) { - Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov, T_Code.Dir }); + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov }); + } + if (pControle.DirecionalAutomatico) + { + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Dir }); } if (pControle.PulverizadorAutomatico) { @@ -1282,7 +1292,9 @@ namespace AgroBase.Models continue; if (Ctrl.Tipo == T_Code.Atu && !pControle.PulverizadorAutomatico) continue; - if ((Ctrl.Tipo == T_Code.Mov || Ctrl.Tipo == T_Code.Dir) && !pControle.MovimentoAutomatico) + if (Ctrl.Tipo == T_Code.Mov && !pControle.MovimentoAutomatico) + continue; + if (Ctrl.Tipo == T_Code.Dir && !pControle.DirecionalAutomatico) continue; } @@ -1314,7 +1326,7 @@ namespace AgroBase.Models { case T_Code.Mov: { - if (pControle.FrenagemAutomatica && _Controle.EmFreio) + if (pControle.FrenagemAutomaticaAoParar && _Controle.EmFreio) { _Controle.Direcao = Direcao.EmFreio; } @@ -1645,7 +1657,11 @@ namespace AgroBase.Models if (Variaveis.OperacaoEmAndamento.Pausa) return; if (controleBase.Controle == null) return; - if (Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico && Variaveis.OperacaoEmAndamento.Iniciado) return; + + var cmdRover = GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.botaoJoy == controleBase.Tecla); + + if (cmdRover?.Dispositivo == T_Code.Mov && Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico && Variaveis.OperacaoEmAndamento.Iniciado) return; + if (cmdRover?.Dispositivo == T_Code.Dir && Variaveis.OperacaoEmAndamento.Parametros.Controle.DirecionalAutomatico && Variaveis.OperacaoEmAndamento.Iniciado) return; var _Controle = Variaveis.OperacaoEmAndamento.Controle; if (controleBase.Controle.PercentualVelocidadeSP != null) _Controle.PercentualVelocidadeSP = (double)controleBase.Controle.PercentualVelocidadeSP; @@ -1653,7 +1669,7 @@ namespace AgroBase.Models if (controleBase.Controle.TipoMovimentoDirecional != null) _Controle.TipoMovimento = (TipoMovimentoDirecional)controleBase.Controle.TipoMovimentoDirecional; if (controleBase.Controle.EmFreio != null) _Controle.EmFreio = (bool)controleBase.Controle.EmFreio; - Keys tecla = GeneralJoystick.DeParaComandos.FirstOrDefault(x => x.botaoJoy == controleBase.Tecla)?.key ?? Keys.Escape; + Keys tecla = cmdRover?.key ?? Keys.Escape; GeneralJoystick.EnviaComandoMotor(tecla, controleBase.Dispositivo, ForcarComando: true, ID: controleBase._comp_id); } @@ -1881,7 +1897,7 @@ namespace AgroBase.Models string nome = Variaveis.OperacaoEmAndamento.idxLog.ToString(); - Camera.SaveFrames(new List() { TipoFrameCamera.Rgb, TipoFrameCamera.Segmentacao }, nome, Caminho); + Camera.SaveFrames(new List() { TipoFrameCamera.Rgb, TipoFrameCamera.Segmentacao }, nome, Caminho); // TipoFrameCamera.Raw4 var cameras_conectadas = JsonConvert.DeserializeObject>(RedisService.Get(CtxKey.DadosCameras)); bool conectada = cameras_conectadas.ContainsKey(Camera?.Id ?? ""); @@ -2136,17 +2152,8 @@ namespace AgroBase.Models public void Reiniciar() { var _Parametros = Variaveis.OperacaoEmAndamento.Parametros.Controle; - if (_Parametros.MovimentoAutomatico) - { - Angulo = 0; - PercentualVelocidadeSP = 0; - } - else - { - Angulo = _Parametros.DirAnguloMaximo; - PercentualVelocidadeSP = _Parametros.MovVelocidadeCErvasPercent; - } - + PercentualVelocidadeSP = _Parametros.MovimentoAutomatico ? 0 : _Parametros.MovVelocidadeCErvasPercent; + Angulo = _Parametros.DirecionalAutomatico ? 0 : _Parametros.DirAnguloMaximo; EmFreio = false; Direcao = Direcao.Parado; TipoMovimento = TipoMovimentoDirecional.RodasDianteiras; @@ -2567,10 +2574,10 @@ namespace AgroBase.Models { var vw = OperadorVisual?.Clone(); if (vw != null) - vw.CameraFrames = new Dictionary(); + vw.CameraFrames = new Dictionary(); var ww = OperadorErvas?.Clone(); if (ww != null) - ww.CameraFrames = new Dictionary(); + ww.CameraFrames = new Dictionary(); return new OperacaoSensoriamentoLogModel() { diff --git a/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs b/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs index 204fa32e2..bbf9780c7 100644 --- a/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs +++ b/AgroBase/AgroBase/Models/Operacoes/OperacaoParametrosModel.cs @@ -31,10 +31,13 @@ namespace AgroBase.Models.Operacoes public class OperacaoParametrosControleModel { - public bool SonarAtivado { get; set; } public bool MovimentoAutomatico { get; set; } + public bool DirecionalAutomatico { get; set; } public bool PulverizadorAutomatico { get; set; } - public bool FrenagemAutomatica { get; set; } + public bool SonarAtivado { get; set; } + public bool OakParadaPorObstaculo { get; set; } + public bool ImuParadaPorInclinacao { get; set; } + public bool FrenagemAutomaticaAoParar { get; set; } public int MovVelocidadeSErvasPercent { get; set; } public int MovRpmMax diff --git a/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs b/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs index 6c91d3fcf..373a50d39 100644 --- a/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs +++ b/AgroBase/AgroBase/Models/Operadores/CameraWorkerModel.cs @@ -59,13 +59,5 @@ namespace AgroBase.Models.Operadores ScriptCarregado = 1, } - public enum CameraFrameType - { - Rgb = 1, - Heatmap = 2, - RadarTopDown = 3, - Segmentacao = 4, - Debug = 5 - } } diff --git a/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs b/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs index bcd54860e..83751d61e 100644 --- a/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs +++ b/AgroBase/AgroBase/Models/Operadores/VisualWorkerModel.cs @@ -13,7 +13,7 @@ namespace AgroBase.Models.Operadores public bool Pronto { get; set; } public DateTime ProntoEm { get; set; } public DateTime UltimaMensagem { get; set; } - public Dictionary CameraFrames { get; set; } = new Dictionary(); + public Dictionary CameraFrames { get; set; } = new Dictionary(); public VisualWorkerMessageAnaliseModel Analises { get; set; } = new VisualWorkerMessageAnaliseModel(); public VisualWorkerMessageIMUModel Imu { get; set; } = new VisualWorkerMessageIMUModel(); public StatusModulo Status { get; set; } @@ -27,7 +27,7 @@ namespace AgroBase.Models.Operadores IniciadoEm = IniciadoEm, Pronto = Pronto, ProntoEm = ProntoEm, - CameraFrames = new Dictionary(CameraFrames ?? new Dictionary()), + CameraFrames = new Dictionary(CameraFrames ?? new Dictionary()), Analises = Analises?.Clone(), Imu = Imu?.Clone(), UltimaMensagem = UltimaMensagem, @@ -42,7 +42,7 @@ namespace AgroBase.Models.Operadores IniciadoEm = DateTime.MinValue; Pronto = false; ProntoEm = DateTime.MinValue; - CameraFrames = new Dictionary(); + CameraFrames = new Dictionary(); Analises = new VisualWorkerMessageAnaliseModel(); Imu = new VisualWorkerMessageIMUModel(); Resumo = new VisualWorkerResumoModel(); diff --git a/AgroBase/AgroBase/Models/Operadores/WeedWorkerModel.cs b/AgroBase/AgroBase/Models/Operadores/WeedWorkerModel.cs index d414e315b..f6e267510 100644 --- a/AgroBase/AgroBase/Models/Operadores/WeedWorkerModel.cs +++ b/AgroBase/AgroBase/Models/Operadores/WeedWorkerModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using static AgroBase.Models.Enums; namespace AgroBase.Models.Operadores { @@ -10,7 +11,7 @@ namespace AgroBase.Models.Operadores public bool Pronto { get; set; } public DateTime ProntoEm { get; set; } public DateTime UltimaMensagem { get; set; } - public Dictionary CameraFrames { get; set; } = new Dictionary(); + public Dictionary CameraFrames { get; set; } = new Dictionary(); public WeedWorkerAnaliseModel Analise { get; set; } = new WeedWorkerAnaliseModel(); @@ -22,7 +23,7 @@ namespace AgroBase.Models.Operadores IniciadoEm = IniciadoEm, Pronto = Pronto, ProntoEm = ProntoEm, - CameraFrames = new Dictionary(CameraFrames ?? new Dictionary()), + CameraFrames = new Dictionary(CameraFrames ?? new Dictionary()), Analise = Analise.Clone(), UltimaMensagem = UltimaMensagem, }; @@ -34,7 +35,7 @@ namespace AgroBase.Models.Operadores IniciadoEm = DateTime.MinValue; Pronto = false; ProntoEm = DateTime.MinValue; - CameraFrames = new Dictionary(); + CameraFrames = new Dictionary(); } } diff --git a/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs b/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs index f9a90ef4a..ad4ed3ed0 100644 --- a/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs +++ b/AgroBase/AgroBase/Models/TrajetoriaMapaOperacaoModel.cs @@ -6,6 +6,7 @@ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Linq; +using static AgroBase.Models.CorredorTrajetoriaModel; using static AgroBase.Models.Enums; namespace AgroBase.Models @@ -683,7 +684,7 @@ namespace AgroBase.Models DefinirProximoPonto(); if (PontoAtual == null) goto Inicio; - if (VerificaInicioOperacaoMeioRua()) goto Inicio; + if (VerificaInicioOperacaoMeioRua(true)) goto Inicio; MarcarPontosIntermediariosNaoVisitados(); DefinirPontoMaisProximo(); @@ -724,41 +725,42 @@ namespace AgroBase.Models return melhoresPontosCorredores.Any(x => x.Value.Item1) ? melhoresPontosCorredores.Where(x => x.Value.Item1).OrderBy(x => x.Value.Item2).FirstOrDefault().Key : -1; } - private (bool, int) VerificaEquipamentoDentroCorredor() + private (bool, int) VerificaEquipamentoDentroCorredorMontado(GPSModel posicaoAtual) { - _TrajetoriaJanela = _TrajetoriaFixa; - AtualizarPropriedadesPontosTrajetoria(); - AtualizarTrajetoriaJanela(); + if (Corredores == null) + return (false, -1); + List melhoresPontosCorredores = new List(); foreach (var corredor in Corredores) { - (GPSModel pontoMaisProximo, double distanciaAtual) = GPSUtils.CalcularPontoMaisProximoTrajetoria(_TrajetoriaFixa[0].Posicao, corredor); - if (pontoMaisProximo == null) - { - return (false, -1); - } + (GPSModel pontoMaisProximo, double distanciaAtual) = GPSUtils.CalcularPontoMaisProximoTrajetoria(posicaoAtual, corredor); + if (pontoMaisProximo == null) continue; - var melhorPonto = _TrajetoriaFixa.FirstOrDefault(x => x.Posicao.Latitude == pontoMaisProximo.Latitude && x.Posicao.Longitude == pontoMaisProximo.Longitude); + var melhorPonto = _Corredores[Corredores.IndexOf(corredor)].Pontos.FirstOrDefault(x => x.Posicao.Latitude == pontoMaisProximo.Latitude && x.Posicao.Longitude == pontoMaisProximo.Longitude); + melhorPonto.AtualizarPropriedades(); melhoresPontosCorredores.Add(melhorPonto); } - bool pontoNaMargem = melhoresPontosCorredores.Any(x => x.NaMargem); - int idxPonto = !pontoNaMargem ? 0 : melhoresPontosCorredores.Where(x => x.NaMargem).OrderBy(x => x.DistanciaAtual).FirstOrDefault().idxPonto; + var ponto = melhoresPontosCorredores.Where(x => x.NaMargem).OrderBy(x => x.DistanciaAtual).FirstOrDefault(); + bool pontoNaMargem = ponto != null; + int idxPonto = !pontoNaMargem ? -1 : ponto.idxPonto; return (pontoNaMargem, idxPonto); } - private bool VerificaInicioOperacaoMeioRua() + private bool VerificaInicioOperacaoMeioRua(bool considerarStatus) { - if (!VerificacaoInicialMeioRuaConcluida && new List() { StatusOperacao.Aguardando, StatusOperacao.EmAndamento }.Contains(Variaveis.OperacaoEmAndamento.StatusAtual)) + if (!VerificacaoInicialMeioRuaConcluida && ((considerarStatus && new List() { StatusOperacao.Aguardando, StatusOperacao.EmAndamento }.Contains(Variaveis.OperacaoEmAndamento.StatusAtual)) || !considerarStatus)) { VerificacaoInicialMeioRuaConcluida = true; - (bool noCoredor, var idxPontoMaisProximo) = VerificaEquipamentoDentroCorredor(); + (bool noCoredor, var idxPontoMaisProximo) = VerificaEquipamentoDentroCorredorMontado(_TrajetoriaFixa[0].Posicao); if (noCoredor) { - for (int i = 0; i < idxPontoMaisProximo; i++) + for (int i = 0; i <= idxPontoMaisProximo; i++) { _TrajetoriaFixa[i].Visitado = true; } + CorredorAtual.AtualizarDados(); + return true; } } @@ -771,106 +773,177 @@ namespace AgroBase.Models { if (CorredorAtual == null) return; - bool abrirCurva = true; + bool modoSimulador = false && Variaveis.OperacaoEmAndamento.Simulando; + + // Limiar de "margem" para considerar proximidade do fim double limiarDistanciaMargem = DistanciaErroMapaPlantacao > -1 ? DistanciaErroMapaPlantacao : 5.0; + double distanciaCorredor = CorredorAtual.DistanciaTotal; double distanciaRestanteCorredor = CorredorAtual.DistanciaRestante; double distanciaUltimoPontoCorredor = GPSUtils.DistanciaEntrePontos(Variaveis.OperacaoEmAndamento.Sensoriamento.Gps, CorredorAtual.Pontos.LastOrDefault().Posicao); - var OpVisual = Variaveis.OperacaoEmAndamento.Sensoriamento?.OperadorVisual ?? new VisualWorkerModel(); - StatusModulo OpVisualStatus = Variaveis.OperacaoEmAndamento.Sensoriamento.ModulosSaude.FirstOrDefault(x => x.modulo == T_Code.Snr)?.status ?? StatusModulo.Desconectado; - var DadosSegmentacao = OpVisual.Analises?.segmentacao ?? new VisualWorkerMessageSegmentacaoSemanticaModel(); - if (OpVisualStatus == StatusModulo.Operante || Variaveis.OperacaoEmAndamento.Simulando) //OpVisual.Iniciado && + var opVisual = Variaveis.OperacaoEmAndamento.Sensoriamento?.OperadorVisual ?? new VisualWorkerModel(); + StatusModulo opVisualStatus = Variaveis.OperacaoEmAndamento.Sensoriamento.ModulosSaude.FirstOrDefault(x => x.modulo == T_Code.Snr)?.status ?? StatusModulo.Desconectado; + var dadosSegmentacao = opVisual.Analises?.segmentacao ?? new VisualWorkerMessageSegmentacaoSemanticaModel(); + + // Se não tem visual operante, não está no modoSimulador ou o corredor eh curto demais, não faz nada + if (!(opVisualStatus == StatusModulo.Operante || modoSimulador || distanciaCorredor <= limiarDistanciaMargem)) + return; + + // Garante estrutura de dados visuais do corredor + var dv = CorredorAtual.DadosVisuais ?? (CorredorAtual.DadosVisuais = new DadosVisuaisCorredor()); + + StatusCarroMapa statusAtual = dadosSegmentacao.status_corredor; + StatusCarroMapa statusAnterior = dadosSegmentacao.status_corredor_anterior; + var agora = DateTime.Now; + + // 1) Atualiza tempo e distância por status (usando o status anterior) + if (dv.UltimoUpdate > DateTime.MinValue) { - // Contagem de tempo por status em segundos - if (CorredorAtual.TempoPorStatus == null) CorredorAtual.TempoPorStatus = new Dictionary(); - StatusCarroMapa statusCarro = DadosSegmentacao.status_corredor; - StatusCarroMapa statusCarroAnt = DadosSegmentacao.status_corredor_anterior; - if (!CorredorAtual.TempoPorStatus.TryGetValue(statusCarro, out var status)) - { - CorredorAtual.TempoPorStatus.Add(statusCarro, 0); - } - if (CorredorAtual.UltimoTempoStatus > DateTime.MinValue) - { - CorredorAtual.TempoPorStatus[statusCarro] += (DateTime.Now - CorredorAtual.UltimoTempoStatus).TotalSeconds; - } - CorredorAtual.UltimoTempoStatus = DateTime.Now; - double TempoTotalContagem = CorredorAtual.TempoPorStatus.Sum(x => x.Value); - double TempoMovimento = CorredorAtual.TempoPorStatus.Where(x => x.Key != StatusCarroMapa.Parado).Sum(x => x.Value); - CorredorAtual.TempoPorStatus.TryGetValue(StatusCarroMapa.CaminhandoRua, out double TempoCaminhandoRua); - CorredorAtual.TempoPorStatus.TryGetValue(StatusCarroMapa.EntrandoRua, out double TempoEntrandoRua); - CorredorAtual.TempoPorStatus.TryGetValue(StatusCarroMapa.SaindoRua, out double TempoSaindoRua); - CorredorAtual.TempoPorStatus.TryGetValue(StatusCarroMapa.Direcionando, out double TempoDirecionando); - double TempoDentroRua = TempoEntrandoRua + TempoCaminhandoRua + TempoSaindoRua; - double PercentualTempoComCana = TempoMovimento == 0 ? 0 : TempoDentroRua / TempoMovimento; - double PercentualTempoSemCana = TempoMovimento == 0 ? 0 : TempoDirecionando / TempoMovimento; - double ts_agora = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000.0; + double dt = (agora - dv.UltimoUpdate).TotalSeconds; + if (dt < 0) dt = 0; - if ( - ( - (Variaveis.OperacaoEmAndamento.Simulando || - (ts_agora - DadosSegmentacao.timestamp < 2.0 && PercentualTempoComCana > 0.4)) // Esteve a pelo menos 40% do tempo em movimento com presenca de cana e o dado esta atualizado - ) - && distanciaCorredor >= limiarDistanciaMargem - && distanciaRestanteCorredor < limiarDistanciaMargem // Esta a pelo menos x metros do final do corredor - && distanciaUltimoPontoCorredor < limiarDistanciaMargem // Esta a pelo menos x metros do ultimo ponto do corredor - && statusCarro == StatusCarroMapa.Direcionando // Carro esta fora do corredor - //&& statusCarroAnt != statusCarro - ) + // Aproximação da distância percorrida nesse intervalo pelo mapa + double deltaDist = 0; + if (dv.DistanciaRestanteAnterior >= 0) { - double anguloControle = Variaveis.OperacaoEmAndamento.Controle.Angulo; - if (abrirCurva && !CorredorAtual.Ultimo) + deltaDist = dv.DistanciaRestanteAnterior - distanciaRestanteCorredor; + if (deltaDist < 0) deltaDist = 0; // proteção contra ruído + } + + bool emMovimento = statusAnterior != StatusCarroMapa.Parado; + + if (emMovimento) + { + switch (statusAnterior) { - anguloControle = CorredorAtual.idxRuaDireita > CorredorAtual.idxRuaEsquerda ? -Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo : Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo; + case StatusCarroMapa.CaminhandoRua: + case StatusCarroMapa.EntrandoRua: + case StatusCarroMapa.SaindoRua: + dv.TempoDentroRuaTotal += dt; + dv.DistanciaDentroRuaTotal += deltaDist; + dv.TempoForaRuaContinuo = 0; + dv.DistanciaForaRuaContinuo = 0; + break; + + case StatusCarroMapa.Direcionando: + dv.TempoForaRuaTotal += dt; + dv.DistanciaForaRuaTotal += deltaDist; + dv.TempoForaRuaContinuo += dt; + dv.DistanciaForaRuaContinuo += deltaDist; + break; + + default: + // Outros estados quebram a continuidade "fora do corredor" + dv.TempoForaRuaContinuo = 0; + dv.DistanciaForaRuaContinuo = 0; + break; + } + } + else + { + // Parado: não acumula movimento, mas quebra janela contínua + dv.TempoForaRuaContinuo = 0; + dv.DistanciaForaRuaContinuo = 0; + } + } + + dv.UltimoUpdate = agora; + dv.DistanciaRestanteAnterior = distanciaRestanteCorredor; + + // 2) Confirmar se este corredor realmente existiu (teve cana) + const double MIN_DIST_CORREDOR_CONFIRMADO = 5.0; // metros dentro da rua + const double MIN_TEMPO_CORREDOR_CONFIRMADO = 10.0; // segundos dentro da rua + + if (!dv.CorredorConfirmado) + { + if (dv.DistanciaDentroRuaTotal >= MIN_DIST_CORREDOR_CONFIRMADO || dv.TempoDentroRuaTotal >= MIN_TEMPO_CORREDOR_CONFIRMADO) + { + dv.CorredorConfirmado = true; + } + } + + // 3) Critérios para considerar que chegou ao fim do corredor antes do mapa acabar + + double tsAgora = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() / 1000.0; + bool dadoFresco = (tsAgora - dadosSegmentacao.timestamp) < 2.0; + + bool pertoDoFim = distanciaRestanteCorredor < limiarDistanciaMargem && distanciaUltimoPontoCorredor < limiarDistanciaMargem; + + bool foraDoCorredorAgora = (statusAtual == StatusCarroMapa.Direcionando); + + // Limiar de "quanto tempo/distância já estou fora do corredor" para evitar buracos pontuais + const double MIN_TEMPO_FORA_CORREDOR = 2.0; // segundos + const double MIN_DIST_FORA_CORREDOR = 1.0; // metros + + bool foraContinuoSuficiente = dv.TempoForaRuaContinuo >= MIN_TEMPO_FORA_CORREDOR || dv.DistanciaForaRuaContinuo >= MIN_DIST_FORA_CORREDOR; + + bool podeUsarSegmentacao = modoSimulador || (dadoFresco && dv.CorredorConfirmado); + + bool abrirCurva = false; // mantém seu flag por enquanto + + if (podeUsarSegmentacao && pertoDoFim && foraDoCorredorAgora && foraContinuoSuficiente) + { + // 4) Aqui consideramos que o corredor acabou antes do fim do mapa + double anguloControle = Variaveis.OperacaoEmAndamento.Controle.Angulo; + + if (abrirCurva && !CorredorAtual.Ultimo) + { + anguloControle = CorredorAtual.idxRuaDireita > CorredorAtual.idxRuaEsquerda + ? -Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo + : Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAnguloMaximo; + } + + int pontosMarcar = 0; + foreach (var ponto in CorredorAtual.Pontos.Where(x => !x.Visitado)) + { + ponto.Visitado = true; + pontosMarcar++; + } + + if (!CorredorAtual.Ultimo) + { + // Marca ponto de ligação de entrada do próximo corredor como visitado + _TrajetoriaFixa[CorredorAtual.Pontos[CorredorAtual.QtdPontos - 1].idxPonto + 1].Visitado = true; + + // Avança bem a janela para "pular" o restinho do corredor + AtualizarIndicesJanela((pontosMarcar + 2) * 2); + AtualizarTrajetoriaJanela(); + DefinirPontoAtual(); + AtualizarCorredorAtual(); + + // Garante que os primeiros pontos do corredor atual estão como visitados + for (int i = 0; i < pontosMarcar && i < CorredorAtual.Pontos.Count; i++) + { + CorredorAtual.Pontos[i].Visitado = true; } - int pontosMarcar = 0; - foreach (var Ponto in CorredorAtual.Pontos.Where(x => !x.Visitado)) + AtualizarIndicesJanela(); + AtualizarTrajetoriaJanela(); + DefinirPontoAtual(); + DefinirProximoPonto(); + + if (abrirCurva) { - Ponto.Visitado = true; - pontosMarcar++; - } - if (!CorredorAtual.Ultimo) - { - _TrajetoriaFixa[CorredorAtual.Pontos[CorredorAtual.QtdPontos - 1].idxPonto + 1].Visitado = true; // Marca ponto de ligacao de entrada do proximo corredor como visitado - AtualizarIndicesJanela((pontosMarcar + 2) * 2); - AtualizarTrajetoriaJanela(); - DefinirPontoAtual(); - AtualizarCorredorAtual(); - for (int i = 0; i < pontosMarcar; i++) + var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle; + + if (pControle.MovimentoAutomatico) { - CorredorAtual.Pontos[i].Visitado = true; + Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP = Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent; + Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == T_Code.Mov).DelayEnvioComandoExtra = 2000; + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov }); } - AtualizarIndicesJanela(); - AtualizarTrajetoriaJanela(); - DefinirPontoAtual(); - DefinirProximoPonto(); - - if (abrirCurva) + if (pControle.DirecionalAutomatico) { Console.WriteLine($"Angulo de controle definido de {Variaveis.OperacaoEmAndamento.Controle.Angulo} para {anguloControle}"); Variaveis.OperacaoEmAndamento.Controle.Angulo = anguloControle; - Variaveis.OperacaoEmAndamento.Controle.PercentualVelocidadeSP = Variaveis.OperacaoEmAndamento.Parametros.Controle.MovVelocidadeCErvasPercent; Variaveis.OperacaoEmAndamento.Controle.TipoMovimento = TipoMovimentoDirecional.MovimentoArco; Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == T_Code.Dir).DelayEnvioComandoExtra = 1500; - Variaveis.OperacaoEmAndamento.Controle.TiposControle.FirstOrDefault(x => x.Tipo == T_Code.Mov).DelayEnvioComandoExtra = 2000; - - var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle; - if (pControle.MovimentoAutomatico) - { - Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov, T_Code.Dir }); - } + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Dir }); } } } - - RedisService.AtualizarCampos( - CtxKey.DadosVisualWorker, - ("segmentacao.status_corredor_anterior", (int)statusCarro) - ); - if (VisualWorkerService.DadosLeitura.Analises.segmentacao != null) - VisualWorkerService.DadosLeitura.Analises.segmentacao.status_corredor_anterior = statusCarro; } } @@ -946,20 +1019,26 @@ namespace AgroBase.Models bool mangerDestravou = novoComando != null && (_Controle.ticks_sem_resposta.AddMilliseconds(min_ticks_sem_resposta) < agora && novoComando.heartbeat != _Controle.heartbeat); if (novoComando != null && (comandoMudou || mangerDestravou)) { - _Controle.Angulo = novoComando.angulo; - _Controle.TipoMovimento = novoComando.tipo_movimento; - _Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade; - _Controle.EmFreio = novoComando.em_freio; - _Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List(); - _Controle.Latencia = novoComando.latencia; - _Controle.ErroLateral = novoComando.erro_lateral; - _Controle.DebugCustoMpc = novoComando.debug_custo; - var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle; + if (pControle.MovimentoAutomatico) { - Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov, T_Code.Dir }); + _Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade; + _Controle.EmFreio = novoComando.em_freio; + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov }); } + + if (pControle.DirecionalAutomatico) + { + _Controle.Angulo = novoComando.angulo; + _Controle.TipoMovimento = novoComando.tipo_movimento; + _Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List(); + _Controle.Latencia = novoComando.latencia; + _Controle.ErroLateral = novoComando.erro_lateral; + _Controle.DebugCustoMpc = novoComando.debug_custo; + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Dir }); + } + } if (novoComando != null && novoComando.heartbeat == _Controle.heartbeat) @@ -1718,6 +1797,9 @@ namespace AgroBase.Models GPSModel posicaoAtual = Variaveis.OperacaoEmAndamento.Sensoriamento.Gps; + VerificaInicioOperacaoMeioRua(false); + AtualizarDadosTrajetoria(); + // ========================= // REGRA 0 – Está dentro de corredor? // ========================= @@ -2251,8 +2333,7 @@ namespace AgroBase.Models public int idxRuaEsquerda { get; set; } public int idxRuaDireita { get; set; } public double FatorLarguraCorredor { get; set; } - public DateTime UltimoTempoStatus { get; set; } = DateTime.MinValue; - public Dictionary TempoPorStatus { get; set; } + public DadosVisuaisCorredor DadosVisuais { get; set; } = new DadosVisuaisCorredor(); public void AtualizarDados() { @@ -2302,8 +2383,7 @@ namespace AgroBase.Models Pontos = new List(), Ultimo = Ultimo, FatorLarguraCorredor = FatorLarguraCorredor, - UltimoTempoStatus = UltimoTempoStatus, - TempoPorStatus = new Dictionary(TempoPorStatus ?? new Dictionary()) + DadosVisuais = DadosVisuais }; if (clonarPontos) { @@ -2312,6 +2392,30 @@ namespace AgroBase.Models return obj; } + + + public class DadosVisuaisCorredor + { + // Quanto já andou DENTRO do corredor (EntrandoRua, CaminhandoRua, SaindoRua) + public double TempoDentroRuaTotal { get; set; } = 0; + public double DistanciaDentroRuaTotal { get; set; } = 0; + + // Quanto já andou FORA do corredor (Direcionando) + public double TempoForaRuaTotal { get; set; } = 0; + public double DistanciaForaRuaTotal { get; set; } = 0; + + // Janela contínua atual fora do corredor (protege contra buracos curtos) + public double TempoForaRuaContinuo { get; set; } = 0; + public double DistanciaForaRuaContinuo { get; set; } = 0; + + // Para acumular tempo/distância por intervalo entre chamadas + public DateTime UltimoUpdate { get; set; } = DateTime.MinValue; + public double DistanciaRestanteAnterior { get; set; } = -1; + + // Flag: este corredor realmente existiu (teve cana por X tempo/distância) + public bool CorredorConfirmado { get; set; } = false; + } + } public class PontoTrajetoriaModel @@ -2378,7 +2482,7 @@ namespace AgroBase.Models // Define o limite de distância para considerar o ponto como visitado double fatorAjuste = Tipo == TipoPontoRua.CruvaEntreCorredores ? 3.0 : 2.0; // Curvas podem ter menos tolerância - double limiteDistancia = Math.Ceiling(TrajetoriaMapaOperacaoModel.DistanciaMaximaEntreLeituras / distanciaEntrePontos) * fatorAjuste * distanciaEntrePontos; + double limiteDistancia = Math.Max(0.1, Math.Ceiling(TrajetoriaMapaOperacaoModel.DistanciaMaximaEntreLeituras / distanciaEntrePontos) * fatorAjuste * distanciaEntrePontos); // Se o ponto está dentro da margem e dentro do limite de distância, marca como visitado if (NaMargem && DistanciaTrajeto <= limiteDistancia) diff --git a/AgroBase/AgroBase/Models/Variaveis.cs b/AgroBase/AgroBase/Models/Variaveis.cs index 36732ad4e..543606b46 100644 --- a/AgroBase/AgroBase/Models/Variaveis.cs +++ b/AgroBase/AgroBase/Models/Variaveis.cs @@ -229,7 +229,7 @@ namespace AgroBase.Models public static double PercentualReservatorioMinCritio { get; set; } = 5.0; public static double PercentualToleranciaPressaoLinha { get; set; } = 0.15; public static int QuantidadeCamerasSolo { get; set; } = 1; - public static int QuantidadeBicosPulverizadores { get; set; } = 3; + public static int QuantidadeBicosPulverizadores { get; set; } = 7; public static double AlturaBarraPulverizadoraCm { get; set; } = 80; public static double ComprimentoBarraPulverizadoraCm { get; set; } = 103.7; public static double DistanciaEntreBicosCm { get; set; } = 50; diff --git a/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs index 5f4f841ce..142a42002 100644 --- a/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/CameraWorkerService.cs @@ -106,6 +106,7 @@ namespace AgroBase.Services.Operadores { var camera_str = RedisService.Get(RedisService.CamKey(cam.Key)); var camera = JsonConvert.DeserializeObject(camera_str); + if (camera.mx_id == null) continue; CamerasConectadas.Add(new OAKCameraModel() { Dispositivo = camera.dispositivo, diff --git a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs index eee12769d..e8d0deba9 100644 --- a/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/HealthWorkerService.cs @@ -177,6 +177,7 @@ namespace AgroBase.Services.Operadores ("serial_number", VariaveisEquipamento.Parametros.serial_number), ("largura", VariaveisEquipamento.LarguraEquipamentoMm / 1000.0), ("distancia_entre_eixos", VariaveisEquipamento.DistanciaEntreEixos / 100.0), + ("qtd_bicos", VariaveisEquipamento.QuantidadeBicosPulverizadores), ("percentual_reservatorio_min", VariaveisEquipamento.PercentualReservatorioMin), ("percentual_tensao_bateria_min", VariaveisEquipamento.PercentualTensaoBateriaMin), ("camera_caminho_id", Variaveis.OperacaoEmAndamento.DispSen?.Dados?.CameraCaminho?.Id ?? ""), @@ -242,7 +243,10 @@ namespace AgroBase.Services.Operadores distanciaMargem = p.LarguraCorredor * 0.8 }) .ToList(), - horizonte = 2.5, + horizonte = 2.0, + horizonte_min = 1.2, + horizonte_max = 2.8, + horizonte_parado = 1.2, angulo_max_graus = pControle.DirAnguloMaximo, velocidade_min = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeCErvasPercent), velocidade_max = FuncoesMatematicas.CalculaVelocidadeMsPercentual(pControle.MovVelocidadeSErvasPercent), @@ -291,8 +295,10 @@ namespace AgroBase.Services.Operadores CtxKey.DadosControle, ("pulverizador_automatico", pControle.PulverizadorAutomatico), ("movimento_automatico", pControle.MovimentoAutomatico), - ("frenagem_automatica", pControle.FrenagemAutomatica), - ("sonar_ativado", pControle.SonarAtivado) + ("direcional_automatico", pControle.DirecionalAutomatico), + ("frenagem_automatica", pControle.FrenagemAutomaticaAoParar), + ("oak_parada_por_bloqueio", pControle.OakParadaPorObstaculo), + ("imu_parada_por_inclinacao", pControle.ImuParadaPorInclinacao) ); } diff --git a/AgroBase/AgroBase/Services/Operadores/ManagerWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/ManagerWorkerService.cs index 80332ef35..19ee13a1a 100644 --- a/AgroBase/AgroBase/Services/Operadores/ManagerWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/ManagerWorkerService.cs @@ -79,16 +79,20 @@ namespace AgroBase.Services.Operadores bool comandoMudou = (_Controle.Angulo != novoComando.angulo || _Controle.PercentualVelocidadeSP != novoComando.percentual_velocidade || _Controle.TipoMovimento != novoComando.tipo_movimento || _Controle.EmFreio != novoComando.em_freio); if (novoComando != null && comandoMudou) { - _Controle.Angulo = novoComando.angulo; - _Controle.TipoMovimento = novoComando.tipo_movimento; - _Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade; - _Controle.EmFreio = novoComando.em_freio; - _Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List(); - var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle; if (pControle.MovimentoAutomatico) { - Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov, T_Code.Dir }); + _Controle.PercentualVelocidadeSP = novoComando.percentual_velocidade; + _Controle.EmFreio = novoComando.em_freio; + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Mov }); + } + + if (pControle.DirecionalAutomatico) + { + _Controle.Angulo = novoComando.angulo; + _Controle.TipoMovimento = novoComando.tipo_movimento; + _Controle.SimulacaoMPC = novoComando.simulacao?.Select(x => new MPCSimulacaoModel() { latitude = x[0], longitude = x[1], orientacao = x[2] }).ToList() ?? new List(); + Variaveis.OperacaoEmAndamento.AtualizarDadosControle(false, new List() { T_Code.Dir }); } } } @@ -110,7 +114,7 @@ namespace AgroBase.Services.Operadores break; case ManagerWorkerCommandType.EnviarDadosControle: - if (Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico) + if (Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico || Variaveis.OperacaoEmAndamento.Parametros.Controle.DirecionalAutomatico) { AtualizarControle(comando.@params); } diff --git a/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs b/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs index dfbdfe585..3552f100f 100644 --- a/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs +++ b/AgroBase/AgroBase/Services/Operadores/OperadoresService.cs @@ -79,7 +79,7 @@ namespace AgroBase.Services.Operadores if (!Conectado) { TempoDesconectado++; - if (Variaveis.OperacaoEmAndamento.Iniciado && Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico) + if (Variaveis.OperacaoEmAndamento.Iniciado && (Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico || Variaveis.OperacaoEmAndamento.Parametros.Controle.DirecionalAutomatico)) { RedisService.AtualizarCampos( CtxKey.DadosOperacao, @@ -89,9 +89,24 @@ namespace AgroBase.Services.Operadores ); var _Controle = Variaveis.OperacaoEmAndamento.Controle; + if (Variaveis.OperacaoEmAndamento.Parametros.Controle.MovimentoAutomatico) + { + _Controle.PercentualVelocidadeSP = 0; + RedisService.AtualizarCampos( + CtxKey.DadosControle, + ("velocidade_sp", _Controle.PercentualVelocidadeSP) + ); + } + + if (Variaveis.OperacaoEmAndamento.Parametros.Controle.DirecionalAutomatico) + { + _Controle.Angulo = 0; + RedisService.AtualizarCampos( + CtxKey.DadosControle, + ("angulo_sp", _Controle.Angulo) + ); + } - _Controle.Angulo = 0; - _Controle.PercentualVelocidadeSP = 0; _Controle.Bicos.ForEach(x => x.ComandoAtuar = false); RedisService.AtualizarCampos( CtxKey.DadosControle, diff --git a/AgroBase/AgroBase/Services/Operadores/VisualWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/VisualWorkerService.cs index 971e95123..e50d7991e 100644 --- a/AgroBase/AgroBase/Services/Operadores/VisualWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/VisualWorkerService.cs @@ -68,7 +68,7 @@ namespace AgroBase.Services.Operadores break; case VisualWorkerCommandType.GetCameraFrame: - CameraFrameType tipo = (CameraFrameType)Convert.ToInt32(comando.@params["tipo"].ToString()); + TipoFrameCamera tipo = (TipoFrameCamera)Convert.ToInt32(comando.@params["tipo"].ToString()); DadosLeitura.CameraFrames[tipo] = new OAKCameraFrameModel() { frame = comando.@params["frame"].ToString(), @@ -106,7 +106,7 @@ namespace AgroBase.Services.Operadores RedisService.Publish(CmdKey.VisualWorkerRx, JsonConvert.SerializeObject(comando)); } - public static async Task GetCameraFrame(CameraFrameType tipo = CameraFrameType.Rgb) + public static async Task GetCameraFrame(TipoFrameCamera tipo = TipoFrameCamera.Rgb) { DateTime Inicio = DateTime.Now; diff --git a/AgroBase/AgroBase/Services/Operadores/WeedWorkerService.cs b/AgroBase/AgroBase/Services/Operadores/WeedWorkerService.cs index eb89cbf92..8ebdc5042 100644 --- a/AgroBase/AgroBase/Services/Operadores/WeedWorkerService.cs +++ b/AgroBase/AgroBase/Services/Operadores/WeedWorkerService.cs @@ -71,6 +71,7 @@ namespace AgroBase.Services.Operadores } if (comandoMudou) { + Console.WriteLine("Comando dos bicos alterado: " + JsonConvert.SerializeObject(novoComando)); var pControle = Variaveis.OperacaoEmAndamento.Parametros.Controle; if (pControle.PulverizadorAutomatico) { @@ -98,7 +99,7 @@ namespace AgroBase.Services.Operadores break; case WeedWorkerCommandType.GetCameraFrame: - CameraFrameType tipo = (CameraFrameType)Convert.ToInt32(comando.@params["tipo"].ToString()); + TipoFrameCamera tipo = (TipoFrameCamera)Convert.ToInt32(comando.@params["tipo"].ToString()); DadosLeitura.CameraFrames[tipo] = new OAKCameraFrameModel() { frame = comando.@params["frame"].ToString(), @@ -133,7 +134,7 @@ namespace AgroBase.Services.Operadores Saude = OperadoresModels.AtualizarSaude(CtxKey.DadosWeedWorker); } - public static async Task GetCameraFrame(CameraFrameType tipo = CameraFrameType.Rgb) + public static async Task GetCameraFrame(TipoFrameCamera tipo = TipoFrameCamera.Rgb) { DateTime Inicio = DateTime.Now; 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 e2195b793..8f5df550a 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":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 +{"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":-1,"AnguloControle":0.0,"AnguloAbertura":30.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":-1,"AnguloControle":0.0,"AnguloAbertura":30.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":-1,"AnguloControle":0.0,"AnguloAbertura":30.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":"B04","ID_Num":74,"Posicao":4,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":-1,"AnguloControle":0.0,"AnguloAbertura":30.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":"B05","ID_Num":75,"Posicao":5,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":-1,"AnguloControle":0.0,"AnguloAbertura":30.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":"B06","ID_Num":76,"Posicao":6,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":-1,"AnguloControle":0.0,"AnguloAbertura":30.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":"B07","ID_Num":77,"Posicao":7,"Componente":11,"AtuacaoNivelAlto":true,"Servo_ID_Num":-1,"AnguloControle":0.0,"AnguloAbertura":30.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":true,"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":true,"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":true,"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":[],"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 e52fc5c2e..646b360fc 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":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-24T08:40:37.0472699-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 +{"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":"2026-02-26T15:12:11.7521527-03: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":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":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-26T16:00:21.332118-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":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 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 98ab66dd5..ad3ef5feb 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.802598446831809,"UltimaMudancaModo":"2026-02-24T08:35:04.2527267-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.0010074"},"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":112,"Index":0,"Id":"LT00B00001","Name":"GAL5000-60ucNIR","Description":"(0) GAL5000-60ucNIR","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":"1005","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":31.881600000000006,"UltimaMudancaModo":"0001-01-01T00:00: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":112,"Index":0,"Id":"LT00B00001","Name":"GAL5000-60ucNIR","Description":"(0) GAL5000-60ucNIR","State":null,"Usb_Speed":null,"Available_Camera_Sensors":null,"Version":"1005","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/Python/Scripts/workers/camera_worker/camera_gal.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/camera_worker/camera_gal.py index 4a7eb5c38..9d0c68c28 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/camera_worker/camera_gal.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/camera_worker/camera_gal.py @@ -1,9 +1,12 @@ import numpy as np import time +import socket +import struct from camera_worker.raw_segformer_service import make_bgr_preview_from_raw -from shared.enums import StatusModulo, T_Code, TipoFrameCamera -from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey +from shared.utils import resize_frame +from shared.enums import StatusModulo, T_Code +from shared.contexto_global_redis import ContextoGlobalRedis from camera_worker.gal_service import GalService import subprocess @@ -16,9 +19,10 @@ class CameraGal: self.mostrar_log = mostrar_log self.gst_proc = None - self.gst_WIDTH = 640 - self.gst_HEIGHT = 360 - self.gst_BIT_RATE = 500 + self.gst_FPS = 5 + self.gst_WIDTH = 480 + self.gst_HEIGHT = 270 + self.gst_BIT_RATE = 300 self._ultimo_envio_gst = 0.0 self.dispositivo = T_Code.Vzo @@ -52,16 +56,26 @@ class CameraGal: self.modelo = info.get("model") self.versao = info.get("version_word") + _camera = ContextoGlobalRedis.get_camera(self.mx_id) or {} + _camera["mx_id"] = self.mx_id + _camera["versao"] = self.versao + _camera["iniciando"] = True + _camera["iniciado"] = False + _camera["rodando"] = False + _camera["parametros"] = {} + # Criar processo para transmissao de video try: - _cfg = ContextoGlobalRedis.get_equipamento() or {} - _ip = _cfg.get("base_ip") - _porta = _cfg.get("base_porta_ervas") - if _ip is not None and _porta is not None: + self._sock = None + self._sock_conectado = False + self._sock_ultima_tentativa_conexao = 0.0 + self._sock_intervalo_reconexao = 5.0 # segundos entre tentativas + if False and _ip is not None and _porta is not None: self.mostrar_log(f"Iniciando GStreamer para {_ip}:{_porta}...") gst_cmd = [ GST_LAUNCH, "fdsrc", "fd=0", + #"!", "queue", "leaky=2", "max-size-buffers=1", # dropa frames antigos "!", "videoparse", f"width={self.gst_WIDTH}", f"height={self.gst_HEIGHT}", "format=bgr", @@ -71,6 +85,7 @@ class CameraGal: "!", f"video/x-raw,width={self.gst_WIDTH},height={self.gst_HEIGHT}", "!", "x264enc", "tune=zerolatency", "speed-preset=ultrafast", f"bitrate={self.gst_BIT_RATE}", "key-int-max=20", + #"byte-stream=true", "key-int-max=5", "bframes=0", "aud=true", f"bitrate={self.gst_BIT_RATE}", "!", "rtph264pay", "config-interval=-1", "pt=96", #"!", "h264parse", "!", "mpegtsmux", "!", "udpsink", @@ -85,6 +100,11 @@ class CameraGal: self.gst_proc = None self.mostrar_log(f"Erro ao criar script de transmissao de video: {e}") + _camera["modelo"] = self.modelo + _camera["dispositivo"] = self.dispositivo.value + _camera["tem_depht"] = False + _camera["tem_imu"] = False + # Fase 2: criar pipeline e instanciar normalmente try: rgb_width = 2592 @@ -110,15 +130,20 @@ class CameraGal: "cm_por_px_y": cm_por_px_y, } + _camera["parametros"] = self.parametros + self.ultima_saude["timestamp"] = time.time() self.ultima_saude["status"] = StatusModulo.OPERANTE.value self.iniciado = True + _camera["iniciado"] = True + _camera["iniciado_em"] = time.time() except Exception as e: self.mostrar_log(f"Erro ao iniciar camera: {e}") pass - #ContextoGlobalRedis.set(ContextoGlobalRedis.CamKey(self.mx_id), _camera) + _camera["iniciando"] = False + ContextoGlobalRedis.set(ContextoGlobalRedis.CamKey(self.mx_id), _camera) def requisitar_frame_raw(self, force: bool = False, max_age_s: float = None): """ @@ -348,3 +373,81 @@ class CameraGal: from camera_worker.manager import definir_saude_camera definir_saude_camera(self.mx_id, status, saude, motivos, self.rodando, performance, conectado, agora, self.dispositivo) + def _sock_tentar_conectar(self): + _cfg = ContextoGlobalRedis.get_equipamento() or {} + _ip = _cfg.get("base_ip") + _porta = _cfg.get("base_porta_ervas") + # Sem IP/porta configurado, nem tenta + if not _ip or not _porta: + return + + agora = time.time() + if (agora - self._sock_ultima_tentativa_conexao) < self._sock_intervalo_reconexao: + # ainda não deu o tempo mínimo, evita flood + return + + self._sock_ultima_tentativa_conexao = agora + + # Se já tem socket antigo, fecha + if self._sock is not None: + try: + self._sock.close() + except: + pass + self._sock = None + + try: + #self.mostrar_log(f"Tentando conectar em {_ip}:{_porta}...") + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + s.settimeout(1.0) # timeout curto pra não travar + + s.connect((_ip, _porta)) + s.settimeout(None) # depois de conectado, volta p/ blocking normal + + self._sock = s + self._sock_conectado = True + self.mostrar_log("Socket de vídeo conectado.") + except Exception as e: + self._sock_conectado = False + self._sock = None + # log mais leve pra não spammar + #self.mostrar_log(f"Falha ao conectar socket de vídeo: {e}") + + def enviar_frame_tcp(self, frame_bgr): + _stream_on = (ContextoGlobalRedis.get_camera(self.mx_id) or {}).get("streaming", False) + if not _stream_on: + return # se operador desligar o streaming, sai secão + + # Se não está conectado, tenta conectar e sai se ainda assim não conseguir + if not self._sock_conectado or self._sock is None: + self._sock_tentar_conectar() + if not self._sock_conectado or self._sock is None: + return # sem conexão, simplesmente não envia o frame + + # 🔹 OPCIONAL: padronizar resolução antes de encodar + frame_bgr = resize_frame(frame_bgr, max_width=640, max_height=360) + + # Aqui já consideramos que temos conexão, aí sim vale a pena encodar o frame + encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 50] # qualidade ajustável + ok, buf = cv2.imencode(".jpg", frame_bgr, encode_param) + if not ok: + return + + data = buf.tobytes() + size = len(data) + header = struct.pack("!I", size) # 4 bytes big-endian + + try: + self._sock.sendall(header + data) + except (BrokenPipeError, ConnectionResetError, OSError) as e: + self.mostrar_log(f"Conexão de vídeo perdida: {e}") + # marca como desconectado, próxima chamada vai tentar reconectar + self._sock_conectado = False + try: + self._sock.close() + except: + pass + self._sock = None + + diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/camera_worker/camera_oak.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/camera_worker/camera_oak.py index 14b70898e..c6122673c 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/camera_worker/camera_oak.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/camera_worker/camera_oak.py @@ -1,10 +1,13 @@ import numpy as np import depthai as dai import time +import socket +import struct from health_worker.modulos.imu import IMUCamera -from shared.enums import StatusModulo, T_Code, TipoFrameCamera -from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey +from shared.utils import resize_frame +from shared.enums import StatusModulo, T_Code +from shared.contexto_global_redis import ContextoGlobalRedis import subprocess import cv2 @@ -17,9 +20,10 @@ class CameraOak: self.modelo_ia_det = modelo_ia_det self.gst_proc = None - self.gst_WIDTH = 640 - self.gst_HEIGHT = 360 - self.gst_BIT_RATE = 500 + self.gst_FPS = 5 + self.gst_WIDTH = 480 + self.gst_HEIGHT = 270 + self.gst_BIT_RATE = 300 self._ultimo_envio_gst = 0.0 self.dispositivo = T_Code.Vzo @@ -84,10 +88,11 @@ class CameraOak: # Criar processo para transmissao de video try: - _cfg = ContextoGlobalRedis.get_equipamento() or {} - _ip = _cfg.get("base_ip") - _porta = _cfg.get("base_porta_caminho") if self.dispositivo == T_Code.Snr else _cfg.get("base_porta_ervas") - if _ip is not None and _porta is not None: + self._sock = None + self._sock_conectado = False + self._sock_ultima_tentativa_conexao = 0.0 + self._sock_intervalo_reconexao = 5.0 # segundos entre tentativas + if False and _ip is not None and _porta is not None: self.mostrar_log(f"Iniciando GStreamer para {_ip}:{_porta}...") gst_cmd = [ GST_LAUNCH, @@ -101,6 +106,7 @@ class CameraOak: "!", f"video/x-raw,width={self.gst_WIDTH},height={self.gst_HEIGHT}", "!", "x264enc", "tune=zerolatency", "speed-preset=ultrafast", f"bitrate={self.gst_BIT_RATE}", "key-int-max=20", + #"byte-stream=true", "key-int-max=5", "bframes=0", "aud=true", f"bitrate={self.gst_BIT_RATE}", "!", "rtph264pay", "config-interval=-1", "pt=96", #"!", "h264parse", "!", "mpegtsmux", "!", "udpsink", @@ -180,13 +186,11 @@ class CameraOak: self.iniciado = True _camera["iniciado"] = True _camera["iniciado_em"] = time.time() - except Exception as e: self.mostrar_log(f"Erro ao iniciar camera: {e}") pass _camera["iniciando"] = False - ContextoGlobalRedis.set(ContextoGlobalRedis.CamKey(self.mx_id), _camera) def _criar_pipeline(self): @@ -696,5 +700,83 @@ class CameraOak: from camera_worker.manager import definir_saude_camera definir_saude_camera(self.mx_id, status, saude, motivos, self.rodando, performance, conectado, agora, self.dispositivo) + + def _sock_tentar_conectar(self): + _cfg = ContextoGlobalRedis.get_equipamento() or {} + _ip = _cfg.get("base_ip") + _porta = _cfg.get("base_porta_caminho") + # Sem IP/porta configurado, nem tenta + if not _ip or not _porta: + return + + agora = time.time() + if (agora - self._sock_ultima_tentativa_conexao) < self._sock_intervalo_reconexao: + # ainda não deu o tempo mínimo, evita flood + return + + self._sock_ultima_tentativa_conexao = agora + + # Se já tem socket antigo, fecha + if self._sock is not None: + try: + self._sock.close() + except: + pass + self._sock = None + + try: + #self.mostrar_log(f"Tentando conectar em {_ip}:{_porta}...") + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + s.settimeout(1.0) # timeout curto pra não travar + + s.connect((_ip, _porta)) + s.settimeout(None) # depois de conectado, volta p/ blocking normal + + self._sock = s + self._sock_conectado = True + self.mostrar_log("Socket de vídeo conectado.") + except Exception as e: + self._sock_conectado = False + self._sock = None + # log mais leve pra não spammar + #self.mostrar_log(f"Falha ao conectar socket de vídeo: {e}") + + def enviar_frame_tcp(self, frame_bgr): + _stream_on = (ContextoGlobalRedis.get_camera(self.mx_id) or {}).get("streaming", False) + if not _stream_on: + return # se operador desligar o streaming, sai secão + + # Se não está conectado, tenta conectar e sai se ainda assim não conseguir + if not self._sock_conectado or self._sock is None: + self._sock_tentar_conectar() + if not self._sock_conectado or self._sock is None: + return # sem conexão, simplesmente não envia o frame + + # 🔹 OPCIONAL: padronizar resolução antes de encodar + frame_bgr = resize_frame(frame_bgr, max_width=640, max_height=360) + + # Aqui já consideramos que temos conexão, aí sim vale a pena encodar o frame + encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 50] # qualidade ajustável + ok, buf = cv2.imencode(".jpg", frame_bgr, encode_param) + if not ok: + return + + data = buf.tobytes() + size = len(data) + header = struct.pack("!I", size) # 4 bytes big-endian + + try: + self._sock.sendall(header + data) + except (BrokenPipeError, ConnectionResetError, OSError) as e: + self.mostrar_log(f"Conexão de vídeo perdida: {e}") + # marca como desconectado, próxima chamada vai tentar reconectar + self._sock_conectado = False + try: + self._sock.close() + except: + pass + self._sock = None + diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/bateria.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/bateria.py new file mode 100644 index 000000000..ff04a53d2 --- /dev/null +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/health_worker/modulos/bateria.py @@ -0,0 +1,352 @@ +import time +from shared.contexto_global_redis import ContextoGlobalRedis +from shared.enums import StatusModulo, T_Code +from health_worker.modulos.base import ModuloDiagnosticoBase + + +class ModuloBateria(ModuloDiagnosticoBase): + def __init__(self): + self.t_code = T_Code.Bat + self.nome = "Bateria / BMS Daly" + self.timeout = 10 # segundos para considerar desatualizado + + def _status_por_score(self, score: float) -> StatusModulo: + if score >= 80: + return StatusModulo.OPERANTE + elif score >= 50: + return StatusModulo.ALERTA + else: + return StatusModulo.FALHA + + def atualizar_saude(self): + try: + SAUDE_MIN_ALERTA = 80 + + motivos = [] + condicoes = [] + saude_individual = [] + + now = time.perf_counter() + saude = 0 + + dados = ContextoGlobalRedis.get_modulo(self.t_code) or {} + + conectado = dados.get("iniciado") + if not conectado: + saude = 0 + motivos.append("Desconectado") + else: + momento = float(dados.get("timestamp") or 0.0) + dt = now - momento if momento > 0 else 9999.0 + + # ------------ LEITURA DOS DADOS DA BATERIA ------------ + v_total = dados.get("tensao_total_v") + corrente = dados.get("corrente_a") + soc = dados.get("soc_pct") + v_min = dados.get("tensao_min_celula_v") + v_max = dados.get("tensao_max_celula_v") + idx_vmin = dados.get("idx_celula_min") + idx_vmax = dados.get("idx_celula_max") + t_min = dados.get("temp_min_c") + t_max = dados.get("temp_max_c") + cap_rest = dados.get("cap_restante_ah") + num_cells = dados.get("num_celulas_serie") + alarms = dados.get("alarmes") or {} + bms_life = dados.get("bms_life_raw") + + delta_cells = None + if v_min is not None and v_max is not None: + delta_cells = v_max - v_min + + # ------------ SCORES PARCIAIS ------------ + + # 1) Score de comunicação / frescor + if not dados: + score_com = 0.0 + motivos.append("Nenhum dado de telemetria da bateria disponível.") + else: + if dt > self.timeout: + score_com = max(0.0, 100.0 - (dt - self.timeout) * 5.0) # cai 5 pts por segundo acima do timeout + motivos.append(f"Dados da bateria desatualizados ({dt:.1f} s sem atualização).") + else: + score_com = 100.0 + + # 2) Score de SOC + if soc is None: + score_soc = 60.0 # penaliza por não ter SOC + motivos.append("SOC da bateria indisponível / não informado pelo BMS.") + else: + if soc <= 3: + score_soc = 20.0 + motivos.append(f"SOC crítico ({soc:.1f}%).") + elif soc <= 10: + score_soc = 40.0 + motivos.append(f"SOC muito baixo ({soc:.1f}%).") + elif soc <= 20: + score_soc = 60.0 + motivos.append(f"SOC baixo ({soc:.1f}%).") + else: + score_soc = 100.0 + + # 3) Score de desbalanceamento entre células + if delta_cells is None: + score_bal = 70.0 # não informado, mas não mata + motivos.append("Não foi possível calcular desbalanceamento entre células (Vmin/Vmax ausentes).") + else: + if delta_cells > 0.15: + score_bal = 30.0 + motivos.append( + f"Desbalanceamento elevado entre células ({delta_cells:.3f} V) " + f"[Vmin={v_min:.3f} V (#{idx_vmin}), Vmax={v_max:.3f} V (#{idx_vmax})]." + ) + elif delta_cells > 0.08: + score_bal = 60.0 + motivos.append( + f"Desbalanceamento moderado entre células ({delta_cells:.3f} V)." + ) + else: + score_bal = 100.0 + + # 4) Score de temperatura + if t_max is None: + score_temp = 70.0 + motivos.append("Temperatura da bateria não informada.") + else: + if t_max >= 60: + score_temp = 20.0 + motivos.append(f"Temperatura crítica da bateria ({t_max:.1f} °C).") + elif t_max >= 55: + score_temp = 40.0 + motivos.append(f"Temperatura muito alta da bateria ({t_max:.1f} °C).") + elif t_max >= 45: + score_temp = 70.0 + motivos.append(f"Temperatura elevada da bateria ({t_max:.1f} °C).") + else: + score_temp = 100.0 + + # 5) Score baseado em alarmes do BMS + score_alarm = 100.0 + alarmes_ativos = [nome for nome, val in alarms.items() if val] + + if alarmes_ativos: + for nome in alarmes_ativos: + if nome in ("soc_low_1", "soc_low_2"): + score_alarm -= 20.0 + motivos.append(f"Alarme BMS: {nome} ativo (SOC baixo).") + elif nome in ("ovp", "uvp", "otp", "utp"): + score_alarm -= 40.0 + motivos.append(f"Alarme BMS crítico: {nome} ativo.") + else: + score_alarm -= 15.0 + motivos.append(f"Alarme BMS: {nome} ativo.") + + score_alarm = max(0.0, score_alarm) + + # ------------ SAÚDE GLOBAL ------------ + + # Peso dos sub-scores (total 1.0) + w_com = 0.20 # comunicação + w_soc = 0.25 # estado de carga + w_bal = 0.20 # balanceamento + w_temp = 0.20 # temperatura + w_alarm = 0.15 # alarmes + + health = ( + w_com * score_com + + w_soc * score_soc + + w_bal * score_bal + + w_temp * score_temp + + w_alarm * score_alarm + ) + + saude = round(health, 1) + + # ------------ SAÚDE INDIVIDUAL / CONDIÇÕES ------------ + + # 1) SOC + cond_soc = [] + if score_soc < SAUDE_MIN_ALERTA: + severidade = int(max(0, 100 - score_soc)) + c = { + "label": "Estado de carga (SOC)", + "valor": soc if soc is not None else -1, + "severidade": severidade, + "descricao": "SOC abaixo do ideal para operação segura.", + "acoes": [ + "Planejar recarga da bateria antes de continuar a operação.", + "Reduzir velocidade e carga dos atuadores para economizar energia.", + "Evitar iniciar serviços longos com SOC baixo." + ] + } + condicoes.append(c) + cond_soc.append(c) + + saude_individual.append({ + "id": "bat_soc", + "label": "Estado de carga (SOC)", + "status": self._status_por_score(score_soc).value, + "saude": round(score_soc, 1), + "motivos": [m for m in motivos if "SOC " in m or "SOC" in m], + "condicoes_operacionais": cond_soc, + "em_uso": True, + }) + + # 2) Desbalanceamento entre células + cond_bal = [] + if score_bal < SAUDE_MIN_ALERTA: + severidade = int(max(0, 100 - score_bal)) + c = { + "label": "Desbalanceamento de células", + "valor": round(delta_cells, 4) if delta_cells is not None else -1, + "severidade": severidade, + "descricao": "Diferença de tensão significativa entre células da bateria.", + "acoes": [ + "Permitir período de balanceamento com o carregador conectado.", + "Evitar descargas profundas até reduzir o desbalanceamento.", + "Verificar se alguma célula está degradada ou com problema." + ] + } + condicoes.append(c) + cond_bal.append(c) + + saude_individual.append({ + "id": "bat_cells", + "label": "Balanceamento entre células", + "status": self._status_por_score(score_bal).value, + "saude": round(score_bal, 1), + "motivos": [m for m in motivos if "Desbalanceamento" in m], + "condicoes_operacionais": cond_bal, + "em_uso": True, + }) + + # 3) Temperatura da bateria + cond_temp = [] + if score_temp < SAUDE_MIN_ALERTA: + severidade = int(max(0, 100 - score_temp)) + c = { + "label": "Temperatura da bateria", + "valor": t_max if t_max is not None else -273, + "severidade": severidade, + "descricao": "Temperatura da bateria acima da faixa ideal.", + "acoes": [ + "Reduzir corrente de descarga (velocidade / esforços dos atuadores).", + "Verificar ventilação / refrigeração do pack de baterias.", + "Interromper operação se a temperatura continuar subindo." + ] + } + condicoes.append(c) + cond_temp.append(c) + + saude_individual.append({ + "id": "bat_temp", + "label": "Temperatura da bateria", + "status": self._status_por_score(score_temp).value, + "saude": round(score_temp, 1), + "motivos": [m for m in motivos if "Temperatura" in m], + "condicoes_operacionais": cond_temp, + "em_uso": True, + }) + + # 4) Alarmes do BMS + cond_alarm = [] + if score_alarm < SAUDE_MIN_ALERTA or alarmes_ativos: + severidade = int(max(0, 100 - score_alarm)) + c = { + "label": "Alarmes do BMS", + "valor": len(alarmes_ativos), + "severidade": severidade, + "descricao": "Um ou mais alarmes foram acionados pelo BMS.", + "acoes": [ + "Verificar detalhes dos alarmes no painel do BMS.", + "Investigar causas de sobretensão, subtensão ou sobretemperatura.", + "Interromper operação em caso de alarmes críticos persistentes." + ] + } + condicoes.append(c) + cond_alarm.append(c) + + saude_individual.append({ + "id": "bat_alarms", + "label": "Alarmes do BMS", + "status": self._status_por_score(score_alarm).value, + "saude": round(score_alarm, 1), + "motivos": [m for m in motivos if "Alarme BMS" in m], + "condicoes_operacionais": cond_alarm, + "em_uso": True, + }) + + # 5) Comunicação / frescor dos dados + cond_com = [] + if score_com < SAUDE_MIN_ALERTA: + severidade = int(max(0, 100 - score_com)) + c = { + "label": "Atualização de telemetria", + "valor": round(dt, 2), + "severidade": severidade, + "descricao": "Dados da bateria desatualizados.", + "acoes": [ + "Verificar comunicação CAN entre ECU e BMS.", + "Verificar módulo responsável por requisitar dados da bateria.", + "Checar cabos/conectores e alimentação do BMS." + ] + } + condicoes.append(c) + cond_com.append(c) + + saude_individual.append({ + "id": "bat_telemetry", + "label": "Telemetria da bateria", + "status": self._status_por_score(score_com).value, + "saude": round(score_com, 1), + "motivos": [m for m in motivos if "Dados da bateria" in m or "telemetria" in m], + "condicoes_operacionais": cond_com, + "em_uso": True, + }) + + # ------------ STATUS GERAL DO MÓDULO ------------ + + status = StatusModulo.OPERANTE + if not conectado: + status = StatusModulo.DESCONECTADO + elif saude <= 0: + status = StatusModulo.FALHA + elif saude < SAUDE_MIN_ALERTA: + status = StatusModulo.ALERTA + + payload = { + "conectado": conectado, + "status": status.value, + "saude": saude, + "motivos": motivos, + "saude_individual": saude_individual, + "condicoes_operacionais": condicoes, + "detalhes": { + "tensao_total_v": locals().get("v_total", 0), + "corrente_a": locals().get("corrente", 0), + "soc_pct": locals().get("soc", 0), + "cap_restante_ah": locals().get("cap_rest", 0), + "num_celulas_serie": locals().get("num_cells", 0), + "tensao_min_celula_v": locals().get("v_min", 0), + "tensao_max_celula_v": locals().get("v_max", 0), + "delta_celulas_v": locals().get("delta_cells", 0), + "temp_min_c": locals().get("t_min", 0), + "temp_max_c": locals().get("t_max", 0), + "bms_life_raw": locals().get("bms_life", 0), + "tempo_desde_ultimo_update_s": locals().get("dt", 0), + "qtd_alarmes_ativos": len(locals().get("alarmes_ativos", [])), + "alarmes_ativos": locals().get("alarmes_ativos", []), + "score_com": round(locals().get("score_com", 0), 1), + "score_soc": round(locals().get("score_soc", 0), 1), + "score_balanceamento": round(locals().get("score_bal", 0), 1), + "score_temp": round(locals().get("score_temp", 0), 1), + "score_alarm": round(locals().get("score_alarm", 0), 1), + } + } + + ContextoGlobalRedis.atualizar_ctx_dict( + ContextoGlobalRedis.ModKey(self.t_code), + saude=payload + ) + + except Exception as e: + print(f"Erro ao atualizar saude do modulo {self.t_code.name}: {e}") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/gerenciador.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/gerenciador.py index bce4e5c06..aba0cca23 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/gerenciador.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/gerenciador.py @@ -25,15 +25,13 @@ class ManagerWorker: def executar(self, envia_resposta): t0 = time.time() - movimento_automatico = ContextoGlobalRedis.get_controle().get("movimento_automatico", False) - if movimento_automatico: - self.definir_processador() - if self.processador: - comando = self.processador.processar() - if comando is not None and envia_resposta: - ContextoGlobalRedis.publicar_comando(CmdKey.ManagerWorkerTx, { "cmd": ManagerWorkerCommandType.EnviarDadosControle.value, "params": comando }) - else: - mostrar_log("Processador nao definido") + self.definir_processador() + if self.processador: + comando = self.processador.processar() + if comando is not None and envia_resposta: + ContextoGlobalRedis.publicar_comando(CmdKey.ManagerWorkerTx, { "cmd": ManagerWorkerCommandType.EnviarDadosControle.value, "params": comando }) + else: + mostrar_log("Processador nao definido") t1 = time.time() latencia = t1 - t0 diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py index d8ae8b8f8..9af0ae0d5 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/direcional.py @@ -1,6 +1,6 @@ import time -from shared.enums import ModoOperacao, StatusCarroMapa, StatusModulo, StatusOperacao, T_Code, TipoMovimentoDirecional, TiposControladorDirecional +from shared.enums import ModoOperacao, StatusCarroMapa, StatusModulo, T_Code, TipoMovimentoDirecional, TiposControladorDirecional from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey from manager_worker.config import mostrar_log from manager_worker.modulos.mpc import get_mpc, comando_parado @@ -103,7 +103,7 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): }, "RegrasAtivas": { "matriz_custo": False, - "deteccao_obstaculos": True, + "deteccao_obstaculos": False, }, "Equipamento": { "largura": _equipamento.get("largura", 0.85), @@ -116,19 +116,14 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): #print(contexto["VisualWorker"]) if _tipo_controle == TiposControladorDirecional.MPC: - comando = _regras_taticas(contexto) - - if (comando.get("comando_definido", False)): - return _montar_comando_retorno(comando, latencia=latencia) + op_modo = ModoOperacao(_operacao.get("modo", ModoOperacao.NaoDefinido.value)) + if op_modo == ModoOperacao.MapaGPS: + return _comando_mapa_gps_mpc(contexto) + elif op_modo == ModoOperacao.MapeamentoVisual: + return _comando_mapeamento_visual(contexto) else: - op_modo = ModoOperacao(_operacao.get("modo", ModoOperacao.NaoDefinido.value)) - if op_modo == ModoOperacao.MapaGPS: - return _comando_mapa_gps_mpc(contexto) - elif op_modo == ModoOperacao.MapeamentoVisual: - return _comando_mapeamento_visual(contexto) - else: - comando = _comando_direcional_parado(True) - return _montar_comando_retorno(comando, latencia=latencia) + comando = _comando_direcional_parado() + return _montar_comando_retorno(comando, latencia=latencia) elif _tipo_controle == TiposControladorDirecional.PID: angulo_max = _controle.get("angulo_max", 30) @@ -157,7 +152,7 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): _cmd = { "comando_definido": True, "enviar_comando": True, - "parada_necessaria": True, + "parada_necessaria": False, "erro": False, "latencia": 0.0, "angulo": angulo, @@ -169,83 +164,25 @@ def definir_comando(pid: PIDAdaptativo, envio_necessario: bool): except Exception as e: mostrar_log(f"❌ Erro ao definir comando direcional: {e}") -def _comando_direcional_parado(definido: bool, frear: bool = False): +def _comando_direcional_parado(): try: angulo, tipo = comando_parado() _cmd = { - "comando_definido": definido, - "enviar_comando": True, - "parada_necessaria": True, - "erro": False, - "latencia": 0.0, - "angulo": angulo, - "tipo": tipo.value, - "simulacao": [], - "frear": frear + "enviar_comando": True, + "parada_necessaria": False, + "erro": False, + "angulo": angulo, + "tipo": tipo.value, + "simulacao": [], + "erro_lateral": 0, + "erro_orientacao": 0, + "debug_custo": {}, + "candidatos_testados": 0 } return _cmd except Exception as e: mostrar_log(f"❌ Erro ao montar comando direcional parado: {e}") -def _regras_taticas(contexto): - try: - if contexto.get("Operacao", {}).get("Status", StatusOperacao.NaoIniciado.value) != StatusOperacao.EmAndamento.value or contexto.get("Operacao", {}).get("Finalizando", False): - mostrar_log("🟥 Direcional parado: operação não está em andamento ou está finalizando.") - return _comando_direcional_parado(True) - - velocidade_media = contexto.get("Carro", {}).get("Velocidade", 0.0) - if velocidade_media < 0.01: - mostrar_log("⚠️ Possível travamento detectado (velocidade quase zero).") - # Pode evoluir para uma lógica de recuperação no futuro - - dados_vw = contexto.get("VisualWorker", {}) - - vw_ativado = dados_vw.get("Ativado", False) - vw_operante = dados_vw.get("Operante", False) - - if vw_ativado and not vw_operante: - #mostrar_log("⚠️ Sensores principais inativos. Rodando controle no modo básico.") - return _comando_direcional_parado(False) - - imu = ContextoGlobalRedis.get_modulo(T_Code.Imu) - if imu is not None and imu.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value) == StatusModulo.OPERANTE.value: - ang_roll_max = contexto.get("Equipamento", {}).get("angulo_roll_max", 15.0) - ang_pitch_max = contexto.get("Equipamento", {}).get("angulo_pitch_max", 30.0) - if abs(imu.get("pitch", 0.0)) > ang_pitch_max or abs(imu.get("roll", 0.0)) > ang_roll_max: - mostrar_log(f"🟥 Inclinação perigosa detectada. Parando movimentação. roll: {imu.get('roll')}, pitch: {imu.get('pitch')}, yaw: {imu.get('yaw')}") - return _comando_direcional_parado(True) - - if not vw_ativado: - mostrar_log("⚠️ Sensores principais desativados. Rodando controle no modo básico.") - return _comando_direcional_parado(False) - - # >>> NOVO: gate de bloqueio/parede com block + d_obs_min <<< - if vw_operante and contexto.get("RegrasAtivas", {}).get("deteccao_obstaculos", False): - block = dados_vw.get("MatrizCusto", {}).get("Block", None) - if block is not None: - reason = block.get("reason", "none") - decision = block.get("decision", {}) - - #print(block) - - if decision.get("parar", False): - mostrar_log(f"🟥 Parada necessaria por {reason}.") - return _comando_direcional_parado(True, frear=True) - - # motivo narrow: não para, mas dá dica lateral - if isinstance(block, dict) and reason == "narrow": - sb = (block.get("side_bias") or {}).get("value", 0.0) - hints = contexto.setdefault("DirecionalHints", {}) - if sb > 0.25: hints["vetar_direita"] = True - if sb < -0.25: hints["vetar_esquerda"] = True - - # se chegou até aqui, pode seguir - return _comando_direcional_parado(False) - - except Exception as e: - mostrar_log(f"❌ Erro ao processar regras taticas do direcional: {e}") - return _comando_direcional_parado(True) - def _comando_mapa_gps_mpc(contexto): try: mpc = get_mpc() @@ -278,7 +215,7 @@ def _comando_mapa_gps_mpc(contexto): def _comando_mapeamento_visual(contexto): try: # ⛔ Fallback seguro se visual não operante - comando = _comando_direcional_parado(True) + comando = _comando_direcional_parado() if not contexto.get("VisualWorker", {}).get("Operante", False): mostrar_log("Sensores principais inativos! Impossível definir controle") return comando["angulo"], comando["tipo"], comando["simulacao"], comando["parada_necessaria"], False @@ -311,13 +248,17 @@ def _comando_mapeamento_visual(contexto): # 🔧 Monta comando final comando = { - "enviar_comando": True, - "parada_necessaria": parada_necessaria, - "erro": False, + "enviar_comando": True, + "parada_necessaria": parada_necessaria, + "erro": False, "latencia": latencia, - "angulo": round(angulo, 2), - "tipo": tipo_movimento.value, - "simulacao": [] + "angulo": round(angulo, 2), + "tipo": tipo_movimento.value, + "simulacao": [], + "erro_lateral": 0, + "erro_orientacao": 0, + "debug_custo": {}, + "candidatos_testados": 0 } return _montar_comando_retorno(comando) diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py index 8b1473466..08dfa7607 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/movimentacao.py @@ -1,42 +1,13 @@ -import time -from shared.enums import ModoOperacao, StatusModulo, StatusOperacao, StatusCarroMapa, T_Code +from shared.enums import ModoOperacao, StatusModulo, StatusCarroMapa, T_Code from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey from manager_worker.config import mostrar_log from manager_worker.filtros import FiltroVelocidade -def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVelocidade, erro_orientacao: float = None): +def definir_comando(filtro_vel: FiltroVelocidade, erro_orientacao: float = None): try: _operacao = ContextoGlobalRedis.get_operacao() _controle = ContextoGlobalRedis.get_controle() - status_operacao = StatusOperacao(_operacao.get("status", StatusOperacao.NaoIniciado.value)) - finalizando = _operacao.get("finalizando", False) - if erro: - mostrar_log("🟥 Movimento parado: erro ao definir comando direcional.") - return _montar_comando_retorno(0.0, False) - - if parada_necessaria: - mostrar_log("🟥 Movimento parado: direcional sem possibilidade de desvio.") - frenagem_automatica = ContextoGlobalRedis.get_controle().get("frenagem_automatica", False) - frear = False - deve_frear = frenagem_automatica and frear - return _montar_comando_retorno(0.0, deve_frear) - - if (status_operacao != StatusOperacao.EmAndamento) or finalizando: - mostrar_log(f"🟥 Movimento parado: operação não está em andamento ou finalizando: {status_operacao.name}") - return _montar_comando_retorno(0.0, False) - - _dados_vw = ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {}) - _snr = ContextoGlobalRedis.get_modulo(T_Code.Snr) - sonar_ativado = _controle.get("sonar_ativado", False) - visual_worker_operante = (_snr.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value)) == StatusModulo.OPERANTE.value - analise_deteccao_atualizada = (time.perf_counter() - _dados_vw.get("matriz_confianca", {}).get("ts", 10.0) <= 1.0) - obstaculo_detectado = _dados_vw.get("matriz_confianca", {}).get("block", {}).get("decision", {}).get("parar", False) if analise_deteccao_atualizada else False - - if (sonar_ativado and visual_worker_operante and obstaculo_detectado): - mostrar_log(f"🟥 Movimento parado: obstaculo proximo detectado no sonar") - return _montar_comando_retorno(0.0, True) - op_modo = ModoOperacao(_operacao.get("modo", ModoOperacao.NaoDefinido.value)) _contexto = ContextoGlobalRedis.get_contexto() @@ -70,6 +41,7 @@ def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVeloc if erro_orientacao is None: erro_orientacao = _trajetoria.get("erro_angular", 0) pontos_fim_corredor = _trajetoria.get("CorredorAtual", {}).get("pontos_restantes", -1) elif op_modo == ModoOperacao.MapeamentoVisual: + _dados_vw = ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {}) status_carro = StatusCarroMapa(_dados_vw.get("segmentacao", {}).get("status_corredor", StatusCarroMapa.Parado.value)) if erro_orientacao is None: erro_orientacao = _dados_vw.get("segmentacao", {}).get("erro_angular", 0) @@ -101,7 +73,7 @@ def definir_comando(parada_necessaria: bool, erro: bool, filtro_vel: FiltroVeloc #mostrar_log(f"🚗 Velocidade definida: {velocidade_sp:.1f}%") - return _montar_comando_retorno(velocidade_sp, False) + return _montar_comando_retorno(velocidade_sp) except Exception as e: mostrar_log(f"Erro ao definir o comando de movimentacao: {e}") @@ -128,8 +100,7 @@ def calcular_velocidade_relativa(vel_min, vel_max, ang_max, erro_orientacao, k=1 vel = vel_min + (1.0 - k*s) * faixa return round(vel, 2) -def _montar_comando_retorno(velocidade_sp: float, frear: bool): +def _montar_comando_retorno(velocidade_sp: float): return { - "velocidade": velocidade_sp, - "frear": frear + "velocidade": velocidade_sp } diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py index 0337baea6..c164b71e7 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/mpc.py @@ -41,6 +41,12 @@ class ControladorMPC: self.velocidade_min = parametros_mpc.get("velocidade_min", 0.4) self.velocidade_max = parametros_mpc.get("velocidade_max", 1.9) self.horizonte = parametros_mpc.get("horizonte", 2.5) + self.horizonte_min = parametros_mpc.get("horizonte_min", 0.6) + self.horizonte_max = parametros_mpc.get("horizonte_max", 2.8) + self.horizonte_parado = parametros_mpc.get("horizonte_parado", 0.5) + self._beam_traj_min = parametros_mpc.get("beam_traj_min", 3) # nº mínimo de trajetórias completas que queremos + self._beam_topN_max = parametros_mpc.get("beam_topN_max", 5) # limite superior de candidatos ativos + self._beam_topN_min = parametros_mpc.get("beam_topN_min", 2) # limite inferior # otimizacoes self._np_bool = np.bool_ @@ -595,15 +601,16 @@ class ControladorMPC: # tente usar self.vel_max_m_s se já existir; senão, usa 6.8 km/h (~1.889 m/s) vel_max_ms = getattr(self, "vel_max_m_s", 6.8/3.6) v = float(velocidade) - if v <= 1.05: # heurística: trata <=1.0 como v_norm - v = max(0.0, min(1.0, v)) * vel_max_ms - else: - v = max(0.0, v) # já está em m/s + #if v <= 1.05: # heurística: trata <=1.0 como v_norm + # v = max(0.0, min(1.0, v)) * vel_max_ms + #else: + # v = max(0.0, v) # já está em m/s + v = max(0.0, v) # já está em m/s # --- 2) Base polinomial (suave e previsível) ------------------------------ # L_base = L0 + a*v + b*v^2 (clamp em [Lmin, Lmax]) - Lmin, Lmax = 0.60, 2.80 # bom para teu range (1.3–6.8 km/h) - L0, a, b = 0.60, 0.70, 0.20 + Lmin, Lmax = self.horizonte_min, self.horizonte_max # bom para teu range (1.3–6.8 km/h) + L0, a, b = self.horizonte_parado, 0.70, 0.20 L = L0 + a*v + b*(v*v) if L < Lmin: L = Lmin if L > Lmax: L = Lmax @@ -736,300 +743,12 @@ class ControladorMPC: t_exec = max((now() - self.ultima_atualizacao), 1e-3) if comando['erro']: - mostrar_log(f"🧭 Direcional MPC | Latencia: {comando['latencia']} | Parada: {comando['parada_necessaria']} | Movimento: {TipoMovimentoDirecional(comando['tipo']).name} | Ângulo: {comando['angulo']}° | Horizonte: {len(comando['simulacao'])} | dt: {dt_raw:.2f} s | freq = {(1.0 / dt_raw):.2f} Hz | t_exec: {t_exec:.2} s | f_exec: {(1.0 / t_exec):.2f} Hz") + mostrar_log(f"🧭 Direcional MPC | Latencia: {comando['latencia']} | Parada: {comando['parada_necessaria']} | Movimento: {TipoMovimentoDirecional(comando['tipo']).name} | Ângulo: {comando['angulo']}° | CT: {comando['candidatos_testados']} ({len(comando['debug_custo'])}) | Horizonte: {len(comando['simulacao'])} | dt: {dt_raw:.2f} s | freq = {(1.0 / dt_raw):.2f} Hz | t_exec: {t_exec:.2} s | f_exec: {(1.0 / t_exec):.2f} Hz") return comando except Exception as e: mostrar_log(f"❌ Erro ao processar compute MPC: {e}") - def _processar_mpc_receding_old(self, contexto, comando_anterior): - now = time.perf_counter - t0 = now() - - SLA_MS = getattr(self, "_mpc_sla_ms", 200.0) # 200 ms ⇒ 5 Hz - HEAD_MS = getattr(self, "_mpc_headroom_ms", 25.0) - deadline = t0 + (SLA_MS - HEAD_MS) / 1000.0 - - def ms_left(): - return (deadline - now()) * 1000.0 - - try: - if not self.pontos_info: - return None - - GPS = contexto.get("GPS", {}) - pos_lat = GPS.get("Latitude", 0.0) - pos_lon = GPS.get("Longitude", 0.0) - pos_theta = GPS.get("AnguloCarro", 0.0) - pos_passos_atraso = GPS.get("PassosAtraso", 0) - pos_timestamp = GPS.get("Timestamp", 0.0) - pos_latencia = now() - pos_timestamp - - LAT_MAX = 2.0 - if pos_latencia >= LAT_MAX: - mostrar_log(f"[GPS] Grande latencia entre coordenadas detectado ({pos_latencia:.3f}/{LAT_MAX}): parando por fallback") - return self._comando_fallback_hot_stop(comando_anterior, latencia=pos_latencia) - if (pos_passos_atraso > 3): - mostrar_log(f"[GPS] Atraso detectado de {(pos_passos_atraso / 3.0):.1f} passos, {pos_latencia:.3f} s") - - x, y = self.gps_handler.converter_latlon_para_xz(pos_lat, pos_lon) - theta = np.radians(pos_theta) - x0, y0, t0 = x, y, theta - velocidade = contexto.get("Carro", {}).get("Velocidade", 0) - status_carro = contexto.get("Carro", {}).get("Status", StatusCarroMapa.Parado.value) - idx_proximo_ponto_real = contexto.get("Carro", {}).get("IdxProximoPonto", 0) - idx_ponto_alvo = contexto.get("Carro", {}).get("IdxPontoAlvo", 0) - Nmax = 20 if status_carro == StatusCarroMapa.CaminhandoRua.value else 60 - - - # Comando de hold (se não tiver buffer de comandos aplicados) - u_hold = { - "tipo": comando_anterior.get("tipo"), - "angulo": np.radians(comando_anterior.get("angulo", 0.0)), - "v": velocidade, - "omega": self.gps_handler.calcular_omega(velocidade, np.radians(comando_anterior.get("angulo", 0.0)), comando_anterior.get("tipo")) - } - # Opcional: sequência real de comandos aplicados durante a latência (se você tiver) - cmd_seq = None # ou algo como [(0.12, u1), (0.08, u2), ...] - x, y, theta, pts_visitados = self.corrigir_pose_por_latencia( - x, y, theta, self.visitados_execucao, - latency_s=min(pos_latencia, LAT_MAX), - dt=self.dt, - nova_posicao_fn=self._nova_posicao, - u_hold=u_hold, - cmd_seq=cmd_seq, - time_left_ms=lambda: (deadline - now()) * 1000.0, - calc_omega_fn=self.gps_handler.calcular_omega - ) - idx_alvo_correcao = self._corrigir_pontos_visitados(x, y, pts_visitados, idx_proximo_ponto_real) # marca pontos antigos como visitados - - #print(f"Anterior: x: {x0}, y: {y0}, t: {t0} - Novo: x: {x}, y: {y}, t: {theta}") - - #print(GPS) - - distancia_m = velocidade * self.dt - ultimo_ponto = idx_proximo_ponto_real >= len(self.pontos_info) - self.tempo_execucao_local = contexto.get("Carro", {}).get("TempoEntreComandos", 0.5) - if ultimo_ponto: - self.passos_horizonte_local = 1 - self.qtd_comandos_sucessivos = 3 - elif distancia_m > 0: - passos_total = min(int(self.horizonte / distancia_m), Nmax) - self.passos_horizonte_local = max(1, math.ceil(self.tempo_execucao_local / self.dt)) - self.qtd_comandos_sucessivos = max(1, passos_total // self.passos_horizonte_local) - else: - self.passos_horizonte_local = 0 - self.qtd_comandos_sucessivos = 0 - - angulo_anterior = np.radians(comando_anterior.get("angulo", 0)) - tipo_anterior = TipoMovimentoDirecional(comando_anterior.get("tipo", TipoMovimentoDirecional.RodasDianteiras.value)) - - simulacao_latlon = [] - - #mostrar_log(f"previsao_futura em {(t_1 - t_0):.4f}s, correcao_pontos_visitados em {(t_2 - t_1):.4f}") - - if ultimo_ponto: - angulo_final, tipo_final = comando_parado() - parada_necessaria = True - else: - candidatos_ativos = [{ - "x": x, "y": y, "theta": theta, - "custo": 0.0, - "comandos": [(tipo_anterior, angulo_anterior)], - "trajetoria": [], - "visitados": pts_visitados, - "inicial": True - }] - - # quantas expansões cabem no tempo restante deste ciclo - est = max(1.0, getattr(self, "_t_est_passo_ms", 6.0)) - exp_budget = max(4, int(ms_left() // est)) - - #print(f"Comecando, idx_proximo_ponto_real: {idx_proximo_ponto_real}, idx_alvo_correcao: {idx_alvo_correcao}") - for passo in range(self.qtd_comandos_sucessivos): - if ms_left() <= 0: - break - novos_candidatos = [] - for candidato in candidatos_ativos: - # encerra passo se orçamento acabou - if exp_budget <= 0 or ms_left() <= 0: - break - x_atual, y_atual, theta_atual = candidato["x"], candidato["y"], candidato["theta"] - visitados = candidato["visitados"].copy() - cmd_anterior = { - "tipo": candidato["comandos"][-1][0], - "angulo": candidato["comandos"][-1][1], - } - idx_alvo = self._corrigir_pontos_visitados(x_atual, y_atual, visitados) - #if passo == 0 and idx_alvo < idx_ponto_alvo: - # print(f"ponto alvo alterado de {idx_alvo} para {idx_ponto_alvo}") - # idx_alvo = idx_ponto_alvo - if idx_alvo < len(self.pontos_info) - 1: - idx_alvo = idx_alvo + 1 - ponto_alvo = self.pontos_info[idx_alvo] - tipos, angs, custos_candidatos = self._gerar_angulos_candidatos_receding(ponto_alvo, (x_atual, y_atual, theta_atual), (x, y, theta), contexto, deadline, 15.0) - if ms_left() <= 0 or exp_budget <= 0: - break - - # ---------- INÍCIO BLOCO SEM THREADS ---------- - ang_array = np.asarray(angs, dtype=np.float32) - graus_r = np.round(np.degrees(ang_array), 2) - - pairs_tipo, pairs_ang, pairs_heur = [], [], [] - - for tipo in tipos: - tv = tipo.value - # heurísticos para TODOS os ângulos deste tipo - h_tmp = np.array( - [float(custos_candidatos.get((tv, float(g)), 0.0)) for g in graus_r], - dtype=np.float32 - ) - pairs_tipo.append([tipo] * ang_array.size) - pairs_ang.append(ang_array) # sem copy - pairs_heur.append(h_tmp) - - if not pairs_tipo: - continue - - from itertools import chain - tipos_flat = list(chain.from_iterable(pairs_tipo)) - angs_flat = np.concatenate(pairs_ang, axis=0) - heur_flat = np.concatenate(pairs_heur, axis=0) - - if heur_flat.size == 0: - continue - - ord_idx = np.argsort(heur_flat) - - tempo_util_ms = max(0.0, ms_left() - 10.0) - est_local = max(1.0, min(getattr(self, "_t_est_passo_ms", 6.0), 20.0)) - Kmax = 12 - Kdyn = int(min(Kmax, max(3, tempo_util_ms // est_local))) - Kdyn = min(Kdyn, ord_idx.size) - - melhor_custo_local = float("inf") - - for k in range(Kdyn): - if ms_left() <= 0 or exp_budget <= 0: - break - - i = int(ord_idx[k]) - tipo_k = tipos_flat[i] - ang_k = float(angs_flat[i]) - heur_k = float(heur_flat[i]) - - if (candidato["custo"] + heur_k) > (melhor_custo_local * 1.20) and ms_left() < 2*est_local: - continue - - t_c_ini = now() - try: - custo, sim, valido, visitados_sim = self._simular_passo( - x_atual, y_atual, theta_atual, - tipo_k, ang_k, - custos_candidatos, - cmd_anterior, contexto, - visitados # <- sem copy aqui - ) - if valido: - x_f, y_f, theta_f = sim[-1] - novo = { - "x": x_f, "y": y_f, "theta": theta_f, - "custo": candidato["custo"] + float(custo), - "comandos": candidato["comandos"] + [(tipo_k, ang_k)], - "trajetoria": candidato["trajetoria"] + sim, - "visitados": visitados_sim, - "inicial": False - } - novos_candidatos.append(novo) - if novo["custo"] < melhor_custo_local: - melhor_custo_local = novo["custo"] - except Exception as e: - mostrar_log(f"Erro ao simular passo (sem threads) {tipo_k.name} | {np.degrees(ang_k):.2f}: {e}") - finally: - dt_ms = (now() - t_c_ini) * 1000.0 - alpha = getattr(self, "_ema_alpha", 0.2) - self._t_est_passo_ms = (1.0 - alpha)*getattr(self, "_t_est_passo_ms", 6.0) + alpha*dt_ms - exp_budget -= 1 - # ---------- FIM BLOCO SEM THREADS ---------- - - if exp_budget <= 0: - pass # apenas segue para seleção dos melhores - - if exp_budget <= 0 or ms_left() <= 0: - break # sai do laço de passos - - # Filtro opcional: limitar para os N melhores candidatos - candidatos_ativos = self._filtrar_por_margem_angular(novos_candidatos, margem_graus=2.0) - N_top = 5 if exp_budget > 6 else 3 - candidatos_ativos = self._selecionar_melhores(candidatos_ativos, N=N_top) - - candidatos_validos = [c for c in candidatos_ativos if not c.get("inicial", False)] - if len(candidatos_validos) > 0: - try: - melhor = min(candidatos_validos, key=lambda c: c["custo"]) - except Exception as e: - mostrar_log(f"Erro ao selecionar melhor candidato: {e}") - melhor = None - else: - melhor = None - parada_necessaria = melhor is None - if not parada_necessaria: - _comandos = melhor.get("comandos", []) - if len(_comandos) == 0: - pass - else: - idx_cmd = 0 if len(_comandos) == 1 else 1 - tipo_final, angulo_final = _comandos[idx_cmd] - simulacao_latlon = list(self.gps_handler.converter_trajetoria_para_latlon(melhor["trajetoria"]) or []) - simulacao_latlon.insert(0, (pos_lat, pos_lon, pos_theta)) - else: - angulo_final = 0 - tipo_final = TipoMovimentoDirecional.RodasDianteiras - simulacao_latlon = [] - #print(f"Simulacao: {len(simulacao_latlon)}") - _cmd = { - "enviar_comando": True, - "parada_necessaria": parada_necessaria, - "erro": False, - "latencia": pos_latencia, - "angulo": float(round(np.degrees(angulo_final), 2)), - "tipo": tipo_final.value, - "simulacao": simulacao_latlon - } - - - self._tick_id = getattr(self, "_tick_id", 0) + 1 - if (getattr(self, "debug_cost_vis", False) - and contexto.get("RegrasAtivas", {}).get("matriz_custo", False) - and (self._tick_id % 10 == 0)): - dados_matriz_custo = contexto.get("VisualWorker", {}).get("MatrizCusto", {}) - # reconstroi set de candidatos só pra plot, com orçamento curtinho - deadline_dbg = time.perf_counter() + 0.03 # ~30 ms pra não pesar - tipos_dbg, angs_dbg, _ = self._gerar_angulos_candidatos_receding( - ponto_alvo=self.pontos_info[idx_alvo_correcao], - ponto_atual=(x, y, theta), - ponto_ref=(x, y, theta), - contexto=contexto, - deadline=deadline_dbg, - margem_ms=8.0, - ) - angs_dbg_deg = [round(float(np.degrees(a)), 2) for a in angs_dbg] - self.debug_plot_matriz_custo( - dados_matriz_custo, - tipos_dbg, - angs_dbg_deg, - max_linhas=3, - titulo=f"debug_cost_{int(self._tick_id):06d}.png", - highlight=(tipo_final.value, round(float(np.degrees(angulo_final)), 2)), - ) - - - return _cmd - - except Exception as e: - mostrar_log(f"❌ Erro ao processar MPC: {e}") - return self._comando_fallback_hot_stop(comando_anterior, latencia=pos_latencia) - def _processar_mpc_receding(self, contexto, comando_anterior): now = time.perf_counter t0 = now() @@ -1127,6 +846,18 @@ class ControladorMPC: # >>> escolha K dentro do [K_lb, K_cap]; pacing do orçamento vem depois K = max(K_lb, min(K_cap, K_ALVO)) + beam_traj_min = int(getattr(self, "_beam_traj_min", 3)) + # custo bruto para levar beam_traj_min trajetórias até K passos + exp_min_full = beam_traj_min * K + if exp_budget < exp_min_full: + # aqui temos três opções, em ordem: + # 1) reduzir beam_traj_min, mas garantir pelo menos 1 traj completa + beam_traj_min = max(1, exp_budget // max(1, K)) + # 2) se mesmo assim ficar ridículo, melhor nem recalcular nada e reaproveitar o comando anterior + if beam_traj_min <= 0: + # fallback suave: continua com comando_anterior + return comando_anterior + # dt para que K passos cubram S (agora garantido dentro de [DT_MIN, DT_MAX]) dt_pred = (S_ALVO / (v_sim * K)) dt_pred = max(DT_MIN, min(dt_pred, DT_MAX)) @@ -1221,6 +952,18 @@ class ControladorMPC: Kmax = 12 Kdyn = int(min(Kmax, max(3, tempo_util_ms // est_local))) Kdyn = min(Kdyn, ord_idx.size) + + passos_restantes = self.qtd_comandos_sucessivos - passo + if passos_restantes <= 0: + break + # quantas expansões mínimas queremos garantir por passo + traj_ativas = max(1, len(candidatos_ativos)) + exp_min_por_passo = traj_ativas # pelo menos 1 ângulo por candidato + # quantas expansões ainda cabem, por passo restante + exp_por_passo = max(1, exp_budget // passos_restantes) + # Kdyn não pode passar do que cabe no orçamento + Kdyn_orc = max(1, exp_por_passo // max(1, traj_ativas)) + Kdyn = int(min(Kdyn, Kdyn_orc, ord_idx.size)) melhor_custo_local = float("inf") @@ -1274,9 +1017,20 @@ class ControladorMPC: break # Filtro de diversidade angular e top-N + #candidatos_ativos = self._filtrar_por_margem_angular(novos_candidatos, margem_graus=2.0) + #N_top = 5 if exp_budget > 6 else 3 + #candidatos_ativos = self._selecionar_melhores(candidatos_ativos, N=N_top) + beam_topN_max = int(getattr(self, "_beam_topN_max", 5)) + beam_topN_min = int(getattr(self, "_beam_topN_min", 2)) candidatos_ativos = self._filtrar_por_margem_angular(novos_candidatos, margem_graus=2.0) - N_top = 5 if exp_budget > 6 else 3 - candidatos_ativos = self._selecionar_melhores(candidatos_ativos, N=N_top) + # número alvo de trajetórias ativas + #N_alvo = min(beam_topN_max, max(beam_topN_min, beam_traj_min)) + beam_traj_min = max(1, min(beam_traj_min, beam_topN_max)) # sanity + # número alvo de trajetórias ativas: não pode passar de beam_traj_min + N_alvo = min(beam_traj_min, beam_topN_max) + # se quiser um piso suave: + N_alvo = max(1, N_alvo) + candidatos_ativos = self._selecionar_melhores(candidatos_ativos, N=N_alvo) candidatos_validos = [c for c in candidatos_ativos if not c.get("inicial", False)] if len(candidatos_validos) > 0: @@ -1319,7 +1073,8 @@ class ControladorMPC: "simulacao": simulacao_latlon, "erro_lateral": erro_lateral, "erro_orientacao": erro_orientacao, - "debug_custo": debug_custo + "debug_custo": debug_custo, + "candidatos_testados": K } # -------------------- Debug opcional da matriz de custo -------------------- @@ -1369,7 +1124,10 @@ class ControladorMPC: "angulo": comando_anterior.get("angulo", 0), "tipo": comando_anterior.get("tipo", TipoMovimentoDirecional.RodasDianteiras.value), "simulacao": [], - "erro_latreral": 0 + "erro_latreral": 0, + "erro_orientacao": 0, + "debug_custo": {}, + "candidatos_testados": 0 } return _cmd @@ -2149,103 +1907,6 @@ class ControladorMPC: mostrar_log(f"❌ Erro ao filtrar por margem angular: {e}") return candidatos - def _simular_passo_old(self, x, y, theta, tipo, angulo_testado, custos_candidatos, comando_anterior, contexto, visitados, dt_pred, v_planejado): - """ - Simula UM 'passo' do receding (um comando) cobrindo dt_pred de tempo, - subdividido em passos menores (sub_dt) para estabilidade geométrica. - O custo é acumulado 'por metro' (multiplicando por v_planejado * sub_dt). - """ - try: - custo_total = 0.0 - x_sim, y_sim, theta_sim = x, y, theta - self.x_ant, self.y_ant = 0.0, 0.0 - - # chave para custo heurístico vindo do VisualWorker (por ângulo/tipo) - chave = (tipo.value, round(float(np.degrees(angulo_testado)), 2)) - custo_visual_worker = float(custos_candidatos.get(chave, 0.0)) - - simulacoes = [] - prev_ang = float(comando_anterior.get("angulo", 0.0)) - prev_tipo = comando_anterior.get("tipo", TipoMovimentoDirecional.RodasDianteiras.value) - pontos_visitados = visitados.copy() - - # Contexto usado no custo - angulo_caminho = np.radians(contexto.get("Carro", {}).get("AnguloCaminho", 0.0)) - status_carro = StatusCarroMapa(contexto.get("Carro", {}).get("Status", StatusCarroMapa.Parado.value)) - dentro_corredor = bool(contexto.get("Carro", {}).get("DentroCorredor", False)) - - # omega e sub-stepping - omega_const = self.gps_handler.calcular_omega(v_planejado, angulo_testado, tipo) - - # Se alguém setar self.passos_horizonte_local > 1, a gente cobre tudo em dt_total: - passos_local = max(1, int(getattr(self, "passos_horizonte_local", 1))) - dt_total = float(dt_pred) * passos_local - - SUB_MAX = float(getattr(self, "_dt_sub_max", 0.15)) # ~80 ms por subpasso - n_sub = max(1, int(math.ceil(dt_total / SUB_MAX))) - sub_dt = dt_total / n_sub - dist_sub = v_planejado * sub_dt # usado para custo por metro - - for _ in range(n_sub): - # IMPORTANTE: _nova_posicao precisa aceitar dt opcional (ver nota abaixo) - x_sim, y_sim, theta_sim = self._nova_posicao( - x_sim, y_sim, theta_sim, - omega_const, v_planejado, # ordem original: (omega, v, tipo, angulo) - tipo, angulo_testado, - dt=sub_dt # <<--- dt variável - ) - - simulacoes.append((x_sim, y_sim, theta_sim)) - - # alvo mais próximo após avançar - idx_alvo_sim = self._corrigir_pontos_visitados(x_sim, y_sim, pontos_visitados, velocidade=v_planejado, dt=sub_dt) - ponto_alvo_sim = self.pontos_info[idx_alvo_sim]["xy"] - - # orientação do caminho + erro angular combinado - orient_sim = self.gps_handler.calcular_orientacao((x_sim, y_sim), ponto_alvo_sim) - orient_sim = (orient_sim + np.pi) % (2 * np.pi) - - # erros - erro_pos = float(np.linalg.norm([x_sim - ponto_alvo_sim[0], y_sim - ponto_alvo_sim[1]])) - peso_erro_orientacao_caminho = 0.3 if (status_carro == StatusCarroMapa.CaminhandoRua and dentro_corredor) else 0.7 - erro_ori_sim = self.gps_handler.erro_angular(orient_sim, theta_sim, angulo_caminho, peso_erro_orientacao_caminho) - erro_lateral = self.cross_track_error_point(x_sim, y_sim)[0] - - # pesos dinâmicos - pesos = self._calcular_pesos_movimento(contexto, erro_ori_sim) - peso_erro_pos, peso_erro_ori, peso_suavidade, peso_fator_re, peso_ideal, peso_lateral, peso_movimento = pesos - - # ângulo relativo ao alvo e suavidade - vetor_alvo = np.array(ponto_alvo_sim) - np.array([x_sim, y_sim]) - vetor_alvo_norm = vetor_alvo / (np.linalg.norm(vetor_alvo) + 1e-9) - vetor_movel = np.array([np.cos(theta_sim), np.sin(theta_sim)]) - cos_angulo = -float(np.dot(vetor_movel, vetor_alvo_norm)) - delta_angulo = abs(angulo_testado - prev_ang) - - # componentes de custo - custo_pos = erro_pos * peso_erro_pos - custo_ori = ((erro_ori_sim / np.pi) * erro_pos) * peso_erro_ori - custo_suavidade = ((delta_angulo / np.pi) * erro_pos) * peso_suavidade - custo_tipo_movimento = float(peso_movimento[tipo]) - erro_re = (1.0 - cos_angulo) if cos_angulo > 0 else cos_angulo - custo_re = -erro_re * erro_pos * peso_fator_re - custo_lateral = abs(erro_lateral) * peso_lateral - - # soma local (heurística do visual + demais), e NORMALIZA por metro - custo_mapa = (custo_pos + custo_ori + custo_suavidade + custo_tipo_movimento + custo_re + custo_lateral + custo_visual_worker) - custo_total += custo_mapa * dist_sub # <<< custo POR METRO - - #print(f"Angulo: {np.degrees(angulo_testado):.2f}, Tipo: {tipo.name}, Theta: {np.degrees(theta):.2f}, ep: {erro_pos:.4f}, eo: {erro_ori_sim:.4f}, er: {erro_re:.4f}, el: {erro_lateral:.4f}") - - prev_ang = angulo_testado - prev_tipo = tipo - - return float(custo_total), simulacoes, True, pontos_visitados - - except Exception as e: - mostrar_log(f"Erro ao simular passo para {tipo.name} | angulo: {np.degrees(angulo_testado):.2f}: {e}") - return float('inf'), [(0.0, 0.0, 0.0)], False, visitados - def _simular_passo(self, x, y, theta, tipo, angulo_testado, custos_candidatos, comando_anterior, contexto, visitados, dt_pred, v_planejado, passo=-1): """ Simula UM 'passo' do receding cobrindo dt_pred, subdividido em subpassos. @@ -2463,18 +2124,6 @@ class ControladorMPC: mostrar_log(f"Erro ao simular passo para {tipo.name} | angulo: {np.degrees(angulo_testado):.2f}: {e}") return float('inf'), [(0.0, 0.0, 0.0)], False, visitados - def _nova_posicao_old(self, x, y, theta, omega, velocidade, tipo, angulo_rad, dt=None): - """ - Atualiza a pose integrando por 'dt' (se None, cai em self.dt). - Mantém a ordem dos parâmetros antigos para não quebrar chamadas existentes. - """ - dt_use = self.dt if (dt is None) else float(dt) - distancia_m = velocidade * dt_use - theta_sim = theta + (omega * dt_use) - x_sim = x + (np.sin(theta_sim) * distancia_m) - y_sim = y + (np.cos(theta_sim) * distancia_m) - return x_sim, y_sim, theta_sim - def _nova_posicao(self, x, y, theta, omega, velocidade, tipo, angulo_rad, dt=None): dt_use = self.dt if (dt is None) else float(dt) theta_next = theta + omega * dt_use # orientação do corpo (no diagonal, ω≈0 → mantém) diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py new file mode 100644 index 000000000..2dbda8e52 --- /dev/null +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/modulos/regras_taticas.py @@ -0,0 +1,51 @@ +import time +from shared.enums import StatusModulo, StatusOperacao, T_Code +from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey +from manager_worker.config import mostrar_log + +def verifica_controle_liberado(): + try: + motivos = [] + _operacao = ContextoGlobalRedis.get_operacao() + status_operacao = StatusOperacao(_operacao.get("status", StatusOperacao.NaoIniciado.value)) + finalizando = _operacao.get("finalizando", False) + + if (status_operacao != StatusOperacao.EmAndamento) or finalizando: + motivos.append(f"Operação não está em andamento ou finalizando: {status_operacao.name}") + + _controle = ContextoGlobalRedis.get_controle() + + oak_parada_por_bloqueio = _controle.get("oak_parada_por_bloqueio", False) + if oak_parada_por_bloqueio: + _dados_vw = ContextoGlobalRedis.get(CtxKey.DadosVisualWorker, {}) + _snr = ContextoGlobalRedis.get_modulo(T_Code.Snr) + _snr_saude = StatusModulo(_snr.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value)) + visual_worker_operante = _snr_saude == StatusModulo.OPERANTE + analise_deteccao_atualizada = (time.perf_counter() - _dados_vw.get("matriz_confianca", {}).get("ts", 10.0) <= 1.0) + obstaculo_detectado = _dados_vw.get("matriz_confianca", {}).get("block", {}).get("decision", {}).get("parar", False) if analise_deteccao_atualizada else False + + if (not visual_worker_operante): + motivos.append(f"Sonar mandatório não operante: {_snr_saude.name}") + elif (visual_worker_operante and obstaculo_detectado): + motivos.append(f"Obstáculo próximo detectado no sonar") + + imu_parada_por_inclinacao = _controle.get("imu_parada_por_inclinacao", False) + if imu_parada_por_inclinacao: + _imu = ContextoGlobalRedis.get_modulo(T_Code.Imu) + _imu_saude = StatusModulo(_imu.get("saude", {}).get("status", StatusModulo.DESCONECTADO.value)) + imu_operante = _imu_saude == StatusModulo.OPERANTE + _equipamento = ContextoGlobalRedis.get_equipamento() + ang_roll_max = _equipamento.get("angulo_roll_max", 15.0) + ang_pitch_max = _equipamento.get("angulo_pitch_max", 30.0) + inclinacao_perigosa = abs(_imu.get("pitch", 0.0)) > ang_pitch_max or abs(_imu.get("roll", 0.0)) > ang_roll_max + + if not imu_operante: + motivos.append(f"IMU mandatório não operante: {_imu_saude.name}") + elif imu_operante and inclinacao_perigosa: + motivos.append(f"Inclinação perigosa detectada. roll: {_imu.get('roll')}, pitch: {_imu.get('pitch')}, yaw: {_imu.get('yaw')}") + + return motivos + + except Exception as e: + mostrar_log(f"Erro ao verificar liberacao do controle: {e}") + diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_0_nao_iniciado.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_0_nao_iniciado.py index 9c7f4093e..8a1b274d8 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_0_nao_iniciado.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_0_nao_iniciado.py @@ -6,4 +6,5 @@ class ProcessadorNaoIniciado(ProcessadorBase): try: return comando_parado() except Exception as e: - print(f"Erro no processador NaoIniciado: {e}") + from manager_worker.config import mostrar_log + mostrar_log(f"Erro no processador NaoIniciado: {e}") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_1_parametrizando.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_1_parametrizando.py index 62e3d771d..ab394ae56 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_1_parametrizando.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_1_parametrizando.py @@ -6,4 +6,5 @@ class ProcessadorParametrizando(ProcessadorBase): try: return comando_parado() except Exception as e: - print(f"Erro no processador Parametrizando: {e}") + from manager_worker.config import mostrar_log + mostrar_log(f"Erro no processador Parametrizando: {e}") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_2_calibrando.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_2_calibrando.py index 017b866b9..a85bd57f2 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_2_calibrando.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_2_calibrando.py @@ -6,4 +6,5 @@ class ProcessadorCalibrando(ProcessadorBase): try: return comando_parado() except Exception as e: - print(f"Erro no processador Calibrando: {e}") + from manager_worker.config import mostrar_log + mostrar_log(f"Erro no processador Calibrando: {e}") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_3_aguardando.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_3_aguardando.py index fcd5085bc..09b792d4d 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_3_aguardando.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_3_aguardando.py @@ -6,4 +6,5 @@ class ProcessadorAguardando(ProcessadorBase): try: return comando_parado() except Exception as e: - print(f"Erro no processador Aguardando: {e}") + from manager_worker.config import mostrar_log + mostrar_log(f"Erro no processador Aguardando: {e}") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_4_em_andamento.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_4_em_andamento.py index 68fbe85e4..d51dbd57f 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_4_em_andamento.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_4_em_andamento.py @@ -1,9 +1,11 @@ import time +from shared.enums import TipoMovimentoDirecional from shared.contexto_global_redis import ContextoGlobalRedis from manager_worker.modulos.pid import PIDAdaptativo from .base import ProcessadorBase from manager_worker.filtros import FiltroVelocidade from manager_worker.processadores.padroes import comando_controle +from manager_worker.modulos.regras_taticas import verifica_controle_liberado from manager_worker.modulos.direcional import definir_comando as definir_comando_dir from manager_worker.modulos.movimentacao import definir_comando as definir_comando_mov @@ -28,23 +30,50 @@ class ProcessadorEmAndamento(ProcessadorBase): try: agora = time.perf_counter() envio_necessario = (agora - self.ultimo_comando_enviado) > 0.3 - comando_dir = definir_comando_dir(self.pid_dir, envio_necessario) - if comando_dir.get("enviar_comando", False): - self.ultimo_comando_enviado = agora - custos = comando_dir.get("debug_custo", {}) - e_ori = custos.get(f"{comando_dir['tipo']}_{comando_dir['angulo']:.2f}", {}).get("erro_orientacao", None) or None - comando_mov = definir_comando_mov(comando_dir.get("parada_necessaria", False), comando_dir.get("erro", False), self.filtro_mov, erro_orientacao=e_ori) + + motivos_parada = verifica_controle_liberado() + if len(motivos_parada) > 0: + from manager_worker.config import mostrar_log + mostrar_log(f"⛔ Controle bloqueado: {' | '.join(motivos_parada)}") return comando_controle( - percentual_velocidade=comando_mov.get("velocidade"), - frear=comando_mov.get("frear", False), - angulo=comando_dir.get("angulo"), - tipo_movimento=comando_dir.get("tipo"), - simulacao=comando_dir.get("simulacao"), + percentual_velocidade=0, + frear=True, + angulo=0, + tipo_movimento=TipoMovimentoDirecional.RodasDianteiras.value, + simulacao=[], + erro=False, + latencia=0, + erro_lateral=0, + debug_custo={} + ) + + _controle = ContextoGlobalRedis.get_controle() + comando_mov = {} + movimento_automatico = _controle.get("movimento_automatico", False) + if movimento_automatico: + comando_mov = definir_comando_mov(self.filtro_mov) + + comando_dir = {} + direcional_automatico = _controle.get("direcional_automatico", False) + if direcional_automatico: + comando_dir = definir_comando_dir(self.pid_dir, envio_necessario) + + enviar_comando = (direcional_automatico and comando_dir.get("enviar_comando", False)) or not direcional_automatico + + if enviar_comando: + self.ultimo_comando_enviado = agora + return comando_controle( + percentual_velocidade=comando_mov.get("velocidade", 0), + frear=comando_dir.get("parada_necessaria", False), + angulo=comando_dir.get("angulo", 0), + tipo_movimento=comando_dir.get("tipo", TipoMovimentoDirecional.RodasDianteiras.value), + simulacao=comando_dir.get("simulacao", []), erro=comando_dir.get("erro", False), latencia=comando_dir.get("latencia", 0.0), erro_lateral=comando_dir.get("erro_lateral", 0.0), debug_custo=comando_dir.get("debug_custo", {}) ) except Exception as e: - print(f"Erro no processador EmAndamento: {e}") + from manager_worker.config import mostrar_log + mostrar_log(f"Erro no processador EmAndamento: {e}") return None diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_5_parado.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_5_parado.py index c246ffaae..08bf0deea 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_5_parado.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_5_parado.py @@ -6,4 +6,5 @@ class ProcessadorParado(ProcessadorBase): try: return comando_parado() except Exception as e: - print(f"Erro no processador Parado: {e}") + from manager_worker.config import mostrar_log + mostrar_log(f"Erro no processador Parado: {e}") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_6_concluido.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_6_concluido.py index a39e283d0..a275be2e7 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_6_concluido.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/_6_concluido.py @@ -6,4 +6,5 @@ class ProcessadorConcluido(ProcessadorBase): try: return comando_parado() except Exception as e: - print(f"Erro no processador Concluido: {e}") + from manager_worker.config import mostrar_log + mostrar_log(f"Erro no processador Concluido: {e}") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/padroes.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/padroes.py index b974f29dc..9983333fd 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/padroes.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/manager_worker/processadores/padroes.py @@ -4,13 +4,15 @@ from manager_worker.config import mostrar_log from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey def comando_controle(percentual_velocidade: float, frear: bool, angulo: float, tipo_movimento: int, simulacao = [], erro: bool = False, latencia: float = 0.0, erro_lateral: float = 0.0, debug_custo: dict = {}): - hb_atual = ContextoGlobalRedis.get_controle().get("heartbeat", 0) + _controle = ContextoGlobalRedis.get_controle() + hb_atual = _controle.get("heartbeat", 0) + hb_novo = hb_atual if erro == False: try: - hb_atual = int(hb_atual) % 10 + hb_novo = int(hb_novo) % 10 except: - hb_atual = 0 - hb_atual = (hb_atual + 1) % 10 + hb_novo = 0 + hb_novo = (hb_novo + 1) % 10 ContextoGlobalRedis.atualizar_ctx_dict( CtxKey.DadosControle, @@ -19,7 +21,7 @@ def comando_controle(percentual_velocidade: float, frear: bool, angulo: float, t velocidade_sp=percentual_velocidade, em_freio=frear, simulacao=simulacao, - heartbeat=hb_atual, + heartbeat=hb_novo, latencia=latencia, erro_lateral=erro_lateral, debug_custo=debug_custo @@ -30,7 +32,7 @@ def comando_controle(percentual_velocidade: float, frear: bool, angulo: float, t "angulo_sp": angulo, "tipo_movimento_direcional": tipo_movimento, "simulacao": simulacao, - "heartbeat": hb_atual, + "heartbeat": hb_novo, "latencia": latencia, "erro_lateral": erro_lateral, "debug_custo": debug_custo diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py index f612d0a8d..b33021457 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/contexto_global_redis.py @@ -478,6 +478,15 @@ class ContextoGlobalRedis: if (iniciado and not status_iniciado_anterior): cls._iniciar_operacao() + # Não está liberado para operação + if not op_liberada: + if status_atual != StatusOperacao.Parado: + cls.atualizar_ctx_dict(CtxKey.DadosOperacao, status_anterior_parado=status_atual.value) + mostrar_log(f"Operacao Parada! {_operacao.get('motivo_nao_liberado')}") + if status_atual != StatusOperacao.Parado: + cls.atualizar_ctx_dict(CtxKey.DadosOperacao, status=StatusOperacao.Parado.value) + return + # Verifica se ainda está aguardando tempo inicial tempo_aguardando = cls.get_operacao().get("tempo_aguardando", 0) em_espera = (tempo_aguardando + _operacao.get("tempo_aguardar_inicio_operacao", 25)) > agora @@ -496,15 +505,6 @@ class ContextoGlobalRedis: cls._finalizar_operacao() return - # Não está liberado para operação - if not op_liberada: - if status_atual != StatusOperacao.Parado: - cls.atualizar_ctx_dict(CtxKey.DadosOperacao, status_anterior_parado=status_atual.value) - mostrar_log(f"Operacao Parada! {_operacao.get('motivo_nao_liberado')}") - if status_atual != StatusOperacao.Parado: - cls.atualizar_ctx_dict(CtxKey.DadosOperacao, status=StatusOperacao.Parado.value) - return - # Estava parado e liberou: volta para aguardando if status_atual == StatusOperacao.Parado: cls.atualizar_ctx_dict( diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/enums.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/enums.py index c7973ec99..f09f7edc9 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/enums.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/enums.py @@ -172,13 +172,6 @@ class TipoPontoRua(IntEnum): CruvaEntreCorredores = 6 Desvio = 7 -class CameraFrameType(IntEnum): - Rgb = 1 - Heatmap = 2 - RadarTopDown = 3 - Segmentacao = 4 - Debug = 5 - class TipoFrameCamera(IntEnum): Rgb = 0 Segmentacao = 1 @@ -188,3 +181,4 @@ class TipoFrameCamera(IntEnum): MatrizCusto = 5 Deteccoes = 6 Corredor = 7 + Raw4 = 8 diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/utils.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/utils.py index d920eaec3..7178853cf 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/utils.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/shared/utils.py @@ -244,3 +244,23 @@ def get_velocidade_atual_ms(): mostrar_log(f"Erro ao consultar velocidade atual: {e}") finally: return velocidade + + + +def resize_frame(frame_bgr, max_width=640, max_height=360): + h, w = frame_bgr.shape[:2] + + # se já está menor que o limite, não faz nada + if w <= max_width and h <= max_height: + return frame_bgr + + # escala baseada em qual limite "aperta" primeiro + scale_w = max_width / w + scale_h = max_height / h + scale = min(scale_w, scale_h) + + new_w = int(w * scale) + new_h = int(h * scale) + + frame_resized = cv2.resize(frame_bgr, (new_w, new_h), interpolation=cv2.INTER_AREA) + return frame_resized 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 1995fc474..2217afa3b 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 @@ -5,18 +5,13 @@ import time from concurrent.futures import ThreadPoolExecutor import cv2 -import cupy as cp import numpy as np -from visual_worker.utils import calcular_threshold_anomalias, converter_valores_numpy, gerar_heatmap -from visual_worker.processamento.analise_solo import AnaliseSoloManager -from visual_worker.processamento.analise_anomalias import AnaliseAnomaliasManager -from visual_worker.processamento.radar_top_down import Radar2DManager +from visual_worker.utils import converter_valores_numpy, gerar_heatmap from visual_worker.processamento.segmentacao_semantica import ClassesSegmentacao, SegmentacaoManager from camera_worker.segformer_runner import SegformerNavRunner from visual_worker.processamento.costmap_fuser import CostmapFuser, unpack_snapshot from shared.enums import StatusModulo, T_Code, TipoFrameCamera -from shared.utils import analisar_linhas_por_profundidade, converter_mask_ids_para_bgr, decode_image_base64, encode_image_base64, fazer_overlay, get_velocidade_atual_ms -from shared.gps_handler import GPSHandler +from shared.utils import converter_mask_ids_para_bgr, get_velocidade_atual_ms from camera_worker.camera_oak import CameraOak from shared.contexto_global_redis import ContextoGlobalRedis, CtxKey @@ -120,7 +115,7 @@ class CameraManager: self._analisando_deteccao = False self._iniciar_loop_analise_continua(15.0) - self._iniciar_loop_frame_stream(5.0) + self._iniciar_loop_frame_stream(self.camera.gst_FPS) self.iniciando = False self.atualizar_saude_camera() @@ -299,10 +294,13 @@ class CameraManager: continue t0 = time.time() try: - _frame_type = (TipoFrameCamera)((ContextoGlobalRedis.get_camera(self.mx_id) or {}).get("frame_type", TipoFrameCamera.Rgb.value)) - _frame = self.get_selected_frame(_frame_type) - if _frame is not None: - self.camera.enviar_frame_stream(_frame) + _camera = (ContextoGlobalRedis.get_camera(self.mx_id) or {}) + _stream_on = _camera.get("streaming", False) + if (_stream_on): + _frame_type = TipoFrameCamera(_camera.get("frame_type", TipoFrameCamera.Rgb.value)) + _frame = self.get_selected_frame(_frame_type) + if _frame is not None: + self.camera.enviar_frame_tcp(_frame) from visual_worker.config import load_seg_config, load_det_config seg_config = load_seg_config() diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/main.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/main.py index 35795ee1e..9e526f500 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/main.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/main.py @@ -51,15 +51,16 @@ def main(): get_camera_manager().atualizar_saude_camera() elif acao == VisualWorkerCommandType.GetCameraFrame: tipo = TipoFrameCamera(dados.get("params", TipoFrameCamera.Rgb.value)) - frame, ts = get_camera_manager().get_selected_frame(tipo) - base64_img = encode_image_base64(frame) - if base64_img is not None: - resposta = { - "frame": base64_img, - "timestamp": ts, - "tipo": tipo.value - } - ContextoGlobalRedis.publicar_comando(CmdKey.VisualWorkerTx, { "cmd": VisualWorkerCommandType.GetCameraFrame.value, "params": resposta }) + frame = get_camera_manager().get_selected_frame(tipo) + if frame is not None: + base64_img = encode_image_base64(frame) + if base64_img is not None: + resposta = { + "frame": base64_img, + "timestamp": time.time(), + "tipo": tipo.value + } + ContextoGlobalRedis.publicar_comando(CmdKey.VisualWorkerTx, { "cmd": VisualWorkerCommandType.GetCameraFrame.value, "params": resposta }) elif acao == VisualWorkerCommandType.SaveCameraFrames: nome = dados.get("params", {}).get("nome", "") pasta = dados.get("params", {}).get("caminho", "frames_salvos") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/segmentacao_semantica.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/segmentacao_semantica.py index 8ee410cc0..343d90374 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/segmentacao_semantica.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/visual_worker/processamento/segmentacao_semantica.py @@ -47,6 +47,7 @@ class SegmentacaoManager: # tamanho máximo da deque (fallback se o FPS variar) self.max_len = max_len or int(self.janela_s * fps_esperado * 1.5) self._status_hist = deque(maxlen=self.max_len) + self._status_final_hist = deque(maxlen=2) def segmentar(self, predictions): @@ -190,7 +191,7 @@ class SegmentacaoManager: lat_out = round(float(self._ema_lat), 3) mask_nav = (self.predictions == ClassesSegmentacao.NAVEGAVEL.value) - status_now, status_final, prob, debug = self.classificar_status_corredor(mask_nav) + status_now, status_final, status_before, prob, debug = self.classificar_status_corredor(mask_nav) return { "timestamp": time.time(), @@ -199,6 +200,7 @@ class SegmentacaoManager: "erro_angular": ang_out, "erro_lateral_pct": lat_out, "status_corredor": status_final.value, + "status_corredor_anterior": status_before.value, "centros_corredor": centros, "larguras_px": larguras, "confianca": round(float(score), 3), @@ -446,8 +448,10 @@ class SegmentacaoManager: # Histerese temporal: mantém teu esquema de histórico self._status_hist.append((status_now, self._now())) status_final = self._maioria_ultimos() + self._status_final_hist.append(status_final) + status_before = self._status_final_hist[0] if len(self._status_final_hist) > 1 else status_final - return status_now, status_final, probs, debug + return status_now, status_final, status_before, probs, debug @staticmethod def _now(): diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/camera_manager.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/camera_manager.py index b625844dd..5889c6528 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/camera_manager.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/camera_manager.py @@ -4,9 +4,9 @@ import threading import time import cv2 +import numpy as np from camera_worker.raw_segformer_service import RawSegformerService from shared.enums import StatusModulo, StatusOperacao, T_Code, TipoFrameCamera, WeedWorkerCommandType -from shared.utils import decode_image_base64, encode_image_base64, fazer_overlay from camera_worker.camera_gal import CameraGal from shared.contexto_global_redis import CmdKey, ContextoGlobalRedis, CtxKey from weed_worker.weed_detector import WeedDetector @@ -28,6 +28,7 @@ class CameraManager: self._ts_segmentacao_anterior = 0 self._ts_ultima_analise = 0 self._ultimo_predictions = None + self._ultimo_raw_base = None self._ultimo_raw_input = None self._ultimo_controle = None self._analisando_segmentacao = False @@ -67,6 +68,7 @@ class CameraManager: self._ultima_analise = {} self._ultimo_rgb_frame = None self._ultimo_predictions = None + self._ultimo_raw_base = None self._ultimo_raw_input = None self._ultimo_controle = None self._analisando_segmentacao = False @@ -77,7 +79,7 @@ class CameraManager: self.weed_detector = WeedDetector(color_map=colormap_rgb, classes=classes) self._iniciar_loop_analise_continua(20.0) - self._iniciar_loop_frame_stream(5.0) + self._iniciar_loop_frame_stream(self.camera.gst_FPS) self.iniciando = False self.atualizar_saude_camera() @@ -127,12 +129,11 @@ class CameraManager: t2 = time.time() predictions = self.model_svc.infer_raw(raw_input) ts = time.time() - res = { - "raw_input": raw_input - } + res = {} - self._ultimo_predictions = predictions + self._ultimo_raw_base = raw4_base self._ultimo_raw_input = raw_input + self._ultimo_predictions = predictions #print(f"[PREDICTIONS] t_total: {ts - t0:.5f} s, t_req: {t1 - t0:.5f} s, t_build_raw: {t2 - t1:.5f} s, t_infer: {ts - t2:.5f} s") @@ -149,15 +150,19 @@ class CameraManager: def get_selected_frame(self, _frame_type: TipoFrameCamera): _frame = None - if (_frame_type == TipoFrameCamera.Rgb): - _frame = self._ultimo_rgb_frame - elif (_frame_type in [TipoFrameCamera.Segmentacao, TipoFrameCamera.Overlay]): - if _frame_type == TipoFrameCamera.Segmentacao: _alpha = 1.0 - elif _frame_type == TipoFrameCamera.Overlay: _alpha = 0.5 - _, _, _frame, _, _ = self.model_svc.preview_infer_cached(self._ultimo_raw_input, self._ultimo_predictions, alpha=_alpha) - elif _frame_type == TipoFrameCamera.Debug: - self.weed_detector._mostrar_debug_bicos_overlay(_frame, [], self._ultimo_controle, show=False) - _frame = self.weed_detector._dbg_img + if (_frame_type in [TipoFrameCamera.Rgb, TipoFrameCamera.Segmentacao, TipoFrameCamera.Overlay, TipoFrameCamera.Debug]): + rgb_frame, seg_frame, overlay_frame, _, _ = self.model_svc.preview_infer_cached(self._ultimo_raw_input, self._ultimo_predictions, alpha=0.5) + if _frame_type == TipoFrameCamera.Rgb: + _frame = rgb_frame + elif _frame_type == TipoFrameCamera.Segmentacao: + _frame = seg_frame + elif _frame_type == TipoFrameCamera.Overlay: + _frame = overlay_frame + elif _frame_type == TipoFrameCamera.Debug: + self.weed_detector._mostrar_debug_bicos_overlay(overlay_frame, [], self._ultimo_controle, show=False) + _frame = self.weed_detector._dbg_img + elif _frame_type == TipoFrameCamera.Raw4: + _frame = self._ultimo_raw_base return _frame def _iniciar_loop_analise_continua(self, freq): @@ -192,16 +197,20 @@ class CameraManager: continue t0 = time.time() try: - _frame_type = (TipoFrameCamera)((ContextoGlobalRedis.get_camera(self.mx_id) or {}).get("frame_type", TipoFrameCamera.Rgb.value)) - _frame = self.get_selected_frame(_frame_type) - if _frame is not None: - self.camera.enviar_frame_stream(_frame) + _camera = (ContextoGlobalRedis.get_camera(self.mx_id) or {}) + _stream_on = _camera.get("streaming", False) + if (_stream_on): + _frame_type = TipoFrameCamera(_camera.get("frame_type", TipoFrameCamera.Rgb.value)) + _frame = self.get_selected_frame(_frame_type) + if _frame is not None: + self.camera.enviar_frame_tcp(_frame) from weed_worker.config import load_seg_config config = load_seg_config() if (config.get("debug_visual")): - _frame = self.get_selected_frame(TipoFrameCamera.Overlay) - self.weed_detector._mostrar_debug_bicos_overlay(_frame, [], self._ultimo_controle, config, show=True) + frame_dbg = self.get_selected_frame(TipoFrameCamera.Overlay) + if frame_dbg is not None: + self.weed_detector._mostrar_debug_bicos_overlay(frame_dbg, [], self._ultimo_controle, config, show=True) except Exception as e: self.mostrar_log(f"Erro no loop de stream: {e}") finally: @@ -215,7 +224,9 @@ class CameraManager: try: t0 = time.time() predictions, ts, res = self.get_segmentation_predictions() - if ts == self._ts_segmentacao_anterior: return # já analisado + if ts == self._ts_segmentacao_anterior: + self._analisando_segmentacao = False + return fps = 1.0 / (ts - self._ts_segmentacao_anterior) self._ts_segmentacao_anterior = ts if predictions is not None: @@ -281,9 +292,13 @@ class CameraManager: for _frame_type in tipos: _frame = self.get_selected_frame(_frame_type) if _frame is not None and _frame.size > 0: - nome_frame = f"{frame_name}_{(TipoFrameCamera(_frame_type)).name}.jpeg" - caminho = os.path.join(pasta, nome_frame) - cv2.imwrite(caminho, _frame) + nome_frame = f"{frame_name}_{(TipoFrameCamera(_frame_type)).name}" + if _frame_type == TipoFrameCamera.Raw4: + caminho = os.path.join(pasta, f"{nome_frame}.raw") + _frame.astype(np.float32).tofile(caminho) + else: + caminho = os.path.join(pasta, f"{nome_frame}.jpeg") + cv2.imwrite(caminho, _frame) frames_salvos.append(caminho) return frames_salvos diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/config.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/config.py index b8dda098f..91811729f 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/config.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/config.py @@ -106,7 +106,8 @@ def load_seg_config(force_reload=False): } dadosAtu = ContextoGlobalRedis.get_operacao().get("Atu", {}) contexto = ContextoGlobalRedis.get_contexto() - _CONFIG_CACHE["qtd_bicos"] = dadosAtu.get("qtd_bicos", 4) + equipamento = ContextoGlobalRedis.get_equipamento() + _CONFIG_CACHE["qtd_bicos"] = equipamento.get("qtd_bicos") _CONFIG_CACHE["velocidade_robo"] = contexto.get("Gerais", {}).get("velocidade_ms", 0.0) _CONFIG_CACHE["ia_model_path"] = ContextoGlobalRedis.get_equipamento().get("path_ia_model_ervas") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/main.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/main.py index db4bf59a2..5e2a716d9 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/main.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/main.py @@ -48,15 +48,16 @@ def main(): get_camera_manager().atualizar_saude_camera() elif acao == WeedWorkerCommandType.GetCameraFrame: tipo = TipoFrameCamera(dados.get("params", TipoFrameCamera.Rgb.value)) - frame, ts = get_camera_manager().get_selected_frame(tipo) - base64_img = encode_image_base64(frame) - if base64_img is not None: - resposta = { - "frame": base64_img, - "timestamp": ts, - "tipo": tipo.value - } - ContextoGlobalRedis.publicar_comando(CmdKey.WeedWorkerTx, { "cmd": WeedWorkerCommandType.GetCameraFrame.value, "params": resposta }) + frame = get_camera_manager().get_selected_frame(tipo) + if frame is not None: + base64_img = encode_image_base64(frame) + if base64_img is not None: + resposta = { + "frame": base64_img, + "timestamp": time.time(), + "tipo": tipo.value + } + ContextoGlobalRedis.publicar_comando(CmdKey.WeedWorkerTx, { "cmd": WeedWorkerCommandType.GetCameraFrame.value, "params": resposta }) elif acao == WeedWorkerCommandType.SaveCameraFrames: nome = dados.get("params", {}).get("nome", "") pasta = dados.get("params", {}).get("caminho", "frames_salvos") diff --git a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/weed_detector.py b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/weed_detector.py index 38845ac6d..240c8dc7e 100644 --- a/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/weed_detector.py +++ b/AgroBase/AgroBase/bin/x64/Debug/Python/Scripts/workers/weed_worker/weed_detector.py @@ -30,6 +30,7 @@ class WeedDetector: self.img_mock = "C:\\ZendionInc\\agrobot_base\\AgroBase\\AgroBase\\bin\\x64\\Debug\\Operacoes\\25_07_2025_14_39_14\\Cam0\\85_rgb.jpeg" self.predictions = None self.dados_visuais = {} + self._dbg_img = None self._dbg_img_shape = (706, 560) self._mostrar_debug = True @@ -451,7 +452,7 @@ class WeedDetector: faixa_atuacao = float(config.get("area_atuacao_bicos", 0.3)) # --- alocação única dos buffers de debug --- - if not hasattr(self, "_dbg_img") or self._dbg_img.shape[:2] != (self._dbg_img_shape[1], self._dbg_img_shape[0]): + if self._dbg_img is None or self._dbg_img.shape[:2] != (self._dbg_img_shape[1], self._dbg_img_shape[0]): # _dbg_img_shape = (W, H) self._dbg_img = np.empty((self._dbg_img_shape[1], self._dbg_img_shape[0], 3), dtype=np.uint8) self._layer = np.zeros_like(self._dbg_img) diff --git a/AgroBase/OperationControl/Models/TcpVideoReceiver.cs b/AgroBase/OperationControl/Models/TcpVideoReceiver.cs new file mode 100644 index 000000000..73b9fd590 --- /dev/null +++ b/AgroBase/OperationControl/Models/TcpVideoReceiver.cs @@ -0,0 +1,151 @@ +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Windows.Media.Imaging; + +namespace OperationControl.Models +{ + internal class TcpVideoReceiver + { + private readonly int _port; + private readonly System.Windows.Controls.Image _imageControl; + + private volatile bool _rodando; + private Thread _thread; + private TcpListener _listener; + + public TcpVideoReceiver(int port, System.Windows.Controls.Image imageControl) + { + _port = port; + _imageControl = imageControl; + } + + public void Iniciar() + { + if (_rodando) return; + + _rodando = true; + _thread = new Thread(Run) { IsBackground = true }; + _thread.Start(); + } + + public void Parar() + { + _rodando = false; + try + { + _listener?.Stop(); + _imageControl.Source = null; + } + catch { /* ignora */ } + } + + private void Run() + { + try + { + _listener = new TcpListener(IPAddress.Any, _port); + _listener.Start(); + Console.WriteLine($"[VideoReceiver] Ouvindo na porta {_port}..."); + + while (_rodando) + { + TcpClient client = null; + + try + { + // Em vez de bloquear direto no Accept, usamos Pending() + Sleep + if (!_listener.Pending()) + { + Thread.Sleep(100); + continue; + } + + client = _listener.AcceptTcpClient(); + client.NoDelay = true; + Console.WriteLine("[VideoReceiver] Cliente conectado."); + + using (var stream = client.GetStream()) + using (var br = new BinaryReader(stream)) + { + while (_rodando && client.Connected) + { + // 1) lê tamanho (4 bytes big-endian) + byte[] sizeBytes = br.ReadBytes(4); + if (sizeBytes.Length < 4) + break; + + int size = + (sizeBytes[0] << 24) | + (sizeBytes[1] << 16) | + (sizeBytes[2] << 8) | + (sizeBytes[3]); + + // 2) lê JPEG + byte[] imgBytes = br.ReadBytes(size); + if (imgBytes.Length < size) + break; + + _imageControl.Dispatcher.BeginInvoke(new Action(() => + { + try + { + using (var ms = new MemoryStream(imgBytes)) + { + var bmp = new BitmapImage(); + bmp.BeginInit(); + bmp.CacheOption = BitmapCacheOption.OnLoad; + bmp.StreamSource = ms; + bmp.EndInit(); + bmp.Freeze(); + _imageControl.Source = bmp; + } + } + catch + { + // ignora frame corrompido ou problema de decode + } + })); + } + } + + Console.WriteLine("[VideoReceiver] Cliente desconectado."); + client.Close(); + } + catch (SocketException ex) + { + // WSACancelBlockingCall ao parar o listener é normal + if (!_rodando) + break; + + Console.WriteLine("[VideoReceiver] SocketException: " + ex.Message); + client?.Close(); + Thread.Sleep(500); + } + catch (IOException) + { + // desconexão abrupta do cliente + client?.Close(); + Thread.Sleep(200); + } + catch (Exception ex) + { + Console.WriteLine("[VideoReceiver] Erro geral: " + ex.Message); + client?.Close(); + Thread.Sleep(500); + } + } + + Console.WriteLine("[VideoReceiver] Loop encerrado."); + } + catch (Exception ex) + { + Console.WriteLine("[VideoReceiver] Erro ao iniciar listener: " + ex.Message); + } + finally + { + try { _listener?.Stop(); } catch { } + } + } + } +} diff --git a/AgroBase/OperationControl/Windows/MainWindow.xaml b/AgroBase/OperationControl/Windows/MainWindow.xaml index 6dee164b7..3eb105e6b 100644 --- a/AgroBase/OperationControl/Windows/MainWindow.xaml +++ b/AgroBase/OperationControl/Windows/MainWindow.xaml @@ -826,16 +826,24 @@ diff --git a/AgroBase/OperationControl/Windows/MainWindow.xaml.cs b/AgroBase/OperationControl/Windows/MainWindow.xaml.cs index be542b2ed..9d5b6b6f6 100644 --- a/AgroBase/OperationControl/Windows/MainWindow.xaml.cs +++ b/AgroBase/OperationControl/Windows/MainWindow.xaml.cs @@ -27,11 +27,13 @@ namespace OperationControl.Windows /// public partial class MainWindow : Window, INotifyPropertyChanged { - private LibVLC _libVLC; - private MediaPlayer _playerFront; - private MediaPlayer _playerWeed; - private Media _mediaFront; - private Media _mediaWeed; + //private LibVLC _libVLC; + //private MediaPlayer _playerFront; + //private MediaPlayer _playerWeed; + //private Media _mediaFront; + //private Media _mediaWeed; + private TcpVideoReceiver videoFront; + private TcpVideoReceiver videoWeed; public MainWindow() { @@ -82,17 +84,20 @@ namespace OperationControl.Windows // Opções focadas em baixa latência - _libVLC = new LibVLC( - "--network-caching=1000", // ms (ajusta depois) - "--clock-jitter=0", - "--clock-synchro=0" - ); + //_libVLC = new LibVLC( + // "--network-caching=1000", // ms (ajusta depois) + // "--clock-jitter=0", + // "--clock-synchro=0" + //); // Player da câmera frontal - _playerFront = new MediaPlayer(_libVLC); - VideoFront.MediaPlayer = _playerFront; - _playerWeed = new MediaPlayer(_libVLC); - VideoWeed.MediaPlayer = _playerWeed; + //_playerFront = new MediaPlayer(_libVLC); + //VideoFront.MediaPlayer = _playerFront; + //_playerWeed = new MediaPlayer(_libVLC); + //VideoWeed.MediaPlayer = _playerWeed; + + videoFront = new TcpVideoReceiver(5000, imgVideoFront); + videoWeed = new TcpVideoReceiver(5002, imgVideoWeed); Loaded += MainWindow_Loaded; @@ -119,7 +124,7 @@ namespace OperationControl.Windows { PararStreamCameraFrontal(true); PararStreamCameraErvas(true); - _libVLC?.Dispose(); + //_libVLC?.Dispose(); } #region DISPOSITIVOS @@ -1779,7 +1784,7 @@ namespace OperationControl.Windows txtParametros_PctErvaOff.Text = controle.AtuPercentualErvasBicoOff.ToString(); txtParametros_TempoOn.Text = controle.AtuDuracaoAtuacao.ToString(); chbParametros_Pulverizador.IsChecked = controle.PulverizadorAutomatico; - chbParametros_Frenagem.IsChecked = controle.FrenagemAutomatica; + chbParametros_Frenagem.IsChecked = controle.FrenagemAutomaticaAoParar; chbParametros_Sonar.IsChecked = controle.SonarAtivado; } catch (Exception exUi) @@ -1807,7 +1812,7 @@ namespace OperationControl.Windows { MovimentoAutomatico = modo != AgroBase.Models.Enums.ModoOperacao.Manual, SonarAtivado = chbParametros_Sonar.IsChecked ?? false, - FrenagemAutomatica = chbParametros_Frenagem.IsChecked ?? false, + FrenagemAutomaticaAoParar = chbParametros_Frenagem.IsChecked ?? false, MovVelocidadeCErvasPercent = int.Parse(txtParametros_VelCErvas.Text), MovVelocidadeSErvasPercent = int.Parse(txtParametros_VelSErvas.Text), @@ -1922,45 +1927,49 @@ namespace OperationControl.Windows #region CAMERA FRONTAL + private void cmbCameraFrontalFrameTipo_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (cmbDispositivo.SelectedItem is null || cmbDispositivo.SelectedItem == VariaveisControleOperacao.BaseMarkerID) return; + PararStreamCameraFrontal(); + IniciarStreamCameraFrontal(); + } + private void IniciarStreamCameraFrontal() { - var path = @"streams\camera_frontal.sdp"; - - if (!File.Exists(path)) - { - string stream = - "v=0\r\n" + - "o=- 0 0 IN IP4 0.0.0.0\r\n" + - "s=OAK H264\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "t=0 0\r\n" + - "m=video 5000 RTP/AVP 96\r\n" + - "a=rtpmap:96 H264/90000\r\n" + - "a=fmtp:96 packetization-mode=1\r\n"; - File.WriteAllText(path, stream); - } - - _mediaFront?.Dispose(); // limpa antigo, se existir - _mediaFront = new Media(_libVLC, path, FromType.FromPath); - // _mediaFront.AddOption(":network-caching=150"); // se quiser por arquivo - - _playerFront.Play(_mediaFront); + //var path = @"streams\camera_frontal.sdp"; + //if (!File.Exists(path)) + //{ + // string stream = + // "v=0\r\n" + + // "o=- 0 0 IN IP4 0.0.0.0\r\n" + + // "s=OAK H264\r\n" + + // "c=IN IP4 0.0.0.0\r\n" + + // "t=0 0\r\n" + + // "m=video 5000 RTP/AVP 96\r\n" + + // "a=rtpmap:96 H264/90000\r\n" + + // "a=fmtp:96 packetization-mode=1\r\n"; + // File.WriteAllText(path, stream); + //} + //_mediaFront?.Dispose(); // limpa antigo, se existir + //_mediaFront = new Media(_libVLC, path, FromType.FromPath); + //_playerFront.Play(_mediaFront); + videoFront.Iniciar(); VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, true, ((AgroBase.Models.Enums.TipoFrameCamera)cmbCameraFrontalFrameTipo.SelectedIndex)); } private void PararStreamCameraFrontal(bool finalizar = false) { - _playerFront?.Stop(); - - if (finalizar) - { - _mediaFront?.Dispose(); - _mediaFront = null; - _playerFront?.Dispose(); - _playerFront = null; - } + //_playerFront?.Stop(); + //if (finalizar) + //{ + // _mediaFront?.Dispose(); + // _mediaFront = null; + // _playerFront?.Dispose(); + // _playerFront = null; + //} + videoFront.Parar(); VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Snr, false, ((AgroBase.Models.Enums.TipoFrameCamera)cmbCameraFrontalFrameTipo.SelectedIndex)); } @@ -1968,45 +1977,50 @@ namespace OperationControl.Windows #region CAMERA ERVAS + private void cmbCameraTraseiraFrameTipo_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (cmbDispositivo.SelectedItem is null || cmbDispositivo.SelectedItem == VariaveisControleOperacao.BaseMarkerID) return; + PararStreamCameraErvas(); + IniciarStreamCameraErvas(); + } + private void IniciarStreamCameraErvas() { - var path = @"streams\camera_ervas.sdp"; - - if (!File.Exists(path)) - { - string stream = - "v=0\r\n" + - "o=- 0 0 IN IP4 0.0.0.0\r\n" + - "s=OAK H264\r\n" + - "c=IN IP4 0.0.0.0\r\n" + - "t=0 0\r\n" + - "m=video 5002 RTP/AVP 96\r\n" + // <- porta 5001 - "a=rtpmap:96 H264/90000\r\n" + - "a=fmtp:96 packetization-mode=1\r\n"; - File.WriteAllText(path, stream); - } - - _mediaWeed?.Dispose(); - _mediaWeed = new Media(_libVLC, path, FromType.FromPath); - // _mediaWeed.AddOption(":network-caching=150"); - - _playerWeed.Play(_mediaWeed); + //var path = @"streams\camera_ervas.sdp"; + //if (!File.Exists(path)) + //{ + // string stream = + // "v=0\r\n" + + // "o=- 0 0 IN IP4 0.0.0.0\r\n" + + // "s=OAK H264\r\n" + + // "c=IN IP4 0.0.0.0\r\n" + + // "t=0 0\r\n" + + // "m=video 5002 RTP/AVP 96\r\n" + // <- porta 5001 + // "a=rtpmap:96 H264/90000\r\n" + + // "a=fmtp:96 packetization-mode=1\r\n"; + // File.WriteAllText(path, stream); + //} + //_mediaWeed?.Dispose(); + //_mediaWeed = new Media(_libVLC, path, FromType.FromPath); + //_mediaWeed.AddOption(":network-caching=150"); + //_playerWeed.Play(_mediaWeed); + videoWeed.Iniciar(); VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Cam, true, ((AgroBase.Models.Enums.TipoFrameCamera)cmbCameraTraseiraFrameTipo.SelectedIndex)); } private void PararStreamCameraErvas(bool finalizar = false) { - _playerWeed?.Stop(); - - if (finalizar) - { - _mediaWeed?.Dispose(); - _mediaWeed = null; - _playerWeed?.Dispose(); - _playerWeed = null; - } + //_playerWeed?.Stop(); + //if (finalizar) + //{ + // _mediaWeed?.Dispose(); + // _mediaWeed = null; + // _playerWeed?.Dispose(); + // _playerWeed = null; + //} + videoWeed.Parar(); VariaveisControleOperacao.EnviarComandoTransmissaoVideo(AgroBase.Models.Enums.T_Code.Cam, false, ((AgroBase.Models.Enums.TipoFrameCamera)cmbCameraTraseiraFrameTipo.SelectedIndex)); } @@ -2246,6 +2260,9 @@ namespace OperationControl.Windows + + + #endregion diff --git a/Firmware/Modulos/BicoPulverizadorModel.h b/Firmware/Modulos/BicoPulverizadorModel.h index b169ed7b8..96dcf52a6 100644 --- a/Firmware/Modulos/BicoPulverizadorModel.h +++ b/Firmware/Modulos/BicoPulverizadorModel.h @@ -107,8 +107,12 @@ class Bico : public ComponenteCAN { break; } case CanMessagePosicaoDados::Dados1: { + int angulo = 0; + if (servoMov != nullptr) { + angulo = servoMov->_Angulo; + } data.push_back(static_cast(_Status)); - data.push_back(servoMov->_Angulo); + data.push_back(angulo); break; } }