519 lines
17 KiB
C#
519 lines
17 KiB
C#
using AgroBase.Models;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net.Sockets;
|
|
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 FlushBufferAsync(); // Limpa o buffer antes de enviar
|
|
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;
|
|
}
|
|
}
|
|
|
|
public async Task<byte[]> ReceiveDataAsync2(int bufferSize = 1024, int timeoutMilliseconds = 1000)
|
|
{
|
|
if (_networkStream == null || !_networkStream.CanRead)
|
|
{
|
|
Console.WriteLine("O NetworkStream não está disponível para leitura.");
|
|
return null;
|
|
}
|
|
|
|
Console.WriteLine("Iniciando teste de leitura do stream...");
|
|
|
|
try
|
|
{
|
|
var buffer = new byte[bufferSize];
|
|
var cancellationTokenSource = new CancellationTokenSource(timeoutMilliseconds);
|
|
|
|
while (!cancellationTokenSource.Token.IsCancellationRequested)
|
|
{
|
|
if (_networkStream.DataAvailable)
|
|
{
|
|
int bytesRead = await _networkStream.ReadAsync(buffer, 0, buffer.Length, cancellationTokenSource.Token);
|
|
if (bytesRead > 0)
|
|
{
|
|
// Exibe os dados lidos no console
|
|
Console.WriteLine($"Dados recebidos ({bytesRead} bytes): {BitConverter.ToString(buffer, 0, bytesRead)}");
|
|
return buffer;
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("Nenhum dado foi lido.");
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
await Task.Delay(10); // Aguarda brevemente antes de verificar novamente
|
|
}
|
|
}
|
|
|
|
Console.WriteLine("Leitura do stream finalizada ou timeout atingido.");
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
Console.WriteLine("Timeout atingido durante o teste de leitura do stream.");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Erro ao ler do stream: {ex.Message}");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
public async Task FlushBufferAsync()
|
|
{
|
|
try
|
|
{
|
|
if (_networkStream.DataAvailable) // Verifica se há dados pendentes no buffer
|
|
{
|
|
var tempBuffer = new byte[1024]; // Buffer temporário para leitura
|
|
while (_networkStream.DataAvailable)
|
|
{
|
|
await _networkStream.ReadAsync(tempBuffer, 0, tempBuffer.Length);
|
|
}
|
|
//Console.WriteLine("Buffer limpo.");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Erro ao limpar buffer: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
// 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(string _interface)
|
|
{
|
|
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where(x => x.Name == _interface))
|
|
{
|
|
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(string _interface)
|
|
{
|
|
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where(x => x.Name == _interface))
|
|
{
|
|
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(string _interface)
|
|
{
|
|
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where(x => x.Name == _interface))
|
|
{
|
|
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(string _interface)
|
|
{
|
|
foreach (NetworkInterface networkInterface in NetworkInterface.GetAllNetworkInterfaces().Where(x => x.Name == _interface))
|
|
{
|
|
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, bool response)
|
|
{
|
|
try
|
|
{
|
|
// 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);
|
|
|
|
if (response)
|
|
{
|
|
MessageBox.Show("IP dinamico definido com sucesso!", "Configuração de IP", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (response)
|
|
{
|
|
MessageBox.Show($"Erro ao definir IP dinamico: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void DefinirIpFixo(string nomeInterface, string ipAddress, string subnetMask, string gateway, bool response)
|
|
{
|
|
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.4.4 register=primary";
|
|
ExecutarComandoNetsh(comandoDns);
|
|
|
|
if (response)
|
|
{
|
|
MessageBox.Show("IP fixo definido com sucesso!", "Configuração de IP", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
if (response)
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
public static async Task ScanSubnetAsync(string subnet)
|
|
{
|
|
for (int i = 1; i <= 254; i++)
|
|
{
|
|
string ip = $"{subnet}.{i}";
|
|
bool isAlive = await PingAsync(ip);
|
|
if (isAlive)
|
|
{
|
|
Console.WriteLine($"Dispositivo ativo encontrado: {ip}");
|
|
}
|
|
}
|
|
}
|
|
|
|
public static async Task<bool> PingAsync(string ip)
|
|
{
|
|
try
|
|
{
|
|
using (Ping ping = new Ping())
|
|
{
|
|
PingReply reply = await ping.SendPingAsync(ip, 500); // 500 ms timeout
|
|
return reply.Status == IPStatus.Success;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static void ConfigurarIP(bool fixo, bool response)
|
|
{
|
|
var interfaces = ObterNomesInterfaces();
|
|
|
|
string _Interface = interfaces.FirstOrDefault(x => x.ToLower().Contains("wi-fi") && x.ToLower().Contains("ativa"));
|
|
if (!string.IsNullOrEmpty(_Interface))
|
|
{
|
|
_Interface = _Interface.Split('(')[0].Trim();
|
|
string gateway = ObterIpGateway(_Interface);
|
|
string ipAtual = ObterIpAtual(_Interface);
|
|
string ip = Variaveis.IP_Host;
|
|
string submask = ObterSubnetMaskAtual(_Interface);
|
|
|
|
if (fixo)
|
|
{
|
|
DefinirIpFixo(_Interface, ip, submask, gateway, response);
|
|
}
|
|
else
|
|
{
|
|
DefinirIpDinamico(_Interface, response);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}
|