using Application.Models; using Infrastructure.Extensions; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Extensions.Configuration; using System; using System.Threading; using System.Threading.Tasks; namespace IoT.Shared.Infrastructure { public class BaseClientService : IClientService { protected string _notifyHost; protected HubConnection Connection; protected readonly IServiceProvider applicationServices; protected readonly IConfiguration _cfg; protected CancellationTokenSource _tokenSource; public string ConnectionId { get; private set; } public BaseClientService(IServiceProvider applicationServices, IConfiguration configuration) { this.applicationServices = applicationServices; this._cfg = configuration; this._tokenSource = new CancellationTokenSource(); this.ConnectionId = Guid.NewGuid().ToBase62(); } public void Start() { Task.Run(async () => { while (!_tokenSource.IsCancellationRequested) { this.Connect(); await Task.Delay(10 * 1000); } }); } public void Connect() { if (this._cfg.GetValue("notify:enabled", false)) { Console.WriteLine("notify is enabled"); try { if (Connection == null) { Console.WriteLine("connection is null"); InitConnection(); } if (Connection.State == HubConnectionState.Disconnected) { Console.WriteLine("start connect"); if (this._notifyHost != this._cfg["notify:host"]) { InitConnection(); } Connection.StartAsync().Wait(); this.OnConnected(); } else { if (this._notifyHost != this._cfg["notify:host"]) { this.ReConnect(null); } else { Console.WriteLine($"connection has connected"); } } } catch (Exception ex) { ex.PrintStack(); } } else { Console.WriteLine("notify is disabled"); this.Close(); } } public virtual void OnConnected() { } public virtual void ConnectionOn() { } public void Close() { if (this.Connection != null) { if (this.Connection.State == HubConnectionState.Connected) { this.Connection.StopAsync(); } this.Connection.DisposeAsync(); this.Connection = null; } } private Task ReConnect(Exception arg) { this.Close(); this.Connect(); return Task.CompletedTask; } private void InitConnection() { this._notifyHost = this._cfg["notify:host"]; var url = $"http://{this._notifyHost}/hub?group={this._cfg["sn"]}"; Console.WriteLine($"init connection for {url}"); if (this.Connection != null) { this.Connection.DisposeAsync(); } this.Connection = new HubConnectionBuilder().WithUrl(url).Build(); this.Connection.Closed += ReConnect; this.Connection.On(Methods.ServerToClient, (string method, string message, string fromConnectionId) => this.OnServerToClient(method, message, fromConnectionId)); this.ConnectionOn(); } public virtual void OnServerToClient(string method, string message, string fromConnectionId) { } public void ServerToClient(string method, string message, string fromConnectionId) { this.OnServerToClient(method, method, fromConnectionId); } public void ClientToServer(string method, string message, string fromConnectionId = null) { Task.Run(() => { try { if (this.Connection != null && this.Connection.State == HubConnectionState.Connected) { this.Connection.SendAsync(Methods.ClientToServer, method, message, fromConnectionId); } else { Console.WriteLine($"{_notifyHost} not connected"); } } catch (Exception ex) { ex.PrintStack(); } }); } public void Dispose() { this._tokenSource.Cancel(); this.Close(); } } }