ajustes udp
This commit is contained in:
parent
c95564d49f
commit
2b4505d98a
|
|
@ -108,6 +108,8 @@ namespace AgroBase.Forms
|
|||
|
||||
PythonService.EncerrarProcessos();
|
||||
|
||||
Variaveis.StopUdpChannel();
|
||||
|
||||
foreach (var Disp in Variaveis.DispositivosConectados)
|
||||
{
|
||||
Disp.EnviarProtocolosConfiguracao(false);
|
||||
|
|
|
|||
|
|
@ -1709,7 +1709,8 @@ namespace AgroBase.Models
|
|||
if (topico != null && !string.IsNullOrEmpty(msg))
|
||||
{
|
||||
await Variaveis.MqttServiceBase.PublishAsync(topico, msg);
|
||||
Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.UltimoEnvioLog = DateTime.Now;
|
||||
if (Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura != null)
|
||||
Variaveis.OperacaoEmAndamento.Parametros.DadosLeitura.UltimoEnvioLog = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -199,24 +199,28 @@ namespace AgroBase.Models
|
|||
private static AsyncTaskTimerModel _tmrUdpWatchdog;
|
||||
|
||||
private const int FAILSAFE_MS = 400;
|
||||
private const int UDP_RESTART_MS = 2000;
|
||||
private const int UDP_RESTART_MS = 5000;
|
||||
|
||||
|
||||
public static void IniciarUDP()
|
||||
{
|
||||
StartUdpChannel();
|
||||
|
||||
_tmrFailSafe?.Dispose();
|
||||
_tmrFailSafe = new AsyncTaskTimerModel("tmrFailSafe", tmrFailSafe_Tick, 100);
|
||||
_tmrFailSafe.Start();
|
||||
|
||||
_tmrUdpWatchdog?.Dispose();
|
||||
_tmrUdpWatchdog = new AsyncTaskTimerModel("tmrUdpWatchdog", tmrUdpWatchdog_Tick, 250);
|
||||
_tmrUdpWatchdog.Start();
|
||||
}
|
||||
|
||||
private static void StartUdpChannel()
|
||||
{
|
||||
StopUdpChannel();
|
||||
//StopUdpChannel();
|
||||
|
||||
UdpChannel?.Stop();
|
||||
UdpChannel?.Dispose();
|
||||
UdpChannel = new UdpReliableChannel();
|
||||
UdpChannel.Start(VariaveisPortas.Ethernet_UDP_RX);
|
||||
|
||||
|
|
@ -231,6 +235,9 @@ namespace AgroBase.Models
|
|||
{
|
||||
try
|
||||
{
|
||||
_tmrFailSafe?.Dispose();
|
||||
_tmrUdpWatchdog?.Dispose();
|
||||
|
||||
UdpChannel?.Stop();
|
||||
UdpChannel?.Dispose();
|
||||
}
|
||||
|
|
@ -249,6 +256,8 @@ namespace AgroBase.Models
|
|||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("[UDP] Commnad");
|
||||
|
||||
// Só controle entra daqui
|
||||
if (type != UdpReliableChannel.TYPE_COMMAND) return;
|
||||
|
||||
|
|
@ -375,6 +384,7 @@ namespace AgroBase.Models
|
|||
}
|
||||
catch { }
|
||||
|
||||
Console.WriteLine("[UDP] Tentando reconectar...");
|
||||
// Reinicia o canal
|
||||
StartUdpChannel();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
using AgroBase.Models;
|
||||
using AgroMonitor;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
|
@ -10,7 +8,7 @@ using System.Threading.Tasks;
|
|||
public sealed class UdpReliableChannel : IDisposable
|
||||
{
|
||||
public const ushort MAGIC = 0xA711;
|
||||
public const byte TYPE_COMMAND = 0x7F;
|
||||
public const byte TYPE_COMMAND = 0x01;
|
||||
public const byte TYPE_HEARTBEAT = 0x7F;
|
||||
|
||||
public int AckTimeoutMs { get; set; } = 120;
|
||||
|
|
@ -95,7 +93,7 @@ public sealed class UdpReliableChannel : IDisposable
|
|||
try
|
||||
{
|
||||
if (_rxThread != null && _rxThread.IsAlive)
|
||||
_rxThread.Join(500);
|
||||
_rxThread.Join(2000); // ou sem timeout se preferir travar até fechar
|
||||
}
|
||||
catch { }
|
||||
|
||||
|
|
@ -272,62 +270,75 @@ public sealed class UdpReliableChannel : IDisposable
|
|||
{
|
||||
var from = new IPEndPoint(IPAddress.Any, 0);
|
||||
|
||||
while (_running)
|
||||
while (true)
|
||||
{
|
||||
byte[] data = null;
|
||||
UdpClient udp;
|
||||
lock (_sockLock) udp = _udp;
|
||||
|
||||
if (!_running || udp == null) break;
|
||||
|
||||
try
|
||||
{
|
||||
data = _udp.Receive(ref from); // bloqueia
|
||||
if (udp.Available == 0)
|
||||
{
|
||||
Thread.Sleep(30);
|
||||
continue;
|
||||
}
|
||||
|
||||
var data = udp.Receive(ref from);
|
||||
if (data == null || data.Length < 12) continue;
|
||||
|
||||
ushort magic = (ushort)((data[0] << 8) | data[1]);
|
||||
if (magic != MAGIC) continue;
|
||||
|
||||
byte type = data[2];
|
||||
byte flags = data[3];
|
||||
uint seq = ReadU32BE(data, 4);
|
||||
|
||||
int payloadLen = data.Length - 12;
|
||||
byte[] payload = new byte[payloadLen];
|
||||
if (payloadLen > 0)
|
||||
Buffer.BlockCopy(data, 12, payload, 0, payloadLen);
|
||||
|
||||
// ACK
|
||||
if (type == 0xFF)
|
||||
{
|
||||
if (payloadLen >= 4)
|
||||
{
|
||||
uint ackSeq = ReadU32BE(payload, 0);
|
||||
var h = OnAck;
|
||||
if (h != null) h(ackSeq);
|
||||
|
||||
TaskCompletionSource<bool> tcs;
|
||||
if (_pendingAck.TryGetValue(ackSeq, out tcs))
|
||||
tcs.TrySetResult(true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// newest wins
|
||||
if (seq <= _lastSeqRx) continue;
|
||||
_lastSeqRx = seq;
|
||||
|
||||
var handler = OnPacket;
|
||||
if (handler != null)
|
||||
handler(type, payload, from);
|
||||
|
||||
// responde ACK se pedido
|
||||
if ((flags & 1) != 0)
|
||||
{
|
||||
try { SendAckAsync(from, seq); }
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
break; // Stop()
|
||||
}
|
||||
catch (SocketException)
|
||||
{
|
||||
if (!_running) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data == null || data.Length < 12) continue;
|
||||
|
||||
ushort magic = (ushort)((data[0] << 8) | data[1]);
|
||||
if (magic != MAGIC) continue;
|
||||
|
||||
byte type = data[2];
|
||||
byte flags = data[3];
|
||||
uint seq = ReadU32BE(data, 4);
|
||||
|
||||
int payloadLen = data.Length - 12;
|
||||
byte[] payload = new byte[payloadLen];
|
||||
if (payloadLen > 0)
|
||||
Buffer.BlockCopy(data, 12, payload, 0, payloadLen);
|
||||
|
||||
// ACK
|
||||
if (type == 0xFF)
|
||||
{
|
||||
if (payloadLen >= 4)
|
||||
{
|
||||
uint ackSeq = ReadU32BE(payload, 0);
|
||||
var h = OnAck;
|
||||
if (h != null) h(ackSeq);
|
||||
|
||||
TaskCompletionSource<bool> tcs;
|
||||
if (_pendingAck.TryGetValue(ackSeq, out tcs))
|
||||
tcs.TrySetResult(true);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// newest wins
|
||||
if (seq <= _lastSeqRx) continue;
|
||||
_lastSeqRx = seq;
|
||||
|
||||
var handler = OnPacket;
|
||||
if (handler != null)
|
||||
handler(type, payload, from);
|
||||
|
||||
// responde ACK se pedido
|
||||
if ((flags & 1) != 0)
|
||||
{
|
||||
try { SendAckAsync(from, seq); }
|
||||
catch { }
|
||||
// erro real (raro). pode logar se quiser
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue