novos arquivos para o fluxo can

This commit is contained in:
Diego Freitas 2025-12-08 14:37:55 -03:00
parent 19aa3ed2e6
commit 7f7ea84bd2
12 changed files with 142 additions and 35 deletions

View File

@ -75,6 +75,7 @@
Bat = 119,
Npc = 120,
Ipb = 121,
Can = 122
}
public enum F_Code

View File

@ -834,8 +834,10 @@ namespace AgroBase.Models
Variaveis.OperacaoEmAndamento.Parametros.RoverId = VariaveisEquipamento.Parametros.serial_number;
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Add(new OperacaoModulosMandatoriosModel() { Dispositivo = T_Code.Npc, Mandatorio = true, Utilizar = true });
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Add(new OperacaoModulosMandatoriosModel() { Dispositivo = T_Code.Bat, Mandatorio = true, Utilizar = true });
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Add(new OperacaoModulosMandatoriosModel() { Dispositivo = T_Code.Can, Mandatorio = true, Utilizar = true });
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Add(new OperacaoModulosMandatoriosModel() { Dispositivo = T_Code.Ipb, Mandatorio = true, Utilizar = true });
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.Add(new OperacaoModulosMandatoriosModel() { Dispositivo = T_Code.Bat, Mandatorio = true, Utilizar = true });
Variaveis.OperacaoEmAndamento.Parametros.ModulosMandatorios.ForEach(m => m.ComponentesEmUso = Variaveis.OperacaoEmAndamento.PreencherComponentesEmUso(m.Dispositivo));
Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura = new OperacaoSensoriamentoLogModel();
@ -2275,6 +2277,7 @@ namespace AgroBase.Models
public bool CanSerialAtivado { get; set; }
public Dictionary<string, bool> Iniciados { get; set; }
public List<OperacaoSensoriamentoLogErrosModel> Logs { get; set; }
public DateTime UltimoComandoRespondido { get; set; }
public void InserirLog(T_Code dispositivo, StatusModulo status, double saude, string mensagem, string id = null, string condicoes = null)
{
@ -2354,6 +2357,7 @@ namespace AgroBase.Models
AnguloBarraEsquerda = _DispAtu.Dados.AnguloBarraEsquerda,
AnguloBarraDireita = _DispAtu.Dados.AnguloBarraDireita,
AnguloBarraAltura = _DispAtu.Dados.AnguloBarraAltura,
UltimoComandoRespondido = _DispAtu.Dados.DadosLeitura?.UltimoComandoRespondido ?? DateTime.MinValue
} : new OperacaoSensoriamentoLogAtuModel();
var dadosMovimentacao = _DispMvd != null ? new OperacaoSensoriamentoLogMovModel()
@ -2378,7 +2382,8 @@ namespace AgroBase.Models
TemperaturaDriver = x.MovMotor.TemperaturaDriver,
RPM_Motor = x.MovMotor.RPM_Motor,
RPM_Roda = x.MovMotor.RPM_Roda,
VelocidadeInstantanea = x.MovMotor.VelocidadeInstantanea
VelocidadeInstantanea = x.MovMotor.VelocidadeInstantanea,
UltimoComandoRespondido = x.MovMotor.Leitura?.UltimoComandoRecebido ?? DateTime.MinValue,
}).ToList(),
} : new OperacaoSensoriamentoLogMovModel();
@ -2400,7 +2405,7 @@ namespace AgroBase.Models
AnguloFolgaCompensar = x.DirMotor.AnguloFolgaCompensar,
AnguloLeitura = x.DirMotor.AnguloLeitura,
Controlar = x.DirMotor.Comandar,
UltimoComandoRespondido = x.DirMotor.UltimoComandoEnviado,
UltimoComandoRespondido = x.DirMotor.Leitura?.UltimoComandoRecebido ?? DateTime.MinValue,
Velocidade = x.DirMotor.Velocidade,
}).ToList()
} : new OperacaoSensoriamentoLogDirModel();
@ -2519,7 +2524,8 @@ namespace AgroBase.Models
ModsCalibragem = new Dictionary<T_Code, Dictionary<string, bool>>(Variaveis.OperacaoEmAndamento.ModsCalibragem),
Temperaturas = _DispSen?.Dados?.Sensores?.Where(x => x.Componente == S_Code.sNTC)?.ToDictionary(x => x.ID, y => (double?)(y.ValoresLeituras?.FirstOrDefault(v => v.funcao == FuncoesPinout.Temperatura)?.atual?.valor) ?? -1),
Iniciados = _DispSen?.Dados?.Servos?.Select(s => new { s.ID, s.Inicializado }).Union(_DispSen?.Dados?.Reles?.Select(r => new { r.ID, r.Inicializado })).Union(_DispSen?.Dados?.Sinaleiros?.Select(s => new { s.ID, s.Inicializado })).Union(_DispSen?.Dados?.Sensores?.Select(s => new { s.ID, s.Inicializado })).ToDictionary(s => s.ID, s => s.Inicializado),
Logs = new List<OperacaoSensoriamentoLogErrosModel>(Logs ?? new List<OperacaoSensoriamentoLogErrosModel>())
Logs = new List<OperacaoSensoriamentoLogErrosModel>(Logs ?? new List<OperacaoSensoriamentoLogErrosModel>()),
UltimoComandoRespondido = _DispSen?.Dados?.DadosLeitura?.UltimoComandoRespondido ?? DateTime.MinValue
};
Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura = dadosAtualizados;
@ -2569,7 +2575,8 @@ namespace AgroBase.Models
ModsCalibragem = new Dictionary<T_Code, Dictionary<string, bool>>(ModsCalibragem),
Temperaturas = new Dictionary<string, double>(Temperaturas ?? new Dictionary<string, double>()),
Iniciados = new Dictionary<string, bool>(Iniciados ?? new Dictionary<string, bool>()),
Logs = new List<OperacaoSensoriamentoLogErrosModel>(Logs ?? new List<OperacaoSensoriamentoLogErrosModel>())
Logs = new List<OperacaoSensoriamentoLogErrosModel>(Logs ?? new List<OperacaoSensoriamentoLogErrosModel>()),
UltimoComandoRespondido = UltimoComandoRespondido
};
}
@ -2625,6 +2632,7 @@ namespace AgroBase.Models
public double AnguloBarraDireita { get; set; }
public double AnguloBarraAltura { get; set; }
public Dictionary<string, bool> Iniciados { get; set; }
public DateTime UltimoComandoRespondido { get; set; }
public OperacaoSensoriamentoLogAtuModel Clone()
{
@ -2650,7 +2658,8 @@ namespace AgroBase.Models
AnguloBarraEsquerda = AnguloBarraEsquerda,
AnguloBarraDireita = AnguloBarraDireita,
AnguloBarraAltura = AnguloBarraAltura,
Iniciados = new Dictionary<string, bool>(Iniciados ?? new Dictionary<string, bool>())
Iniciados = new Dictionary<string, bool>(Iniciados ?? new Dictionary<string, bool>()),
UltimoComandoRespondido = UltimoComandoRespondido
};
}
}
@ -2704,6 +2713,7 @@ namespace AgroBase.Models
public double CicloTrabalho { get; set; }
public double RPM_Motor { get; set; }
public double VelocidadeInstantanea { get; set; }
public DateTime UltimoComandoRespondido { get; set; }
}
public class OperacaoSensoriamentoLogDirModel

