ajustes calculo vazao por fluxo, saude do mov por frequencia por parametro
This commit is contained in:
parent
9b5fdf267f
commit
bbd5f4bfec
|
|
@ -129,16 +129,21 @@ namespace AgroBase.Models.Modules
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
int pulsos = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.QtdPulsos)?.atual?.valor ?? 0.0);
|
int pulsos = (int)(SensorFluxoLinha?.ValoresLeituras?
|
||||||
|
.FirstOrDefault(x => x.funcao == FuncoesPinout.QtdPulsos)?
|
||||||
|
.atual?.valor ?? 0.0);
|
||||||
|
|
||||||
int periodo = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Periodo)?.atual?.valor ?? 0.0);
|
int periodo = (int)(SensorFluxoLinha?.ValoresLeituras?
|
||||||
|
.FirstOrDefault(x => x.funcao == FuncoesPinout.Periodo)?
|
||||||
|
.atual?.valor ?? 0.0);
|
||||||
|
|
||||||
if (pulsos <= 0 || periodo <= 0)
|
if (pulsos <= 0 || periodo <= 0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
|
const double FatorCalibracaoFluxo = 0.776;
|
||||||
|
|
||||||
double frequencia = (double)pulsos / periodo * 1000.0;
|
double frequencia = (double)pulsos / periodo * 1000.0;
|
||||||
|
|
||||||
// Fabricante: F = 8.1*q - 3, q em L/min
|
|
||||||
double q_L_min = (frequencia + 3.0) / 8.1;
|
double q_L_min = (frequencia + 3.0) / 8.1;
|
||||||
|
|
||||||
if (q_L_min < 0)
|
if (q_L_min < 0)
|
||||||
|
|
@ -147,7 +152,7 @@ namespace AgroBase.Models.Modules
|
||||||
if (q_L_min > VazaoMaximaSensor_LMin)
|
if (q_L_min > VazaoMaximaSensor_LMin)
|
||||||
q_L_min = VazaoMaximaSensor_LMin;
|
q_L_min = VazaoMaximaSensor_LMin;
|
||||||
|
|
||||||
return q_L_min * 1000.0 / 60.0;
|
return q_L_min * 1000.0 / 60.0 * FatorCalibracaoFluxo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,44 +235,107 @@ namespace AgroBase.Models.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private DateTime _ultimoEnvioControleMov = DateTime.MinValue;
|
||||||
|
private DateTime _ultimoRegistroLogMov = DateTime.MinValue;
|
||||||
|
|
||||||
|
private static readonly TimeSpan IntervaloControleMov = TimeSpan.FromSeconds(1);
|
||||||
|
private static readonly TimeSpan IntervaloLogMov = TimeSpan.FromSeconds(1);
|
||||||
private async Task tmrRegistradorMOV_Tick()
|
private async Task tmrRegistradorMOV_Tick()
|
||||||
{
|
{
|
||||||
if (Variaveis.Fechando) return;
|
if (Variaveis.Fechando)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!OIDCanService.Iniciado && SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Mov))
|
DateTime agora = DateTime.Now;
|
||||||
|
|
||||||
|
if (!OIDCanService.Iniciado &&
|
||||||
|
SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Mov))
|
||||||
{
|
{
|
||||||
foreach (var Leitura in OIDCanService.DadosLeitura.Where(x => x.UltimoComandoRecebido.AddSeconds(10) < DateTime.Now))
|
foreach (var leitura in OIDCanService.DadosLeitura
|
||||||
|
.Where(x => x.UltimoComandoRecebido.AddSeconds(10) < agora))
|
||||||
{
|
{
|
||||||
OIDCanService.RequisitarDado(_EnderecoCAN_Tx, _EnderecoCAN_Rx, OIDCanService.OidHandler.OidParametros.CodErro);
|
OIDCanService.RequisitarDado(
|
||||||
|
leitura.EnderecoTx,
|
||||||
|
leitura.EnderecoRx,
|
||||||
|
OIDCanService.OidHandler.OidParametros.CodErro
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmrRegistradorMOV.SetInterval(3000);
|
tmrRegistradorMOV.SetInterval(3000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool deveEnviarControle =
|
||||||
foreach (var Modulo in Modulos)
|
_ultimoEnvioControleMov == DateTime.MinValue ||
|
||||||
|
agora - _ultimoEnvioControleMov >= IntervaloControleMov;
|
||||||
|
|
||||||
|
bool deveRegistrarLog =
|
||||||
|
_ultimoRegistroLogMov == DateTime.MinValue ||
|
||||||
|
agora - _ultimoRegistroLogMov >= IntervaloLogMov;
|
||||||
|
|
||||||
|
bool enviouControle = false;
|
||||||
|
bool registrouLog = false;
|
||||||
|
|
||||||
|
var controleMov =
|
||||||
|
deveEnviarControle
|
||||||
|
? Variaveis.OperacaoEmAndamento.Controle.TiposControle?
|
||||||
|
.FirstOrDefault(x => x.Tipo == T_Code.Mov)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
foreach (var modulo in Modulos)
|
||||||
{
|
{
|
||||||
if (Modulo.MovMotor.Inicializado)
|
if (!modulo.MovMotor.Inicializado)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
byte addrTx = modulo.MovMotor._EnderecoCAN_Tx;
|
||||||
|
byte addrRx = modulo.MovMotor._EnderecoCAN_Rx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Esse continua em todo tick.
|
||||||
|
* O OIDCanService já segura throttle, pendência e rodízio.
|
||||||
|
*/
|
||||||
|
OIDCanService.RequisitarProximoDado(addrTx, addrRx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Desligado por enquanto para aliviar CAN.
|
||||||
|
*/
|
||||||
|
// modulo.MovMotor.RequisitarDadosSensoresExternos();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Controle só a cada 1s.
|
||||||
|
* Se o EnviarComandoControle já tiver dedupe interno, melhor ainda.
|
||||||
|
*/
|
||||||
|
if (deveEnviarControle && controleMov != null)
|
||||||
{
|
{
|
||||||
byte addrTx = Modulo.MovMotor._EnderecoCAN_Tx;
|
modulo.MovMotor.EnviarComandoControle(controleMov.UltimaDirecao);
|
||||||
byte addrRx = Modulo.MovMotor._EnderecoCAN_Rx;
|
enviouControle = true;
|
||||||
OIDCanService.RequisitarProximoDado(addrTx, addrRx);
|
}
|
||||||
Modulo.MovMotor.RequisitarDadosSensoresExternos();
|
|
||||||
|
|
||||||
var Controle = Variaveis.OperacaoEmAndamento.Controle.TiposControle?.FirstOrDefault(x => x.Tipo == T_Code.Mov);
|
/*
|
||||||
if (Controle != null)
|
* Essa leitura é local, pode deixar no tick.
|
||||||
{
|
*/
|
||||||
Modulo.MovMotor.EnviarComandoControle(Controle.UltimaDirecao);
|
modulo.MovMotor.ConfigFreio.Leitura =
|
||||||
}
|
modulo.MovMotor.Leitura?.Freado ?? false;
|
||||||
|
|
||||||
Modulo.MovMotor.ConfigFreio.Leitura = Modulo.MovMotor.Leitura?.Freado ?? false;
|
/*
|
||||||
|
* Log só a cada 1s para não virar serragem de JSON.
|
||||||
Variaveis.OperacaoEmAndamento.DispMvd.Dados.RegistrarLogMov(Modulo);
|
*/
|
||||||
|
if (deveRegistrarLog)
|
||||||
|
{
|
||||||
|
Variaveis.OperacaoEmAndamento.DispMvd.Dados.RegistrarLogMov(modulo);
|
||||||
|
registrouLog = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enviouControle)
|
||||||
|
_ultimoEnvioControleMov = agora;
|
||||||
|
|
||||||
|
if (registrouLog)
|
||||||
|
_ultimoRegistroLogMov = agora;
|
||||||
|
|
||||||
tmrRegistradorMOV.SetInterval(OIDCanService.TaxaAmostragem);
|
tmrRegistradorMOV.SetInterval(OIDCanService.TaxaAmostragem);
|
||||||
|
|
||||||
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task tmrRegistradorDIR_Tick()
|
private async Task tmrRegistradorDIR_Tick()
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@ namespace AgroBase.Services
|
||||||
{
|
{
|
||||||
public class OIDCanService
|
public class OIDCanService
|
||||||
{
|
{
|
||||||
public static List<OIDModel> DadosLeitura =
|
public static List<OIDModel> DadosLeitura = new List<OIDModel>();
|
||||||
new List<OIDModel>();
|
|
||||||
|
|
||||||
private static T_Code Dispositivo { get; set; } =
|
private static T_Code Dispositivo { get; set; } =
|
||||||
T_Code.Oid;
|
T_Code.Oid;
|
||||||
|
|
@ -22,72 +21,33 @@ namespace AgroBase.Services
|
||||||
|
|
||||||
private static AsyncTaskTimerModel tmrHeartbeat;
|
private static AsyncTaskTimerModel tmrHeartbeat;
|
||||||
|
|
||||||
private static readonly object _sync =
|
private static readonly object _sync = new object();
|
||||||
new object();
|
private static readonly HashSet<byte> _handlersRegistrados = new HashSet<byte>();
|
||||||
|
private static readonly Dictionary<byte, DateTime> _ultimoEnvioConsultaPorDriver = new Dictionary<byte, DateTime>();
|
||||||
private static readonly HashSet<byte> _handlersRegistrados =
|
private static readonly Dictionary<string, DateTime> _ultimoEnvioParametro = new Dictionary<string, DateTime>();
|
||||||
new HashSet<byte>();
|
private static readonly Dictionary<byte, OidParametros> _ultimaConsultaPendente = new Dictionary<byte, OidParametros>();
|
||||||
|
private static readonly Dictionary<byte, int> _cursorPollingPorDriver = new Dictionary<byte, int>();
|
||||||
private static readonly Dictionary<byte, DateTime>
|
private static readonly Dictionary<string, string> _ultimoComandoControleAssinatura = new Dictionary<string, string>();
|
||||||
_ultimoEnvioConsultaPorDriver =
|
private static readonly Dictionary<string, DateTime> _ultimoComandoControleQuando = new Dictionary<string, DateTime>();
|
||||||
new Dictionary<byte, DateTime>();
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, DateTime>
|
|
||||||
_ultimoEnvioParametro =
|
|
||||||
new Dictionary<string, DateTime>();
|
|
||||||
|
|
||||||
private static readonly Dictionary<byte, OidParametros>
|
|
||||||
_ultimaConsultaPendente =
|
|
||||||
new Dictionary<byte, OidParametros>();
|
|
||||||
|
|
||||||
private static readonly Dictionary<byte, int>
|
|
||||||
_cursorPollingPorDriver =
|
|
||||||
new Dictionary<byte, int>();
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, string>
|
|
||||||
_ultimoComandoControleAssinatura =
|
|
||||||
new Dictionary<string, string>();
|
|
||||||
|
|
||||||
private static readonly Dictionary<string, DateTime>
|
|
||||||
_ultimoComandoControleQuando =
|
|
||||||
new Dictionary<string, DateTime>();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Consultas síncronas do OID respondem sempre com DATA[0]=0x0F.
|
* Consultas síncronas do OID respondem sempre com DATA[0]=0x0F.
|
||||||
* A diferença fica em DATA[1]. Para evitar confusão no CanService,
|
* A diferença fica em DATA[1]. Para evitar confusão no CanService,
|
||||||
* enviaremos no máximo uma consulta pendente por driver.
|
* enviaremos no máximo uma consulta pendente por driver.
|
||||||
*/
|
*/
|
||||||
private static readonly TimeSpan IntervaloMinimoConsultaPorDriver =
|
private static readonly TimeSpan IntervaloMinimoConsultaPorDriver = TimeSpan.FromMilliseconds(120);
|
||||||
TimeSpan.FromMilliseconds(120);
|
private static readonly TimeSpan IntervaloMinimoMesmoParametro = TimeSpan.FromMilliseconds(300);
|
||||||
|
private static readonly TimeSpan JanelaConsultaPendente = TimeSpan.FromMilliseconds(450);
|
||||||
private static readonly TimeSpan IntervaloMinimoMesmoParametro =
|
private static readonly TimeSpan JanelaDedupeComandoControle = TimeSpan.FromMilliseconds(80);
|
||||||
TimeSpan.FromMilliseconds(300);
|
private static readonly TimeSpan TempoRespostaRecente = TimeSpan.FromSeconds(3);
|
||||||
|
private static readonly TimeSpan TempoRemoverDriver = TimeSpan.FromSeconds(15);
|
||||||
private static readonly TimeSpan JanelaConsultaPendente =
|
private static readonly TimeSpan PeriodoHeartbeat = TimeSpan.FromMilliseconds(500);
|
||||||
TimeSpan.FromMilliseconds(450);
|
|
||||||
|
|
||||||
private static readonly TimeSpan JanelaDedupeComandoControle =
|
|
||||||
TimeSpan.FromMilliseconds(80);
|
|
||||||
|
|
||||||
private static readonly TimeSpan TempoRespostaRecente =
|
|
||||||
TimeSpan.FromSeconds(3);
|
|
||||||
|
|
||||||
private static readonly TimeSpan TempoRemoverDriver =
|
|
||||||
TimeSpan.FromSeconds(15);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* O manual sugere heartbeat com período metade do timeout.
|
|
||||||
* O timer continua em 500ms, mas o payload passa a seguir o manual:
|
|
||||||
* DATA[0] = 0x00.
|
|
||||||
*/
|
|
||||||
private static readonly TimeSpan PeriodoHeartbeat =
|
|
||||||
TimeSpan.FromMilliseconds(500);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Polling recomendado. Se outro ponto do sistema ainda chamar
|
* Polling recomendado. Se outro ponto do sistema ainda chamar
|
||||||
* RequisitarDado() em massa, o throttle interno também segura.
|
* RequisitarDado() em massa, o throttle interno também segura.
|
||||||
*/
|
*/
|
||||||
private static readonly OidParametros[] OrdemPolling =
|
public static readonly OidParametros[] OrdemPolling =
|
||||||
{
|
{
|
||||||
OidParametros.VelocidadeAtual,
|
OidParametros.VelocidadeAtual,
|
||||||
OidParametros.CorrenteMotor,
|
OidParametros.CorrenteMotor,
|
||||||
|
|
@ -101,24 +61,264 @@ namespace AgroBase.Services
|
||||||
OidParametros.IO_Status,
|
OidParametros.IO_Status,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly Dictionary<OidParametros, TimeSpan>
|
private static readonly Dictionary<OidParametros, TimeSpan> IntervaloParametro = new Dictionary<OidParametros, TimeSpan>
|
||||||
IntervaloParametro =
|
{
|
||||||
new Dictionary<OidParametros, TimeSpan>
|
{ OidParametros.VelocidadeAtual, TimeSpan.FromMilliseconds(160) },
|
||||||
|
{ OidParametros.CorrenteMotor, TimeSpan.FromMilliseconds(300) },
|
||||||
|
{ OidParametros.CorrenteBarramento, TimeSpan.FromMilliseconds(350) },
|
||||||
|
{ OidParametros.CodErro, TimeSpan.FromMilliseconds(750) },
|
||||||
|
{ OidParametros.Tensao, TimeSpan.FromSeconds(1) },
|
||||||
|
{ OidParametros.Temperatura, TimeSpan.FromSeconds(1) },
|
||||||
|
{ OidParametros.CicloTrabalho, TimeSpan.FromMilliseconds(500) },
|
||||||
|
{ OidParametros.Potencia, TimeSpan.FromMilliseconds(500) },
|
||||||
|
{ OidParametros.PosicaoAbsoluta, TimeSpan.FromMilliseconds(500) },
|
||||||
|
{ OidParametros.PosicaoRelativa, TimeSpan.FromMilliseconds(500) },
|
||||||
|
{ OidParametros.ModoCodificador, TimeSpan.FromSeconds(2) },
|
||||||
|
{ OidParametros.ErroLerCache, TimeSpan.FromSeconds(5) },
|
||||||
|
{ OidParametros.IO_Status, TimeSpan.FromSeconds(2) },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public class OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
public OidParametros Parametro { get; set; }
|
||||||
|
public string RedisKey { get; set; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frequência esperada para health.
|
||||||
|
* Não precisa ser a frequência máxima possível.
|
||||||
|
* É o que consideramos saudável para operação.
|
||||||
|
*/
|
||||||
|
public double FreqBaseHz { get; set; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Abaixo disso começa alerta.
|
||||||
|
* Sugestão: 50% a 60% da base, dependendo da importância.
|
||||||
|
*/
|
||||||
|
public double FreqMinHz { get; set; }
|
||||||
|
|
||||||
|
public bool EmUsoHealth { get; set; } = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly Dictionary<OidParametros, OidParametroHealthConfig> HealthParametroConfig = new Dictionary<OidParametros, OidParametroHealthConfig>
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Runtime importante.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
OidParametros.VelocidadeAtual,
|
||||||
|
new OidParametroHealthConfig
|
||||||
{
|
{
|
||||||
{ OidParametros.VelocidadeAtual, TimeSpan.FromMilliseconds(160) },
|
Parametro = OidParametros.VelocidadeAtual,
|
||||||
{ OidParametros.CorrenteMotor, TimeSpan.FromMilliseconds(300) },
|
RedisKey = "rpm",
|
||||||
{ OidParametros.CorrenteBarramento, TimeSpan.FromMilliseconds(350) },
|
FreqBaseHz = 1.0,
|
||||||
{ OidParametros.CodErro, TimeSpan.FromMilliseconds(750) },
|
FreqMinHz = 0.45,
|
||||||
{ OidParametros.Tensao, TimeSpan.FromSeconds(1) },
|
EmUsoHealth = true
|
||||||
{ OidParametros.Temperatura, TimeSpan.FromSeconds(1) },
|
}
|
||||||
{ OidParametros.CicloTrabalho, TimeSpan.FromMilliseconds(500) },
|
},
|
||||||
{ OidParametros.Potencia, TimeSpan.FromMilliseconds(500) },
|
{
|
||||||
{ OidParametros.PosicaoAbsoluta, TimeSpan.FromMilliseconds(500) },
|
OidParametros.CorrenteMotor,
|
||||||
{ OidParametros.PosicaoRelativa, TimeSpan.FromMilliseconds(500) },
|
new OidParametroHealthConfig
|
||||||
{ OidParametros.ModoCodificador, TimeSpan.FromSeconds(2) },
|
{
|
||||||
{ OidParametros.ErroLerCache, TimeSpan.FromSeconds(5) },
|
Parametro = OidParametros.CorrenteMotor,
|
||||||
{ OidParametros.IO_Status, TimeSpan.FromSeconds(2) },
|
RedisKey = "corrente_motor",
|
||||||
};
|
FreqBaseHz = 1.0,
|
||||||
|
FreqMinHz = 0.45,
|
||||||
|
EmUsoHealth = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OidParametros.CorrenteBarramento,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.CorrenteBarramento,
|
||||||
|
RedisKey = "corrente_barramento",
|
||||||
|
FreqBaseHz = 1.0,
|
||||||
|
FreqMinHz = 0.45,
|
||||||
|
EmUsoHealth = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Estado elétrico/térmico. Pode ser mais lento.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
OidParametros.Tensao,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.Tensao,
|
||||||
|
RedisKey = "tensao",
|
||||||
|
FreqBaseHz = 0.5,
|
||||||
|
FreqMinHz = 0.20,
|
||||||
|
EmUsoHealth = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OidParametros.Temperatura,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.Temperatura,
|
||||||
|
RedisKey = "temperatura",
|
||||||
|
FreqBaseHz = 0.5,
|
||||||
|
FreqMinHz = 0.20,
|
||||||
|
EmUsoHealth = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Diagnóstico/telemetria secundária.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
OidParametros.CodErro,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.CodErro,
|
||||||
|
RedisKey = "erro",
|
||||||
|
FreqBaseHz = 0.5,
|
||||||
|
FreqMinHz = 0.20,
|
||||||
|
EmUsoHealth = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OidParametros.CicloTrabalho,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.CicloTrabalho,
|
||||||
|
RedisKey = "ciclo_trabalho",
|
||||||
|
FreqBaseHz = 0.5,
|
||||||
|
FreqMinHz = 0.20,
|
||||||
|
EmUsoHealth = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OidParametros.Potencia,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.Potencia,
|
||||||
|
RedisKey = "potencia",
|
||||||
|
FreqBaseHz = 0.5,
|
||||||
|
FreqMinHz = 0.20,
|
||||||
|
EmUsoHealth = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Por enquanto, não cobra no health se não for usado.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
OidParametros.PosicaoAbsoluta,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.PosicaoAbsoluta,
|
||||||
|
RedisKey = "posicao_absoluta",
|
||||||
|
FreqBaseHz = 0.2,
|
||||||
|
FreqMinHz = 0.08,
|
||||||
|
EmUsoHealth = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OidParametros.IO_Status,
|
||||||
|
new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = OidParametros.IO_Status,
|
||||||
|
RedisKey = "io_status",
|
||||||
|
FreqBaseHz = 0.2,
|
||||||
|
FreqMinHz = 0.08,
|
||||||
|
EmUsoHealth = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
public static OidParametroHealthConfig ObterConfigHealth(OidParametros parametro)
|
||||||
|
{
|
||||||
|
if (HealthParametroConfig.TryGetValue(parametro, out var cfg))
|
||||||
|
{
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OidParametroHealthConfig
|
||||||
|
{
|
||||||
|
Parametro = parametro,
|
||||||
|
RedisKey = parametro.ToString().ToLowerInvariant(),
|
||||||
|
FreqBaseHz = 0.5,
|
||||||
|
FreqMinHz = 0.2,
|
||||||
|
EmUsoHealth = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double ObterFreqBaseHz(OidParametros parametro)
|
||||||
|
{
|
||||||
|
return ObterConfigHealth(parametro).FreqBaseHz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double ObterFreqMinHz(OidParametros parametro)
|
||||||
|
{
|
||||||
|
return ObterConfigHealth(parametro).FreqMinHz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ParametroEmUsoHealth(OidParametros parametro)
|
||||||
|
{
|
||||||
|
return ObterConfigHealth(parametro).EmUsoHealth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double ObterIntervaloPollingParametroMs(OidParametros parametro)
|
||||||
|
{
|
||||||
|
if (IntervaloParametro.TryGetValue(parametro, out TimeSpan intervalo))
|
||||||
|
{
|
||||||
|
return intervalo.TotalMilliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 500.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static (string campo, object valor)[] GerarCamposRedisHealthBase(int enderecoMov)
|
||||||
|
{
|
||||||
|
var campos = new List<(string campo, object valor)>();
|
||||||
|
|
||||||
|
foreach (var kv in HealthParametroConfig)
|
||||||
|
{
|
||||||
|
var cfg = kv.Value;
|
||||||
|
string key = cfg.RedisKey;
|
||||||
|
|
||||||
|
campos.Add((
|
||||||
|
$"{enderecoMov}.freq_base.{key}",
|
||||||
|
cfg.FreqBaseHz
|
||||||
|
));
|
||||||
|
|
||||||
|
campos.Add((
|
||||||
|
$"{enderecoMov}.freq_min.{key}",
|
||||||
|
cfg.FreqMinHz
|
||||||
|
));
|
||||||
|
|
||||||
|
campos.Add((
|
||||||
|
$"{enderecoMov}.freq_uso.{key}",
|
||||||
|
cfg.EmUsoHealth
|
||||||
|
));
|
||||||
|
|
||||||
|
campos.Add((
|
||||||
|
$"{enderecoMov}.polling_ms.{key}",
|
||||||
|
ObterIntervaloPollingParametroMs(kv.Key)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
campos.Add((
|
||||||
|
$"{enderecoMov}.polling.intervalo_timer_ms",
|
||||||
|
TaxaAmostragem
|
||||||
|
));
|
||||||
|
|
||||||
|
campos.Add((
|
||||||
|
$"{enderecoMov}.polling.qtd_parametros",
|
||||||
|
OrdemPolling.Length
|
||||||
|
));
|
||||||
|
|
||||||
|
campos.Add((
|
||||||
|
$"{enderecoMov}.polling.ordem",
|
||||||
|
OrdemPolling.Select(x => ObterConfigHealth(x).RedisKey).ToList()
|
||||||
|
));
|
||||||
|
|
||||||
|
return campos.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static bool Iniciado
|
public static bool Iniciado
|
||||||
{
|
{
|
||||||
|
|
@ -542,47 +742,25 @@ namespace AgroBase.Services
|
||||||
|
|
||||||
private static OidParametros? EscolherProximoParametro(byte idTx)
|
private static OidParametros? EscolherProximoParametro(byte idTx)
|
||||||
{
|
{
|
||||||
DateTime agora =
|
DateTime agora = DateTime.Now;
|
||||||
DateTime.Now;
|
|
||||||
|
|
||||||
int cursor =
|
int cursor = _cursorPollingPorDriver.TryGetValue(idTx, out int c) ? c : 0;
|
||||||
_cursorPollingPorDriver.TryGetValue(
|
|
||||||
idTx,
|
|
||||||
out int c
|
|
||||||
)
|
|
||||||
? c
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
for (int tentativa = 0;
|
for (int tentativa = 0; tentativa < OrdemPolling.Length; tentativa++)
|
||||||
tentativa < OrdemPolling.Length;
|
|
||||||
tentativa++)
|
|
||||||
{
|
{
|
||||||
int index =
|
int index = (cursor + tentativa) % OrdemPolling.Length;
|
||||||
(cursor + tentativa) %
|
|
||||||
OrdemPolling.Length;
|
|
||||||
|
|
||||||
OidParametros parametro =
|
OidParametros parametro = OrdemPolling[index];
|
||||||
OrdemPolling[index];
|
|
||||||
|
|
||||||
string chave =
|
string chave = idTx.ToString("X2") + ":" + ((byte)parametro).ToString("X2");
|
||||||
idTx.ToString("X2") +
|
|
||||||
":" +
|
|
||||||
((byte)parametro).ToString("X2");
|
|
||||||
|
|
||||||
TimeSpan intervalo =
|
TimeSpan intervalo = IntervaloParametro.TryGetValue(parametro, out TimeSpan valor)
|
||||||
IntervaloParametro.TryGetValue(
|
? valor
|
||||||
parametro,
|
: TimeSpan.FromMilliseconds(500);
|
||||||
out TimeSpan valor
|
|
||||||
)
|
|
||||||
? valor
|
|
||||||
: TimeSpan.FromMilliseconds(500);
|
|
||||||
|
|
||||||
if (!_ultimoEnvioParametro.TryGetValue(chave, out DateTime ultimo) ||
|
if (!_ultimoEnvioParametro.TryGetValue(chave, out DateTime ultimo) || agora - ultimo >= intervalo)
|
||||||
agora - ultimo >= intervalo)
|
|
||||||
{
|
{
|
||||||
_cursorPollingPorDriver[idTx] =
|
_cursorPollingPorDriver[idTx] = (index + 1) % OrdemPolling.Length;
|
||||||
(index + 1) %
|
|
||||||
OrdemPolling.Length;
|
|
||||||
|
|
||||||
return parametro;
|
return parametro;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -424,13 +424,20 @@ namespace AgroBase.Services.Operadores
|
||||||
);
|
);
|
||||||
|
|
||||||
int endereco_mov = mod.MovMotor._EnderecoCAN_Tx;
|
int endereco_mov = mod.MovMotor._EnderecoCAN_Tx;
|
||||||
RedisService.AtualizarCampos(
|
var camposMov = new List<(string campo, object valor)>
|
||||||
RedisService.ModKey(Enums.T_Code.Mov),
|
{
|
||||||
($"{endereco_mov}.timestamp", agora),
|
($"{endereco_mov}.timestamp", agora),
|
||||||
($"{endereco_mov}.conectado", mod.MovMotor.Inicializado),
|
($"{endereco_mov}.conectado", mod.MovMotor.Inicializado),
|
||||||
($"{endereco_mov}.freq_base", 1),
|
|
||||||
|
// legado
|
||||||
|
($"{endereco_mov}.freq_base",
|
||||||
|
OIDCanService.ObterFreqBaseHz(
|
||||||
|
OIDCanService.OidHandler.OidParametros.VelocidadeAtual
|
||||||
|
)),
|
||||||
|
|
||||||
($"{endereco_mov}.endereco", mod.MovMotor._EnderecoCAN_Tx),
|
($"{endereco_mov}.endereco", mod.MovMotor._EnderecoCAN_Tx),
|
||||||
($"{endereco_mov}.mod_id", mod.Modulo_ID),
|
($"{endereco_mov}.mod_id", mod.Modulo_ID),
|
||||||
|
|
||||||
($"{endereco_mov}.cod_erro", mod.MovMotor.CodigoAlarme),
|
($"{endereco_mov}.cod_erro", mod.MovMotor.CodigoAlarme),
|
||||||
($"{endereco_mov}.rpm", mod.MovMotor.RPM_Roda),
|
($"{endereco_mov}.rpm", mod.MovMotor.RPM_Roda),
|
||||||
($"{endereco_mov}.rpm_sp", mod.MovMotor.RPM_SP_Leitura),
|
($"{endereco_mov}.rpm_sp", mod.MovMotor.RPM_SP_Leitura),
|
||||||
|
|
@ -440,12 +447,21 @@ namespace AgroBase.Services.Operadores
|
||||||
($"{endereco_mov}.temperatura_driver", mod.MovMotor.TemperaturaDriver),
|
($"{endereco_mov}.temperatura_driver", mod.MovMotor.TemperaturaDriver),
|
||||||
($"{endereco_mov}.temperatura_motor", mod.MovMotor.Temperatura),
|
($"{endereco_mov}.temperatura_motor", mod.MovMotor.Temperatura),
|
||||||
($"{endereco_mov}.freado", mod.MovMotor.Leitura?.Freado ?? false),
|
($"{endereco_mov}.freado", mod.MovMotor.Leitura?.Freado ?? false),
|
||||||
|
|
||||||
($"{endereco_mov}.freq.erro", mod.MovMotor.Leitura?.CodigoAlarme?.frequencia ?? 0),
|
($"{endereco_mov}.freq.erro", mod.MovMotor.Leitura?.CodigoAlarme?.frequencia ?? 0),
|
||||||
($"{endereco_mov}.freq.rpm", mod.MovMotor.Leitura?.ERPM?.frequencia ?? 0),
|
($"{endereco_mov}.freq.rpm", mod.MovMotor.Leitura?.ERPM?.frequencia ?? 0),
|
||||||
($"{endereco_mov}.freq.tensao", mod.MovMotor.Leitura?.Tensao?.frequencia ?? 0),
|
($"{endereco_mov}.freq.tensao", mod.MovMotor.Leitura?.Tensao?.frequencia ?? 0),
|
||||||
($"{endereco_mov}.freq.corrente_motor", mod.MovMotor.Leitura?.CorrenteMotor?.frequencia ?? 0),
|
($"{endereco_mov}.freq.corrente_motor", mod.MovMotor.Leitura?.CorrenteMotor?.frequencia ?? 0),
|
||||||
($"{endereco_mov}.freq.corrente_barramento", mod.MovMotor.Leitura?.CorrenteBarramento?.frequencia ?? 0),
|
($"{endereco_mov}.freq.corrente_barramento", mod.MovMotor.Leitura?.CorrenteBarramento?.frequencia ?? 0),
|
||||||
($"{endereco_mov}.freq.temperatura", mod.MovMotor.Leitura?.Temperatura?.frequencia ?? 0)
|
($"{endereco_mov}.freq.temperatura", mod.MovMotor.Leitura?.Temperatura?.frequencia ?? 0),
|
||||||
|
|
||||||
|
($"{endereco_mov}.freq.ciclo_trabalho", mod.MovMotor.Leitura?.CicloTrabalho?.frequencia ?? 0),
|
||||||
|
($"{endereco_mov}.freq.potencia", mod.MovMotor.Leitura?.Potencia?.frequencia ?? 0),
|
||||||
|
};
|
||||||
|
camposMov.AddRange(OIDCanService.GerarCamposRedisHealthBase(endereco_mov));
|
||||||
|
RedisService.AtualizarCampos(
|
||||||
|
RedisService.ModKey(Enums.T_Code.Mov),
|
||||||
|
camposMov.ToArray()
|
||||||
);
|
);
|
||||||
|
|
||||||
dirAtivos.Add(endereco_dir);
|
dirAtivos.Add(endereco_dir);
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,8 @@ class SensorFluxo_v2 : public ComponenteCAN {
|
||||||
float CalcularVazao(uint16_t pulsos, unsigned long periodoMs) {
|
float CalcularVazao(uint16_t pulsos, unsigned long periodoMs) {
|
||||||
if (periodoMs == 0) return 0.0f;
|
if (periodoMs == 0) return 0.0f;
|
||||||
|
|
||||||
|
const float FATOR_CALIBRACAO_FLUXO = 0.776f;
|
||||||
|
|
||||||
float frequenciaHz = ((float)pulsos) * 1000.0f / (float)periodoMs;
|
float frequenciaHz = ((float)pulsos) * 1000.0f / (float)periodoMs;
|
||||||
|
|
||||||
float q_L_min = (frequenciaHz + 3.0f) / 8.1f;
|
float q_L_min = (frequenciaHz + 3.0f) / 8.1f;
|
||||||
|
|
@ -159,6 +161,9 @@ class SensorFluxo_v2 : public ComponenteCAN {
|
||||||
if (q_L_min > 10.0f) q_L_min = 10.0f;
|
if (q_L_min > 10.0f) q_L_min = 10.0f;
|
||||||
|
|
||||||
float q_mL_s = q_L_min * (1000.0f / 60.0f);
|
float q_mL_s = q_L_min * (1000.0f / 60.0f);
|
||||||
|
|
||||||
|
q_mL_s *= FATOR_CALIBRACAO_FLUXO;
|
||||||
|
|
||||||
return q_mL_s;
|
return q_mL_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue