97 lines
3.2 KiB
C#
97 lines
3.2 KiB
C#
using System.Net;
|
|
using System.Net.Sockets;
|
|
|
|
namespace Inspectron.Epson;
|
|
|
|
public class DiscoveryService : IDiscoveryService
|
|
{
|
|
private const int DiscoveryPort = 3289;
|
|
private const string DiscoveryMessage = "EPSONQ";
|
|
private const int MessageLength = 14;
|
|
|
|
/// <summary>
|
|
/// Discovers Epson printers on the local network using UDP broadcast
|
|
/// </summary>
|
|
/// <param name="timeout">How long to wait for responses (default: 5 seconds)</param>
|
|
/// <param name="onPrinterDiscovered">Optional callback invoked when a printer is discovered</param>
|
|
/// <returns>List of discovered printer information</returns>
|
|
public async Task<List<DiscoveredPrinter>> DiscoverPrintersAsync(
|
|
TimeSpan? timeout = null,
|
|
Action<DiscoveredPrinter>? onPrinterDiscovered = null)
|
|
{
|
|
timeout ??= TimeSpan.FromSeconds(5);
|
|
|
|
using var udpClient = new UdpClient();
|
|
udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, 0));
|
|
|
|
// Send discovery broadcast message
|
|
var msg = BuildDiscoveryMessage();
|
|
var broadcastEndpoint = new IPEndPoint(IPAddress.Broadcast, DiscoveryPort);
|
|
await udpClient.SendAsync(msg, msg.Length, broadcastEndpoint);
|
|
|
|
// Receive responses
|
|
var discoveredPrinters = new List<DiscoveredPrinter>();
|
|
var endTime = DateTime.UtcNow.Add(timeout.Value);
|
|
|
|
while (DateTime.UtcNow < endTime)
|
|
{
|
|
try
|
|
{
|
|
var remainingTime = endTime - DateTime.UtcNow;
|
|
if (remainingTime <= TimeSpan.Zero)
|
|
break;
|
|
|
|
var receiveTask = udpClient.ReceiveAsync();
|
|
var timeoutTask = Task.Delay(remainingTime);
|
|
var completedTask = await Task.WhenAny(receiveTask, timeoutTask);
|
|
|
|
if (completedTask == receiveTask)
|
|
{
|
|
var result = await receiveTask;
|
|
|
|
// Check if we've already discovered this printer
|
|
if (!discoveredPrinters.Any(p => p.IPAddress.Equals(result.RemoteEndPoint.Address)))
|
|
{
|
|
var printer = new DiscoveredPrinter
|
|
{
|
|
IPAddress = result.RemoteEndPoint.Address.ToString(),
|
|
DiscoveredAt = DateTime.UtcNow
|
|
};
|
|
|
|
discoveredPrinters.Add(printer);
|
|
onPrinterDiscovered?.Invoke(printer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break; // Timeout reached
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// Ignore errors and continue waiting for other responses
|
|
break;
|
|
}
|
|
}
|
|
|
|
return discoveredPrinters;
|
|
}
|
|
|
|
private static byte[] BuildDiscoveryMessage()
|
|
{
|
|
// msg = b'EPSONQ' + bytes([0x00] * 8)
|
|
var msg = new byte[MessageLength];
|
|
Array.Copy(System.Text.Encoding.ASCII.GetBytes(DiscoveryMessage), msg, 6);
|
|
msg[6] = 3;
|
|
for (int i = 7; i < msg.Length; i++)
|
|
{
|
|
msg[i] = 0x00;
|
|
}
|
|
|
|
msg[10] = 0x10;
|
|
return msg;
|
|
}
|
|
}
|
|
|
|
|