Initial commit
Initial commit til Git. V2 er deployed
This commit is contained in:
378
PointOfSale/Utilities/ESCPOS_NET/Printers/BasePrinter.cs
Normal file
378
PointOfSale/Utilities/ESCPOS_NET/Printers/BasePrinter.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
36
PointOfSale/Utilities/ESCPOS_NET/Printers/FilePrinter.cs
Normal file
36
PointOfSale/Utilities/ESCPOS_NET/Printers/FilePrinter.cs
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
PointOfSale/Utilities/ESCPOS_NET/Printers/IPrinter.cs
Normal file
17
PointOfSale/Utilities/ESCPOS_NET/Printers/IPrinter.cs
Normal file
@@ -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.
|
||||
}
|
||||
}
|
||||
33
PointOfSale/Utilities/ESCPOS_NET/Printers/MemoryPrinter.cs
Normal file
33
PointOfSale/Utilities/ESCPOS_NET/Printers/MemoryPrinter.cs
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
101
PointOfSale/Utilities/ESCPOS_NET/Printers/NetworkPrinter.cs
Normal file
101
PointOfSale/Utilities/ESCPOS_NET/Printers/NetworkPrinter.cs
Normal file
@@ -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; }
|
||||
|
||||
}
|
||||
}
|
||||
32
PointOfSale/Utilities/ESCPOS_NET/Printers/SerialPrinter.cs
Normal file
32
PointOfSale/Utilities/ESCPOS_NET/Printers/SerialPrinter.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
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.
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
OverridableDispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// TODO: Implement this class
|
||||
|
||||
namespace ESCPOS_NET
|
||||
{
|
||||
public class VirtualPrinter
|
||||
{
|
||||
public byte[] Output { get; private set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user