Initial commit
Initial commit til Git. V2 er deployed
This commit is contained in:
11
PointOfSale/Utilities/ESCPOS_NET/Utils/Consts.cs
Normal file
11
PointOfSale/Utilities/ESCPOS_NET/Utils/Consts.cs
Normal file
@@ -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";
|
||||
}
|
||||
}
|
||||
185
PointOfSale/Utilities/ESCPOS_NET/Utils/EchoStream.cs
Normal file
185
PointOfSale/Utilities/ESCPOS_NET/Utils/EchoStream.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
PointOfSale/Utilities/ESCPOS_NET/Utils/TCPConnection.cs
Normal file
59
PointOfSale/Utilities/ESCPOS_NET/Utils/TCPConnection.cs
Normal file
@@ -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 { }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user