View File

@ -163,6 +163,12 @@ namespace AgroBase.Services
string _portName { get; set; }
bool Iniciado { get; }
bool IsConnected { get; }
double UltimoTx { get; set; }
double FreqTx { get; set; }
double UltimoRx { get; set; }
double FreqRx { get; set; }
int ErrosCriticos { get; set; }
double UltimoErroCritico { get; set; }
}
}

View File

@ -1,7 +1,9 @@
using AgroBase.Models;
using Emgu.CV.Structure;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
@ -34,8 +36,15 @@ namespace AgroBase.Services
private List<CanMessage> Mensagens = new List<CanMessage>();
private readonly object _LockMensagens = new object();
private DateTime UltimoTx = DateTime.MinValue;
private DateTime UltimoRx = DateTime.MinValue;
public double UltimoTx { get; set; } = 0;
private DateTime _ultimoTx = DateTime.MinValue;
public double FreqTx { get; set; } = 0;
public double UltimoRx { get; set; } = 0;
private DateTime _ultimoRx = DateTime.MinValue;
public double FreqRx{ get; set; } = 0;
public int ErrosCriticos { get; set; } = 0;
public double UltimoErroCritico { get; set; } = 0;
private DateTime _ultimoErroCritico = DateTime.MinValue;
private bool DebugMode = false;
private void MostrarLog(string message, byte id)
@ -121,9 +130,8 @@ namespace AgroBase.Services
Iniciado = true;
SerialService.DispositivosMapeados.Add(new DispositivoDetalhesModel()
{
Dispositivo = T_Code.Vzo,
Endereco = _portName,
Mod_ID = "CAN"
Dispositivo = T_Code.Can,
Endereco = _portName
});
break;
}
@ -196,8 +204,10 @@ namespace AgroBase.Services
_PortaCAN.DiscardOutBuffer();
}
UltimoRx = DateTime.Now;
UltimoTx = DateTime.Now;
_ultimoRx = DateTime.Now;
UltimoRx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
_ultimoTx = DateTime.Now;
UltimoTx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
tmrOuvirCAN?.Dispose();
tmrOuvirCAN = new AsyncTaskTimerModel("tmrOuvirCAN", OuvirCAN, 1);
@ -277,7 +287,10 @@ namespace AgroBase.Services
if (tempBuffer.Length > 0)
{
UltimoRx = DateTime.Now;
var agora = DateTime.Now;
FreqRx = 1.0 / (agora - _ultimoRx).TotalSeconds;
_ultimoRx = agora;
UltimoRx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
}
}
}
@ -531,7 +544,10 @@ namespace AgroBase.Services
{
_PortaCAN.Write(comando);
//Console.WriteLine($"[CAN] Frame enviado: {comando}");
UltimoTx = DateTime.Now;
var agora = DateTime.Now;
FreqTx = 1.0 / (agora - _ultimoTx).TotalSeconds;
_ultimoTx = agora;
UltimoTx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
return true;
}
return false;
@ -575,14 +591,19 @@ namespace AgroBase.Services
return;
}
if (IsConnected && (((Agora - UltimoTx).TotalSeconds > 2 && (Agora - UltimoRx).TotalSeconds > 2) || _precisaReabrir))
if (IsConnected && (((Agora - _ultimoTx).TotalSeconds > 2 && (Agora - _ultimoRx).TotalSeconds > 2) || _precisaReabrir))
{
ErrosCriticos++;
_ultimoErroCritico = Agora;
UltimoErroCritico = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
_precisaReabrir = false;
UltimoRx = Agora;
UltimoTx = Agora;
MostrarLog("Muito tempo sem receber novos dados, reiniciando conexao CAN...", 0);
ReabrirPortaSegura();
}
if ((Agora - _ultimoErroCritico).TotalMinutes > 10)
{
ErrosCriticos = 0;
}
}
public void Fechar()
@ -715,6 +736,12 @@ namespace AgroBase.Services
EnviarComando("Z0\r"); Thread.Sleep(50);
EnviarComando(ComandoBitRate(_bitRate)); Thread.Sleep(50);
EnviarComando("O\r"); Thread.Sleep(50);
_ultimoRx = DateTime.Now;
UltimoRx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
_ultimoTx = DateTime.Now;
UltimoTx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
}
catch
{

View File

@ -2,6 +2,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Text;
@ -34,8 +35,15 @@ namespace AgroBase.Services
private List<CanMessage> MensagensPendentes = new List<CanMessage>();
private readonly object _LockMensagens = new object();
private bool DebugMode = false;
private DateTime UltimoTx = DateTime.MinValue;
private DateTime UltimoRx = DateTime.MinValue;
public double UltimoTx { get; set; } = 0;
private DateTime _ultimoTx = DateTime.MinValue;
public double FreqTx { get; set; } = 0;
public double UltimoRx { get; set; } = 0;
private DateTime _ultimoRx = DateTime.MinValue;
public double FreqRx { get; set; } = 0;
public int ErrosCriticos { get; set; } = 0;
public double UltimoErroCritico { get; set; } = 0;
private DateTime _ultimoErroCritico = DateTime.MinValue;
private void MostrarLog(string message, byte id)
{
@ -87,7 +95,8 @@ namespace AgroBase.Services
while (FramesRecebidos.Count > 4096) // cap opcional
FramesRecebidos.TryDequeue(out _);
}
UltimoRx = now;
_ultimoRx = now;
UltimoRx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
}
catch (Exception ex)
{
@ -111,8 +120,10 @@ namespace AgroBase.Services
if (canIniciado || !IsConnected)
{
UltimoRx = DateTime.Now;
UltimoTx = DateTime.Now;
_ultimoRx = DateTime.Now;
UltimoRx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
_ultimoTx = DateTime.Now;
UltimoTx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
tmrEnviarCAN?.Dispose();
tmrEnviarCAN = new AsyncTaskTimerModel("tmrEnviarCAN", EnviarCAN, 3);
@ -138,6 +149,11 @@ namespace AgroBase.Services
while (processed < MAX_BATCH && FramesRecebidos.TryDequeue(out var frame))
{
var agora = DateTime.Now;
FreqRx = 1.0 / (agora - _ultimoRx).TotalSeconds;
_ultimoRx = agora;
UltimoRx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
ProcessarFrameCAN(frame);
processed++;
@ -369,7 +385,10 @@ namespace AgroBase.Services
if (sucesso)
{
MostrarLog($"Frame enviado: {comando}", msg.IdTx);
UltimoTx = DateTime.Now;
var agora = DateTime.Now;
FreqTx = 1.0 / (agora - _ultimoTx).TotalSeconds;
_ultimoTx = agora;
UltimoTx = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
}
else
{
@ -405,10 +424,11 @@ namespace AgroBase.Services
private void VerificaSaudeConexao()
{
DateTime Agora = DateTime.Now;
if (IsConnected && ((Agora - UltimoTx).TotalSeconds > 10 || (Agora - UltimoRx).TotalSeconds > 10))
if (IsConnected && ((Agora - _ultimoTx).TotalSeconds > 2 && (Agora - _ultimoRx).TotalSeconds > 2))
{
UltimoRx = Agora;
UltimoTx = Agora;
ErrosCriticos++;
_ultimoErroCritico = Agora;
UltimoErroCritico = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency;
MostrarLog("Muito tempo sem receber novos dados, reiniciando conexao CAN...", 0);
try { Connector.Close(); } catch { }
try
@ -417,6 +437,10 @@ namespace AgroBase.Services
}
catch { }
}
if ((Agora - _ultimoErroCritico).TotalMinutes > 10)
{
ErrosCriticos = 0;
}
}
public void Fechar()

View File

@ -580,6 +580,20 @@ namespace AgroBase.Services.Operadores
("gpu_temp", DadosMod.GPU_temp ?? 0)
);
var DadosCan = CanManager.CanService;
RedisService.AtualizarCampos(RedisService.ModKey(Enums.T_Code.Can),
("timestamp", agora),
("conectado", DadosCan.Iniciado),
("iniciado", DadosCan.IsConnected),
("executando", SerialService.DispositivosMapeados.Any(x => SerialService.DispositivosCan.Contains(x.Dispositivo))),
("erros_criticos", DadosCan.ErrosCriticos),
("freq_tx", DadosCan.FreqTx),
("freq_rx", DadosCan.FreqRx),
("last_tx", DadosCan.UltimoTx),
("last_rx", DadosCan.UltimoRx),
("last_ec", DadosCan.UltimoErroCritico)
);
}

View File

@ -30,7 +30,7 @@ namespace AgroBase.Services
public static List<T_Code> DispositivosConexaoInicial = new List<T_Code>() { T_Code.Mvd, T_Code.Atu, T_Code.Sen };
public static List<T_Code> DispositivosProprios = new List<T_Code>() { T_Code.Atu, T_Code.Sen };
public static List<T_Code> DispositivosModbus = new List<T_Code>() { T_Code.Pzm, T_Code.Wit, T_Code.A05 };
public static List<T_Code> DispositivosCan = new List<T_Code>() { T_Code.Vzo, T_Code.Mov, T_Code.Oid, T_Code.Dir, T_Code.Mks, T_Code.Sen, T_Code.Atu };
public static List<T_Code> DispositivosCan = new List<T_Code>() { T_Code.Mov, T_Code.Oid, T_Code.Dir, T_Code.Mks, T_Code.Sen, T_Code.Atu };
public static List<T_Code> DispositivosMultiplos = new List<T_Code>() { T_Code.Bld, T_Code.Mks, T_Code.Mvd, T_Code.Oid, T_Code.Mov, T_Code.Dir };
public static List<DispositivoDetalhesModel> DispositivosMapeados = new List<DispositivoDetalhesModel>()

View File

@ -17,6 +17,7 @@ def main():
from health_worker.modulos.pc import ModuloPC
from health_worker.modulos.livox import ModuloLivox
from health_worker.modulos.ponte_ip import ModuloIPBribge
from health_worker.modulos.can import ModuloCAN
from health_worker.config import mostrar_log
from shared.contexto_global_redis import ContextoGlobalRedis, CmdKey, CtxKey
@ -31,6 +32,7 @@ def main():
T_Code.Npc: ModuloPC(),
T_Code.Lvx: ModuloLivox(),
T_Code.Ipb: ModuloIPBribge(),
T_Code.Can: ModuloCAN(),
}
def loop_ativo():

