using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR.Client; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; using System.Web; using TEAMModelOS.SDK; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.DI.Device; using TEAMModelOS.SDK.Extension; using static Azure.Core.HttpHeader; namespace IESHybridCloud.Services { public class SignalRIESHybridClientHub : BackgroundService, IDisposable { private readonly IConfiguration _configuration; private readonly ILogger _logger; private TEAMModelOS.SDK.HybridClient? device; private readonly CoreDevice _device; private readonly IHttpClientFactory _httpClientFactory; private readonly BackgroundWorkerQueue _backgroundWorkerQueue; private readonly AzureSignalRFactory _azureSignalRFactory; public SignalRIESHybridClientHub(AzureSignalRFactory azureSignalRFactory,BackgroundWorkerQueue backgroundWorkerQueue, IConfiguration configuration, ILogger logger, IHttpClientFactory httpClientFactory, CoreDevice device) { _configuration=configuration; _logger=logger; _httpClientFactory=httpClientFactory; _device = device; _backgroundWorkerQueue=backgroundWorkerQueue; _azureSignalRFactory=azureSignalRFactory; } protected async override Task ExecuteAsync(CancellationToken stoppingToken) { var coreDevice = await _device.GetCoreDevice(); device=coreDevice.ToJsonString().ToObject(); string clientid = device.deviceId!; string? CenterUrl = _configuration.GetSection("HybridClient:CenterUrl").Value; long Timeout = _configuration.GetValue("HybridClient:Timeout"); long Delay = _configuration.GetValue("HybridClient:Delay"); device.timeout = Timeout; device.delay = Delay; await StartHubConnectionAsync(clientid, CenterUrl); } private async Task StartHubConnectionAsync(string clientid, string? CenterUrl) { //重写重连策略,防止服务端更新,断线后,客户端达到最大连接次数,依然连线不上服务端。 var reconnectPolicy = new ExponentialBackoffReconnectPolicy(TimeSpan.FromSeconds(10), _logger); // 尝试重连的最大次数,这里使用 int.MaxValue 表示无限次 reconnectPolicy.MaxRetryCount = int.MaxValue; //HubConnection hubConnection = new HubConnectionBuilder() // .WithUrl($"https://localhost:5001/hub/hybrid-cloud?grant_type={HybridConstant.grant_type}&clientid={clientid}&device={HttpUtility.UrlEncode(device.ToJsonString(), Encoding.Unicode)}") //only one slash // .WithAutomaticReconnect(reconnectPolicy) // .ConfigureLogging(logging => // { // logging.SetMinimumLevel(LogLevel.Information); // logging.AddConsole(); // }) // .Build(); try { //hubConnection.On("ReceiveConnection", (message) => //{ // _logger.LogInformation($"连接成功:{message.ToJsonString()}"); // //重置重连次数。 // reconnectPolicy.Reset(); //}); //hubConnection.On("ReceiveMessage", async (message) => //{ // { // _logger.LogInformation($"获得推送数据,{message.ToJsonString()}"); // } //});ieshybridcloudhub //await hubConnection.StartAsync(); var hub = _azureSignalRFactory.GetServiceManager().GetHubContext($"/ieshybridcloudhub"); await hub.Clients.User(device.deviceId).SendCoreAsync("ReceiveMessage", new[]{new { connectionId = "1", to = "2", groupname ="3", sender = device.deviceId, text = device.ToJsonString() }}); } catch (Exception ex) { _logger.LogError("初次启动连接SignalR失败,等待重连......"); int retryCount = 0; const int maxRetries = 360; const int retryDelaySeconds = 10; while (retryCount < maxRetries) { try { await Task.Delay(retryDelaySeconds * 1000); // 等待一段时间后重试 // await hubConnection.StartAsync(); _logger.LogInformation("SignalR连接成功(重试后)!"); break; // 连接成功,退出循环 } catch (Exception retryEx) { retryCount++; _logger.LogInformation($"SignalR连接重试失败: {retryEx.Message}。重试次数: {retryCount}/{maxRetries}"); // 可以在这里决定是否因为某种原因停止重试 if (retryCount == maxRetries) { _logger.LogInformation("达到最大重试次数,停止重试。"); break; } } } } } public async Task<(int status, string msg, JsonNode? data)> ReceiveMessage(JsonNode data) { int status = 0; string msg = string.Empty; _backgroundWorkerQueue.QueueBackgroundWorkItem(async task => { var pk= data["pk"]; }); return (status, msg, data); } } public class ExponentialBackoffReconnectPolicy : IRetryPolicy { private readonly TimeSpan _retryInterval; private int _retryCount; public int MaxRetryCount { get; set; } = int.MaxValue; public readonly ILogger _logger; public ExponentialBackoffReconnectPolicy(TimeSpan retryInterval, ILogger logger) { _retryInterval = retryInterval; _retryCount = 0; _logger = logger; } public TimeSpan? NextRetryDelay(RetryContext retryContext) { _logger.LogInformation($"重连次数: {_retryCount}"); if (_retryCount < MaxRetryCount) { _retryCount++; // 计算下一次重连的延迟时间 return _retryInterval; } return null; // 达到最大重连次数后不再重连 } public void Reset() { _retryCount = 0; } } }