Initial commit
Initial commit til Git. V2 er deployed
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EpsonPrinter.Model;
|
||||
using EpsonPrinter.Services;
|
||||
|
||||
namespace EpsonPrinter.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class PosPrinterController : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// PrintReceipt receipt, so far only for all Epson Thermal Printers
|
||||
/// </summary>
|
||||
/// PrintStyle is:
|
||||
/// None
|
||||
/// FontB
|
||||
/// Bold
|
||||
/// DoubleHeight
|
||||
/// DoubleWidth
|
||||
/// Underline
|
||||
/// There is support for any combination of PrintStyles
|
||||
/// ----------------------------------------
|
||||
///
|
||||
///
|
||||
/// <param name="receiptModel"></param>
|
||||
[HttpPost]
|
||||
[Route("Receipt")]
|
||||
public void PrintReceipt([FromServices] EpsonPrintService epsonPrint, ReceiptModel receiptModel)
|
||||
{
|
||||
epsonPrint.PrintReceipt(receiptModel);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("SaleOfDay")]
|
||||
public void PrintSaleOfDay([FromServices] EpsonPrintService epsonPrint, SaleOfDayModel saleOfDayModel)
|
||||
{
|
||||
epsonPrint.PrintSaleOfDay(saleOfDayModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace EpsonPrinter.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Route("HelloWorld")]
|
||||
public string Get()
|
||||
{
|
||||
return "HelloWorld";
|
||||
}
|
||||
}
|
||||
}
|
||||
9
PointOfSale/EpsonPrinterLinux/Enums/AlignmentEnum.cs
Normal file
9
PointOfSale/EpsonPrinterLinux/Enums/AlignmentEnum.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace EpsonPrinter.Enums
|
||||
{
|
||||
public enum AlignmentEnum
|
||||
{
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
}
|
||||
}
|
||||
12
PointOfSale/EpsonPrinterLinux/Enums/PrintStylesEnum.cs
Normal file
12
PointOfSale/EpsonPrinterLinux/Enums/PrintStylesEnum.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace EpsonPrinter.Enums
|
||||
{
|
||||
public enum PrintStylesEnum
|
||||
{
|
||||
None,
|
||||
FontB,
|
||||
Bold,
|
||||
DoubleHeight,
|
||||
DoubleWidth,
|
||||
UnderLine
|
||||
}
|
||||
}
|
||||
22
PointOfSale/EpsonPrinterLinux/EpsonPrinter.csproj
Normal file
22
PointOfSale/EpsonPrinterLinux/EpsonPrinter.csproj
Normal file
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<DockerfileContext>..\Pos</DockerfileContext>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="ESC-POS\**" />
|
||||
<Content Remove="ESC-POS\**" />
|
||||
<EmbeddedResource Remove="ESC-POS\**" />
|
||||
<None Remove="ESC-POS\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.7" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
18
PointOfSale/EpsonPrinterLinux/Model/BodyModel.cs
Normal file
18
PointOfSale/EpsonPrinterLinux/Model/BodyModel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class BodyModel
|
||||
{
|
||||
public List<BodyProductModel> Products { get; set; }
|
||||
public decimal TotalPrice { get; set; }
|
||||
public decimal TotalVat { get; set; }
|
||||
public int ReceiptNumber { get; set; }
|
||||
public string ReceiptTime { get; set; }
|
||||
public string Staff { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
15
PointOfSale/EpsonPrinterLinux/Model/BodyProductModel.cs
Normal file
15
PointOfSale/EpsonPrinterLinux/Model/BodyProductModel.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class BodyProductModel
|
||||
{
|
||||
public string Product { get; set; }
|
||||
public int NoOfProduct { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
public decimal TotalPrice { get; set; }
|
||||
}
|
||||
}
|
||||
16
PointOfSale/EpsonPrinterLinux/Model/FooterModel.cs
Normal file
16
PointOfSale/EpsonPrinterLinux/Model/FooterModel.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EpsonPrinter.Enums;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class FooterModel
|
||||
{
|
||||
public string Value { get; set; }
|
||||
public PrintStyleModel PrintStyles { get; set; }
|
||||
public AlignmentEnum TextAlignment { get; set; }
|
||||
public int FeedingLines { get; set; }
|
||||
}
|
||||
}
|
||||
16
PointOfSale/EpsonPrinterLinux/Model/HeaderModel.cs
Normal file
16
PointOfSale/EpsonPrinterLinux/Model/HeaderModel.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EpsonPrinter.Enums;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class HeaderModel
|
||||
{
|
||||
public string Value { get; set; }
|
||||
public PrintStyleModel PrintStyles { get; set; }
|
||||
public AlignmentEnum TextAlignment { get; set; }
|
||||
public int FeedingLines { get; set; }
|
||||
}
|
||||
}
|
||||
16
PointOfSale/EpsonPrinterLinux/Model/PrintStyleModel.cs
Normal file
16
PointOfSale/EpsonPrinterLinux/Model/PrintStyleModel.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class PrintStyleModel
|
||||
{
|
||||
public bool FontB { get; set; }
|
||||
public bool Bold { get; set; }
|
||||
public bool DoubleHeight { get; set; }
|
||||
public bool DoubleWidth { get; set; }
|
||||
public bool Underline { get; set; }
|
||||
}
|
||||
}
|
||||
13
PointOfSale/EpsonPrinterLinux/Model/ReceiptModel.cs
Normal file
13
PointOfSale/EpsonPrinterLinux/Model/ReceiptModel.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class ReceiptModel
|
||||
{
|
||||
public string LogoBase64 { get; set; }
|
||||
public List<HeaderModel> Header { get; set; }
|
||||
public BodyModel BodyModel { get; set; }
|
||||
public List<FooterModel> Footer { get; set; }
|
||||
}
|
||||
}
|
||||
10
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayDetail.cs
Normal file
10
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayDetail.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class SaleOfDayDetail
|
||||
{
|
||||
public string Category { get; set; }
|
||||
public decimal TotalSale { get; set; }
|
||||
}
|
||||
}
|
||||
14
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayModel.cs
Normal file
14
PointOfSale/EpsonPrinterLinux/Model/SaleOfDayModel.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EpsonPrinter.Model
|
||||
{
|
||||
public class SaleOfDayModel
|
||||
{
|
||||
public DateTime Date { get; set; }
|
||||
public int TotalCustomers { get; set; }
|
||||
public Decimal TotalSale { get; set; }
|
||||
public List<SaleOfDayDetail> SaleOfDayDetail { get; set; } = new();
|
||||
|
||||
}
|
||||
}
|
||||
23
PointOfSale/EpsonPrinterLinux/Program.cs
Normal file
23
PointOfSale/EpsonPrinterLinux/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using EpsonPrinter.Services;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Services
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
builder.Services.AddScoped<EpsonPrintService>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Swagger (altid aktiv – vi er på en Pi, ikke i produktion)
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
|
||||
// Routing
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
31
PointOfSale/EpsonPrinterLinux/Properties/launchSettings.json
Normal file
31
PointOfSale/EpsonPrinterLinux/Properties/launchSettings.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:23653",
|
||||
"sslPort": 44334
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"EpsonPrinter": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": "true",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
PointOfSale/EpsonPrinterLinux/README_LINUX_USB.txt
Normal file
18
PointOfSale/EpsonPrinterLinux/README_LINUX_USB.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
Linux USB version of the EpsonPrinter API.
|
||||
|
||||
What changed:
|
||||
- Keeps the incoming JSON models for /api/PosPrinter/Receipt and /api/PosPrinter/SaleOfDay
|
||||
- Replaces COM/SerialPrinter transport with raw writes to Linux USB printer device
|
||||
- Uses /dev/usb/lp0 by default from appsettings.json
|
||||
- Builds a standard receipt when parts of the payload are missing
|
||||
- Pulls fallback values from appsettings.json under PrintSettings:Defaults
|
||||
|
||||
Typical run:
|
||||
dotnet restore
|
||||
dotnet run
|
||||
|
||||
Typical endpoint:
|
||||
POST /api/PosPrinter/Receipt
|
||||
|
||||
Important setting:
|
||||
PrintSettings:DevicePath = /dev/usb/lp0
|
||||
248
PointOfSale/EpsonPrinterLinux/Services/EpsonPrintService.cs
Normal file
248
PointOfSale/EpsonPrinterLinux/Services/EpsonPrintService.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using EpsonPrinter.Model;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace EpsonPrinter.Services
|
||||
{
|
||||
public class EpsonPrintService
|
||||
{
|
||||
private readonly IConfiguration _config;
|
||||
private readonly string _devicePath;
|
||||
|
||||
public EpsonPrintService(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_devicePath = _config["PrintSettings:DevicePath"] ?? "/dev/usb/lp0";
|
||||
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)
|
||||
{
|
||||
using var stream = new FileStream(_devicePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite);
|
||||
stream.Write(data, 0, data.Length);
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
private void Write(byte[][] data)
|
||||
{
|
||||
foreach (var segment in data)
|
||||
{
|
||||
Write(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
PointOfSale/EpsonPrinterLinux/Services/PrintAlignment.cs
Normal file
24
PointOfSale/EpsonPrinterLinux/Services/PrintAlignment.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using EpsonPrinter.Enums;
|
||||
using ESCPOS_NET.Emitters;
|
||||
|
||||
namespace EpsonPrinter.Services
|
||||
{
|
||||
public class PrintAlignment
|
||||
{
|
||||
public byte[] GetTextAlignment(ICommandEmitter e, AlignmentEnum alignment)
|
||||
{
|
||||
if (alignment == AlignmentEnum.Left)
|
||||
return e.LeftAlign();
|
||||
|
||||
if (alignment == AlignmentEnum.Right)
|
||||
return e.RightAlign();
|
||||
|
||||
return e.CenterAlign();
|
||||
}
|
||||
}
|
||||
}
|
||||
117
PointOfSale/EpsonPrinterLinux/Services/PrintBody.cs
Normal file
117
PointOfSale/EpsonPrinterLinux/Services/PrintBody.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EpsonPrinter.Model;
|
||||
using ESCPOS_NET.Emitters;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace EpsonPrinter.Services
|
||||
{
|
||||
public class PrintBody
|
||||
{
|
||||
private ICommandEmitter _e;
|
||||
private IConfiguration _config;
|
||||
|
||||
private int productMaxWidth;
|
||||
|
||||
public PrintBody(ICommandEmitter e, IConfiguration config)
|
||||
{
|
||||
_e = e;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public List<byte[][]> Print(BodyModel model)
|
||||
{
|
||||
List<byte[][]> data = new List<byte[][]>();
|
||||
|
||||
byte[][] headerModel =
|
||||
{
|
||||
_e.SetStyles(PrintStyle.None),
|
||||
_e.LeftAlign(),
|
||||
_e.PrintLine($"Dato.........: {model.ReceiptTime}"),
|
||||
_e.PrintLine($"Ekspedient...: {model.Staff}"),
|
||||
_e.PrintLine($"Kvittering...: {model.ReceiptNumber}"),
|
||||
_e.FeedLines(1)
|
||||
};
|
||||
data.Add(headerModel);
|
||||
|
||||
int printWidth = Convert.ToInt32(_config["PrintSettings:PrintWidth"]);
|
||||
foreach (BodyProductModel product in model.Products)
|
||||
{
|
||||
//Size of product is max half of recipt
|
||||
string totalProductLine = MakeProductNameString(product.Product, printWidth);
|
||||
totalProductLine += MakeProductNumber(product.NoOfProduct, product.Price);
|
||||
totalProductLine = MakeTotalProductPrice(totalProductLine, product.TotalPrice,printWidth);
|
||||
|
||||
byte[][] p =
|
||||
{
|
||||
_e.PrintLine(totalProductLine)
|
||||
};
|
||||
data.Add(p);
|
||||
}
|
||||
|
||||
PrintString printString = new PrintString();
|
||||
string totalPricePrint = printString.MakePrintString(printWidth, $"Total: ", $"{model.TotalPrice:F} DKK");
|
||||
byte[][] totalPrice =
|
||||
{
|
||||
_e.FeedLines(1),
|
||||
_e.SetStyles(PrintStyle.Bold | PrintStyle.DoubleHeight),
|
||||
_e.RightAlign(),
|
||||
_e.PrintLine(totalPricePrint)
|
||||
};
|
||||
data.Add(totalPrice);
|
||||
|
||||
byte[][] vat =
|
||||
{
|
||||
_e.FeedLines(1),
|
||||
_e.SetStyles(PrintStyle.None),
|
||||
_e.LeftAlign(),
|
||||
_e.PrintLine(MakeVat(printWidth,model.TotalVat))
|
||||
};
|
||||
data.Add(vat);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private string MakeProductNameString(string product, int totalWidth)
|
||||
{
|
||||
string productString = product;
|
||||
productMaxWidth = (totalWidth / 2) - 5;
|
||||
int productLength = product.Length;
|
||||
if (productLength < productMaxWidth)
|
||||
{
|
||||
|
||||
for (int i = productLength; i < productMaxWidth; i++)
|
||||
{
|
||||
productString += ".";
|
||||
}
|
||||
}
|
||||
|
||||
return productString;
|
||||
}
|
||||
|
||||
private string MakeProductNumber(int noOfProduct, decimal price)
|
||||
{
|
||||
return $"{noOfProduct} á {price:F} DKK :";
|
||||
}
|
||||
|
||||
private string MakeTotalProductPrice(string buffer, decimal totalPrice, int printWidth)
|
||||
{
|
||||
PrintString printString = new PrintString();
|
||||
string p = $"{totalPrice:F} DKK";
|
||||
string makePrintString = printString.MakePrintString(printWidth, buffer, p);
|
||||
return makePrintString;
|
||||
}
|
||||
|
||||
private string MakeVat(int printWidth, decimal vat)
|
||||
{
|
||||
PrintString printString = new PrintString();
|
||||
string vatDesc = $"Moms udgør 25% :";
|
||||
string v = $"{vat:F} DKK";
|
||||
string vatString = printString.MakePrintString(printWidth, vatDesc, v);
|
||||
return vatString;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
PointOfSale/EpsonPrinterLinux/Services/PrintFooter.cs
Normal file
47
PointOfSale/EpsonPrinterLinux/Services/PrintFooter.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EpsonPrinter.Model;
|
||||
using ESCPOS_NET;
|
||||
using ESCPOS_NET.Emitters;
|
||||
|
||||
namespace EpsonPrinter.Services
|
||||
{
|
||||
public class PrintFooter
|
||||
{
|
||||
private ICommandEmitter _e;
|
||||
|
||||
public PrintFooter(ICommandEmitter e)
|
||||
{
|
||||
_e = e;
|
||||
}
|
||||
|
||||
public List<byte[][]> Print(List<FooterModel> model)
|
||||
{
|
||||
List<byte[][]> data = new List<byte[][]>();
|
||||
PrintStyleCombination printStyleCombination = new PrintStyleCombination();
|
||||
PrintAlignment printAlignment = new PrintAlignment();
|
||||
byte[][] feedLines =
|
||||
{
|
||||
_e.FeedLines(1)
|
||||
};
|
||||
data.Add(feedLines);
|
||||
foreach (FooterModel footerModel in model)
|
||||
{
|
||||
|
||||
PrintStyle printStyle = printStyleCombination.Combine(footerModel.PrintStyles);
|
||||
byte[][] bytes = {
|
||||
_e.SetStyles(PrintStyle.None),
|
||||
printAlignment.GetTextAlignment(_e,footerModel.TextAlignment),
|
||||
_e.SetStyles(printStyle),
|
||||
_e.PrintLine(footerModel.Value),
|
||||
_e.FeedLines(footerModel.FeedingLines)
|
||||
};
|
||||
data.Add(bytes);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
PointOfSale/EpsonPrinterLinux/Services/PrintHeader.cs
Normal file
47
PointOfSale/EpsonPrinterLinux/Services/PrintHeader.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using EpsonPrinter.Model;
|
||||
using ESCPOS_NET;
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace EpsonPrinter.Services
|
||||
{
|
||||
public class PrintHeader
|
||||
{
|
||||
private ICommandEmitter _e;
|
||||
|
||||
public PrintHeader(ICommandEmitter e)
|
||||
{
|
||||
_e = e;
|
||||
}
|
||||
|
||||
public List<Byte[][]> Print(List<HeaderModel> model)
|
||||
{
|
||||
List<byte[][]> data = new List<byte[][]>();
|
||||
PrintStyleCombination printStyleCombination = new PrintStyleCombination();
|
||||
PrintAlignment printAlignment = new PrintAlignment();
|
||||
foreach (HeaderModel headerModel in model)
|
||||
{
|
||||
|
||||
PrintStyle printStyle = printStyleCombination.Combine(headerModel.PrintStyles);
|
||||
byte[][] bytes = {
|
||||
_e.SetStyles(PrintStyle.None),
|
||||
printAlignment.GetTextAlignment(_e,headerModel.TextAlignment),
|
||||
_e.SetStyles(printStyle),
|
||||
_e.PrintLine(headerModel.Value),
|
||||
_e.FeedLines(headerModel.FeedingLines)
|
||||
};
|
||||
data.Add(bytes);
|
||||
}
|
||||
byte[][] feedLines =
|
||||
{
|
||||
_e.FeedLines(1)
|
||||
};
|
||||
data.Add(feedLines);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
PointOfSale/EpsonPrinterLinux/Services/PrintString.cs
Normal file
44
PointOfSale/EpsonPrinterLinux/Services/PrintString.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpsonPrinter.Services
|
||||
{
|
||||
public class PrintString
|
||||
{
|
||||
/// <summary>
|
||||
/// An appropriate interval is converted into the length of
|
||||
/// the tab about two texts. And make a printing data.
|
||||
/// </summary>
|
||||
/// <param name="iLineChars">
|
||||
/// The width of the territory which it prints on is converted into the number of
|
||||
/// characters, and that value is specified.
|
||||
/// </param>
|
||||
/// <param name="strBuf">
|
||||
/// It is necessary as an information for deciding the interval of the text.
|
||||
/// </param>
|
||||
/// <param name="strPrice">
|
||||
/// It is necessary as an information for deciding the interval of the text, too.
|
||||
/// </param>
|
||||
/// <returns>printing data.
|
||||
/// </returns>
|
||||
public String MakePrintString(int iLineChars, String strBuf, String strPrice)
|
||||
{
|
||||
int iSpaces = 0;
|
||||
String tab = "";
|
||||
try
|
||||
{
|
||||
iSpaces = iLineChars - (strBuf.Length + strPrice.Length);
|
||||
for (int j = 0; j < iSpaces; j++)
|
||||
{
|
||||
tab += " ";
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
return strBuf + tab + strPrice;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using EpsonPrinter.Enums;
|
||||
using EpsonPrinter.Model;
|
||||
using ESCPOS_NET.Emitters;
|
||||
|
||||
namespace EpsonPrinter.Services
|
||||
{
|
||||
public class PrintStyleCombination
|
||||
{
|
||||
public PrintStyle Combine(PrintStyleModel printStyleModel)
|
||||
{
|
||||
|
||||
//Bold
|
||||
if (printStyleModel.Bold && !printStyleModel.DoubleHeight && !printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.Bold;
|
||||
|
||||
if (printStyleModel.Bold && printStyleModel.DoubleHeight && !printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.Bold | PrintStyle.DoubleHeight;
|
||||
|
||||
if(printStyleModel.Bold && printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.Bold | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth;
|
||||
|
||||
if (printStyleModel.Bold && printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.Bold | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB;
|
||||
|
||||
if (printStyleModel.Bold && printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && printStyleModel.Underline)
|
||||
return PrintStyle.Bold | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB | PrintStyle.Underline;
|
||||
|
||||
//DoubleHeight
|
||||
if (printStyleModel.DoubleHeight && !printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.DoubleHeight;
|
||||
|
||||
if (printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.DoubleHeight | PrintStyle.DoubleWidth;
|
||||
|
||||
if (printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB;
|
||||
|
||||
if (printStyleModel.DoubleHeight && printStyleModel.DoubleWidth && printStyleModel.FontB && printStyleModel.Underline)
|
||||
return PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.FontB | PrintStyle.Underline;
|
||||
|
||||
//DoubleWidth
|
||||
if (printStyleModel.DoubleWidth && !printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.DoubleWidth;
|
||||
|
||||
if (printStyleModel.DoubleWidth && printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.DoubleWidth | PrintStyle.FontB;
|
||||
|
||||
if (printStyleModel.DoubleWidth && printStyleModel.FontB && printStyleModel.Underline)
|
||||
return PrintStyle.DoubleWidth | PrintStyle.FontB | PrintStyle.Underline;
|
||||
|
||||
//FontB
|
||||
if (printStyleModel.FontB && !printStyleModel.Underline)
|
||||
return PrintStyle.FontB;
|
||||
|
||||
if(printStyleModel.FontB && printStyleModel.Underline)
|
||||
return PrintStyle.FontB | PrintStyle.Underline;
|
||||
|
||||
//Underline
|
||||
if (printStyleModel.Underline)
|
||||
return PrintStyle.Underline;
|
||||
|
||||
return PrintStyle.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
26
PointOfSale/EpsonPrinterLinux/appsettings.json
Normal file
26
PointOfSale/EpsonPrinterLinux/appsettings.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"PrintSettings": {
|
||||
"DevicePath": "/dev/usb/lp0",
|
||||
"PrintWidth": 48,
|
||||
"CodePage": "ISO8859_15_LATIN9",
|
||||
"Defaults": {
|
||||
"StoreName": "Blomster Til Alt",
|
||||
"AddressLine1": "Adelgade 88",
|
||||
"AddressLine2": "5400 Bogense",
|
||||
"Cvr": "CVR: 37144436",
|
||||
"Phone": "Tlf: 41 82 71 66",
|
||||
"FooterLine1": "Tak for dit køb!",
|
||||
"FooterLine2": "Vi håber du bliver glad for dine varer.",
|
||||
"Staff": "Ukendt",
|
||||
"ReceiptPrefix": "BON"
|
||||
}
|
||||
}
|
||||
}
|
||||
73
PointOfSale/EpsonPrinterLinux/testdata.json
Normal file
73
PointOfSale/EpsonPrinterLinux/testdata.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"logoBase64": "string",
|
||||
"header": [
|
||||
{
|
||||
"value": "Første linie med ÆØÅ æøå",
|
||||
"printStyles": {
|
||||
"fontB": false,
|
||||
"bold": true,
|
||||
"doubleHeight": false,
|
||||
"doubleWidth": false,
|
||||
"underline": false
|
||||
},
|
||||
"textAlignment": 0
|
||||
},
|
||||
{
|
||||
"value": "Anden linie",
|
||||
"printStyles": {
|
||||
"fontB": false,
|
||||
"bold": true,
|
||||
"doubleHeight": false,
|
||||
"doubleWidth": false,
|
||||
"underline": false
|
||||
},
|
||||
"textAlignment": 0
|
||||
},
|
||||
{
|
||||
"value": "Tredje linie",
|
||||
"printStyles": {
|
||||
"fontB": false,
|
||||
"bold": true,
|
||||
"doubleHeight": false,
|
||||
"doubleWidth": false,
|
||||
"underline": false
|
||||
},
|
||||
"textAlignment": 0
|
||||
},
|
||||
{
|
||||
"value": "Fjerde linie",
|
||||
"printStyles": {
|
||||
"fontB": false,
|
||||
"bold": true,
|
||||
"doubleHeight": false,
|
||||
"doubleWidth": false,
|
||||
"underline": false
|
||||
},
|
||||
"textAlignment": 0
|
||||
},
|
||||
{
|
||||
"value": "Femte linie",
|
||||
"printStyles": {
|
||||
"fontB": false,
|
||||
"bold": true,
|
||||
"doubleHeight": false,
|
||||
"doubleWidth": false,
|
||||
"underline": false
|
||||
},
|
||||
"textAlignment": 0
|
||||
}
|
||||
],
|
||||
"footer": [
|
||||
{
|
||||
"value": "string",
|
||||
"printStyles": {
|
||||
"fontB": true,
|
||||
"bold": true,
|
||||
"doubleHeight": true,
|
||||
"doubleWidth": true,
|
||||
"underline": true
|
||||
},
|
||||
"textAlignment": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user