agrobot_base/AgroBase/AgroBase/Services/EthernetService.cs

370 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
public class EthernetService
{
public readonly string _ipAddress;
private readonly int _port;
private TcpClient _client;
private NetworkStream _networkStream;
public bool IsConnected
{
get
{
try
{
// Verifica se o cliente foi inicializado e está conectado
return _client != null && _client.Client != null && _client.Client.Connected;
}
catch
{
return false;
}
}
}
public EthernetService(string ipAddress, int port)
{
_ipAddress = ipAddress;
_port = port;
}
// Método para estabelecer conexão TCP com o conversor Ethernet-RS485
public async Task<bool> ConnectAsync(int timeoutMilliseconds = 1000)
{
try
{
_client = new TcpClient();
using (var cts = new CancellationTokenSource(timeoutMilliseconds))
{
var connectTaskCompletionSource = new TaskCompletionSource<bool>();
var connectTask = _client.ConnectAsync(_ipAddress, _port).ContinueWith(t =>
{
if (t.IsCompleted)
{
connectTaskCompletionSource.TrySetResult(true);
}
else if (t.IsFaulted)
{
connectTaskCompletionSource.TrySetException(t.Exception?.InnerException ?? t.Exception);
}
else
{
connectTaskCompletionSource.TrySetResult(false);
}
}, TaskScheduler.Default);
var completedTask = await Task.WhenAny(connectTaskCompletionSource.Task, Task.Delay(timeoutMilliseconds, cts.Token));
if (completedTask == connectTaskCompletionSource.Task && await connectTaskCompletionSource.Task)
{
if (_client.Connected)
{
_networkStream = _client.GetStream();
return true;
}
}
// Timeout foi atingido; limpa a conexão
Console.WriteLine("Conexão cancelada devido ao timeout.");
_client.Dispose();
return false;
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Conexão cancelada pela operação.");
return false;
}
catch (Exception ex)
{
Console.WriteLine($"Erro ao conectar: {ex.Message}");
_client?.Close();
return false;
}
}
// Método para desconectar e liberar recursos
public void Disconnect()
{
try
{
_networkStream?.Close();
_client?.Close();
_networkStream = null;
_client = null;
}
catch (Exception ex)
{
Console.WriteLine($"Erro ao desconectar: {ex.Message}");
}
}
// Método para enviar dados ao dispositivo via Ethernet
public async Task<bool> SendDataAsync(byte[] data)
{
if (IsConnected && _networkStream.CanWrite)
{
try
{
await _networkStream.WriteAsync(data, 0, data.Length);
await _networkStream.FlushAsync();
return true;
}
catch (Exception ex)
{
Console.WriteLine($"Erro ao enviar dados: {ex.Message}");
}
}
else
{
Console.WriteLine("Não conectado ao dispositivo.");
}
return false;
}
// Método para receber dados do dispositivo via Ethernet
public async Task<byte[]> ReceiveDataAsync(int expectedLength, int timeoutMilliseconds = 1000)
{
var buffer = new byte[expectedLength];
try
{
var readTask = _networkStream.ReadAsync(buffer, 0, expectedLength); // Tarefa de leitura sem o token
// Cria uma tarefa de delay que representa o timeout
if (await Task.WhenAny(readTask, Task.Delay(timeoutMilliseconds)) == readTask)
{
// Se readTask completa antes do timeout
var bytesRead = await readTask;
Array.Resize(ref buffer, bytesRead); // Ajusta o tamanho do buffer para os bytes lidos
return buffer;
}
else
{
// Se o timeout for atingido, retorna nulo ou exibe uma mensagem
Console.WriteLine("Timeout ao receber dados via Ethernet.");
return null;
}
}
catch (Exception ex)
{
Console.WriteLine($"Erro ao receber dados: {ex.Message}");
return null;
}
}
// Método para verificar a conexão (pode ser usado para um "heartbeat")
public async Task<bool> CheckConnectionAsync()
{
if (!IsConnected)
{
Console.WriteLine("Conexão perdida. Tentando reconectar...");
return await ConnectAsync();
}
return true;
}
public bool _isReconnecting = false;
private int _reconnectAttempts = 0;
private const int MaxReconnectAttempts = 5;
private const int ReconnectInterval = 2000; // Intervalo de 2000 ms = 2 segundos
// Método para gerenciar a reconexão
public async Task<bool> ReconnectAsync()
{
if (_isReconnecting) return false; // Evita tentativas duplicadas
_isReconnecting = true;
try
{
while (_reconnectAttempts < MaxReconnectAttempts && !IsConnected)
{
Console.WriteLine($"Tentando reconectar ao IP {_ipAddress}... Tentativa {_reconnectAttempts + 1}");
bool connected = await ConnectAsync(5000);
if (connected)
{
Console.WriteLine("Reconexão bem-sucedida.");
_reconnectAttempts = 0;
return true;
}
else
{
_reconnectAttempts++;
await Task.Delay(ReconnectInterval);
}
}
if (!IsConnected)
{
Console.WriteLine("Número máximo de tentativas de reconexão atingido.");
await Task.Delay(5000);
_reconnectAttempts = 0;
}
return IsConnected;
}
finally
{
_isReconnecting = false; // Libera para novas tentativas futuras
}
}
public static List<string> ObterNomesInterfaces()
{
var listaInterfaces = new List<string>();
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var nic in interfaces)
{
string status = nic.OperationalStatus == OperationalStatus.Up ? "Ativa" : "Inativa";
listaInterfaces.Add($"{nic.Name} ({status})");
}
return listaInterfaces;
}
// Obtém o IP do gateway padrão (roteador) da rede ativa
public static string ObterIpGateway()
{
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
if (networkInterface.OperationalStatus == OperationalStatus.Up)
{
foreach (GatewayIPAddressInformation gateway in networkInterface.GetIPProperties().GatewayAddresses)
{
if (gateway.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return gateway.Address.ToString();
}
}
}
}
return null;
}
// Obtém o IP atual do PC na rede ativa
public static string ObterIpAtual()
{
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
if (networkInterface.OperationalStatus == OperationalStatus.Up)
{
foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip.Address.ToString();
}
}
}
}
return null;
}
public static string ObterSubnetMaskAtual()
{
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
if (networkInterface.OperationalStatus == OperationalStatus.Up)
{
foreach (UnicastIPAddressInformation ip in networkInterface.GetIPProperties().UnicastAddresses)
{
if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
return ip.IPv4Mask.ToString(); // Retorna a máscara de sub-rede como string
}
}
}
}
return null; // Retorna null se não encontrar uma máscara de sub-rede
}
public static string ObterTipoConfiguracaoIP()
{
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces())
{
if (networkInterface.OperationalStatus == OperationalStatus.Up)
{
var ipProperties = networkInterface.GetIPProperties();
if (ipProperties.GatewayAddresses.Count > 0) // Confirma que há um gateway configurado
{
// Verifica se o DHCP está habilitado para IPv4
if (ipProperties.GetIPv4Properties().IsDhcpEnabled)
{
return "Dinâmico (DHCP)";
}
else
{
return "IP Fixo (Estático)";
}
}
}
}
return "Nenhuma interface de rede ativa encontrada";
}
public static void DefinirIpDinamico(string interfaceName)
{
// Define o IP para DHCP
string comandoIp = $"interface ip set address \"{interfaceName}\" dhcp";
// Define o DNS para DHCP
string comandoDns = $"interface ip set dns \"{interfaceName}\" dhcp";
ExecutarComandoNetsh(comandoIp);
ExecutarComandoNetsh(comandoDns);
}
public static void DefinirIpFixo(string nomeInterface, string ipAddress, string subnetMask, string gateway)
{
try
{
// Define o IP fixo na interface de rede
string comandoIp = $"interface ip set address name=\"{nomeInterface}\" static {ipAddress} {subnetMask} {gateway}";
ExecutarComandoNetsh(comandoIp);
// Configura o DNS para automático (caso desejado)
string comandoDns = $"interface ip set dns name=\"{nomeInterface}\" source=static addr=8.8.8.8 register=primary";
ExecutarComandoNetsh(comandoDns);
MessageBox.Show("IP fixo definido com sucesso!", "Configuração de IP", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Erro ao definir IP fixo: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private static string ExecutarComandoNetsh(string comando)
{
Process process = new Process();
process.StartInfo.FileName = "netsh";
process.StartInfo.Arguments = comando;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return output;
}
}