namespace CommonConsole { using OmniPlus; using System; using System.IO; using System.IO.Ports; using System.Text; using System.Threading; using System.Threading.Tasks; class Program { static void Main() { var connection = new IRDAPort(); var response = connection.Send(0x01); Console.WriteLine(Encoding.ASCII.GetString(response)); response = connection.Send(0xFD, 0xC6); Console.WriteLine(Encoding.ASCII.GetString(response)); connection.Dispose(); } } public abstract class Port : IDisposable { private readonly String name; private readonly Int32 bauds; private readonly Int32 data; private readonly Parity parity; private readonly StopBits stop; private SerialPort port; protected Port(String name, Int32 bauds, Int32 data, Parity parity, StopBits stop) { this.name = name; this.bauds = bauds; this.data = data; this.parity = parity; this.stop = stop; } protected bool IsOpen => this.port?.IsOpen ?? false; protected Stream Stream => this.port.BaseStream; public virtual void Dispose() { try { if (this.port != null) { this.port.Disposed -= this.Port_Disposed; this.port.ErrorReceived -= this.Port_ErrorReceived; this.port.Close(); this.port.Dispose(); this.port = null; } } catch (Exception e) { Console.WriteLine(e); } Console.WriteLine("... Port disposed"); } protected virtual void Open() { this.Dispose(); try { this.port = new SerialPort { PortName = this.name, BaudRate = this.bauds, DataBits = this.data, Parity = this.parity, StopBits = this.stop, }; this.port.Disposed += this.Port_Disposed; this.port.ErrorReceived += this.Port_ErrorReceived; this.port.Open(); } catch (Exception e) { Console.WriteLine(e); } Console.WriteLine("... Port created"); } 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.port.IsOpen) { this.Dispose(); } } } public class IRDAPort : Port { public IRDAPort() : base("COM26", 115200, 8, Parity.None, StopBits.One) { } public Byte[] Send(params Byte[] request) { Console.WriteLine(">>> " + BitConverter.ToString(request)); if (!this.IsOpen) { this.Open(); } var response = new Byte[] { }; if (!this.IsOpen || !this.Stream.CanWrite || !this.Stream.CanRead) { return response; } Console.WriteLine(">>> 1-1-1-1"); this.Stream.Write(new byte[] { 1, 1, 1, 1 }, 0, 4); request = request .ToUI1236Message() .ToIrdaMessage(); Console.WriteLine(">>> " + BitConverter.ToString(request)); 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 class IRDAAsyncState { 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[256]; } 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.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.BeginReadAsync(); } else { this.manualResetEventSlim.Set(); } } private void EndReadAsync(IAsyncResult asyncResult) { if (asyncResult.AsyncState is IRDAAsyncState 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("<<< " + BitConverter.ToString(response)); response = response .FromIrdaMessage() .FromUI1236Message(); Console.WriteLine("<<< " + BitConverter.ToString(response)); if (response.Length != 0) { this.Response = response; } } } } internal void BeginWriteAsync(Byte[] request) { 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); } } } }