Initial commit
Initial commit til Git. V2 er deployed
1
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto
|
||||
12
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: ['lukevp']
|
||||
#patreon: # Replace with a single Patreon username
|
||||
#open_collective: # Replace with a single Open Collective username
|
||||
#ko_fi: # Replace with a single Ko-fi username
|
||||
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
#liberapay: # Replace with a single Liberapay username
|
||||
#issuehunt: # Replace with a single IssueHunt username
|
||||
#otechie: # Replace with a single Otechie username
|
||||
#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
7
PointOfSale/Pos.Ui/EpsonPrinter/ESC-POS/ESC-POS-.NET-master/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
.vs/
|
||||
.idea/
|
||||
**/obj/
|
||||
**/bin/
|
||||
push.ps1
|
||||
/push.txt
|
||||
/ESCPOS_NET/ESCPOS_NET.csproj.user
|
||||
@@ -0,0 +1,74 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="5.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ESCPOS_NET\ESCPOS_NET.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="abe-lincoln.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\abe-lincoln.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\kitten.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-100.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-200.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-300.bmp">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-300.gif">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-300.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-300.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-400.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-500.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo-600.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\pd-logo.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="images\Portal_Companion_Cube.jpg">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="kitten.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="pd-logo.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="test-files\output-juliogamasso.bin">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,267 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Threading;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
private static BasePrinter printer;
|
||||
private static ICommandEmitter e;
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
|
||||
Console.WriteLine("Welcome to the ESCPOS_NET Test Application!");
|
||||
Console.Write("Would you like to see all debug messages? (y/n): ");
|
||||
var response = Console.ReadLine().Trim().ToLowerInvariant();
|
||||
var logLevel = LogLevel.Information;
|
||||
if (response.Length >= 1 && response[0] == 'y')
|
||||
{
|
||||
Console.WriteLine("Debugging enabled!");
|
||||
logLevel = LogLevel.Trace;
|
||||
}
|
||||
var factory = LoggerFactory.Create(b => b.AddConsole().SetMinimumLevel(logLevel));
|
||||
var logger = factory.CreateLogger<Program>();
|
||||
ESCPOS_NET.Logging.Logger = logger;
|
||||
|
||||
Console.WriteLine("1 ) Test Serial Port");
|
||||
Console.WriteLine("2 ) Test Network Printer");
|
||||
Console.Write("Choice: ");
|
||||
string comPort = "";
|
||||
string baudRate;
|
||||
string ip;
|
||||
string networkPort;
|
||||
response = Console.ReadLine();
|
||||
var valid = new List<string> { "1", "2" };
|
||||
if (!valid.Contains(response))
|
||||
{
|
||||
response = "1";
|
||||
}
|
||||
|
||||
int choice = int.Parse(response);
|
||||
|
||||
if (choice == 1)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
while (!comPort.StartsWith("COM"))
|
||||
{
|
||||
Console.Write("COM Port (enter for default COM5): ");
|
||||
comPort = Console.ReadLine();
|
||||
if (string.IsNullOrWhiteSpace(comPort))
|
||||
{
|
||||
comPort = "COM5";
|
||||
}
|
||||
}
|
||||
Console.Write("Baud Rate (enter for default 115200): ");
|
||||
baudRate = Console.ReadLine();
|
||||
if (string.IsNullOrWhiteSpace(baudRate))
|
||||
{
|
||||
baudRate = "115200";
|
||||
}
|
||||
printer = new SerialPrinter(portName: comPort, baudRate: 115200);
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
Console.Write("File / virtual com path (eg. /dev/usb/lp0): ");
|
||||
comPort = Console.ReadLine();
|
||||
if (string.IsNullOrWhiteSpace(comPort))
|
||||
{
|
||||
comPort = "/dev/usb/lp0";
|
||||
}
|
||||
printer = new FilePrinter(filePath: comPort, false);
|
||||
}
|
||||
}
|
||||
else if (choice == 2)
|
||||
{
|
||||
Console.Write("IP Address (eg. 192.168.1.240): ");
|
||||
ip = Console.ReadLine();
|
||||
if (string.IsNullOrWhiteSpace(ip))
|
||||
{
|
||||
ip = "192.168.254.202";
|
||||
}
|
||||
Console.Write("TCP Port (enter for default 9100): ");
|
||||
networkPort = Console.ReadLine();
|
||||
if (string.IsNullOrWhiteSpace(networkPort))
|
||||
{
|
||||
networkPort = "9100";
|
||||
}
|
||||
printer = new NetworkPrinter(settings: new NetworkPrinterSettings() { ConnectionString = $"{ip}:{networkPort}" });
|
||||
}
|
||||
|
||||
bool monitor = false;
|
||||
Thread.Sleep(500);
|
||||
Console.Write("Turn on Live Status Back Monitoring? (y/n): ");
|
||||
response = Console.ReadLine().Trim().ToLowerInvariant();
|
||||
if (response.Length >= 1 && response[0] == 'y')
|
||||
{
|
||||
monitor = true;
|
||||
}
|
||||
|
||||
e = new EPSON();
|
||||
var testCases = new Dictionary<Option, string>()
|
||||
{
|
||||
{ Option.SingleLinePrinting, "Single Line Printing" },
|
||||
{ Option.MultiLinePrinting, "Multi-line Printing" },
|
||||
{ Option.LineSpacing, "Line Spacing" },
|
||||
{ Option.BarcodeStyles, "Barcode Styles" },
|
||||
{ Option.BarcodeTypes, "Barcode Types" },
|
||||
{ Option.TwoDimensionCodes, "2D Codes" },
|
||||
{ Option.TextStyles, "Text Styles" },
|
||||
{ Option.FullReceipt, "Full Receipt" },
|
||||
{ Option.CodePages, "Code Pages (Euro, Katakana, Etc)" },
|
||||
{ Option.Images, "Images" },
|
||||
{ Option.LegacyImages, "Legacy Images" },
|
||||
{ Option.LargeByteArrays, "Large Byte Arrays" },
|
||||
{ Option.CashDrawerPin2, "Cash Drawer Pin2" },
|
||||
{ Option.CashDrawerPin5, "Cash Drawer Pin5" },
|
||||
{ Option.Exit, "Exit" }
|
||||
|
||||
};
|
||||
while (true)
|
||||
{
|
||||
foreach (var item in testCases)
|
||||
{
|
||||
Console.WriteLine($"{(int)item.Key} : {item.Value}");
|
||||
}
|
||||
Console.Write("Execute Test: ");
|
||||
|
||||
if (!int.TryParse(Console.ReadLine(), out choice) || !Enum.IsDefined(typeof(Option), choice))
|
||||
{
|
||||
Console.WriteLine("Invalid entry. Please try again.");
|
||||
continue;
|
||||
}
|
||||
|
||||
var enumChoice = (Option)choice;
|
||||
if (enumChoice == Option.Exit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Clear();
|
||||
|
||||
if (monitor)
|
||||
{
|
||||
printer.Write(e.Initialize());
|
||||
printer.Write(e.Enable());
|
||||
printer.Write(e.EnableAutomaticStatusBack());
|
||||
}
|
||||
Setup(monitor);
|
||||
|
||||
printer?.Write(e.PrintLine($"== [ Start {testCases[enumChoice]} ] =="));
|
||||
|
||||
switch (enumChoice)
|
||||
{
|
||||
case Option.SingleLinePrinting:
|
||||
printer.Write(Tests.SingleLinePrinting(e));
|
||||
break;
|
||||
case Option.MultiLinePrinting:
|
||||
printer.Write(Tests.MultiLinePrinting(e));
|
||||
break;
|
||||
case Option.LineSpacing:
|
||||
printer.Write(Tests.LineSpacing(e));
|
||||
break;
|
||||
case Option.BarcodeStyles:
|
||||
printer.Write(Tests.BarcodeStyles(e));
|
||||
break;
|
||||
case Option.BarcodeTypes:
|
||||
printer.Write(Tests.BarcodeTypes(e));
|
||||
break;
|
||||
case Option.TwoDimensionCodes:
|
||||
printer.Write(Tests.TwoDimensionCodes(e));
|
||||
break;
|
||||
case Option.TextStyles:
|
||||
printer.Write(Tests.TextStyles(e));
|
||||
break;
|
||||
case Option.FullReceipt:
|
||||
printer.Write(Tests.Receipt(e));
|
||||
break;
|
||||
case Option.Images:
|
||||
printer.Write(Tests.Images(e, false));
|
||||
break;
|
||||
case Option.LegacyImages:
|
||||
printer.Write(Tests.Images(e, true));
|
||||
break;
|
||||
case Option.LargeByteArrays:
|
||||
try
|
||||
{
|
||||
printer.Write(Tests.TestLargeByteArrays(e));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine($"Aborting print due to test failure. Exception: {e?.Message}, Stack Trace: {e?.GetBaseException()?.StackTrace}");
|
||||
}
|
||||
break;
|
||||
case Option.CashDrawerPin2:
|
||||
printer.Write(Tests.CashDrawerOpenPin2(e));
|
||||
break;
|
||||
case Option.CashDrawerPin5:
|
||||
printer.Write(Tests.CashDrawerOpenPin5(e));
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine("Invalid entry.");
|
||||
break;
|
||||
}
|
||||
|
||||
Setup(monitor);
|
||||
printer?.Write(e.PrintLine($"== [ End {testCases[enumChoice]} ] =="));
|
||||
printer?.Write(e.PartialCutAfterFeed(5));
|
||||
|
||||
// TODO: also make an automatic runner that runs all tests (command line).
|
||||
}
|
||||
}
|
||||
|
||||
public enum Option
|
||||
{
|
||||
SingleLinePrinting = 1,
|
||||
MultiLinePrinting,
|
||||
LineSpacing,
|
||||
BarcodeStyles,
|
||||
BarcodeTypes,
|
||||
TwoDimensionCodes,
|
||||
TextStyles,
|
||||
FullReceipt,
|
||||
CodePages,
|
||||
Images,
|
||||
LegacyImages,
|
||||
LargeByteArrays,
|
||||
CashDrawerPin2,
|
||||
CashDrawerPin5,
|
||||
Exit = 99
|
||||
}
|
||||
|
||||
private static void StatusChanged(object sender, EventArgs ps)
|
||||
{
|
||||
var status = (PrinterStatusEventArgs)ps;
|
||||
if (status == null) { Console.WriteLine("Status was null - unable to read status from printer."); return; }
|
||||
Console.WriteLine($"Printer Online Status: {status.IsPrinterOnline}");
|
||||
Console.WriteLine(JsonConvert.SerializeObject(status));
|
||||
}
|
||||
private static bool _hasEnabledStatusMonitoring = false;
|
||||
|
||||
private static void Setup(bool enableStatusBackMonitoring)
|
||||
{
|
||||
if (printer != null)
|
||||
{
|
||||
// Only register status monitoring once.
|
||||
if (!_hasEnabledStatusMonitoring)
|
||||
{
|
||||
printer.StatusChanged += StatusChanged;
|
||||
_hasEnabledStatusMonitoring = true;
|
||||
}
|
||||
printer?.Write(e.Initialize());
|
||||
printer?.Write(e.Enable());
|
||||
if (enableStatusBackMonitoring)
|
||||
{
|
||||
printer.Write(e.EnableAutomaticStatusBack());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
private const string websiteString = "https://github.com/lukevp/ESC-POS-.NET/";
|
||||
public static byte[][] TwoDimensionCodes(ICommandEmitter e) => new byte[][] {
|
||||
e.PrintLine("PDF417:"),
|
||||
e.Print2DCode(TwoDimensionCodeType.PDF417, websiteString),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("PDF417 (TINY):"),
|
||||
e.Print2DCode(TwoDimensionCodeType.PDF417, websiteString, Size2DCode.TINY),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("PDF417 (LARGE):"),
|
||||
e.Print2DCode(TwoDimensionCodeType.PDF417, websiteString, Size2DCode.LARGE),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("QRCODE MODEL 1:"),
|
||||
e.Print2DCode(TwoDimensionCodeType.QRCODE_MODEL1, websiteString),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("QRCODE MODEL 2:"),
|
||||
e.PrintQRCode(websiteString),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("QRCODE MICRO:"),
|
||||
e.Print2DCode(TwoDimensionCodeType.QRCODE_MICRO, "github.com/lukevp"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("QRCODE MODEL 1 (TINY):"),
|
||||
e.Print2DCode(TwoDimensionCodeType.QRCODE_MODEL1, websiteString, Size2DCode.TINY),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("QRCODE MODEL 1 (LARGE):"),
|
||||
e.Print2DCode(TwoDimensionCodeType.QRCODE_MODEL1, websiteString, Size2DCode.LARGE),
|
||||
e.PrintLine()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] BarcodeStyles(ICommandEmitter e) => new byte[][] {
|
||||
//TODO: test all widths and put bar in front in label
|
||||
e.PrintLine("Thinnest Width:"),
|
||||
e.SetBarcodeHeightInDots(300),
|
||||
e.SetBarWidth(BarWidth.Thinnest),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Thin Width:"),
|
||||
e.SetBarcodeHeightInDots(300),
|
||||
e.SetBarWidth(BarWidth.Thin),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Default Width:"),
|
||||
e.SetBarcodeHeightInDots(300),
|
||||
e.SetBarWidth(BarWidth.Default),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Thicker Width:"),
|
||||
e.SetBarcodeHeightInDots(300),
|
||||
e.SetBarWidth(BarWidth.Thick),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Thickest Width:"),
|
||||
e.SetBarcodeHeightInDots(300),
|
||||
e.SetBarWidth(BarWidth.Thickest),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
|
||||
e.PrintLine("Short (50 dots):"),
|
||||
e.SetBarcodeHeightInDots(50),
|
||||
e.SetBarWidth(BarWidth.Default),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Tall (255 dots):"),
|
||||
e.SetBarcodeHeightInDots(255),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Label Above:"),
|
||||
e.SetBarcodeHeightInDots(50),
|
||||
e.SetBarLabelPosition(BarLabelPrintPosition.Above),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Label Above and Below:"),
|
||||
e.SetBarLabelPosition(BarLabelPrintPosition.Both),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Label Below:"),
|
||||
e.SetBarLabelPosition(BarLabelPrintPosition.Below),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905"),
|
||||
|
||||
e.PrintLine("Font B Label Below:"),
|
||||
e.SetBarLabelFontB(true),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "012345678905")
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] BarcodeTypes(ICommandEmitter e) => new byte[][] {
|
||||
e.SetBarcodeHeightInDots(600),
|
||||
e.SetBarWidth(BarWidth.Thinnest),
|
||||
e.SetBarLabelPosition(BarLabelPrintPosition.Below),
|
||||
|
||||
e.PrintLine("CODABAR_NW_7:"),
|
||||
e.PrintBarcode(BarcodeType.CODABAR_NW_7, "A31117013206375B"),
|
||||
|
||||
e.PrintLine("CODE128:"),
|
||||
e.PrintBarcode(BarcodeType.CODE128, "ESC_POS_NET"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("CODE128 Type C:"),
|
||||
e.PrintBarcode(BarcodeType.CODE128, "123456789101", BarcodeCode.CODE_C),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("CODE39:"),
|
||||
e.PrintBarcode(BarcodeType.CODE39, "*ESC-POS-NET*"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("CODE93:"),
|
||||
e.PrintBarcode(BarcodeType.CODE93, "*ESC_POS_NET*"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("GS1_128:"),
|
||||
e.PrintBarcode(BarcodeType.GS1_128, "(01)9501234567890*"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("GS1_DATABAR_EXPANDED:"),
|
||||
e.PrintBarcode(BarcodeType.GS1_DATABAR_EXPANDED, "0001234567890"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("GS1_DATABAR_LIMITED:"),
|
||||
e.PrintBarcode(BarcodeType.GS1_DATABAR_LIMITED, "0001234567890"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("GS1_DATABAR_OMNIDIRECTIONAL:"),
|
||||
e.PrintBarcode(BarcodeType.GS1_DATABAR_OMNIDIRECTIONAL, "0001234567890"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("GS1_DATABAR_TRUNCATED:"),
|
||||
e.PrintBarcode(BarcodeType.GS1_DATABAR_TRUNCATED, "0001234567890"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("ITF:"),
|
||||
e.PrintBarcode(BarcodeType.ITF, "1234567895"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("JAN13_EAN13:"),
|
||||
e.PrintBarcode(BarcodeType.JAN13_EAN13, "5901234123457"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("JAN8_EAN8:"),
|
||||
e.PrintBarcode(BarcodeType.JAN8_EAN8, "96385074"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("UPC_A:"),
|
||||
e.PrintBarcode(BarcodeType.UPC_A, "042100005264"),
|
||||
e.PrintLine(),
|
||||
|
||||
e.PrintLine("UPC_E:"),
|
||||
e.PrintBarcode(BarcodeType.UPC_E, "425261"),
|
||||
e.PrintLine()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] CashDrawerOpenPin2(ICommandEmitter e) => new byte[][] {
|
||||
e.CashDrawerOpenPin2()
|
||||
};
|
||||
|
||||
public static byte[][] CashDrawerOpenPin5(ICommandEmitter e) => new byte[][] {
|
||||
e.CashDrawerOpenPin5()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] CodePages(ICommandEmitter e, CodePage codePage) {
|
||||
List<byte[]> test = new List<byte[]>();
|
||||
test.Add(e.LeftAlign());
|
||||
test.Add(e.PrintLine("Empty space = space or non-printable character."));
|
||||
test.Add(e.PrintLine("Each row represents the first hex digit."));
|
||||
test.Add(e.PrintLine("Each column represents the second hex digit."));
|
||||
test.Add(e.PrintLine("For example, row 7, column A, represents"));
|
||||
test.Add(e.PrintLine("the character with hex 0x7A."));
|
||||
test.Add(e.PrintLine());
|
||||
test.Add(e.PrintLine("Character Table for Code Page:"));
|
||||
test.Add(e.PrintLine(codePage + " (Page " + ((int)codePage) + ")"));
|
||||
test.Add(e.PrintLine("=========================="));
|
||||
test.Add(e.PrintLine());
|
||||
test.Add(e.PrintLine(" 0 1 2 3 4 5 6 7 8 9 A B C D E F "));
|
||||
// Set CodePage to test codepage.
|
||||
test.Add(e.CodePage(codePage));
|
||||
for (int d1 = 0; d1 < 0x10; d1++)
|
||||
{
|
||||
|
||||
var upperDigit = d1.ToString("x1").ToUpperInvariant();
|
||||
test.Add(e.Print(upperDigit + " "));
|
||||
for (int d2 = 0; d2 < 0x10; d2++)
|
||||
{
|
||||
var digit = d1 * 0x10 + d2;
|
||||
if (digit <= 0x20) digit = 0x20;
|
||||
test.Add(e.Print((char)digit + " "));
|
||||
}
|
||||
test.Add(e.PrintLine());
|
||||
}
|
||||
// Set CodePage back to default
|
||||
test.Add(e.CodePage(CodePage.PC437_USA_STANDARD_EUROPE_DEFAULT));
|
||||
test.Add(e.PrintLine());
|
||||
return test.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
using System.IO;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] Images(ICommandEmitter e, bool isLegacy) => new byte[][] {
|
||||
e.CenterAlign(),
|
||||
e.PrintLine("Test PNG images with widths 100 - 600 px,"),
|
||||
e.PrintLine("at native resolution"),
|
||||
e.PrintLine("-- pd-logo-100.png --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-100.png"), true, isLegacy),
|
||||
e.PrintLine("-- pd-logo-200.png --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-200.png"), true, isLegacy),
|
||||
e.PrintLine("-- pd-logo-300.png --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy),
|
||||
e.PrintLine("-- pd-logo-400.png --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-400.png"), true, isLegacy),
|
||||
e.PrintLine("-- pd-logo-500.png --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-500.png"), true, isLegacy),
|
||||
e.PrintLine("-- pd-logo-600.png --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-600.png"), true, isLegacy),
|
||||
e.PrintLine("Test resizing 600 px image to 300px"),
|
||||
e.PrintLine("-- pd-logo-600.png /300 --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-600.png"), true, isLegacy, 300),
|
||||
e.PrintLine("Test image with taller height than width"),
|
||||
e.PrintLine("-- abe-lincoln.png /300 --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/abe-lincoln.png"), true, isLegacy, 300),
|
||||
e.PrintLine("Test 300px image resized to all remainders of 8,"),
|
||||
e.PrintLine("to ensure overflow checking"),
|
||||
e.PrintLine("-- pd-logo-300.png /296 (0 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 296),
|
||||
e.PrintLine("-- pd-logo-300.png /297 (1 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 297),
|
||||
e.PrintLine("-- pd-logo-300.png /298 (2 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 298),
|
||||
e.PrintLine("-- pd-logo-300.png /299 (3 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 299),
|
||||
e.PrintLine("-- pd-logo-300.png /300 (4 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 300),
|
||||
e.PrintLine("-- pd-logo-300.png /301 (5 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 301),
|
||||
e.PrintLine("-- pd-logo-300.png /302 (6 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 302),
|
||||
e.PrintLine("-- pd-logo-300.png /303 (7 remainder) --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true, isLegacy, 303),
|
||||
e.PrintLine("Test 300px image in JPG format"),
|
||||
e.PrintLine("-- pd-logo-300.jpg --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.jpg"), true, isLegacy),
|
||||
e.PrintLine("Test 300px image in BMP format"),
|
||||
e.PrintLine("-- pd-logo-300.jpg --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.bmp"), true, isLegacy),
|
||||
e.PrintLine("Test 300px image in GIF format"),
|
||||
e.PrintLine("-- pd-logo-300.jpg --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.gif"), true, isLegacy),
|
||||
e.PrintLine("Test full color image converted"),
|
||||
e.PrintLine("to black and white and interpolated"),
|
||||
e.PrintLine("-- kitten.jpg --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/kitten.jpg"), true, isLegacy, 500),
|
||||
e.PrintLine("-- portal companion cube.jpg --"),
|
||||
e.PrintImage(File.ReadAllBytes("images/Portal_Companion_Cube.jpg"), true, isLegacy, 500)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[] TestLargeByteArrays(ICommandEmitter e)
|
||||
{
|
||||
var kitten = e.PrintImage(File.ReadAllBytes("images/kitten.jpg"), true, true, 500);
|
||||
var cube = e.PrintImage(File.ReadAllBytes("images/Portal_Companion_Cube.jpg"), true, true, 500);
|
||||
var expectedResult = ByteSplicer.Combine(
|
||||
e.CenterAlign(),
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube,
|
||||
kitten,
|
||||
cube
|
||||
);
|
||||
MemoryPrinter mp = new MemoryPrinter();
|
||||
mp.Write(expectedResult);
|
||||
var response = mp.GetAllData();
|
||||
bool hasErrors = false;
|
||||
if (expectedResult.Length != response.Length)
|
||||
{
|
||||
Console.WriteLine($"Error: MemoryPrinter length mismatch - ${response.Length}, expected ${expectedResult.Length}");
|
||||
hasErrors = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < expectedResult.Length; i++)
|
||||
{
|
||||
if (expectedResult[i] != response[i])
|
||||
{
|
||||
Console.WriteLine($"Error: MemoryPrinter data mismatch - ${expectedResult[i]}, expected ${response[i]}, at location ${i}");
|
||||
hasErrors = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasErrors)
|
||||
{
|
||||
Console.WriteLine("MemoryPrinter: ALL OK!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("MemoryPrinter: Errors occured during testing, aborting!");
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
Random r = new Random();
|
||||
var filename = $"{r.NextDouble().ToString()}.tmp";
|
||||
using (FilePrinter fp = new FilePrinter(filename, true))
|
||||
{
|
||||
fp.Write(expectedResult);
|
||||
}
|
||||
response = File.ReadAllBytes(filename);
|
||||
hasErrors = false;
|
||||
if (expectedResult.Length != response.Length)
|
||||
{
|
||||
Console.WriteLine($"Error: FilePrinter length mismatch - ${response.Length}, expected ${expectedResult.Length}");
|
||||
hasErrors = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < expectedResult.Length; i++)
|
||||
{
|
||||
if (expectedResult[i] != response[i])
|
||||
{
|
||||
Console.WriteLine($"Error: FilePrinter data mismatch - ${expectedResult[i]}, expected ${response[i]}, at location ${i}");
|
||||
hasErrors = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasErrors)
|
||||
{
|
||||
Console.WriteLine("FilePrinter: ALL OK!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("FilePrinter: Errors occured during testing, aborting!");
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
return expectedResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] LineSpacing(ICommandEmitter e) => new byte[][] {
|
||||
e.SetLineSpacingInDots(200),
|
||||
e.PrintLine("This is the default spacing."),
|
||||
e.SetLineSpacingInDots(15),
|
||||
e.PrintLine("This has 200 dots of spacing above."),
|
||||
e.ResetLineSpacing(),
|
||||
e.PrintLine("This has 15 dots of spacing above."),
|
||||
e.PrintLine("This has the default spacing.")
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] MultiLinePrinting(ICommandEmitter e) => new byte[][] {
|
||||
e.Print("Multiline Test: Windows...\r\nOSX...\rUnix...\n"),
|
||||
//TODO: sanitize test.
|
||||
e.PrintLine("Feeding 250 dots."),
|
||||
e.FeedDots(250),
|
||||
e.PrintLine("Feeding 3 lines."),
|
||||
e.FeedLines(3),
|
||||
e.PrintLine("Done Feeding."),
|
||||
e.PrintLine("Reverse Feeding 6 lines."),
|
||||
e.FeedLinesReverse(6),
|
||||
e.PrintLine("Done Reverse Feeding.")
|
||||
};
|
||||
|
||||
public static byte[][] SingleLinePrinting(ICommandEmitter e) => new byte[][] {
|
||||
e.Print("Single Test Line Of Text\r\n"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
using System.IO;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] Receipt(ICommandEmitter e) => new byte[][] {
|
||||
e.CenterAlign(),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true),
|
||||
e.PrintLine(),
|
||||
e.SetBarcodeHeightInDots(360),
|
||||
e.SetBarWidth(BarWidth.Default),
|
||||
e.SetBarLabelPosition(BarLabelPrintPosition.None),
|
||||
e.PrintBarcode(BarcodeType.ITF, "0123456789"),
|
||||
e.PrintLine("B&H PHOTO & VIDEO"),
|
||||
e.PrintLine("420 NINTH AVE."),
|
||||
e.PrintLine("NEW YORK, NY 10001"),
|
||||
e.PrintLine("(212) 502-6380 - (800)947-9975"),
|
||||
e.SetStyles(PrintStyle.Underline),
|
||||
e.PrintLine("www.bhphotovideo.com"),
|
||||
e.SetStyles(PrintStyle.None),
|
||||
e.PrintLine(),
|
||||
e.LeftAlign(),
|
||||
e.PrintLine("Order: 123456789 Date: 02/01/19"),
|
||||
e.PrintLine(),
|
||||
e.PrintLine(),
|
||||
e.SetStyles(PrintStyle.FontB),
|
||||
e.PrintLine("1 TRITON LOW-NOISE IN-LINE MICROPHONE PREAMP"),
|
||||
e.PrintLine(" TRFETHEAD/FETHEAD 89.95 89.95"),
|
||||
e.PrintLine("----------------------------------------------------------------"),
|
||||
e.RightAlign(),
|
||||
e.PrintLine("SUBTOTAL 89.95"),
|
||||
e.PrintLine("Total Order: 89.95"),
|
||||
e.PrintLine("Total Payment: 89.95"),
|
||||
e.PrintLine(),
|
||||
e.LeftAlign(),
|
||||
e.SetStyles(PrintStyle.Bold | PrintStyle.FontB),
|
||||
e.PrintLine("SOLD TO: SHIP TO:"),
|
||||
e.SetStyles(PrintStyle.FontB),
|
||||
e.PrintLine(" LUKE PAIREEPINART LUKE PAIREEPINART"),
|
||||
e.PrintLine(" 123 FAKE ST. 123 FAKE ST."),
|
||||
e.PrintLine(" DECATUR, IL 12345 DECATUR, IL 12345"),
|
||||
e.PrintLine(" (123)456-7890 (123)456-7890"),
|
||||
e.PrintLine(" CUST: 87654321"),
|
||||
e.PrintLine(),
|
||||
e.PrintLine()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using ESCPOS_NET.Utilities;
|
||||
|
||||
namespace ESCPOS_NET.ConsoleTest
|
||||
{
|
||||
|
||||
public static partial class Tests
|
||||
{
|
||||
public static byte[][] TextStyles(ICommandEmitter e) => new byte[][] {
|
||||
e.SetStyles(PrintStyle.None),
|
||||
e.Print("Default: The quick brown fox jumped over the lazy dogs.\n"),
|
||||
e.SetStyles(PrintStyle.FontB),
|
||||
e.Print("Font B: The quick brown fox jumped over the lazy dogs.\n"),
|
||||
e.SetStyles(PrintStyle.Bold),
|
||||
e.Print("Bold: The quick brown fox jumped over the lazy dogs.\n"),
|
||||
e.SetStyles(PrintStyle.Underline),
|
||||
e.Print("Underline: The quick brown fox jumped over the lazy dogs.\n"),
|
||||
e.SetStyles(PrintStyle.DoubleWidth),
|
||||
e.Print("DoubleWidth: The quick brown fox jumped over the lazy dogs.\n"),
|
||||
e.SetStyles(PrintStyle.DoubleHeight),
|
||||
e.Print("DoubleHeight: The quick brown fox jumped over the lazy dogs.\n"),
|
||||
e.SetStyles(PrintStyle.FontB | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth | PrintStyle.Underline | PrintStyle.Bold),
|
||||
e.Print("All Styles: The quick brown fox jumped over the lazy dogs.\n"),
|
||||
e.SetStyles(PrintStyle.None),
|
||||
e.ReverseMode(true),
|
||||
e.PrintLine("REVERSE MODE: The quick brown fox jumped over the lazy dogs."),
|
||||
e.SetStyles(PrintStyle.FontB | PrintStyle.DoubleHeight | PrintStyle.DoubleWidth),
|
||||
e.PrintLine("REVERSE MODE: The quick brown fox jumped over the lazy dogs."),
|
||||
e.SetStyles(PrintStyle.None),
|
||||
e.ReverseMode(false),
|
||||
e.SetStyles(PrintStyle.None),
|
||||
e.RightCharacterSpacing(5),
|
||||
e.PrintLine("Right space 5: The quick brown fox jumped over the lazy dogs."),
|
||||
e.RightCharacterSpacing(0),
|
||||
e.SetStyles(PrintStyle.None),
|
||||
e.UpsideDownMode(true),
|
||||
e.PrintLine("Upside Down Mode: The quick brown fox jumped over the lazy dogs."),
|
||||
e.UpsideDownMode(false)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 27 KiB |
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
|
||||
<svg
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:ns1="http://sozi.baierouge.fr"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
id="Layer_1"
|
||||
sodipodi:docname="public-domain-logo-slightly-nicer.svg"
|
||||
enable-background="new 0.995 1.495 88 31"
|
||||
xml:space="preserve"
|
||||
viewBox="0.995 1.495 671.6875 215.625"
|
||||
version="1.1"
|
||||
y="0px"
|
||||
x="0px"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
><sodipodi:namedview
|
||||
id="namedview43"
|
||||
fit-margin-left="0"
|
||||
inkscape:zoom="0.3"
|
||||
borderopacity="1"
|
||||
inkscape:current-layer="Layer_1"
|
||||
inkscape:cx="450.19344"
|
||||
inkscape:cy="-104.995"
|
||||
inkscape:window-maximized="1"
|
||||
showgrid="false"
|
||||
fit-margin-right="0"
|
||||
bordercolor="#666666"
|
||||
inkscape:window-x="0"
|
||||
guidetolerance="10"
|
||||
objecttolerance="10"
|
||||
inkscape:window-y="24"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
pagecolor="#ffffff"
|
||||
gridtolerance="10"
|
||||
inkscape:window-height="1124"
|
||||
showborder="false"
|
||||
fit-margin-top="0"
|
||||
/>
|
||||
<g
|
||||
id="g4285"
|
||||
transform="translate(-224.16 380.12)"
|
||||
><rect
|
||||
id="rect3914-6"
|
||||
style="stroke-linejoin:round;fill-rule:evenodd;stroke:#000000;stroke-linecap:round;stroke-width:4.9835;fill:#ffffff"
|
||||
rx="16.992"
|
||||
ry="13.212"
|
||||
height="210.65"
|
||||
width="666.71"
|
||||
y="-376.14"
|
||||
x="227.64"
|
||||
/><path
|
||||
id="path11-9-3-7"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m411.62-355.34c25.35 19.694 41.867 51.242 41.874 86.922-0.008 32.459-13.679 61.507-35.231 81.323h457.33v-168.24h-463.97z"
|
||||
/><g
|
||||
id="g15-9-3-0"
|
||||
transform="matrix(8.4847 0 0 8.4847 226.81 -409.82)"
|
||||
><path
|
||||
id="path17-8-7-0"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m36.739 8.557c0.392 0 0.728 0.059 1.002 0.173 0.276 0.116 0.5 0.268 0.674 0.456 0.173 0.189 0.299 0.405 0.379 0.647 0.079 0.241 0.118 0.493 0.118 0.753 0 0.253-0.039 0.503-0.118 0.749-0.08 0.244-0.206 0.462-0.379 0.65-0.174 0.188-0.397 0.341-0.674 0.456-0.274 0.115-0.61 0.173-1.002 0.173h-1.452v2.267h-1.382v-6.324h2.834zm-0.379 2.976c0.158 0 0.312-0.012 0.457-0.035 0.147-0.023 0.276-0.069 0.388-0.137 0.111-0.068 0.201-0.164 0.269-0.288s0.101-0.287 0.101-0.487c0-0.201-0.033-0.363-0.101-0.488-0.067-0.123-0.157-0.22-0.269-0.286-0.111-0.069-0.24-0.114-0.388-0.138-0.146-0.024-0.299-0.036-0.457-0.036h-1.073v1.896l1.073-0.001z"
|
||||
/><path
|
||||
id="path19-2-5-5"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m44.751 14.398c-0.476 0.417-1.133 0.625-1.972 0.625-0.851 0-1.509-0.207-1.976-0.62-0.466-0.413-0.699-1.052-0.699-1.913v-3.933h1.381v3.934c0 0.171 0.016 0.339 0.045 0.506 0.029 0.165 0.091 0.311 0.185 0.438 0.094 0.125 0.225 0.229 0.392 0.309s0.392 0.119 0.673 0.119c0.493 0 0.833-0.109 1.021-0.332 0.188-0.221 0.282-0.568 0.282-1.04v-3.934h1.382v3.934c-0.001 0.855-0.239 1.491-0.714 1.907z"
|
||||
/><path
|
||||
id="path21-0-4-6"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m50.069 8.557c0.301 0 0.572 0.027 0.817 0.081 0.246 0.053 0.459 0.14 0.636 0.26 0.176 0.121 0.312 0.282 0.407 0.483 0.099 0.201 0.146 0.45 0.146 0.745 0 0.318-0.071 0.584-0.217 0.796-0.144 0.212-0.355 0.388-0.637 0.522 0.387 0.112 0.676 0.309 0.865 0.589 0.191 0.281 0.286 0.619 0.286 1.015 0 0.319-0.062 0.595-0.185 0.829-0.123 0.232-0.289 0.422-0.498 0.57-0.207 0.148-0.445 0.257-0.713 0.328-0.269 0.07-0.541 0.105-0.822 0.105h-3.044v-6.323h2.959zm-0.173 2.56c0.246 0 0.447-0.059 0.606-0.178 0.157-0.118 0.237-0.309 0.237-0.576 0-0.147-0.026-0.269-0.08-0.362-0.053-0.095-0.122-0.168-0.211-0.222-0.088-0.053-0.188-0.09-0.303-0.109-0.115-0.022-0.233-0.032-0.356-0.032h-1.294v1.479h1.401zm0.078 2.685c0.135 0 0.264-0.014 0.387-0.04 0.125-0.026 0.231-0.072 0.326-0.133 0.094-0.062 0.168-0.147 0.227-0.254 0.056-0.104 0.083-0.241 0.083-0.406 0-0.325-0.093-0.557-0.271-0.696-0.184-0.138-0.425-0.208-0.724-0.208h-1.505v1.737h1.477z"
|
||||
/><path
|
||||
id="path23-9-1-0"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m55.142 8.557v5.155h3.062v1.169h-4.444v-6.324h1.382z"
|
||||
/><path
|
||||
id="path25-4-8-8"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m60.748 8.557v6.324h-1.382v-6.324h1.382z"
|
||||
/><path
|
||||
id="path27-9-0-7"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m66.45 10.244c-0.082-0.132-0.184-0.248-0.307-0.349-0.125-0.101-0.265-0.179-0.421-0.235-0.153-0.057-0.315-0.085-0.487-0.085-0.312 0-0.574 0.062-0.791 0.183-0.217 0.12-0.396 0.283-0.527 0.486-0.137 0.204-0.232 0.436-0.296 0.695-0.062 0.26-0.093 0.529-0.093 0.806 0 0.267 0.031 0.525 0.093 0.776s0.159 0.477 0.296 0.677c0.134 0.201 0.311 0.361 0.527 0.483 0.217 0.12 0.479 0.181 0.791 0.181 0.424 0 0.754-0.129 0.99-0.389s0.383-0.602 0.437-1.028h1.337c-0.034 0.396-0.126 0.753-0.271 1.072-0.146 0.318-0.34 0.591-0.58 0.815s-0.521 0.395-0.846 0.513c-0.322 0.119-0.678 0.178-1.064 0.178-0.48 0-0.914-0.084-1.299-0.252-0.383-0.17-0.709-0.399-0.972-0.696-0.265-0.295-0.468-0.641-0.606-1.04-0.143-0.399-0.213-0.829-0.213-1.29 0-0.472 0.07-0.91 0.213-1.314 0.141-0.404 0.344-0.757 0.606-1.058 0.263-0.302 0.589-0.537 0.972-0.709 0.385-0.172 0.816-0.258 1.299-0.258 0.347 0 0.675 0.051 0.98 0.15 0.309 0.102 0.583 0.248 0.827 0.439 0.243 0.191 0.444 0.43 0.603 0.713 0.16 0.283 0.258 0.608 0.301 0.974h-1.339c-0.024-0.159-0.078-0.305-0.16-0.438z"
|
||||
/><path
|
||||
id="path29-7-0-4"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m36.615 17.415c0.405 0 0.782 0.064 1.131 0.193 0.35 0.131 0.651 0.326 0.906 0.586s0.455 0.584 0.599 0.975c0.144 0.389 0.216 0.848 0.216 1.372 0 0.462-0.059 0.888-0.176 1.274-0.118 0.391-0.295 0.728-0.532 1.012-0.238 0.283-0.534 0.506-0.89 0.668-0.354 0.162-0.772 0.244-1.254 0.244h-2.71v-6.324h2.71zm-0.096 5.154c0.199 0 0.393-0.031 0.581-0.097s0.354-0.174 0.502-0.323c0.146-0.151 0.264-0.349 0.352-0.59 0.088-0.242 0.132-0.537 0.132-0.887 0-0.316-0.031-0.605-0.093-0.863-0.062-0.257-0.162-0.478-0.304-0.658-0.141-0.186-0.326-0.324-0.559-0.422-0.231-0.099-0.517-0.146-0.858-0.146h-0.984v3.984h1.231v0.002z"
|
||||
/><path
|
||||
id="path31-9-8-2"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m40.8 19.289c0.141-0.405 0.344-0.759 0.606-1.06 0.265-0.304 0.589-0.537 0.973-0.709 0.385-0.172 0.816-0.258 1.298-0.258 0.487 0 0.921 0.086 1.303 0.258 0.383 0.172 0.705 0.405 0.969 0.709 0.265 0.301 0.467 0.652 0.605 1.06 0.143 0.403 0.213 0.843 0.213 1.313 0 0.461-0.07 0.892-0.213 1.288-0.141 0.397-0.343 0.746-0.605 1.041-0.264 0.296-0.586 0.526-0.969 0.694-0.382 0.168-0.814 0.253-1.303 0.253-0.481 0-0.913-0.085-1.298-0.253-0.384-0.168-0.708-0.398-0.973-0.694-0.263-0.295-0.466-0.644-0.606-1.041-0.141-0.396-0.211-0.827-0.211-1.288 0-0.47 0.07-0.91 0.211-1.313zm1.262 2.089c0.062 0.252 0.16 0.479 0.295 0.68 0.135 0.199 0.312 0.36 0.527 0.48 0.218 0.121 0.481 0.184 0.792 0.184 0.312 0 0.576-0.062 0.792-0.184 0.219-0.12 0.395-0.281 0.529-0.48 0.134-0.201 0.232-0.428 0.295-0.68 0.062-0.25 0.092-0.509 0.092-0.773 0-0.276-0.029-0.547-0.092-0.807-0.062-0.261-0.161-0.49-0.295-0.695-0.137-0.203-0.312-0.365-0.529-0.486-0.216-0.12-0.48-0.182-0.792-0.182-0.311 0-0.574 0.062-0.792 0.182-0.216 0.121-0.393 0.283-0.527 0.486-0.135 0.205-0.233 0.437-0.295 0.695s-0.093 0.527-0.093 0.807c0.001 0.264 0.032 0.523 0.093 0.773z"
|
||||
/><path
|
||||
id="path33-4-9-1"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m50.092 17.415 1.47 4.35h0.021l1.391-4.35h1.944v6.324h-1.294v-4.482h-0.019l-1.541 4.482h-1.062l-1.54-4.438h-0.019v4.438h-1.295v-6.324h1.944z"
|
||||
/><path
|
||||
id="path35-8-7-3"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m59.765 17.415 2.35 6.324h-1.436l-0.475-1.408h-2.35l-0.494 1.408h-1.392l2.377-6.324h1.42zm0.079 3.88-0.793-2.321h-0.019l-0.816 2.321h1.628z"
|
||||
/><path
|
||||
id="path37-6-1-3"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m64.547 17.415v6.324h-1.382v-6.324h1.382z"
|
||||
/><path
|
||||
id="path39-3-0-1"
|
||||
style="fill:#ffffff"
|
||||
inkscape:connector-curvature="0"
|
||||
d="m67.603 17.415 2.623 4.242h0.018v-4.242h1.295v6.324h-1.383l-2.613-4.234h-0.018v4.234h-1.295v-6.324h1.373z"
|
||||
/></g
|
||||
><path
|
||||
id="path3912-1-5"
|
||||
d="m336.08-360.91c-51.67 0-93.562 40.444-93.562 90.336 0 49.885 41.892 90.336 93.57 90.336 51.67 0 93.562-40.452 93.562-90.336-0.008-49.893-41.9-90.336-93.57-90.336z"
|
||||
style="stroke:#000000;stroke-width:10.267;fill:none"
|
||||
inkscape:connector-curvature="0"
|
||||
/><path
|
||||
id="path27-9-4-1-6"
|
||||
d="m359.71-299.7c-1.4695-2.3655-3.2974-4.4444-5.5016-6.2543-2.2401-1.81-4.7489-3.2077-7.5445-4.2113-2.7418-1.0215-5.645-1.5232-8.7273-1.5232-5.5912 0-10.286 1.111-14.175 3.2794-3.8887 2.1505-7.0965 5.0715-9.444 8.7094-2.4552 3.6558-4.1576 7.8133-5.3045 12.455-1.1111 4.6593-1.6666 9.4799-1.6666 14.444 0 4.7848 0.55549 9.4082 1.6666 13.906 1.1111 4.498 2.8494 8.5481 5.3045 12.132 2.4013 3.602 5.5732 6.4693 9.444 8.6556 3.8888 2.1505 8.5839 3.2436 14.175 3.2436 7.5983 0 13.512-2.3117 17.741-6.9711 4.2293-4.6593 6.8635-10.788 7.8313-18.422h23.96c-0.60926 7.0965-2.258 13.494-4.8564 19.211-2.6164 5.6987-6.093 10.591-10.394 14.605-4.3009 4.0142-9.3366 7.0786-15.161 9.1933-5.7704 2.1325-12.15 3.1898-19.067 3.1898-8.6019 0-16.379-1.5053-23.279-4.5159-6.8635-3.0465-12.706-7.1503-17.419-12.473-4.749-5.2866-8.3868-11.487-10.86-18.637-2.5626-7.1503-3.817-14.856-3.817-23.117 0-8.4585 1.2544-16.308 3.817-23.547 2.5268-7.2399 6.1647-13.566 10.86-18.96 4.7131-5.412 10.555-9.6233 17.419-12.706 6.8994-3.0823 14.623-4.6235 23.279-4.6235 6.2184 0 12.096 0.91395 17.562 2.6881 5.5374 1.8279 10.448 4.4443 14.82 7.8671 4.3547 3.4228 7.9568 7.7058 10.806 12.777 2.8672 5.0715 4.6235 10.896 5.394 17.455h-23.996c-0.42988-2.8493-1.3978-5.4658-2.8673-7.8492z"
|
||||
style="fill:#000000"
|
||||
inkscape:connector-curvature="0"
|
||||
/><path
|
||||
id="path4039-5-1"
|
||||
d="m250.51-308.07 174.92 51.631"
|
||||
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:10.267;fill:none"
|
||||
inkscape:connector-curvature="0"
|
||||
/></g
|
||||
><metadata
|
||||
><rdf:RDF
|
||||
><cc:Work
|
||||
><dc:format
|
||||
>image/svg+xml</dc:format
|
||||
><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
|
||||
/><cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
|
||||
/><dc:publisher
|
||||
><cc:Agent
|
||||
rdf:about="http://openclipart.org/"
|
||||
><dc:title
|
||||
>Openclipart</dc:title
|
||||
></cc:Agent
|
||||
></dc:publisher
|
||||
></cc:Work
|
||||
><cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/publicdomain/"
|
||||
><cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction"
|
||||
/><cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution"
|
||||
/><cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
|
||||
/></cc:License
|
||||
></rdf:RDF
|
||||
></metadata
|
||||
></svg
|
||||
>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,40 @@
|
||||
// This code is adapted from a sample found at the URL
|
||||
// "http://blogs.msdn.com/b/jmanning/archive/2004/12/19/325699.aspx"
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace TcpEchoServer
|
||||
{
|
||||
public class TcpEchoServer
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
Console.WriteLine("Starting echo server...");
|
||||
|
||||
int port = 9100;
|
||||
TcpListener listener = new TcpListener(IPAddress.Loopback, port);
|
||||
listener.Start();
|
||||
|
||||
TcpClient client = listener.AcceptTcpClient();
|
||||
NetworkStream stream = client.GetStream();
|
||||
StreamWriter writer = new StreamWriter(stream, Encoding.ASCII) { AutoFlush = true };
|
||||
StreamReader reader = new StreamReader(stream, Encoding.ASCII);
|
||||
|
||||
while (true)
|
||||
{
|
||||
string inputLine = "";
|
||||
while (inputLine != null)
|
||||
{
|
||||
inputLine = reader.ReadLine();
|
||||
writer.Write("E");
|
||||
Console.WriteLine("Echoing string: " + inputLine);
|
||||
}
|
||||
Console.WriteLine("Server saw disconnect from client.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="1.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ESCPOS_NET\ESCPOS_NET.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,77 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using Xunit;
|
||||
|
||||
namespace ESCPOS_NET.UnitTest.EmittersBased.EPSONTests
|
||||
{
|
||||
public class BarCode
|
||||
{
|
||||
private const string WEBSITE_STRING = "https://github.com/lukevp/ESC-POS-.NET/";
|
||||
|
||||
[Theory]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL1, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_15)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_25)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_30)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.EXTRA, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.LARGE, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.NORMAL, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.SMALL, CorrectionLevel2DCode.PERCENT_7)]
|
||||
[InlineData(TwoDimensionCodeType.QRCODE_MICRO, Size2DCode.TINY, CorrectionLevel2DCode.PERCENT_7)]
|
||||
public void PrintQRCode_Success(TwoDimensionCodeType codeType, Size2DCode size2DCode, CorrectionLevel2DCode correctionLevel2DCode)
|
||||
{
|
||||
var result = new byte[] { 29, 40, 107, 4, 0, 49, 65, (byte)codeType, 0, 29, 40, 107, 3, 0, 49, 67, (byte)size2DCode, 29, 40, 107, 3, 0, 49, 69, (byte)correctionLevel2DCode, 29, 40, 107, 42, 0, 49, 80, 48, 104, 116, 116, 112, 115, 58, 47, 47, 103, 105, 116, 104, 117, 98, 46, 99, 111, 109, 47, 108, 117, 107, 101, 118, 112, 47, 69, 83, 67, 45, 80, 79, 83, 45, 46, 78, 69, 84, 47, 29, 40, 107, 3, 0, 49, 81, 48 };
|
||||
Assert.Equal(result, new EPSON().Print2DCode(codeType, WEBSITE_STRING, size2DCode, correctionLevel2DCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Xunit;
|
||||
|
||||
namespace ESCPOS_NET.UnitTest.GlobalTests
|
||||
{
|
||||
public class Barcode
|
||||
{
|
||||
private const string WEBSITE_STRING = "https://github.com/lukevp/ESC-POS-.NET/";
|
||||
|
||||
[Theory]
|
||||
[InlineData("EPSON", TwoDimensionCodeType.QRCODE_MODEL1)]
|
||||
[InlineData("EPSON", TwoDimensionCodeType.QRCODE_MODEL2)]
|
||||
[InlineData("EPSON", TwoDimensionCodeType.QRCODE_MICRO)]
|
||||
[InlineData("EPSON", null)]
|
||||
public void PrintQRCode_Success(string emitter, TwoDimensionCodeType? codeType)
|
||||
{
|
||||
var type = Assembly.LoadFrom("ESCPOS_NET").GetType($"ESCPOS_NET.Emitters.{emitter}", true);
|
||||
ICommandEmitter e = (ICommandEmitter)Activator.CreateInstance(type);
|
||||
|
||||
byte[] bytes;
|
||||
if (codeType is TwoDimensionCodeType codeTypeValue)
|
||||
bytes = e.PrintQRCode(WEBSITE_STRING, codeTypeValue);
|
||||
else
|
||||
bytes = e.PrintQRCode(WEBSITE_STRING);
|
||||
|
||||
Assert.True(bytes.Length > 0);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("EPSON", TwoDimensionCodeType.PDF417)]
|
||||
public void PrintQRCode_Failure(string emitter, TwoDimensionCodeType codeType)
|
||||
{
|
||||
var type = Assembly.LoadFrom("ESCPOS_NET").GetType($"ESCPOS_NET.Emitters.{emitter}", true);
|
||||
ICommandEmitter e = (ICommandEmitter)Activator.CreateInstance(type);
|
||||
Assert.Throws<ArgumentException>(() => e.PrintQRCode(WEBSITE_STRING, codeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31515.178
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ESCPOS_NET", "ESCPOS_NET\ESCPOS_NET.csproj", "{BA181101-43A5-435E-8744-ACDA313D04D8}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ESCPOS_NET.ConsoleTest", "ESCPOS_NET.ConsoleTest\ESCPOS_NET.ConsoleTest.csproj", "{958464FE-6B30-4BA7-A4B1-D63ED2E23158}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ESCPOS_NET.UnitTest", "ESCPOS_NET.UnitTest\ESCPOS_NET.UnitTest.csproj", "{8A848879-9776-4EBC-8484-41B8EE65FD8D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BA181101-43A5-435E-8744-ACDA313D04D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BA181101-43A5-435E-8744-ACDA313D04D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BA181101-43A5-435E-8744-ACDA313D04D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BA181101-43A5-435E-8744-ACDA313D04D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{958464FE-6B30-4BA7-A4B1-D63ED2E23158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{958464FE-6B30-4BA7-A4B1-D63ED2E23158}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{958464FE-6B30-4BA7-A4B1-D63ED2E23158}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{958464FE-6B30-4BA7-A4B1-D63ED2E23158}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8A848879-9776-4EBC-8484-41B8EE65FD8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8A848879-9776-4EBC-8484-41B8EE65FD8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8A848879-9776-4EBC-8484-41B8EE65FD8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A848879-9776-4EBC-8484-41B8EE65FD8D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {FB679B5F-BE89-407A-820F-185FE53B15C5}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,182 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
/* FROM: https://www.codeproject.com/Tips/674256/ByteArrayBuilder-a-StringBuilder-for-Bytes 2/9/2019 */
|
||||
namespace ESCPOS_NET.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides similar functionality to a StringBuilder, but for bytes.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// To fill the builder, construct a new, empty builder, and call the
|
||||
/// appropriate Append method overloads.
|
||||
/// To read data from the builder, either use Rewind on an existing
|
||||
/// builder, or construct a new builder by passing it the byte array
|
||||
/// from a previous builder - which you can get with the ToArray
|
||||
/// method.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
///
|
||||
/// ByteArrayBuilder bab = new ByteArrayBuilder();
|
||||
/// string[] lines = File.ReadAllLines(@"D:\Temp\myText.txt");
|
||||
/// bab.Append(lines.Length);
|
||||
/// foreach (string s in lines)
|
||||
/// {
|
||||
/// bab.Append(s);
|
||||
/// }
|
||||
/// byte[] data = bab.ToArray();
|
||||
/// ...
|
||||
/// ByteArrayBuilder babOut = new ByteArrayBuilder(data);
|
||||
/// int count = bab.GetInt();
|
||||
/// string[] linesOut = new string[count];
|
||||
/// for (int lineNo = 0; lineNo < count; lineNo++)
|
||||
/// {
|
||||
/// linesOut[lineNo](babOut.GetString());
|
||||
/// }
|
||||
/// .
|
||||
/// </example>
|
||||
public class ByteArrayBuilder : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// True in a byte form of the Line.
|
||||
/// </summary>
|
||||
private const byte StreamTrue = (byte)1;
|
||||
|
||||
/// <summary>
|
||||
/// False in the byte form of a line.
|
||||
/// </summary>
|
||||
private const byte StreamFalse = (byte)0;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the actual bytes.
|
||||
/// </summary>
|
||||
private MemoryStream store = new MemoryStream();
|
||||
|
||||
/// <summary>
|
||||
/// Gets bytes in the store.
|
||||
/// </summary>
|
||||
public int Length => (int)store.Length;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty builder ready to be filled.
|
||||
/// </summary>
|
||||
public ByteArrayBuilder()
|
||||
{
|
||||
}
|
||||
|
||||
public ByteArrayBuilder Append(byte b)
|
||||
{
|
||||
AddBytes(new byte[] { b });
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an IEnumerable of bytes to an array.
|
||||
/// </summary>
|
||||
/// <param name="b">Value to append to existing builder data.</param>
|
||||
/// </param>
|
||||
public ByteArrayBuilder Append(IEnumerable<byte> b)
|
||||
{
|
||||
if (b is byte[])
|
||||
{
|
||||
AddBytes((byte[])b);
|
||||
return this;
|
||||
}
|
||||
|
||||
AddBytes(b.ToArray());
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all content from the builder.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
store.Close();
|
||||
store.Dispose();
|
||||
store = new MemoryStream();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewind the builder ready to read data.
|
||||
/// </summary>
|
||||
public void Rewind()
|
||||
{
|
||||
store.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set an absolute position in the builder.
|
||||
/// **WARNING**
|
||||
/// If you add any variable size objects to the builder, the results of
|
||||
/// reading after a Seek to a non-zero value are unpredictable.
|
||||
/// A builder does not store just objects - for some it stores additional
|
||||
/// information as well.
|
||||
/// </summary>
|
||||
/// <param name="position">the position to seek.</param>
|
||||
public void Seek(int position)
|
||||
{
|
||||
store.Seek((long)position, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the builder as an array of bytes.
|
||||
/// </summary>
|
||||
/// <returns>An array.</returns>
|
||||
public byte[] ToArray()
|
||||
{
|
||||
byte[] data = new byte[Length];
|
||||
Array.Copy(store.GetBuffer(), data, Length);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a text based (Base64) string version of the current content.
|
||||
/// </summary>
|
||||
/// <returns>The converted string.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return Convert.ToBase64String(ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a string of raw bytes to the store.
|
||||
/// </summary>
|
||||
/// <param name="byteArray">the byte array.</param>
|
||||
private void AddBytes(byte[] byteArray)
|
||||
{
|
||||
store.Write(byteArray, 0, byteArray.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a specific number of bytes from the store.
|
||||
/// </summary>
|
||||
/// <param name="length">The length.</param>
|
||||
/// <returns>The byte array.</returns>
|
||||
private byte[] GetBytes(int length)
|
||||
{
|
||||
byte[] data = new byte[length];
|
||||
if (length > 0)
|
||||
{
|
||||
int read = store.Read(data, 0, length);
|
||||
if (read != length)
|
||||
{
|
||||
throw new ApplicationException("Buffer did not contain " + length + " bytes");
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose of this builder and its resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
store.Close();
|
||||
store.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public static class ByteExtensions
|
||||
{
|
||||
public static bool IsBitSet(this byte b, int offset)
|
||||
{
|
||||
return (b & (1 << offset)) != 0;
|
||||
}
|
||||
|
||||
public static bool IsBitNotSet(this byte b, int offset)
|
||||
{
|
||||
return (b & (1 << offset)) == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace ESCPOS_NET.Utilities
|
||||
{
|
||||
public static class ByteSplicer
|
||||
{
|
||||
public static byte[] Combine(params byte[][] byteArrays)
|
||||
{
|
||||
ByteArrayBuilder builder = new ByteArrayBuilder();
|
||||
foreach (var byteArray in byteArrays)
|
||||
{
|
||||
builder.Append(byteArray);
|
||||
}
|
||||
return builder.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ESCPOS_NET.DataValidation
|
||||
{
|
||||
public class DataConstraint
|
||||
{
|
||||
public int MinLength { get; set; }
|
||||
|
||||
public int MaxLength { get; set; }
|
||||
|
||||
public List<int> ValidLengths { get; set; }
|
||||
|
||||
public string ValidChars { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
using ESCPOS_NET.Emitters;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ESCPOS_NET.DataValidation
|
||||
{
|
||||
public abstract class BaseDataValidator<T> where T : Enum
|
||||
{
|
||||
protected Dictionary<T, DataConstraint> _constraints;
|
||||
|
||||
public void Validate(T type, string data, BarcodeCode? code = null)
|
||||
{
|
||||
if (data is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(data));
|
||||
}
|
||||
|
||||
// Validate constraints on barcode.
|
||||
_constraints.TryGetValue(type, out var constraints);
|
||||
if (constraints is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check lengths
|
||||
if (constraints.ValidLengths != null)
|
||||
{
|
||||
if (!constraints.ValidLengths.Contains(data.Length))
|
||||
{
|
||||
throw new ArgumentException($"Code '{data}' is not a valid length from: [{string.Join(", ", constraints.ValidLengths)}].");
|
||||
}
|
||||
}
|
||||
else if (data.Length < constraints.MinLength)
|
||||
{
|
||||
throw new ArgumentException($"Code '{data}' is shorter than minimum length {constraints.MinLength}.");
|
||||
}
|
||||
else if (data.Length > constraints.MaxLength)
|
||||
{
|
||||
throw new ArgumentException($"Code '{data}' is longer than maximum length {constraints.MaxLength}.");
|
||||
}
|
||||
|
||||
// Check if barcode contains invalid characters.
|
||||
if (constraints.ValidChars == "7BIT-ASCII")
|
||||
{
|
||||
if (!data.All(x => x <= 127 && x >= 0))
|
||||
{
|
||||
throw new ArgumentException($"Code '{data}' contained invalid characters not in: {constraints.ValidChars}.");
|
||||
}
|
||||
}
|
||||
else if (constraints.ValidChars != null && !data.All(x => constraints.ValidChars.Contains(x)))
|
||||
{
|
||||
throw new ArgumentException($"Code '{data}' contained invalid characters not in: {constraints.ValidChars}.");
|
||||
}
|
||||
|
||||
RunSpecificValidations(type, data, code);
|
||||
}
|
||||
|
||||
protected abstract void RunSpecificValidations(T type, string data, BarcodeCode? code);
|
||||
}
|
||||
|
||||
public static class DataValidator
|
||||
{
|
||||
private static BarcodeDataValidator singletonBarcode = null;
|
||||
private static TwoDimensionCodeDataValidator singleton2DCode = null;
|
||||
|
||||
public static void ValidateBarcode(BarcodeType type, BarcodeCode code, string data)
|
||||
{
|
||||
if (singletonBarcode is null)
|
||||
{
|
||||
singletonBarcode = new BarcodeDataValidator();
|
||||
}
|
||||
|
||||
singletonBarcode.Validate(type, data, code);
|
||||
}
|
||||
|
||||
public static void Validate2DCode(TwoDimensionCodeType type, string data)
|
||||
{
|
||||
if (singleton2DCode is null)
|
||||
{
|
||||
singleton2DCode = new TwoDimensionCodeDataValidator();
|
||||
}
|
||||
|
||||
singleton2DCode.Validate(type, data);
|
||||
}
|
||||
|
||||
private class BarcodeDataValidator : BaseDataValidator<BarcodeType>
|
||||
{
|
||||
public BarcodeDataValidator()
|
||||
{
|
||||
_constraints = new Dictionary<BarcodeType, DataConstraint>()
|
||||
{
|
||||
{ BarcodeType.UPC_A, new DataConstraint() { MinLength = 11, MaxLength = 12, ValidChars = "0123456789" } },
|
||||
{ BarcodeType.UPC_E, new DataConstraint() { ValidLengths = new List<int>() { 6, 7, 8, 11, 12 }, ValidChars = "0123456789" } },
|
||||
{ BarcodeType.JAN13_EAN13, new DataConstraint() { MinLength = 12, MaxLength = 13, ValidChars = "0123456789" } },
|
||||
{ BarcodeType.JAN8_EAN8, new DataConstraint() { MinLength = 7, MaxLength = 8, ValidChars = "0123456789" } },
|
||||
{ BarcodeType.CODE39, new DataConstraint() { MinLength = 1, MaxLength = 255, ValidChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./" } },
|
||||
{ BarcodeType.ITF, new DataConstraint() { MinLength = 2, MaxLength = 255, ValidChars = "0123456789" } },
|
||||
{ BarcodeType.CODABAR_NW_7, new DataConstraint() { MinLength = 2, MaxLength = 255, ValidChars = "0123456789ABCDabcd$+-./:" } },
|
||||
{ BarcodeType.CODE93, new DataConstraint() { MinLength = 1, MaxLength = 255, ValidChars = "7BIT-ASCII" } },
|
||||
{ BarcodeType.CODE128, new DataConstraint() { MinLength = 1, MaxLength = 253, ValidChars = "7BIT-ASCII" } },
|
||||
{ BarcodeType.GS1_128, new DataConstraint() { MinLength = 1, MaxLength = 253, ValidChars = "7BIT-ASCII" } },
|
||||
{ BarcodeType.GS1_DATABAR_OMNIDIRECTIONAL, new DataConstraint() { MinLength = 13, MaxLength = 13, ValidChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./" } },
|
||||
{ BarcodeType.GS1_DATABAR_TRUNCATED, new DataConstraint() { MinLength = 13, MaxLength = 13, ValidChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./" } },
|
||||
{ BarcodeType.GS1_DATABAR_LIMITED, new DataConstraint() { MinLength = 13, MaxLength = 13, ValidChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./" } },
|
||||
{ BarcodeType.GS1_DATABAR_EXPANDED, new DataConstraint() { MinLength = 2, MaxLength = 255, ValidChars = "0123456789ABCDabcd !\"%$'()*+,-./:;<=>?_{" } },
|
||||
};
|
||||
}
|
||||
|
||||
protected override void RunSpecificValidations(BarcodeType type, string barcode, BarcodeCode? code)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case BarcodeType.UPC_E:
|
||||
if (barcode.Length != 6 && !barcode.StartsWith("0", StringComparison.InvariantCulture))
|
||||
{
|
||||
throw new ArgumentException($"UPC_E Barcode {barcode} with length of 7, 8, 11, or 12 must start with 0.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BarcodeType.ITF:
|
||||
if (barcode.Length % 2 != 0)
|
||||
{
|
||||
throw new ArgumentException($"ITF Barcode {barcode} has length {barcode.Length}, which is not an even number.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BarcodeType.CODABAR_NW_7:
|
||||
if (!"ABCD".Contains(barcode[0]) || !"ABCD".Contains(barcode[barcode.Length - 1]))
|
||||
{
|
||||
throw new ArgumentException($"CODABAR_NW_7 Barcode {barcode} must start and end with an ABCD character.");
|
||||
}
|
||||
|
||||
if (barcode.Skip(1).Take(barcode.Length - 2).Any(x => "ABCD".Contains(x)))
|
||||
{
|
||||
throw new ArgumentException($"CODABAR_NW_7 Barcode {barcode} must not include ABCD characters in the body of the barcode.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BarcodeType.CODE93:
|
||||
if (!barcode.StartsWith("*", StringComparison.InvariantCulture) || !barcode.EndsWith("*", StringComparison.InvariantCulture))
|
||||
{
|
||||
throw new ArgumentException($"CODE93 Barcode {barcode} must start and end with * characters.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BarcodeType.CODE128:
|
||||
if (code == BarcodeCode.CODE_C)
|
||||
{
|
||||
if (barcode.Length % 2 != 0)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(barcode)} length must be divisible by 2");
|
||||
}
|
||||
|
||||
if (!barcode.All(x => x <= '9' && x >= '0'))
|
||||
{
|
||||
throw new ArgumentException($"Barcode {barcode} is invalid. CODE128 CODE_C barcodes only support numeric characters.");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class TwoDimensionCodeDataValidator : BaseDataValidator<TwoDimensionCodeType>
|
||||
{
|
||||
public TwoDimensionCodeDataValidator()
|
||||
{
|
||||
_constraints = new Dictionary<TwoDimensionCodeType, DataConstraint>()
|
||||
{
|
||||
{ TwoDimensionCodeType.PDF417, new DataConstraint() { MinLength = 0, MaxLength = 255 } },
|
||||
{ TwoDimensionCodeType.QRCODE_MODEL1, new DataConstraint() { MinLength = 0, MaxLength = 707 } },
|
||||
{ TwoDimensionCodeType.QRCODE_MODEL2, new DataConstraint() { MinLength = 0, MaxLength = 4296 } },
|
||||
{ TwoDimensionCodeType.QRCODE_MICRO, new DataConstraint() { MinLength = 0, MaxLength = 21 } },
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Research specific validations for QRCode & PDF417
|
||||
protected override void RunSpecificValidations(TwoDimensionCodeType type, string barcode, BarcodeCode? code)
|
||||
{
|
||||
if (code != null)
|
||||
{
|
||||
throw new ArgumentException($"Barcode code should be always null for 2D Codes.", nameof(code));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<Company>animalistic.io</Company>
|
||||
<Product>ESCPOS_NET</Product>
|
||||
<Authors>Luke Paireepinart</Authors>
|
||||
<Description>.NET Standard 2.0 Implementation of ESC/POS command generation and integration with thermal printers.
|
||||
Allows creating receipts with all common functionality supported.</Description>
|
||||
<Copyright>Copyright 2021 CandL Development, LLC.</Copyright>
|
||||
<PackageLicenseUrl></PackageLicenseUrl>
|
||||
<RepositoryUrl>https://github.com/lukevp/ESC-POS-.NET</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>epson thermal receipt printing printer usb wifi bluetooth serial esc pos escpos escp esc/pos esc/pos.net esc_pos esc_pos_net esc_pos_usb esc_pos_usb_net</PackageTags>
|
||||
<Version>2.0.0</Version>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
<FileVersion>2.0.0.0</FileVersion>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/lukevp/ESC-POS-.NET</PackageProjectUrl>
|
||||
<PackageReleaseNotes>- Completely rebuilt the network printer code</PackageReleaseNotes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0" />
|
||||
<PackageReference Include="SuperSimpleTcp" Version="2.4.0" />
|
||||
<PackageReference Include="System.IO.Ports" Version="4.6.0" />
|
||||
<PackageReference Include="System.Text.Json" Version="5.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Action Commands */
|
||||
public virtual byte[] FullCut() => new byte[] { Cmd.GS, Ops.PaperCut, Functions.PaperCutFullCut };
|
||||
|
||||
public virtual byte[] PartialCut() => new byte[] { Cmd.GS, Ops.PaperCut, Functions.PaperCutPartialCut };
|
||||
|
||||
public virtual byte[] FullCutAfterFeed(int lineCount) => new byte[] { Cmd.GS, Ops.PaperCut, Functions.PaperCutFullCutWithFeed, (byte)lineCount };
|
||||
|
||||
public virtual byte[] PartialCutAfterFeed(int lineCount) => new byte[] { Cmd.GS, Ops.PaperCut, Functions.PaperCutPartialCutWithFeed, (byte)lineCount };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using ESCPOS_NET.DataValidation;
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
using ESCPOS_NET.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Barcode Commands */
|
||||
public virtual byte[] PrintBarcode(BarcodeType type, string barcode, BarcodeCode code = BarcodeCode.CODE_B)
|
||||
{
|
||||
DataValidator.ValidateBarcode(type, code, barcode);
|
||||
return BarcodeBytes(type, barcode, code);
|
||||
}
|
||||
|
||||
protected virtual byte[] BarcodeBytes(BarcodeType type, string barcode, BarcodeCode code)
|
||||
{
|
||||
// For CODE128, prepend the first 2 characters as 0x7B and the CODE type, and escape 0x7B characters.
|
||||
if (type == BarcodeType.CODE128)
|
||||
{
|
||||
if (code == BarcodeCode.CODE_C)
|
||||
{
|
||||
byte[] b = Encoding.ASCII.GetBytes(barcode);
|
||||
byte[] ob = new byte[b.Length / 2];
|
||||
for (int i = 0, obc = 0; i < b.Length; i += 2)
|
||||
{
|
||||
ob[obc++] = (byte)(((b[i] - '0') * 10) + (b[i + 1] - '0'));
|
||||
}
|
||||
|
||||
barcode = Encoding.ASCII.GetString(ob);
|
||||
}
|
||||
|
||||
barcode = barcode.Replace("{", "{{");
|
||||
barcode = $"{(char)0x7B}{(char)code}" + barcode;
|
||||
}
|
||||
|
||||
var command = new List<byte> { Cmd.GS, Barcodes.PrintBarcode, (byte)type, (byte)barcode.Length };
|
||||
command.AddRange(barcode.ToCharArray().Select(x => (byte)x));
|
||||
return command.ToArray();
|
||||
}
|
||||
|
||||
public virtual byte[] PrintQRCode(string data, TwoDimensionCodeType type = TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode size = Size2DCode.NORMAL, CorrectionLevel2DCode correction = CorrectionLevel2DCode.PERCENT_7)
|
||||
{
|
||||
if (type == TwoDimensionCodeType.PDF417)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(TwoDimensionCodeType.PDF417)} is not a valid QRCode type. Please use {nameof(Print2DCode)} method", nameof(type));
|
||||
}
|
||||
|
||||
return Print2DCode(type, data, size, correction);
|
||||
}
|
||||
|
||||
public virtual byte[] Print2DCode(TwoDimensionCodeType type, string data, Size2DCode size = Size2DCode.NORMAL, CorrectionLevel2DCode correction = CorrectionLevel2DCode.PERCENT_7)
|
||||
{
|
||||
DataValidator.Validate2DCode(type, data);
|
||||
return TwoDimensionCodeBytes(type, data, size, correction);
|
||||
}
|
||||
|
||||
protected virtual byte[] TwoDimensionCodeBytes(TwoDimensionCodeType type, string data, Size2DCode size, CorrectionLevel2DCode correction)
|
||||
{
|
||||
List<byte> command = new List<byte>();
|
||||
byte[] initial = { Cmd.GS, Barcodes.Set2DCode, Barcodes.PrintBarcode };
|
||||
switch (type)
|
||||
{
|
||||
case TwoDimensionCodeType.PDF417:
|
||||
command.AddRange(initial, Barcodes.SetPDF417NumberOfColumns, Barcodes.AutoEnding);
|
||||
command.AddRange(initial, Barcodes.SetPDF417NumberOfRows, Barcodes.AutoEnding);
|
||||
command.AddRange(initial, Barcodes.SetPDF417DotSize, (byte)size);
|
||||
command.AddRange(initial, Barcodes.SetPDF417CorrectionLevel, (byte)correction);
|
||||
|
||||
// k = (pL + pH * 256) - 3 --> But pH is always 0.
|
||||
int k = data.Length;
|
||||
int l = k + 3;
|
||||
command.AddRange(initial, (byte)l, Barcodes.StorePDF417Data);
|
||||
command.AddRange(data.ToCharArray().Select(x => (byte)x));
|
||||
|
||||
// Prints stored PDF417
|
||||
command.AddRange(initial, Barcodes.PrintPDF417);
|
||||
break;
|
||||
|
||||
case TwoDimensionCodeType.QRCODE_MODEL1:
|
||||
case TwoDimensionCodeType.QRCODE_MODEL2:
|
||||
case TwoDimensionCodeType.QRCODE_MICRO:
|
||||
command.AddRange(initial, Barcodes.SelectQRCodeModel, (byte)type, Barcodes.AutoEnding);
|
||||
command.AddRange(initial, Barcodes.SetQRCodeDotSize, (byte)size);
|
||||
command.AddRange(initial, Barcodes.SetQRCodeCorrectionLevel, (byte)correction);
|
||||
int num = data.Length + 3;
|
||||
int pL = num % 256;
|
||||
int pH = num / 256;
|
||||
command.AddRange(initial, (byte)pL, (byte)pH, Barcodes.StoreQRCodeData);
|
||||
command.AddRange(data.ToCharArray().Select(x => (byte)x));
|
||||
|
||||
// Prints stored QRCode
|
||||
command.AddRange(initial, Barcodes.PrintQRCode);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"2D Code '{type}' was not implemented yet.");
|
||||
}
|
||||
|
||||
return command.ToArray();
|
||||
}
|
||||
|
||||
public virtual byte[] SetBarcodeHeightInDots(int height) => new byte[] { Cmd.GS, Barcodes.SetBarcodeHeightInDots, (byte)height };
|
||||
|
||||
public virtual byte[] SetBarWidth(BarWidth width) => new byte[] { Cmd.GS, Barcodes.SetBarWidth, (byte)width };
|
||||
|
||||
public virtual byte[] SetBarLabelPosition(BarLabelPrintPosition position) => new byte[] { Cmd.GS, Barcodes.SetBarLabelPosition, (byte)position };
|
||||
|
||||
public virtual byte[] SetBarLabelFontB(bool fontB) => new byte[] { Cmd.GS, Barcodes.SetBarLabelFont, (byte)(fontB ? 1 : 0) };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Cash Drawer Commands */
|
||||
public virtual byte[] CashDrawerOpenPin2(int pulseOnTimeMs = 120, int pulseOffTimeMs = 240) {
|
||||
return new byte[] { Cmd.ESC, Ops.CashDrawerPulse, 0x00, (byte) (pulseOnTimeMs / 2), (byte) (pulseOffTimeMs / 2) };
|
||||
}
|
||||
|
||||
public virtual byte[] CashDrawerOpenPin5(int pulseOnTimeMs = 120, int pulseOffTimeMs = 240) {
|
||||
return new byte[] { Cmd.ESC, Ops.CashDrawerPulse, 0x01, (byte) (pulseOnTimeMs / 2), (byte) (pulseOffTimeMs / 2) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Character Commands */
|
||||
public virtual byte[] SetStyles(PrintStyle style) => new byte[] { Cmd.ESC, Chars.StyleMode, (byte)style };
|
||||
|
||||
public virtual byte[] LeftAlign() => new byte[] { Cmd.ESC, Chars.Alignment, (byte)Align.Left };
|
||||
|
||||
public virtual byte[] CenterAlign() => new byte[] { Cmd.ESC, Chars.Alignment, (byte)Align.Center };
|
||||
|
||||
public virtual byte[] RightAlign() => new byte[] { Cmd.ESC, Chars.Alignment, (byte)Align.Right };
|
||||
|
||||
public virtual byte[] RightCharacterSpacing(int spaceCount) => new byte[] { Cmd.ESC, Chars.RightCharacterSpacing, (byte)spaceCount };
|
||||
|
||||
public virtual byte[] CodePage(CodePage codePage) => new byte[] { Cmd.ESC, Chars.CodePage, (byte)codePage };
|
||||
|
||||
public virtual byte[] Color(Color color) => new byte[] { Cmd.ESC, Chars.Color, (byte)color };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Display Commands */
|
||||
public virtual byte[] Clear() => new byte[] { Display.CLR };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
using ESCPOS_NET.Utilities;
|
||||
using SixLabors.ImageSharp;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
private byte[] GetImageHeader(int commandLength)
|
||||
{
|
||||
byte[] lengths = new byte[4];
|
||||
int i = 0;
|
||||
while (commandLength > 0)
|
||||
{
|
||||
lengths[i] = (byte)(commandLength & 0xFF);
|
||||
commandLength >>= 8;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i >= 3)
|
||||
{
|
||||
return new byte[] { Cmd.GS, Images.ImageCmd8, Images.ImageCmdL, lengths[0], lengths[1], lengths[2], lengths[3] };
|
||||
}
|
||||
else
|
||||
{
|
||||
return new byte[] { Cmd.GS, Images.ImageCmdParen, Images.ImageCmdL, lengths[0], lengths[1] };
|
||||
}
|
||||
}
|
||||
|
||||
/* Image Commands */
|
||||
public virtual byte[] SetImageDensity(bool isHiDPI)
|
||||
{
|
||||
ByteArrayBuilder builder = new ByteArrayBuilder();
|
||||
byte dpiSetting = isHiDPI ? (byte)0x33 : (byte)0x32; // TODO: is this right??
|
||||
byte[] baseCommand = new byte[] { 0x30, 0x31, dpiSetting, dpiSetting };
|
||||
builder.Append(GetImageHeader(baseCommand.Length));
|
||||
builder.Append(baseCommand);
|
||||
return builder.ToArray();
|
||||
}
|
||||
|
||||
public virtual byte[] BufferImage(byte[] image, int maxWidth = -1, bool isLegacy = false, int color = 1)
|
||||
{
|
||||
ByteArrayBuilder imageCommand = new ByteArrayBuilder();
|
||||
|
||||
byte colorByte;
|
||||
switch (color)
|
||||
{
|
||||
case 2:
|
||||
colorByte = 0x32;
|
||||
break;
|
||||
case 3:
|
||||
colorByte = 0x33;
|
||||
break;
|
||||
default:
|
||||
colorByte = 0x31;
|
||||
break;
|
||||
}
|
||||
|
||||
int width;
|
||||
int height;
|
||||
byte[] imageData;
|
||||
using (var img = Image.Load(image))
|
||||
{
|
||||
imageData = img.ToSingleBitPixelByteArray(maxWidth: maxWidth == -1 ? (int?)null : maxWidth);
|
||||
height = img.Height;
|
||||
width = img.Width;
|
||||
}
|
||||
|
||||
byte heightL = (byte)height;
|
||||
byte heightH = (byte)(height >> 8);
|
||||
|
||||
if (isLegacy)
|
||||
{
|
||||
var byteWidth = (width + 7 & -8) / 8;
|
||||
byte widthL = (byte)byteWidth;
|
||||
byte widthH = (byte)(byteWidth >> 8);
|
||||
imageCommand.Append(new byte[] { Cmd.GS, Images.ImageCmdLegacy, 0x30, 0x00, widthL, widthH, heightL, heightH });
|
||||
}
|
||||
else
|
||||
{
|
||||
byte widthL = (byte)width;
|
||||
byte widthH = (byte)(width >> 8);
|
||||
imageCommand.Append(new byte[] { 0x30, 0x70, 0x30, 0x01, 0x01, colorByte, widthL, widthH, heightL, heightH });
|
||||
}
|
||||
|
||||
imageCommand.Append(imageData);
|
||||
|
||||
// Load image to print buffer
|
||||
ByteArrayBuilder response = new ByteArrayBuilder();
|
||||
byte[] imageCommandBytes = imageCommand.ToArray();
|
||||
if (!isLegacy)
|
||||
{
|
||||
response.Append(GetImageHeader(imageCommandBytes.Length));
|
||||
}
|
||||
|
||||
response.Append(imageCommandBytes);
|
||||
return response.ToArray();
|
||||
}
|
||||
|
||||
public virtual byte[] WriteImageFromBuffer()
|
||||
{
|
||||
// Print image that's already buffered.
|
||||
ByteArrayBuilder response = new ByteArrayBuilder();
|
||||
byte[] printCommandBytes = new byte[] { 0x30, 0x32 };
|
||||
response.Append(GetImageHeader(printCommandBytes.Length));
|
||||
response.Append(printCommandBytes);
|
||||
return response.ToArray();
|
||||
}
|
||||
|
||||
public virtual byte[] PrintImage(byte[] image, bool isHiDPI, bool isLegacy = false, int maxWidth = -1, int color = 1)
|
||||
{
|
||||
if (isLegacy)
|
||||
{
|
||||
return ByteSplicer.Combine(BufferImage(image, maxWidth, isLegacy));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ByteSplicer.Combine(SetImageDensity(isHiDPI), BufferImage(image, maxWidth, isLegacy, color), WriteImageFromBuffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
public virtual byte[] ResetLineSpacing() => new byte[] { Cmd.ESC, Whitespace.ResetLineSpacing };
|
||||
|
||||
public virtual byte[] SetLineSpacingInDots(int dots) => new byte[] { Cmd.ESC, Whitespace.LineSpacingInDots, (byte)dots };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Operational Commands */
|
||||
public virtual byte[] Initialize() => new byte[] { Cmd.ESC, Ops.Initialize };
|
||||
|
||||
public virtual byte[] Enable() => new byte[] { Cmd.ESC, Ops.EnableDisable, 1 };
|
||||
|
||||
public virtual byte[] Disable() => new byte[] { Cmd.ESC, Ops.EnableDisable, 0 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Linq;
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Printing Commands */
|
||||
public virtual byte[] Print(string data)
|
||||
{
|
||||
// Fix OSX or Windows-style newlines
|
||||
data = data.Replace("\r\n", "\n");
|
||||
data = data.Replace("\r", "\n");
|
||||
|
||||
// TODO: Sanitize...
|
||||
return data.ToCharArray().Select(x => (byte)x).ToArray();
|
||||
}
|
||||
|
||||
public virtual byte[] PrintLine(string line)
|
||||
{
|
||||
if (line == null)
|
||||
{
|
||||
return Print("\n");
|
||||
}
|
||||
|
||||
return Print(line.Replace("\r", string.Empty).Replace("\n", string.Empty) + "\n");
|
||||
}
|
||||
|
||||
public virtual byte[] FeedLines(int lineCount) => new byte[] { Cmd.ESC, Whitespace.FeedLines, (byte)lineCount };
|
||||
|
||||
public virtual byte[] FeedLinesReverse(int lineCount) => new byte[] { Cmd.ESC, Whitespace.FeedLinesReverse, (byte)lineCount };
|
||||
|
||||
public virtual byte[] FeedDots(int dotCount) => new byte[] { Cmd.ESC, Whitespace.FeedDots, (byte)dotCount };
|
||||
|
||||
public virtual byte[] ReverseMode(bool enable) => new byte[] { Cmd.GS, Chars.ReversePrintMode, enable ? (byte)0x01 : (byte)0x00 };
|
||||
|
||||
public virtual byte[] UpsideDownMode(bool enable) => new byte[] { Cmd.ESC, Chars.UpsideDownMode, enable ? (byte)0x01 : (byte)0x00 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public abstract partial class BaseCommandEmitter : ICommandEmitter
|
||||
{
|
||||
/* Status Commands */
|
||||
public virtual byte[] EnableAutomaticStatusBack() => new byte[] { Cmd.GS, Status.AutomaticStatusBack, 0xFF };
|
||||
|
||||
public virtual byte[] EnableAutomaticInkStatusBack() => new byte[] { Cmd.GS, Status.AutomaticInkStatusBack, 0xFF };
|
||||
public virtual byte[] DisableAutomaticStatusBack() => new byte[] { Cmd.GS, Status.AutomaticStatusBack, 0x00 };
|
||||
|
||||
public virtual byte[] DisableAutomaticInkStatusBack() => new byte[] { Cmd.GS, Status.AutomaticInkStatusBack, 0x00 };
|
||||
public virtual byte[] RequestPaperStatus() => new byte[] { Cmd.GS, Status.RequestStatus, 0x31 };
|
||||
public virtual byte[] RequestDrawerStatus() => new byte[] { Cmd.GS, Status.RequestStatus, 0x32 };
|
||||
public virtual byte[] RequestInkStatus() => new byte[] { Cmd.GS, Status.RequestStatus, 0x34 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Barcodes
|
||||
{
|
||||
public static readonly byte PrintBarcode = 0x6B;
|
||||
public static readonly byte SetBarcodeHeightInDots = 0x68;
|
||||
public static readonly byte SetBarWidth = 0x77;
|
||||
public static readonly byte SetBarLabelPosition = 0x48;
|
||||
public static readonly byte SetBarLabelFont = 0x66;
|
||||
|
||||
public static readonly byte Set2DCode = 0x28;
|
||||
public static readonly byte AutoEnding = 0x00;
|
||||
public static readonly byte[] SetPDF417NumberOfColumns = { 0x03, 0x00, 0x30, 0x41 };
|
||||
public static readonly byte[] SetPDF417NumberOfRows = { 0x03, 0x00, 0x30, 0x42 };
|
||||
public static readonly byte[] SetPDF417DotSize = { 0x03, 0x00, 0x30, 0x43 };
|
||||
public static readonly byte[] SetPDF417CorrectionLevel = { 0x04, 0x00, 0x30, 0x45, 0x30 };
|
||||
public static readonly byte[] StorePDF417Data = { 0x00, 0x30, 0x50, 0x30 };
|
||||
public static readonly byte[] PrintPDF417 = { 0x03, 0x00, 0x30, 0x51, 0x30 };
|
||||
|
||||
public static readonly byte[] SelectQRCodeModel = { 0x04, 0x00, 0x31, 0x41 };
|
||||
public static readonly byte[] SetQRCodeDotSize = { 0x03, 0x00, 0x31, 0x43 };
|
||||
public static readonly byte[] SetQRCodeCorrectionLevel = { 0x03, 0x00, 0x31, 0x45 };
|
||||
public static readonly byte[] StoreQRCodeData = { 0x31, 0x50, 0x30 };
|
||||
public static readonly byte[] PrintQRCode = { 0x03, 0x00, 0x31, 0x51, 0x30 };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Chars
|
||||
{
|
||||
public static readonly byte StyleMode = 0x21;
|
||||
public static readonly byte Alignment = 0x61;
|
||||
public static readonly byte ReversePrintMode = 0x42;
|
||||
public static readonly byte RightCharacterSpacing = 0x20;
|
||||
public static readonly byte UpsideDownMode = 0x7B;
|
||||
public static readonly byte CodePage = 0x74;
|
||||
public static readonly byte Color = 0x72;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Cmd
|
||||
{
|
||||
public static readonly byte ESC = 0x1B;
|
||||
public static readonly byte GS = 0x1D;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Display
|
||||
{
|
||||
public static readonly byte CLR = 0x0C;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Functions
|
||||
{
|
||||
public static readonly byte PaperCutFullCut = 0x00;
|
||||
public static readonly byte PaperCutFullCutWithFeed = 0x41;
|
||||
public static readonly byte PaperCutPartialCut = 0x01;
|
||||
public static readonly byte PaperCutPartialCutWithFeed = 0x42;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Images
|
||||
{
|
||||
public static readonly byte ImageCmdParen = 0x28;
|
||||
public static readonly byte ImageCmdLegacy = 0x76;
|
||||
public static readonly byte ImageCmd8 = 0x38;
|
||||
public static readonly byte ImageCmdL = 0x4C;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Ops
|
||||
{
|
||||
public static readonly byte Initialize = 0x40;
|
||||
public static readonly byte EnableDisable = 0x3D;
|
||||
public static readonly byte PaperCut = 0x56;
|
||||
public static readonly byte CashDrawerPulse = 0x70;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Status
|
||||
{
|
||||
public static readonly byte AutomaticStatusBack = 0x61;
|
||||
public static readonly byte AutomaticInkStatusBack = 0x6A;
|
||||
public static readonly byte RequestStatus = 0x72;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace ESCPOS_NET.Emitters.BaseCommandValues
|
||||
{
|
||||
public static class Whitespace
|
||||
{
|
||||
// TODO: tabs?
|
||||
public static readonly byte Linefeed = 0x0A;
|
||||
public static readonly byte FeedLines = 0x64;
|
||||
public static readonly byte FeedLinesReverse = 0x65;
|
||||
public static readonly byte FeedDots = 0x4A;
|
||||
public static readonly byte ResetLineSpacing = 0x32;
|
||||
public static readonly byte LineSpacingInDots = 0x33;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public class EPSON : BaseCommandEmitter
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum TwoDimensionCodeType
|
||||
{
|
||||
PDF417 = 0,
|
||||
QRCODE_MODEL1 = 49,
|
||||
QRCODE_MODEL2 = 50,
|
||||
QRCODE_MICRO = 51,
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum Size2DCode
|
||||
{
|
||||
TINY = 2,
|
||||
SMALL = 3,
|
||||
NORMAL = 4,
|
||||
LARGE = 5,
|
||||
EXTRA = 6,
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum CorrectionLevel2DCode
|
||||
{
|
||||
PERCENT_7 = 48,
|
||||
PERCENT_15 = 49,
|
||||
PERCENT_25 = 50,
|
||||
PERCENT_30 = 51,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum Align
|
||||
{
|
||||
Left = 0,
|
||||
Center = 1,
|
||||
Right = 2,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment..")]
|
||||
public enum BarLabelPrintPosition
|
||||
{
|
||||
None = 0,
|
||||
Above = 1,
|
||||
Below = 2,
|
||||
Both = 3,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum BarWidth
|
||||
{
|
||||
Thinnest = 2,
|
||||
Thin = 3,
|
||||
Default = 4,
|
||||
Thick = 5,
|
||||
Thickest = 6,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public enum BarcodeCode
|
||||
{
|
||||
CODE_A = 0x41,
|
||||
CODE_B = 0x42,
|
||||
CODE_C = 0x43,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum BarcodeType // All from Function B
|
||||
{
|
||||
UPC_A = 0x41,
|
||||
UPC_E = 0x42,
|
||||
JAN13_EAN13 = 0x43,
|
||||
JAN8_EAN8 = 0x44,
|
||||
CODE39 = 0x45,
|
||||
ITF = 0x46,
|
||||
CODABAR_NW_7 = 0x47,
|
||||
CODE93 = 0x48,
|
||||
CODE128 = 0x49,
|
||||
GS1_128 = 0x4A,
|
||||
GS1_DATABAR_OMNIDIRECTIONAL = 0x4B,
|
||||
GS1_DATABAR_TRUNCATED = 0x4C,
|
||||
GS1_DATABAR_LIMITED = 0x4D,
|
||||
GS1_DATABAR_EXPANDED = 0x4E,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
#pragma warning disable SA1602 // Enumeration items should be documented
|
||||
#pragma warning disable SA1600 // Elements should be documented
|
||||
public enum CodePage
|
||||
{
|
||||
PC437_USA_STANDARD_EUROPE_DEFAULT = 0,
|
||||
KATAKANA = 1,
|
||||
PC850_MULTILINGUAL = 2,
|
||||
PC860_PORTUGUESE = 3,
|
||||
PC863_CANADIAN_FRENCH = 4,
|
||||
PC865_NORDIC = 5,
|
||||
HIRAGANA = 6,
|
||||
ONE_PASS_KANJI = 7,
|
||||
ONE_PASS_KANJI2 = 8,
|
||||
PC851_GREEK = 11,
|
||||
PC853_TURKISH = 12,
|
||||
PC857_TURKISH = 13,
|
||||
PC737_GREEK = 14,
|
||||
ISO8859_7_GREEK = 15,
|
||||
WPC1252 = 16,
|
||||
PC866_CYRILLIC2 = 17,
|
||||
PC852_LATIN2 = 18,
|
||||
PC858_EURO = 19,
|
||||
KU42_THAI = 20,
|
||||
TIS11_THAI = 21,
|
||||
TIS13_THAI = 22,
|
||||
TIS14_THAI = 23,
|
||||
TIS16_THAI = 24,
|
||||
TIS17_THAI = 25,
|
||||
TIS18_THAI = 26,
|
||||
TCVN3_VIETNAMESE_L = 30,
|
||||
TCVN3_VIETNAMESE_U = 31,
|
||||
PC720_ARABIC = 32,
|
||||
WPC775_BALTIC_RIM = 33,
|
||||
PC855_CYRILLIC = 34,
|
||||
PC861_ICELANDIC = 35,
|
||||
PC862_HEBREW = 36,
|
||||
PC864_ARABIC = 37,
|
||||
PC869_GREEK = 38,
|
||||
ISO8859_2_LATIN2 = 39,
|
||||
ISO8859_15_LATIN9 = 40,
|
||||
PC1098_FARSI = 41,
|
||||
PC1118_LITHUANIAN = 42,
|
||||
PC1119_LITHUANIAN = 43,
|
||||
PC1125_UKRANIAN = 44,
|
||||
WPC1250_LATIN2 = 45,
|
||||
WPC1251_CYRILLIC = 46,
|
||||
WPC1253_GREEK = 47,
|
||||
WPC1254_TURKISH = 48,
|
||||
WPC1255_HEBREW = 49,
|
||||
WPC1256_ARABIC = 50,
|
||||
WPC1257_BALTIC_RIM = 51,
|
||||
WPC1258_VIETNAMESE = 52,
|
||||
KZ1048_KAZAKHSTAN = 53,
|
||||
DEVANAGARI = 66,
|
||||
BENGALI = 67,
|
||||
TAMIL = 68,
|
||||
TELUGU = 69,
|
||||
ASSAMESE = 70,
|
||||
ORIYA = 71,
|
||||
KANNADA = 72,
|
||||
MALAYALAM = 73,
|
||||
GUJARATI = 74,
|
||||
PUNJABI = 75,
|
||||
MARATHI = 82,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
[Flags]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum Color
|
||||
{
|
||||
Black = 0,
|
||||
Red = 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
[Flags]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "Enums are easier to read if they have whitespace alignment.")]
|
||||
public enum PrintStyle
|
||||
{
|
||||
None = 0,
|
||||
FontB = 1,
|
||||
Bold = 1 << 3,
|
||||
DoubleHeight = 1 << 4,
|
||||
DoubleWidth = 1 << 5,
|
||||
Underline = 1 << 7,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
namespace ESCPOS_NET.Emitters
|
||||
{
|
||||
public interface ICommandEmitter
|
||||
{
|
||||
/* Print Commands */
|
||||
byte[] PrintLine(string line = null);
|
||||
|
||||
byte[] Print(string line);
|
||||
|
||||
byte[] FeedLines(int lineCount);
|
||||
|
||||
byte[] FeedLinesReverse(int lineCount);
|
||||
|
||||
byte[] FeedDots(int dotCount);
|
||||
|
||||
/* Line Spacing Commands */
|
||||
byte[] ResetLineSpacing();
|
||||
|
||||
byte[] SetLineSpacingInDots(int dots);
|
||||
|
||||
/* Operational Commands */
|
||||
byte[] Initialize();
|
||||
|
||||
byte[] Enable();
|
||||
|
||||
byte[] Disable();
|
||||
|
||||
/* Cash Drawer Commands */
|
||||
byte[] CashDrawerOpenPin2(int pulseOnTimeMs = 120, int pulseOffTimeMs = 240);
|
||||
|
||||
byte[] CashDrawerOpenPin5(int pulseOnTimeMs = 120, int pulseOffTimeMs = 240);
|
||||
|
||||
/* Character Commands */
|
||||
byte[] SetStyles(PrintStyle style);
|
||||
|
||||
byte[] LeftAlign();
|
||||
|
||||
byte[] RightAlign();
|
||||
|
||||
byte[] CenterAlign();
|
||||
|
||||
byte[] ReverseMode(bool activate);
|
||||
|
||||
byte[] RightCharacterSpacing(int spaceCount);
|
||||
|
||||
byte[] UpsideDownMode(bool activate);
|
||||
|
||||
byte[] CodePage(CodePage codePage);
|
||||
|
||||
byte[] Color(Color color);
|
||||
|
||||
/* Action Commands */
|
||||
byte[] FullCut();
|
||||
|
||||
byte[] PartialCut();
|
||||
|
||||
byte[] FullCutAfterFeed(int lineCount);
|
||||
|
||||
byte[] PartialCutAfterFeed(int lineCount);
|
||||
|
||||
/* Image Commands */
|
||||
byte[] SetImageDensity(bool isHiDPI);
|
||||
|
||||
byte[] BufferImage(byte[] image, int maxWidth, bool isLegacy = false, int color = 1);
|
||||
|
||||
byte[] WriteImageFromBuffer();
|
||||
|
||||
byte[] PrintImage(byte[] image, bool isHiDPI, bool isLegacy = false, int maxWidth = -1, int color = 1);
|
||||
|
||||
/* Status Commands */
|
||||
byte[] EnableAutomaticStatusBack();
|
||||
|
||||
byte[] EnableAutomaticInkStatusBack();
|
||||
|
||||
/* Barcode Commands */
|
||||
byte[] PrintBarcode(BarcodeType type, string barcode, BarcodeCode code = BarcodeCode.CODE_B);
|
||||
|
||||
byte[] PrintQRCode(string data, TwoDimensionCodeType type = TwoDimensionCodeType.QRCODE_MODEL2, Size2DCode size = Size2DCode.NORMAL, CorrectionLevel2DCode correction = CorrectionLevel2DCode.PERCENT_7);
|
||||
|
||||
byte[] Print2DCode(TwoDimensionCodeType type, string data, Size2DCode size = Size2DCode.NORMAL, CorrectionLevel2DCode correction = CorrectionLevel2DCode.PERCENT_7);
|
||||
|
||||
byte[] SetBarcodeHeightInDots(int height);
|
||||
|
||||
byte[] SetBarWidth(BarWidth width);
|
||||
|
||||
byte[] SetBarLabelPosition(BarLabelPrintPosition position);
|
||||
|
||||
byte[] SetBarLabelFontB(bool fontB);
|
||||
|
||||
/* 2D-Code Commands */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
|
||||
namespace SixLabors.ImageSharp
|
||||
{
|
||||
public static class ImageSharpExtensions
|
||||
{
|
||||
public static byte[] ToSingleBitPixelByteArray(this Image<Rgba32> image, bool rasterFormat = true, int? maxWidth = null, int? maxHeight = null, float threshold = 0.5F)
|
||||
{
|
||||
image.Mutate(img =>
|
||||
{
|
||||
if (maxWidth.HasValue || maxHeight.HasValue)
|
||||
{
|
||||
img.Resize(new ResizeOptions
|
||||
{
|
||||
Mode = ResizeMode.Max,
|
||||
Size = new Size(maxWidth ?? int.MaxValue, maxHeight ?? int.MaxValue),
|
||||
});
|
||||
}
|
||||
|
||||
img.BackgroundColor(Color.White);
|
||||
img.Grayscale().BinaryDither(KnownDitherings.Stucki);
|
||||
|
||||
if (!rasterFormat)
|
||||
{
|
||||
img.Rotate(RotateMode.Rotate90);
|
||||
img.Flip(FlipMode.Horizontal);
|
||||
}
|
||||
});
|
||||
|
||||
var result = image.ToSingleBitPixelByteArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] ToSingleBitPixelByteArray(this Image<Rgba32> image)
|
||||
{
|
||||
var bytesPerRow = (image.Width + 7 & -8) / 8;
|
||||
|
||||
var result = new byte[bytesPerRow * image.Height];
|
||||
for (int y = 0; y < image.Height; y++)
|
||||
{
|
||||
var row = image.GetPixelRowSpan(y);
|
||||
var rowStartPosition = y * bytesPerRow;
|
||||
|
||||
for (int x = 0; x < row.Length; x++)
|
||||
{
|
||||
if (!row[x].IsBlack())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result[rowStartPosition + (x / 8)] |= (byte)(0x01 << (7 - (x % 8)));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static bool IsBlack(this Rgba32 rgba)
|
||||
{
|
||||
return rgba.R == 0 && rgba.G == 0 && rgba.B == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ESCPOS_NET.Extensions
|
||||
{
|
||||
public static class TaskExtensions
|
||||
{
|
||||
public static void LogExceptions(this Task task)
|
||||
{
|
||||
task.ContinueWith(t =>
|
||||
{
|
||||
var aggException = t.Exception.Flatten();
|
||||
foreach (var exception in aggException.InnerExceptions)
|
||||
{
|
||||
Logging.Logger?.LogError(exception, "Uncaught Thread Exception.");
|
||||
}
|
||||
},
|
||||
TaskContinuationOptions.OnlyOnFaulted);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ESCPOS_NET.Extensions
|
||||
{
|
||||
public static class Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds to the list of T items and/or enumerables of T. All other types will be ignored and not added to the list.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">List's items type.</typeparam>
|
||||
/// <param name="list">List to be added the items.</param>
|
||||
/// <param name="items">Items to be added.</param>
|
||||
/// <returns>True if no item was ignored, otherwise False.</returns>
|
||||
public static bool AddRange<T>(this List<T> list, params object[] items)
|
||||
{
|
||||
bool ignoredItems = false;
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is T itemT)
|
||||
{
|
||||
list.Add(itemT);
|
||||
}
|
||||
else if (item is IEnumerable<T> arrayT)
|
||||
{
|
||||
list.AddRange(arrayT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ignoredItems = true;
|
||||
}
|
||||
}
|
||||
|
||||
return !ignoredItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
// attributes that are applied to this project.
|
||||
// Project-level suppressions either have no target or are given
|
||||
// a specific target and scoped to a namespace, type, member, etc.
|
||||
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives should be placed correctly", Justification = "Placing usings within namespaces is not default in VS or in generated code.")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this", Justification = "Visual Studio by default recommends removing prefixed 'this'.")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1309:Field names should not begin with underscore", Justification = "MS style guide uses _ for private members.")]
|
||||
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "<Pending>", Scope = "type", Target = "~T:ESCPOS_NET.Emitters.CodePage")]
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Luke Paireepinart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public static class Logging
|
||||
{
|
||||
public static ILogger Logger { get; set; }
|
||||
static Logging()
|
||||
{
|
||||
|
||||
TaskScheduler.UnobservedTaskException += (s, e) =>
|
||||
{
|
||||
//LogUnhandledException(e.Exception, "TaskScheduler.UnobservedTaskException");
|
||||
e.SetObserved();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,378 @@
|
||||
using ESCPOS_NET.Emitters.BaseCommandValues;
|
||||
using ESCPOS_NET.Utilities;
|
||||
using ESCPOS_NET.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public abstract partial class BasePrinter : IPrinter, IDisposable
|
||||
{
|
||||
private bool disposed = false;
|
||||
|
||||
//private volatile bool _isMonitoring;
|
||||
|
||||
private CancellationTokenSource _readCancellationTokenSource;
|
||||
private CancellationTokenSource _writeCancellationTokenSource;
|
||||
|
||||
private readonly int _maxBytesPerWrite = 15000; // max byte chunks to write at once.
|
||||
|
||||
public PrinterStatusEventArgs Status { get; private set; } = new PrinterStatusEventArgs();
|
||||
|
||||
public event EventHandler StatusChanged;
|
||||
public event EventHandler Disconnected;
|
||||
public event EventHandler Connected;
|
||||
//public event EventHandler WriteFailed;
|
||||
//public event EventHandler Idle;
|
||||
|
||||
protected BinaryWriter Writer { get; set; }
|
||||
|
||||
protected BinaryReader Reader { get; set; }
|
||||
|
||||
protected ConcurrentQueue<byte> ReadBuffer { get; set; } = new ConcurrentQueue<byte>();
|
||||
|
||||
protected ConcurrentQueue<byte[]> WriteBuffer { get; set; } = new ConcurrentQueue<byte[]>();
|
||||
|
||||
protected int BytesWrittenSinceLastFlush { get; set; } = 0;
|
||||
|
||||
protected volatile bool IsConnected = true;
|
||||
|
||||
public string PrinterName { get; protected set; }
|
||||
|
||||
protected BasePrinter()
|
||||
{
|
||||
PrinterName = Guid.NewGuid().ToString();
|
||||
Init();
|
||||
}
|
||||
protected BasePrinter(string printerName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(printerName))
|
||||
{
|
||||
printerName = Guid.NewGuid().ToString();
|
||||
}
|
||||
PrinterName = printerName;
|
||||
Init();
|
||||
}
|
||||
private void Init()
|
||||
{
|
||||
_readCancellationTokenSource = new CancellationTokenSource();
|
||||
_writeCancellationTokenSource = new CancellationTokenSource();
|
||||
Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Initializing Task Threads...", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
//Task.Factory.StartNew(MonitorPrinterStatusLongRunningTask, _connectivityCancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);
|
||||
Task.Factory.StartNew(WriteLongRunningTask, _writeCancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);
|
||||
Task.Factory.StartNew(ReadLongRunningTask, _readCancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);
|
||||
// TODO: read and status monitoring probably won't work for fileprinter, should let printer types disable this feature.
|
||||
Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Task Threads started", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
|
||||
|
||||
protected void InvokeConnect()
|
||||
{
|
||||
Task.Run(() => Connected?.Invoke(this, new ConnectionEventArgs() { IsConnected = true }));
|
||||
}
|
||||
protected void InvokeDisconnect()
|
||||
{
|
||||
Task.Run(() => Disconnected?.Invoke(this, new ConnectionEventArgs() { IsConnected = false }));
|
||||
}
|
||||
|
||||
protected virtual void Reconnect()
|
||||
{
|
||||
// Implemented in the network printer
|
||||
}
|
||||
protected virtual async void WriteLongRunningTask()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_writeCancellationTokenSource != null && _writeCancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Write Long-Running Task Cancellation was requested.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
break;
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
if (!IsConnected)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var didDequeue = WriteBuffer.TryDequeue(out var nextBytes);
|
||||
if (didDequeue && nextBytes?.Length > 0)
|
||||
{
|
||||
WriteToBinaryWriter(nextBytes);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
// Thrown if the printer times out the socket connection
|
||||
// default is 90 seconds
|
||||
//Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Swallowing IOException... sometimes happens with network printers. Should get reconnected automatically.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Swallow the exception
|
||||
//Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Swallowing generic read exception... sometimes happens with serial port printers.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async void ReadLongRunningTask()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_readCancellationTokenSource != null && _readCancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Read Long-Running Task Cancellation was requested.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
break;
|
||||
}
|
||||
|
||||
await Task.Delay(100);
|
||||
|
||||
if (Reader == null) continue;
|
||||
if (!IsConnected) continue;
|
||||
|
||||
try
|
||||
{
|
||||
// Sometimes the serial port lib will throw an exception and read past the end of the queue if a
|
||||
// status changes while data is being written. We just ignore these bytes.
|
||||
var b = Reader.BaseStream.ReadByte();
|
||||
if (b >= 0 && b <= 255)
|
||||
{
|
||||
ReadBuffer.Enqueue((byte)b);
|
||||
DataAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Swallow the exception
|
||||
//Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Swallowing generic read exception... sometimes happens with serial port printers.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Write(params byte[][] arrays)
|
||||
{
|
||||
Write(ByteSplicer.Combine(arrays));
|
||||
}
|
||||
|
||||
public virtual void Write(byte[] bytes)
|
||||
{
|
||||
WriteBuffer.Enqueue(bytes);
|
||||
}
|
||||
|
||||
protected virtual void WriteToBinaryWriter(byte[] bytes)
|
||||
{
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Logging.Logger?.LogInformation("[{Function}]:[{PrinterName}] Attempted to write but printer isn't connected. Attempting to reconnect...", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
Reconnect();
|
||||
}
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
Logging.Logger?.LogError("[{Function}]:[{PrinterName}] Unrecoverable connectivity error writing to printer.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
throw new IOException("Unrecoverable connectivity error writing to printer.");
|
||||
}
|
||||
|
||||
int bytePointer = 0;
|
||||
int bytesLeft = bytes.Length;
|
||||
bool hasFlushed = false;
|
||||
while (bytesLeft > 0)
|
||||
{
|
||||
|
||||
int count = Math.Min(_maxBytesPerWrite, bytesLeft);
|
||||
try
|
||||
{
|
||||
Writer.Write(bytes, bytePointer, count);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
Reconnect();
|
||||
if (!IsConnected)
|
||||
{
|
||||
Logging.Logger?.LogError(e, "[{Function}]:[{PrinterName}] Unrecoverable connectivity error writing to printer.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
Writer.Write(bytes, bytePointer, count);
|
||||
}
|
||||
BytesWrittenSinceLastFlush += count;
|
||||
if (BytesWrittenSinceLastFlush >= 200)
|
||||
{
|
||||
// Immediately trigger a flush before proceeding so the output buffer will not be delayed.
|
||||
hasFlushed = true;
|
||||
Flush(null, null);
|
||||
}
|
||||
|
||||
bytePointer += count;
|
||||
bytesLeft -= count;
|
||||
}
|
||||
|
||||
if (!hasFlushed)
|
||||
{
|
||||
Task.Run(async () => { await Task.Delay(50); Flush(null, null); });
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Flush(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
BytesWrittenSinceLastFlush = 0;
|
||||
Writer.Flush();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Logger?.LogError(ex, "[{Function}]:[{PrinterName}] Flush threw exception.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void DataAvailable()
|
||||
{
|
||||
if (ReadBuffer.Count() % 4 == 0)
|
||||
{
|
||||
var bytes = new byte[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (!ReadBuffer.TryDequeue(out bytes[i]))
|
||||
{
|
||||
// Ran out of bytes unexpectedly.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TryUpdatePrinterStatus(bytes);
|
||||
|
||||
// TODO: call other update handlers.
|
||||
}
|
||||
}
|
||||
|
||||
private void TryUpdatePrinterStatus(byte[] bytes)
|
||||
{
|
||||
var bytesToString = BitConverter.ToString(bytes);
|
||||
|
||||
Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] TryUpdatePrinterStatus: Received flag values {bytesToString}", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName, bytesToString);
|
||||
|
||||
// Check header bits 0, 1 and 7 are 0, and 4 is 1
|
||||
if (bytes[0].IsBitNotSet(0) && bytes[0].IsBitNotSet(1) && bytes[0].IsBitSet(4) && bytes[0].IsBitNotSet(7))
|
||||
{
|
||||
Status = new PrinterStatusEventArgs()
|
||||
{
|
||||
// byte[0] == 20 cash drawer closed
|
||||
// byte[0] == 16 cash drawer open
|
||||
// Note some cash drawers do not close properly.
|
||||
IsCashDrawerOpen = bytes[0].IsBitNotSet(2),
|
||||
IsPrinterOnline = bytes[0].IsBitNotSet(3),
|
||||
IsCoverOpen = bytes[0].IsBitSet(5),
|
||||
IsPaperCurrentlyFeeding = bytes[0].IsBitSet(6),
|
||||
IsWaitingForOnlineRecovery = bytes[1].IsBitSet(0),
|
||||
IsPaperFeedButtonPushed = bytes[1].IsBitSet(1),
|
||||
DidRecoverableNonAutocutterErrorOccur = bytes[1].IsBitSet(2),
|
||||
DidAutocutterErrorOccur = bytes[1].IsBitSet(3),
|
||||
DidUnrecoverableErrorOccur = bytes[1].IsBitSet(5),
|
||||
DidRecoverableErrorOccur = bytes[1].IsBitSet(6),
|
||||
IsPaperLow = bytes[2].IsBitSet(0) && bytes[2].IsBitSet(1),
|
||||
IsPaperOut = bytes[2].IsBitSet(2) && bytes[2].IsBitSet(3),
|
||||
};
|
||||
}
|
||||
|
||||
if (StatusChanged != null)
|
||||
{
|
||||
Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Invoking Status Changed Event Handler...", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
StatusChanged?.Invoke(this, Status);
|
||||
}
|
||||
}
|
||||
|
||||
~BasePrinter()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void OverridableDispose() // This method should only be called by the Dispose method. // It allows synchronous disposing of derived class dependencies with base class disposes.
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
_readCancellationTokenSource?.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logger?.LogDebug(e, "[{Function}]:[{PrinterName}] Dispose Issue during cancellation token cancellation call.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
try
|
||||
{
|
||||
Reader?.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logger?.LogDebug(e, "[{Function}]:[{PrinterName}] Dispose Issue closing reader.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
try
|
||||
{
|
||||
Reader?.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logger?.LogDebug(e, "[{Function}]:[{PrinterName}] Dispose Issue disposing reader.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
try
|
||||
{
|
||||
Writer?.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logger?.LogDebug(e, "[{Function}]:[{PrinterName}] Dispose Issue closing writer.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
try
|
||||
{
|
||||
Writer?.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logger?.LogDebug(e, "[{Function}]:[{PrinterName}] Dispose Issue disposing writer.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
try
|
||||
{
|
||||
OverridableDispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logger?.LogDebug(e, "[{Function}]:[{PrinterName}] Dispose Issue during overridable dispose.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
|
||||
}
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
public PrinterStatusEventArgs GetStatus()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class ConnectionEventArgs : EventArgs
|
||||
{
|
||||
public bool IsConnected;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.IO;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class FilePrinter : BasePrinter
|
||||
{
|
||||
private readonly FileStream _file;
|
||||
|
||||
// TODO: default values to their default values in ctor.
|
||||
public FilePrinter(string filePath, bool createIfNotExists = false)
|
||||
: base()
|
||||
{
|
||||
if (createIfNotExists)
|
||||
{
|
||||
_file = File.Open(filePath, FileMode.OpenOrCreate);
|
||||
}
|
||||
else
|
||||
{
|
||||
_file = File.Open(filePath, FileMode.Open);
|
||||
}
|
||||
Writer = new BinaryWriter(_file);
|
||||
Reader = new BinaryReader(_file);
|
||||
}
|
||||
|
||||
~FilePrinter()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected override void OverridableDispose()
|
||||
{
|
||||
_file?.Close();
|
||||
_file?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public interface IPrinter
|
||||
{
|
||||
PrinterStatusEventArgs GetStatus();
|
||||
void Write(params byte[][] arrays);
|
||||
void Write(byte[] bytes);
|
||||
event EventHandler StatusChanged;
|
||||
event EventHandler Disconnected;
|
||||
event EventHandler Connected;
|
||||
//event EventHandler WriteFailed;
|
||||
//event EventHandler Idle;
|
||||
//event EventHandler IdleDisconnected; is this useful? to know that it disconnected because of idle? probably better to have this as info in disconnected event object instead.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.IO;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class MemoryPrinter : BasePrinter
|
||||
{
|
||||
private readonly MemoryStream _ms;
|
||||
|
||||
// TODO: default values to their default values in ctor.
|
||||
public MemoryPrinter()
|
||||
: base()
|
||||
{
|
||||
_ms = new MemoryStream();
|
||||
Writer = new BinaryWriter(_ms);
|
||||
}
|
||||
|
||||
~MemoryPrinter()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public byte[] GetAllData()
|
||||
{
|
||||
return _ms.ToArray();
|
||||
}
|
||||
|
||||
protected override void OverridableDispose()
|
||||
{
|
||||
_ms?.Close();
|
||||
_ms?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using SimpleTcp;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class NetworkPrinterSettings
|
||||
{
|
||||
// Connection string is of the form printer_name:port or ip:port
|
||||
public string ConnectionString { get; set; }
|
||||
public EventHandler ConnectedHandler { get; set; }
|
||||
public EventHandler DisconnectedHandler { get; set; }
|
||||
//public bool ReconnectOnTimeout { get; set; }
|
||||
//public uint? ReceiveTimeoutMs { get; set; }
|
||||
//public uint? SendTimeoutMs { get; set; }
|
||||
//public uint? ConnectTimeoutMs { get; set; }
|
||||
//public uint? ReconnectTimeoutMs { get; set; }
|
||||
//public uint? MaxReconnectAttempts { get; set; }
|
||||
public string PrinterName { get; set; }
|
||||
}
|
||||
public class NetworkPrinter : BasePrinter
|
||||
{
|
||||
private readonly NetworkPrinterSettings _settings;
|
||||
private TCPConnection _tcpConnection;
|
||||
|
||||
public NetworkPrinter(NetworkPrinterSettings settings) : base(settings.PrinterName)
|
||||
{
|
||||
_settings = settings;
|
||||
if (settings.ConnectedHandler != null)
|
||||
{
|
||||
Connected += settings.ConnectedHandler;
|
||||
}
|
||||
if (settings.DisconnectedHandler != null)
|
||||
{
|
||||
Disconnected += settings.DisconnectedHandler;
|
||||
}
|
||||
Connect();
|
||||
}
|
||||
|
||||
private void ConnectedEvent(object sender, ClientConnectedEventArgs e)
|
||||
{
|
||||
Logging.Logger?.LogInformation("[{Function}]:[{PrinterName}] Connected successfully to network printer! Connection String: {ConnectionString}", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName, _settings.ConnectionString);
|
||||
IsConnected = true;
|
||||
InvokeConnect();
|
||||
}
|
||||
private void DisconnectedEvent(object sender, ClientDisconnectedEventArgs e)
|
||||
{
|
||||
IsConnected = false;
|
||||
InvokeDisconnect();
|
||||
Logging.Logger?.LogWarning("[{Function}]:[{PrinterName}] Network printer connection terminated. Attempting to reconnect. Connection String: {ConnectionString}", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName, _settings.ConnectionString);
|
||||
Connect();
|
||||
}
|
||||
private void AttemptReconnectInfinitely()
|
||||
{
|
||||
try
|
||||
{
|
||||
//_tcpConnection.ConnectWithRetries(300000);
|
||||
_tcpConnection.ConnectWithRetries(3000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//Logging.Logger?.LogWarning("[{Function}]:[{PrinterName}] Network printer unable to connect after 5 minutes. Attempting to reconnect. Settings: {Settings}", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName, JsonSerializer.Serialize(_settings));
|
||||
Task.Run(async () => { await Task.Delay(250); Connect(); });
|
||||
}
|
||||
}
|
||||
|
||||
private void Connect()
|
||||
{
|
||||
if (_tcpConnection != null)
|
||||
{
|
||||
_tcpConnection.Connected -= ConnectedEvent;
|
||||
_tcpConnection.Disconnected -= DisconnectedEvent;
|
||||
}
|
||||
|
||||
// instantiate
|
||||
_tcpConnection = new TCPConnection(_settings.ConnectionString);
|
||||
|
||||
// set events
|
||||
_tcpConnection.Connected += ConnectedEvent;
|
||||
_tcpConnection.Disconnected += DisconnectedEvent;
|
||||
|
||||
Reader = new BinaryReader(_tcpConnection.ReadStream);
|
||||
Writer = new BinaryWriter(_tcpConnection.WriteStream);
|
||||
|
||||
Task.Run(() => { AttemptReconnectInfinitely(); });
|
||||
}
|
||||
|
||||
protected override void OverridableDispose()
|
||||
{
|
||||
_tcpConnection = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class PrinterOptions
|
||||
{
|
||||
int IdleTimeoutSeconds { get; set; } = 60;
|
||||
int StatusPollingIntervalMilliseconds { get; set; } = 500;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class PrinterStatusEventArgs : EventArgs
|
||||
{
|
||||
public bool? IsWaitingForOnlineRecovery { get; set; }
|
||||
|
||||
public bool? IsPaperCurrentlyFeeding { get; set; }
|
||||
|
||||
public bool? IsPaperFeedButtonPushed { get; set; }
|
||||
|
||||
public bool? IsPrinterOnline { get; set; }
|
||||
|
||||
public bool? IsCashDrawerOpen { get; set; }
|
||||
|
||||
public bool? IsCoverOpen { get; set; }
|
||||
|
||||
public bool? IsPaperLow { get; set; }
|
||||
|
||||
public bool? IsPaperOut { get; set; }
|
||||
|
||||
public bool? IsInErrorState => (DidRecoverableErrorOccur ?? false) || (DidUnrecoverableErrorOccur ?? false) || (DidAutocutterErrorOccur ?? false) || (DidRecoverableNonAutocutterErrorOccur ?? false);
|
||||
|
||||
public bool? DidRecoverableErrorOccur { get; set; }
|
||||
|
||||
public bool? DidUnrecoverableErrorOccur { get; set; }
|
||||
|
||||
public bool? DidAutocutterErrorOccur { get; set; }
|
||||
|
||||
public bool? DidRecoverableNonAutocutterErrorOccur { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class SerialPrinter : BasePrinter
|
||||
{
|
||||
private readonly SerialPort _serialPort;
|
||||
|
||||
public SerialPrinter(string portName, int baudRate)
|
||||
: base()
|
||||
{
|
||||
_serialPort = new SerialPort(portName, baudRate);
|
||||
_serialPort.Open();
|
||||
Writer = new BinaryWriter(_serialPort.BaseStream);
|
||||
Reader = new BinaryReader(_serialPort.BaseStream);
|
||||
}
|
||||
|
||||
protected override void OverridableDispose()
|
||||
{
|
||||
_serialPort?.Close();
|
||||
_serialPort?.Dispose();
|
||||
Task.Delay(250).Wait(); // Based on MSDN Documentation, should sleep after calling Close or some functionality will not be determinant.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// TODO: Implement this class
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class VirtualPrinter
|
||||
{
|
||||
public byte[] Output { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ESCPOS_NET.Utils
|
||||
{
|
||||
public static class Consts
|
||||
{
|
||||
public static readonly string LIBNAME = "ESCPOS_NET";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace ESCPOS_NET.Utils
|
||||
{
|
||||
|
||||
public class EchoStream : Stream
|
||||
{
|
||||
public override bool CanTimeout { get; } = true;
|
||||
public override int ReadTimeout { get; set; } = Timeout.Infinite;
|
||||
public override int WriteTimeout { get; set; } = Timeout.Infinite;
|
||||
public override bool CanRead { get; } = true;
|
||||
public override bool CanSeek { get; } = false;
|
||||
public override bool CanWrite { get; } = true;
|
||||
|
||||
public bool CopyBufferOnWrite { get; set; } = false;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
// Default underlying mechanism for BlockingCollection is ConcurrentQueue<T>, which is what we want
|
||||
private readonly BlockingCollection<byte[]> _Buffers;
|
||||
private int _maxQueueDepth = 10;
|
||||
|
||||
private byte[] m_buffer = null;
|
||||
private int m_offset = 0;
|
||||
private int m_count = 0;
|
||||
|
||||
private bool m_Closed = false;
|
||||
public override void Close()
|
||||
{
|
||||
m_Closed = true;
|
||||
|
||||
// release any waiting writes
|
||||
_Buffers.CompleteAdding();
|
||||
}
|
||||
|
||||
public bool DataAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Buffers.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private long _Length = 0L;
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Length;
|
||||
}
|
||||
}
|
||||
|
||||
private long _Position = 0L;
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
return _Position;
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public EchoStream() : this(10)
|
||||
{
|
||||
}
|
||||
|
||||
public EchoStream(int maxQueueDepth)
|
||||
{
|
||||
_maxQueueDepth = maxQueueDepth;
|
||||
_Buffers = new BlockingCollection<byte[]>(_maxQueueDepth);
|
||||
}
|
||||
|
||||
// we override the xxxxAsync functions because the default base class shares state between ReadAsync and WriteAsync, which causes a hang if both are called at once
|
||||
public new Task WriteAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return Task.Run(() => Write(buffer, offset, count));
|
||||
}
|
||||
|
||||
// we override the xxxxAsync functions because the default base class shares state between ReadAsync and WriteAsync, which causes a hang if both are called at once
|
||||
public new Task<int> ReadAsync(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
return Read(buffer, offset, count);
|
||||
});
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (m_Closed || buffer.Length - offset < count || count <= 0)
|
||||
return;
|
||||
|
||||
byte[] newBuffer;
|
||||
if (!CopyBufferOnWrite && offset == 0 && count == buffer.Length)
|
||||
newBuffer = buffer;
|
||||
else
|
||||
{
|
||||
newBuffer = new byte[count];
|
||||
System.Buffer.BlockCopy(buffer, offset, newBuffer, 0, count);
|
||||
}
|
||||
if (!_Buffers.TryAdd(newBuffer, WriteTimeout))
|
||||
throw new TimeoutException("EchoStream Write() Timeout");
|
||||
|
||||
_Length += count;
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (count == 0)
|
||||
return 0;
|
||||
lock (_lock)
|
||||
{
|
||||
if (m_count == 0 && _Buffers.Count == 0)
|
||||
{
|
||||
if (m_Closed)
|
||||
return -1;
|
||||
|
||||
if (_Buffers.TryTake(out m_buffer, ReadTimeout))
|
||||
{
|
||||
m_offset = 0;
|
||||
m_count = m_buffer.Length;
|
||||
}
|
||||
else
|
||||
return m_Closed ? -1 : 0;
|
||||
}
|
||||
|
||||
int returnBytes = 0;
|
||||
while (count > 0)
|
||||
{
|
||||
if (m_count == 0)
|
||||
{
|
||||
if (_Buffers.TryTake(out m_buffer, 0))
|
||||
{
|
||||
m_offset = 0;
|
||||
m_count = m_buffer.Length;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
var bytesToCopy = (count < m_count) ? count : m_count;
|
||||
System.Buffer.BlockCopy(m_buffer, m_offset, buffer, offset, bytesToCopy);
|
||||
m_offset += bytesToCopy;
|
||||
m_count -= bytesToCopy;
|
||||
offset += bytesToCopy;
|
||||
count -= bytesToCopy;
|
||||
|
||||
returnBytes += bytesToCopy;
|
||||
}
|
||||
|
||||
_Position += returnBytes;
|
||||
|
||||
return returnBytes;
|
||||
}
|
||||
}
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
byte[] returnValue = new byte[1];
|
||||
return (Read(returnValue, 0, 1) <= 0 ? -1 : (int)returnValue[0]);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class InterceptableWriteMemoryStream : Stream
|
||||
{
|
||||
private MemoryStream _innerStream = new MemoryStream();
|
||||
public override bool CanRead => _innerStream.CanRead;
|
||||
|
||||
public override bool CanSeek => _innerStream.CanSeek;
|
||||
|
||||
public override bool CanWrite => _innerStream.CanWrite;
|
||||
|
||||
public override long Length => _innerStream.Length;
|
||||
|
||||
public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; }
|
||||
|
||||
private Action<byte[]> _writeAction { get; set; }
|
||||
public InterceptableWriteMemoryStream(Action<byte[]> writeAction)
|
||||
{
|
||||
_writeAction = writeAction;
|
||||
}
|
||||
public override void Flush()
|
||||
{
|
||||
_innerStream.Flush();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
return _innerStream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
return _innerStream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
_innerStream.SetLength(value);
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
var writeArray = new byte[count];
|
||||
Buffer.BlockCopy(buffer, offset, writeArray, 0, count);
|
||||
_writeAction(writeArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using ESCPOS_NET.Utils;
|
||||
using SimpleTcp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class TCPConnection
|
||||
{
|
||||
public Stream ReadStream { get; private set; } = new EchoStream();
|
||||
public Stream WriteStream { get; private set; }
|
||||
public event EventHandler<ClientConnectedEventArgs> Connected;
|
||||
public event EventHandler<ClientDisconnectedEventArgs> Disconnected;
|
||||
public bool IsConnected => _client?.IsConnected ?? false;
|
||||
private SimpleTcpClient _client;
|
||||
//public event EventHandler<DataReceivedEventArgs> DataReceived;
|
||||
public TCPConnection(string destination)
|
||||
{
|
||||
_client = new SimpleTcpClient(destination);
|
||||
_client.Events.Connected += ConnectedEventHandler;
|
||||
_client.Events.Disconnected += DisconnectedEventHandler;
|
||||
_client.Events.DataReceived += DataReceivedEventHandler;
|
||||
_client.Keepalive = new SimpleTcpKeepaliveSettings() { EnableTcpKeepAlives = true, TcpKeepAliveInterval = 1, TcpKeepAliveTime = 1, TcpKeepAliveRetryCount = 3 };
|
||||
ReadStream.ReadTimeout = 1500;
|
||||
WriteStream = new InterceptableWriteMemoryStream(bytes => _client.Send(bytes));
|
||||
}
|
||||
private void ConnectedEventHandler(object sender, ClientConnectedEventArgs e)
|
||||
{
|
||||
Connected?.Invoke(sender, e);
|
||||
}
|
||||
private void DisconnectedEventHandler(object sender, ClientDisconnectedEventArgs e)
|
||||
{
|
||||
Disconnected?.Invoke(sender, e);
|
||||
}
|
||||
private void DataReceivedEventHandler(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
ReadStream.Write(e.Data, 0, e.Data.Length);
|
||||
}
|
||||
public void ConnectWithRetries(int timeoutMs)
|
||||
{
|
||||
_client.ConnectWithRetries(timeoutMs);
|
||||
}
|
||||
|
||||
~TCPConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
_client.Events.DataReceived -= DataReceivedEventHandler;
|
||||
_client.Events.Connected -= ConnectedEventHandler;
|
||||
_client.Events.Disconnected -= DisconnectedEventHandler;
|
||||
_client?.Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Luke Paireepinart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,212 @@
|
||||
<img src="https://raw.githubusercontent.com/lukevp/ESC-POS-.NET/master/banner2.jpg" />
|
||||
<h1 align="center">ESCPOS.NET - Easy to use, Cross-Platform, Fast and Efficient.</h1>
|
||||
<br />
|
||||
<p align="center">
|
||||
<a href="https://raw.githubusercontent.com/lukevp/ESC-POS-.NET/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/lukevp/ESC-POS-.NET" />
|
||||
</a>
|
||||
<a href="https://github.com/lukevp/ESC-POS-.NET/issues">
|
||||
<img src="https://img.shields.io/github/issues/lukevp/ESC-POS-.NET" />
|
||||
<img alt="GitHub closed issues" src="https://img.shields.io/github/issues-closed/lukevp/ESC-POS-.NET">
|
||||
</a>
|
||||
<a href="https://www.nuget.org/packages/ESCPOS_NET/">
|
||||
<img alt="Nuget" src="https://img.shields.io/nuget/dt/ESCPOS_NET?label=NuGet%20downloads">
|
||||
</a>
|
||||
<a href="https://github.com/lukevp/ESC-POS-.NET/graphs/contributors">
|
||||
<img alt="GitHub contributors" src="https://img.shields.io/github/contributors/lukevp/ESC-POS-.NET">
|
||||
</a>
|
||||
</p>
|
||||
ESCPOS.NET is a super easy to use library that supports the most common functionality of the ESC/POS standard by Epson. It is highly compatible, and runs on full framework .NET as well as .NET Core.
|
||||
|
||||
It works with Serial, USB, Ethernet, and WiFi printers, and works great on Windows, Linux and OSX.
|
||||
|
||||
This library is used for thermal receipt printers, line displays, cash drawers, and more!
|
||||
|
||||
ESC/POS is a binary protocol that's a type of "raw" text, which means you do not need drivers to use it.
|
||||
|
||||
This library encompasses helper functions that assist in creating the binary command stream that is needed to control this hardware, as well as the underlying communications that are needed to interface with the hardware.
|
||||
|
||||
This means that Bluetooth, WiFi, Ethernet, USB, and Serial printers are all usable with just this software library and nothing else.
|
||||
|
||||
# Get Started
|
||||
|
||||
## Step 1: Create a Printer object
|
||||
```csharp
|
||||
// Ethernet or WiFi
|
||||
var printer = new NetworkPrinter(ipAddress: "192.168.1.50", port: 9000, reconnectOnTimeout: true);
|
||||
|
||||
// USB, Bluetooth, or Serial
|
||||
var printer = new SerialPrinter(portName: "COM5", baudRate: 115200);
|
||||
|
||||
// Linux output to USB / Serial file
|
||||
var printer = new FilePrinter(filePath: "/dev/usb/lp0");
|
||||
```
|
||||
## Step 1a (optional): Monitor for Events - out of paper, cover open...
|
||||
```csharp
|
||||
// Define a callback method.
|
||||
static void StatusChanged(object sender, EventArgs ps)
|
||||
{
|
||||
var status = (PrinterStatusEventArgs)ps;
|
||||
Console.WriteLine($"Status: {status.IsPrinterOnline}");
|
||||
Console.WriteLine($"Has Paper? {status.IsPaperOut}");
|
||||
Console.WriteLine($"Paper Running Low? {status.IsPaperLow}");
|
||||
Console.WriteLine($"Cash Drawer Open? {status.IsCashDrawerOpen}");
|
||||
Console.WriteLine($"Cover Open? {status.IsCoverOpen}");
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
// In your program, register event handler to call the method when printer status changes:
|
||||
printer.StatusChanged += StatusChanged;
|
||||
|
||||
// and start monitoring for changes.
|
||||
printer.StartMonitoring();
|
||||
|
||||
```
|
||||
|
||||
## Step 2: Write a receipt to the printer
|
||||
```csharp
|
||||
var e = new EPSON();
|
||||
printer.Write(
|
||||
ByteSplicer.Combine(
|
||||
e.CenterAlign(),
|
||||
e.PrintImage(File.ReadAllBytes("images/pd-logo-300.png"), true),
|
||||
e.PrintLine(),
|
||||
e.SetBarcodeHeightInDots(360),
|
||||
e.SetBarWidth(BarWidth.Default),
|
||||
e.SetBarLabelPosition(BarLabelPrintPosition.None),
|
||||
e.PrintBarcode(BarcodeType.ITF, "0123456789"),
|
||||
e.PrintLine(),
|
||||
e.PrintLine("B&H PHOTO & VIDEO"),
|
||||
e.PrintLine("420 NINTH AVE."),
|
||||
e.PrintLine("NEW YORK, NY 10001"),
|
||||
e.PrintLine("(212) 502-6380 - (800)947-9975"),
|
||||
e.SetStyles(PrintStyle.Underline),
|
||||
e.PrintLine("www.bhphotovideo.com"),
|
||||
e.SetStyles(PrintStyle.None),
|
||||
e.PrintLine(),
|
||||
e.LeftAlign(),
|
||||
e.PrintLine("Order: 123456789 Date: 02/01/19"),
|
||||
e.PrintLine(),
|
||||
e.PrintLine(),
|
||||
e.SetStyles(PrintStyle.FontB),
|
||||
e.PrintLine("1 TRITON LOW-NOISE IN-LINE MICROPHONE PREAMP"),
|
||||
e.PrintLine(" TRFETHEAD/FETHEAD 89.95 89.95"),
|
||||
e.PrintLine("----------------------------------------------------------------"),
|
||||
e.RightAlign(),
|
||||
e.PrintLine("SUBTOTAL 89.95"),
|
||||
e.PrintLine("Total Order: 89.95"),
|
||||
e.PrintLine("Total Payment: 89.95"),
|
||||
e.PrintLine(),
|
||||
e.LeftAlign(),
|
||||
e.SetStyles(PrintStyle.Bold | PrintStyle.FontB),
|
||||
e.PrintLine("SOLD TO: SHIP TO:"),
|
||||
e.SetStyles(PrintStyle.FontB),
|
||||
e.PrintLine(" FIRSTN LASTNAME FIRSTN LASTNAME"),
|
||||
e.PrintLine(" 123 FAKE ST. 123 FAKE ST."),
|
||||
e.PrintLine(" DECATUR, IL 12345 DECATUR, IL 12345"),
|
||||
e.PrintLine(" (123)456-7890 (123)456-7890"),
|
||||
e.PrintLine(" CUST: 87654321"),
|
||||
e.PrintLine(),
|
||||
e.PrintLine()
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
# Supported Platforms
|
||||
Desktop support (WiFI, Ethernet, Bluetooth, USB, Serial):
|
||||
* Windows
|
||||
- Windows 7+ can support .NET Core or the .NET 471 runtime, and can use this library.
|
||||
* Linux
|
||||
- ARM platforms such as Raspberry Pi
|
||||
- x86/64 platform
|
||||
* Mac OSX
|
||||
- Tested on high sierra
|
||||
|
||||
Mobile support (WiFi/Ethernet only):
|
||||
* iOS
|
||||
- Xamarin.iOS
|
||||
* Android
|
||||
- Xamarin.Android
|
||||
* Windows
|
||||
- UWP
|
||||
|
||||
# Supported Hardware
|
||||
Epson thermal receipt printers are supported, and most common functions such as test printing, styling, alignment, image printing, and barcode printing.
|
||||
|
||||
Generic thermal printers that implement ESC/POS typically work, for example the Royal PT-300, and BemaTech printers are also tested by some members of the community, @juliogamasso and @ivanmontilla.
|
||||
|
||||
Cash Drawers are supported, as are Line Displays.
|
||||
|
||||
|
||||
## Further Documentation and Usage
|
||||
Check out the ESCPOS_NET.ConsoleTest for a comprehensive test suite that covers all implemented functions.
|
||||
|
||||
This package is available on NuGet @ https://www.nuget.org/packages/ESCPOS_NET/
|
||||
|
||||
Please comment / DM / open issues and let me know how the library is working for you!
|
||||
|
||||
## Contributors
|
||||
Thanks to all of our contributors working to make this the best .NET thermal printer library out there!!
|
||||
|
||||
* [@lukevp](https://github.com/lukevp)
|
||||
* [@juliogamasso](https://github.com/juliogamasso)
|
||||
* [@naaeef](https://github.com/naaeef)
|
||||
* [@netgg93](https://github.com/netgg93)
|
||||
* [@igorocampos](https://github.com/igorocampos)
|
||||
* [@kodejack](https://github.com/kodejack)
|
||||
|
||||
# USB Usage Guide
|
||||
|
||||
For cross-platform support and ease of maintenance, all USB printers are supported over Serial-USB interfaces. These are full-speed and work just as well as native USB as long as you have your port settings optimized.
|
||||
|
||||
On Linux and Mac, USB for Epson printers is exposed as a serial port directly by the os under /dev/ttyusb or something similar based on your platform, and doesn't require drivers.
|
||||
|
||||
On Windows, you must install some type of virtual COM port driver for native USB support, and then map your printer to a specific port, or use a USB-Serial cable and use a serial printer.
|
||||
|
||||
If you have an official Epson printer, the link to install it from Epson is here: https://download.epson-biz.com/modules/pos/index.php?page=single_soft&cid=6481&scat=36&pcat=5
|
||||
|
||||
If you do not have an official Epson printer, you will have to find a compatible way to expose the USB interface as a virtual Serial port.
|
||||
|
||||
NOTE: The cross platform .NET library we use from Microsoft only supports COM ports 8 and below on windows, so be sure not to use a very high # COM port.
|
||||
|
||||
|
||||
# Implemented Commands
|
||||
|
||||
## Bit Image Commands
|
||||
* `ESC ✻` Select bit-image mode
|
||||
* `GS ( L` OR `GS 8 L` Set graphics data
|
||||
* Set the reference dot density for graphics.
|
||||
* Print the graphics data in the print buffer.
|
||||
* Store the graphics data in the print buffer (raster format).
|
||||
|
||||
## Character Commands
|
||||
* `ESC !` Select print mode(s)
|
||||
* `GS B` Turn white/black reverse print mode on/off - Thanks @juliogamasso!
|
||||
|
||||
|
||||
## Print Commands
|
||||
* `LF` Print and line feed
|
||||
* `CR` Print and carriage return
|
||||
* `ESC J` Print and feed paper
|
||||
* `ESC K` Print and reverse feed
|
||||
* `ESC d` Print and feed n lines
|
||||
* `ESC e` Print and reverse feed n lines
|
||||
|
||||
## Bar Code Commands
|
||||
* `GS H` Select print position of HRI characters
|
||||
* `GS f` Select font for HRI characters
|
||||
* `GS h` Set bar code height
|
||||
* `GS k` Print bar code
|
||||
* `GS w` Set bar code width
|
||||
|
||||
## Status Commands
|
||||
* `GS a` Enable/disable Automatic Status Back (ASB)
|
||||
|
||||
## Open Cash Drawer Commands
|
||||
* `ESC p 0` Open cash drawer pin 2
|
||||
* `ESC p 1` Open cash drawer pin 5
|
||||
|
||||
## Miscellaneous Commands
|
||||
* `ESC @` Initialize printer
|
||||
|
After Width: | Height: | Size: 127 KiB |
@@ -0,0 +1,494 @@
|
||||
## Line Spacing Commands
|
||||
* ESC 2 Select default line spacing
|
||||
* ESC 3 Set line spacing
|
||||
|
||||
## Character Commands
|
||||
* `ESC SP` Set right-side character spacing
|
||||
* `ESC –` Turn underline mode on/off
|
||||
* `ESC E` Turn emphasized mode on/off
|
||||
* `ESC G` Turn double-strike mode on/off
|
||||
* `ESC M` Select character font
|
||||
* `ESC V` Turn 90° clockwise rotation mode on/off
|
||||
* `ESC r` Select print color
|
||||
* `ESC t` Select character code table
|
||||
* `ESC {` Turn upside-down print mode on/off
|
||||
* `GS !` Select character size
|
||||
* `GS b` Turn smoothing mode on/off
|
||||
|
||||
## Panel Button Commands
|
||||
* `ESC c 5` Enable/disable panel buttons
|
||||
|
||||
## Paper Sensor Commands
|
||||
@@this is for parallel only ESC c 3 Select paper sensor(s) to output paper-end signals
|
||||
@@this should stop by default ESC c 4 Select paper sensor(s) to stop printing
|
||||
|
||||
## Print Position Commands
|
||||
* `HT` Horizontal tab
|
||||
* `ESC $` Set absolute print position
|
||||
* `ESC D` Set horizontal tab positions
|
||||
* `ESC a` Select justification
|
||||
* `GS L` Set left margin
|
||||
* `GS W` Set print area width
|
||||
|
||||
## Bit Image Commands
|
||||
* `ESC *` Select bit-image mode
|
||||
|
||||
|
||||
|
||||
## Mechanism Control Commands
|
||||
* `ESC U` Turn unidirectional print mode on/off
|
||||
* `GS V` Select cut mode and cut paper
|
||||
|
||||
## Miscellaneous Commands
|
||||
* `ESC @` Initialize printer
|
||||
* `DLE ENQ` Send real-time request to printer
|
||||
* `DLE DC4 (fn = 1)` Generate pulse in real-time
|
||||
* `DLE DC4 (fn = 2)` Execute power-off sequence
|
||||
|
||||
TODO: check for DLE DC4 other functions and any other real time commands to make sure they're not part of graphics data because they will be processed immediately. also can use GS ( D to disable realtime commands before processing graphics data
|
||||
|
||||
* `ESC p` Generate pulse
|
||||
* `GS ( A` Execute test print
|
||||
* `GS ( D` Enable/disable real-time command
|
||||
* `GS ( H` Request transmission of response or status
|
||||
* `GS ( K` Select print control method(s)
|
||||
* Select the print control mode
|
||||
* Select the print density
|
||||
* Select the print speed
|
||||
* Select the number of parts for the thermal head energizing
|
||||
* `GS ( P` Page mode control
|
||||
* Printable area setting when page mode is selected
|
||||
* `GS ( Q` Commands for drawing graphics
|
||||
* Draw line
|
||||
* Draw rectangle
|
||||
|
||||
## Two Dimension Code Commands (QR Codes)
|
||||
* `GS ( k` Set up and print the symbol
|
||||
|
||||
## Customize Commands
|
||||
* `GS ( C` Edit NV user memory
|
||||
* Delete the specified record
|
||||
* Store the data in the specified record
|
||||
* Transmit the data in the specified record
|
||||
* Transmit capacity of the NV user memory currently being used
|
||||
* Transmit the remaining capacity of the NV user memory
|
||||
* Transmit the key code list
|
||||
* Delete all data in the NV user memory
|
||||
* `GS ( E` Set user setup commands
|
||||
* Change into the user setting mode
|
||||
* End the user setting mode session
|
||||
* Change the memory switch
|
||||
* Transmit the settings of the memory switch
|
||||
* Set the customized setting values
|
||||
* Transmit the customized setting values
|
||||
* Copy the user-defined page
|
||||
* Define the data (column format) for the character code page
|
||||
* Define the data (raster format) for the character code page
|
||||
* Delete the data for the character code page
|
||||
* Set the configuration item for the serial interface
|
||||
* Transmit the configuration item for the serial interface
|
||||
* Set the configuration item for the Bluetooth interface
|
||||
* Transmit the configuration item for the Bluetooth interface
|
||||
* Delete the paper layout
|
||||
* Set the paper layout
|
||||
|
||||
## Counter Printing Commands
|
||||
|
||||
## Printing Paper Commands
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## All Commands
|
||||
|
||||
## Print Commands
|
||||
* LF Print and line feed
|
||||
* FF (in page mode) Print and return to standard mode (in page mode)
|
||||
* CR Print and carriage return
|
||||
* ESC FF Print data in page mode
|
||||
* ESC J Print and feed paper
|
||||
* ESC K Print and reverse feed
|
||||
* ESC d Print and feed n lines
|
||||
* ESC e Print and reverse feed n lines
|
||||
|
||||
## Line Spacing Commands
|
||||
* ESC 2 Select default line spacing
|
||||
* ESC 3 Set line spacing
|
||||
|
||||
## Character Commands
|
||||
* CAN Cancel print data in page mode
|
||||
* ESC SP Set right-side character spacing
|
||||
* ESC ! Select print mode(s)
|
||||
* ESC % Select/cancel user-defined character set
|
||||
* ESC & Define user-defined characters
|
||||
* ESC – Turn underline mode on/off
|
||||
* ESC ? Cancel user-defined characters
|
||||
* ESC E Turn emphasized mode on/off
|
||||
* ESC G Turn double-strike mode on/off
|
||||
* ESC M Select character font
|
||||
* ESC R Select an international character set
|
||||
* ESC V Turn 90° clockwise rotation mode on/off
|
||||
* ESC r Select print color
|
||||
* ESC t Select character code table
|
||||
* ESC { Turn upside-down print mode on/off
|
||||
* GS ( N Select character effects
|
||||
* Select character color
|
||||
* Select background color
|
||||
* Turn shading mode on/off
|
||||
* GS ! Select character size
|
||||
* GS B Turn white/black reverse print mode on/off
|
||||
* GS b Turn smoothing mode on/off
|
||||
|
||||
|
||||
## Panel Button Commands
|
||||
* ESC c 5 Enable/disable panel buttons
|
||||
|
||||
|
||||
## Paper Sensor Commands
|
||||
* ESC c 3 Select paper sensor(s) to output paper-end signals
|
||||
* ESC c 4 Select paper sensor(s) to stop printing
|
||||
|
||||
## Print Position Commands
|
||||
* HT Horizontal tab
|
||||
* ESC $ Set absolute print position
|
||||
* ESC D Set horizontal tab positions
|
||||
* ESC T Select print direction in page mode
|
||||
* ESC W Set print area in page mode
|
||||
* ESC \ Set relative print position
|
||||
* ESC a Select justification
|
||||
* GS $ Set absolute vertical print position in page mode
|
||||
* GS L Set left margin
|
||||
* GS T Set print position to the beginning of print line
|
||||
* GS W Set print area width
|
||||
* GS \ Set relative vertical print position in page mode
|
||||
|
||||
## Bit Image Commands
|
||||
* ESC ✻ Select bit-image mode
|
||||
* FS p Print NV bit image
|
||||
* GS ( L GS 8 L Set graphics data
|
||||
* Transmit the NV graphics memory capacity.
|
||||
* Set the reference dot density for graphics.
|
||||
* Print the graphics data in the print buffer.
|
||||
* Transmit the remaining capacity of the NV graphics memory.
|
||||
* Transmit the remaining capacity of the download graphics memory.
|
||||
* Transmit the key code list for defined NV graphics.
|
||||
* Delete all NV graphics data.
|
||||
* Delete the specified NV graphics data.
|
||||
* Define the NV graphics data (raster format).
|
||||
* Define the NV graphics data (column format).
|
||||
* Print the specified NV graphics data.
|
||||
* Transmit the key code list for defined download graphics.
|
||||
* Delete all NV graphics data.
|
||||
* Delete the specified download graphics data.
|
||||
* Define the downloaded graphics data (raster format).
|
||||
* Define the downloaded graphics data (column format).
|
||||
* Print the specified download graphics data.
|
||||
* Store the graphics data in the print buffer (raster format).
|
||||
* Store the graphics data in the print buffer (column format).
|
||||
* FS q Define NV bit image
|
||||
* GS v 0 Print raster bit image
|
||||
* GS ✻ Define downloaded bit image
|
||||
* GS / Print downloaded bit image
|
||||
* GS Q 0 Print variable vertical size bit image
|
||||
|
||||
## Status Commands
|
||||
* DLE EOT Transmit real-time status
|
||||
* ESC u Transmit peripheral device status
|
||||
* ESC v Transmit paper sensor status
|
||||
* GS a Enable/disable Automatic Status Back (ASB)
|
||||
* GS j Enable/disable Automatic Status Back (ASB) for ink
|
||||
* GS r Transmit status
|
||||
|
||||
## Bar Code Commands
|
||||
* GS H Select print position of HRI characters
|
||||
* GS f Select font for HRI characters
|
||||
* GS h Set bar code height
|
||||
* GS k Print bar code
|
||||
* GS w Set bar code width
|
||||
|
||||
## Macro Function Commands
|
||||
* GS : Start/end macro definition
|
||||
* GS ^ Execute macro
|
||||
|
||||
## Mechanism Control Commands
|
||||
* ESC < Return home
|
||||
* ESC U Turn unidirectional print mode on/off
|
||||
* ESC i Partial cut (one point left uncut)
|
||||
* ESC m Partial cut (three points left uncut)
|
||||
* GS V Select cut mode and cut paper
|
||||
|
||||
## Miscellaneous Commands
|
||||
* DLE ENQ Send real-time request to printer
|
||||
* DLE DC4 (fn = 1) Generate pulse in real-time
|
||||
* DLE DC4 (fn = 2) Execute power-off sequence
|
||||
* DLE DC4 (fn = 7) Transmit specified status in real time
|
||||
* DLE DC4 (fn = 8) Clear buffer (s)
|
||||
* ESC ( A Control beeper tones
|
||||
* Beep integrated beeper in TM-U230 models
|
||||
* Set integrated beeper when offline factors occur in TM-U230 models
|
||||
* Set integrated beeper except when offline factors occur in TM-U230 models
|
||||
* ESC = Select peripheral device
|
||||
* ESC @ Initialize printer
|
||||
* ESC L Select page mode
|
||||
* ESC S Select standard mode
|
||||
* ESC p Generate pulse
|
||||
* GS ( A Execute test print
|
||||
* GS ( D Enable/disable real-time command
|
||||
* GS ( H Request transmission of response or status
|
||||
* GS ( K Select print control method(s)
|
||||
* Select the print control mode
|
||||
* Select the print density
|
||||
* Select the print speed
|
||||
* Select the number of parts for the thermal head energizing
|
||||
* GS ( P Page mode control
|
||||
* Printable area setting when page mode is selected
|
||||
* GS ( Q Commands for drawing graphics
|
||||
* Draw line
|
||||
* Draw rectangle
|
||||
|
||||
## Kanji Commands
|
||||
* FS ! Select print mode(s) for Kanji characters
|
||||
* FS & Select Kanji character mode
|
||||
* FS ( A Select Kanji character style(s)
|
||||
* Select Kanji character font
|
||||
* FS – Turn underline mode on/off for Kanji characters
|
||||
* FS . Cancel Kanji character mode
|
||||
* FS 2 Define user-defined Kanji characters
|
||||
* FS C Select Kanji character code system
|
||||
* FS S Set Kanji character spacing
|
||||
* FS W Turn quadruple-size mode on/off for Kanji characters
|
||||
* FS ? Cancel user-defined Kanji characters
|
||||
|
||||
## Two Dimension Code Commands (QR Codes)
|
||||
* GS ( k Set up and print the symbol
|
||||
|
||||
## Customize Commands
|
||||
* FS g 1 Write to NV user memory
|
||||
* FS g 2 Read from NV user memory
|
||||
* GS ( C Edit NV user memory
|
||||
* Delete the specified record
|
||||
* Store the data in the specified record
|
||||
* Transmit the data in the specified record
|
||||
* Transmit capacity of the NV user memory currently being used
|
||||
* Transmit the remaining capacity of the NV user memory
|
||||
* Transmit the key code list
|
||||
* Delete all data in the NV user memory
|
||||
* GS ( E Set user setup commands
|
||||
* Change into the user setting mode
|
||||
* End the user setting mode session
|
||||
* Change the memory switch
|
||||
* Transmit the settings of the memory switch
|
||||
* Set the customized setting values
|
||||
* Transmit the customized setting values
|
||||
* Copy the user-defined page
|
||||
* Define the data (column format) for the character code page
|
||||
* Define the data (raster format) for the character code page
|
||||
* Delete the data for the character code page
|
||||
* Set the configuration item for the serial interface
|
||||
* Transmit the configuration item for the serial interface
|
||||
* Set the configuration item for the Bluetooth interface
|
||||
* Transmit the configuration item for the Bluetooth interface
|
||||
* Delete the paper layout
|
||||
* Set the paper layout
|
||||
|
||||
## Counter Printing Commands
|
||||
* GS C 0 Select counter print mode
|
||||
* GS C 1 Select count mode (A)
|
||||
* GS C 2 Set counter
|
||||
* GS C ; Select counter mode (B)
|
||||
* GS c Print counter
|
||||
|
||||
## Printing Paper Commands
|
||||
* FS ( L Select label and black mark control function(s)
|
||||
* Paper layout setting
|
||||
* Paper layout information transmission
|
||||
* Transmit the positioning information
|
||||
* Feed paper to the label peeling position
|
||||
* Feed paper to the cutting position
|
||||
* Feed paper to the print starting position
|
||||
* Paper layout error special margin setting
|
||||
|
||||
|
||||
|
||||
|
||||
## Mechanism Control Commands
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Graphics Commands
|
||||
|
||||
## NV Graphics Commands
|
||||
|
||||
|
||||
## Download Graphics Commands
|
||||
|
||||
## Logo Print Commands
|
||||
|
||||
## Bar Code Commands
|
||||
|
||||
## Two-Dimensional Code Commands
|
||||
|
||||
## Status Commands
|
||||
|
||||
## Macro Function Commands
|
||||
|
||||
## Miscellaneous Commands
|
||||
|
||||
|
||||
### User Setup Commands
|
||||
|
||||
TODO:
|
||||
* Line Spacing
|
||||
* SetLineSpacing()
|
||||
* SetLineSpacing(n dots) 0 <= n <= 255
|
||||
|
||||
Not In Scope:
|
||||
* Drawer Kick Out Commands
|
||||
* Page Mode Commands
|
||||
|
||||
|
||||
|
||||
|
||||
# COMMANDS IN ALPHANUMERIC ORDER
|
||||
Command|Name|Function type
|
||||
---|---|---
|
||||
HT |Horizontal tab |PRINT POSITION COMMANDS
|
||||
LF |Print and line feed |PRINT COMMANDS
|
||||
FF (in page mode) |Print and return to standard mode| PRINT COMMANDS
|
||||
CR |Print and carriage return |PRINT COMMANDS
|
||||
CAN |Cancel print data in page mode |CHARACTER COMMANDS
|
||||
DLE EOT |Real-time status transmission |STATUS COMMANDS
|
||||
DLE ENQ |Real-time request to printer| MISCELLANEOUS COMMANDS
|
||||
DLE DC4 (fn = 1) |Generate pulse at real-time |MISCELLANEOUS COMMANDS
|
||||
DLE DC4 (fn = 2) |Turn off the power| MISCELLANEOUS COMMANDS
|
||||
DLE DC4 (fn = 7) |Transmit specified status in real time |MISCELLANEOUS COMMANDS
|
||||
DLE DC4 (fn = 8) |Clear buffer| MISCELLANEOUS COMMANDS
|
||||
ESC FF |Print data in page mode |PRINT COMMANDS
|
||||
ESC SP |Set right-side character spacing |CHARACTER COMMANDS
|
||||
ESC ! |Select print mode(s) |CHARACTER COMMANDS
|
||||
ESC $ |Set absolute print position |PRINT POSITION COMMANDS
|
||||
ESC % |Select/cancel user-defined character set| CHARACTER COMMANDS
|
||||
ESC & |Define user-defined characters |CHARACTER COMMANDS
|
||||
ESC ( A |Control of the beeper |MISCELLANEOUS COMMANDS
|
||||
ESC ✻ |Select bit-image mode| BIT-IMAGE COMMANDS
|
||||
ESC – |Turn underline mode on/off| CHARACTER COMMANDS
|
||||
ESC 2 |Select default line spacing| LINE SPACING COMMANDS
|
||||
ESC 3 |Set line spacing |LINE SPACING COMMANDS
|
||||
ESC < |Return home| MECHANISM CONTROL COMMANDS
|
||||
ESC = |Select peripheral device |MISCELLANEOUS COMMANDS
|
||||
ESC ? |Cancel user-defined characters| CHARACTER COMMANDS
|
||||
ESC @ |Initialize printer| MISCELLANEOUS COMMANDS
|
||||
ESC D |Set horizontal tab positions |PRINT POSITION COMMANDS
|
||||
ESC E |Turn emphasized mode on/off |CHARACTER COMMANDS
|
||||
ESC G |Turn double-strike mode on/off| CHARACTER COMMANDS
|
||||
ESC J |Print and feed paper |PRINT COMMANDS
|
||||
ESC K |Print and reverse feed |PRINT COMMANDS
|
||||
ESC L |Select page mode |MISCELLANEOUS COMMANDS
|
||||
ESC M |Select character font| CHARACTER COMMANDS
|
||||
ESC R |Select an international character set| CHARACTER COMMANDS
|
||||
ESC S |Select standard mode |MISCELLANEOUS COMMANDS
|
||||
ESC T |Select print direction in page mode |PRINT POSITION COMMANDS
|
||||
ESC U |Turn unidirectional printing mode on/off |MECHANISM CONTROL COMMANDS
|
||||
ESC V |Turn 90° clockwise rotation mode on/off |CHARACTER COMMANDS
|
||||
ESC W |Set printing area in page mode |PRINT POSITION COMMANDS
|
||||
ESC \ |Set relative print position| PRINT POSITION COMMANDS
|
||||
ESC a |Select justification |PRINT POSITION COMMANDS
|
||||
ESC c 3 |Select paper sensor(s) to output paper-end signals |PAPER SENSOR COMMANDS
|
||||
ESC c 4 |Select paper sensor(s) to stop printing |PAPER SENSOR COMMANDS
|
||||
ESC c 5 |Enable/disable panel buttons| PANEL BUTTON COMMAND
|
||||
ESC d |Print and feed n lines |PRINT COMMANDS
|
||||
ESC e |Print and reverse feed n lines |PRINT COMMANDS
|
||||
ESC i |Partial cut (one point left uncut) |MECHANISM CONTROL COMMANDS
|
||||
ESC m |Partial cut (three points left uncut) |MECHANISM CONTROL COMMANDS
|
||||
ESC p |Generate pulse| MISCELLANEOUS COMMANDS
|
||||
ESC r |Select print color| CHARACTER COMMANDS
|
||||
ESC t |Select character code table |CHARACTER COMMANDS
|
||||
ESC u |Transmit peripheral device status| STATUS COMMANDS
|
||||
ESC { |Turn upside-down printing mode on/off| CHARACTER COMMANDS
|
||||
FS ! |Set print mode(s) for Kanji characters |KANJI COMMANDS
|
||||
FS & |Select Kanji character mode |KANJI COMMANDS
|
||||
FS ( A |Define character effects of Kanji characters. |KANJI COMMANDS
|
||||
FS ( L |Control of the label paper / black mark paper |PRINTING PAPER COMMANDS
|
||||
FS – |Turn underline mode on/off for Kanji characters |KANJI COMMANDS
|
||||
FS . |Cancel Kanji character mode |KANJI COMMANDS
|
||||
FS 2 |Define user-defined Kanji characters| KANJI COMMANDS
|
||||
FS C |Select Kanji character code system |KANJI COMMANDS
|
||||
FS S |Set Kanji character spacing |KANJI COMMANDS
|
||||
FS W |Turn quadruple-size mode on/off for Kanji characters| KANJI COMMANDS
|
||||
FS ? |Cancel user-defined Kanji characters |KANJI COMMANDS
|
||||
FS g 1 |Write to NV user memory |CUSTOMIZE COMMANDS
|
||||
FS g 2 |Read from NV user memory |CUSTOMIZE COMMANDS
|
||||
FS p |Print NV bit image |BIT-IMAGE COMMANDS
|
||||
FS q |Define NV bit image |BIT-IMAGE COMMANDS
|
||||
GS ! |Select character size |CHARACTER COMMANDS
|
||||
GS $ |Set absolute vertical print position in page mode| PRINT POSITION COMMANDS
|
||||
GS ( A |Execute test print| MISCELLANEOUS COMMANDS
|
||||
GS ( C |Edit NV user memory |CUSTOMIZE COMMANDS
|
||||
GS ( D |Enable/disable real-time command| MISCELLANEOUS COMMANDS
|
||||
GS ( E |User setup commands |CUSTOMIZE COMMANDS
|
||||
GS ( H |Require response transmission |MISCELLANEOUS COMMANDS
|
||||
GS ( K |Select printing control| MISCELLANEOUS COMMANDS
|
||||
GS ( L GS 8 L |Specify graphics data| BIT-IMAGE COMMANDS
|
||||
GS ( M |Customize printer control value(s)| CUSTOMIZE COMMANDS
|
||||
GS ( N |Select character effects| CHARACTER COMMANDS
|
||||
GS ( k |Specify and print the symbol |TWO DIMENSION CODE COMMANDS
|
||||
GS ✻ |Define downloaded bit image |BIT-IMAGE COMMANDS
|
||||
GS / |Print downloaded bit image |BIT-IMAGE COMMANDS
|
||||
GS : |Start/end macro definition |MACRO FUNCTION COMMANDS
|
||||
GS B |Turn white/black reverse printing mode on/off| CHARACTER COMMANDS
|
||||
GS C 0 |Select counter print mode| COUNTER PRINTING COMMANDS
|
||||
GS C 1 |Select count mode (A) |COUNTER PRINTING COMMANDS
|
||||
GS C 2 |Select counter print mode| COUNTER PRINTING COMMANDS
|
||||
GS C ; |Select counter mode (B) |COUNTER PRINTING COMMANDS
|
||||
GS H |Select printing position of HRI characters |BAR CODE COMMANDS
|
||||
GS I |Transmit printer |ID MISCELLANEOUS COMMANDS
|
||||
GS L |Set left margin |PRINT POSITION COMMANDS
|
||||
GS P |Set horizontal and vertical motion units| MISCELLANEOUS COMMANDS
|
||||
GS Q 0 |Print variable vertical size bit image |BIT-IMAGE COMMANDS
|
||||
GS T |Set print position to the beginning of print line| PRINT POSITION COMMANDS
|
||||
GS V |Select cut mode and cut paper |MECHANISM CONTROL COMMANDS
|
||||
GS W |Set printing area width PRINT |POSITION COMMANDS
|
||||
GS \ |Set relative vertical print position in page mode| PRINT POSITION COMMANDS
|
||||
GS ^ |Execute macro |MACRO FUNCTION COMMANDS
|
||||
GS a |Enable/disable Automatic Status Back (ASB) |STATUS COMMANDS
|
||||
GS b |Turn smoothing mode on/off |CHARACTER COMMANDS
|
||||
GS c |Print counter| COUNTER PRINTING COMMANDS
|
||||
GS f |Select font for HRI characters |BAR CODE COMMANDS
|
||||
GS g 0 |Initialize maintenance counter| MISCELLANEOUS COMMANDS
|
||||
GS g 2 |Transmit maintenance counter |MISCELLANEOUS COMMANDS
|
||||
GS h |Set bar code height |BAR CODE COMMANDS
|
||||
GS j |Enable/disable Ink Automatic Status Back (ASB) |STATUS COMMANDS
|
||||
GS k |Print bar code |BAR CODE COMMANDS
|
||||
GS r |Transmit status |STATUS COMMANDS
|
||||
GS v 0 |Print raster bit image |BIT-IMAGE COMMANDS
|
||||
GS w |Set bar code width |BAR CODE COMMANDS
|
||||
GS z 0 |Set online recovery wait time| MISCELLANEOUS COMMANDS
|
||||
GS z 0 |(TM-L90 w/ Peeler) Set online recovery wait time| MISCELLANEOUS COMMANDS
|
||||
|
||||
## The following commands are supported only by Simplified Chinese/Traditional Chinese/Japanese models.
|
||||
|
||||
Command|Name|Function type
|
||||
---|---|---
|
||||
FS ! |Set print mode(s) for Kanji characters |KANJI COMMANDS
|
||||
FS & |Select Kanji character mode |KANJI COMMANDS
|
||||
FS ( A |Define character effects of Kanji characters |KANJI COMMANDS
|
||||
FS – |Turn underline mode on/off for Kanji characters |KANJI COMMANDS
|
||||
FS . |Cancel Kanji character mode |KANJI COMMANDS
|
||||
FS 2 |Define user-defined Kanji characters| KANJI COMMANDS
|
||||
FS C |Select Kanji character code system |KANJI COMMANDS
|
||||
FS S |Set Kanji character spacing| KANJI COMMANDS
|
||||
FS W |Turn quadruple-size mode on/off for Kanji characters |KANJI COMMANDS
|
||||
FS ? |Cancel user-defined Kanji characters| KANJI COMMANDS
|
||||
|
||||
|
||||
|
||||