Browse Source

Update File packer

Zixuan 1 week ago
parent
commit
818a0f4271

+ 5 - 45
.gitignore

@@ -1,45 +1,5 @@
-/EEMSMain/obj
-/UICommon/bin
-/UICommon/obj
-/Module/Test/obj
-/Universal/bin
-/Universal/obj
-/.vs
-/Binary
-/Data/Device/bin/Debug/net8.0
-/Data/Device/obj
-/GlobalData/GlobalData/bin/Debug
-/GlobalData/GlobalData/obj
-/Module/ConfigFileManager/obj
-/Module/DeviceManagement/obj
-/Module/DeviceScanner/obj
-/Data/Config/bin/Debug/net8.0
-/Data/Config/obj
-/Data/GeneralData/bin/Debug/net8.0
-/Data/GeneralData/obj
-/Data_ViewModel/GlobalData/bin/Debug
-/Data_ViewModel/GlobalData/obj
-/Test/bin/Debug/net8.0
-/Test/obj
-/Analizer/KeplerAnalizer/obj
-/Analizer/ProximaAnalizer/obj
-/Data/GeneralData/bin/Release/net8.0
-/Data_ViewModel/GlobalData/bin/Release/net8.0-windows
-/Module/DashBoard/obj
-/DataBase/EntryFrameworkORM/obj
-/DataBase/ORM/bin
-/DataBase/ORM/obj
-/DataBase/SqlSugarORM/obj
-/Communicatror/KeplerCommunicator_DB/bin/Debug/net8.0
-/Communicatror/KeplerCommunicator_DB/obj
-/DataBase/EntryFrameworkORM/bin/Debug/net8.0
-/DataBase/SqlSugarORM/bin/Debug/net8.0
-/Data/DataService/bin/Debug/net8.0
-/Data/DataService/obj
-/DataBase/DB_Proxima/bin/Debug/net8.0
-/DataBase/DB_Proxima/obj
-/Tools/DBBackupTool/bin
-/Tools/DBBackupTool/obj
-/CAD2XMAL/bin/Debug/net8.0
-/CAD2XMAL/obj
-/EEMSCenter/obj
+.vs/
+Binary/
+packages/
+obj/
+bin/

+ 1 - 0
Directory.Packages.props

@@ -5,6 +5,7 @@
   <ItemGroup>
     <PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
     <PackageVersion Include="Mapster" Version="7.4.0" />
+    <PackageVersion Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.19" />
     <PackageVersion Include="Microsoft.AspNetCore.SignalR.Common" Version="8.0.19" />
     <PackageVersion Include="netDxf" Version="2023.11.10" />
     <PackageVersion Include="netDxf.netstandard" Version="3.0.1" />

+ 5 - 1
EEMSCenter/EEMSCenter.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
 	<PropertyGroup>
-		<OutputType>WinExe</OutputType>
+		<OutputType>Exe</OutputType>
 		<TargetFramework>net8.0-windows</TargetFramework>
 		<OutputPath>$(SolutionDir)Binary\Server</OutputPath>
 		<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
@@ -16,4 +16,8 @@
 	<ItemGroup>
 	  <PackageReference Include="Microsoft.AspNetCore.SignalR.Common" />
 	</ItemGroup>
+	<ItemGroup>
+	  <ProjectReference Include="..\Data\Device\Device.csproj" />
+	  <ProjectReference Include="..\Universal\Universal.csproj" />
+	</ItemGroup>
 </Project>

+ 6 - 0
EEMSCenter/EEMSCenter.csproj.user

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_LastSelectedProfileId>D:\Projects\EEMS\EEMSCenter\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
+  </PropertyGroup>
+</Project>

+ 107 - 0
EEMSCenter/HubSender/UISender.cs

