diff --git a/ESCPOS_NET.ConsoleTest/ESCPOS_NET.ConsoleTest.csproj b/ESCPOS_NET.ConsoleTest/ESCPOS_NET.ConsoleTest.csproj
index 915b7dc..90f5af2 100644
--- a/ESCPOS_NET.ConsoleTest/ESCPOS_NET.ConsoleTest.csproj
+++ b/ESCPOS_NET.ConsoleTest/ESCPOS_NET.ConsoleTest.csproj
@@ -2,7 +2,7 @@
Exe
- netcoreapp3.0
+ netcoreapp3.1
diff --git a/ESCPOS_NET.ConsoleTest/Program.cs b/ESCPOS_NET.ConsoleTest/Program.cs
index 3a93888..c0165e3 100644
--- a/ESCPOS_NET.ConsoleTest/Program.cs
+++ b/ESCPOS_NET.ConsoleTest/Program.cs
@@ -92,6 +92,8 @@ static void Main(string[] args)
printer = new NetworkPrinter(settings: new NetworkPrinterSettings() { ConnectionString = $"{ip}:{networkPort}" });
}
+ printer.Connect();
+
bool monitor = false;
Thread.Sleep(500);
Console.Write("Turn on Live Status Back Monitoring? (y/n): ");
diff --git a/ESCPOS_NET/Emitters/BaseCommandEmitter/CharacterCommands.cs b/ESCPOS_NET/Emitters/BaseCommandEmitter/CharacterCommands.cs
index 5dac730..b3756cb 100644
--- a/ESCPOS_NET/Emitters/BaseCommandEmitter/CharacterCommands.cs
+++ b/ESCPOS_NET/Emitters/BaseCommandEmitter/CharacterCommands.cs
@@ -13,6 +13,12 @@ public abstract partial class BaseCommandEmitter : ICommandEmitter
public virtual byte[] RightAlign() => new byte[] { Cmd.ESC, Chars.Alignment, (byte)Align.Right };
+ public virtual byte[] LeftAlignAlt() => new byte[] { Cmd.ESC, Chars.Alignment, (byte)Align.LeftAlt };
+
+ public virtual byte[] CenterAlignAlt() => new byte[] { Cmd.ESC, Chars.Alignment, (byte)Align.CenterAlt };
+
+ public virtual byte[] RightAlignAlt() => new byte[] { Cmd.ESC, Chars.Alignment, (byte)Align.RightAlt };
+
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 };
diff --git a/ESCPOS_NET/Emitters/BaseCommandEmitter/OperationalCommands.cs b/ESCPOS_NET/Emitters/BaseCommandEmitter/OperationalCommands.cs
index 8f40497..00ed00e 100644
--- a/ESCPOS_NET/Emitters/BaseCommandEmitter/OperationalCommands.cs
+++ b/ESCPOS_NET/Emitters/BaseCommandEmitter/OperationalCommands.cs
@@ -10,5 +10,7 @@ public abstract partial class BaseCommandEmitter : ICommandEmitter
public virtual byte[] Enable() => new byte[] { Cmd.ESC, Ops.EnableDisable, 1 };
public virtual byte[] Disable() => new byte[] { Cmd.ESC, Ops.EnableDisable, 0 };
+
+ public virtual byte[] StandardMode() => new byte[] { Cmd.ESC, Ops.StandardMode };
}
}
diff --git a/ESCPOS_NET/Emitters/BaseCommandValues/Ops.cs b/ESCPOS_NET/Emitters/BaseCommandValues/Ops.cs
index 9cf4263..e9bdf27 100644
--- a/ESCPOS_NET/Emitters/BaseCommandValues/Ops.cs
+++ b/ESCPOS_NET/Emitters/BaseCommandValues/Ops.cs
@@ -6,5 +6,6 @@ public static class Ops
public static readonly byte EnableDisable = 0x3D;
public static readonly byte PaperCut = 0x56;
public static readonly byte CashDrawerPulse = 0x70;
+ public static readonly byte StandardMode = 0x1B;
}
}
diff --git a/ESCPOS_NET/Emitters/Enums/Align.cs b/ESCPOS_NET/Emitters/Enums/Align.cs
index be7ef6b..ba54a09 100644
--- a/ESCPOS_NET/Emitters/Enums/Align.cs
+++ b/ESCPOS_NET/Emitters/Enums/Align.cs
@@ -6,5 +6,8 @@ public enum Align
Left = 0,
Center = 1,
Right = 2,
+ LeftAlt = 48,
+ CenterAlt = 49,
+ RightAlt = 50
}
}
diff --git a/ESCPOS_NET/Emitters/Enums/PrintStyle.cs b/ESCPOS_NET/Emitters/Enums/PrintStyle.cs
index ab2b921..48c4b31 100644
--- a/ESCPOS_NET/Emitters/Enums/PrintStyle.cs
+++ b/ESCPOS_NET/Emitters/Enums/PrintStyle.cs
@@ -8,9 +8,12 @@ public enum PrintStyle
{
None = 0,
FontB = 1,
+ Proportional = 1 << 1,
+ Condensed = 1 << 2,
Bold = 1 << 3,
DoubleHeight = 1 << 4,
DoubleWidth = 1 << 5,
+ Italic = 1 << 6,
Underline = 1 << 7,
}
}
diff --git a/ESCPOS_NET/Printers/BasePrinter.cs b/ESCPOS_NET/Printers/BasePrinter.cs
index 11a7c16..008001e 100644
--- a/ESCPOS_NET/Printers/BasePrinter.cs
+++ b/ESCPOS_NET/Printers/BasePrinter.cs
@@ -2,6 +2,7 @@
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -18,7 +19,9 @@ public abstract partial class BasePrinter : IPrinter, IDisposable
//private volatile bool _isMonitoring;
private CancellationTokenSource _readCancellationTokenSource;
+ private bool _readTaskRunning = false;
private CancellationTokenSource _writeCancellationTokenSource;
+ private bool _writeTaskRunning = false;
private readonly int _maxBytesPerWrite = 15000; // max byte chunks to write at once.
@@ -27,12 +30,6 @@ public abstract partial class BasePrinter : IPrinter, IDisposable
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 ReadBuffer { get; set; } = new ConcurrentQueue();
@@ -40,14 +37,17 @@ public abstract partial class BasePrinter : IPrinter, IDisposable
protected int BytesWrittenSinceLastFlush { get; set; } = 0;
- protected volatile bool IsConnected = true;
+ protected volatile bool IsConnected = true;
public string PrinterName { get; protected set; }
+ protected abstract int ReadBytesUnderlying(byte[] buffer, int offset, int bufferSize);
+ protected abstract void WriteBytesUnderlying(byte[] buffer, int offset, int count);
+ protected abstract void FlushUnderlying();
+
protected BasePrinter()
{
PrinterName = Guid.NewGuid().ToString();
- Init();
}
protected BasePrinter(string printerName)
{
@@ -56,105 +56,110 @@ protected BasePrinter(string printerName)
printerName = Guid.NewGuid().ToString();
}
PrinterName = printerName;
- Init();
}
- private void Init()
+
+ public virtual void Connect(bool reconnecting = false)
{
- _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);
+ if (!reconnecting)
+ {
+ _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(WriteLongRunningAsync, _writeCancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default).ConfigureAwait(false);
+ Task.Factory.StartNew(ReadLongRunningAsync, _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 }));
+ Connected?.Invoke(this, new ConnectionEventArgs() { IsConnected = true });
}
protected void InvokeDisconnect()
{
- Task.Run(() => Disconnected?.Invoke(this, new ConnectionEventArgs() { IsConnected = false }));
+ Disconnected?.Invoke(this, new ConnectionEventArgs() { IsConnected = false });
}
- protected virtual void Reconnect()
- {
- // Implemented in the network printer
- }
- protected virtual async void WriteLongRunningTask()
+ protected virtual async void WriteLongRunningAsync()
{
+ _writeTaskRunning = true;
+ List internalWriteBuffer = new List();
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);
+ internalWriteBuffer.AddRange(nextBytes);
+ WriteToBinaryWriter(ref internalWriteBuffer);
}
}
catch (IOException)
{
// 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.");
+ Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Swallowing IOException... sometimes happens with network printers. Should get reconnected automatically.");
}
catch
{
// Swallow the exception
- //Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Swallowing generic read exception... sometimes happens with serial port printers.");
+ Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Swallowing generic read exception... sometimes happens with serial port printers.");
+ }
+
+ if (!WriteBuffer.Any() && _writeCancellationTokenSource != null && _writeCancellationTokenSource.IsCancellationRequested)
+ {
+ Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Write Long-Running Task Cancellation was requested.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
+ break;
}
}
+
+ Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Write Long-Running Task has exited.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
+ _writeTaskRunning = false;
}
- protected virtual async void ReadLongRunningTask()
+ protected virtual async void ReadLongRunningAsync()
{
+ _readTaskRunning = true;
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)
+ byte[] buffer = new byte[4096];
+ int readBytes = this.ReadBytesUnderlying(buffer, 0, 4096);
+ if (readBytes > 0)
{
- ReadBuffer.Enqueue((byte)b);
- DataAvailable();
+ for (int ix = 0; ix < readBytes; ix++)
+ {
+ ReadBuffer.Enqueue((byte)buffer[ix]);
+ DataAvailable();
+ }
}
}
-
+
catch
- {
+ {
// Swallow the exception
//Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Swallowing generic read exception... sometimes happens with serial port printers.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
}
+
+ if (_readCancellationTokenSource != null && _readCancellationTokenSource.IsCancellationRequested)
+ {
+ Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Read Long-Running Task Cancellation was requested.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
+ break;
+ }
}
+
+ Logging.Logger?.LogDebug("[{Function}]:[{PrinterName}] Read Long-Running Task has exited.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
+ _readTaskRunning = false;
}
public virtual void Write(params byte[][] arrays)
@@ -167,56 +172,31 @@ public virtual void Write(byte[] bytes)
WriteBuffer.Enqueue(bytes);
}
- protected virtual void WriteToBinaryWriter(byte[] bytes)
+ protected void WriteToBinaryWriter(ref List 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)
+ try
{
- 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.");
- }
+ while (bytes.Count > 0)
+ {
- int bytePointer = 0;
- int bytesLeft = bytes.Length;
- bool hasFlushed = false;
- while (bytesLeft > 0)
- {
+ int count = Math.Min(_maxBytesPerWrite, bytes.Count);
+ this.WriteBytesUnderlying(bytes.ToArray(), 0, count);
+ bytes.RemoveRange(0, count);
- int count = Math.Min(_maxBytesPerWrite, bytesLeft);
- try
- {
- Writer.Write(bytes, bytePointer, count);
- }
- catch (IOException e)
- {
- Reconnect();
- if (!IsConnected)
+ BytesWrittenSinceLastFlush += count;
+ if (BytesWrittenSinceLastFlush >= 200)
{
- Logging.Logger?.LogError(e, "[{Function}]:[{PrinterName}] Unrecoverable connectivity error writing to printer.", $"{this}.{MethodBase.GetCurrentMethod().Name}", PrinterName);
+ // Immediately trigger a flush before proceeding so the output buffer will not be delayed.
+ Flush(null, null);
}
- 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;
+ Flush(null, null);
}
-
- if (!hasFlushed)
+ catch (IOException e)
{
- Task.Run(async () => { await Task.Delay(50); Flush(null, null); });
+ // Network or serial connection failed, dont consume the buffer this time around
+ Logging.Logger?.LogDebug(e, "Device appears disconnected. No more bytes will be written until it is reconnected.");
}
}
@@ -224,9 +204,8 @@ protected virtual void Flush(object sender, ElapsedEventArgs e)
{
try
{
-
BytesWrittenSinceLastFlush = 0;
- Writer.Flush();
+ this.FlushUnderlying();
}
catch (Exception ex)
{
@@ -292,6 +271,7 @@ private void TryUpdatePrinterStatus(byte[] bytes)
~BasePrinter()
{
+ Flush(this, null);
Dispose(false);
}
@@ -317,43 +297,15 @@ protected virtual void Dispose(bool disposing)
try
{
_readCancellationTokenSource?.Cancel();
+ _writeCancellationTokenSource?.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);
- }
+
+ while (_readTaskRunning || _writeTaskRunning) Thread.Sleep(100);
+
try
{
OverridableDispose();
diff --git a/ESCPOS_NET/Printers/FilePrinter.cs b/ESCPOS_NET/Printers/FilePrinter.cs
index d49ad23..4f38536 100644
--- a/ESCPOS_NET/Printers/FilePrinter.cs
+++ b/ESCPOS_NET/Printers/FilePrinter.cs
@@ -4,11 +4,19 @@ namespace ESCPOS_NET
{
public class FilePrinter : BasePrinter
{
- private readonly FileStream _file;
+ private FileStream _file;
+ private bool createIfNotExists;
+ private string filePath;
// TODO: default values to their default values in ctor.
public FilePrinter(string filePath, bool createIfNotExists = false)
: base()
+ {
+ this.createIfNotExists = createIfNotExists;
+ this.filePath = filePath;
+ }
+
+ public override void Connect(bool reconnecting = false)
{
if (createIfNotExists)
{
@@ -17,9 +25,25 @@ public FilePrinter(string filePath, bool createIfNotExists = false)
else
{
_file = File.Open(filePath, FileMode.Open);
+ //if (_file.CanSeek) _file.Seek(0, SeekOrigin.End);
}
- Writer = new BinaryWriter(_file);
- Reader = new BinaryReader(_file);
+
+ base.Connect(reconnecting);
+ }
+
+ protected override int ReadBytesUnderlying(byte[] buffer, int offset, int bufferSize)
+ {
+ return _file.Read(buffer, offset, bufferSize);
+ }
+
+ protected override void WriteBytesUnderlying(byte[] buffer, int offset, int count)
+ {
+ _file.Write(buffer, offset, count);
+ }
+
+ protected override void FlushUnderlying()
+ {
+ _file.Flush();
}
~FilePrinter()
diff --git a/ESCPOS_NET/Printers/MemoryPrinter.cs b/ESCPOS_NET/Printers/MemoryPrinter.cs
index 11060f1..8563656 100644
--- a/ESCPOS_NET/Printers/MemoryPrinter.cs
+++ b/ESCPOS_NET/Printers/MemoryPrinter.cs
@@ -11,7 +11,6 @@ public MemoryPrinter()
: base()
{
_ms = new MemoryStream();
- Writer = new BinaryWriter(_ms);
}
~MemoryPrinter()
@@ -24,6 +23,21 @@ public byte[] GetAllData()
return _ms.ToArray();
}
+ protected override int ReadBytesUnderlying(byte[] buffer, int offset, int bufferSize)
+ {
+ return 0;
+ }
+
+ protected override void WriteBytesUnderlying(byte[] buffer, int offset, int count)
+ {
+ _ms.Write(buffer, offset, count);
+ }
+
+ protected override void FlushUnderlying()
+ {
+ _ms.Flush();
+ }
+
protected override void OverridableDispose()
{
_ms?.Close();
diff --git a/ESCPOS_NET/Printers/NetworkPrinter.cs b/ESCPOS_NET/Printers/NetworkPrinter.cs
index a1dba44..1d77c89 100644
--- a/ESCPOS_NET/Printers/NetworkPrinter.cs
+++ b/ESCPOS_NET/Printers/NetworkPrinter.cs
@@ -4,6 +4,7 @@
using System.IO;
using System.Threading.Tasks;
using System.Reflection;
+using System.Threading;
namespace ESCPOS_NET
{
@@ -21,6 +22,7 @@ public class NetworkPrinterSettings
//public uint? MaxReconnectAttempts { get; set; }
public string PrinterName { get; set; }
}
+
public class NetworkPrinter : BasePrinter
{
private readonly NetworkPrinterSettings _settings;
@@ -37,7 +39,6 @@ public NetworkPrinter(NetworkPrinterSettings settings) : base(settings.PrinterNa
{
Disconnected += settings.DisconnectedHandler;
}
- Connect();
}
private void ConnectedEvent(object sender, ClientConnectedEventArgs e)
@@ -46,34 +47,19 @@ private void ConnectedEvent(object sender, ClientConnectedEventArgs e)
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
- {
- //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(); });
- }
+ Connect(true);
}
- private void Connect()
+ public override void Connect(bool reconnecting = false)
{
- if (_tcpConnection != null)
- {
- _tcpConnection.Connected -= ConnectedEvent;
- _tcpConnection.Disconnected -= DisconnectedEvent;
- }
+
+ OverridableDispose();
// instantiate
_tcpConnection = new TCPConnection(_settings.ConnectionString);
@@ -82,15 +68,35 @@ private void Connect()
_tcpConnection.Connected += ConnectedEvent;
_tcpConnection.Disconnected += DisconnectedEvent;
- Reader = new BinaryReader(_tcpConnection.ReadStream);
- Writer = new BinaryWriter(_tcpConnection.WriteStream);
+ _tcpConnection.ConnectWithRetries(3000);
- Task.Run(() => { AttemptReconnectInfinitely(); });
+ base.Connect(reconnecting);
+ }
+
+ protected override void WriteBytesUnderlying(byte[] buffer, int offset, int count)
+ {
+ _tcpConnection.WriteStream?.Write(buffer, offset, count);
+ }
+
+ protected override int ReadBytesUnderlying(byte[] buffer, int offset, int bufferSize)
+ {
+ return _tcpConnection.ReadStream?.Read(buffer, offset, bufferSize) ?? 0;
+ }
+
+ protected override void FlushUnderlying()
+ {
+ _tcpConnection.WriteStream?.Flush();
}
protected override void OverridableDispose()
{
- _tcpConnection = null;
+ if (_tcpConnection != null)
+ {
+ _tcpConnection.Connected -= ConnectedEvent;
+ _tcpConnection.Disconnected -= DisconnectedEvent;
+ _tcpConnection?.Dispose();
+ _tcpConnection = null;
+ }
}
}
}
diff --git a/ESCPOS_NET/Printers/SerialPrinter.cs b/ESCPOS_NET/Printers/SerialPrinter.cs
index a9a6041..5440367 100644
--- a/ESCPOS_NET/Printers/SerialPrinter.cs
+++ b/ESCPOS_NET/Printers/SerialPrinter.cs
@@ -1,3 +1,4 @@
+using System;
using System.IO;
using System.IO.Ports;
using System.Threading.Tasks;
@@ -6,22 +7,49 @@ namespace ESCPOS_NET
{
public class SerialPrinter : BasePrinter
{
- private readonly SerialPort _serialPort;
+ private readonly string portName;
+ private readonly int baudRate;
+ private SerialPort _serialPort;
public SerialPrinter(string portName, int baudRate)
: base()
+ {
+ this.portName = portName;
+ this.baudRate = baudRate;
+ }
+
+ public override void Connect(bool reconnecting = false)
{
_serialPort = new SerialPort(portName, baudRate);
_serialPort.Open();
- Writer = new BinaryWriter(_serialPort.BaseStream);
- Reader = new BinaryReader(_serialPort.BaseStream);
+
+ base.Connect(reconnecting);
+ }
+
+ protected override int ReadBytesUnderlying(byte[] buffer, int offset, int bufferSize)
+ {
+ if (this._serialPort.BytesToRead == 0) return 0;
+ return this._serialPort.Read(buffer, 0, Math.Min(bufferSize, this._serialPort.BytesToRead));
+ }
+
+ protected override void WriteBytesUnderlying(byte[] buffer, int offset, int count)
+ {
+ this._serialPort.Write(buffer, 0, count);
+ }
+
+ protected override void FlushUnderlying()
+ {
+ // noop
}
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.
+ if (_serialPort != null)
+ {
+ _serialPort?.Close();
+ _serialPort?.Dispose();
+ Task.Delay(250).Wait(); // Based on MSDN Documentation, should sleep after calling Close or some functionality will not be determinant.
+ }
}
}
}
\ No newline at end of file
diff --git a/ESCPOS_NET/Utils/EchoStream.cs b/ESCPOS_NET/Utils/EchoStream.cs
index 7013a12..05abe4b 100644
--- a/ESCPOS_NET/Utils/EchoStream.cs
+++ b/ESCPOS_NET/Utils/EchoStream.cs
@@ -81,16 +81,15 @@ public EchoStream(int 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));
+ Write(buffer, offset, count);
+
+ return Task.CompletedTask;
}
// 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 ReadAsync(byte[] buffer, int offset, int count)
{
- return Task.Run(() =>
- {
- return Read(buffer, offset, count);
- });
+ return Task.FromResult(Read(buffer, offset, count));
}
public override void Write(byte[] buffer, int offset, int count)
diff --git a/ESCPOS_NET/Utils/TCPConnection.cs b/ESCPOS_NET/Utils/TCPConnection.cs
index 559dbd6..2f2f1c4 100644
--- a/ESCPOS_NET/Utils/TCPConnection.cs
+++ b/ESCPOS_NET/Utils/TCPConnection.cs
@@ -5,7 +5,7 @@
namespace ESCPOS_NET
{
- public class TCPConnection
+ public class TCPConnection : IDisposable
{
public Stream ReadStream { get; private set; } = new EchoStream();
public Stream WriteStream { get; private set; }
@@ -13,7 +13,8 @@ public class TCPConnection
public event EventHandler Disconnected;
public bool IsConnected => _client?.IsConnected ?? false;
private SimpleTcpClient _client;
- //public event EventHandler DataReceived;
+ private bool disposedValue;
+
public TCPConnection(string destination)
{
_client = new SimpleTcpClient(destination);
@@ -24,34 +25,49 @@ public TCPConnection(string destination)
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()
+ protected virtual void Dispose(bool disposing)
{
- try
+ if (!disposedValue)
{
- _client.Events.DataReceived -= DataReceivedEventHandler;
- _client.Events.Connected -= ConnectedEventHandler;
- _client.Events.Disconnected -= DisconnectedEventHandler;
- _client?.Dispose();
+ if (disposing)
+ {
+ _client.Events.DataReceived -= DataReceivedEventHandler;
+ _client.Events.Connected -= ConnectedEventHandler;
+ _client.Events.Disconnected -= DisconnectedEventHandler;
+ _client.Disconnect();
+ _client?.Dispose();
+ }
+
+ disposedValue = true;
}
- catch { }
}
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
}
}
diff --git a/README.md b/README.md
index 196762a..c34a89b 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,8 @@ var printer = new SerialPrinter(portName: "COM5", baudRate: 115200);
// Linux output to USB / Serial file
var printer = new FilePrinter(filePath: "/dev/usb/lp0");
+
+printer.Connect();
```
## Step 1a (optional): Monitor for Events - out of paper, cover open...
```csharp