using Microsoft.Extensions.Logging; using Inspectron.Epson.PrintServer.Printers; using Inspectron.Epson.PrintServer.Printers.Utils; namespace Inspectron.Epson.PrintServer.PrintServices; public class EpsonPrintService: IPrintService { private readonly ILogger _logger; private readonly IPrinterFactory _printerFactory; private readonly IWrapperPrinterFactory _wrapperPrinterFactory; private readonly IPrinterConfigurationSource _printerConfigurationSource; private readonly IReceiptConverterFactory _receiptConverterFactory; private readonly HttpClient _httpClient; public EpsonPrintService(ILogger logger, IPrinterFactory printerFactory, IWrapperPrinterFactory wrapperPrinterFactory, IPrinterConfigurationSource printerConfigurationSource, IReceiptConverterFactory receiptConverterFactory, HttpClient httpClient) { _logger = logger; _printerFactory = printerFactory; _wrapperPrinterFactory = wrapperPrinterFactory; _printerConfigurationSource = printerConfigurationSource; _receiptConverterFactory = receiptConverterFactory; _httpClient = httpClient; } public async Task PrintAsync(string printerIp, PrintJob job) { try { var configuration = _printerConfigurationSource.GetConfiguration(printerIp); await using var epsonPrinter = _printerFactory.CreatePrinter(); string address = printerIp; int port = 9100; await epsonPrinter.ConnectAsync(address, port); var printerId = await epsonPrinter.GetPrinterIdAsync(); _logger.LogInformation("Printer ID({ip}): {PrinterId}", printerIp, printerId); var status = await epsonPrinter.GetPrinterStatusAsync(); if (!status.IsOnline) { throw new InvalidOperationException("Printer is offline or out of paper."); } var printerAdapter = _wrapperPrinterFactory.CreatePrinterFromId(printerId.Value, epsonPrinter); await printerAdapter.InitAsync(); if (!string.IsNullOrEmpty(job.Document.LogoUrl)) { // Download logo image var logoFileName = Path.GetFileName(new Uri(job.Document.LogoUrl).LocalPath); var ext = Path.GetExtension(logoFileName).ToLowerInvariant(); var encodedName = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(logoFileName)); logoFileName = $"{encodedName}{ext}"; var logoCachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logos"); // Ensure logos cache directory exists if (!Directory.Exists(logoCachePath)) { Directory.CreateDirectory(logoCachePath); } var cachedLogoPath = Path.Combine(logoCachePath, logoFileName); // Download only if not already cached if (!File.Exists(cachedLogoPath)) { var logoData = await _httpClient.GetByteArrayAsync(job.Document.LogoUrl); await File.WriteAllBytesAsync(cachedLogoPath, logoData); _logger.LogInformation("Downloaded logo {LogoFileName} from {LogoUrl}", logoFileName, job.Document.LogoUrl); } else { _logger.LogDebug("Using cached logo {LogoFileName}", logoFileName); } await printerAdapter.PrintImageAsync(cachedLogoPath); } await printerAdapter.SetFontSizeAsync(configuration.FontSize); // Convert receipt content to print commands using the factory List commands; try { var converter = _receiptConverterFactory.Create(job.Document.ReceiptType, printerId.Value); commands = converter.Convert(job.Document.Content); } catch (Exception e) { _logger.LogWarning(e, "Conversion error for print job on printer {PrinterUid}", printerIp); return PrintResult.Fail(PrintErrorType.ConversionError); } await printerAdapter.PrintAsync(commands); await Task.Delay(200); status = await epsonPrinter.GetPrinterStatusAsync(); if (!status.IsOnline) { throw new InvalidOperationException("Printer is offline or out of paper."); } await printerAdapter.Cut(); } catch (Exception e) { _logger.LogWarning(e, "Failed to print job for printer {PrinterUid}", printerIp); return PrintResult.Fail(PrintErrorType.Other); } return PrintResult.Ok(); } }