diff --git a/ConfigurationPannel/Pages/Configure.cshtml.cs b/ConfigurationPannel/Pages/Configure.cshtml.cs index 7e8eaae..57997c5 100644 --- a/ConfigurationPannel/Pages/Configure.cshtml.cs +++ b/ConfigurationPannel/Pages/Configure.cshtml.cs @@ -18,7 +18,7 @@ public class ConfigureModel : PageModel private readonly PrintServerHostedService _printServerService; private readonly LogoService _logoService; private readonly IWebHostEnvironment _env; - private readonly ENPCDiscoveryService _discoveryService; + private readonly DiscoveryService _discoveryService; private readonly ILogger _logger; public ConfigureModel( @@ -32,7 +32,7 @@ public class ConfigureModel : PageModel _printServerService = printServerService; _logoService = logoService; _env = env; - _discoveryService = new ENPCDiscoveryService(); + _discoveryService = new DiscoveryService(); _logger = logger; } diff --git a/EpsonPrintService/ConsoleDiscoveredPrintersReceiver.cs b/EpsonPrintService/ConsoleDiscoveredPrintersReceiver.cs new file mode 100644 index 0000000..3ca9545 --- /dev/null +++ b/EpsonPrintService/ConsoleDiscoveredPrintersReceiver.cs @@ -0,0 +1,26 @@ +using Inspectron.Epson; + +namespace EpsonPrintService; + +/// +/// Simple console implementation that logs discovered printers to the console +/// +public class ConsoleDiscoveredPrintersReceiver : IDiscoveredPrintersReceiver +{ + public Task OnPrintersDiscoveredAsync(IReadOnlyList printers) + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Discovered printers changed. Found {printers.Count} printer(s):"); + + foreach (var printer in printers) + { + Console.WriteLine($" - {printer.IPAddress}"); + } + + if (printers.Count == 0) + { + Console.WriteLine(" (no printers found)"); + } + + return Task.CompletedTask; + } +} diff --git a/EpsonPrintService/IDiscoveredPrintersReceiver.cs b/EpsonPrintService/IDiscoveredPrintersReceiver.cs new file mode 100644 index 0000000..5dbfbae --- /dev/null +++ b/EpsonPrintService/IDiscoveredPrintersReceiver.cs @@ -0,0 +1,15 @@ +using Inspectron.Epson; + +namespace EpsonPrintService; + +/// +/// Interface for receiving discovered printer updates +/// +public interface IDiscoveredPrintersReceiver +{ + /// + /// Called when the list of discovered printers has changed + /// + /// The current list of discovered printers + Task OnPrintersDiscoveredAsync(IReadOnlyList printers); +} diff --git a/EpsonPrintService/IPrintJobSource.cs b/EpsonPrintService/IPrintJobSource.cs deleted file mode 100644 index c73ef52..0000000 --- a/EpsonPrintService/IPrintJobSource.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Threading.Channels; - -namespace EpsonPrintService; - -public interface IPrintJobSource -{ - Task GetNextJobAsync(CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs b/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs new file mode 100644 index 0000000..9ba362d --- /dev/null +++ b/EpsonPrintService/PrinterDiscoveryBackgroundTask.cs @@ -0,0 +1,94 @@ +using Inspectron.Epson; +using Microsoft.Extensions.Logging; + +namespace EpsonPrintService; + +/// +/// Background task that periodically discovers printers and notifies receivers when changes occur +/// +public class PrinterDiscoveryBackgroundTask +{ + private readonly IDiscoveryService _discoveryService; + private readonly IDiscoveredPrintersReceiver _receiver; + private readonly ILogger _logger; + private readonly TimeSpan _interval; + private readonly TimeSpan _discoveryTimeout; + + private HashSet _lastDiscoveredPrinterIps = new(); + private List _lastDiscoveredPrinters = new(); + + public PrinterDiscoveryBackgroundTask( + IDiscoveryService discoveryService, + IDiscoveredPrintersReceiver receiver, + ILogger logger, + TimeSpan? interval = null, + TimeSpan? discoveryTimeout = null) + { + _discoveryService = discoveryService; + _receiver = receiver; + _logger = logger; + _interval = interval ?? TimeSpan.FromSeconds(30); + _discoveryTimeout = discoveryTimeout ?? TimeSpan.FromSeconds(3); + } + + /// + /// Starts the background discovery task + /// + /// Token to cancel the background task + public async Task StartAsync(CancellationToken cancellationToken) + { + _logger.LogInformation("Starting printer discovery background task (interval: {Interval}s)", _interval.TotalSeconds); + + // Run immediately on start + await DiscoverAndNotifyAsync(); + + // Then run periodically + while (!cancellationToken.IsCancellationRequested) + { + try + { + await Task.Delay(_interval, cancellationToken); + await DiscoverAndNotifyAsync(); + } + catch (TaskCanceledException) + { + break; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error during printer discovery"); + } + } + + _logger.LogInformation("Printer discovery background task stopped"); + } + + private async Task DiscoverAndNotifyAsync() + { + try + { + var printers = await _discoveryService.DiscoverPrintersAsync(_discoveryTimeout); + var currentIps = printers.Select(p => p.IPAddress).ToHashSet(); + + if (HasConfigurationChanged(currentIps)) + { + _logger.LogInformation("Discovered printer configuration changed: {Count} printer(s)", printers.Count); + _lastDiscoveredPrinterIps = currentIps; + _lastDiscoveredPrinters = printers; + await _receiver.OnPrintersDiscoveredAsync(printers.AsReadOnly()); + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to discover printers"); + } + } + + private bool HasConfigurationChanged(HashSet currentIps) + { + if (currentIps.Count != _lastDiscoveredPrinterIps.Count) + return true; + + return !currentIps.SetEquals(_lastDiscoveredPrinterIps); + } +} diff --git a/EpsonPrintService/Program.cs b/EpsonPrintService/Program.cs index 4d9999b..562a9c9 100644 --- a/EpsonPrintService/Program.cs +++ b/EpsonPrintService/Program.cs @@ -11,17 +11,17 @@ using Inspectron.Epson.PrintServer.JobSources; using Inspectron.Epson.PrintServer.PrinterAssinment; using Inspectron.Epson.PrintServer.Printers; using Inspectron.Epson.PrintServer.PrintServices; +using EpsonPrintService; StandardKernel kernel = new StandardKernel(); -//var config = new EpsonPrintServiceConfiguration() -//{ -// GroupId = "67e534f8e86e816689323023", -// RestaurantId = "63e37295bd6f26dbd36164c0" -//}; -//File.WriteAllText("config.json",JsonSerializer.Serialize(config,new JsonSerializerOptions(){WriteIndented = true})); + var config = JsonSerializer.Deserialize( File.ReadAllText("config.json")); + +kernel.Bind().To().InSingletonScope(); + + kernel.Bind().ToConstant(config); kernel.Bind().To().InSingletonScope(); @@ -38,8 +38,12 @@ kernel.Bind().ToConstant(config); kernel.Bind().To().InSingletonScope(); kernel.Bind().To(); kernel.Bind().ToSelf().InSingletonScope(); +kernel.Bind().To().InSingletonScope(); +kernel.Bind().ToSelf().InSingletonScope(); + var printLoop = kernel.Get(); var printServer = kernel.Get(); +var discoveryTask = kernel.Get(); printServer.RegisterPrinter("127.0.0.1"); @@ -55,6 +59,9 @@ Console.CancelKeyPress += (sender, e) => cts.Cancel(); }; +// Start the printer discovery background task +_ = discoveryTask.StartAsync(cts.Token); + try { await Task.Delay(Timeout.Infinite, cts.Token); diff --git a/EpsonTest/Program.cs b/EpsonTest/Program.cs index 9742e06..83585f5 100644 --- a/EpsonTest/Program.cs +++ b/EpsonTest/Program.cs @@ -42,18 +42,18 @@ using System.Xml.Linq; -var printer = new EpsonPrinter(); -await printer.ConnectAsync("127.0.0.1",8888); -for (int i = 0; i < 20; i++) -{ - await printer.PrintTextAsync("Hello\n"); -} +//var printer = new EpsonPrinter(); +//await printer.ConnectAsync("127.0.0.1",8888); +//for (int i = 0; i < 20; i++) +//{ +// await printer.PrintTextAsync("Hello\n"); +//} -await printer.FeedLinesAsync(5); -await printer.CutAsync(); +//await printer.FeedLinesAsync(5); +//await printer.CutAsync(); -var status = await printer.GetPrinterStatusAsync(); -Console.ReadLine(); +//var status = await printer.GetPrinterStatusAsync(); +//Console.ReadLine(); //var receipt = new Receipt @@ -230,21 +230,24 @@ Console.ReadLine(); //await Task.Delay(200); //KitchenReceiptPrinter krp = new KitchenReceiptPrinter(33); -//var receipt = new KitchenReceipt( -// Location: "Warme Küche", -// Date: "23-Okt-25 12:18 Nr.:13201B166", -// Owner: "Mariano Amato\n32 (VK Restaurant)", -// Tisch: "22", -// items: new List -// { -// new KitchenGang("1. Gang"), -// new KitchenProduct(1, "Avocado Sashimi"), -// new KitchenProduct(1, "Baby Spinach Salad with Truffl"), -// new KitchenGang("2. Gang"), -// new KitchenProduct(1, "Beef Tataki"), -// new KitchenProduct(1, "Salmon Taco") -// } -//); +var receipt = new KitchenReceipt( + Location: "Warme Küche", + Date: "23-Okt-25 12:18 Nr.:13201B166", + Owner: "Mariano Amato\n32 (VK Restaurant)", + Tisch: "22", + items: new List + { + new KitchenGang("1. Gang"), + new KitchenProduct(1, "Avocado Sashimi"), + new KitchenProduct(1, "Baby Spinach Salad with Truffl"), + new KitchenGang("2. Gang"), + new KitchenProduct(1, "Beef Tataki"), + new KitchenProduct(1, "Salmon Taco") + } +); + +var test = JsonSerializer.Serialize(receipt, new JsonSerializerOptions() { WriteIndented = true }); +Console.WriteLine(test); ////// Create printer with 42 character line width (default) //var commands = krp.ConvertToCommands(receipt); @@ -288,8 +291,8 @@ Console.ReadLine(); -await printer.FeedLinesAsync(10); -await Task.Delay(1000); +//await printer.FeedLinesAsync(10); +//await Task.Delay(1000); //await printer.SetQuadrupleMode(false); @@ -335,7 +338,7 @@ await Task.Delay(1000); //await printer.PrintTextAsync("Hello!"); //await printer.FeedLinesAsync(5); -await printer.CutAsync(); +//await printer.CutAsync(); diff --git a/Inspectron.Epson/ENPCDiscoveryService.cs b/Inspectron.Epson/DiscoveryService.cs similarity index 98% rename from Inspectron.Epson/ENPCDiscoveryService.cs rename to Inspectron.Epson/DiscoveryService.cs index 91d99cc..5d81a11 100644 --- a/Inspectron.Epson/ENPCDiscoveryService.cs +++ b/Inspectron.Epson/DiscoveryService.cs @@ -3,7 +3,7 @@ using System.Net.Sockets; namespace Inspectron.Epson; -public class ENPCDiscoveryService +public class DiscoveryService : IDiscoveryService { private const int DiscoveryPort = 3289; private const string DiscoveryMessage = "EPSONQ"; diff --git a/Inspectron.Epson/IDiscoveryService.cs b/Inspectron.Epson/IDiscoveryService.cs new file mode 100644 index 0000000..600b2f8 --- /dev/null +++ b/Inspectron.Epson/IDiscoveryService.cs @@ -0,0 +1,17 @@ +namespace Inspectron.Epson; + +/// +/// Interface for ENPC printer discovery service +/// +public interface IDiscoveryService +{ + /// + /// Discovers Epson printers on the local network using UDP broadcast + /// + /// How long to wait for responses (default: 5 seconds) + /// Optional callback invoked when a printer is discovered + /// List of discovered printer information + Task> DiscoverPrintersAsync( + TimeSpan? timeout = null, + Action? onPrinterDiscovered = null); +}