Connection changes
This commit is contained in:
@@ -2,8 +2,10 @@
|
||||
using OmniPlus.Hanlers;
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
@@ -21,6 +23,42 @@ namespace OmniPlus
|
||||
this.Options.LogFile = $".\\IRDA\\[{portName}].txt";
|
||||
}
|
||||
|
||||
public Byte[] Send(params Byte[] request)
|
||||
{
|
||||
this.InvokeLogMessage(">>> PLAIN" + BitConverter.ToString(request));
|
||||
|
||||
if (!this.IsOpen)
|
||||
{
|
||||
this.OpenII();
|
||||
}
|
||||
|
||||
var response = new Byte[] { };
|
||||
|
||||
if (!this.IsOpen || !this.Stream.CanWrite || !this.Stream.CanRead)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
this.Stream.Write(new byte[] { 1, 1, 1, 1 }, 0, 4);
|
||||
|
||||
var asyncState = new IRDAAsyncState
|
||||
{
|
||||
Request = request,
|
||||
Stream = this.Stream
|
||||
};
|
||||
|
||||
var lock_object = new object();
|
||||
|
||||
lock (lock_object)
|
||||
{
|
||||
Task.Factory.StartNew(asyncState.BeginReadAsync, asyncState.CancellationToken);
|
||||
|
||||
asyncState.BeginWriteAsync(request);
|
||||
}
|
||||
|
||||
return asyncState.Response;
|
||||
}
|
||||
|
||||
public byte[] SendMessage(byte[] command)
|
||||
{
|
||||
var response = new byte[0];
|
||||
@@ -76,9 +114,9 @@ namespace OmniPlus
|
||||
{
|
||||
var message = default(byte[]);
|
||||
var length = bytes.Length;
|
||||
var start = 0;
|
||||
var start = -1;
|
||||
|
||||
while (start < bytes.Length)
|
||||
while (++start < bytes.Length)
|
||||
{
|
||||
if (bytes[start] == OmniPlusExtensions.IRDA_START)
|
||||
{
|
||||
@@ -102,11 +140,126 @@ namespace OmniPlus
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
start++;
|
||||
}
|
||||
|
||||
this.MessageReceived?.Invoke(message);
|
||||
}
|
||||
}
|
||||
|
||||
public class IRDAAsyncState
|
||||
{
|
||||
private const int BUFFER_SIZE = 256;
|
||||
private const int MAX_REPEATS = 5;
|
||||
|
||||
private readonly ManualResetEventSlim manualResetEventSlim;
|
||||
private readonly CancellationTokenSource cancellationTokenSource;
|
||||
|
||||
public IRDAAsyncState()
|
||||
{
|
||||
this.manualResetEventSlim = new ManualResetEventSlim();
|
||||
this.cancellationTokenSource = new CancellationTokenSource();
|
||||
this.CancellationToken = this.cancellationTokenSource.Token;
|
||||
this.Buffer = new Byte[BUFFER_SIZE];
|
||||
}
|
||||
|
||||
public Int32 Repeats { get; private set; }
|
||||
|
||||
public Byte[] Buffer { get; private set; }
|
||||
|
||||
public Byte[] Request { get; set; }
|
||||
|
||||
public Byte[] Response { get; set; }
|
||||
|
||||
public Stream Stream { get; set; }
|
||||
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
||||
internal void BeginReadAsync()
|
||||
{
|
||||
this.Repeats++;
|
||||
this.Response = null;
|
||||
|
||||
var asyncResult = this.Stream.BeginRead(this.Buffer, 0, this.Buffer.Length, this.EndReadAsync, this);
|
||||
|
||||
asyncResult.AsyncWaitHandle.WaitOne();
|
||||
|
||||
if (this.Response is null && this.Repeats <= MAX_REPEATS)
|
||||
{
|
||||
this.BeginReadAsync();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.Response is null)
|
||||
{
|
||||
this.Response = new Byte[] { };
|
||||
}
|
||||
|
||||
this.manualResetEventSlim.Set();
|
||||
}
|
||||
|
||||
private void EndReadAsync(IAsyncResult asyncResult)
|
||||
{
|
||||
if (asyncResult.AsyncState is IRDAAsyncState asyncState)
|
||||
{
|
||||
lock (asyncState)
|
||||
{
|
||||
var bytesLength = asyncState.Stream.EndRead(asyncResult);
|
||||
|
||||
if (this.Response is null)
|
||||
{
|
||||
var response = new Byte[bytesLength];
|
||||
|
||||
Array.Copy(this.Buffer, 0, response, 0, bytesLength);
|
||||
|
||||
Console.WriteLine("<<< IRDA " + BitConverter.ToString(response));
|
||||
|
||||
response = response.FromIrdaMessage();
|
||||
|
||||
Console.WriteLine("<<< UI1236 " + BitConverter.ToString(response));
|
||||
|
||||
response = response.FromUI1236Message();
|
||||
|
||||
Console.WriteLine("<<< OMNI " + BitConverter.ToString(response));
|
||||
|
||||
if (response.Length != 0)
|
||||
{
|
||||
this.Response = response;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void BeginWriteAsync(Byte[] request)
|
||||
{
|
||||
Console.WriteLine(">>> OMNI " + BitConverter.ToString(request));
|
||||
|
||||
request = request.ToUI1236Message();
|
||||
|
||||
Console.WriteLine(">>> UI1236 " + BitConverter.ToString(request));
|
||||
|
||||
request = request.ToIrdaMessage();
|
||||
|
||||
Console.WriteLine(">>> IRDA " + BitConverter.ToString(request));
|
||||
|
||||
request = request
|
||||
.ToUI1236Message()
|
||||
.ToIrdaMessage();
|
||||
|
||||
var asyncResult = this.Stream.BeginWrite(request, 0, request.Length, this.EndWriteAsync, this);
|
||||
|
||||
asyncResult.AsyncWaitHandle.WaitOne();
|
||||
|
||||
this.manualResetEventSlim.Wait();
|
||||
}
|
||||
|
||||
private void EndWriteAsync(IAsyncResult asyncResult)
|
||||
{
|
||||
if (asyncResult.AsyncState is IRDAAsyncState asyncState)
|
||||
{
|
||||
asyncState.Stream.EndWrite(asyncResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@ using OmniPlus.Options;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Ports;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OmniPlus
|
||||
{
|
||||
internal abstract class SerialPortConnection
|
||||
internal abstract class SerialPortConnection : IDisposable
|
||||
{
|
||||
protected event StateChangedEventHandler StateChanged;
|
||||
protected event DataReceivedHandler DataReceived;
|
||||
@@ -17,7 +17,6 @@ namespace OmniPlus
|
||||
|
||||
private SerialPort serialPort;
|
||||
private SerialPortState state;
|
||||
private bool buisy;
|
||||
|
||||
protected SerialPortConnection()
|
||||
=> this.Options = new SerialPortOptions();
|
||||
@@ -26,13 +25,66 @@ namespace OmniPlus
|
||||
|
||||
public bool Connected => this.state == SerialPortState.Open;
|
||||
|
||||
protected bool IsOpen => this.serialPort?.IsOpen ?? false;
|
||||
|
||||
protected Stream Stream => this.serialPort.BaseStream;
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.serialPort != null)
|
||||
{
|
||||
this.serialPort.Disposed -= this.Port_Disposed;
|
||||
this.serialPort.ErrorReceived -= this.Port_ErrorReceived;
|
||||
|
||||
this.serialPort.Close();
|
||||
this.serialPort.Dispose();
|
||||
this.serialPort = null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
Console.WriteLine("... Port disposed");
|
||||
}
|
||||
|
||||
protected virtual void OpenII()
|
||||
{
|
||||
this.Dispose();
|
||||
|
||||
try
|
||||
{
|
||||
this.serialPort = new SerialPort
|
||||
{
|
||||
PortName = this.Options.PortName,
|
||||
BaudRate = (int)this.Options.BaudRate,
|
||||
DataBits = (int)this.Options.DataBits,
|
||||
Parity = this.Options.Parity,
|
||||
StopBits = this.Options.StopBits,
|
||||
RtsEnable = this.Options.RtsEnabled,
|
||||
DtrEnable = this.Options.DtrEnabled
|
||||
};
|
||||
|
||||
this.serialPort.Disposed += this.Port_Disposed;
|
||||
this.serialPort.ErrorReceived += this.Port_ErrorReceived;
|
||||
|
||||
this.serialPort.Open();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Close()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (this.serialPort != null)
|
||||
{
|
||||
// this.serialPort.DataReceived -= this.SerialPort_DataReceived;
|
||||
this.serialPort.Disposed -= this.SerialPort_Disposed;
|
||||
this.serialPort.ErrorReceived -= this.SerialPort_ErrorReceived;
|
||||
this.serialPort.PinChanged -= this.SerialPort_PinChanged;
|
||||
@@ -86,10 +138,26 @@ namespace OmniPlus
|
||||
}
|
||||
}
|
||||
|
||||
private void Port_Disposed(Object sender, EventArgs args)
|
||||
{
|
||||
this.Dispose();
|
||||
|
||||
Console.WriteLine("... Port disposed internal");
|
||||
}
|
||||
|
||||
private void Port_ErrorReceived(Object sender, SerialErrorReceivedEventArgs args)
|
||||
{
|
||||
Console.WriteLine("... Port error received");
|
||||
Console.WriteLine($"... {args.EventType}");
|
||||
|
||||
if (!this.serialPort.IsOpen)
|
||||
{
|
||||
this.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Open()
|
||||
{
|
||||
this.Close();
|
||||
|
||||
try
|
||||
{
|
||||
var fileInfo = new FileInfo(this.Options.LogFile);
|
||||
@@ -119,8 +187,7 @@ namespace OmniPlus
|
||||
RtsEnable = this.Options.RtsEnabled,
|
||||
DtrEnable = this.Options.DtrEnabled
|
||||
};
|
||||
|
||||
// this.serialPort.DataReceived += this.SerialPort_DataReceived;
|
||||
|
||||
this.serialPort.Disposed += this.SerialPort_Disposed;
|
||||
this.serialPort.ErrorReceived += this.SerialPort_ErrorReceived;
|
||||
this.serialPort.PinChanged += this.SerialPort_PinChanged;
|
||||
@@ -136,7 +203,7 @@ namespace OmniPlus
|
||||
+ $", {this.Options.BaudRate}"
|
||||
+ $", {this.Options.DataBits}"
|
||||
+ $", {this.Options.Parity}"
|
||||
+ $", {this.Options.StopBits}");
|
||||
+ $", {this.Options.StopBits}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -231,12 +298,13 @@ namespace OmniPlus
|
||||
private bool BeginWaitingResponseAsync()
|
||||
{
|
||||
var buffer = new byte[1024];
|
||||
var baseStream = this.serialPort.BaseStream;
|
||||
|
||||
this.serialPort?.BaseStream?.BeginRead(buffer, 0, buffer.Length, delegate(IAsyncResult asyncResult)
|
||||
var ar = baseStream.BeginRead(buffer, 0, buffer.Length, delegate(IAsyncResult asyncResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
var actualLength = this.serialPort?.BaseStream?.EndRead(asyncResult) ?? 0;
|
||||
var actualLength = baseStream.EndRead(asyncResult);
|
||||
|
||||
if (actualLength <= 0)
|
||||
{
|
||||
@@ -257,6 +325,8 @@ namespace OmniPlus
|
||||
}
|
||||
}, null);
|
||||
|
||||
Task.Factory.StartNew(ar.AsyncWaitHandle.WaitOne);
|
||||
|
||||
return this.serialPort != null && this.serialPort.IsOpen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ namespace OmniPlus.Features
|
||||
{
|
||||
public class FeatureRequest : FeatureResponse
|
||||
{
|
||||
protected readonly int length;
|
||||
|
||||
public FeatureRequest(int length)
|
||||
: base(length)
|
||||
=> this.length = length;
|
||||
|
||||
@@ -6,21 +6,30 @@ namespace OmniPlus.Features
|
||||
{
|
||||
public class FeatureResponse
|
||||
{
|
||||
protected int length;
|
||||
protected readonly byte[] bytes;
|
||||
|
||||
public FeatureResponse(int length = 0)
|
||||
=> this.bytes = new byte[length];
|
||||
public FeatureResponse(int length = 0)
|
||||
{
|
||||
this.length = length;
|
||||
this.bytes = new byte[length];
|
||||
}
|
||||
|
||||
public FeatureResponse(byte[] response, int length = 0) : this(length)
|
||||
{
|
||||
if (response?.Length > 0)
|
||||
if (response != null)
|
||||
{
|
||||
this.Status = (Status)response[0];
|
||||
}
|
||||
var responseLength = response.Length;
|
||||
|
||||
if (response?.Length > length)
|
||||
{
|
||||
Array.Copy(response, 1, this.bytes, 0, length);
|
||||
if (responseLength > 0)
|
||||
{
|
||||
this.Status = (Status)response[0];
|
||||
}
|
||||
|
||||
if (responseLength > this.length)
|
||||
{
|
||||
Array.Copy(response, 1, this.bytes, 0, this.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +45,5 @@ namespace OmniPlus.Features
|
||||
|
||||
public override string ToString()
|
||||
=> BitConverter.ToString(this.bytes);
|
||||
|
||||
//public static implicit operator byte[](FeatureResponse response)
|
||||
// => response?.bytes ?? new byte[0];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
namespace OmniPlus
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO.Ports;
|
||||
using System.Linq;
|
||||
|
||||
public class OMNIPool
|
||||
{
|
||||
private readonly ConcurrentDictionary<OMNISlot, OMNIFeatures> features;
|
||||
private readonly ConcurrentDictionary<OMNISlot, OMNIConnection> connections;
|
||||
|
||||
public OMNIPool()
|
||||
{
|
||||
this.connections = new ConcurrentDictionary<OMNISlot, OMNIConnection>();
|
||||
}
|
||||
|
||||
public void AddConnection(String portNr)
|
||||
{
|
||||
var slot = new OMNISlot(this.connections.Count + 1, portNr);
|
||||
_ = this.features.AddOrUpdate(slot, new OMNIFeatures(), (_slot, _) => new OMNIFeatures());
|
||||
_ = this.connections.AddOrUpdate(slot, new OMNIConnection(slot), (_slot, _) => new OMNIConnection(_slot));
|
||||
}
|
||||
}
|
||||
|
||||
public class OMNIConnection
|
||||
{
|
||||
private readonly OMNISlot slot;
|
||||
private readonly OMNIFeatures features;
|
||||
|
||||
public OMNIConnection(OMNISlot slot)
|
||||
{
|
||||
this.slot = slot;
|
||||
this.features = new OMNIFeatures();
|
||||
}
|
||||
}
|
||||
|
||||
public class OMNIFeatures
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class OMNISlot : IComparable<OMNISlot>
|
||||
{
|
||||
public OMNISlot(Int32 nr, String port)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(port))
|
||||
{
|
||||
throw new ArgumentNullException("COM port is required!");
|
||||
}
|
||||
else if (!SerialPort.GetPortNames().Any(x => x == port))
|
||||
{
|
||||
throw new ArgumentException("COM port dose not exists!");
|
||||
}
|
||||
|
||||
this.Nr = nr;
|
||||
this.Port = port;
|
||||
}
|
||||
|
||||
public Int32 Nr { get; }
|
||||
|
||||
public String Port { get; }
|
||||
|
||||
public Int32 CompareTo(OMNISlot other)
|
||||
{
|
||||
return this.Port.CompareTo(other.Port);
|
||||
}
|
||||
|
||||
public override Boolean Equals(Object other)
|
||||
{
|
||||
return this.Equals(other);
|
||||
}
|
||||
|
||||
public override Int32 GetHashCode()
|
||||
{
|
||||
return this.Port.GetHashCode();
|
||||
}
|
||||
|
||||
public override String ToString()
|
||||
{
|
||||
return $"{this.Nr}. {this.Port}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,9 @@
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net40\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@@ -100,6 +103,7 @@
|
||||
<Compile Include="OmniPlusMeter.cs" />
|
||||
<Compile Include="OmniPlusStateChanged.cs" />
|
||||
<Compile Include="OmniPlusType.cs" />
|
||||
<Compile Include="OMNIPool.cs" />
|
||||
<Compile Include="Options\OmniControlOptions.cs" />
|
||||
<Compile Include="Options\SerialPortOptions.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
@@ -110,6 +114,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ExchangeHub\ExchangeHub.csproj">
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace OmniPlus
|
||||
this.irdaConnection.Open();
|
||||
|
||||
this.connected = () => this.irdaConnection.Connected;
|
||||
this.MessageHandler = this.irdaConnection.SendMessage;
|
||||
this.MessageHandler = this.irdaConnection.Send;
|
||||
|
||||
return this.irdaConnection.Connected;
|
||||
}
|
||||
@@ -412,13 +412,5 @@ namespace OmniPlus
|
||||
|
||||
return new FeatureResponse();
|
||||
}
|
||||
|
||||
private void WaitBeforeNextExecution()
|
||||
{
|
||||
while (this.secondsToWait > 0)
|
||||
{
|
||||
this.secondsToWait--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +202,16 @@ namespace OmniPlus
|
||||
return payload;
|
||||
}
|
||||
|
||||
var bytesLength = bytes.Length;
|
||||
|
||||
if (bytesLength >= 2)
|
||||
{
|
||||
if (bytes[1] == IRDA_PING)
|
||||
{
|
||||
return payload;
|
||||
}
|
||||
}
|
||||
|
||||
var payloadLength = bytes.Length - IRDA_MIN_LENGTH;
|
||||
|
||||
if (payloadLength <= OxOO)
|
||||
|
||||
@@ -14,12 +14,14 @@
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.MeterVolume != 0 && this.VolumeMessured != 0)
|
||||
try
|
||||
{
|
||||
return this.MeterVolume / this.VolumeMessured * 100;
|
||||
return 100 - this.MeterVolume / this.VolumeMessured * 100;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,5 +29,8 @@ namespace OmniPlus
|
||||
|
||||
return seconds * milliliter / 1000 / 1000;
|
||||
}
|
||||
|
||||
public double VolumeM3(OmniPlusTest test)
|
||||
=> this.VolumeM3(test.Rotations, test.Duration);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
using OmniPlus.Enums;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System;
|
||||
using System.IO.Ports;
|
||||
|
||||
namespace OmniPlus.Options
|
||||
@@ -32,5 +35,8 @@ namespace OmniPlus.Options
|
||||
public bool DtrEnabled { get; set; }
|
||||
|
||||
public string LogFile { get; set; }
|
||||
|
||||
public override String ToString()
|
||||
=> JsonConvert.SerializeObject(this, Formatting.Indented);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net40" />
|
||||
</packages>
|
||||
Reference in New Issue
Block a user