using Inspectron.Epson; using Inspectron.Epson.PrintServer; using Inspectron.Epson.PrintServer.ConfigurationSources; using Inspectron.Epson.PrintServer.Hooks; using Inspectron.Epson.PrintServer.JobSources; using Inspectron.Epson.PrintServer.JobStatusReporters; using Inspectron.Epson.PrintServer.PrinterAssinment; using Inspectron.Epson.PrintServer.Printers; using Inspectron.Epson.PrintServer.Printers.Utils; using Inspectron.Epson.PrintServer.PrintServices; using Inspectron.Epson.PrintServer.Telemetry; using Inspectron.Epson.Queue; using Microsoft.Extensions.Logging; using Ninject; using System.Reflection; namespace EpsonPrintService; public class PrintServerBootstrapper { private readonly EpsonPrintServiceConfiguration _config; private readonly CancellationTokenSource _cts; private readonly List _arrivedHandlers = new(); private StandardKernel? _kernel; public bool IsRunning { get; private set; } public PrintServerBootstrapper(EpsonPrintServiceConfiguration config, CancellationTokenSource cts) { _config = config; _cts = cts; } /// /// Register a handler that fires once per print job as it arrives from the job source, /// before it's enqueued on the printer queue. Register all handlers before calling . /// Handler exceptions are logged and swallowed; they never block a print. /// public void OnPrintJobArrived(PrintJobArrivedHandler handler) { if (IsRunning) throw new InvalidOperationException("Register hooks before StartAsync()."); _arrivedHandlers.Add(handler); } public async Task StartAsync() { _kernel = new StandardKernel(); _kernel.Bind().ToConstant(new HttpClient { Timeout = TimeSpan.FromSeconds(30) }).InSingletonScope(); if (_config.EmulationMode) _kernel.Bind().To().InSingletonScope(); else _kernel.Bind().To().InSingletonScope(); _kernel.Bind().ToConstant(_config); if (_config.EmulationMode) { var emulationConfigs = new Dictionary { ["127.0.0.2"] = ("emulation/u220.html", 0x13, 258), ["127.0.0.3"] = ("emulation/t30.html", 0x01, 384), }; var discovery = new PreconfiguredDiscoveryService(); discovery.AddPrinter("127.0.0.2", "TM-U220II"); discovery.AddPrinter("127.0.0.3", "TM-T30III"); _kernel.Bind().ToConstant(discovery).InSingletonScope(); _kernel.Bind().ToMethod(ctx => new EmulationPrinterFactory(emulationConfigs, ctx.Kernel.Get())); Console.WriteLine("Emulation mode enabled: 127.0.0.2 (TM-U220II), 127.0.0.3 (TM-T30III)"); } else { // hardcoded discovery // quick and dirty fix for testing without discovery - just bind a preconfigured discovery service with known printer IPs // DO NOT REMOVE !!! //var discovery = new PreconfiguredDiscoveryService(); //discovery.AddPrinter("192.168.1.124", "TM-T30III"); //_kernel.Bind().ToConstant(discovery).InSingletonScope();\ _kernel.Bind().To().InSingletonScope(); _kernel.Bind().To(); } _kernel.Bind().To().InSingletonScope(); _kernel.Bind().To(); _kernel.Bind().ToMethod(ctx => { var loggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); builder.SetMinimumLevel(LogLevel.Trace); }); return loggerFactory.CreateLogger("EpsonPrintService"); }); _kernel.Bind().To().InSingletonScope(); _kernel.Bind().To(); _kernel.Bind().To().InSingletonScope(); _kernel.Bind().To(); _kernel.Bind().ToSelf().InSingletonScope(); foreach (var handler in _arrivedHandlers) { _kernel.Bind().ToConstant(handler); } _kernel.Bind().ToSelf().InSingletonScope(); _kernel.Bind().ToMethod(ctx => new InsinTelemetryDiscoveredPrintersReceiver( ctx.Kernel.Get(), ctx.Kernel.Get())) .InSingletonScope(); _kernel.Bind().ToSelf().InSingletonScope(); _kernel.Bind().ToSelf().InSingletonScope(); var printLoop = _kernel.Get(); var discoveryTask = _kernel.Get(); var heartbeatTask = _kernel.Get(); var jobSourceTask = _kernel.Get(); // Start background tasks _ = discoveryTask.StartAsync(_cts.Token); _ = heartbeatTask.StartAsync(_cts.Token); // Delay for a moment to allow discovery to find printers Console.WriteLine("Waiting for printer discovery..."); await Task.Delay(3000); _ = jobSourceTask.StartAsync(); await printLoop.StartAsync(); IsRunning = true; Console.WriteLine("Print server started."); var version = Assembly.GetExecutingAssembly().GetName().Version?.ToString() ?? "unknown"; var telemetry = _kernel.Get(); try { telemetry.Emit(InsinEventKinds.ServiceStarted, InsinMessageFormatter.Format( ("version", version), ("restaurantId", _config.RestaurantId))); } catch { /* telemetry must never fail startup */ } } }