ajustes no fluxo e registro de logs

This commit is contained in:
Diego Freitas 2025-03-20 13:43:12 -03:00
parent 67e85b19e5
commit e65e9b2c66
97 changed files with 352 additions and 174301 deletions

Binary file not shown.

View File

@ -3,24 +3,20 @@
"WorkspaceRootPath": "C:\\ZendionINC\\agrobot_base\\AgroBase\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|c:\\zendioninc\\agrobot_base\\agrobase\\agrobase\\models\\trajetoriamapaoperacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\trajetoriamapaoperacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|c:\\zendioninc\\agrobot_base\\agrobase\\agrobase\\models\\variaveis.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\variaveis.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|C:\\ZendionINC\\agrobot_base\\AgroBase\\agrobase\\models\\operacoes\\operacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\operacoes\\operacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|C:\\ZendionINC\\agrobot_base\\AgroBase\\agrobase\\models\\operacoes\\operacaomapagpsmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\operacoes\\operacaomapagpsmodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|C:\\ZendionINC\\agrobot_base\\AgroBase\\agrobase\\forms\\frmsimulacaomapagps.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\forms\\frmsimulacaomapagps.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|c:\\zendioninc\\agrobot_base\\agrobase\\agrobase\\forms\\ihm\\frmdialogomapa.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\forms\\ihm\\frmdialogomapa.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|c:\\zendioninc\\agrobot_base\\agrobase\\agrobase\\models\\operacoes\\operacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\operacoes\\operacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|c:\\zendioninc\\agrobot_base\\agrobase\\agrobase\\models\\trajetoriamapaoperacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\trajetoriamapaoperacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
@ -30,69 +26,56 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 4,
"SelectedChildIndex": 0,
"Children": [
{
"$type": "Document",
"DocumentIndex": 4,
"DocumentIndex": 0,
"Title": "Variaveis.cs",
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Variaveis.cs",
"RelativeDocumentMoniker": "AgroBase\\Models\\Variaveis.cs",
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Variaveis.cs",
"RelativeToolTip": "AgroBase\\Models\\Variaveis.cs",
"ViewState": "AQIAAAAAAAAAAAAAAAAAAKsEAAAAAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-03-20T12:50:31.51Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "OperacaoModel.cs",
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Operacoes\\OperacaoModel.cs",
"RelativeDocumentMoniker": "AgroBase\\Models\\Operacoes\\OperacaoModel.cs",
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Operacoes\\OperacaoModel.cs",
"RelativeToolTip": "AgroBase\\Models\\Operacoes\\OperacaoModel.cs",
"ViewState": "AQIAAPQEAAAAAAAAAAAswEwFAACJAAAA",
"ViewState": "AQIAAAwBAAAAAAAAAIA4wLUFAAAtAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-03-19T22:01:26.068Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 3,
"Title": "frmDialogoMapa.cs",
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Forms\\IHM\\frmDialogoMapa.cs",
"RelativeDocumentMoniker": "AgroBase\\Forms\\IHM\\frmDialogoMapa.cs",
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Forms\\IHM\\frmDialogoMapa.cs",
"RelativeToolTip": "AgroBase\\Forms\\IHM\\frmDialogoMapa.cs",
"ViewState": "AQIAAAwAAAAAAAAAAAAAAGcAAAAcAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-03-19T16:39:31.785Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "frmSimulacaoMapaGPS.cs",
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Forms\\frmSimulacaoMapaGPS.cs",
"RelativeDocumentMoniker": "AgroBase\\Forms\\frmSimulacaoMapaGPS.cs",
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Forms\\frmSimulacaoMapaGPS.cs",
"RelativeToolTip": "AgroBase\\Forms\\frmSimulacaoMapaGPS.cs",
"ViewState": "AQIAABoAAAAAAAAAAAAQwJcAAABPAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-03-18T19:07:04.826Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "OperacaoMapaGPSModel.cs",
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Operacoes\\OperacaoMapaGPSModel.cs",
"RelativeDocumentMoniker": "AgroBase\\Models\\Operacoes\\OperacaoMapaGPSModel.cs",
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Operacoes\\OperacaoMapaGPSModel.cs",
"RelativeToolTip": "AgroBase\\Models\\Operacoes\\OperacaoMapaGPSModel.cs",
"ViewState": "AQIAAAAAAAAAAAAAAAAAADsAAAArAAAA",
"ViewState": "AQIAAAAAAAAAAAAAAAAAABEAAAAIAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-03-18T11:05:46.524Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 0,
"DocumentIndex": 3,
"Title": "TrajetoriaMapaOperacaoModel.cs",
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\TrajetoriaMapaOperacaoModel.cs",
"RelativeDocumentMoniker": "AgroBase\\Models\\TrajetoriaMapaOperacaoModel.cs",
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\TrajetoriaMapaOperacaoModel.cs",
"RelativeToolTip": "AgroBase\\Models\\TrajetoriaMapaOperacaoModel.cs",
"ViewState": "AQIAAAAAAAAAAAAAAAAAANACAAAsAAAA",
"ViewState": "AQIAAAAAAAAAAAAAAAAAAMACAAAsAAAA",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2025-03-18T10:53:08.916Z",
"EditorCaption": ""

View File

@ -105,7 +105,7 @@ namespace AgroBase.Forms
{
var DispMvd = Variaveis.OperacaoEmAndamento.DispMvd;
lblTempoConectado.Text = "Tempo conectado: " + TimeSpan.FromSeconds(DispMvd.TempoConectado).ToString(@"hh\:mm\:ss") + " hrs";
lblTempoConectado.Text = "Tempo conectado: " + (DateTime.Now - DispMvd.CriadoEm).ToString("HH:mm:ss") + " hrs";
lblTempoEmMovimento.Text = "Tempo em movimento: " + TimeSpan.FromSeconds(DispMvd.Dados.TempoEmAtividade).ToString(@"hh\:mm\:ss") + " hrs";
lblDistanciaTotal.Text = "Distancia percorrida total: " + DispMvd.Dados.DistanciaPercorridaTotal.ToString("0.00") + " m";
lblDistanciaParcial.Text = "Distancia percorrida parcial: " + DispMvd.Dados.DistanciaPercorridaParcial.ToString("0.00") + " m";

View File

@ -1,4 +1,5 @@
using AgroBase.Services;
using System;
using System.Linq;
using static AgroBase.Models.Enums;
@ -10,6 +11,7 @@ namespace AgroBase.Models
public class DispositivoDetalhesModel
{
public DateTime CriadoEm { get; set; } = DateTime.Now;
public string Endereco { get; set; }
public TipoConexao Tipo
{

View File

@ -113,41 +113,48 @@ namespace AgroBase.Models
private void PnlZoomMapa_Paint(object sender, PaintEventArgs e)
{
Panel panel1 = (Panel)sender;
Graphics g = e.Graphics;
// Defina as dimensões do panel
int width = panel1.Width;
int height = panel1.Height;
// Coordenadas centrais (onde o robô estará), ajustadas pelo deslocamento do mapa
float centerX = width / 2 + _mapOffset.X;
float centerY = height / 2 + _mapOffset.Y;
// Desenha os pontos da rua com plantacao
foreach (var _rua in RuasPlantacao)
try
{
var rua = _rua.Select(x => new PontoTrajetoriaModel(Enums.TipoPontoRua.Indefinido) { Posicao = x }).ToList();
DrawTrajectory(g, rua, centerX, centerY, Color.Blue, Pens.Black);
Panel panel1 = (Panel)sender;
Graphics g = e.Graphics;
// Defina as dimensões do panel
int width = panel1.Width;
int height = panel1.Height;
// Coordenadas centrais (onde o robô estará), ajustadas pelo deslocamento do mapa
float centerX = width / 2 + _mapOffset.X;
float centerY = height / 2 + _mapOffset.Y;
// Desenha os pontos da rua com plantacao
foreach (var _rua in RuasPlantacao)
{
var rua = _rua.Select(x => new PontoTrajetoriaModel(Enums.TipoPontoRua.Indefinido) { Posicao = x }).ToList();
DrawTrajectory(g, rua, centerX, centerY, Color.Blue, Pens.Black);
}
// Desenha os pontos da trajetória projetada
DrawTrajectory(g, TrajetoriaDinamica, centerX, centerY, Color.Purple, Pens.MediumPurple, true);
// Desenha os pontos da trajetória planejada da rua atual
DrawTrajectory(g, TrajetoriaRuaProjetada, centerX, centerY, Color.Green, Pens.Blue);
// Desenha os pontos da trajetória percorrida
var _trajetoriaRobo = TrajetoriaRobo.Select(x => new PontoTrajetoriaModel(Enums.TipoPontoRua.Indefinido) { Posicao = x }).ToList();
DrawTrajectory(g, _trajetoriaRobo, centerX, centerY, Color.Orange, Pens.OrangeRed);
// Desenha a posição atual do robô (ponto vermelho)
float PxToCm = DrawRobot(g, centerX, centerY, Color.Red, Color.Red, (float)VariaveisEquipamento.LarguraEsquerda, (float)VariaveisEquipamento.LarguraDireita, (float)VariaveisEquipamento.ComprimentoFrente, (float)VariaveisEquipamento.ComprimentoTras, AnguloCarro);
if (obstaculoDetectado != null)
{
DrawObstacle(g, centerX, centerY, Color.Cyan, Color.Cyan, AnguloCaminho - (float)obstaculoDetectado.AnguloParaDesvio, obstaculoDetectado, PxToCm);
}
}
// Desenha os pontos da trajetória projetada
DrawTrajectory(g, TrajetoriaDinamica, centerX, centerY, Color.Purple, Pens.MediumPurple, true);
// Desenha os pontos da trajetória planejada da rua atual
DrawTrajectory(g, TrajetoriaRuaProjetada, centerX, centerY, Color.Green, Pens.Blue);
// Desenha os pontos da trajetória percorrida
var _trajetoriaRobo = TrajetoriaRobo.Select(x => new PontoTrajetoriaModel(Enums.TipoPontoRua.Indefinido) { Posicao = x }).ToList();
DrawTrajectory(g, _trajetoriaRobo, centerX, centerY, Color.Orange, Pens.OrangeRed);
// Desenha a posição atual do robô (ponto vermelho)
float PxToCm = DrawRobot(g, centerX, centerY, Color.Red, Color.Red, (float)VariaveisEquipamento.LarguraEsquerda, (float)VariaveisEquipamento.LarguraDireita, (float)VariaveisEquipamento.ComprimentoFrente, (float)VariaveisEquipamento.ComprimentoTras, AnguloCarro);
if (obstaculoDetectado != null)
catch (Exception ex)
{
DrawObstacle(g, centerX, centerY, Color.Cyan, Color.Cyan, AnguloCaminho - (float)obstaculoDetectado.AnguloParaDesvio, obstaculoDetectado, PxToCm);
Console.WriteLine("Erro ao atualizar mapa dinamico: " + ex.Message);
}
}

View File

@ -115,6 +115,7 @@ namespace AgroBase.Models.Operacoes
// Aplica a correção. Isso pode incluir limites para evitar comandos excessivos.
correcaoAngulo = Math.Min(_Controle.Angulo_Max, correcaoAngulo);
correcaoAngulo = Math.Max(_Controle.Angulo_Min, correcaoAngulo);
correcaoAngulo = Math.Round(correcaoAngulo, 2);
_Controle.Angulo = correcaoAngulo;
}
@ -287,7 +288,7 @@ namespace AgroBase.Models.Operacoes
(1 - (pesoAnguloControle * percentualReduzido) - reducaoPorErroOrientacao) * (Controle.PercentualVelocidadeMax - Controle.PercentualVelocidadeMin);
// **Garante que a velocidade fique dentro dos limites aceitáveis (0 a 100%)**
percentualVelocidadeRelativo = Math.Max(Controle.PercentualVelocidadeMin, Math.Min(Controle.PercentualVelocidadeMax, percentualVelocidadeRelativo));
percentualVelocidadeRelativo = Math.Round(Math.Max(Controle.PercentualVelocidadeMin, Math.Min(Controle.PercentualVelocidadeMax, percentualVelocidadeRelativo)), 2);
return percentualVelocidadeRelativo;
}

View File

@ -89,7 +89,7 @@ namespace AgroBase.Models
etapaAtual = StatusOperacao.Aguardando;
}
// Não existem corredores pendentes e a etapa atual ainda não foi marcada como concluída
else if (!(Variaveis.OperacaoEmAndamento.Trajetoria?.CorredoresNaoFinalizados?.Any() ?? false) && StatusAtual != StatusOperacao.Concluido)
else if ((Variaveis.OperacaoEmAndamento.Trajetoria?.CorredorAtual?.Ultimo ?? false) && (Variaveis.OperacaoEmAndamento.Trajetoria?.CorredorAtual?.Concluido ?? false) && StatusAtual != StatusOperacao.Concluido)
{
etapaAtual = StatusOperacao.Concluido;
}
@ -812,14 +812,6 @@ namespace AgroBase.Models
SalvarLogs(false);
string caminhoArquivoGps = Path.Combine(Variaveis.CaminhoLogsDispositivos, "Gps", ID + ".json");
if (!File.Exists(caminhoArquivoGps))
{
MapaFeatureCollectionModel mapa = MapasService.ConverterPontosParaMapa(new List<List<GPSModel>>() { Variaveis.OperacaoEmAndamento.GPSTrajetoria });
string json = JsonConvert.SerializeObject(mapa);
File.WriteAllText(caminhoArquivoGps, json);
}
Variaveis.OperacaoEmAndamento.Finalizando = false;
}
@ -1018,7 +1010,10 @@ namespace AgroBase.Models
Posicao = CamerasSolo.Count(),
ArquivoLeitura = "ervas_" + CamNome + ".json",
browser = null,
camera = new CameraService(),
camera = new CameraService()
{
InverterDadosLeitura = true,
},
combo = new ComboBox(),
MaxLeituras = 1,
VideoPorta = (VariaveisPortas.CameraSolo + CamerasSolo.Count()).ToString(),

View File

@ -30,7 +30,7 @@ namespace AgroBase.Models
public DateTime UltimaAtualizacaoDados { get; set; } = DateTime.MinValue;
[JsonProperty]
public double TempoEntreLeituras { get; private set; }
private void AtuaalizarTempoEntreLeituras()
private void AtualizarTempoEntreLeituras()
{
double dt = Math.Min((1.0 / GPSService.TaxaAmostragemHz), (UltimaAtualizacaoDados - GPSService.UltimaLeitura.Momento).TotalSeconds);
TempoEntreLeituras = dt;
@ -86,24 +86,6 @@ namespace AgroBase.Models
}
}
[JsonProperty]
public List<int> CorredoresNaoFinalizados { get; private set; }
private void AtualizarCorredoresNaoFinalizados()
{
// ✅ Retorna lista vazia imediatamente se não houver pontos
if (_Corredores == null || _Corredores.Count == 0)
{
CorredoresNaoFinalizados = new List<int>();
return;
}
// ✅ Obtém apenas os corredores com pontos não visitados, sem duplicatas
CorredoresNaoFinalizados = _Corredores
.Where(p => !p.Concluido) // Filtra apenas pontos não visitados
.Select(p => p.Idx) // Pega apenas o id do corredor
.ToList(); // Converte para lista
}
public List<PontoTrajetoriaModel> _TrajetoriaFixa { get; set; }
private bool _TrajetoriaFixaDefinida
{
@ -136,7 +118,10 @@ namespace AgroBase.Models
{
new PontoTrajetoriaModel(TipoPontoRua.PosicaoRobo)
{
Posicao = GPSService.UltimaLeitura
Posicao = GPSService.UltimaLeitura,
LarguraCorredor = 1.0,
idxCorredor = CorredorAtual.Idx,
Visitado = true
}
};
@ -525,7 +510,7 @@ namespace AgroBase.Models
{
if (!_TrajetoriaFixaDefinida) return;
AtuaalizarTempoEntreLeituras();
AtualizarTempoEntreLeituras();
AtualizarDistanciaMaximaEntreLeituras();
AtualizarIndicesJanela();
@ -542,7 +527,6 @@ namespace AgroBase.Models
AtualizarNaMargemDoCorredor();
AtualizarManobrandoEntreRuas();
AtualizarStatusAtual();
AtualizarCorredoresNaoFinalizados();
AtualizarDistanciaPercorrida();
AtualizarDistanciaRestante();
AtualizarPercentualTrajetoria();
@ -916,7 +900,8 @@ namespace AgroBase.Models
DistanciaPercorridaCorredor = 0,
DistanciaPercorridaTotal = 0,
idxRuaDireita = idxDir + incDir,
idxRuaEsquerda = idxEsq + incEsq
idxRuaEsquerda = idxEsq + incEsq,
Ultimo = i == x.Count() - 1
};
return obj;
@ -1095,6 +1080,7 @@ namespace AgroBase.Models
public double Progresso { get; private set; }
[JsonProperty]
public bool Concluido { get; private set; }
public bool Ultimo { get; set; }
public int idxRuaEsquerda { get; set; }
public int idxRuaDireita { get; set; }
public double FatorLarguraCorredor { get; private set; }
@ -1165,7 +1151,7 @@ namespace AgroBase.Models
public Enums.DirecaoCarroRua Direcao { get; set; }
public Enums.TipoPontoRua Tipo { get; }
public double LarguraCorredor { get; set; }
public double DistanciaMargem { get; set; }
public double DistanciaMargem { get; private set; }
public bool Visitado { get; set; } = false;
// ✅ Agora, propriedades podem ser atualizadas com `set; private`

View File

@ -347,39 +347,51 @@ namespace AgroBase.Models
}
}
public static GPSModel PosicaoBase { get; set; }
public static void RegistrarLogDispositivo(List<string> Logs, string Caminho, string NomeArquivo, int MinLogs = 100)
private static readonly object _lock = new object();
public static void RegistrarLogDispositivo(List<string> Logs, T_Code Dispositivo, string Sulfixo, int MinLogs = 100)
{
try
lock (_lock)
{
if (Logs.Count() >= MinLogs)
var Caminho = Path.Combine(Variaveis.CaminhoLogsDispositivos, Dispositivo.ToString());
string NomeArquivo = Dispositivo.ToString() + Sulfixo;
var Disp = SerialService.DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == Dispositivo);
try
{
if (!Directory.Exists(Caminho))
if (Disp != null)
{
Directory.CreateDirectory(Caminho);
NomeArquivo = Disp.CriadoEm.ToString("dd_MM_yyyy_HH_mm_ss") + Sulfixo;
}
Caminho = Path.Combine(Caminho, NomeArquivo);
foreach (var mensagem in Logs)
if (Logs.Count() >= MinLogs)
{
if (!Directory.Exists(Caminho))
{
Directory.CreateDirectory(Caminho);
}
Caminho = Path.Combine(Caminho, NomeArquivo);
if (!File.Exists(Caminho))
{
File.WriteAllText(Caminho, mensagem);
File.WriteAllLines(Caminho, Logs);
}
else
{
File.AppendAllText(Caminho, mensagem);
File.AppendAllLines(Caminho, Logs);
}
}
Logs.Clear();
Logs.Clear();
}
}
catch
{
Console.WriteLine("Erro ao salvar log: " + NomeArquivo);
}
}
catch
{
Console.WriteLine("Erro ao salvar log: " + NomeArquivo);
}
}