View File

@ -67,12 +67,14 @@ class T_Code(IntEnum):
Gps = 104
Lra = 106
Cam = 112
Mod = 115
Snr = 117
Lvx = 118
Bat = 119
Npc = 120
Ipb = 121
Mod = 115,
Oid = 116,
Snr = 117,
Lvx = 118,
Bat = 119,
Npc = 120,
Ipb = 121,
Can = 122
class ParametrosOperacao(IntEnum):
CameraSolo = 1

View File

@ -147,6 +147,7 @@
<Label x:Name="lblDiagnosticos_GPS" Content="🔒GPS" Style="{StaticResource RoundedLabel}" Height="21" Width="40" Canvas.Left="202" Canvas.Top="192" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<Label x:Name="lblDiagnosticos_SEN" Tag="sMOD" Content="🔒SEN" Style="{StaticResource RoundedLabel}" Height="21" Width="40" Canvas.Left="202" Canvas.Top="218" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<Label x:Name="lblDiagnosticos_NPC" Content="🔒NCP" Style="{StaticResource RoundedLabel}" Height="21" Width="40" Canvas.Left="202" Canvas.Top="244" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<Label x:Name="lblDiagnosticos_CAN" Content="🔒CAN" Style="{StaticResource RoundedLabel}" Height="21" Width="40" Canvas.Left="398" Canvas.Top="192" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Label x:Name="lblDiagnosticos_IPB" Content="🔒LAN" Style="{StaticResource RoundedLabel}" Height="21" Width="40" Canvas.Left="398" Canvas.Top="218" HorizontalAlignment="Left" VerticalAlignment="Center"/>
<Label x:Name="lblDiagnosticos_ATU_BOMBA" Tag="sBMB" Content="🔒BMB" Style="{StaticResource RoundedLabel}" Height="21" Width="40" Canvas.Left="202" Canvas.Top="309" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<Label x:Name="lblDiagnosticos_ATU" Tag="sMOD" Content="🔒ATU" Style="{StaticResource RoundedLabel}" Height="21" Width="40" Canvas.Left="202" Canvas.Top="349" HorizontalAlignment="Center" VerticalAlignment="Top"/>

