using ExchangeHub.Contracts; using System; using System.Collections.Generic; using System.IO; using System.Runtime.InteropServices; using Microsoft.AspNet.SignalR.Client; namespace ExchangeHub { [ClassInterface(ClassInterfaceType.None)] [ComSourceInterfaces(typeof(IExchangeEvents))] [Guid("2ABFAC6C-9F3C-4702-9E08-4979A26577EF")] [ProgId("ExchangeHub.ExchangeConnection")] public class ExchangeConnection : IExchangeHubMaster { public const string HUB_DIR = ".\\SignalRClient"; public const string HUB_NAME = "ExchangeHub"; private readonly ICollection disposables; private HubConnection connection; private IHubProxy proxy; private string outputDIR; public ExchangeConnection() => this.disposables = new List(); public event VoidEventHandler Disposed; public event DoubleEventHandler StartQ; public event VoidEventHandler StopQ; public event IntEventHandler StartRef; public event DoubleEventHandler StopRef; public event StringEventHandler StateChanged; public string OutputDir { get => this.outputDIR; set { if (string.IsNullOrWhiteSpace(value)) { value = HUB_DIR; } this.outputDIR = Directory .CreateDirectory(value) .FullName; } } public bool Connect(string url) { this.connection = new HubConnection(url); this.connection.Closed += this.Connection_Closed; this.connection.ConnectionSlow += Connection_ConnectionSlow; this.connection.Error += this.Connection_Error; this.connection.Received += this.Connection_Received; this.connection.Reconnected += this.Connection_Reconnected; this.connection.Reconnecting += this.Connection_Reconnecting; this.connection.StateChanged += this.Connection_StateChanged; this.proxy = this.connection.CreateHubProxy(HUB_NAME); this.disposables.Add(this.proxy.On(nameof(this.StopQ), () => this.StopQ?.Invoke())); this.disposables.Add(this.proxy.On(nameof(this.Disposed), () => this.Disposed?.Invoke())); this.disposables.Add(this.proxy.On(nameof(this.StartRef), duration => this.StartRef?.Invoke(duration))); this.disposables.Add(this.proxy.On(nameof(this.StartQ), volumeM3 => this.StartQ?.Invoke(volumeM3))); this.disposables.Add(this.proxy.On(nameof(this.StopRef), volumeM3 => this.StopRef?.Invoke(volumeM3))); try { this.connection .Start() .Wait(); } catch (Exception e) { this.FileAppendLine(e.ToString()); } return this.connection.State == ConnectionState.Connected; } public void Dispose() { try { if (this.connection.State == ConnectionState.Connected) { this.proxy.Invoke(nameof(this.Disposed)); } foreach (var disposable in this.disposables) { disposable?.Dispose(); } this.connection.Stop(); } catch (Exception e) { this.FileAppendLine(e.Message); } this.FileAppendLine("Connection disposed."); } public void NotifyStartQ(double value = double.MaxValue) { if (this.connection.State == ConnectionState.Connected) { this.proxy.Invoke(nameof(this.StartQ), value); this.FileAppendLine($"Sent: {nameof(this.StartQ)}:{value}"); } } public void NotifyStartRef(int durationSS) { if (this.connection.State == ConnectionState.Connected) { this.proxy.Invoke(nameof(this.StartRef), durationSS); this.FileAppendLine($"Sent: {nameof(this.StartRef)}"); } } public void NotifyStopQ() { if (this.connection.State == ConnectionState.Connected) { this.proxy.Invoke(nameof(this.StopQ)); this.FileAppendLine($"Sent: {nameof(this.StopQ)}"); } } public void NotifyStopRef(double value = double.MaxValue) { if (this.connection.State == ConnectionState.Connected) { this.proxy.Invoke(nameof(this.StopRef), value); this.FileAppendLine($"Sent: {nameof(this.StopRef)}:{value}"); } } private void Connection_Closed() => this.FileAppendLine("HubConnection closed!"); private void Connection_ConnectionSlow() => this.FileAppendLine("HubConnection is about to timeout!"); private void Connection_Error(Exception e) => this.FileAppendLine(e.ToString()); private void Connection_Received(string data) => this.FileAppendLine(data); private void Connection_Reconnected() => this.FileAppendLine("HubConnection reconnected!"); private void Connection_Reconnecting() => this.FileAppendLine("HubConnection reconnecting!"); private void Connection_StateChanged(StateChange state) => this.FileAppendLine($"{state.OldState} -> {state.NewState}"); private void FileAppendLine(string text) { try { var fileName = $"{this.OutputDir}\\{DateTime.Now:yyyy_MM_dd}.txt"; File.AppendAllText(fileName, $"[{DateTime.Now:HH:mm:ss}] {text}{Environment.NewLine}"); this.StateChanged?.Invoke(fileName); } catch (Exception e) { } } } }