Add project files.
This commit is contained in:
107
Discovery/PrinterDiscoveryService.cs
Normal file
107
Discovery/PrinterDiscoveryService.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace Inspectron.Epson;
|
||||
|
||||
public class PrinterDiscoveryService
|
||||
{
|
||||
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,
|
||||
ResponseData = result.Buffer,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public class DiscoveredPrinter
|
||||
{
|
||||
public required IPAddress IPAddress { get; init; }
|
||||
public required byte[] ResponseData { get; init; }
|
||||
public DateTime DiscoveredAt { get; init; }
|
||||
|
||||
public string GetResponseDataAsHex()
|
||||
{
|
||||
return string.Join(" ", ResponseData.Select(b => $"{b:X2}"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user