View File

@ -581,11 +581,24 @@ namespace OperationControl.Windows
var status = individual?.status ?? saude?.status ?? AgroBase.Models.Enums.StatusModulo.Desconectado;
var motivos = string.Join(", ", (individual?.motivos ?? saude?.motivos) ?? new List<string>());
DateTime ucr = DateTime.MinValue;
if (modulo == AgroBase.Models.Enums.T_Code.Sen)
ucr = rover?.DadosLeitura?.UltimoComandoRespondido ?? DateTime.MinValue;
else if (modulo == AgroBase.Models.Enums.T_Code.Atu)
ucr = rover?.DadosLeitura?.Atuador?.UltimoComandoRespondido ?? DateTime.MinValue;
else if (modulo == AgroBase.Models.Enums.T_Code.Mov)
ucr = rover?.DadosLeitura?.Movimentacao?.Dados?.FirstOrDefault(x => x.ID == label)?.UltimoComandoRespondido ?? DateTime.MinValue;
else if (modulo == AgroBase.Models.Enums.T_Code.Dir)
ucr = rover?.DadosLeitura?.Direcional?.Dados?.FirstOrDefault(x => x.Modulo_ID == label)?.UltimoComandoRespondido ?? DateTime.MinValue;
DateTime mom = rover.DadosLeitura?.Momento ?? DateTime.MinValue;
double can_latencia = (mom - ucr).TotalMilliseconds;
lblSaude_Descricao.Content = $"Módulo {modulo} {label}";
lblSaude_Iniciado.Content = (iniciado ? "Iniciado" : "Não Iniciado");
lblSaude_Iniciado.Foreground = new SolidColorBrush(iniciado ? System.Windows.Media.Colors.Green : System.Windows.Media.Colors.Red);
lblSaude_Status.Content = $"{individual?.status ?? saude?.status ?? AgroBase.Models.Enums.StatusModulo.Desconectado} (Saúde {individual?.saude ?? saude?.saude ?? 0}%)";
lblSaude_CAN.Content = $"CAN {dispositivo?.VelocidadeBarramento ?? 0} ms";
lblSaude_CAN.Content = $"CAN {can_latencia} ms";
lblSaude_Latencia.Content = $"Latência {dispositivo?.Latencia ?? 0} ms";
lblSaude_Impedimento.Text = $"Impedimento: {motivos ?? "Nenhum"}";

View File

@ -19,6 +19,13 @@ enum T_Code {
Knt = 113,
A05 = 114,
Mod = 115,
Oid = 116,
Snr = 117,
Lvx = 118,
Bat = 119,
Npc = 120,
Ipb = 121,
Can = 122
};
enum F_Code {