@@ -0,0 +1,107 @@
+namespace EEMSCenter.HubSender;
+
+internal class UISender(ClientManager clientManager)
+{
+    private Task<bool> SendAsync(string name)
+    {
+        if (string.IsNullOrEmpty(name))
+            return Task.FromResult(false);
+
+        if (clientManager.UIClient is null)
+            return Task.FromResult(false);
+
+        try
+        {
+            clientManager.UIClient.SendAsync("test");
+        }
+        catch
+        {
+            return Task.FromResult(false);
+        }
+        return Task.FromResult(true);
+    }
+
+    private Task<bool> SendAsync<T>(string name, T para)
+    {
+        if (string.IsNullOrEmpty(name))
+            return Task.FromResult(false);
+
+        if (clientManager.UIClient is null)
+            return Task.FromResult(false);
+
+        try
+        {
+            clientManager.UIClient.SendAsync(name, para);
+        }
+        catch
+        {
+            return Task.FromResult(false);
+        }
+        return Task.FromResult(true);
+    }
+
+    private Task<bool> SendAsync<T1, T2>(string name, T1 para1, T2 para2)
+    {
+        if (string.IsNullOrEmpty(name))
+            return Task.FromResult(false);
+
+        if (clientManager.UIClient is null)
+            return Task.FromResult(false);
+
+        try
+        {
+            clientManager.UIClient.SendAsync(name, para1, para2);
+        }
+        catch
+        {
+            return Task.FromResult(false);
+        }
+        return Task.FromResult(true);
+    }
+
+    private Task<bool> SendAsync<T1, T2, T3>(string name, T1 para1, T2 para2, T3 para3)
+    {
+        if (string.IsNullOrEmpty(name))
+            return Task.FromResult(false);
+
+        if (clientManager.UIClient is null)
+            return Task.FromResult(false);
+
+        try
+        {
+            clientManager.UIClient.SendAsync(name, para1, para2, para3);
+        }
+        catch
+        {
+            return Task.FromResult(false);
+        }
+        return Task.FromResult(true);
+    }
+
+    private Task<bool> SendAsync<T1, T2, T3, T4>(string name, T1 para1, T2 para2, T3 para3, T4 para4)
+    {
+        if (string.IsNullOrEmpty(name))
+            return Task.FromResult(false);
+
+        if (clientManager.UIClient is null)
+            return Task.FromResult(false);
+
+        try
+        {
+            clientManager.UIClient.SendAsync(name, para1, para2, para3, para4);
+        }
+        catch
+        {
+            return Task.FromResult(false);
+        }
+        return Task.FromResult(true);
+    }
+
+    public async Task<bool> TestSend()
+    {
+        if (clientManager.UIClient is null)
+            return false;
+
+        return await this.SendAsync("Test");
+    }  
+}

+ 19 - 4
EEMSCenter/Hubs/ClientsHub.cs

@@ -1,7 +1,22 @@
-using Microsoft.AspNetCore.SignalR;
+namespace EEMSCenter.Hubs;
 
-namespace EEMSCenter.Hubs;
-
-internal class ClientsHub : Hub
+internal partial class ClientsHub(DeviceManager deviceManager, ClientManager clientManager) : HubBase
 {
+    public override Task OnDisconnectedAsync(Exception? exception)
+    {
+        deviceManager.RemoveDevice(Context.ConnectionId, out DeviceInfo? device);
+
+        if (device is not null && device.Guid.HasValue)
+            clientManager.DeviceClients.TryRemove(device.Guid.Value, out _);
+
+        return base.OnDisconnectedAsync(exception);
+    }
+
+    public Task<Guid> RegisterDevice(DeviceInfo deviceInfo)
+    {
+        deviceInfo.Guid ??= Guid.NewGuid();
+        deviceManager.LoginDevice(Context.ConnectionId, deviceInfo);
+        clientManager.DeviceClients[deviceInfo.Guid.Value] = Clients.Caller;
+        return Task.FromResult(deviceInfo.Guid.Value);
+    }
 }

+ 44 - 0
EEMSCenter/Hubs/FileHub.cs

@@ -0,0 +1,44 @@
+namespace EEMSCenter.Hubs;
+
+internal partial class ClientsHub : HubBase
+{
+    private static ConcurrentDictionary<Guid, MemoryStream> Streams { get; } = [];
+
+
+
+    public Task<bool> FilePack(Guid guid, byte[] buffer, int current, int total)
+    {
+        if (!Streams.TryGetValue(guid, out MemoryStream? stream) || stream is null)
+        {
+            if (current != 1)
+                return Task.FromResult(false);
+
+            stream = new();
+            Streams[guid] = stream;
+            Timer timer = new(FileCleanerTimerCallback, guid, 600000, Timeout.Infinite);
+        }
+
+        stream.Write(buffer);
+
+        if (current != total)
+            return Task.FromResult(true);
+
+        if (!Compressor.DecompressZipFile(Environment.CurrentDirectory, stream))
+            return Task.FromResult(false);
+
+        if (Streams.TryRemove(guid, out MemoryStream? memoryStream) && memoryStream is not null)
+            memoryStream.Dispose();
+
+
+        return Task.FromResult(true);
+    }
+
+    private void FileCleanerTimerCallback(object? state)
+    {
+        if (state is not Guid guid)
+            return;
+
+        if (Streams.TryRemove(guid, out MemoryStream? memoryStream) && memoryStream is not null)
+            memoryStream.Dispose();
+    }
+}

+ 8 - 0
EEMSCenter/Hubs/HubBase.cs

@@ -0,0 +1,8 @@
+namespace EEMSCenter.Hubs;
+
+internal class HubBase : Hub
+{
+
+
+
+}

+ 8 - 10
EEMSCenter/Hubs/UIHub.cs

@@ -1,12 +1,10 @@
-using Microsoft.AspNetCore.SignalR;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+namespace EEMSCenter.Hubs;
 
-namespace EEMSCenter.Hubs;
-
-internal class UIHub : Hub
+internal class UIHub(ClientManager clientManager) : HubBase
 {
-}
+    public override Task OnConnectedAsync()
+    {
+        clientManager.UIClient = Clients.All;
+        return base.OnConnectedAsync();
+    }
+}

+ 7 - 0
EEMSCenter/Managers/ClientManager.cs

@@ -0,0 +1,7 @@
+namespace EEMSCenter.Managers;
+
+internal class ClientManager
+{
+    public IClientProxy? UIClient;
+    public readonly ConcurrentDictionary<Guid, ISingleClientProxy> DeviceClients = [];
+}

+ 40 - 0
EEMSCenter/Managers/DeviceManager.cs

@@ -0,0 +1,40 @@
+namespace EEMSCenter.Managers;
+
+internal class DeviceManager
+{
+    private readonly ConcurrentDictionary<string, DeviceInfo> DevicesFromConnectionID = [];
+    private readonly ConcurrentDictionary<Guid, DeviceInfo> DevicesFromGuid = [];
+
+    public bool LoginDevice(string connectionID, DeviceInfo deviceInfo)
+    {
+        if (!deviceInfo.Guid.HasValue)
+            return false;
+        DevicesFromGuid[deviceInfo.Guid.Value] = deviceInfo;
+        DevicesFromConnectionID[connectionID] = deviceInfo;
+        return true;
+    }
+
+    public void RemoveDevice(string connectionID, out DeviceInfo? device)
+    {
+        DevicesFromConnectionID.TryRemove(connectionID, out device);
+        if (device is null || !device.Guid.HasValue)
+            return;
+        DevicesFromGuid.TryRemove(device.Guid.Value, out _);
+
+    }
+
+    public bool TryGetDevice(string connectionID, out DeviceInfo? device)
+    {
+        device = default;
+        if (string.IsNullOrEmpty(connectionID))
+            return false;
+
+        return DevicesFromConnectionID.TryGetValue(connectionID, out device);
+    }
+
+    public bool TryGetDevice(Guid guid, out DeviceInfo? device)
+    {
+        return DevicesFromGuid.TryGetValue(guid, out device);
+    }
+
+}

+ 13 - 1
EEMSCenter/Program.cs

@@ -1,4 +1,5 @@
 using EEMSCenter.Hubs;
+using EEMSCenter.HubSender;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.Extensions.DependencyInjection;
 using System.Windows;
@@ -31,13 +32,24 @@ internal class Program
 
         //Host Service
         builder.Services.AddHostedService<HostLifetime>();
+        builder.Services.AddSingleton<DeviceManager>();
+        builder.Services.AddSingleton<ClientManager>();
+
+        builder.Services.AddSingleton<UISender>();
 
         WebApplication = builder.Build();
         WebApplication.MapHub<UIHub>("/UIHub");
         WebApplication.MapHub<ClientsHub>("/ClientHub");
-        WebApplication.RunAsync($"http://127.0.0.1:50054").Wait();
+
+
+        string? address = NetworkAddressHelper.GetAllIPAddressStr().Where(t => t.StartsWith("10.")).FirstOrDefault()?.ToString();
+        address ??= "127.0.0.1";
+
+        WebApplication.RunAsync($"http://{address}:50054").Wait();
     }
 
+
+
     private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
     {
         string? s = e.ExceptionObject?.ToString();

+ 11 - 0
EEMSCenter/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>E:\TestServer</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+  </PropertyGroup>
+</Project>

+ 8 - 0
EEMSCenter/Properties/PublishProfiles/FolderProfile.pubxml.user

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
+<Project>
+  <PropertyGroup>
+    <History>True|2025-09-01T05:47:14.3768845Z||;True|2025-09-01T13:46:18.1542477+08:00||;True|2025-09-01T13:43:54.7660119+08:00||;</History>
+    <LastFailureDetails />
+  </PropertyGroup>
+</Project>

+ 6 - 0
EEMSCenter/Properties/_global.cs

@@ -0,0 +1,6 @@
+global using Microsoft.AspNetCore.SignalR;
+global using System.Collections.Concurrent;
+global using System.IO;
+global using Universal;
+global using Device;
+global using EEMSCenter.Managers;

+ 6 - 0
EEMSMain.sln

@@ -68,6 +68,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CAD2XMAL", "CAD2XMAL\CAD2XM
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EEMSCenter", "EEMSCenter\EEMSCenter.csproj", "{9C18B022-F837-4736-B298-480AC29F8362}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestSignalRClient", "TestSignalRClient\TestSignalRClient.csproj", "{969746CD-C070-4F36-B6ED-9ADB9606E15E}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -166,6 +168,10 @@ Global
 		{9C18B022-F837-4736-B298-480AC29F8362}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{9C18B022-F837-4736-B298-480AC29F8362}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{9C18B022-F837-4736-B298-480AC29F8362}.Release|Any CPU.Build.0 = Release|Any CPU
+		{969746CD-C070-4F36-B6ED-9ADB9606E15E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{969746CD-C070-4F36-B6ED-9ADB9606E15E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{969746CD-C070-4F36-B6ED-9ADB9606E15E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{969746CD-C070-4F36-B6ED-9ADB9606E15E}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 67 - 0
TestSignalRClient/HubSender.cs

@@ -0,0 +1,67 @@
+using Microsoft.AspNetCore.SignalR.Client;
+using System.Threading.Channels;
+using System.Threading.Tasks;
+using Universal;
+
+namespace TestSignalRClient;
+
+internal class HubSender : SenderBase
+{
+    public bool Initialize(string ip, int port, string hub, int retry = 40)
+    {
+        if (_hubConnection is not null)
+            return false;
+
+        HubConnection temp = new HubConnectionBuilder()
+            .WithUrl($"http://{ip}:{port}/{hub}")
+            .WithAutomaticReconnect()
+            .Build();
+
+        //temp.On<byte, Mini8Data>("UpdateMini8", UpdateMini8);
+        //temp.On<byte, byte, ChannelData>("UpdateSingleChannel", receiver.UpdateSingleChannel);
+        //temp.On<byte, List<ChannelData>>("UpdateChannel", receiver.UpdateChannels);
+        //temp.On<TemperatureConfig>("UpdateFiles", receiver.UpdateFiles);
+        //temp.On("ClearFiles", receiver.ClearFiles);
+        //temp.On<byte, Mini8Address>("UpdateAddress", receiver.UpdateAddress);
+        //temp.On<TemperatureConfig>("CurrentFile", receiver.CurrentFile);
+        //temp.On<byte, byte, float>("AlarmNotify", receiver.AlarmNotify);
+        //temp.On<byte, byte>("AlarmTcBrockenNotify", receiver.AlarmTcBrockenNotify);
+        //temp.On<byte, bool>("Mini8Connect", receiver.Mini8Connect);
+        //temp.On<int, DateTime>("UpdateDataBaseInfo", receiver.UpdateDataBaseInfo);
+        //temp.On<byte, byte, ChannelData>("ChannelDataUpdate", receiver.ChannelDataUpdate);
+
+        //temp.ServerTimeout = TimeSpan.FromSeconds(5.0);
+
+
+        for (int i = 1; i <= retry; i++)
+        {
+            try
+            {
+                temp.StartAsync().Wait();
+                _hubConnection = temp;
+                break;
+            }
+            catch
+            {
+                if (i == retry)
+                    return false;
+                Thread.Sleep(1000);
+            }
+        }
+
+        return true;
+    }
+
+    public async Task<bool> SendFile(Guid guid, MemoryStream stream)
+    {
+        if (!stream.Split(out List<byte[]>? buffer, 8192) || buffer is null)
+            return false;
+
+        for (int i = 0; i < buffer.Count; i++)
+        {
+            if (!await base.Send<Guid, byte[], int, int>("FilePack", guid, buffer[i], i + 1, buffer.Count))
+                return false;
+        }  
+        return true;
+    }
+}

+ 17 - 0
TestSignalRClient/Program.cs

@@ -0,0 +1,17 @@
+using Universal;
+
+namespace TestSignalRClient;
+
+internal class Program
+{
+    static void Main(string[] args)
+    {
+        HubSender hubSender = new();
+        hubSender.Initialize("10.4.6.87", 50054, "FileHub");
+        using MemoryStream stream = new();
+        Compressor.CompressZipFileDirectory(new(@"E:\Recipes"), stream);
+
+        //await hubSender.SendFile(Guid.NewGuid(),stream);
+        Thread.Sleep(-1);
+    }
+}

+ 214 - 0
TestSignalRClient/SenderBase.cs

@@ -0,0 +1,214 @@
+using Microsoft.AspNetCore.SignalR.Client;
+using System.Diagnostics;
+
+namespace TestSignalRClient;
+
+public class SenderBase : IDisposable
+{
+    protected HubConnection? _hubConnection;
+    private bool CheckConnect()
+    {
+        if (_hubConnection is null)
+            return false;
+        if (_hubConnection.State != HubConnectionState.Connected)
+            return false;
+
+        return true;
+    }
+
+    //protected static bool StartConsole()
+    //{
+    //    Mutex mutex = new(false, "7E862400-8020-BE75-5266-B2C4BEB54076", out bool flag);
+
+    //    if (!flag)
+    //    {
+    //        mutex.Dispose();
+    //        return true;
+    //    }
+
+    //    try
+    //    {
+    //        Process p = new();
+    //        p.StartInfo.FileName = FilePaths.ConsoleExe;
+    //        p.StartInfo.UseShellExecute = false;
+    //        p.StartInfo.RedirectStandardInput = true;
+    //        p.Start();
+    //    }
+    //    catch
+    //    {
+    //        mutex.Dispose();
+    //        return false;
+    //    }
+
+    //    mutex.Dispose();
+    //    return true;
+    //}
+
+    public void Dispose()
+    {
+        _hubConnection?.StopAsync();
+        _hubConnection = null;
+    }
+
+    protected async Task<bool> Send(string name)
+    {
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            await _hubConnection!.SendAsync(name);
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected async Task<bool> Send<T1>(string name, T1 para1)
+    {
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            await _hubConnection!.SendAsync(name, para1);
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected async Task<bool> Send<T1, T2>(string name, T1 para1, T2 para2)
+    {
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            await _hubConnection!.SendAsync(name, para1, para2);
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+
+
+    protected async Task<bool> Send<T1, T2, T3>(string name, T1 para1, T2 para2, T3 para3)
+    {
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            await _hubConnection!.SendAsync(name, para1, para2, para3);
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected async Task<bool> Send<T1, T2, T3, T4>(string name, T1 para1, T2 para2, T3 para3, T4 para4)
+    {
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            await _hubConnection!.SendAsync(name, para1, para2, para3, para4);
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected bool Invoke<T_Return>(string name, out T_Return? returnValue)
+    {
+        returnValue = default;
+
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            returnValue = _hubConnection!.InvokeAsync<T_Return>(name).Result;
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected bool Invoke<T_Return, T_para1>(string name, T_para1 para1, out T_Return? returnValue)
+    {
+        returnValue = default;
+
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            returnValue = _hubConnection!.InvokeAsync<T_Return>(name, para1).Result;
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+    protected bool Invoke<T_Return, T_para1, T_Para2>(string name, T_para1 para1, T_Para2 para2, out T_Return? returnValue)
+    {
+        returnValue = default;
+
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            returnValue = _hubConnection!.InvokeAsync<T_Return>(name, para1, para2).Result;
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    protected bool Invoke<T_Return, T_para1, T_Para2, T_Para3>(string name, T_para1 para1, T_Para2 para2, T_Para3 para3, out T_Return? returnValue)
+    {
+        returnValue = default;
+
+        if (!CheckConnect())
+            return false;
+
+        try
+        {
+            returnValue = _hubConnection!.InvokeAsync<T_Return>(name, para1, para2, para3).Result;
+        }
+        catch
+        {
+            return false;
+        }
+
+        return true;
+    }
+}

+ 18 - 0
TestSignalRClient/TestSignalRClient.csproj

@@ -0,0 +1,18 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\Universal\Universal.csproj" />
+  </ItemGroup>
+
+</Project>

+ 22 - 1
Universal/Compressor.cs

@@ -36,7 +36,7 @@ public class Compressor
     {
         if (!sourceDirectory.Exists)
             return false;
-        
+
         try
         {
             ZipFile.CreateFromDirectory(sourceDirectory.FullName, stream, CompressionLevel.SmallestSize, false);
@@ -48,4 +48,25 @@ public class Compressor
 
         return true;
     }
+
+    public static bool DecompressZipFile(string path, Stream stream)
+    {
+
+        try
+        {
+            DirectoryInfo directory = new(path);
+            if (!directory.Exists)
+                directory.Create();
+
+            ZipFile.ExtractToDirectory(stream, path, true);
+
+        }
+        catch
+        {
+
+            return false;
+        }
+
+        return true;
+    }
 }

+ 27 - 0
Universal/Extensions.cs

@@ -100,6 +100,33 @@ public static class Extensions
         return Encoding.ASCII.GetString(bytes);
     }
 
+
+    public static bool Split(this MemoryStream input, out List<byte[]>? output, int packLength = 4096)
+    {
+        output = default;
+
+        if (packLength < 1)
+            return false;
+
+        Span<byte> t = input.ToArray();
+        int count = t.Length / packLength;
+
+        Span<byte> ts;
+        output = [];
+        for (int i = 0; i <= count; i++)
+        {
+            if (i == count)
+            {
+                ts = t.Slice(i * packLength);
+                output.Add(ts.ToArray());
+                break;
+            }
+            ts = t.Slice(i * packLength, packLength);
+            output.Add(ts.ToArray());
+        }
+
+        return true;
+    }
 }
 #endif
 

+ 64 - 0
Universal/NetworkAddressHelper.cs

@@ -0,0 +1,64 @@
+using System.Net;
+using System.Net.NetworkInformation;
+
+namespace Universal;
+
+public class NetworkAddressHelper
+{
+    public static List<IPAddress> GetAllIPAddress()
+    {
+        List<IPAddress> ipAddresses = [];
+
+        foreach (var item in GetNetworkAdapterNames())
+            ipAddresses.AddRange(GetIPAddressByAdapterName(item));
+
+        return ipAddresses;
+    }
+    public static List<string> GetAllIPAddressStr()
+    {
+        List<string> ipAddresses = [];
+
+        foreach (var item in GetNetworkAdapterNames())
+            GetIPAddressByAdapterName(item).Foreach(t => ipAddresses.Add(t.ToString()));
+
+
+        return ipAddresses;
+    }
+
+
+    public static List<string> GetNetworkAdapterNames()
+    {
+        List<string> adapterNames = [];
+        NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
+
+        foreach (NetworkInterface networkInterface in networkInterfaces)
+        {
+            adapterNames.Add(networkInterface.Name);
+        }
+
+        return adapterNames;
+    }
+    public static List<IPAddress> GetIPAddressByAdapterName(string adapterName)
+    {
+        List<IPAddress> ipAddresses = [];
+        NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
+
+        foreach (NetworkInterface networkInterface in networkInterfaces)
+        {
+            if (networkInterface.Name.Equals(adapterName, StringComparison.OrdinalIgnoreCase))
+            {
+                IPInterfaceProperties properties = networkInterface.GetIPProperties();
+                foreach (UnicastIPAddressInformation ipAddressInfo in properties.UnicastAddresses)
+                {
+                    if (ipAddressInfo.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
+                    {
+                        ipAddresses.Add(ipAddressInfo.Address);
+                    }
+                }
+                break;
+            }
+        }
+
+        return ipAddresses;
+    }
+}