CrazyIter_Bin 9 ماه پیش
والد
کامیت
7434450f29

+ 62 - 8
TEAMModelOS.Extension/HTEX.Complex/Controllers/ScreenController.cs

@@ -5,6 +5,8 @@ using Microsoft.AspNetCore.SignalR;
 using HTEX.Complex.Services;
 using System.Text.Json;
 using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.DI.Device;
+using Microsoft.Azure.Amqp.Framing;
 
 namespace HTEX.Complex.Controllers
 {
@@ -19,8 +21,10 @@ namespace HTEX.Complex.Controllers
         private readonly AzureRedisFactory _azureRedis;
         private readonly IHubContext<SignalRScreenServerHub> _screenServerHub;
         private readonly ILogger<ScreenController> _logger;
+        private readonly CoreDevice _device;
+
         public ScreenController(AzureRedisFactory azureRedis,  IHttpClientFactory httpClient, IConfiguration configuration, AzureStorageFactory azureStorage,
-            DingDing dingDing, IHubContext<SignalRScreenServerHub> screenServerHub , ILogger<ScreenController> logger)
+            DingDing dingDing, IHubContext<SignalRScreenServerHub> screenServerHub , ILogger<ScreenController> logger, CoreDevice device)
         {
             _httpClient = httpClient;
             _configuration = configuration;
@@ -29,8 +33,21 @@ namespace HTEX.Complex.Controllers
             _azureRedis=azureRedis;
             _screenServerHub = screenServerHub;
             _logger = logger;
+            _device = device;
+        }
+        /// <summary>
+        /// 添加任务
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("push-task")]
+        public async Task<IActionResult> AddTask(JsonElement json) 
+        {
+            GenPDFData  genPDFData = json.ToObject<GenPDFData>();
+            ClientDevice serverDevice =  await _device.GetCoreDevice();
+            var addData = await GenPDFService.AddGenPdfQueue(_azureRedis, genPDFData, serverDevice);
+            await ManualSendTask();
+            return Ok(new { add= addData .add ,total= addData .total});
         }
-
         /// <summary>
         /// 外部触发任务发送
         /// </summary>
@@ -38,7 +55,14 @@ namespace HTEX.Complex.Controllers
         [HttpPost("send-task")]
         public async Task<IActionResult> SendTask(JsonElement json)
         {
-            var values =  await _azureRedis.GetRedisClient(8).HashGetAllAsync("ScreenApi:clients");
+            await ManualSendTask(); 
+            return Ok();
+        }
+
+        private async Task ManualSendTask()
+        {
+            ClientDevice serverDevice = await _device.GetCoreDevice();
+            var values = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"ScreenApi:clients:{serverDevice.deviceId}");
             if (values!=null)
             {
                 foreach (var value in values)
@@ -51,9 +75,40 @@ namespace HTEX.Complex.Controllers
                     }
                     if (screenClient.status!.Equals(ScreenConstant.idle) && !string.IsNullOrWhiteSpace(screenClient.connid))
                     {
+                        ////////////////////
+                        ///检擦是否在线
+                        //var cts = new CancellationTokenSource();
+                        //try
+                        //{
+                        //    await _screenServerHub.Clients.Client(screenClient.connid!).SendAsync("ReceiveConnection", new ConnectionMessage
+                        //    {
+                        //        connid=screenClient.connid!,
+                        //        clientid = screenClient.clientid,
+                        //        status = screenClient.status,
+                        //        grant_type = screenClient.grant_type,
+                        //        message_type= MessageType.conn_success,
+                        //        content = $"检查连接!"
+                        //    }, cts);
+                        //}
+                        //catch (OperationCanceledException)
+                        //{
+                        //    Console.WriteLine("Operation was canceled.");
+                        //}
+                        //catch (HubException ex) 
+                        //{
+                        //    if (ex.Message.Contains("disconnected"))
+                        //    {
+                        //        _logger.LogInformation($"客户端连接异常=>{screenClient.name},{screenClient.region},{screenClient.clientid},连接失败......{ex.Message},{ex.StackTrace}");  // 客户端不在线
+                        //    }
+                        //    _logger.LogInformation($"客户端连接异常=>{screenClient.name},{screenClient.region},{screenClient.clientid},连接失败......{ex.Message},{ex.StackTrace}");
+                        //}
+                        //catch (Exception ex)
+                        //{
+                        //    _logger.LogInformation($"客户端连接异常=>{screenClient.name},{screenClient.region},{screenClient.clientid},连接失败......{ex.Message},{ex.StackTrace}");
+                        //}
                         _logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{screenClient.clientid},分发任务......");
                         //连接成功,马上分发任务。
-                        var task = await TaskService.SentTask(_azureRedis, _azureStorage);
+                        var task = await TaskService.SentTask(_azureRedis, _azureStorage, _logger, serverDevice);
                         if (task.genQueue!=null && task.genRedis!=null  && !string.IsNullOrWhiteSpace(task.genQueue.cntName))
                         {
                             screenClient.status =  ScreenConstant.busy;
@@ -67,10 +122,11 @@ namespace HTEX.Complex.Controllers
                                 message_type= MessageType.task_send_success,
                                 content =$"{task.genQueue.ToJsonString()}",//从Redis中获取任务信息
                             });
+                            _logger.LogInformation($"分发任务:{task.genQueue.ToJsonString()}");
                         }
                         else
                         {
-                            _logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{screenClient.clientid},暂无任务可领取的任务......");
+                            //_logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{screenClient.clientid},暂无任务可领取的任务......");
                             if (task.genRedis!=null)
                             {
                                 string msgError = $"分发任务异常原因=>{screenClient.name},{screenClient.region},{screenClient.clientid}:{task.msg}\ngenQueue:{task.genQueue?.ToJsonString()}\ngenRedis:{task.genRedis?.ToJsonString()}";
@@ -92,11 +148,9 @@ namespace HTEX.Complex.Controllers
                             });
                         }
                     }
-                    await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients", screenClient.clientid, screenClient.ToJsonString());
+                    await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients:{serverDevice.deviceId}", screenClient.clientid, screenClient.ToJsonString());
                 }
             }
-            else { }
-            return Ok();
         }
     }
 }

+ 2 - 0
TEAMModelOS.Extension/HTEX.Complex/HTEX.Complex.csproj

@@ -15,6 +15,8 @@
 	<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.9.3" />
 	<PackageReference Include="MQTTnet.AspNetCore" Version="4.3.6.1152" />
 	<PackageReference Include="MQTTnet.AspNetCore.Routing" Version="0.4.37" />
+	<PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
+	<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\TEAMModelOS.SDK\TEAMModelOS.SDK.csproj" />

+ 24 - 4
TEAMModelOS.Extension/HTEX.Complex/Program.cs

@@ -18,13 +18,35 @@ using System.Text.Json;
 using Microsoft.Extensions.Hosting;
 using MQTTnet.AspNetCore.Routing;
 using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting.Server;
+using Microsoft.AspNetCore.Hosting.Server.Features;
+using System.Security.Policy;
+using System.Net.Http;
+using TEAMModelOS.SDK.DI.Device;
+using Serilog;
 namespace HTEX.Complex
 {
     public class Program
     {
         public static void Main(string[] args)
         {
+
+          
             var builder = WebApplication.CreateBuilder(args);
+            //防止编译后的appsettings.json 文件内容,在重新部署的时候,因为不同的环境导致被覆盖的问题,
+            //所以在正式环境中指定appsettings-prod.json一个本地开发环境不存在的文件,以达到不会被覆盖的问题,
+            //即使在生产环境中未配置appsettings-prod.json 也不影响启动,因为会按照appsettings.json的配置启动
+#if !DEBUG
+            builder.Host.ConfigureAppConfiguration((context, config) => {
+                 config.SetBasePath(Directory.GetCurrentDirectory());
+                 config.AddJsonFile("appsettings-prod.json", optional: true, reloadOnChange: true);
+             });
+#endif
+
+            Log.Logger = new LoggerConfiguration().MinimumLevel.Debug().WriteTo.Console(outputTemplate: "{Timestamp:HH:mm:ss.fff zzz} [{Level:u3}] ({ThreadId}) {Message}{NewLine}{Exception}")
+            .WriteTo.File("logs/log-.log", rollingInterval: RollingInterval.Day).CreateLogger();
+            builder.Host.UseSerilog();
+
             //builder.WebHost.ConfigureKestrel(options =>
             //{
             //    //options.ListenAnyIP(4001, options => {
@@ -87,16 +109,13 @@ namespace HTEX.Complex
             builder.Services.AddAzureStorage(StorageConnectionString, "Default");
             //Redis
             builder.Services.AddAzureRedis(RedisConnectionString, "Default");
-            string? StorageConnectionStringTest = builder.Configuration.GetValue<string>("Azure:Storage:ConnectionString-Test");
-            //Storage
-            builder.Services.AddAzureStorage(StorageConnectionStringTest, "Test");
-
             builder.Services.AddSignalR();
             builder.Services.AddHttpContextAccessor();
             builder.Services.AddHttpClient<DingDing>();
             string path = $"{builder.Environment.ContentRootPath}/JsonFiles";
             builder.Services.TryAddSingleton(new Region2LongitudeLatitudeTranslator(path));
             builder.Services.AddIPSearcher(path);
+            builder.Services.AddSingleton<CoreDevice>();
             builder.Services.AddCors(options =>
             {
                 options.AddDefaultPolicy(
@@ -155,6 +174,7 @@ namespace HTEX.Complex
                 //server.ClientAcknowledgedPublishPacketAsync += events._mqttServer_ClientAcknowledgedPublishPacketAsync;//已确认发布数据包
             });
             app.Run();
+           
         }
     }
 }

+ 46 - 20
TEAMModelOS.Extension/HTEX.Complex/Services/SignalRScreenServerHub.cs

@@ -7,6 +7,12 @@ using System.Web;
 using System.Text;
 
 using StackExchange.Redis;
+using Microsoft.Extensions.Logging;
+using TEAMModelOS.SDK.Models;
+using Google.Protobuf.WellKnownTypes;
+using Microsoft.Extensions.DependencyInjection;
+using TEAMModelOS.SDK.DI.Device;
+
 namespace HTEX.Complex.Services
 {
     public class SignalRScreenServerHub : Hub<IClient>
@@ -16,12 +22,14 @@ namespace HTEX.Complex.Services
         private readonly AzureRedisFactory _azureRedis;
         private readonly AzureStorageFactory _azureStorage;
         private readonly DingDing _dingDing;
-        public SignalRScreenServerHub(AzureRedisFactory azureRedis, ILogger<SignalRScreenServerHub> logger ,AzureStorageFactory azureStorage, DingDing dingDing)
+        private readonly CoreDevice _device;
+        public SignalRScreenServerHub(AzureRedisFactory azureRedis,   ILogger<SignalRScreenServerHub> logger,  AzureStorageFactory azureStorage, DingDing dingDing, CoreDevice device)
         {
             _logger = logger;
             _azureRedis = azureRedis;
             _azureStorage = azureStorage;
             _dingDing = dingDing;
+            _device=device;
         }
 
         /// <summary>
@@ -30,6 +38,9 @@ namespace HTEX.Complex.Services
         /// <returns></returns>
         public override async Task OnConnectedAsync()
         {
+            var serverDevice = await  _device.GetCoreDevice();
+            
+             
             var connid = Context.ConnectionId;
             var httpContext = Context.GetHttpContext();
             if (httpContext != null)
@@ -49,15 +60,16 @@ namespace HTEX.Complex.Services
                     {
                         connid = connid,
                         grant_type = grant_type,
-                        clientid= clientid
+                        clientid= clientid,
+                        serverid=serverDevice.deviceId,
                     };
-                    await _azureRedis.GetRedisClient(8).HashSetAsync($"SignalRClient:connects", connid, client.ToJsonString());
-                    ClientDevice device = HttpUtility.UrlDecode(_device, Encoding.Unicode).ToObject<ClientDevice>();
+                    await _azureRedis.GetRedisClient(8).HashSetAsync($"SignalRClient:connects:{serverDevice.deviceId}", connid, client.ToJsonString());
+                    ScreenClient device = HttpUtility.UrlDecode(_device, Encoding.Unicode).ToObject<ScreenClient>();
                     switch (true) 
                     {
                         case bool when grant_type.Equals(ScreenConstant.grant_type):
                             ScreenClient screenClient ;
-                            var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients", client.clientid);
+                            var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients:{serverDevice.deviceId}", client.clientid);
                             if (value!=default  && value.HasValue)
                             {
                                 screenClient = value.ToString().ToObject<ScreenClient>();
@@ -93,6 +105,7 @@ namespace HTEX.Complex.Services
                             screenClient.cpu = device.cpu;
                             screenClient.ram = device.ram;
                             screenClient.last_time= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                            screenClient.deviceId = serverDevice.deviceId;
                             //连接成功,发送消息给客户端。
                             await SendConnection(connid, new ConnectionMessage
                             {
@@ -107,7 +120,7 @@ namespace HTEX.Complex.Services
                             if (screenClient.status!.Equals(ScreenConstant.idle)) {
                                 _logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{clientid},分发任务......");
                                 //连接成功,马上分发任务。
-                                var task = await TaskService.SentTask(_azureRedis,_azureStorage);
+                                var task = await TaskService.SentTask(_azureRedis,_azureStorage, _logger, serverDevice);
                                 if (task.genQueue!=null && task.genRedis!=null  && !string.IsNullOrWhiteSpace(task.genQueue.cntName))
                                 {
                                     screenClient.status =  ScreenConstant.busy;
@@ -121,9 +134,10 @@ namespace HTEX.Complex.Services
                                         message_type= MessageType.task_send_success,
                                         content =$"{task.genQueue.ToJsonString()}",//从Redis中获取任务信息
                                     });
+                                    _logger.LogInformation($"分发任务:{task.genQueue.ToJsonString()}");
                                 }
                                 else {
-                                    _logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{clientid},暂无任务可领取的任务......");
+                                   // _logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{clientid},暂无任务可领取的任务......");
                                     if (task.genRedis!=null)
                                     {
                                         string msgError = $"分发任务异常原因=>{screenClient.name},{screenClient.region},{clientid}:{task.msg}\ngenQueue:{task.genQueue?.ToJsonString()}\ngenRedis:{task.genRedis?.ToJsonString()}";
@@ -144,7 +158,7 @@ namespace HTEX.Complex.Services
                                     });
                                 }
                             }
-                            await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients", client.clientid, screenClient.ToJsonString());
+                            await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients:{serverDevice.deviceId}", client.clientid, screenClient.ToJsonString());
                             break;
                     }
                 }
@@ -165,30 +179,40 @@ namespace HTEX.Complex.Services
 
         public override async  Task OnDisconnectedAsync(Exception? exception)
         {
+
+            var serverDevice= await _device.GetCoreDevice();
             var connid = Context.ConnectionId;
-            var redisData = await _azureRedis.GetRedisClient(8).HashGetAsync($"SignalRClient:connects", connid);
+            var redisData = await _azureRedis.GetRedisClient(8).HashGetAsync($"SignalRClient:connects:{serverDevice.deviceId}", connid);
             _logger.LogInformation($"客户端断开连接=>{connid} ");
             ///连接配置,并且使用钉钉 离线通知。
             if (!redisData.IsNullOrEmpty)
             {
                 var client = redisData.ToString().ToObject<SignalRClient>();
-                await _azureRedis.GetRedisClient(8).HashDeleteAsync($"SignalRClient:connects", connid);
+                await _azureRedis.GetRedisClient(8).HashDeleteAsync($"SignalRClient:connects:{serverDevice.deviceId}", connid);
                 if (client != null)
                 {
                     await Groups.RemoveFromGroupAsync(connid, client.grant_type!);
-                    var value =  await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients", client.clientid);
+                    var value =  await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients:{serverDevice.deviceId}", client.clientid);
                     if (value!=default  && value.HasValue) 
                     {
                         ScreenClient screenClient = value.ToString().ToObject<ScreenClient>() ;
                         _logger.LogInformation($"客户端断开连接=>{connid},{screenClient.name},{screenClient.region},{screenClient.clientid} ");
                         long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                         // 判断是否过期
-                        if (screenClient.status!.Equals(ScreenConstant.busy )  &&    screenClient.last_time+screenClient.timeout+screenClient.delay+ ScreenConstant.time_excess <=now)
+                        if (screenClient.status!.Equals(ScreenConstant.busy))
                         {
+                            //超时了
+                            if (screenClient.last_time+screenClient.timeout+screenClient.delay+ ScreenConstant.time_excess <=now)
+                            {
+                                screenClient.status=ScreenConstant.offline;
+                                screenClient.connid= string.Empty;
+                            }
+                        }
+                        else {
                             screenClient.status=ScreenConstant.offline;
                             screenClient.connid= string.Empty;
-                            await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients", client.clientid, screenClient.ToJsonString());
                         }
+                        await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients:{serverDevice.deviceId}", client.clientid, screenClient.ToJsonString());
                     }
                 }
             }
@@ -200,13 +224,14 @@ namespace HTEX.Complex.Services
             ////接收消息
             //如果是超时,放回队列。
             ///分发新任务。
+            var serverDevice = await _device.GetCoreDevice();
             long nowNew = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             var connid = Context.ConnectionId;
             PDFGenQueue? task =  message.content?.ToObject<PDFGenQueue>();
             ScreenClient screenClient = null;
             try
             {  //释放客户端的忙碌状态。
-                var redisData = await _azureRedis.GetRedisClient(8).HashGetAsync($"SignalRClient:connects", connid);
+                var redisData = await _azureRedis.GetRedisClient(8).HashGetAsync($"SignalRClient:connects:{serverDevice.deviceId}", connid);
                 var client = redisData.ToString().ToObject<SignalRClient>();
                 await SendConnection(connid, new ConnectionMessage
                 {
@@ -217,14 +242,14 @@ namespace HTEX.Complex.Services
                     message_type= MessageType.conn_success,
                     content = $"客户端空闲,等待任务分发......"
                 });
-                var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients", client.clientid);
+                var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ScreenApi:clients:{serverDevice.deviceId}", client.clientid);
                 if (value!=default  && value.HasValue)
                 {
                     screenClient = value.ToString().ToObject<ScreenClient>();
                     screenClient.status=ScreenConstant.idle;
                     screenClient.last_time=nowNew;
                     screenClient.taskComplete++;
-                    await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients", client.clientid,screenClient.ToJsonString());
+                    await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients:{serverDevice.deviceId}", client.clientid,screenClient.ToJsonString());
                     _logger.LogInformation($"客户端空闲,等待任务分发......=>{connid},{screenClient.name},{screenClient.region},{screenClient.clientid} ");
                 }
                 
@@ -248,12 +273,12 @@ namespace HTEX.Complex.Services
                 ///如果是超时,放回队列。
                 if (message.result==4)
                 {
-                    await _azureRedis.GetRedisClient(8).ListLeftPushAsync($"PDFGen:Queue", task.ToJsonString());
+                    await _azureRedis.GetRedisClient(8).ListLeftPushAsync($"PDFGen:Queue:{serverDevice.deviceId}", task.ToJsonString());
                 }
             }
             if (screenClient!=null && screenClient.status!.Equals(ScreenConstant.idle))
             {
-                var taskData = await TaskService.SentTask(_azureRedis, _azureStorage);
+                var taskData = await TaskService.SentTask(_azureRedis, _azureStorage, _logger, serverDevice);
                 if (taskData.genQueue!=null && taskData.genRedis!=null  && !string.IsNullOrWhiteSpace(taskData.genQueue.cntName))
                 {
                     screenClient.status =  ScreenConstant.busy;
@@ -267,10 +292,11 @@ namespace HTEX.Complex.Services
                         message_type= MessageType.task_send_success,
                         content =$"{taskData.genQueue.ToJsonString()}",//从Redis中获取任务信息
                     });
+                    _logger.LogInformation($"分发任务:{taskData.genQueue.ToJsonString()}");
                 }
                 else
                 {
-                    _logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{screenClient.clientid},暂无任务可领取的任务......");
+                    //_logger.LogInformation($"客户端当前空闲=>{screenClient.name},{screenClient.region},{screenClient.clientid},暂无任务可领取的任务......");
                     if (taskData.genRedis!=null)
                     {
                         string msgError = $"分发任务异常原因=>{screenClient.name},{screenClient.region},{screenClient.clientid}:{taskData.msg}\ngenQueue:{taskData.genQueue?.ToJsonString()}\ngenRedis:{taskData.genRedis?.ToJsonString()}";
@@ -291,7 +317,7 @@ namespace HTEX.Complex.Services
                         content = taskData.msg
                     });
                 }
-                await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients", screenClient.clientid, screenClient.ToJsonString());
+                await _azureRedis.GetRedisClient(8).HashSetAsync($"ScreenApi:clients:{serverDevice.deviceId}", screenClient.clientid, screenClient.ToJsonString());
             }
         }
         public async Task SendConnection(string connectionId, MessageBody msg)

+ 9 - 6
TEAMModelOS.Extension/HTEX.Complex/Services/TaskService.cs

@@ -9,12 +9,12 @@ namespace HTEX.Complex.Services
 {
     public class TaskService
     {
-        public static async Task<(PDFGenRedis genRedis, PDFGenQueue genQueue, string msg)> SentTask(AzureRedisFactory _azureRedis, AzureStorageFactory _azureStorage)
+        public static async Task<(PDFGenRedis genRedis, PDFGenQueue genQueue, string msg)> SentTask(AzureRedisFactory _azureRedis, AzureStorageFactory _azureStorage, ILogger logger,ClientDevice serverDevice)
         {
             string msg = string.Empty;
             //从尾部弹出元素,队列先进先出
             long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-            var queueValue = await _azureRedis.GetRedisClient(8).ListRightPopAsync("PDFGen:Queue");
+            var queueValue = await _azureRedis.GetRedisClient(8).ListRightPopAsync($"PDFGen:Queue:{serverDevice.deviceId}");
             PDFGenRedis genRedis = null;
             PDFGenQueue genQueue = null;
             if (queueValue!=default && queueValue.HasValue)
@@ -38,8 +38,8 @@ namespace HTEX.Complex.Services
                             url=  HttpUtility.UrlDecode(url);
                             uri = new Uri(url);
                             string host = uri.Host;
-                            string azure_region = genQueue.env.Equals(ScreenConstant.env_develop) ? "Test" : "Default";
-                            var blobServiceClient = _azureStorage.GetBlobServiceClient(azure_region);
+                            
+                            var blobServiceClient = _azureStorage.GetBlobServiceClient();
                             if (host.Equals(blobServiceClient.Uri.Host))
                             {
                                 // 获取容器名,它是路径的第一个部分
@@ -49,11 +49,12 @@ namespace HTEX.Complex.Services
                                 string directoryPath = string.Join("", uri.Segments, 2, uri.Segments.Length - 3);
                                 string? fileName = Path.GetFileNameWithoutExtension(uri.AbsolutePath);
                                 string blobPath = $"{directoryPath}{fileName}.pdf";
-                                var urlSas = _azureStorage.GetBlobSAS(containerName, blobPath, BlobSasPermissions.Write|BlobSasPermissions.Read, hour: 1, name: azure_region);
+                                var urlSas = _azureStorage.GetBlobSAS(containerName, blobPath, BlobSasPermissions.Write|BlobSasPermissions.Read, hour: 1);
                                 genQueue.blobSas =  urlSas.sas;
                                 genQueue.blobName=blobPath;
                                 genQueue.cntName=containerName;
                                 genQueue.blobFullUrl=urlSas.fullUri;
+                                
                             }
                             else
                             {
@@ -73,7 +74,9 @@ namespace HTEX.Complex.Services
                     }
                     catch (Exception ex)
                     {
-                        msg=$"数据地址处理异常,异常信息:{ex.Message}";
+                        
+                        msg =$"数据地址处理异常,异常信息:{ex.Message}";
+                        logger.LogInformation($"{msg},{ex.StackTrace}");
                         genRedis.status=3;
                         genRedis.msg = ex.Message;
                     }

+ 1 - 2
TEAMModelOS.Extension/HTEX.Complex/appsettings.Development.json

@@ -18,8 +18,7 @@
   },
   "Azure": {
     "Storage": {
-      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelos;AccountKey=Dl04mfZ9hE9cdPVO1UtqTUQYN/kz/dD/p1nGvSq4tUu/4WhiKcNRVdY9tbe8620nPXo/RaXxs+1F9sVrWRo0bg==;EndpointSuffix=core.chinacloudapi.cn",
-      "ConnectionString-Test": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
+      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn",
     },
     "Redis": {
       "ConnectionString": "52.130.252.100:6379,password=habook,ssl=false,abortConnect=False,writeBuffer=10240"

+ 3 - 5
TEAMModelOS.Extension/HTEX.Complex/appsettings.json

@@ -9,21 +9,19 @@
   "Kestrel": {
     "Endpoints": {
       "Http": {
-        "Url": "http://*:8807"
+        "Url": "http://*:8907"
       },
       "Https": {
-        "Url": "https://*:8808"
+        "Url": "https://*:8908"
       }
     }
   },
   "Azure": {
     "Storage": {
       "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelos;AccountKey=Dl04mfZ9hE9cdPVO1UtqTUQYN/kz/dD/p1nGvSq4tUu/4WhiKcNRVdY9tbe8620nPXo/RaXxs+1F9sVrWRo0bg==;EndpointSuffix=core.chinacloudapi.cn",
-      "ConnectionString-Test": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
     },
     "Redis": {
-      "ConnectionString": "52.130.252.100:6379,password=habook,ssl=false,abortConnect=False,writeBuffer=10240"
-      //"ConnectionString": "CoreRedisCN.redis.cache.chinacloudapi.cn:6380,password=LyJWP1ORJdv+poXWofAF97lhCEQPg1wXWqvtzXGXQuE=,ssl=True,abortConnect=False"
+      "ConnectionString": "CoreRedisCN.redis.cache.chinacloudapi.cn:6380,password=LyJWP1ORJdv+poXWofAF97lhCEQPg1wXWqvtzXGXQuE=,ssl=True,abortConnect=False"
     }
   }
 }

+ 9 - 6
TEAMModelOS.Extension/HTEX.ScreenClient/Program.cs

@@ -5,6 +5,7 @@ using System.Net;
 using System.Net.Sockets;
 using System.Runtime.InteropServices;
 using System.Text.RegularExpressions;
+using TEAMModelOS.SDK.DI.Device;
 
 namespace HTEX.ScreenClient
 {
@@ -14,16 +15,18 @@ namespace HTEX.ScreenClient
         {
            
             var builder = WebApplication.CreateBuilder(args);
-   
+            builder.WebHost.UseKestrel(options =>
+            {
+                // options.ListenAnyIP(CheckOrNewPort(1883), options => {/*options.UseHttps("Crt/iteden.pfx", "iteden");*/ });
+                options.ListenAnyIP(CheckOrNewPort(5000), options => {/* options.UseHttps("Configs/Crt/iteden.pfx", "iteden"); */}); // Default HTTP pipeline
+            });
+            //写在端口配置之前,并且在用到的DI之前。否则会导致DI注入失败
+            
             builder.Services.AddControllers();
             builder.Services.AddHttpClient();
             builder.Services.AddHttpContextAccessor();
-            //CheckOrNewPort(5000)
-            builder.WebHost.UseKestrel(options => {
-                options.ListenAnyIP(CheckOrNewPort(5000), options => {/* options.UseHttps("Configs/Crt/iteden.pfx", "iteden"); */}); // Default HTTP pipeline
-            });
-
             builder.Services.AddHostedService<SignalRScreenClientHub>();
+            builder.Services.AddSingleton<CoreDevice>();
             var app = builder.Build();
 
             app.UseHttpsRedirection();

+ 9 - 156
TEAMModelOS.Extension/HTEX.ScreenClient/Services/SignalRScreenClientHub.cs

@@ -18,6 +18,7 @@ using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using System.Web;
 using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.DI.Device;
 using TEAMModelOS.SDK.Extension;
 
 namespace HTEX.ScreenClient.Services
@@ -26,28 +27,23 @@ namespace HTEX.ScreenClient.Services
     {
         private readonly IConfiguration _configuration; 
         private readonly ILogger<SignalRScreenClientHub> _logger;
+        private TEAMModelOS.SDK.ScreenClient? device;
+        private readonly CoreDevice _device;
         private readonly IHttpClientFactory _httpClientFactory;
-        private readonly IServiceProvider _services;
-        private IEnumerable<string>? _url = new List<string>();
-        private ClientDevice? device;
-        public SignalRScreenClientHub(IConfiguration configuration,ILogger<SignalRScreenClientHub> logger,IHttpClientFactory httpClientFactory, IServiceProvider services,IHostApplicationLifetime lifetime) 
+        public SignalRScreenClientHub(IConfiguration configuration,ILogger<SignalRScreenClientHub> logger,IHttpClientFactory httpClientFactory, CoreDevice device) 
         {
                 
             _configuration=configuration;
             _logger=logger;
             _httpClientFactory=httpClientFactory;
-            _services=services;
-            lifetime.ApplicationStarted.Register(() => {
-                var server = _services.GetService<IServer>();
-                _url = server?.Features.Get<IServerAddressesFeature>()?.Addresses;
-            });
+            _device = device;
         }
         
         protected async override Task ExecuteAsync(CancellationToken stoppingToken)
         {
-            device =  await GetClientInfo();
-            string hashData = $"{device.name}-{device.remote}-{device.port}-{device.os}-{string.Join(",",device.networks.Select(x=>$"{x.mac}-{x.ip}"))}";
-            string clientid =  ShaHashHelper.GetSHA256(hashData);
+            var coreDevice =  await _device.GetCoreDevice();
+            device=coreDevice.ToJsonString().ToObject<TEAMModelOS.SDK.ScreenClient>();
+            string clientid = device.deviceId!;
             string? CenterUrl = _configuration.GetSection("ScreenClient:CenterUrl").Value;
             string? ScreenUrl = _configuration.GetSection("ScreenClient:ScreenUrl").Value;
             long Timeout = _configuration.GetValue<long>("ScreenClient:Timeout");
@@ -220,150 +216,7 @@ namespace HTEX.ScreenClient.Services
             return (status, msg, task);
         }
 
-        public async Task<ClientDevice> GetClientInfo()
-        {
-            string hostName =$"{Environment.UserName}-{Dns.GetHostName()}" ;
-            string os = RuntimeInformation.OSDescription;
-            //获取当前客户端的服务端口
-            var _httpClient = _httpClientFactory.CreateClient();
-            ClientDevice device = new ClientDevice { name =hostName, os= os };
-            HttpResponseMessage message = await _httpClient.PostAsJsonAsync("https://www.teammodel.cn/core/system-info", new { });
-            if (message.IsSuccessStatusCode)
-            {
-                JsonNode? json = JsonSerializer.Deserialize<JsonNode>(await message.Content.ReadAsStringAsync());
-                var ip =  json?["ip"];
-                var region = json?["region"];
-                _logger.LogInformation($"远程地址:{ip}");
-                _logger.LogInformation($"所属地区:{region}");
-                device.remote=ip?.ToString();
-                device.region=region?.ToString();
-            }
-            _logger.LogInformation($"计算机名:{hostName}");
-            _logger.LogInformation($"系统名称:{RuntimeInformation.OSDescription}");
-            int CpuCoreCount = 0;
-            long MenemorySize = 0;
-            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
-            {
-                // 获取CPU核心数
-                //int processorCount = Environment.ProcessorCount;
-               //Console.WriteLine("CPU 核心数: " + processorCount);
-                using (ManagementClass managementClass = new ManagementClass("Win32_Processor"))
-                {
-                    using (ManagementObjectCollection managementObjectCollection = managementClass.GetInstances())
-                    {
-                        foreach (ManagementObject managementObject in managementObjectCollection)
-                        {
-                            CpuCoreCount += Convert.ToInt32(managementObject.Properties["NumberOfLogicalProcessors"].Value);
-                        }
-                    }
-                }
-                using (ManagementClass mc = new ManagementClass("Win32_ComputerSystem"))
-                {
-                    using (ManagementObjectCollection moc = mc.GetInstances())
-                    {
-                        foreach (ManagementObject mo in moc)
-                        {
-                            if (mo["TotalPhysicalMemory"]!= null)
-                            {
-                                MenemorySize = Convert.ToInt64(mo["TotalPhysicalMemory"]);
-                            }
-                        }
-                    }
-                }
-            }
-            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
-            {
-                //int processorCount = Environment.ProcessorCount;
-               // Console.WriteLine("CPU 核心数: " + processorCount);
-                string[] cpu_lines = File.ReadAllLines("/proc/cpuinfo");
-                CpuCoreCount= cpu_lines.Count(line => line.StartsWith("processor", StringComparison.OrdinalIgnoreCase));
-                string[] mem_lines = File.ReadAllLines("/proc/meminfo");
-                var match = mem_lines.FirstOrDefault(line => line.StartsWith("MemTotal:"));
-                if (match != null)
-                {
-                    var matchResult = Regex.Match(match, @"\d+");
-                    if (matchResult.Success)
-                    {
-                        MenemorySize=  long.Parse(matchResult.Value);
-                    }
-                }
-            }
-            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
-            {
-                using (var process = new Process())
-                {
-                    process.StartInfo.FileName = "/usr/sbin/sysctl";
-                    process.StartInfo.Arguments = "-n hw.ncpu";
-                    process.StartInfo.RedirectStandardOutput = true;
-                    process.StartInfo.UseShellExecute = false;
-                    process.Start();
-                    string output = process.StandardOutput.ReadToEnd().Trim();
-                    int coreCount;
-                    if (int.TryParse(output, out coreCount))
-                    {
-                        CpuCoreCount= coreCount;
-                    }
-                }
-                using (var process = new Process())
-                {
-                    process.StartInfo.FileName = "/usr/sbin/sysctl";
-                    process.StartInfo.Arguments = "-n hw.memsize";
-                    process.StartInfo.RedirectStandardOutput = true;
-                    process.StartInfo.UseShellExecute = false;
-                    process.Start();
-                    string output = process.StandardOutput.ReadToEnd().Trim();
-                    long memorySize;
-                    if (long.TryParse(output, out memorySize))
-                    {
-                        MenemorySize=  memorySize;
-                    }
-                }
-            }
-
-            //Console.WriteLine("CPU 核心数: " + CpuCoreCount+",RAM 大小:"+MenemorySize);
-            _logger.LogInformation($"内存大小:{MenemorySize}");
-            _logger.LogInformation($"核心数量:{CpuCoreCount}");
-            device.cpu=CpuCoreCount;
-            device.ram=MenemorySize;
-            var nics = NetworkInterface.GetAllNetworkInterfaces();
-            foreach (var nic in nics)
-            {
-                if (nic.OperationalStatus == OperationalStatus.Up)
-                {
-                    var name = $"{nic.Name}-{nic.Description}";
-                    var mac = nic.GetPhysicalAddress().ToString();
-                    var properties = nic.GetIPProperties();
-                    var unicastAddresses = properties.UnicastAddresses;
-                    foreach (var unicast in unicastAddresses)
-                    {
-                        if (unicast.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
-                        {
-                            var ip = unicast.Address.ToString();
-                            Network network= new Network() { mac=mac, ip=ip ,name= name};
-                            if (!string.IsNullOrWhiteSpace(mac.ToString())  && !mac.Equals("000000000000"))
-                            {
-                                device.networks.Add(network);
-                                _logger.LogInformation($"网卡名称: {name}");
-                                _logger.LogInformation($"网卡地址: {mac}");
-                                _logger.LogInformation($"内网地址: {ip}");
-                            }
-                        }
-                    }
-                }
-            }
-            if (_url!=null) 
-            {
-                List<int> ports = new List<int>();
-                foreach (var url in _url)
-                {
-                    Uri uri = new Uri(url);
-                    ports.Add(uri.Port);
-                }
-                device.port= string.Join(",", ports);
-                _logger.LogInformation($"占用端口: {device.port}");
-            }
-            return device ;
-        }
+       
        
     }
     public class ExponentialBackoffReconnectPolicy : IRetryPolicy

+ 1 - 1
TEAMModelOS.Extension/HTEX.ScreenClient/appsettings.Development.json

@@ -10,6 +10,6 @@
     "ScreenUrl": "http://52.130.252.100:13000",
     "Timeout": 30000,
     "Delay": 500,
-    "CenterUrl": "http://52.130.252.100:8807"
+    "CenterUrl": "http://127.0.0.1:8807"
   }
 }

+ 1 - 1
TEAMModelOS.Function/IESServiceBusTrigger.cs

@@ -117,7 +117,7 @@ namespace TEAMModelOS.Function
                         json.TryGetProperty("headLang", out JsonElement headLang);
                         List<string> studentIds = _studentIds.ToObject<List<string>>();
                         var data =  await GenPDFService.GenArtStudentPdf(_azureRedis, _azureCosmos,  _coreAPIHttpService, _dingDing, _azureStorage,_configuration, studentIds,$"{_artId}",$"{_schoolId}",$"{headLang}");
-                        await GenPDFService. PushScreenTask(_azureRedis, _configuration, $"{_artId}",data. art,data. studentPdfs);
+                        await GenPDFService. PushScreenTask(_azureRedis, _configuration, $"{_artId}",data. art,data. studentPdfs,_httpClient,_dingDing);
                         break;
                 }
             }

+ 52 - 0
TEAMModelOS.SDK/DI/Device/CoreDevice.cs

@@ -0,0 +1,52 @@
+using Microsoft.AspNetCore.Hosting.Server.Features;
+using Microsoft.Azure.Cosmos;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting.Server;
+namespace TEAMModelOS.SDK.DI.Device
+{
+    public class CoreDevice
+    {
+        private readonly IServiceProvider _services;
+        private readonly ILogger _logger;
+        private readonly IHttpClientFactory _httpClientFactory;
+        private readonly IHostApplicationLifetime _lifetime;
+        private ConcurrentDictionary<string, Task <ClientDevice>> clientDevice { get; } = new ConcurrentDictionary<string, Task<ClientDevice>>();
+        public CoreDevice(IServiceProvider services,  ILogger<CoreDevice> logger, IHostApplicationLifetime lifetime, IHttpClientFactory httpClientFactory)
+        {
+            _services = services;
+            _logger = logger;
+            _services=services;
+            _httpClientFactory=httpClientFactory;
+            _lifetime = lifetime;
+           
+          
+        }
+        public   Task<ClientDevice> GetCoreDevice()
+        {
+            try
+            {
+                var server = _services.GetService<IServer>();
+                var d = server?.Features.Get<IServerAddressesFeature>();
+                IEnumerable<string>? _url = server?.Features.Get<IServerAddressesFeature>()?.Addresses;
+                var device = clientDevice.GetOrAdd("Device", x => DeviceHelper.GetClientInfo(_httpClientFactory, _logger, _url));
+                return device;
+            }
+            catch (Exception e)
+            {
+                _logger?.LogWarning(e, e.Message);
+                throw;
+            }
+        }
+    }
+}

+ 174 - 0
TEAMModelOS.SDK/Helper/Common/DeviceHelper.cs

@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net.Http;
+using System.Net.NetworkInformation;
+using System.Net;
+using System.Runtime.InteropServices;
+using System.Security.Policy;
+using System.Text;
+using System.Text.Json.Nodes;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Text.Json;
+using Microsoft.Extensions.Logging;
+using System.IO;
+using Microsoft.Extensions.Configuration;
+using System.Management;
+using System.Net.Http.Json;
+namespace TEAMModelOS.SDK
+{
+    public static class DeviceHelper
+    {
+        public static async Task<ClientDevice> GetClientInfo(IHttpClientFactory _httpClientFactory, ILogger _logger, IEnumerable<string>? _url)
+        {
+            string hostName = $"{Environment.UserName}-{Dns.GetHostName()}";
+            string os = RuntimeInformation.OSDescription;
+            //获取当前客户端的服务端口
+            var _httpClient = _httpClientFactory.CreateClient();
+            ClientDevice device = new ClientDevice { name =hostName, os= os };
+            HttpResponseMessage message = await _httpClient.PostAsJsonAsync("https://www.teammodel.cn/core/system-info", new { });
+            if (message.IsSuccessStatusCode)
+            {
+                JsonNode? json = JsonSerializer.Deserialize<JsonNode>(await message.Content.ReadAsStringAsync());
+                var ip = json?["ip"];
+                var region = json?["region"];
+                _logger.LogInformation($"远程地址:{ip}");
+                _logger.LogInformation($"所属地区:{region}");
+                device.remote=ip?.ToString();
+                device.region=region?.ToString();
+            }
+            _logger.LogInformation($"计算机名:{hostName}");
+            _logger.LogInformation($"系统名称:{RuntimeInformation.OSDescription}");
+            int CpuCoreCount = 0;
+            long MenemorySize = 0;
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                // 获取CPU核心数
+                //int processorCount = Environment.ProcessorCount;
+                //Console.WriteLine("CPU 核心数: " + processorCount);
+                using (ManagementClass managementClass = new ManagementClass("Win32_Processor"))
+                {
+                    using (ManagementObjectCollection managementObjectCollection = managementClass.GetInstances())
+                    {
+                        foreach (ManagementObject managementObject in managementObjectCollection)
+                        {
+                            CpuCoreCount += Convert.ToInt32(managementObject.Properties["NumberOfLogicalProcessors"].Value);
+                        }
+                    }
+                }
+                using (ManagementClass mc = new ManagementClass("Win32_ComputerSystem"))
+                {
+                    using (ManagementObjectCollection moc = mc.GetInstances())
+                    {
+                        foreach (ManagementObject mo in moc)
+                        {
+                            if (mo["TotalPhysicalMemory"]!= null)
+                            {
+                                MenemorySize = Convert.ToInt64(mo["TotalPhysicalMemory"]);
+                            }
+                        }
+                    }
+                }
+            }
+            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+            {
+                //int processorCount = Environment.ProcessorCount;
+                // Console.WriteLine("CPU 核心数: " + processorCount);
+                string[] cpu_lines = File.ReadAllLines("/proc/cpuinfo");
+                CpuCoreCount= cpu_lines.Count(line => line.StartsWith("processor", StringComparison.OrdinalIgnoreCase));
+                string[] mem_lines = File.ReadAllLines("/proc/meminfo");
+                var match = mem_lines.FirstOrDefault(line => line.StartsWith("MemTotal:"));
+                if (match != null)
+                {
+                    var matchResult = Regex.Match(match, @"\d+");
+                    if (matchResult.Success)
+                    {
+                        MenemorySize=  long.Parse(matchResult.Value);
+                    }
+                }
+            }
+            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+            {
+                using (var process = new Process())
+                {
+                    process.StartInfo.FileName = "/usr/sbin/sysctl";
+                    process.StartInfo.Arguments = "-n hw.ncpu";
+                    process.StartInfo.RedirectStandardOutput = true;
+                    process.StartInfo.UseShellExecute = false;
+                    process.Start();
+                    string output = process.StandardOutput.ReadToEnd().Trim();
+                    int coreCount;
+                    if (int.TryParse(output, out coreCount))
+                    {
+                        CpuCoreCount= coreCount;
+                    }
+                }
+                using (var process = new Process())
+                {
+                    process.StartInfo.FileName = "/usr/sbin/sysctl";
+                    process.StartInfo.Arguments = "-n hw.memsize";
+                    process.StartInfo.RedirectStandardOutput = true;
+                    process.StartInfo.UseShellExecute = false;
+                    process.Start();
+                    string output = process.StandardOutput.ReadToEnd().Trim();
+                    long memorySize;
+                    if (long.TryParse(output, out memorySize))
+                    {
+                        MenemorySize=  memorySize;
+                    }
+                }
+            }
+
+            //Console.WriteLine("CPU 核心数: " + CpuCoreCount+",RAM 大小:"+MenemorySize);
+            _logger.LogInformation($"内存大小:{MenemorySize}");
+            _logger.LogInformation($"核心数量:{CpuCoreCount}");
+            device.cpu=CpuCoreCount;
+            device.ram=MenemorySize;
+            var nics = NetworkInterface.GetAllNetworkInterfaces();
+            foreach (var nic in nics)
+            {
+                if (nic.OperationalStatus == OperationalStatus.Up)
+                {
+                    var name = $"{nic.Name}-{nic.Description}";
+                    var mac = nic.GetPhysicalAddress().ToString();
+                    var properties = nic.GetIPProperties();
+                    var unicastAddresses = properties.UnicastAddresses;
+                    foreach (var unicast in unicastAddresses)
+                    {
+                        if (unicast.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
+                        {
+                            var ip = unicast.Address.ToString();
+                            Network network = new Network() { mac=mac, ip=ip, name= name };
+                            if (!string.IsNullOrWhiteSpace(mac.ToString())  && !mac.Equals("000000000000"))
+                            {
+                                device.networks.Add(network);
+                                _logger.LogInformation($"网卡名称: {name}");
+                                _logger.LogInformation($"网卡地址: {mac}");
+                                _logger.LogInformation($"内网地址: {ip}");
+                            }
+                        }
+                    }
+                }
+            }
+            if (_url!.IsNotEmpty())
+            {
+                List<int> ports = new List<int>();
+                foreach (var url in _url)
+                {
+                    Uri uri = new Uri(url);
+                    ports.Add(uri.Port);
+                }
+                device.port= string.Join(",", ports);
+                _logger.LogInformation($"占用端口: {device.port}");
+            }
+            else {
+                throw new Exception("未获取到端口信息!");
+            }
+            string hashData = ShaHashHelper.GetSHA1($"{device.name}-{device.remote}-{device.port}-{device.os}-{string.Join(",", device.networks.Select(x => $"{x.mac}-{x.ip}"))}");
+            device.deviceId=hashData;
+            return device;
+        }
+    }
+}

+ 58 - 34
TEAMModelOS.SDK/Models/Service/GenPDFService.cs

@@ -26,6 +26,7 @@ using TEAMModelOS.SDK.Models.Service;
 using Azure.Core;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using System.Configuration;
+using Google.Protobuf.WellKnownTypes;
 
 namespace TEAMModelOS.SDK
 {
@@ -367,7 +368,7 @@ namespace TEAMModelOS.SDK
         /// <param name="azureRedis"></param>
         /// <param name="data"></param>
         /// <returns></returns>
-        public static async Task<(int total,int add )> AddGenPdfQueue( AzureRedisFactory azureRedis, GenPDFData data) 
+        public static async Task<(int total,int add )> AddGenPdfQueue( AzureRedisFactory azureRedis, GenPDFData data,ClientDevice device) 
         {
             long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             List<PDFGenRedis> genRedis = new List<PDFGenRedis>();
@@ -404,12 +405,12 @@ namespace TEAMModelOS.SDK
                 if (dbData!=null)
                 {
                     
-                    if (dbData.status==0|| dbData.status==1)
-                    {
-                        //不变的
-                        countProcess+=1;
-                    }
-                    else
+                    //if (dbData.status==0|| dbData.status==1)
+                    //{
+                    //    //不变的
+                    //    countProcess+=1;
+                    //}
+                    //else
                     {
                         //需要变更的
                         dbData.status = 0;
@@ -458,7 +459,7 @@ namespace TEAMModelOS.SDK
                 };
                 //string message = JsonSerializer.Serialize(genQueue);
                 //从头部压入元素,队列先进先出
-                await azureRedis.GetRedisClient(8).ListLeftPushAsync($"PDFGen:Queue",  genQueue.ToJsonString());
+                await azureRedis.GetRedisClient(8).ListLeftPushAsync($"PDFGen:Queue:{device.deviceId}",  genQueue.ToJsonString());
 
                 //var serviceBusMessage = new ServiceBusMessage(message);
                 //serviceBusMessage.ApplicationProperties.Add("name", "BlobRoot");
@@ -519,7 +520,8 @@ namespace TEAMModelOS.SDK
             return (null, null, null);
         }
 
-        public static async Task PushScreenTask(AzureRedisFactory _azureRedis, IConfiguration _configuration, string _artId, ArtEvaluation art, List<ArtStudentPdf> studentPdfs)
+        public static async Task PushScreenTask(AzureRedisFactory _azureRedis, IConfiguration _configuration, string _artId, 
+            ArtEvaluation art, List<ArtStudentPdf> studentPdfs,IHttpClientFactory _httpClient,DingDing dingDing)
         {
             string env = ScreenConstant.env_release;
             if (_configuration.GetValue<string>("Option:Location").Contains("Test", StringComparison.OrdinalIgnoreCase) ||
@@ -527,21 +529,37 @@ namespace TEAMModelOS.SDK
             {
                 env = ScreenConstant.env_develop;
             }
-            var addData = await GenPDFService.AddGenPdfQueue(_azureRedis,
-                 new GenPDFData
-                 {
-                     env =env,
-                     timeout=30000,
-                     delay=1000,
-                     checkPageCompleteJs=true,
-                     sessionId=$"{_artId}",
-                     taskName = art.name,
-                     taskType="Art",
-                     owner=art.owner,
-                     scope=art.scope,
-                     pageUrl="https://teammodeltest.blob.core.chinacloudapi.cn/0-public/bookjs/art/index.html",
-                     datas= studentPdfs.Select(x => new PDFData { id= x.studentId, name=x.studentName, url =x.blobFullUrl }).ToList()
-                 });
+            string ComplexAPI= _configuration.GetValue<string>("HTEX.Complex.API");
+            try {
+
+                var client=   _httpClient.CreateClient();
+                client.Timeout= new TimeSpan(0, 0, 30);
+                HttpResponseMessage message = await client.PostAsJsonAsync($"{ComplexAPI}/api/screen/push-task", new GenPDFData
+                {
+                    env =env,
+                    timeout=30000,
+                    delay=1000,
+                    checkPageCompleteJs=true,
+                    sessionId=$"{_artId}",
+                    taskName = art.name,
+                    taskType="Art",
+                    owner=art.owner,
+                    scope=art.scope,
+                    pageUrl="https://teammodeltest.blob.core.chinacloudapi.cn/0-public/bookjs/art/index.html",
+                    datas= studentPdfs.Select(x => new PDFData { id= x.studentId, name=x.studentName, url =x.blobFullUrl }).ToList()
+                });
+                if (message.IsSuccessStatusCode)
+                {
+
+                }
+                else {
+                    await dingDing.SendBotMsg($"艺术评测任务添加接口状态返回异常,状态:{message.StatusCode}", GroupNames.成都开发測試群組);
+                }
+            }
+            catch(Exception ex){
+                await dingDing.SendBotMsg($"艺术评测任务添加异常:{ex.Message},{ex.StackTrace}", GroupNames.成都开发測試群組);
+            }
+             
             //Console.WriteLine($"{addData.total},{addData.add}");
         }
     }
@@ -780,6 +798,18 @@ namespace TEAMModelOS.SDK
         /// 任务完成数
         /// </summary>
         public int taskComplete { get; set; }
+        /// <summary>
+        /// 超时时间,单位毫秒
+        /// </summary>
+        public long timeout { get; set; } = 30000;
+        /// <summary>
+        /// 延迟时间,单位毫秒
+        /// </summary>
+        public long delay { get; set; } = 3000;
+        /// <summary>
+        /// PDF服务地址
+        /// </summary>
+        public string? screenUrl { get; set; }
     }
 
     public class SignalRClient
@@ -796,6 +826,7 @@ namespace TEAMModelOS.SDK
         /// SignalR的连接ID 不建议暴露。
         /// </summary>
         public string? connid { get; set; }
+        public string? serverid { get; set;}
     }
     public interface IClient
     {
@@ -922,18 +953,11 @@ namespace TEAMModelOS.SDK
         /// 网卡 IP信息
         /// </summary>
         public List<Network> networks { get; set; } = new List<Network>();
+       
         /// <summary>
-        /// 超时时间,单位毫秒
-        /// </summary>
-        public long timeout { get; set; } = 30000;
-        /// <summary>
-        /// 延迟时间,单位毫秒
-        /// </summary>
-        public long delay { get; set; } = 3000;
-        /// <summary>
-        /// PDF服务地址
+        /// 设备id
         /// </summary>
-        public string? screenUrl { get; set; } 
+        public string? deviceId { get; set; }
     }
     public class Network
     {

+ 1 - 0
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -50,5 +50,6 @@
 		<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.22.0" />
 		<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Abstractions" Version="1.3.0" />
 		<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
+		<PackageReference Include="System.Management" Version="8.0.0" />
 	</ItemGroup>
 </Project>

+ 2 - 2
TEAMModelOS/Controllers/School/ArtReviewController.cs

@@ -152,8 +152,8 @@ namespace TEAMModelOS.Controllers
 
 
 #if !DEBUG
-        [AuthToken(Roles = "teacher,admin")]
-        [Authorize(Roles = "IES")]
+        //[AuthToken(Roles = "teacher,admin")]
+        //[Authorize(Roles = "IES")]
 #endif
         public async Task<IActionResult> GenPDF(JsonElement request)
         {

+ 8 - 8
TEAMModelOS/Controllers/System/GenPDFController.cs

@@ -58,18 +58,18 @@ namespace TEAMModelOS.Controllers
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("art-report")]
+      //  [ProducesDefaultResponseType]
+       // [HttpPost("art-report")]
 //#if !DEBUG
 //        [AuthToken(Roles = "teacher,admin")]
 //        [Authorize(Roles = "IES")]
 //#endif
-        public async Task<IActionResult> ArtReport (GenPDFData request) 
-        {
+       // public async Task<IActionResult> ArtReport (GenPDFData request) 
+        //{
             
-            var data = await GenPDFService.AddGenPdfQueue(  _azureRedis, request);
-            return Ok(new { total= data.total,add= data .add});
-        }
+            //var data = await GenPDFService.AddGenPdfQueue(  _azureRedis, request);
+            //return Ok(new { total= data.total,add= data .add});
+       // }
         /// <summary>
         /// 艺术评测报告生成
         /// </summary>
@@ -106,7 +106,7 @@ namespace TEAMModelOS.Controllers
                 head_lang = _option.Location.Contains("China") ? "zh-cn" : "en-us";
             }
             var data =   await GenPDFService.GenArtStudentPdf(_azureRedis, _azureCosmos, _coreAPIHttpService, _dingDing, _azureStorage, _configuration, studentIds, $"{_artId}", $"{_schoolId}", $"{head_lang}");
-            await GenPDFService.PushScreenTask(_azureRedis, _configuration, $"{_artId}", data.art, data.studentPdfs);
+            await GenPDFService.PushScreenTask(_azureRedis, _configuration, $"{_artId}", data.art, data.studentPdfs,_httpClient,_dingDing);
             return Ok();
         }