View File

@ -1,6 +1,7 @@
using AgroBase.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static AgroBase.Models.Enums;
@ -538,28 +539,20 @@ namespace AgroBase.Services
public static void RegisrarErrosComunicacao(byte addr, string mensagem)
{
var Caminho = Variaveis.CaminhoLogsDispositivos;
var Arquivo = T_Code.Bld.ToString() + "_err.txt";
mensagem = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff") + " - Endereço " + addr + " (" + _ethernetService._ipAddress + "): " + mensagem + Environment.NewLine;
ErrosComunicacao.Add(mensagem);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, Caminho, Arquivo);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, T_Code.Bld, "_err.txt", 50);
}
public static void RegisrarComandosComunicacao(byte addr, string mensagem)
{
var Caminho = Variaveis.CaminhoLogsDispositivos;
var Arquivo = T_Code.Bld.ToString() + "_log.txt";
mensagem = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff") + " - Endereço " + addr + " (" + _ethernetService._ipAddress + "): " + mensagem + Environment.NewLine;
ComandosComunicacao.Add(mensagem);
VariaveisOperacao.RegistrarLogDispositivo(ComandosComunicacao, Caminho, Arquivo);
VariaveisOperacao.RegistrarLogDispositivo(ComandosComunicacao, T_Code.Bld, "_log.txt", 1000);
}
private static async Task tmrLoopComandos_Tick()

View File

@ -25,6 +25,7 @@ namespace AgroBase.Services
private double conf_threshold = 0.5;
private double nms_threshold = 0.4;
public List<string> URLcamera = new List<string>();
public bool InverterDadosLeitura = false;
public void IniciarCamera(string Script, string[] Argumentos, string FlaskPorta, List<string> FlaskUrl, string MqttTopico, Func<MqttTopicosMensagensModel, Task> mqttCallback = null)

View File

