ajustes no canservice
This commit is contained in:
parent
cae8b20601
commit
a33f02787c
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -3,20 +3,16 @@
|
|||
"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\\mpccontrolleraprimorado.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\mpccontrolleraprimorado.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
"AbsoluteMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|c:\\zendioninc\\agrobot_base\\agrobase\\agrobase\\services\\oidcanservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\services\\oidcanservice.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\\modules\\sensoriamentomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\modules\\sensoriamentomodel.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\\modules\\movimentacaomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\modules\\movimentacaomodel.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\\modules\\dispositivobasemodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\modules\\dispositivobasemodel.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\\modules\\atuadormodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\modules\\atuadormodel.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\\modules\\movimentacaounificadomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
|
||||
"RelativeMoniker": "D:0:0:{C54B41C0-1D21-4E3E-949E-0F86BBC86A33}|AgroBase\\AgroBase.csproj|solutionrelative:agrobase\\models\\modules\\movimentacaounificadomodel.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
|
||||
}
|
||||
],
|
||||
"DocumentGroupContainers": [
|
||||
|
|
@ -26,58 +22,45 @@
|
|||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": 0,
|
||||
"SelectedChildIndex": 2,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "MPCControllerAprimorado.cs",
|
||||
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\MPCControllerAprimorado.cs",
|
||||
"RelativeDocumentMoniker": "AgroBase\\Models\\MPCControllerAprimorado.cs",
|
||||
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\MPCControllerAprimorado.cs",
|
||||
"RelativeToolTip": "AgroBase\\Models\\MPCControllerAprimorado.cs",
|
||||
"ViewState": "AQIAAAAAAAAAAAAAAAAAABoAAABcAAAA",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-04-16T16:33:32.578Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 2,
|
||||
"Title": "DispositivoBaseModel.cs",
|
||||
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\DispositivoBaseModel.cs",
|
||||
"RelativeDocumentMoniker": "AgroBase\\Models\\Modules\\DispositivoBaseModel.cs",
|
||||
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\DispositivoBaseModel.cs",
|
||||
"RelativeToolTip": "AgroBase\\Models\\Modules\\DispositivoBaseModel.cs",
|
||||
"ViewState": "AQIAAAAAAAAAAAAAAAAAAAgAAAAnAAAA",
|
||||
"Title": "MovimentacaoUnificadoModel.cs",
|
||||
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\MovimentacaoUnificadoModel.cs",
|
||||
"RelativeDocumentMoniker": "AgroBase\\Models\\Modules\\MovimentacaoUnificadoModel.cs",
|
||||
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\MovimentacaoUnificadoModel.cs",
|
||||
"RelativeToolTip": "AgroBase\\Models\\Modules\\MovimentacaoUnificadoModel.cs",
|
||||
"ViewState": "AQIAAAAAAAAAAAAAAAAAAPEAAAAzAAAA",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-04-16T13:20:21.786Z",
|
||||
"WhenOpened": "2025-05-02T10:28:02.411Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 1,
|
||||
"Title": "SensoriamentoModel.cs",
|
||||
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\SensoriamentoModel.cs",
|
||||
"RelativeDocumentMoniker": "AgroBase\\Models\\Modules\\SensoriamentoModel.cs",
|
||||
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\SensoriamentoModel.cs",
|
||||
"RelativeToolTip": "AgroBase\\Models\\Modules\\SensoriamentoModel.cs",
|
||||
"ViewState": "AQIAABsHAAAAAAAAAAAuwEUIAAAOAAAA",
|
||||
"Title": "MovimentacaoModel.cs",
|
||||
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\MovimentacaoModel.cs",
|
||||
"RelativeDocumentMoniker": "AgroBase\\Models\\Modules\\MovimentacaoModel.cs",
|
||||
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\MovimentacaoModel.cs",
|
||||
"RelativeToolTip": "AgroBase\\Models\\Modules\\MovimentacaoModel.cs",
|
||||
"ViewState": "AQIAAPYAAAAAAAAAAAAwwF8BAAA/AAAA",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-04-15T10:44:14.963Z",
|
||||
"WhenOpened": "2025-05-02T09:59:28.094Z",
|
||||
"EditorCaption": ""
|
||||
},
|
||||
{
|
||||
"$type": "Document",
|
||||
"DocumentIndex": 3,
|
||||
"Title": "AtuadorModel.cs",
|
||||
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\AtuadorModel.cs",
|
||||
"RelativeDocumentMoniker": "AgroBase\\Models\\Modules\\AtuadorModel.cs",
|
||||
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Models\\Modules\\AtuadorModel.cs",
|
||||
"RelativeToolTip": "AgroBase\\Models\\Modules\\AtuadorModel.cs",
|
||||
"ViewState": "AQIAAAAAAAAAAAAAAAAAAAEAAAAYAAAA",
|
||||
"DocumentIndex": 0,
|
||||
"Title": "OIDCanService.cs",
|
||||
"DocumentMoniker": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Services\\OIDCanService.cs",
|
||||
"RelativeDocumentMoniker": "AgroBase\\Services\\OIDCanService.cs",
|
||||
"ToolTip": "C:\\ZendionINC\\agrobot_base\\AgroBase\\AgroBase\\Services\\OIDCanService.cs",
|
||||
"RelativeToolTip": "AgroBase\\Services\\OIDCanService.cs",
|
||||
"ViewState": "AQIAAAAAAAAAAAAAAAAAAMAAAABGAAAA",
|
||||
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
|
||||
"WhenOpened": "2025-04-15T10:40:50.024Z",
|
||||
"WhenOpened": "2025-05-01T23:29:12.777Z",
|
||||
"EditorCaption": ""
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2377,7 +2377,7 @@ namespace AgroBase.Forms
|
|||
{
|
||||
if (!CanService.IsConnected)
|
||||
{
|
||||
CanService.DefinirPortaCOM(new SerialPort(cmbPorta.Text, Convert.ToInt32(cmbBaud.Text)));
|
||||
Task.Run(async () => await CanService.DefinirPortaCOM(new SerialPort(cmbPorta.Text, Convert.ToInt32(cmbBaud.Text))));
|
||||
}
|
||||
|
||||
if (CanService.IsConnected)
|
||||
|
|
|
|||
|
|
@ -392,7 +392,11 @@ namespace AgroBase.Models.Modules
|
|||
{
|
||||
if (!CanService.IsConnected)
|
||||
{
|
||||
CanService.DefinirPortaCOM(porta);
|
||||
bool sucesso = await CanService.DefinirPortaCOM(porta);
|
||||
if (!sucesso)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CanService.RegistrarHandler(_EnderecoCAN_Rx, _AtuHandler);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ namespace AgroBase.Models.Modules
|
|||
return Leitura?.CorrenteMotor != 0;
|
||||
}
|
||||
}
|
||||
public double LeituraRPM { get; set; } = 0;
|
||||
public bool ComandoLigado { get; set; } = false;
|
||||
//public bool Freio { get; set; } = false;
|
||||
public OidCodigoErro CodigoAlarme
|
||||
|
|
@ -395,14 +396,12 @@ namespace AgroBase.Models.Modules
|
|||
return;
|
||||
}
|
||||
|
||||
byte Addr = _EnderecoCAN_Tx;
|
||||
DateTime Agora = DateTime.Now;
|
||||
|
||||
bool SentidoAlterado = Sentido_SP != Sentido.Parado && (Leitura == null || Leitura.Direcao != Sentido_SP);
|
||||
bool RPMAlterado = ComandoLigado && (Leitura == null || _Controle.PercentualVelocidadeSP != Variaveis.OperacaoEmAndamento.ControleAnterior.PercentualVelocidadeSP);
|
||||
bool LigadoAlterado = Leitura == null || ComandoLigado != LeituraLigado;
|
||||
bool FreioAlterado = Leitura == null || Leitura.Freado != Freado;
|
||||
bool EnviaComando = SentidoAlterado || RPMAlterado || LigadoAlterado;
|
||||
bool PrimeiraLeitura = Leitura == null;
|
||||
bool SentidoAlterado = (Leitura?.Direcao ?? Sentido.Parado) != Sentido_SP;
|
||||
bool RPMAlterado = LeituraRPM != RPM_SP;
|
||||
bool LigadoAlterado = LeituraLigado != ComandoLigado;
|
||||
bool FreioAlterado = (Leitura?.Freado ?? false) != Freado;
|
||||
bool EnviaComando = PrimeiraLeitura || SentidoAlterado || RPMAlterado || LigadoAlterado;
|
||||
|
||||
OidFuncCode modoControle =
|
||||
Freado ? OidFuncCode.ComandoCorrenteFreio :
|
||||
|
|
@ -418,6 +417,8 @@ namespace AgroBase.Models.Modules
|
|||
float velocidade = RPM_SP * mx;
|
||||
|
||||
OIDCanService.ComandoControle(_EnderecoCAN_Tx, _EnderecoCAN_Rx, modoControle, velocidade);
|
||||
|
||||
LeituraRPM = RPM_SP;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -775,7 +775,11 @@ namespace AgroBase.Models.Modules
|
|||
{
|
||||
if (!CanService.IsConnected)
|
||||
{
|
||||
CanService.DefinirPortaCOM(porta);
|
||||
bool sucesso = await CanService.DefinirPortaCOM(porta);
|
||||
if (!sucesso)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CanService.RegistrarHandler(_EnderecoCAN_Rx, _SenHandler);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System.Collections.Generic;
|
|||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static AgroBase.Models.Enums;
|
||||
|
||||
|
|
@ -60,7 +59,6 @@ namespace AgroBase.Services
|
|||
public static SerialPort _PortaCAN;
|
||||
public static string _portName;
|
||||
private static int _baudRate;
|
||||
private static object _lock = new object();
|
||||
public static bool IsConnected { get; private set; }
|
||||
public static bool Iniciado
|
||||
{
|
||||
|
|
@ -73,12 +71,11 @@ namespace AgroBase.Services
|
|||
private static AsyncTaskTimerModel tmrOuvirCAN;
|
||||
private static AsyncTaskTimerModel tmrProcessarCAN;
|
||||
private static StringBuilder SerialCANBuffer = new StringBuilder();
|
||||
private static object _framesLock = new object();
|
||||
private static readonly Queue<string> FramesRecebidos = new Queue<string>();
|
||||
private static ConcurrentQueue<string> FramesRecebidos = new ConcurrentQueue<string>();
|
||||
private static readonly ConcurrentDictionary<byte, ICanMessageHandler> _roteadores = new ConcurrentDictionary<byte, ICanMessageHandler>();
|
||||
private static byte? _ultimoIdEnviado = null;
|
||||
|
||||
private static List<CanMessage> Mensagens = new List<CanMessage>();
|
||||
private static ConcurrentDictionary<string, CanMessage> MensagensPendentes = new ConcurrentDictionary<string, CanMessage>();
|
||||
|
||||
|
||||
public static void RegistrarHandler(byte endereco_rx, ICanMessageHandler handler)
|
||||
|
|
@ -86,48 +83,51 @@ namespace AgroBase.Services
|
|||
_roteadores[endereco_rx] = handler;
|
||||
}
|
||||
|
||||
public static void DefinirPortaCOM(SerialPort Porta)
|
||||
public static async Task<bool> DefinirPortaCOM(SerialPort Porta)
|
||||
{
|
||||
if (!IsConnected)
|
||||
{
|
||||
Porta.Close();
|
||||
}
|
||||
|
||||
bool sucesso = false;
|
||||
|
||||
if (_PortaCAN == null || !IsConnected)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_portName = Porta.PortName;
|
||||
_baudRate = 115200;
|
||||
_portName = Porta.PortName;
|
||||
_baudRate = 115200;
|
||||
|
||||
_PortaCAN = new SerialPort(_portName, _baudRate, Parity.None, 8, StopBits.One);
|
||||
_PortaCAN.Open();
|
||||
_PortaCAN = new SerialPort(_portName, _baudRate, Parity.None, 8, StopBits.One);
|
||||
_PortaCAN.Open();
|
||||
|
||||
EnviarComando("S6\r"); // 500Kbps
|
||||
Thread.Sleep(100);
|
||||
EnviarComando("O\r"); // Open CAN
|
||||
Thread.Sleep(100);
|
||||
sucesso = EnviarComando("S6\r"); // 500Kbps
|
||||
if (!sucesso) return sucesso;
|
||||
await Task.Delay(100);
|
||||
sucesso = EnviarComando("O\r"); // Open CAN
|
||||
await Task.Delay(100);
|
||||
if (!sucesso) return sucesso;
|
||||
|
||||
tmrOuvirCAN?.Dispose();
|
||||
tmrOuvirCAN = new AsyncTaskTimerModel("tmrOuvirCAN", OuvirCAN, 5);
|
||||
tmrOuvirCAN.Start();
|
||||
tmrOuvirCAN?.Dispose();
|
||||
tmrOuvirCAN = new AsyncTaskTimerModel("tmrOuvirCAN", OuvirCAN, 5);
|
||||
tmrOuvirCAN.Start();
|
||||
|
||||
tmrEnviarCAN?.Dispose();
|
||||
tmrEnviarCAN = new AsyncTaskTimerModel("tmrEnviarCAN", EnviarCAN, 100);
|
||||
tmrEnviarCAN.Start();
|
||||
tmrEnviarCAN?.Dispose();
|
||||
tmrEnviarCAN = new AsyncTaskTimerModel("tmrEnviarCAN", EnviarCAN, 5);
|
||||
tmrEnviarCAN.Start();
|
||||
|
||||
tmrProcessarCAN?.Dispose();
|
||||
tmrProcessarCAN = new AsyncTaskTimerModel("tmrProcessarCAN", ProcessarCAN, 5);
|
||||
tmrProcessarCAN.Start();
|
||||
tmrProcessarCAN?.Dispose();
|
||||
tmrProcessarCAN = new AsyncTaskTimerModel("tmrProcessarCAN", ProcessarCAN, 10);
|
||||
tmrProcessarCAN.Start();
|
||||
|
||||
IsConnected = true;
|
||||
}
|
||||
IsConnected = true;
|
||||
}
|
||||
|
||||
if (_PortaCAN != null && !_PortaCAN.IsOpen)
|
||||
{
|
||||
_PortaCAN.Open();
|
||||
}
|
||||
|
||||
return sucesso;
|
||||
}
|
||||
|
||||
private static async Task OuvirCAN()
|
||||
|
|
@ -147,10 +147,7 @@ namespace AgroBase.Services
|
|||
|
||||
if (!string.IsNullOrWhiteSpace(frame))
|
||||
{
|
||||
lock (_framesLock)
|
||||
{
|
||||
FramesRecebidos.Enqueue(frame);
|
||||
}
|
||||
FramesRecebidos.Enqueue(frame);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -163,17 +160,7 @@ namespace AgroBase.Services
|
|||
|
||||
private static async Task ProcessarCAN()
|
||||
{
|
||||
string frame = null;
|
||||
|
||||
lock (_framesLock)
|
||||
{
|
||||
if (FramesRecebidos.Count > 0)
|
||||
{
|
||||
frame = FramesRecebidos.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
if (frame != null)
|
||||
if (FramesRecebidos.TryDequeue(out string frame))
|
||||
{
|
||||
ProcessarFrameCAN(frame);
|
||||
}
|
||||
|
|
@ -198,20 +185,12 @@ namespace AgroBase.Services
|
|||
}
|
||||
|
||||
byte fCodeRx = data[0];
|
||||
|
||||
var mensagem = new CanMessage();
|
||||
|
||||
lock (Mensagens)
|
||||
{
|
||||
mensagem = Mensagens
|
||||
.Where(x => x.IdRx == id)
|
||||
.OrderBy(x => x.EnviadoEm)
|
||||
.FirstOrDefault(x => x.Enviado && !x.Respondido && x.funcCodeRx == fCodeRx);
|
||||
}
|
||||
var mensagem = new CanMessage() { IdTx = (byte)id, IdRx = (byte)id, funcCodeRx = fCodeRx, DataRx = data };
|
||||
|
||||
if (mensagem == null)
|
||||
if (!MensagensPendentes.TryRemove(GerarChaveDicionarioFila(mensagem), out mensagem))
|
||||
{
|
||||
mensagem = new CanMessage { IdTx = (byte)id, IdRx = (byte)id, DataRx = data };
|
||||
mensagem = new CanMessage { IdTx = (byte)id, IdRx = (byte)id, funcCodeRx = fCodeRx, DataRx = data };
|
||||
}
|
||||
|
||||
mensagem.DataRx = data;
|
||||
|
|
@ -226,6 +205,8 @@ namespace AgroBase.Services
|
|||
{
|
||||
Console.WriteLine($"[CAN] ID_Num não tratado: 0x{id:X2}, fCodeRx: 0x{fCodeRx:X2}");
|
||||
}
|
||||
|
||||
LimparMensagensAntigas();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -260,70 +241,51 @@ namespace AgroBase.Services
|
|||
ComResposta = get
|
||||
};
|
||||
|
||||
lock (Mensagens)
|
||||
string chave = GerarChaveDicionarioFila(novaMensagem);
|
||||
|
||||
if (MensagensPendentes.ContainsKey(chave))
|
||||
{
|
||||
// Limpa mensagens antigas antes de avaliar
|
||||
LimparMensagensAntigas();
|
||||
|
||||
var existente = Mensagens.FirstOrDefault(x =>
|
||||
x.IdTx == novaMensagem.IdTx &&
|
||||
x.funcCodeTx == novaMensagem.funcCodeTx &&
|
||||
x.funcCodeRx == novaMensagem.funcCodeRx &&
|
||||
x.ComResposta == novaMensagem.ComResposta &&
|
||||
x.DataTx.SequenceEqual(novaMensagem.DataTx) &&
|
||||
(!x.Enviado || (x.ComResposta && !x.Respondido)) // Está pendente
|
||||
);
|
||||
|
||||
if (existente != null)
|
||||
{
|
||||
// Já existe mensagem igual aguardando ou pendente
|
||||
return;
|
||||
}
|
||||
|
||||
// Log e adiciona
|
||||
//Console.WriteLine($"[MSG] - MENSAGEM ADICIONADA NA FILA para o módulo {Dispositivo} - {FuncoesGlobais.ConverterComandoBytesParaTexto(novaMensagem.DataTx)}");
|
||||
Mensagens.Add(novaMensagem);
|
||||
return;
|
||||
}
|
||||
|
||||
MensagensPendentes.TryAdd(chave, novaMensagem);
|
||||
}
|
||||
|
||||
private static CanMessage ObterProximaMensagem()
|
||||
{
|
||||
lock (Mensagens)
|
||||
var mensagensPendentes = MensagensPendentes.Values
|
||||
.Where(x => !x.Enviado)
|
||||
.ToList();
|
||||
|
||||
if (!mensagensPendentes.Any())
|
||||
return null;
|
||||
|
||||
// Agrupa por IdTx e ordena os grupos
|
||||
var idsDisponiveis = mensagensPendentes
|
||||
.Select(x => x.IdTx)
|
||||
.Distinct()
|
||||
.OrderBy(x => x)
|
||||
.ToList();
|
||||
|
||||
byte proximoId;
|
||||
|
||||
if (!_ultimoIdEnviado.HasValue || !idsDisponiveis.Contains(_ultimoIdEnviado.Value))
|
||||
{
|
||||
var idsDisponiveis = Mensagens
|
||||
.Where(x => !x.Enviado)
|
||||
.Select(x => x.IdTx)
|
||||
.Distinct()
|
||||
.OrderBy(id => id)
|
||||
.ToList();
|
||||
|
||||
if (!idsDisponiveis.Any())
|
||||
return null;
|
||||
|
||||
byte proximoId;
|
||||
|
||||
if (!_ultimoIdEnviado.HasValue || !idsDisponiveis.Contains(_ultimoIdEnviado.Value))
|
||||
{
|
||||
// Começa pelo menor ID disponível
|
||||
proximoId = idsDisponiveis.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Busca o próximo ID após o último usado
|
||||
var index = idsDisponiveis.IndexOf(_ultimoIdEnviado.Value);
|
||||
if (index + 1 < idsDisponiveis.Count)
|
||||
proximoId = idsDisponiveis[index + 1];
|
||||
else
|
||||
proximoId = idsDisponiveis.First(); // ciclo completo
|
||||
}
|
||||
|
||||
var msg = Mensagens
|
||||
.Where(x => !x.Enviado && x.IdTx == proximoId)
|
||||
.OrderBy(x => x.Momento)
|
||||
.FirstOrDefault();
|
||||
|
||||
return msg;
|
||||
proximoId = idsDisponiveis.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
var index = idsDisponiveis.IndexOf(_ultimoIdEnviado.Value);
|
||||
proximoId = (index + 1 < idsDisponiveis.Count) ? idsDisponiveis[index + 1] : idsDisponiveis.First();
|
||||
}
|
||||
|
||||
// Seleciona a mensagem mais antiga com esse IdTx
|
||||
var proximaMsg = mensagensPendentes
|
||||
.Where(x => x.IdTx == proximoId)
|
||||
.OrderBy(x => x.Momento)
|
||||
.FirstOrDefault();
|
||||
|
||||
return proximaMsg;
|
||||
}
|
||||
|
||||
private static async Task EnviarCAN()
|
||||
|
|
@ -338,16 +300,18 @@ namespace AgroBase.Services
|
|||
|
||||
if (_ultimoIdEnviado.HasValue && msg.IdTx == _ultimoIdEnviado.Value)
|
||||
{
|
||||
await Task.Delay(5);
|
||||
//await Task.Delay(5);
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
EnviarComando(frame);
|
||||
EnviarComando(frame);
|
||||
|
||||
msg.Enviado = true;
|
||||
msg.EnviadoEm = DateTime.Now;
|
||||
_ultimoIdEnviado = msg.IdTx;
|
||||
msg.Enviado = true;
|
||||
msg.EnviadoEm = DateTime.Now;
|
||||
_ultimoIdEnviado = msg.IdTx;
|
||||
|
||||
if (!msg.ComResposta)
|
||||
{
|
||||
MensagensPendentes.TryRemove(GerarChaveDicionarioFila(msg), out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -363,26 +327,40 @@ namespace AgroBase.Services
|
|||
return frame;
|
||||
}
|
||||
|
||||
private static void EnviarComando(string comando)
|
||||
private static bool EnviarComando(string comando)
|
||||
{
|
||||
if (_PortaCAN?.IsOpen == true)
|
||||
{
|
||||
_PortaCAN.Write(comando);
|
||||
|
||||
//Console.WriteLine($"[CAN] Frame enviado: {comando}");
|
||||
bool sucesso = SerialService.EnviarDadosPortaSerial(_PortaCAN, comando, false, 20);
|
||||
if (sucesso)
|
||||
{
|
||||
//Console.WriteLine($"[CAN] Frame enviado: {comando}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[CAN] Erro ao enviar frame: {comando}");
|
||||
}
|
||||
return sucesso;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void LimparMensagensAntigas()
|
||||
{
|
||||
lock (Mensagens)
|
||||
var agora = DateTime.Now;
|
||||
|
||||
foreach (var item in MensagensPendentes)
|
||||
{
|
||||
var limite = DateTime.Now.AddSeconds(-5); // ⏱ 5 segundos de validade
|
||||
Mensagens.RemoveAll(x =>
|
||||
(!x.ComResposta && x.Enviado) || // Mensagem que não precisa resposta e já foi enviada
|
||||
(x.ComResposta && x.Respondido && x.RespondidoEm < limite) || // Resposta antiga
|
||||
(x.ComResposta && x.Enviado && !x.Respondido && x.EnviadoEm < limite) // Enviada mas nunca respondida e já passou do prazo
|
||||
);
|
||||
var msg = item.Value;
|
||||
|
||||
if (!msg.ComResposta && msg.Enviado) // mensagem sem resposta e já enviada
|
||||
MensagensPendentes.TryRemove(item.Key, out _);
|
||||
|
||||
else if (msg.ComResposta && msg.Respondido)
|
||||
MensagensPendentes.TryRemove(item.Key, out _);
|
||||
|
||||
else if (msg.ComResposta && msg.Enviado && !msg.Respondido && msg.EnviadoEm < agora.AddSeconds(-5))
|
||||
MensagensPendentes.TryRemove(item.Key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -391,12 +369,10 @@ namespace AgroBase.Services
|
|||
tmrOuvirCAN?.Dispose();
|
||||
tmrEnviarCAN?.Dispose();
|
||||
|
||||
lock (Mensagens)
|
||||
{
|
||||
Mensagens.Clear();
|
||||
}
|
||||
MensagensPendentes.Clear();
|
||||
|
||||
SerialCANBuffer.Clear();
|
||||
FramesRecebidos = new ConcurrentQueue<string>();
|
||||
_roteadores.Clear();
|
||||
_ultimoIdEnviado = null;
|
||||
|
||||
|
|
@ -422,6 +398,11 @@ namespace AgroBase.Services
|
|||
return (byte)(soma & 0xFF);
|
||||
}
|
||||
|
||||
private static string GerarChaveDicionarioFila(CanMessage msg)
|
||||
{
|
||||
byte parametro = (msg?.DataTx?.Length ?? 0) > 1 ? msg.DataTx[1] : (byte)0x00;
|
||||
return $"{msg.IdRx}_{msg.funcCodeRx}_{parametro}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -43,7 +43,11 @@ namespace AgroBase.Services
|
|||
{
|
||||
if (!CanService.IsConnected)
|
||||
{
|
||||
CanService.DefinirPortaCOM(porta);
|
||||
bool sucesso = await CanService.DefinirPortaCOM(porta);
|
||||
if (!sucesso)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (CanService.IsConnected)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ namespace AgroBase.Services
|
|||
public class OIDCanService
|
||||
{
|
||||
public static List<OIDModel> DadosLeitura = new List<OIDModel>();
|
||||
private static int _MStep { get; set; } = 16;
|
||||
private static T_Code Dispositivo { get; set; } = T_Code.Oid;
|
||||
private static OidHandler _OidHandler { get; set; } = new OidHandler();
|
||||
private static AsyncTaskTimerModel tmrHeartbeat;
|
||||
|
|
@ -37,7 +36,11 @@ namespace AgroBase.Services
|
|||
{
|
||||
if (!CanService.IsConnected)
|
||||
{
|
||||
CanService.DefinirPortaCOM(porta);
|
||||
bool sucesso = await CanService.DefinirPortaCOM(porta);
|
||||
if (!sucesso)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (CanService.IsConnected)
|
||||
|
|
@ -84,7 +87,7 @@ namespace AgroBase.Services
|
|||
if (tmrHeartbeat == null || !(tmrHeartbeat?.IsRunning ?? false))
|
||||
{
|
||||
tmrHeartbeat?.Dispose();
|
||||
tmrHeartbeat = new AsyncTaskTimerModel("tmrOidHeartbeat", tmrHeartbeat_Tick, 1000);
|
||||
tmrHeartbeat = new AsyncTaskTimerModel("tmrOidHeartbeat", tmrHeartbeat_Tick, 500);
|
||||
tmrHeartbeat.Start();
|
||||
}
|
||||
|
||||
|
|
@ -125,42 +128,43 @@ namespace AgroBase.Services
|
|||
|
||||
public static void RequisitarDado(byte idTx, byte idRx, OidParametros dado)
|
||||
{
|
||||
EnviarComando(Dispositivo, idTx, idRx, (byte)OidFuncCode.Consulta, new byte[] { (byte)dado });
|
||||
EnviarComando(Dispositivo, idTx, idRx, (byte)OidFuncCode.Consulta, new byte[] { (byte)dado }, true);
|
||||
}
|
||||
|
||||
public static void ComandoControle(byte idTx, byte idRx, OidFuncCode tipoControle, double setPoint)
|
||||
public static void ComandoControle(byte idTx, byte idRx, OidFuncCode funcCode, double setPoint)
|
||||
{
|
||||
byte[] setPointBytes = null;
|
||||
|
||||
switch (tipoControle)
|
||||
switch (funcCode)
|
||||
{
|
||||
case OidFuncCode.ComandoCorrente:
|
||||
case OidFuncCode.ComandoCorrenteFreio:
|
||||
case OidFuncCode.AjusteCorrenteMaxima:
|
||||
{
|
||||
short corrente_10mA = (short)(setPoint * 100);
|
||||
setPointBytes = BitConverter.GetBytes(corrente_10mA);
|
||||
setPointBytes = BitConverter.GetBytes(corrente_10mA).Reverse().ToArray();
|
||||
break;
|
||||
}
|
||||
case OidFuncCode.ComandoVelocidade:
|
||||
{
|
||||
int erpm = (int)(setPoint * VariaveisEquipamento.NumeroPolosMotor);
|
||||
setPointBytes = BitConverter.GetBytes(erpm);
|
||||
setPointBytes = BitConverter.GetBytes(erpm).Reverse().ToArray();
|
||||
break;
|
||||
}
|
||||
case OidFuncCode.ComandoCicloTrabalho:
|
||||
{
|
||||
short duty = (short)(Math.Max(-100, Math.Min(setPoint, 100)) * 10);
|
||||
setPointBytes = BitConverter.GetBytes(duty);
|
||||
setPointBytes = BitConverter.GetBytes(duty).Reverse().ToArray();
|
||||
break;
|
||||
}
|
||||
case OidFuncCode.AjusteAceleracaoVelocidade:
|
||||
case OidFuncCode.AjusteDesaceleracaoVelocidade:
|
||||
{
|
||||
if (setPoint <= 0) setPoint = 1;
|
||||
double erpmMax = VariaveisEquipamento.RPM_Max_Roda * VariaveisEquipamento.RelacaoRPM * VariaveisEquipamento.NumeroPolosMotor;
|
||||
int aceleracao = (int)(erpmMax / setPoint); // setPoint = tempo (s)
|
||||
|
||||
setPointBytes = BitConverter.GetBytes(aceleracao);
|
||||
setPointBytes = BitConverter.GetBytes(aceleracao).Reverse().ToArray();
|
||||
break;
|
||||
}
|
||||
case OidFuncCode.Heartbeat:
|
||||
|
|
@ -170,7 +174,7 @@ namespace AgroBase.Services
|
|||
}
|
||||
default:
|
||||
{
|
||||
Console.WriteLine($"[OID] Comando nao mapeado: {tipoControle.ToString()}");
|
||||
Console.WriteLine($"[OID] Comando nao mapeado: {funcCode.ToString()}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -178,10 +182,12 @@ namespace AgroBase.Services
|
|||
if (setPointBytes == null)
|
||||
return;
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(setPointBytes);
|
||||
if (funcCode != OidFuncCode.Heartbeat)
|
||||
{
|
||||
//Console.WriteLine($"[OID] Comando enviado para fila: {idTx.ToString("X")} {((byte)funcCode).ToString("X")} {string.Join(" ", setPointBytes.Select(x => x.ToString("X")))}");
|
||||
}
|
||||
|
||||
EnviarComando(Dispositivo, idTx, idRx, (byte)tipoControle, setPointBytes);
|
||||
EnviarComando(Dispositivo, idTx, idRx, (byte)funcCode, setPointBytes, false);
|
||||
}
|
||||
|
||||
private static void ConfigurarDriver(MovimentacaoModel Modulo)
|
||||
|
|
@ -210,6 +216,7 @@ namespace AgroBase.Services
|
|||
|
||||
ComandoControle(Mod.MovMotor._EnderecoCAN_Tx, Mod.MovMotor._EnderecoCAN_Rx, OidFuncCode.Heartbeat, novoValor);
|
||||
|
||||
Mod.MovMotor.heartBeatValue = novoValor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -304,6 +311,8 @@ namespace AgroBase.Services
|
|||
OidParametros parametro = (OidParametros)mensagem.DataRx[1];
|
||||
byte[] valorBytes = mensagem.DataRx.Skip(2).ToArray();
|
||||
|
||||
//Console.WriteLine($"[OID] Dados brutos recebidos do driver {mensagem.IdTx} - {string.Join(" ", mensagem.DataRx.Select(x => x.ToString("X")))}");
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(valorBytes);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ namespace AgroBase.Services
|
|||
private static bool VarreduraEmAndamento = false;
|
||||
|
||||
|
||||
public static bool EnviarDadosPortaSerial(SerialPort _porta, string Dados, bool DebugMode = false)
|
||||
public static bool EnviarDadosPortaSerial(SerialPort _porta, string Dados, bool DebugMode = false, int timeout = 2000)
|
||||
{
|
||||
bool ForceDebug = false;
|
||||
if (ForceDebug)
|
||||
|
|
@ -61,7 +61,7 @@ namespace AgroBase.Services
|
|||
try
|
||||
{
|
||||
// Define o tempo de espera máximo para a operação de escrita
|
||||
_porta.WriteTimeout = 2000; // 2 segundos de timeout para escrita (ajuste conforme necessário)
|
||||
_porta.WriteTimeout = timeout; // 2 segundos de timeout para escrita (ajuste conforme necessário)
|
||||
|
||||
// Verifica se há dados para enviar
|
||||
if (string.IsNullOrEmpty(Dados))
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
|
|
@ -25,7 +25,7 @@
|
|||
<meta name="viewport" content="width=device-width,
|
||||
initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<style>
|
||||
#map_0a65390b914a9d20a49b9ea06134c652 {
|
||||
#map_4450d383ac9fb1f3116e73305183afb1 {
|
||||
position: relative;
|
||||
width: 100.0%;
|
||||
height: 100.0%;
|
||||
|
|
@ -39,14 +39,14 @@
|
|||
<body>
|
||||
|
||||
|
||||
<div class="folium-map" id="map_0a65390b914a9d20a49b9ea06134c652" ></div>
|
||||
<div class="folium-map" id="map_4450d383ac9fb1f3116e73305183afb1" ></div>
|
||||
|
||||
</body>
|
||||
<script>
|
||||
|
||||
|
||||
var map_0a65390b914a9d20a49b9ea06134c652 = L.map(
|
||||
"map_0a65390b914a9d20a49b9ea06134c652",
|
||||
var map_4450d383ac9fb1f3116e73305183afb1 = L.map(
|
||||
"map_4450d383ac9fb1f3116e73305183afb1",
|
||||
{
|
||||
center: [0.0, 0.0],
|
||||
crs: L.CRS.EPSG3857,
|
||||
|
|
@ -60,13 +60,13 @@
|
|||
|
||||
|
||||
|
||||
var tile_layer_46f299708219af4df3a972d14ad0e238 = L.tileLayer(
|
||||
var tile_layer_99e7db5371d91587ccc10829a4786ab2 = 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_46f299708219af4df3a972d14ad0e238.addTo(map_0a65390b914a9d20a49b9ea06134c652);
|
||||
tile_layer_99e7db5371d91587ccc10829a4786ab2.addTo(map_4450d383ac9fb1f3116e73305183afb1);
|
||||
|
||||
</script>
|
||||
|
||||
|
|
@ -87,7 +87,7 @@
|
|||
}
|
||||
trajeto_json_add({"features": []});
|
||||
|
||||
trajeto_json.addTo(map_0a65390b914a9d20a49b9ea06134c652);
|
||||
trajeto_json.addTo(map_4450d383ac9fb1f3116e73305183afb1);
|
||||
|
||||
function adicionarGeometria(novaGeometria) {
|
||||
trajeto_json.addData(novaGeometria);
|
||||
|
|
@ -145,7 +145,7 @@
|
|||
|
||||
var marcadorDinamico = L.marker([0, 0], {
|
||||
icon: customIcon
|
||||
}).addTo(map_0a65390b914a9d20a49b9ea06134c652);
|
||||
}).addTo(map_4450d383ac9fb1f3116e73305183afb1);
|
||||
|
||||
// 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_0a65390b914a9d20a49b9ea06134c652.setView(novaPosicao, map_0a65390b914a9d20a49b9ea06134c652.getZoom());
|
||||
map_4450d383ac9fb1f3116e73305183afb1.setView(novaPosicao, map_4450d383ac9fb1f3116e73305183afb1.getZoom());
|
||||
});
|
||||
|
||||
function calcularOrientacao(P1latitude, P1longitude, P2latitude, P2longitude) {
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -482,4 +482,4 @@ C:\ZendionInc\agrobot_base\AgroBase\AgroBase\obj\Debug\AgroBase.csproj.GenerateR
|
|||
C:\ZendionInc\agrobot_base\AgroBase\AgroBase\obj\Debug\AgroBase.csproj.CoreCompileInputs.cache
|
||||
C:\ZendionInc\agrobot_base\AgroBase\AgroBase\obj\Debug\AgroBase.exe
|
||||
C:\ZendionInc\agrobot_base\AgroBase\AgroBase\obj\Debug\AgroBase.pdb
|
||||
C:\ZendionInc\agrobot_base\AgroBase\AgroBase\obj\Debug\AgroBase.csproj.CopyComplete
|
||||
C:\ZendionINC\agrobot_base\AgroBase\AgroBase\obj\Debug\AgroBase.csproj.Up2Date
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue