Files
point_of_sale_v2/PointOfSale/EpsonPrinterLinux/Services/EpsonPrintService.cs
Bjarne Pedersen 170a03e7df Print problemer
Har muligvis rettet den print fejl der er - men mangler at få det testet.
Der er slettet en masse projekter som ikke bliver brugt mere.
Og flyttet rundt på de få projekter som er tilbage.
Dette er V2 og i sit eget repo, så dette er initial commit
2026-07-15 22:40:53 +02:00

307 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using EpsonPrinter.Model;
using ESCPOS_NET;
using ESCPOS_NET.Emitters;
using ESCPOS_NET.Utilities;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace EpsonPrinter.Services
{
public class EpsonPrintService
{
private readonly IConfiguration _config;
private readonly string _devicePath;
private readonly string? _previewPath;
private readonly bool _isDevelopment;
public EpsonPrintService(IConfiguration config, IWebHostEnvironment environment)
{
_config = config;
_isDevelopment = environment.IsDevelopment();
var configuredPath = _config["PrintSettings:DevicePath"] ?? "/dev/usb/lp0";
_devicePath = _isDevelopment && !Path.IsPathRooted(configuredPath)
? Path.Combine(environment.ContentRootPath, configuredPath)
: configuredPath;
var configuredPreviewPath = _config["PrintSettings:PreviewPath"] ?? "printer-preview.txt";
_previewPath = _isDevelopment
? Path.IsPathRooted(configuredPreviewPath)
? configuredPreviewPath
: Path.Combine(environment.ContentRootPath, configuredPreviewPath)
: null;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
public void PrintReceipt(ReceiptModel model)
{
ICommandEmitter e = new EPSON();
InitAndWrite(e);
List<byte[][]> printBytes = new List<byte[][]>();
PrintHeader printHeader = new PrintHeader(e);
PrintBody printBody = new PrintBody(e, _config);
PrintFooter printFooter = new PrintFooter(e);
var header = (model.Header != null && model.Header.Any()) ? model.Header : BuildDefaultHeader();
var body = model.BodyModel ?? BuildDefaultBody();
if (string.IsNullOrWhiteSpace(body.Staff))
{
body.Staff = _config["PrintSettings:Defaults:Staff"] ?? "Ukendt";
}
if (string.IsNullOrWhiteSpace(body.ReceiptTime))
{
body.ReceiptTime = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss");
}
if (body.ReceiptNumber <= 0)
{
body.ReceiptNumber = Math.Abs(Environment.TickCount % 1000000);
}
body.Products ??= new List<BodyProductModel>();
if (!body.Products.Any())
{
body.Products.Add(new BodyProductModel
{
Product = "Standard vare",
NoOfProduct = 1,
Price = 99.00m,
TotalPrice = 99.00m
});
}
if (body.TotalPrice <= 0)
{
body.TotalPrice = body.Products.Sum(x => x.TotalPrice <= 0 ? x.Price * x.NoOfProduct : x.TotalPrice);
}
if (body.TotalVat <= 0)
{
body.TotalVat = Math.Round(body.TotalPrice * 0.25m, 2);
}
var footer = (model.Footer != null && model.Footer.Any()) ? model.Footer : BuildDefaultFooter();
printBytes.AddRange(printHeader.Print(header));
printBytes.AddRange(printBody.Print(body));
printBytes.AddRange(printFooter.Print(footer));
byte[][] array = printBytes.SelectMany(c => c).ToArray();
Write(array);
Write(e.FeedLines(5));
Write(e.FullCut());
}
public void PrintSaleOfDay(SaleOfDayModel model)
{
ICommandEmitter e = new EPSON();
InitAndWrite(e);
PrintSaleOfDay(model, e);
}
private void InitAndWrite(ICommandEmitter e)
{
Write(e.Initialize());
Write(e.Enable());
Write(e.CodePage(CodePage.ISO8859_15_LATIN9));
Write(e.EnableAutomaticStatusBack());
}
private void PrintSaleOfDay(SaleOfDayModel model, ICommandEmitter e)
{
List<byte[][]> data = new List<byte[][]>();
byte[][] dateBytes =
{
e.SetStyles(PrintStyle.DoubleWidth),
e.LeftAlign(),
e.PrintLine($"Dato: {model.Date:dd-MM-yyyy}")
};
data.Add(dateBytes);
byte[][] seperater =
{
e.SetStyles(PrintStyle.None),
e.LeftAlign(),
e.PrintLine("-----------------------------------")
};
data.Add(seperater);
foreach (SaleOfDayDetail saleOfDayDetail in model.SaleOfDayDetail)
{
string pS = $"{saleOfDayDetail.Category} : {saleOfDayDetail.TotalSale.ToString("#.#0", CultureInfo.InvariantCulture)}";
byte[][] totalPrice =
{
e.SetStyles(PrintStyle.DoubleWidth),
e.LeftAlign(),
e.PrintLine(pS)
};
data.Add(totalPrice);
}
data.Add(seperater);
string totalSale = $"Total salg: {model.TotalSale.ToString("#.#0", CultureInfo.InvariantCulture)}";
byte[][] tSBytes =
{
e.SetStyles(PrintStyle.DoubleWidth),
e.LeftAlign(),
e.PrintLine(totalSale)
};
data.Add(tSBytes);
string totalCustomer = $"Antal kunder: {model.TotalCustomers}";
byte[][] tCBytes =
{
e.SetStyles(PrintStyle.DoubleWidth),
e.LeftAlign(),
e.PrintLine(totalCustomer)
};
data.Add(tCBytes);
byte[][] array = data.SelectMany(c => c).ToArray();
Write(array);
Write(e.FeedLines(5));
Write(e.FullCut());
}
private List<HeaderModel> BuildDefaultHeader()
{
return new List<HeaderModel>
{
new HeaderModel
{
Value = _config["PrintSettings:Defaults:StoreName"] ?? "TableTop3D",
TextAlignment = Enums.AlignmentEnum.Center,
FeedingLines = 0,
PrintStyles = new PrintStyleModel { Bold = true, DoubleWidth = true, DoubleHeight = true }
},
new HeaderModel
{
Value = _config["PrintSettings:Defaults:AddressLine1"] ?? string.Empty,
TextAlignment = Enums.AlignmentEnum.Center,
FeedingLines = 0,
PrintStyles = new PrintStyleModel { Bold = true }
},
new HeaderModel
{
Value = _config["PrintSettings:Defaults:AddressLine2"] ?? string.Empty,
TextAlignment = Enums.AlignmentEnum.Center,
FeedingLines = 0,
PrintStyles = new PrintStyleModel()
},
new HeaderModel
{
Value = _config["PrintSettings:Defaults:Cvr"] ?? string.Empty,
TextAlignment = Enums.AlignmentEnum.Center,
FeedingLines = 1,
PrintStyles = new PrintStyleModel()
}
}.Where(x => !string.IsNullOrWhiteSpace(x.Value)).ToList();
}
private FooterModel CreateFooterLine(string value, bool bold = false)
{
return new FooterModel
{
Value = value,
TextAlignment = Enums.AlignmentEnum.Center,
FeedingLines = 0,
PrintStyles = new PrintStyleModel { Bold = bold }
};
}
private List<FooterModel> BuildDefaultFooter()
{
var values = new[]
{
_config["PrintSettings:Defaults:FooterLine1"] ?? "Tak for dit køb!",
_config["PrintSettings:Defaults:FooterLine2"] ?? string.Empty,
_config["PrintSettings:Defaults:Phone"] ?? string.Empty
}.Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
return values.Select((x, i) => CreateFooterLine(x, i == 0)).ToList();
}
private BodyModel BuildDefaultBody()
{
return new BodyModel
{
ReceiptNumber = Math.Abs(Environment.TickCount % 1000000),
ReceiptTime = DateTime.Now.ToString("dd-MM-yyyy HH:mm:ss"),
Staff = _config["PrintSettings:Defaults:Staff"] ?? "Ukendt",
Products = new List<BodyProductModel>
{
new BodyProductModel
{
Product = "Standard vare",
NoOfProduct = 1,
Price = 99.00m,
TotalPrice = 99.00m
}
},
TotalPrice = 99.00m,
TotalVat = 24.75m
};
}
private void Write(byte[] data)
{
var fileMode = _isDevelopment ? FileMode.Append : FileMode.Open;
using var stream = new FileStream(_devicePath, fileMode, FileAccess.Write, FileShare.ReadWrite);
stream.Write(data, 0, data.Length);
stream.Flush();
if (_previewPath != null)
{
AppendPreview(data);
}
}
private void AppendPreview(byte[] data)
{
using var writer = new StreamWriter(_previewPath!, append: true, Encoding.UTF8);
var textEncoding = Encoding.GetEncoding("iso-8859-15");
for (int i = 0; i < data.Length; i++)
{
byte value = data[i];
if (value == 0x1B)
{
i += i + 1 < data.Length && data[i + 1] == 0x40 ? 1 : 2;
continue;
}
if (value == 0x1D)
{
i += 2;
continue;
}
if (value == 0x0A)
{
writer.WriteLine();
continue;
}
if (value >= 0x20)
{
writer.Write(textEncoding.GetString(new[] { value }));
}
}
}
private void Write(byte[][] data)
{
foreach (var segment in data)
{
Write(segment);
}
}
}
}