@ -21,7 +21,13 @@ namespace AgroBase.Comum
public T_Code Dispositivo { get; set; } = T_Code.Vzo;
public string _Nome { get; set; }
public string _Descricao { get; set; }
public DateTime _CriadoEm { get; set; }
public DateTime CriadoEm
{
get
{
return SerialService.DispositivosMapeados.FirstOrDefault(x => x.Dispositivo == Dispositivo)?.CriadoEm ?? DateTime.Now;
}
}
public GroupBox gpbItem { get; set; }
public NumericUpDown nudAmostragem { get; set; }
public Label lblStatus { get; set; }
@ -38,9 +44,9 @@ namespace AgroBase.Comum
}
public Form frmConfig { get; set; }
public Form frmPin { get; set; }
private AsyncTaskTimerModel tmrLogsDispositivo;
//private AsyncTaskTimerModel tmrLogsDispositivo;
public int TempoConectado { get; set; } = 0;
//public int TempoConectado { get; set; } = 0;
public MqttTopicosModel MqttTopicoEnvioComandos;
public MqttTopicosModel MqttTopicoRecebimentoDados;
@ -98,15 +104,12 @@ namespace AgroBase.Comum
}
}
lock (_logsLock)
SalvarLog(new DispositivoLogModel()
{
Logs.Add(new DispositivoLogModel()
{
Momento = DateTime.Now,
Enviado = false,
Protocolo = Recebido,
});
}
Momento = DateTime.Now,
Enviado = false,
Protocolo = Recebido,
});
//AtualizarConsole("< " + DateTime.Now.ToString("HH:mm:ss:fff") + " - " + Recebido);
@ -134,16 +137,13 @@ namespace AgroBase.Comum
);
//Console.WriteLine("Dados enviados: " + Dados);
lock (_logsLock)
SalvarLog(new DispositivoLogModel()
{
Logs.Add(new DispositivoLogModel()
{
Momento = DateTime.Now,
Enviado = true,
Protocolo = Dados,
ErroEnvio = false,
});
}
Momento = DateTime.Now,
Enviado = true,
Protocolo = Dados,
ErroEnvio = false,
});
}
catch (Exception ex)
{
@ -152,6 +152,12 @@ namespace AgroBase.Comum
}
}
private void SalvarLog(DispositivoLogModel Log)
{
Logs.Add(JsonConvert.SerializeObject(Log));
VariaveisOperacao.RegistrarLogDispositivo(Logs, Dispositivo, ".json", 100);
}
public MqttTopicosModel GetMqttTopico(bool Envio)
{
return Envio ? MqttTopicoEnvioComandos : MqttTopicoRecebimentoDados;
@ -359,8 +365,8 @@ namespace AgroBase.Comum
btnPinout.Click -= btnPinout_Click;
btnPinout.Click += btnPinout_Click;
tmrLogsDispositivo = new AsyncTaskTimerModel("tmrLogsDispositivo_" + Dispositivo.ToString(), tmrLogsDispositivo_Tick, 1000);
tmrLogsDispositivo.Start();
//tmrLogsDispositivo = new AsyncTaskTimerModel("tmrLogsDispositivo_" + Dispositivo.ToString(), tmrLogsDispositivo_Tick, 1000);
//tmrLogsDispositivo.Start();
gpbItem.Controls.Add(lblPorta);
gpbItem.Controls.Add(lblBaudRate);
@ -396,22 +402,6 @@ namespace AgroBase.Comum
}
}
private async Task tmrLogsDispositivo_Tick()
{
SalvarLog();
TempoConectado++;
}
private void SalvarLog()
{
string Caminho = Path.Combine(Variaveis.CaminhoLogsDispositivos, Dispositivo.ToString());
string NomeLog = _CriadoEm.ToString("dd_MM_yyyy_HH_mm_ss") + ".json";
VariaveisOperacao.RegistrarLogDispositivo(Logs.Select(x => JsonConvert.SerializeObject(x)).ToList(), Caminho, NomeLog);
}
private void clbDispositivos_ItemCheck(object sender, ItemCheckEventArgs e)
{
((CheckedListBox)sender).ItemCheck -= clbDispositivos_ItemCheck;

View File

@ -1,12 +1,7 @@
using AgroBase.Comum;
using AgroBase.Models;
using AgroBase.Models.Modules;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static AgroBase.Models.Enums;
namespace AgroBase.Services
@ -23,7 +18,6 @@ namespace AgroBase.Services
Dispositivo = tipoDispositivo,
_Nome = nome,
_Descricao = descricao,
_CriadoEm = DateTime.Now,
};
case T_Code.Atu:
return new DispositivosService<AtuadorModel>
@ -31,15 +25,13 @@ namespace AgroBase.Services
Dispositivo = tipoDispositivo,
_Nome = nome,
_Descricao = descricao,
_CriadoEm = DateTime.Now,
};
case T_Code.Mvd:
return new DispositivosService<MovimentacaoUnificadaModel>
{
Dispositivo = tipoDispositivo,
_Nome = nome,
_Descricao = descricao,
_CriadoEm = DateTime.Now,
_Descricao = descricao,
};
default:
throw new ArgumentException("Tipo de dispositivo não reconhecido.");

View File

@ -37,6 +37,7 @@ namespace AgroBase.Services
public static GPSModel UltimaLeitura = new GPSModel();
public static GPSModel PenultimaLeitura = new GPSModel();
public static List<string> Logs = new List<string>();
public static int TaxaAmostragemHz { get; set; } = 5;
@ -140,6 +141,9 @@ namespace AgroBase.Services
_buffer.Clear();
_buffer.Append(mensagens[mensagens.Length - 1]);
}
Logs.Add(JsonConvert.SerializeObject(UltimaLeitura));
VariaveisOperacao.RegistrarLogDispositivo(Logs, T_Code.Gps, ".json", 300);
}
catch (Exception ex)
{
@ -148,32 +152,6 @@ namespace AgroBase.Services
}
private static DateTime ultimaRecepcao = DateTime.MinValue;
private static double frequenciaRecepcao = 0; // Em Hz
private static double intervaloRecepcao = 0; // Em milissegundos
private static void LogTempoLeitura()
{
DateTime agora = DateTime.Now;
if (ultimaRecepcao != DateTime.MinValue)
{
// Calcula o intervalo entre recepções (em segundos)
intervaloRecepcao = (agora - ultimaRecepcao).TotalMilliseconds;
// Calcula a frequência (Hz) => f = 1 / T, onde T é o intervalo em segundos
if (intervaloRecepcao > 0)
{
frequenciaRecepcao = 1000.0 / intervaloRecepcao;
}
// Log no console (ou pode ser salvo em um arquivo)
Console.WriteLine($"GPS - Intervalo: {intervaloRecepcao:F2} ms | Frequência: {frequenciaRecepcao:F2} Hz");
}
// Atualiza o timestamp da última recepção
ultimaRecepcao = agora;
}
private static void ProcessarDadosNMEA(string nmeaData)
{
@ -292,8 +270,6 @@ namespace AgroBase.Services
DateTime currentDate = DateTime.UtcNow.Date;
UltimaLeitura.DataHora = currentDate.Add(timeOfDay);
}
LogTempoLeitura();
}
private static void ProcessarGNRMC(string sentenca)

View File

@ -13,7 +13,6 @@ namespace AgroBase.Services
string _Nome { get; set; }
string _Descricao { get; set; }
DispositivoBaseModel Dados { get; set; }
int TempoConectado { get; set; }
GroupBox gpbItem { get; set; }
Task GerenciarMqttTopicos();
Task EnviarDadosMQTT(string Protocolo);

View File

@ -2,6 +2,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static AgroBase.Models.Enums;
@ -131,28 +132,20 @@ namespace AgroBase.Services
private static void RegisrarErrosComunicacao(byte addr, string mensagem)
{
var Caminho = Variaveis.CaminhoLogsDispositivos;
var Arquivo = T_Code.Mks.ToString() + "_err.txt";
mensagem = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff") + " - Endereço " + addr + " (" + _ethernetService._ipAddress + "): " + mensagem + Environment.NewLine;
ErrosComunicacao.Add(mensagem);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, Caminho, Arquivo, 30);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, T_Code.Mks, "_err.txt", 50);
}
public static void RegisrarComandosComunicacao(byte addr, string mensagem)
{
var Caminho = Variaveis.CaminhoLogsDispositivos;
var Arquivo = T_Code.Mks.ToString() + "_log.txt";
mensagem = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff") + " - Endereço " + addr + " (" + _ethernetService._ipAddress + "): " + mensagem + Environment.NewLine;
ComandosComunicacao.Add(mensagem);
VariaveisOperacao.RegistrarLogDispositivo(ComandosComunicacao, Caminho, Arquivo, 300);
VariaveisOperacao.RegistrarLogDispositivo(ComandosComunicacao, T_Code.Mks, "_log.txt", 1000);
}
private static void DefinirDispositivo(List<string> Mod_IDs)

View File

@ -196,20 +196,11 @@ namespace AgroBase.Services
private static void RegisrarErrosComunicacao(T_Code dispositivo, byte addr, string mensagem)
{
var Caminho = Variaveis.CaminhoLogsDispositivos;
if (!Directory.Exists(Caminho))
{
Directory.CreateDirectory(Caminho);
}
var Arquivo = dispositivo.ToString() + "_err.txt";
Caminho += "/" + Arquivo;
mensagem = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff") + " - Porta " + (_PortaModbus?.PortName ?? "COM") + " - " + addr + ": " + mensagem + Environment.NewLine;
ErrosComunicacao.Add(mensagem);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, Caminho, 50);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, T_Code.Mbs, "_err.txt", 50);
}

View File

