ajustes para oid

This commit is contained in:
Diego Freitas 2026-06-22 17:32:04 -03:00
parent 92a845aec0
commit c3b93d4906
4 changed files with 237 additions and 56 deletions

View File

@ -257,14 +257,7 @@ namespace AgroBase.Models.Modules
{
byte addrTx = Modulo.MovMotor._EnderecoCAN_Tx;
byte addrRx = Modulo.MovMotor._EnderecoCAN_Rx;
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.VelocidadeAtual);
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.Potencia);
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.Temperatura);
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.CicloTrabalho);
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.CodErro);
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.CorrenteBarramento);
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.CorrenteMotor);
OIDCanService.RequisitarDado(addrTx, addrRx, OIDCanService.OidHandler.OidParametros.Tensao);
OIDCanService.RequisitarProximoDado(addrTx, addrRx);
Modulo.MovMotor.RequisitarDadosSensoresExternos();
var Controle = Variaveis.OperacaoEmAndamento.Controle.TiposControle?.FirstOrDefault(x => x.Tipo == T_Code.Mov);

View File

@ -797,7 +797,68 @@ namespace AgroBase.Services
{
_roteadores.TryGetValue(id, out ICanMessageHandler handler);
T_Code dispositivo = handler?.Dispositivo ?? T_Code.Vzo;
if (handler == null)
{
/*
* Fallback para OID/par Tx-Rx:
* Se o frame chegou pelo ID de TX do pendente, talvez não exista
* roteador registrado exatamente nesse ID. Tenta achar o handler
* pelo dispositivo pendente.
*/
T_Code? dispositivoPendente = null;
lock (_LockMensagens)
{
dispositivoPendente =
MensagensPendentes
.Where(x =>
x.ComResposta &&
x.Enviado &&
!x.Respondido &&
(
x.IdRx == id ||
x.IdTx == id
))
.OrderBy(x => x.EnviadoEm)
.Select(x => (T_Code?)x.Dispositivo)
.FirstOrDefault();
}
if (dispositivoPendente.HasValue)
{
handler =
_roteadores
.Values
.FirstOrDefault(
h => h.Dispositivo == dispositivoPendente.Value
);
}
}
T_Code dispositivo =
handler?.Dispositivo ?? T_Code.Vzo;
if (dispositivo == T_Code.Vzo)
{
lock (_LockMensagens)
{
var pendente =
MensagensPendentes
.Where(x =>
x.ComResposta &&
x.Enviado &&
!x.Respondido &&
(
x.IdRx == id ||
x.IdTx == id
))
.OrderBy(x => x.EnviadoEm)
.FirstOrDefault();
if (pendente != null)
dispositivo = pendente.Dispositivo;
}
}
bool db = dispositivo == T_Code.Bat;
byte fCodeRx = db ? (byte)DalyBMSService.GetDataId(id) : data.Length > 0 ? data[0] : (byte)0x00;
@ -854,7 +915,11 @@ namespace AgroBase.Services
}
}
private bool MensagemCorrespondeResposta(CanMessage pendente, T_Code dispositivoResposta, uint idResposta, byte[] dataResposta)
private bool MensagemCorrespondeResposta(
CanMessage pendente,
T_Code dispositivoResposta,
uint idResposta,
byte[] dataResposta)
{
if (pendente == null)
return false;
@ -871,9 +936,6 @@ namespace AgroBase.Services
if (pendente.Dispositivo != dispositivoResposta)
return false;
if (pendente.IdRx != idResposta)
return false;
byte[] dataTx =
pendente.DataTx ?? new byte[0];
@ -884,32 +946,45 @@ namespace AgroBase.Services
{
case T_Code.Bat:
/*
* Daly: DataID vem no CAN ID, então idRx fechou.
* Daly usa DataID no CAN ID estendido.
*/
return true;
return pendente.IdRx == idResposta;
case T_Code.Mks:
return
pendente.IdRx == idResposta &&
dataRx.Length > 0 &&
pendente.funcCodeRx == dataRx[0];
case T_Code.Oid:
/*
* OID:
* consulta retorna DATA[0]=0x0F e DATA[1]=param.
*/
return
dataRx.Length >= 2 &&
dataTx.Length >= 2 &&
dataRx[0] == pendente.funcCodeRx &&
dataRx[1] == dataTx[1];
{
/*
* OID pode responder no mesmo ID do comando ou no par lógico RX.
*/
bool idOk =
pendente.IdRx == idResposta ||
pendente.IdTx == idResposta;
if (!idOk)
return false;
/*
* Consulta OID:
* TX: DATA[0]=0x0F, DATA[1]=param
* RX: DATA[0]=0x0F, DATA[1]=param, DATA[2..]=valor
*/
return
dataRx.Length >= 2 &&
dataTx.Length >= 2 &&
dataRx[0] == pendente.funcCodeRx &&
dataRx[1] == dataTx[1];
}
case T_Code.Atu:
case T_Code.Sen:
/*
* ATU/SEN:
* casa pelo func/posição e, quando existir, pelo ID_Num.
*/
if (pendente.IdRx != idResposta)
return false;
if (dataRx.Length <= 0)
return false;
@ -922,6 +997,9 @@ namespace AgroBase.Services
return true;
default:
if (pendente.IdRx != idResposta)
return false;
if (dataRx.Length <= 0)
return false;

View File

@ -139,7 +139,7 @@ namespace AgroBase.Services
public static int TaxaAmostragem
{
get { return 1000; }
get { return 60; }
}
public static async Task<bool> VerificaDispositivoConectado()
@ -170,7 +170,7 @@ namespace AgroBase.Services
byte idRx =
modulo.MovMotor._EnderecoCAN_Rx;
RegistrarHandler(idRx);
RegistrarHandlersMotor(idTx, idRx);
EnviarComandoDescoberta(idTx, idRx);
@ -217,7 +217,10 @@ namespace AgroBase.Services
if (modulo == null)
continue;
RegistrarHandler(modulo._EnderecoCAN_Rx);
RegistrarHandlersMotor(
modulo._EnderecoCAN_Tx,
modulo._EnderecoCAN_Rx
);
var leitura =
DadosLeitura.FirstOrDefault(
@ -305,11 +308,19 @@ namespace AgroBase.Services
}
}
private static void RegistrarHandlersMotor(byte idTx, byte idRx)
{
RegistrarHandler(idTx);
if (idRx != idTx)
RegistrarHandler(idRx);
}
#region COMANDOS
private static void EnviarComandoDescoberta(byte idTx, byte idRx)
{
RegistrarHandler(idRx);
RegistrarHandlersMotor(idTx, idRx);
CanManager.CanService.AdicionarMensagemNaFila(
Dispositivo,
@ -333,7 +344,7 @@ namespace AgroBase.Services
bool get = true,
bool contabilizarTimeoutHealth = true)
{
RegistrarHandler(idRx);
RegistrarHandlersMotor(idTx, idRx);
CanManager.CanService.AdicionarMensagemNaFila(
dispositivo,
@ -420,6 +431,17 @@ namespace AgroBase.Services
_ultimaConsultaPendente[idTx] = dado;
}
Console.WriteLine(
"[OID/TX] idTx=" +
idTx.ToString("X2") +
" idRx=" +
idRx.ToString("X2") +
" param=" +
dado +
" data=0F-" +
((byte)dado).ToString("X2")
);
EnviarComando(
Dispositivo,
idTx,
@ -447,6 +469,22 @@ namespace AgroBase.Services
dado == OidParametros.CorrenteBarramento;
}
public static void RequisitarProximoDado(byte idTx, byte idRx)
{
OidParametros parametro =
EscolherProximoParametro(idTx) ??
OidParametros.VelocidadeAtual;
RequisitarDadoInterno(
idTx,
idRx,
parametro,
forcar: false,
contabilizarTimeoutHealth:
DeveContabilizarTimeoutHealth(parametro)
);
}
public static void AtualizarDados()
{
try
@ -996,30 +1034,98 @@ namespace AgroBase.Services
SinalZNaoEncontrado = 19
}
private OIDModel ObterOuCriar(uint _idTx, uint _idRx)
private OIDModel ObterOuCriar(CanMessage mensagem)
{
lock (DadosLeitura)
{
byte idTx =
CanManager.ConverterIdCan(_idTx)[0];
byte idTxMsg =
CanManager.ConverterIdCan(
mensagem.IdTx
)[0];
byte idRx =
CanManager.ConverterIdCan(_idRx)[0];
byte idRxMsg =
CanManager.ConverterIdCan(
mensagem.IdRx
)[0];
/*
* Primeiro, tenta achar pelo par exato.
*/
var item =
DadosLeitura.FirstOrDefault(
x => x.EnderecoTx == idTx &&
x.EnderecoRx == idRx
x => x.EnderecoTx == idTxMsg &&
x.EnderecoRx == idRxMsg
);
if (item != null)
return item;
/*
* Depois, tenta achar pelo motor configurado.
* Isso evita criar leitura órfã quando o OID responde no mesmo ID
* usado como Tx ou em outro ID lógico.
*/
var motor =
Variaveis
.OperacaoEmAndamento
.DispMvd?
.Dados?
.Modulos?
.Select(x => x?.MovMotor)
.FirstOrDefault(m =>
m != null &&
(
m._EnderecoCAN_Tx == idTxMsg ||
m._EnderecoCAN_Rx == idTxMsg ||
m._EnderecoCAN_Tx == idRxMsg ||
m._EnderecoCAN_Rx == idRxMsg
)
);
if (motor != null)
{
item =
DadosLeitura.FirstOrDefault(
x => x.EnderecoTx == motor._EnderecoCAN_Tx
);
if (item == null)
{
item = new OIDModel
{
EnderecoTx = motor._EnderecoCAN_Tx,
EnderecoRx = motor._EnderecoCAN_Rx
};
DadosLeitura.Add(item);
}
else
{
item.EnderecoRx = motor._EnderecoCAN_Rx;
}
return item;
}
/*
* Fallback final.
*/
item =
DadosLeitura.FirstOrDefault(
x =>
x.EnderecoTx == idTxMsg ||
x.EnderecoRx == idTxMsg ||
x.EnderecoTx == idRxMsg ||
x.EnderecoRx == idRxMsg
);
if (item == null)
{
item =
new OIDModel
{
EnderecoTx = idTx,
EnderecoRx = idRx
};
item = new OIDModel
{
EnderecoTx = idTxMsg,
EnderecoRx = idRxMsg
};
DadosLeitura.Add(item);
}
@ -1052,11 +1158,7 @@ namespace AgroBase.Services
return;
}
var item =
ObterOuCriar(
mensagem.IdTx,
mensagem.IdRx
);
var item = ObterOuCriar(mensagem);
if (func == OidFuncCode.ConsultaStatusRetornoZero)
{
@ -1070,6 +1172,15 @@ namespace AgroBase.Services
return;
}
Console.WriteLine(
"[OID/RX] idTx=" +
mensagem.IdTx.ToString("X") +
" idRx=" +
mensagem.IdRx.ToString("X") +
" data=" +
BitConverter.ToString(mensagem.DataRx ?? new byte[0])
);
OidParametros parametro =
(OidParametros)mensagem.DataRx[1];
@ -1084,9 +1195,8 @@ namespace AgroBase.Services
lock (_sync)
{
_ultimaConsultaPendente.Remove(
item.EnderecoTx
);
_ultimaConsultaPendente.Remove(item.EnderecoTx);
_ultimaConsultaPendente.Remove(item.EnderecoRx);
}
}
catch (Exception ex)
@ -1223,4 +1333,4 @@ namespace AgroBase.Services
model.ModoControle = modo;
}
}
}
}

View File

@ -428,7 +428,7 @@ namespace AgroBase.Services.Operadores
RedisService.ModKey(Enums.T_Code.Mov),
($"{endereco_mov}.timestamp", agora),
($"{endereco_mov}.conectado", mod.MovMotor.Inicializado),
($"{endereco_mov}.freq_base", Variaveis.OperacaoEmAndamento.DispMvd.Dados.tmrRegistradorMOV.IntervalHz),
($"{endereco_mov}.freq_base", 1),
($"{endereco_mov}.endereco", mod.MovMotor._EnderecoCAN_Tx),
($"{endereco_mov}.mod_id", mod.Modulo_ID),
($"{endereco_mov}.cod_erro", mod.MovMotor.CodigoAlarme),