Add project files.
This commit is contained in:
14
Discovery/Discovery.csproj
Normal file
14
Discovery/Discovery.csproj
Normal file
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Inspectron.Epson\Inspectron.Epson.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
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}"));
|
||||
}
|
||||
}
|
||||
18
Discovery/Program.cs
Normal file
18
Discovery/Program.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Inspectron.Epson;
|
||||
|
||||
Console.WriteLine("Listening for printer responses...\n");
|
||||
|
||||
var discoveryService = new PrinterDiscoveryService();
|
||||
|
||||
var printers = await discoveryService.DiscoverPrintersAsync(
|
||||
timeout: TimeSpan.FromSeconds(5),
|
||||
onPrinterDiscovered: printer =>
|
||||
{
|
||||
Console.WriteLine($"Received {printer.ResponseData.Length} bytes from {printer.IPAddress}");
|
||||
Console.WriteLine(printer.GetResponseDataAsHex());
|
||||
Console.WriteLine();
|
||||
});
|
||||
|
||||
Console.WriteLine($"\nDiscovery complete. Found {printers.Count} printer(s).");
|
||||
|
||||
|
||||
68
Discovery/discovery.c
Normal file
68
Discovery/discovery.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <stdio.h>
|
||||
#include <winsock.h>
|
||||
|
||||
#define MAXBUF 512
|
||||
char buf[MAXBUF];
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
WSADATA data;
|
||||
SOCKET sock;
|
||||
struct sockaddr_in addr;
|
||||
int i, len, fromlen;
|
||||
|
||||
if (argc != 2) {
|
||||
printf("usage: wudp <IP address>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialize windows socket */
|
||||
WSAStartup(0x0101, &data);
|
||||
|
||||
/* Create socket */
|
||||
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
|
||||
fprintf(stderr, "Error socket(): %d\n", WSAGetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialize the parameter */
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(3289);
|
||||
addr.sin_addr.s_addr = inet_addr(argv[1]);
|
||||
|
||||
/* make a packet (PRINTER STATUS) */
|
||||
buf[0] = 'E';
|
||||
buf[1] = 'P';
|
||||
buf[2] = 'S';
|
||||
buf[3] = 'O';
|
||||
buf[4] = 'N';
|
||||
buf[5] = 'Q'; // PacketType(Q)
|
||||
buf[6] = 0x03; // DeviceType(3)
|
||||
buf[7] = 0x00; // DeviceNumber(0)
|
||||
buf[8] = 0x00; // Function(0010h)
|
||||
buf[9] = 0x10;
|
||||
|
||||
buf[10] = 0x00; // Result
|
||||
buf[11] = 0x00;
|
||||
buf[12] = 0x00; // Parameter length
|
||||
buf[13] = 0x00;
|
||||
|
||||
/* send a packet */
|
||||
i = sendto(sock, buf, 14, 0, (struct sockaddr*)&addr, sizeof(addr));
|
||||
|
||||
/* receive packet */
|
||||
fromlen = sizeof(addr);
|
||||
len = recvfrom(sock, buf, MAXBUF, 0, (struct sockaddr*)&addr, &fromlen);
|
||||
|
||||
/* print receive packet */
|
||||
if (len) {
|
||||
if ((buf[10] == 0x00) && (buf[11] == 0x00))
|
||||
for (i = 0; i < len; i++)
|
||||
printf("%3d:%02Xh\n", i, buf[i] & 0xff);
|
||||
}
|
||||
|
||||
/* close socket */
|
||||
closesocket(sock);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user