@ -10,16 +10,23 @@ namespace AgroBase.Services
{
public static List<OAKCameraModel> CamerasConectadas = new List<OAKCameraModel>();
private static readonly object Cameras_Lock = new object();
private static AsyncTaskTimerModel tmrAtualizacao = new AsyncTaskTimerModel("tmrAtualizacao_OAK", async () => { AtualizarListaCameras(); }, 5000);
private static AsyncTaskTimerModel tmrAtualizacao = new AsyncTaskTimerModel("tmrAtualizacao_OAK", async () => { AtualizarListaCameras(); }, 30000);
public static void IniciarRotinas()
{
tmrAtualizacao?.Stop();
tmrAtualizacao?.Start();
AtualizarListaCameras(true);
}
private static void AtualizarListaCameras()
public static void AtualizarListaCameras(bool Forcar = false)
{
if (true && !Forcar)
{
return;
}
var cameras = new List<OAKCameraModel>()
{
new OAKCameraModel()

View File

@ -1,6 +1,7 @@
using AgroBase.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using static AgroBase.Models.Enums;
@ -948,28 +949,20 @@ namespace AgroBase.Services
public static void RegisrarErrosComunicacao(byte addr, string mensagem)
{
var Caminho = Variaveis.CaminhoLogsDispositivos;
var Arquivo = T_Code.Oid.ToString() + "_err.txt";
mensagem = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff") + " - Endereço " + addr + " (" + _ethernetService._ipAddress + "): " + mensagem + Environment.NewLine;
ErrosComunicacao.Add(mensagem);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, Caminho, Arquivo, 30);
VariaveisOperacao.RegistrarLogDispositivo(ErrosComunicacao, T_Code.Oid, "_err.txt", 50);
}
public static void RegisrarComandosComunicacao(byte addr, string mensagem)
{
var Caminho = Variaveis.CaminhoLogsDispositivos;
var Arquivo = T_Code.Oid.ToString() + "_log.txt";
mensagem = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff") + " - Endereço " + addr + " (" + _ethernetService._ipAddress + "): " + mensagem + Environment.NewLine;
ComandosComunicacao.Add(mensagem);
VariaveisOperacao.RegistrarLogDispositivo(ComandosComunicacao, Caminho, Arquivo, 300);
VariaveisOperacao.RegistrarLogDispositivo(ComandosComunicacao, T_Code.Oid, "_log.txt", 1000);
}
private static async Task tmrLoopComandos_Tick()

View File

@ -110,9 +110,9 @@ namespace AgroBase.Services
Arquivo = "model",
Atualizado = true,
Diretorio = Variaveis.CaminhoModelos + "Ervas\\",
Extensao = ".pt",
Versao = "1_0",
ArquivoDownload = "weed_detector_model-1_0.pt",
Extensao = ".blob",
Versao = "1_1",
ArquivoDownload = "weed_detector_model-1_1.blob",
TipoArquivo = TipoArquivoVersionado.ModeloIA_WeedDetector
},
new VersaoArquivoModel()
@ -120,6 +120,17 @@ namespace AgroBase.Services
id = 2,
Arquivo = "model",
Atualizado = true,
Diretorio = Variaveis.CaminhoModelos + "Ervas\\",
Extensao = ".json",
Versao = "1_1",
ArquivoDownload = "weed_detector_model-1_1.json",
TipoArquivo = TipoArquivoVersionado.ModeloIA_WeedDetector
},
new VersaoArquivoModel()
{
id = 3,
Arquivo = "model",
Atualizado = true,
Diretorio = Variaveis.CaminhoModelos + "Ruas\\",
Extensao = ".pth",
Versao = "1_0",
@ -128,7 +139,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 3,
id = 4,
Arquivo = "labelmap",
Atualizado = true,
Diretorio = Variaveis.CaminhoModelos + "Ruas\\",
@ -139,7 +150,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 4,
id = 5,
Arquivo = "parametersAtu",
Atualizado = true,
Diretorio = Variaveis.CaminhoParametros,
@ -150,29 +161,29 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 5,
id = 6,
Arquivo = "parametersMvd",
Atualizado = true,
Diretorio = Variaveis.CaminhoParametros,
Extensao = ".par",
Versao = "1_0",
ArquivoDownload = "parametersMvd-1_0.par",
Versao = "2_0",
ArquivoDownload = "parametersMvd-2_0.par",
TipoArquivo = TipoArquivoVersionado.ParametrosModulo_MVD
},
new VersaoArquivoModel()
{
id = 6,
id = 7,
Arquivo = "parametersSen",
Atualizado = true,
Diretorio = Variaveis.CaminhoParametros,
Extensao = ".par",
Versao = "1_0",
ArquivoDownload = "parametersSen-1_0.par",
Versao = "1_2",
ArquivoDownload = "parametersSen-1_2.par",
TipoArquivo = TipoArquivoVersionado.ParametrosModulo_SEN
},
new VersaoArquivoModel()
{
id = 7,
id = 8,
Arquivo = "parametersKnt",
Atualizado = true,
Diretorio = Variaveis.CaminhoParametros,
@ -183,7 +194,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 8,
id = 9,
Arquivo = "pinoutAtu",
Atualizado = true,
Diretorio = Variaveis.CaminhoParametros,
@ -194,18 +205,18 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 9,
id = 10,
Arquivo = "pinoutSen",
Atualizado = true,
Diretorio = Variaveis.CaminhoParametros,
Extensao = ".pin",
Versao = "1_0",
ArquivoDownload = "pinoutSen-1_0.pin",
Versao = "1_2",
ArquivoDownload = "pinoutSen-1_2.pin",
TipoArquivo = TipoArquivoVersionado.PinoutModulo_SEN
},
new VersaoArquivoModel()
{
id = 10,
id = 11,
Arquivo = "weed_detector",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoScripts),
@ -216,7 +227,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 11,
id = 12,
Arquivo = "green_detector",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoScripts),
@ -227,7 +238,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 12,
id = 13,
Arquivo = "street_detector",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoScripts),
@ -238,7 +249,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 13,
id = 14,
Arquivo = "map_load",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoScripts),
@ -249,7 +260,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 14,
id = 15,
Arquivo = "map_follow",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoScripts),
@ -260,7 +271,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 15,
id = 16,
Arquivo = "gps_viewer",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoScripts),
@ -271,7 +282,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 16,
id = 17,
Arquivo = "modelo_3d",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoLeitura),
@ -282,7 +293,7 @@ namespace AgroBase.Services
},
new VersaoArquivoModel()
{
id = 17,
id = 18,
Arquivo = "modelo_3d",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoLeitura),
@ -291,6 +302,17 @@ namespace AgroBase.Services
ArquivoDownload = "modelo_3d-1_0.mtl",
TipoArquivo = TipoArquivoVersionado.ArquivoModelo3D
},
new VersaoArquivoModel()
{
id = 19,
Arquivo = "list_oak",
Atualizado = true,
Diretorio = Path.Combine(PythonService.CaminhoGeral, PythonService.CaminhoScripts),
Extensao = ".py",
Versao = "1_0",
ArquivoDownload = "list_oak-1_0.py",
TipoArquivo = TipoArquivoVersionado.ScriptListOAKCaneras
},
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
[{"Momento":"2024-09-12T16:38:04.8284177-03:00","Protocolo":"@1;Sen;258;TMVET,1,411,1,200,0,0,36,-1.038$","Enviado":true},{"Momento":"2024-09-12T16:38:04.8373941-03:00","Protocolo":"Sen;#211;TMVET;1$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.8513564-03:00","Protocolo":"Sen;655;1;$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.8593349-03:00","Protocolo":"Sen;#322;AB5V;5.02;16.48;164.80;830.00$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.8673142-03:00","Protocolo":"@2;Sen;258;TMVEF,1,411,1,200,0,0,34,-1.038$","Enviado":true},{"Momento":"2024-09-12T16:38:04.8752922-03:00","Protocolo":"Sen;#211;TMVEF;1$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.8852658-03:00","Protocolo":"Sen;#322;AB12V;12.18;-0.40;-0.51;6.20$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.8932447-03:00","Protocolo":"Sen;655;2;$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.9101991-03:00","Protocolo":"@3;Sen;258;TMVDT,1,411,1,200,0,0,39,-1.038$","Enviado":true},{"Momento":"2024-09-12T16:38:04.9181774-03:00","Protocolo":"Sen;#211;TMVDT;1$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.929148-03:00","Protocolo":"Sen;655;3;$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.9421136-03:00","Protocolo":"@4;Sen;258;TMVDF,1,411,1,200,0,0,35,-1.038$","Enviado":true},{"Momento":"2024-09-12T16:38:04.9500922-03:00","Protocolo":"Sen;#211;TMVDF;1$\r","Enviado":false},{"Momento":"2024-09-12T16:38:04.961063-03:00","Protocolo":"Sen;655;4;$\r","Enviado":false},{"Momento":"2024-09-12T16:38:15.1069147-03:00","Protocolo":"Sen;#322;AB5VSen;#322;AB12V;12.18;-0.34;-0.52;6.20$\r","Enviado":false},{"Momento":"2024-09-12T16:38:20.1105248-03:00","Protocolo":"Sen;#322;AB5V;5.02;16.71;171.70;874.00$\r","Enviado":false},{"Momento":"2024-09-12T16:38:31.0233228-03:00","Protocolo":"Sen;#411;TMVDT;0.00$\r","Enviado":false},{"Momento":"2024-09-12T16:39:00.2723464-03:00","Protocolo":"Sen;#411;TMVDT;0.00$\r","Enviado":false},{"Momento":"2024-09-12T16:39:15.0946825-03:00","Protocolo":"Sen;#322;AB12V;12.18;-0.47;-0.63;7.20$\r","Enviado":false},{"Momento":"2024-09-12T16:39:20.1182406-03:00","Protocolo":"Sen;#322;AB5V;5.02;16.23;173.10;866.00$\r","Enviado":false},{"Momento":"2024-09-12T16:40:15.046882-03:00","Protocolo":"Sen;#322;AB5V;5.02;17.00;167.30;838.00$\r","Enviado":false},{"Momento":"2024-09-12T16:40:20.1278268-03:00","Protocolo":"Sen;#322;AB5V;5.02;16.88;163.10;820.00$\r","Enviado":false}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
[{"Momento":"2024-08-20T15:08:36.0547612-03:00","Protocolo":"@1;Sen;258;LEDMN,1,0,4$","Enviado":true},{"Momento":"2024-08-20T15:08:36.0607483-03:00","Protocolo":"Sen;#211;LEDMN;1$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.5339526-03:00","Protocolo":"@11;Sen;258;LEDMN,1,0,4$","Enviado":true},{"Momento":"2024-08-20T15:08:44.539949-03:00","Protocolo":"Sen;#211;LEDMN;1$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.551426-03:00","Protocolo":"Sen;655;11;$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.563916-03:00","Protocolo":"@12;Sen;258;LEDAT,1,0,16$","Enviado":true},{"Momento":"2024-08-20T15:08:44.5694099-03:00","Protocolo":"Sen;#211;LEDAT;1$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.5808998-03:00","Protocolo":"Sen;655;12;$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.5958868-03:00","Protocolo":"@13;Sen;258;LEDOP,1,0,17$","Enviado":true},{"Momento":"2024-08-20T15:08:44.601873-03:00","Protocolo":"Sen;#211;LEDOP;1$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.6123691-03:00","Protocolo":"Sen;655;13;$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.6278632-03:00","Protocolo":"@14;Sen;258;FRO_DT,1,0,25$","Enviado":true},{"Momento":"2024-08-20T15:08:44.6328498-03:00","Protocolo":"Sen;#211;FRO_DT;1$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.6458464-03:00","Protocolo":"Sen;655;14;$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.6573421-03:00","Protocolo":"@15;Sen;258;MD,1,500,0,0,21,0,22$","Enviado":true},{"Momento":"2024-08-20T15:08:44.6633261-03:00","Protocolo":"Sen;#211;MD;1$\r","Enviado":false},{"Momento":"2024-08-20T15:08:44.7757374-03:00","Protocolo":"Sen;655;15;$\r","Enviado":false},{"Momento":"2024-08-20T15:10:13.80715-03:00","Protocolo":"@16;Sen;258;LEDMN,0,0,4$","Enviado":true},{"Momento":"2024-08-20T15:10:13.8450994-03:00","Protocolo":"Sen;#211;LEDMN;0$\r","Enviado":false},{"Momento":"2024-08-20T15:10:13.8545799-03:00","Protocolo":"Sen;655;16;$\r","Enviado":false},{"Momento":"2024-08-20T15:10:13.8758873-03:00","Protocolo":"@17;Sen;258;LEDAT,0,0,16$","Enviado":true},{"Momento":"2024-08-20T15:10:13.8818732-03:00","Protocolo":"Sen;#211;LEDAT;0$\r","Enviado":false},{"Momento":"2024-08-20T15:10:13.8933667-03:00","Protocolo":"Sen;655;17;$\r","Enviado":false},{"Momento":"2024-08-20T15:10:13.9073622-03:00","Protocolo":"@18;Sen;258;LEDOP,0,0,17$","Enviado":true},{"Momento":"2024-08-20T15:10:13.9143439-03:00","Protocolo":"Sen;#211;LEDOP;0$\r","Enviado":false},{"Momento":"2024-08-20T15:10:13.9748221-03:00","Protocolo":"U??655;18;$\r","Enviado":false},{"Momento":"2024-08-20T15:10:15.4183069-03:00","Protocolo":"@19;Sen;258;FRO_DT,0,0,25$","Enviado":true},{"Momento":"2024-08-20T15:10:15.4247942-03:00","Protocolo":"Sen;#211;FRO_DT;0$\r","Enviado":false},{"Momento":"2024-08-20T15:10:15.435295-03:00","Protocolo":"Sen;655;19;$\r","Enviado":false},{"Momento":"2024-08-20T15:10:15.4497671-03:00","Protocolo":"@20;Sen;258;MD,0,500,0,0,21,0,22$","Enviado":true},{"Momento":"2024-08-20T15:10:15.4572726-03:00","Protocolo":"Sen;#211;MD;0$\r","Enviado":false},{"Momento":"2024-08-20T15:10:15.5667904-03:00","Protocolo":"Sen;655;20;$\r","Enviado":false},{"Momento":"2024-08-20T15:10:15.5773118-03:00","Protocolo":"@18;Sen;258;LEDOP,0,0,17$","Enviado":true},{"Momento":"2024-08-20T15:10:15.5832957-03:00","Protocolo":"Sen;#211;LEDOP;0$\r","Enviado":false},{"Momento":"2024-08-20T15:10:15.5943694-03:00","Protocolo":"Sen;655;18;$\r","Enviado":false}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"tmrRegistrador":{"_uiControl":null,"State":2,"IsRunning":false,"IsStopped":true,"IsCreated":false,"Interval":500,"StackTrace":"AtuadorModel.IniciarRegistrador","Id":"tmrRegistrador_Atu","TimeTick":"00:00:00"},"Modulo_ID":"Atu","IP":"192.168.100.13","RequisitarDados":true,"Conectado":false,"QuantidadeBicos":4,"DensidadeHerbicida":1.05,"BicosPulverizadores":[{"ID":"B01","Posicao":1,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":0.0,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B02","Posicao":2,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":0.0,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B03","Posicao":3,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":2.2843163884147217,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B04","Posicao":4,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":0.0,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0}],"BombasPressurizadoras":[{"ID":"BOMBA","ComandoAtuar":false,"Componente":325,"LeituraEstado":false,"Comandar":true,"Testando":false,"Funcoes":[14,35,36,37,5],"LeituraPotencia":0.0,"LeituraPressaoSP":0.0,"LeituraPressao":0.0,"Leitura":null,"Inicializado":false}],"Sensores":[{"LogGrafico":[],"ID":"FLXLN","Prioridade":23,"Descricao":"Fluxo na linha principal","Componente":198,"Aferir":true,"DelayAmostragem":300,"Leitura":null,"Inicializado":false,"Testando":false,"Funcoes":[25],"Parametros":[],"UnidadeMedida":"mL/s","LimiteMaximo":0.0,"LimiteMinimo":0.0},{"LogGrafico":[],"ID":"MASRS","Prioridade":3,"Descricao":"Massa do reservatório de herbicida","Componente":532,"Aferir":true,"DelayAmostragem":1000,"Leitura":null,"Inicializado":false,"Testando":false,"Funcoes":[22,23],"Parametros":[],"UnidadeMedida":"Kg","LimiteMaximo":50.0,"LimiteMinimo":5.0},{"LogGrafico":[],"ID":"PRSLN","Prioridade":3,"Descricao":"Pressão na linha principal","Componente":333,"Aferir":true,"DelayAmostragem":1000,"Leitura":null,"Inicializado":false,"Testando":false,"Funcoes":[24],"Parametros":[["Vmin","000.00"],["Vmax","004.50"],["Pmax","174.04"]],"UnidadeMedida":"psi","LimiteMaximo":120.0,"LimiteMinimo":60.0}],"BombaPressurizadora":{"ID":"BOMBA","ComandoAtuar":false,"Componente":325,"LeituraEstado":false,"Comandar":true,"Testando":false,"Funcoes":[14,35,36,37,5],"LeituraPotencia":0.0,"LeituraPressaoSP":0.0,"LeituraPressao":0.0,"Leitura":null,"Inicializado":false},"ScriptDeteccaoErvas":"weed_detector_oak-1_0.py","DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"BicosPulverizadores":[],"BombasPressurizadoras":[],"SensoresFluxo":[],"SensoresMassa":[],"SensoresPressao":[]},"_MassaRef":0.8,"_MassaLeituraRef":40876.37,"_MassaLeituraExtra":1895800.0,"MassaReservatorio":0.0,"VolumeReservatorio":0.0,"PercentualReservatorio":0.0,"VolumeVazaoAferido":0.0,"_FluxoMlRef":102.0,"_FluxoPulsoRef":80.0,"VazaoFluxoMLpSInstantanea":0.0,"VazaoFluxoMLpSMedia":0.0,"VolumeVazaoML":0.0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0,"_PressaoVmin":0.0,"_PressaoVmax":4.5,"_PressaoMax":174.045,"PressaoLinha":0.0,"PressaoLinhaCalc":0.0,"PercentualErvasTerreno":0.0}
{"tmrRegistrador":{"_uiControl":null,"State":2,"IsRunning":false,"IsStopped":true,"IsCreated":false,"Interval":500,"StackTrace":"AtuadorModel.IniciarRegistrador","Id":"tmrRegistrador_Atu","TimeTick":"00:00:00"},"Modulo_ID":"Atu","IP":"192.168.100.13","RequisitarDados":true,"Conectado":false,"QuantidadeBicos":4,"DensidadeHerbicida":1.05,"BicosPulverizadores":[{"ID":"B01","Posicao":1,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":0.0,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B02","Posicao":2,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":0.0,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B03","Posicao":3,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":0.0,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0},{"ID":"B04","Posicao":4,"Componente":422,"AtuacaoNivelAlto":true,"ComandoAtuar":false,"Comandar":true,"Testando":false,"Funcoes":[21],"LeituraStatusBico":false,"MediaNivelFluxo":0.21614702381868367,"Leitura":null,"Inicializado":false,"Atuacoes":0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0}],"BombasPressurizadoras":[{"ID":"BOMBA","ComandoAtuar":false,"Componente":325,"LeituraEstado":false,"Comandar":true,"Testando":false,"Funcoes":[14,35,36,37,5],"LeituraPotencia":0.0,"LeituraPressaoSP":0.0,"LeituraPressao":0.0,"Leitura":null,"Inicializado":false}],"Sensores":[{"LogGrafico":[],"ID":"FLXLN","Prioridade":23,"Descricao":"Fluxo na linha principal","Componente":198,"Aferir":true,"DelayAmostragem":300,"Leitura":null,"Inicializado":false,"Testando":false,"Funcoes":[25],"Parametros":[],"UnidadeMedida":"mL/s","LimiteMaximo":0.0,"LimiteMinimo":0.0},{"LogGrafico":[],"ID":"MASRS","Prioridade":3,"Descricao":"Massa do reservatório de herbicida","Componente":532,"Aferir":true,"DelayAmostragem":1000,"Leitura":null,"Inicializado":false,"Testando":false,"Funcoes":[22,23],"Parametros":[],"UnidadeMedida":"Kg","LimiteMaximo":50.0,"LimiteMinimo":5.0},{"LogGrafico":[],"ID":"PRSLN","Prioridade":3,"Descricao":"Pressão na linha principal","Componente":333,"Aferir":true,"DelayAmostragem":1000,"Leitura":null,"Inicializado":false,"Testando":false,"Funcoes":[24],"Parametros":[["Vmin","000.00"],["Vmax","004.50"],["Pmax","174.04"]],"UnidadeMedida":"psi","LimiteMaximo":120.0,"LimiteMinimo":60.0}],"BombaPressurizadora":{"ID":"BOMBA","ComandoAtuar":false,"Componente":325,"LeituraEstado":false,"Comandar":true,"Testando":false,"Funcoes":[14,35,36,37,5],"LeituraPotencia":0.0,"LeituraPressaoSP":0.0,"LeituraPressao":0.0,"Leitura":null,"Inicializado":false},"ScriptDeteccaoErvas":"weed_detector_oak-1_0.py","DadosLeitura":{"Momento":"0001-01-01T00:00:00","Conectado":false,"Mod_ID":null,"QualidadeWifi":0,"LatenciaLoop":0,"BicosPulverizadores":[],"BombasPressurizadoras":[],"SensoresFluxo":[],"SensoresMassa":[],"SensoresPressao":[]},"_MassaRef":0.8,"_MassaLeituraRef":40876.37,"_MassaLeituraExtra":1895800.0,"MassaReservatorio":0.0,"VolumeReservatorio":0.0,"PercentualReservatorio":0.0,"VolumeVazaoAferido":0.0,"_FluxoMlRef":102.0,"_FluxoPulsoRef":80.0,"VazaoFluxoMLpSInstantanea":0.0,"VazaoFluxoMLpSMedia":0.0,"VolumeVazaoML":0.0,"InicioAtuacao":"0001-01-01T00:00:00","TempoAtuado":0.0,"_PressaoVmin":0.0,"_PressaoVmax":4.5,"_PressaoMax":174.045,"PressaoLinha":0.0,"PressaoLinhaCalc":0.0,"PercentualErvasTerreno":0.0}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -142,12 +142,12 @@
{
"id": 13,
"Diretorio": "Python\\Scripts\\",
"Arquivo": "street_detector_oak",
"Arquivo": "street_detector",
"Extensao": ".py",
"Versao": "1_0",
"ArquivoDownload": "street_detector_oak-1_0.py",
"NomeArquivoLocal": "street_detector_oak-1_0.py",
"CaminhoCompleto": "Python\\Scripts\\street_detector_oak-1_0.py",
"ArquivoDownload": "street_detector-1_0.py",
"NomeArquivoLocal": "street_detector-1_0.py",
"CaminhoCompleto": "Python\\Scripts\\street_detector-1_0.py",
"Atualizado": true,
"ArquivoAtualizado": true,
"TipoArquivo": 8

File diff suppressed because one or more lines are too long

View File

@ -25,7 +25,7 @@
<meta name="viewport" content="width=device-width,
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<style>
#map_a884af1c3adf4e85c47a15fa5949a894 {
#map_24f04295d05bcd5705a0ddda1f260790 {
position: relative;
width: 100.0%;
height: 100.0%;
@ -39,14 +39,14 @@
<body>
<div class="folium-map" id="map_a884af1c3adf4e85c47a15fa5949a894" ></div>
<div class="folium-map" id="map_24f04295d05bcd5705a0ddda1f260790" ></div>
</body>
<script>
var map_a884af1c3adf4e85c47a15fa5949a894 = L.map(
"map_a884af1c3adf4e85c47a15fa5949a894",
var map_24f04295d05bcd5705a0ddda1f260790 = L.map(
"map_24f04295d05bcd5705a0ddda1f260790",
{
center: [0.0, 0.0],
crs: L.CRS.EPSG3857,
@ -60,13 +60,13 @@
var tile_layer_6130635c5242ebe8049446b60f4118fd = L.tileLayer(
var tile_layer_059c48f01310aa947f11fa8e0071548e = L.tileLayer(
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
{"attribution": "\u0026copy; \u003ca href=\"https://www.openstreetmap.org/copyright\"\u003eOpenStreetMap\u003c/a\u003e contributors", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 19, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false}
);
tile_layer_6130635c5242ebe8049446b60f4118fd.addTo(map_a884af1c3adf4e85c47a15fa5949a894);
tile_layer_059c48f01310aa947f11fa8e0071548e.addTo(map_24f04295d05bcd5705a0ddda1f260790);
</script>
@ -87,7 +87,7 @@
}
trajeto_json_add({"features": []});
trajeto_json.addTo(map_a884af1c3adf4e85c47a15fa5949a894);
trajeto_json.addTo(map_24f04295d05bcd5705a0ddda1f260790);
function adicionarGeometria(novaGeometria) {
trajeto_json.addData(novaGeometria);
@ -145,7 +145,7 @@
var marcadorDinamico = L.marker([0, 0], {
icon: customIcon
}).addTo(map_a884af1c3adf4e85c47a15fa5949a894);
}).addTo(map_24f04295d05bcd5705a0ddda1f260790);
// Conectar ao broker MQTT
const client = mqtt.connect('ws://localhost:9001'); // Use wss para conexão segura
@ -183,7 +183,7 @@
marcadorDinamico.setRotationAngle(angulo);
adicionarCoordenada("Tj", [novaLongitude, novaLatitude]);
map_a884af1c3adf4e85c47a15fa5949a894.setView(novaPosicao, map_a884af1c3adf4e85c47a15fa5949a894.getZoom());
map_24f04295d05bcd5705a0ddda1f260790.setView(novaPosicao, map_24f04295d05bcd5705a0ddda1f260790.getZoom());
});
function calcularOrientacao(P1latitude, P1longitude, P2latitude, P2longitude) {

File diff suppressed because one or more lines are too long

View File

@ -35,10 +35,6 @@ NUM_CLASSES = 4 # Pascal VOC possui 3 classes + 1 para o fundo
OUTPUT_STRIDE = 16 # Valor comum para DeepLab
MODEL_PATH = model_folder + "model-" + script_version + '.pth' # Caminho para o modelo pré-treinado
# Variáveis globais para armazenar os dados do labelmap
label_colors = None
class_names = None
# Função para carregar o modelo
def load_model(model_path):
model = deeplabv3_model(num_classes=NUM_CLASSES, output_stride=OUTPUT_STRIDE)
@ -69,22 +65,19 @@ def segment_frame(frame):
# Função para ler o mapa de rótulos
def read_labelmap(path):
global label_colors, class_names
if label_colors is None or class_names is None: # Verifica se já estão carregados
label_colors = []
class_names = []
with open(path, 'r') as file:
for line in file.readlines():
if line.startswith('#'):
continue
parts = line.strip().split(':')
if len(parts) >= 2:
label = parts[0].strip()
color = tuple(map(int, parts[1].split(',')))
class_names.append(label)
label_colors.append(color)
label_colors = np.array(label_colors)
return label_colors, class_names
label_colors = []
class_names = []
with open(path, 'r') as file:
for line in file.readlines():
if line.startswith('#'):
continue
parts = line.strip().split(':')
if len(parts) >= 2:
label = parts[0].strip()
color = tuple(map(int, parts[1].split(',')))
class_names.append(label)
label_colors.append(color)
return np.array(label_colors), class_names
# Função para gerar o JSON de saída
def generate_json(image):

View File

@ -7,7 +7,7 @@ import sys
import threading
import paho.mqtt.client as mqtt
import uuid
from flask import Flask, Response
from flask import Flask, Response, request
# 🔹 Configurações MQTT
mqtt_client = mqtt.Client(f"client_oak_d_lite_{uuid.uuid4()}")
@ -15,149 +15,57 @@ mqtt_client.connect("localhost", port=1883)
# 🔹 Parâmetros de entrada
output_folder = 'Python/Output/'
mqtt_topic = sys.argv[1] # Tópico MQTT para envio dos dados
mqtt_topic = sys.argv[1] # Tópico MQTT para envio dos dados de profundidade
porta = int(sys.argv[2]) # Porta do Flask
url_rgb = sys.argv[3] # URL do vídeo RGB
url_heatmap = sys.argv[4] # URL do vídeo do Heatmap
max_readings = int(sys.argv[5])
camera_index = int(sys.argv[6])
url = sys.argv[3] # URL do vídeo
max_readings = int(sys.argv[4])
# 🔹 Flask App
app = Flask(__name__)
# Função para calcular a moda de um array unidimensional
def calc_mode(values):
# Arredonda os valores para eliminar pequenas variações
rounded = np.round(values, 0)
vals, counts = np.unique(rounded, return_counts=True)
return vals[np.argmax(counts)]
# Configuração de filtros
NUM_FRAMES_SMOOTH = 5 # Número de frames para suavização temporal
SMOOTH_KERNEL = (5, 5) # Tamanho do kernel para suavização espacial
OUTLIER_THRESHOLD = 50 # Limiar para remoção de outliers
depth_buffer = [] # Buffer para armazenar os últimos frames de profundidade
# Suavização Temporal
def smooth_depth(depth_frame):
global depth_buffer
if len(depth_buffer) >= NUM_FRAMES_SMOOTH:
depth_buffer.pop(0) # Remove o frame mais antigo
depth_buffer.append(depth_frame) # Adiciona o novo frame
return np.mean(depth_buffer, axis=0).astype(np.uint16) # Retorna a média
# Suavização Espacial (Filtro Gaussiano)
def gaussian_smooth(depth_frame):
return cv2.GaussianBlur(depth_frame, SMOOTH_KERNEL, 0)
# Filtro de Mediana para Remover Ruídos
def median_filter(depth_frame):
return cv2.medianBlur(depth_frame, 5)
# Remover Outliers (Saltos Extremos)
def remove_outliers(depth_frame):
depth_median = cv2.medianBlur(depth_frame, 5)
diff = np.abs(depth_frame - depth_median)
depth_frame[diff > OUTLIER_THRESHOLD] = depth_median[diff > OUTLIER_THRESHOLD]
return depth_frame
# Aplicar filtros no depthFrame
def apply_depth_filters(depth_frame):
if filtro1:
depth_frame = smooth_depth(depth_frame) # 1. Suavização Temporal
if filtro2:
depth_frame = gaussian_smooth(depth_frame) # 2. Suavização Espacial
if filtro3:
depth_frame = median_filter(depth_frame) # 3. Filtro de Mediana
if filtro4:
depth_frame = remove_outliers(depth_frame) # 4. Remoção de Outliers
return depth_frame
# Função para gerar o mapa de calor da profundidade
def generate_heatmap(depth_frame):
normalized_depth = cv2.normalize(depth_frame, None, 0, 255, cv2.NORM_MINMAX)
heatmap = cv2.applyColorMap(normalized_depth.astype(np.uint8), cv2.COLORMAP_JET)
return heatmap
# ───────────────────────────────────────────────
# Configurações da câmera e das matrizes
# ───────────────────────────────────────────────
RGB_WIDTH, RGB_HEIGHT = 640, 480
WIDTH, HEIGHT = 320, 240
# Região do solo (grid A - parte inferior): ocupa 50% da altura da imagem
GROUND_ROWS = 10 # Número de linhas da matriz do solo
GROUND_CELLS = 10 # Número de células por linha
GROUND_REGION_HEIGHT = int(HEIGHT * 0.5) # 50% da altura da imagem
GROUND_TOP_SCALE = 0.5 # A linha mais distante (superior da região) terá 35% da largura total
DEPTH_LIMIT = 50 # (Valor de referência para comparação, mas agora usamos calibração)
# Região aérea (parte superior): ocupa o restante da imagem
AIR_ROWS = 10 # Número de linhas na matriz aérea
AIR_COLS = 15 # Número de colunas na matriz aérea
AIR_REGION_HEIGHT = HEIGHT - GROUND_REGION_HEIGHT # Altura da região aérea
# ───────────────────────────────────────────────
# Parâmetros para calibração e detecção com moda
# ───────────────────────────────────────────────
NUM_CALIB_FRAMES = 100 # Número de frames para calibração
NUM_DETECT_FRAMES = 10 # Número de frames para acumulação antes de calcular a moda na detecção
# Variável global para armazenar o frame de profundidade atual (para uso no callback)
current_depth_frame = None
show_grid = False
filtro1 = True
filtro2 = True
filtro3 = True
filtro4 = True
# ───────────────────────────────────────────────
# Criação do pipeline DepthAI
# ───────────────────────────────────────────────
# 🔹 Criando o pipeline
pipeline = dai.Pipeline()
# Nó da câmera RGB
width, height = 1280, 720
# 📷 Câmera RGB
cam_rgb = pipeline.create(dai.node.ColorCamera)
cam_rgb.setPreviewSize(RGB_WIDTH, RGB_HEIGHT)
cam_rgb.setPreviewSize(width, height)
cam_rgb.setBoardSocket(dai.CameraBoardSocket.RGB)
cam_rgb.setInterleaved(False)
# Criar XLinkOut para saída RGB
xout_rgb = pipeline.create(dai.node.XLinkOut)
xout_rgb.setStreamName("rgb")
cam_rgb.preview.link(xout_rgb.input)
# Nó de profundidade
# 🔹 Câmera de Profundidade
mono_left = pipeline.create(dai.node.MonoCamera)
mono_right = pipeline.create(dai.node.MonoCamera)
mono_left.setResolution(dai.MonoCameraProperties.SensorResolution.THE_480_P)
mono_right.setResolution(dai.MonoCameraProperties.SensorResolution.THE_480_P)
stereo = pipeline.create(dai.node.StereoDepth)
mono_left.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
mono_right.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
mono_left.setBoardSocket(dai.CameraBoardSocket.LEFT)
mono_right.setBoardSocket(dai.CameraBoardSocket.RIGHT)
stereo = pipeline.create(dai.node.StereoDepth)
stereo.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.ROBOTICS)
#stereo.initialConfig.setConfidenceThreshold(250) # Remove ruído, mantendo apenas pontos confiáveis
#stereo.initialConfig.setMedianFilter(dai.MedianFilter.KERNEL_7x7) # Usa filtro de mediana forte
#stereo.setLeftRightCheck(True) # Ativa verificação para evitar erros
#stereo.setExtendedDisparity(False) # Reduz ruído em distâncias curtas
#stereo.setSubpixel(True) # Aumenta a precisão da profundidade
# Configuração do StereoDepth
stereo.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY)
stereo.setLeftRightCheck(True)
stereo.setSubpixel(True)
mono_left.out.link(stereo.left)
mono_right.out.link(stereo.right)
# Criar XLinkOut para profundidade
xout_depth = pipeline.create(dai.node.XLinkOut)
xout_depth.setStreamName("depth")
stereo.depth.link(xout_depth.input)
device_global = None
selected_device_info = None
camera_iniciada = False
def initialize_device():
global device_global, selected_device_info, camera_iniciada
# 🔹 Função para enviar vídeo via Flask
def generate_video(camera_index):
# Listar todas as câmeras conectadas
devices = dai.Device.getAllAvailableDevices()
@ -172,407 +80,86 @@ def initialize_device():
selected_device_info = devices[camera_index] # Seleciona a câmera correta pelo índice
print(f"Usando câmera: {selected_device_info.name} (ID: {selected_device_info.mxid})")
device_global = dai.Device(pipeline, selected_device_info)
camera_iniciada = True
with dai.Device(pipeline, selected_device_info) as device: # 🔹 Agora usa a câmera correta
rgb_queue = device.getOutputQueue(name="rgb", maxSize=4, blocking=False)
depth_queue = device.getOutputQueue(name="depth", maxSize=4, blocking=False)
# 🔹 Função para enviar vídeo via Flask
def process_depth_data():
readings = []
if camera_iniciada == False:
initialize_device()
global device_global, selected_device_info
while True:
frame_data = rgb_queue.get()
if frame_data is None:
continue
depth_queue = device_global.getOutputQueue(name="depth", maxSize=1, blocking=False)
timestamp = time.time()
# Função para calibrar a região do solo utilizando a moda
def calibrate_ground():
print("Calibrando região do solo: coletando {} frames...".format(NUM_CALIB_FRAMES))
calib_data = np.zeros((GROUND_ROWS, GROUND_CELLS, NUM_CALIB_FRAMES))
for frame_idx in range(NUM_CALIB_FRAMES):
# 📏 Captura Profundidade
depth_frame = depth_queue.get().getFrame()
depth_frame = apply_depth_filters(depth_frame)
for i in range(GROUND_ROWS):
y_start = HEIGHT - GROUND_REGION_HEIGHT + i * row_height_ground
y_end = y_start + row_height_ground
scale = GROUND_TOP_SCALE + (i / (GROUND_ROWS - 1)) * (1 - GROUND_TOP_SCALE) if GROUND_ROWS > 1 else 1
effective_width = int(WIDTH * scale)
cell_width = effective_width / GROUND_CELLS
for j in range(GROUND_CELLS):
x_start = int(WIDTH / 2 - effective_width / 2 + j * cell_width)
x_end = int(x_start + cell_width)
calib_data[i, j, frame_idx] = np.mean(depth_frame[y_start:y_end, x_start:x_end])
ground_ref = np.zeros((GROUND_ROWS, GROUND_CELLS))
for i in range(GROUND_ROWS):
for j in range(GROUND_CELLS):
ground_ref[i, j] = calc_mode(calib_data[i, j, :])
print("Calibração da região do solo concluída!")
return ground_ref
# Função para calibrar a região aérea utilizando a moda
def calibrate_air():
print("Calibrando região aérea: coletando {} frames...".format(NUM_CALIB_FRAMES))
calib_data_air = np.zeros((AIR_ROWS, AIR_COLS, NUM_CALIB_FRAMES))
row_height_air = AIR_REGION_HEIGHT // AIR_ROWS
cell_width_air = WIDTH // AIR_COLS
for frame_idx in range(NUM_CALIB_FRAMES):
depth_frame = depth_queue.get().getFrame()
depth_frame = apply_depth_filters(depth_frame)
for i in range(AIR_ROWS):
y_start = i * row_height_air
y_end = y_start + row_height_air
for j in range(AIR_COLS):
x_start = j * cell_width_air
x_end = x_start + cell_width_air
calib_data_air[i, j, frame_idx] = np.mean(depth_frame[y_start:y_end, x_start:x_end])
air_ref = np.zeros((AIR_ROWS, AIR_COLS))
for i in range(AIR_ROWS):
for j in range(AIR_COLS):
air_ref[i, j] = calc_mode(calib_data_air[i, j, :])
print("Calibração da região aérea concluída!")
return air_ref
# Normaliza a profundidade para visualização (mapa de calor)
depth_visual = cv2.normalize(depth_frame, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)
depth_visual = cv2.applyColorMap(depth_visual, cv2.COLORMAP_JET)
# Função para calibrar a distância utilizando a moda
def calibrate_distance(alvo=2500):
global GROUND_REGION_HEIGHT, AIR_REGION_HEIGHT # Garantir que estamos alterando as variáveis globais
NUM_LINHAS_ANALISE = 80 # Número de linhas horizontais para análise
ALTURA_LINHA = HEIGHT // NUM_LINHAS_ANALISE # Altura de cada linha
PROFUNDIDADE_ALVO = alvo # Profundidade alvo em cm para definir a região do solo dinamicamente
media_profundidade_acumulada = np.zeros((NUM_LINHAS_ANALISE, NUM_CALIB_FRAMES))
print("Calibrando profundidade média com {} frames...".format(NUM_CALIB_FRAMES))
for frame_idx in range(NUM_CALIB_FRAMES):
depth_frame = depth_queue.get().getFrame()
depth_frame = apply_depth_filters(depth_frame)
for i in range(NUM_LINHAS_ANALISE):
y_start = HEIGHT - (i + 1) * ALTURA_LINHA
y_end = y_start + ALTURA_LINHA
x_start_crop = int(WIDTH * 0.0)
x_end_crop = int(WIDTH * 1.0)
region_values = depth_frame[y_start:y_end, x_start_crop:x_end_crop].flatten()
valid_values = region_values[(region_values > 0) & (region_values < 10000)]
if valid_values.size > 0:
media_profundidade_acumulada[i, frame_idx] = np.mean(valid_values)
else:
media_profundidade_acumulada[i, frame_idx] = 9999
media_profundidade = np.array([calc_mode(media_profundidade_acumulada[i, :]) for i in range(NUM_LINHAS_ANALISE)])
#print("Médias de profundidade por linha (usando moda):", media_profundidade)
erro_minimo = float('inf')
linha_alvo = None
for i in range(NUM_LINHAS_ANALISE):
erro = abs(media_profundidade[i] - PROFUNDIDADE_ALVO)
if erro < erro_minimo:
erro_minimo = erro
linha_alvo = i
if linha_alvo is not None:
linha_alvo += 1
GROUND_REGION_HEIGHT = HEIGHT - ((NUM_LINHAS_ANALISE - linha_alvo) * ALTURA_LINHA)
else:
GROUND_REGION_HEIGHT = HEIGHT // 2
AIR_REGION_HEIGHT = HEIGHT - GROUND_REGION_HEIGHT
v = GROUND_REGION_HEIGHT // GROUND_ROWS
print("Novo GROUND_REGION_HEIGHT:", GROUND_REGION_HEIGHT)
print("Novo AIR_REGION_HEIGHT:", AIR_REGION_HEIGHT)
print("Novo tamanho das linhas do solo:", v)
return v
# Gerar json dos dados das subdivisoes
def gerar_json_subdivisoes():
data = {
"x_max": WIDTH,
"y_max": HEIGHT,
"subdivisoes_cima": {
"num_linhas": AIR_ROWS,
"num_colunas": AIR_COLS,
"celulas": []
},
"subdivisoes_chao": {
"num_linhas": GROUND_ROWS,
"num_colunas": GROUND_CELLS,
"celulas": []
}
}
# Subdivisões da região aérea
row_height_air = AIR_REGION_HEIGHT // AIR_ROWS
cell_width_air = WIDTH // AIR_COLS
for i in range(AIR_ROWS):
for j in range(AIR_COLS):
x_start = j * cell_width_air
y_start = i * row_height_air
data["subdivisoes_cima"]["celulas"].append({
"linha": i,
"coluna": j,
"x": x_start,
"y": y_start,
"largura": cell_width_air,
"altura": row_height_air,
"profundidade_media": smoothed_air[i, j],
"profundidade_calibragem": air_reference[i, j]
})
# Subdivisões da região do solo
row_height_ground = GROUND_REGION_HEIGHT // GROUND_ROWS
for i in range(GROUND_ROWS):
scale = (GROUND_TOP_SCALE + (i / (GROUND_ROWS - 1)) * (1 - GROUND_TOP_SCALE)) if GROUND_ROWS > 1 else 1
effective_width = int(WIDTH * scale)
cell_width = effective_width / GROUND_CELLS
y_start = HEIGHT - GROUND_REGION_HEIGHT + i * row_height_ground
start_x = int(WIDTH / 2 - effective_width / 2)
# 📡 Enviar dados via MQTT (Apenas a matriz de profundidade reduzida)
depth_data = depth_frame.tolist() # Converte a matriz para lista JSON
for j in range(GROUND_CELLS):
x_start = int(start_x + j * cell_width)
data["subdivisoes_chao"]["celulas"].append({
"linha": i,
"coluna": j,
"x": x_start,
"y": y_start,
"largura": int(cell_width),
"altura": row_height_ground,
"profundidade_media": smoothed_ground[i, j],
"profundidade_calibragem": ground_reference[i, j]
})
return json.dumps(data, indent=4)
# Calibração inicial
row_height_ground = calibrate_distance()
ground_reference = calibrate_ground()
air_reference = calibrate_air()
# Preparação para a detecção usando moda (acumula dados de alguns frames)
detect_counter = 0
detect_data_ground = np.zeros((GROUND_ROWS, GROUND_CELLS, NUM_DETECT_FRAMES))
detect_data_air = np.zeros((AIR_ROWS, AIR_COLS, NUM_DETECT_FRAMES))
last_detect_ground = np.zeros((GROUND_ROWS, GROUND_CELLS))
last_detect_air = np.zeros((AIR_ROWS, AIR_COLS))
# Parâmetro para o filtro de média móvel
alpha = 0.4 # ajuste entre 0 e 1 (valores menores = mais suave)
# Inicialize as grids filtradas com os valores de calibração (ou com zeros, se preferir)
smoothed_ground = ground_reference.copy()
smoothed_air = air_reference.copy()
last_time = time.time()
target_fps = 30 # Limita o FPS
readings = []
while True:
current_time = time.time()
if current_time - last_time < 1 / target_fps:
time.sleep(0.01)
continue
last_time = current_time
in_depth = depth_queue.tryGet()
if in_depth is None:
continue
depth_frame = in_depth.getFrame()
# Aplicação dos filtros em sequência
depth_frame = apply_depth_filters(depth_frame)
# Gera o mapa de calor
heatmap = generate_heatmap(depth_frame)
# Cria uma cópia do heatmap para desenhar o overlay
heatmap_overlay = heatmap.copy()
# ─────────────────────────────────────────────
# Atualiza a grid do SOLO (região inferior) com média móvel
# ─────────────────────────────────────────────
for i in range(GROUND_ROWS):
y_start = HEIGHT - GROUND_REGION_HEIGHT + i * row_height_ground
y_end = y_start + row_height_ground
scale = (GROUND_TOP_SCALE +
(i / (GROUND_ROWS - 1)) * (1 - GROUND_TOP_SCALE)) if GROUND_ROWS > 1 else 1
effective_width = int(WIDTH * scale)
cell_width = effective_width / GROUND_CELLS
for j in range(GROUND_CELLS):
x_start = int(WIDTH / 2 - effective_width / 2 + j * cell_width)
x_end = int(x_start + cell_width)
# Obtém os valores válidos da região
region_values = depth_frame[y_start:y_end, x_start:x_end].flatten()
valid_values = region_values[(region_values > 0) & (region_values < 10000)] # Remove valores inválidos
# Calcula a média da célula e atualiza as variáveis
if valid_values.size > 0:
measurement = np.mean(valid_values)
else:
measurement = 9999 # Define um valor alto se não houver dados válidos
# Atualiza a grid suavizada com a média móvel
smoothed_ground[i, j] = alpha * measurement + (1 - alpha) * smoothed_ground[i, j]
# Atualiza a matriz last_detect_ground com a média real da célula
last_detect_ground[i, j] = measurement
# ─────────────────────────────────────────────
# Atualiza a grid da REGIÃO AÉREA (parte superior) com média móvel
# ─────────────────────────────────────────────
row_height_air = AIR_REGION_HEIGHT // AIR_ROWS
cell_width_air = WIDTH // AIR_COLS
for i in range(AIR_ROWS):
y_start = i * row_height_air
y_end = y_start + row_height_air
for j in range(AIR_COLS):
x_start = j * cell_width_air
x_end = x_start + cell_width_air
# Obtém os valores válidos da região
region_values = depth_frame[y_start:y_end, x_start:x_end].flatten()
valid_values = region_values[(region_values > 0) & (region_values < 10000)] # Remove valores inválidos
# Calcula a média da célula e atualiza as variáveis
if valid_values.size > 0:
measurement = np.mean(valid_values)
else:
measurement = 9999 # Define um valor alto se não houver dados válidos
# Atualiza a grid suavizada com a média móvel
smoothed_air[i, j] = alpha * measurement + (1 - alpha) * smoothed_air[i, j]
# Atualiza a matriz last_detect_air com a média real da célula
last_detect_air[i, j] = measurement
# ─────────────────────────────────────────────
# Processamento da detecção: Região do SOLO
# ─────────────────────────────────────────────
for i in range(GROUND_ROWS):
y_start = HEIGHT - GROUND_REGION_HEIGHT + i * row_height_ground
y_end = y_start + row_height_ground
scale = (GROUND_TOP_SCALE + (i / (GROUND_ROWS - 1)) * (1 - GROUND_TOP_SCALE)) if GROUND_ROWS > 1 else 1
effective_width = int(WIDTH * scale)
cell_width = effective_width / GROUND_CELLS
for j in range(GROUND_CELLS):
x_start = int(WIDTH / 2 - effective_width / 2 + j * cell_width)
x_end = int(x_start + cell_width)
# Compara o valor suavizado com a referência calibrada
if smoothed_ground[i, j] < (ground_reference[i, j] - DEPTH_LIMIT):
# Obstáculo (valor menor: objeto mais próximo)
cv2.rectangle(heatmap_overlay, (x_start, y_start), (x_end, y_end), (0, 0, 255), -1)
elif smoothed_ground[i, j] > (ground_reference[i, j] + DEPTH_LIMIT):
# Erosão (valor maior: superfície rebaixada)
cv2.rectangle(heatmap_overlay, (x_start, y_start), (x_end, y_end), (0, 255, 255), -1)
if show_grid:
cv2.rectangle(heatmap, (x_start, y_start), (x_end, y_end), (255, 255, 255), 1)
# ─────────────────────────────────────────────
# Processamento da detecção: Região AÉREA
# ─────────────────────────────────────────────
for i in range(AIR_ROWS):
y_start = i * row_height_air
y_end = y_start + row_height_air
for j in range(AIR_COLS):
x_start = j * cell_width_air
x_end = x_start + cell_width_air
if smoothed_air[i, j] < (air_reference[i, j] - DEPTH_LIMIT):
cv2.rectangle(heatmap_overlay, (x_start, y_start), (x_end, y_end), (0, 255, 0), -1)
if show_grid:
cv2.rectangle(heatmap, (x_start, y_start), (x_end, y_end), (255, 255, 255), 1)
try:
memory_usage = device_global.getDdrMemoryUsage()
try:
memory_usage = device.getDdrMemoryUsage()
memory_info = {
"remaining": memory_usage.remaining,
"total": memory_usage.total,
"used": memory_usage.used
}
except:
except:
memory_info = None # Se houver erro, define como None
try:
temp = device_global.getChipTemperature()
try:
temp = device.getChipTemperature()
temp_info = {
"css": temp.css,
"mss": temp.mss,
"upa": temp.upa,
"dss": temp.dss
}
except:
except:
temp_info = None # Se houver erro, define como None
device_data = {
"id": selected_device_info.getMxId(), # ID do dispositivo
"name": selected_device_info.name, # Nome do dispositivo
"state": selected_device_info.state.name, # Estado do dispositivo
"usb_speed": str(device_global.getUsbSpeed().name) if hasattr(device_global, 'getUsbSpeed') else None, # Velocidade USB
"available_camera_sensors": [sensor.name for sensor in device_global.getConnectedCameras()], # Sensores de câmera disponíveis
"version": str(device_global.getDeviceInfo().protocol) if hasattr(device_global, 'getDeviceInfo') else None, # Versão do protocolo
"memory_usage": memory_info, # Uso de memória DDR
"temperature": temp_info, # Temperatura do chip
"bootloader_version": str(device_global.getBootloaderVersion()) if hasattr(device_global, 'getBootloaderVersion') else None, # Bootloader
"is_pipeline_running": device_global.isPipelineRunning() if hasattr(device_global, 'isPipelineRunning') else None # Pipeline rodando?
}
device_data = {
"id": selected_device_info.getMxId(), # ID do dispositivo
"name": selected_device_info.name, # Nome do dispositivo
"state": selected_device_info.state.name, # Estado do dispositivo
"usb_speed": str(device.getUsbSpeed().name) if hasattr(device, 'getUsbSpeed') else None, # Velocidade USB
"available_camera_sensors": [sensor.name for sensor in device.getConnectedCameras()], # Sensores de câmera disponíveis
"version": str(device.getDeviceInfo().protocol) if hasattr(device, 'getDeviceInfo') else None, # Versão do protocolo
"memory_usage": memory_info, # Uso de memória DDR
"temperature": temp_info, # Temperatura do chip
"bootloader_version": str(device.getBootloaderVersion()) if hasattr(device, 'getBootloaderVersion') else None, # Bootloader
"is_pipeline_running": device.isPipelineRunning() if hasattr(device, 'isPipelineRunning') else None # Pipeline rodando?
}
json_data = {
'timestamp': current_time,
'device_data': device_data,
'x_max': WIDTH,
'y_max': HEIGHT,
'subdivisoes': gerar_json_subdivisoes(),
}
json_data = {
'timestamp': timestamp,
'device_data': device_data,
'x_max': width,
'y_max': height,
'depth_data': depth_data,
}
readings.append(json_data)
readings.append(json_data)
# Enviar apenas a cada max_readings capturas
if len(readings) >= max_readings:
mensagem_relevante = readings[-1]
mqtt_client.publish(mqtt_topic, json.dumps(mensagem_relevante).encode('utf-8'))
readings.clear()
# Enviar apenas a cada max_readings capturas
if len(readings) >= max_readings:
mensagem_relevante = readings[-1]
mqtt_client.publish(mqtt_topic, json.dumps(mensagem_relevante).encode('utf-8'))
readings.clear()
video_frame = heatmap
ret, buffer = cv2.imencode('.jpg', video_frame, [cv2.IMWRITE_JPEG_QUALITY, 80]) # Reduz qualidade para 80%
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
# 🔹 Função para enviar vídeo via Flask
def view_rgb_video():
if camera_iniciada == False:
initialize_device()
global device_global, selected_device_info
rgb_queue = device_global.getOutputQueue(name="rgb", maxSize=1, blocking=False)
while True:
in_rgb = rgb_queue.tryGet()
if in_rgb is None:
continue
rgb_frame = in_rgb.getCvFrame()
video_frame = rgb_frame
ret, buffer = cv2.imencode('.jpg', video_frame, [cv2.IMWRITE_JPEG_QUALITY, 80]) # Reduz qualidade para 80%
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
frame = frame_data.getCvFrame()
ret, buffer = cv2.imencode('.jpg', frame)
frame = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@ -582,14 +169,10 @@ def send_script_ready():
def run_flask_server():
app.run(host='0.0.0.0', port=porta, threaded=True, debug=False)
# 🔹 Servidores Flask para RGB e Heatmap
@app.route('/' + url_rgb, methods=['GET'])
def video_feed_rgb():
return Response(view_rgb_video(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/' + url_heatmap, methods=['GET'])
def video_feed_heatmap():
return Response(process_depth_data(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/' + url, methods=['GET'])
def video_feed():
camera_index = int(request.args.get('camera_index'))
return Response(generate_video(camera_index), mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
mqtt_thread = threading.Thread(target=send_script_ready)

View File

@ -79,8 +79,8 @@ def detect_oak(camera_index):
manip.initialConfig.setKeepAspectRatio(False)
manip.initialConfig.setFrameType(dai.RawImgFrame.Type.RGB888p) # Força formato RGB correto
#manip.initialConfig.setHorizontalFlip(True)
#manip.initialConfig.setVerticalFlip(True)
manip.initialConfig.setHorizontalFlip(True)
manip.initialConfig.setVerticalFlip(True)
manip.setMaxOutputFrameSize(1228800)
cam.video.link(manip.inputImage)
@ -137,10 +137,11 @@ def detect_oak(camera_index):
current_readings = []
for detection in detections:
x1 = int(detection.xmin * width)
y1 = int(detection.ymin * height)
x2 = int(detection.xmax * width)
y2 = int(detection.ymax * height)
# Invertendo as coordenadas, devido à imagem sofrer flip tanto na horizontal como na vertical
x1 = width - int(detection.xmin * width)
y1 = height - int(detection.ymin * height)
x2 = width - int(detection.xmax * width)
y2 = height - int(detection.ymax * height)
confidence = float(detection.confidence)
class_id = int(detection.label)
descricao = labelMap[class_id] if class_id < len(labelMap) else f"Classe {class_id}"
@ -198,14 +199,8 @@ def detect_oak(camera_index):
"is_pipeline_running": device.isPipelineRunning() if hasattr(device, 'isPipelineRunning') else None # Pipeline rodando?
}
json_data = {
'timestamp': timestamp,
'device_data': device_data,
'x_max': width,
'y_max': height,
'objetos': current_readings
}
json_data = {'timestamp': timestamp, 'x_max': width, 'y_max': height, 'objetos': current_readings, 'device_data': device_data}
print(json_data)
readings.append(json_data)
if len(readings) >= max_readings: