a
This commit is contained in:
248
ScanBox/TcpReaderSearcher.cs
Normal file
248
ScanBox/TcpReaderSearcher.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ScaBox30.Controller
|
||||
{
|
||||
/// <summary>
|
||||
/// Reemplazo del ReaderSearcher del SDK
|
||||
/// Busca sensores SR-X300W en la red mediante escaneo TCP
|
||||
/// </summary>
|
||||
public class TcpReaderSearcher : IDisposable
|
||||
{
|
||||
private bool isSearching = false;
|
||||
private List<NicSearchResult> nicList = new List<NicSearchResult>();
|
||||
|
||||
public bool IsSearching => isSearching;
|
||||
public NicSearchResult SelectedNicSearchResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Lista las interfaces de red disponibles en el equipo
|
||||
/// Compatible con: m_nicList = m_searcher.ListUpNic()
|
||||
/// </summary>
|
||||
public List<NicSearchResult> ListUpNic()
|
||||
{
|
||||
nicList.Clear();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
|
||||
{
|
||||
// Filtrar solo interfaces activas y Ethernet/Wi-Fi
|
||||
if (ni.OperationalStatus == OperationalStatus.Up &&
|
||||
(ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet ||
|
||||
ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211))
|
||||
{
|
||||
IPInterfaceProperties ipProps = ni.GetIPProperties();
|
||||
|
||||
foreach (UnicastIPAddressInformation ip in ipProps.UnicastAddresses)
|
||||
{
|
||||
// Solo IPv4
|
||||
if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
var nicResult = new NicSearchResult
|
||||
{
|
||||
NicIpAddr = ip.Address.ToString(),
|
||||
NicName = ni.Name,
|
||||
NicDescription = ni.Description
|
||||
};
|
||||
|
||||
nicList.Add(nicResult);
|
||||
Console.WriteLine($"[NIC] Encontrada: {nicResult.NicIpAddr} ({nicResult.NicName})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[NIC] Error listando interfaces: {ex.Message}");
|
||||
}
|
||||
|
||||
return nicList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inicia búsqueda de sensores en la red
|
||||
/// Compatible con: m_searcher.Start((res) => { ... })
|
||||
/// </summary>
|
||||
public void Start(Action<SearchResult> onSensorFound)
|
||||
{
|
||||
if (isSearching)
|
||||
{
|
||||
Console.WriteLine("[SEARCH] Ya hay una búsqueda en curso");
|
||||
return;
|
||||
}
|
||||
|
||||
if (SelectedNicSearchResult == null)
|
||||
{
|
||||
Console.WriteLine("[SEARCH] ERROR: No se ha seleccionado una NIC");
|
||||
return;
|
||||
}
|
||||
|
||||
isSearching = true;
|
||||
Console.WriteLine($"[SEARCH] Iniciando búsqueda desde {SelectedNicSearchResult.NicIpAddr}...");
|
||||
|
||||
// Ejecutar búsqueda en background
|
||||
Task.Run(() => SearchSensorsInNetwork(onSensorFound));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Busca sensores SR-X300W en la red local
|
||||
/// Prueba conectar al puerto 9004 (puerto de comandos SR-X300W)
|
||||
/// </summary>
|
||||
private async void SearchSensorsInNetwork(Action<SearchResult> onSensorFound)
|
||||
{
|
||||
try
|
||||
{
|
||||
string localIP = SelectedNicSearchResult.NicIpAddr;
|
||||
string subnet = GetSubnet(localIP);
|
||||
int port = 9004; // Puerto TCP comandos SR-X300W
|
||||
|
||||
Console.WriteLine($"[SEARCH] Escaneando subnet {subnet}.x en puerto {port}");
|
||||
|
||||
// Escanear rango de IPs (ejemplo: 192.168.100.1 - 192.168.100.254)
|
||||
List<Task> scanTasks = new List<Task>();
|
||||
|
||||
for (int i = 1; i <= 254; i++)
|
||||
{
|
||||
string testIP = $"{subnet}.{i}";
|
||||
|
||||
// No probar la IP local
|
||||
if (testIP == localIP)
|
||||
continue;
|
||||
|
||||
// Lanzar escaneo asíncrono
|
||||
scanTasks.Add(Task.Run(async () =>
|
||||
{
|
||||
if (await TryConnectToSensor(testIP, port, 500)) // 500ms timeout
|
||||
{
|
||||
Console.WriteLine($"[SEARCH] ✓ Sensor encontrado en {testIP}:{port}");
|
||||
|
||||
var result = new SearchResult
|
||||
{
|
||||
IpAddress = testIP,
|
||||
Port = port,
|
||||
IsResponding = true
|
||||
};
|
||||
|
||||
onSensorFound?.Invoke(result);
|
||||
}
|
||||
}));
|
||||
|
||||
// Limitar concurrencia para no saturar la red
|
||||
if (scanTasks.Count >= 20)
|
||||
{
|
||||
await Task.WhenAll(scanTasks);
|
||||
scanTasks.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Esperar tareas restantes
|
||||
await Task.WhenAll(scanTasks);
|
||||
|
||||
Console.WriteLine("[SEARCH] Búsqueda completada");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[SEARCH] Error en búsqueda: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
isSearching = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intenta conectar a una IP:Puerto con timeout
|
||||
/// </summary>
|
||||
private async Task<bool> TryConnectToSensor(string ip, int port, int timeoutMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var client = new TcpClient())
|
||||
{
|
||||
var connectTask = client.ConnectAsync(ip, port);
|
||||
var timeoutTask = Task.Delay(timeoutMs);
|
||||
|
||||
if (await Task.WhenAny(connectTask, timeoutTask) == connectTask)
|
||||
{
|
||||
// Conexión exitosa
|
||||
if (client.Connected)
|
||||
{
|
||||
// Verificar que responda a un comando básico
|
||||
using (var stream = client.GetStream())
|
||||
{
|
||||
stream.ReadTimeout = 500;
|
||||
byte[] testCmd = System.Text.Encoding.ASCII.GetBytes("NUM\r");
|
||||
await stream.WriteAsync(testCmd, 0, testCmd.Length);
|
||||
|
||||
byte[] buffer = new byte[256];
|
||||
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
|
||||
|
||||
return bytesRead > 0; // Si responde, es un sensor válido
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Silenciosamente ignorar fallos (IP no responde)
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene la subred de una IP (ejemplo: 192.168.100.1 -> 192.168.100)
|
||||
/// </summary>
|
||||
private string GetSubnet(string ip)
|
||||
{
|
||||
string[] parts = ip.Split('.');
|
||||
if (parts.Length == 4)
|
||||
{
|
||||
return $"{parts[0]}.{parts[1]}.{parts[2]}";
|
||||
}
|
||||
return "192.168.100"; // Fallback
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detiene la búsqueda
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
isSearching = false;
|
||||
Console.WriteLine("[SEARCH] Búsqueda detenida");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resultado de búsqueda de NIC (compatible con SDK)
|
||||
/// </summary>
|
||||
public class NicSearchResult
|
||||
{
|
||||
public string NicIpAddr { get; set; }
|
||||
public string NicName { get; set; }
|
||||
public string NicDescription { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resultado de búsqueda de sensor
|
||||
/// </summary>
|
||||
public class SearchResult
|
||||
{
|
||||
public string IpAddress { get; set; }
|
||||
public int Port { get; set; }
|
||||
public bool IsResponding { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user