ajustes udp
This commit is contained in:
parent
c95564d49f
commit
2b4505d98a
|
|
@ -108,6 +108,8 @@ namespace AgroBase.Forms
|
||||||
|
|
||||||
PythonService.EncerrarProcessos();
|
PythonService.EncerrarProcessos();
|
||||||
|
|
||||||
|
Variaveis.StopUdpChannel();
|
||||||
|
|
||||||
foreach (var Disp in Variaveis.DispositivosConectados)
|
foreach (var Disp in Variaveis.DispositivosConectados)
|
||||||
{
|
{
|
||||||
Disp.EnviarProtocolosConfiguracao(false);
|
Disp.EnviarProtocolosConfiguracao(false);
|
||||||
|
|
|
||||||
|
|
@ -1709,7 +1709,8 @@ namespace AgroBase.Models
|
||||||
if (topico != null && !string.IsNullOrEmpty(msg))
|
if (topico != null && !string.IsNullOrEmpty(msg))
|
||||||
{
|
{
|
||||||
await Variaveis.MqttServiceBase.PublishAsync(topico, 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 static AsyncTaskTimerModel _tmrUdpWatchdog;
|
||||||
|
|
||||||
private const int FAILSAFE_MS = 400;
|
private const int FAILSAFE_MS = 400;
|
||||||
private const int UDP_RESTART_MS = 2000;
|
private const int UDP_RESTART_MS = 5000;
|
||||||
|
|
||||||
|
|
||||||
public static void IniciarUDP()
|
public static void IniciarUDP()
|
||||||
{
|
{
|
||||||
StartUdpChannel();
|
StartUdpChannel();
|
||||||
|
|
||||||
|
_tmrFailSafe?.Dispose();
|
||||||
_tmrFailSafe = new AsyncTaskTimerModel("tmrFailSafe", tmrFailSafe_Tick, 100);
|
_tmrFailSafe = new AsyncTaskTimerModel("tmrFailSafe", tmrFailSafe_Tick, 100);
|
||||||
_tmrFailSafe.Start();
|
_tmrFailSafe.Start();
|
||||||
|
|
||||||
|
_tmrUdpWatchdog?.Dispose();
|
||||||
_tmrUdpWatchdog = new AsyncTaskTimerModel("tmrUdpWatchdog", tmrUdpWatchdog_Tick, 250);
|
_tmrUdpWatchdog = new AsyncTaskTimerModel("tmrUdpWatchdog", tmrUdpWatchdog_Tick, 250);
|
||||||
_tmrUdpWatchdog.Start();
|
_tmrUdpWatchdog.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void StartUdpChannel()
|
private static void StartUdpChannel()
|
||||||
{
|
{
|
||||||
StopUdpChannel();
|
//StopUdpChannel();
|
||||||
|
|
||||||
|
UdpChannel?.Stop();
|
||||||
|
UdpChannel?.Dispose();
|
||||||
UdpChannel = new UdpReliableChannel();
|
UdpChannel = new UdpReliableChannel();
|
||||||
UdpChannel.Start(VariaveisPortas.Ethernet_UDP_RX);
|
UdpChannel.Start(VariaveisPortas.Ethernet_UDP_RX);
|
||||||
|
|
||||||
|
|
@ -231,6 +235,9 @@ namespace AgroBase.Models
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_tmrFailSafe?.Dispose();
|
||||||
|
_tmrUdpWatchdog?.Dispose();
|
||||||
|
|
||||||
UdpChannel?.Stop();
|
UdpChannel?.Stop();
|
||||||
UdpChannel?.Dispose();
|
UdpChannel?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
@ -249,6 +256,8 @@ namespace AgroBase.Models
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("[UDP] Commnad");
|
||||||
|
|
||||||
// Só controle entra daqui
|
// Só controle entra daqui
|
||||||
if (type != UdpReliableChannel.TYPE_COMMAND) return;
|
if (type != UdpReliableChannel.TYPE_COMMAND) return;
|
||||||
|
|
||||||
|
|
@ -375,6 +384,7 @@ namespace AgroBase.Models
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
|
Console.WriteLine("[UDP] Tentando reconectar...");
|
||||||
// Reinicia o canal
|
// Reinicia o canal
|
||||||
StartUdpChannel();
|
StartUdpChannel();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
using AgroBase.Models;
|
using System;
|
||||||
using AgroMonitor;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
@ -10,7 +8,7 @@ using System.Threading.Tasks;
|
||||||
public sealed class UdpReliableChannel : IDisposable
|
public sealed class UdpReliableChannel : IDisposable
|
||||||
{
|
{
|
||||||
public const ushort MAGIC = 0xA711;
|
public const ushort MAGIC = 0xA711;
|
||||||
public const byte TYPE_COMMAND = 0x7F;
|
public const byte TYPE_COMMAND = 0x01;
|
||||||
public const byte TYPE_HEARTBEAT = 0x7F;
|
public const byte TYPE_HEARTBEAT = 0x7F;
|
||||||
|
|
||||||
public int AckTimeoutMs { get; set; } = 120;
|
public int AckTimeoutMs { get; set; } = 120;
|
||||||
|
|
@ -95,7 +93,7 @@ public sealed class UdpReliableChannel : IDisposable
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_rxThread != null && _rxThread.IsAlive)
|
if (_rxThread != null && _rxThread.IsAlive)
|
||||||
_rxThread.Join(500);
|
_rxThread.Join(2000); // ou sem timeout se preferir travar até fechar
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
|
|
@ -272,62 +270,75 @@ public sealed class UdpReliableChannel : IDisposable
|
||||||
{
|
{
|
||||||
var from = new IPEndPoint(IPAddress.Any, 0);
|
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
|
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;
|
if (!_running) break;
|
||||||
continue;
|
// erro real (raro). pode logar se quiser
|
||||||
}
|
|
||||||
|
|
||||||
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 { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue