Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Pull Request] Refactored network related parts. #19

Merged
merged 16 commits into from
Apr 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
a6dd859
💾 Feat(Interfaces): Init basic interfaces for network and module cont…
Dynesshely Apr 20, 2023
12f2404
💾 Feat(TasksManager): Added `RunTask` and `RunTaskAsync` methods to e…
Dynesshely Apr 20, 2023
2bfdea2
🧩 Refactor(DevicesNetwork): Move UDP parts to `DevicesDiscoveryServer…
Dynesshely Apr 20, 2023
4b36f0a
🔧 Fix: Udp part of `DevicesNetwork` moved to new class.
Dynesshely Apr 20, 2023
981807d
💾 Feat(DevicesDiscoveryServer): Added status support.
Dynesshely Apr 20, 2023
d249c62
🧩 Refactor(Network): Better `WebManager` usage.
Dynesshely Apr 20, 2023
ad1790b
💾 Feat(Interfaces): Require `OnReceive` function.
Dynesshely Apr 22, 2023
a0df74d
💾 Feat(Interfaces): `IKitXClient` requires `Send` and `OnReceive` fun…
Dynesshely Apr 22, 2023
88e3077
🧩 📦 Refactor, Struct: Rename `Server` folder to `Network` folder.
Dynesshely Apr 22, 2023
6586add
💾 Feat(Network): Init `DevicesClient.cs` file.
Dynesshely Apr 22, 2023
648dce2
💾 Feat(Interfaces.Network): `OnReceive` callback supports length, and…
Dynesshely Apr 22, 2023
1580bd7
🧩 Refactor(Network): Adapt to updated interfaces.
Dynesshely Apr 22, 2023
5dc99b9
🧩 Refactor(Network): Made `PluginsServer` adapted to new interface.
Dynesshely Apr 22, 2023
f3f4bfb
📄 Docs(Network): Docs for enums in `Status.cs`.
Dynesshely Apr 22, 2023
a68ecee
🧩 Refactor(Network): Depart client part in devices network to `Device…
Dynesshely Apr 23, 2023
48d906f
💾 Feat: Updated call site.
Dynesshely Apr 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ public static void StartUpCheck()

Program.TasksManager.SignalRun(nameof(SignalsNames.MainWindowInitSignal), () =>
{
new Thread(() =>
new Thread(async () =>
{
Thread.Sleep(Program.Config.Web.DelayStartSeconds * 1000);
Program.WebManager = new WebManager().Start();
Program.WebManager = await new WebManager().Start();
}).Start();
});

Expand Down
13 changes: 13 additions & 0 deletions Interfaces/IModuleController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Threading.Tasks;

namespace KitX_Dashboard.Interfaces;

internal interface IModuleController<T> : IDisposable
{
Task<T> Start();

Task<T> Stop();

Task<T> Restart();
}
15 changes: 15 additions & 0 deletions Interfaces/Network/IKitXClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Threading.Tasks;

namespace KitX_Dashboard.Interfaces.Network;

internal interface IKitXClient<T> : IModuleController<T>
{
Task<T> Connect();

Task<T> Disconnect();

Task<T> Send(byte[] content);

T OnReceive(Action<byte[], int?> action);
}
16 changes: 16 additions & 0 deletions Interfaces/Network/IKitXServer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace KitX_Dashboard.Interfaces.Network;

internal interface IKitXServer<T> : IModuleController<T>
{
Task<T> Broadcast(byte[] content);

Task<T> BroadCast(byte[] content, Func<TcpClient, bool>? pattern);

Task<T> Send(byte[] content, string target);

T OnReceive(Action<byte[], int?, string> action);
}
127 changes: 72 additions & 55 deletions Managers/DevicesManager.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Avalonia.Threading;
using KitX.Web.Rules;
using KitX_Dashboard.Data;
using KitX_Dashboard.Servers;
using KitX_Dashboard.Network;
using KitX_Dashboard.Services;
using KitX_Dashboard.Views.Pages.Controls;
using Serilog;
Expand All @@ -16,19 +16,23 @@ internal class DevicesManager
{
internal static void InitEvents()
{
EventService.OnReceivingDeviceInfoStruct4DeviceNet += dis =>
EventService.OnReceivingDeviceInfoStruct += dis =>
{
if (GlobalInfo.IsMainMachine)
if (dis.DeviceServerBuildTime < GlobalInfo.ServerBuildTime)
{
Program.WebManager?.devicesServer?.CancleBuildServer();
Log.Information($"In DevicesManager: Watched for earlier built server. " +
$"DeviceServerAddress: {dis.IPv4}:{dis.DeviceServerPort} " +
$"DeviceServerBuildTime: {dis.DeviceServerBuildTime}");
}
if (dis.IsMainDevice && dis.DeviceServerBuildTime < GlobalInfo.ServerBuildTime)
{
Program.WebManager?.devicesServer?.Stop();

Watch4MainDevice();

Log.Information($"In DevicesManager: Watched earlier built server. " +
$"DeviceServerAddress: {dis.IPv4}:{dis.DeviceServerPort} " +
$"DeviceServerBuildTime: {dis.DeviceServerBuildTime}");
}
};
}

private static readonly object _receivedDeviceInfoStruct4WatchLock = new();

internal static List<DeviceInfoStruct>? receivedDeviceInfoStruct4Watch;

internal static readonly Queue<DeviceInfoStruct> deviceInfoStructs = new();
Expand All @@ -53,7 +57,7 @@ private static bool CheckDeviceIsOffline(DeviceInfoStruct info)
/// <returns>是否是本机卡片</returns>
private static bool CheckIsCurrentMachine(DeviceInfoStruct info)
{
var self = DevicesServer.DefaultDeviceInfoStruct;
var self = DevicesDiscoveryServer.DefaultDeviceInfoStruct;
return info.DeviceMacAddress.Equals(self.DeviceMacAddress)
&& info.DeviceName.Equals(self.DeviceName);
}
Expand Down Expand Up @@ -266,98 +270,111 @@ internal static void KeepCheckAndRemove()
internal static void Update(DeviceInfoStruct deviceInfo)
{
deviceInfoStructs.Enqueue(deviceInfo);
receivedDeviceInfoStruct4Watch?.Add(deviceInfo);

if (deviceInfo.IsMainDevice)
EventService.Invoke(nameof(EventService.OnReceivingDeviceInfoStruct4DeviceNet),
deviceInfo);
if (receivedDeviceInfoStruct4Watch is not null)
{
lock (_receivedDeviceInfoStruct4WatchLock)
{
receivedDeviceInfoStruct4Watch.Add(deviceInfo);
}
}

EventService.Invoke(nameof(EventService.OnReceivingDeviceInfoStruct), deviceInfo);
}

/// <summary>
/// 观察主控
/// </summary>
internal static void Watch4MainDevice()
{
var location = $"{nameof(DevicesManager)}.{nameof(Watch4MainDevice)}";

new Thread(() =>
{
try
{
receivedDeviceInfoStruct4Watch = new();
receivedDeviceInfoStruct4Watch = new();

var checkedTime = 0;
var hadMainDevice = false;
var earliestBuiltServerTime = DateTime.UtcNow;
var serverPort = 0;
var serverAddress = string.Empty;
var checkedTime = 0;
var hadMainDevice = false;
var earliestBuiltServerTime = DateTime.UtcNow;
var serverPort = 0;
var serverAddress = string.Empty;

while (checkedTime < 7)
while (checkedTime < 7)
{
try
{
try
{
if (receivedDeviceInfoStruct4Watch is null) continue;
if (receivedDeviceInfoStruct4Watch is null) continue;

lock (_receivedDeviceInfoStruct4WatchLock)
{
foreach (var item in receivedDeviceInfoStruct4Watch)
{
if (item.IsMainDevice)
{
if (item.DeviceServerBuildTime.ToUniversalTime()
< earliestBuiltServerTime)
if (item.DeviceServerBuildTime.ToUniversalTime() < earliestBuiltServerTime)
{
serverPort = item.DeviceServerPort;
serverAddress = item.IPv4;
}
hadMainDevice = true;
}
}
}

++checkedTime;

Log.Information($"In Watch4MainDevice: " +
$"Watched for {checkedTime} times.");
++checkedTime;

if (checkedTime == 7)
{
receivedDeviceInfoStruct4Watch?.Clear();
receivedDeviceInfoStruct4Watch = null;
WatchingOver(hadMainDevice, serverAddress, serverPort);
}
Log.Information($"In {location}: Watched for {checkedTime} times.");

Thread.Sleep(1 * 1000); // Sleep 1 second.
}
catch (Exception e)
if (checkedTime == 7)
{
receivedDeviceInfoStruct4Watch?.Clear();
receivedDeviceInfoStruct4Watch = null;

Log.Error(e, "In Watch4MainDevice");
WatchingOver(hadMainDevice, serverAddress, serverPort);
}

Thread.Sleep(1 * 1000); // Sleep 1 second.
}
}
catch (Exception ex)
{
receivedDeviceInfoStruct4Watch?.Clear();
receivedDeviceInfoStruct4Watch = null;
catch (Exception e)
{
receivedDeviceInfoStruct4Watch?.Clear();
receivedDeviceInfoStruct4Watch = null;

Log.Error(e, $"In {location}: {e.Message} Rewatch.");

Log.Error(ex, "In Watch4MainDevice");
Watch4MainDevice();
}
}
}).Start();
}

/// <summary>
/// 观察结束
/// </summary>
internal static void WatchingOver(bool hadMainDevice, string serverAddress, int serverPort)
internal static async void WatchingOver(bool foundMainDevice, string serverAddress, int serverPort)
{
Log.Information($"In WatchingOver: hadMainDevice: {hadMainDevice}, " +
$"serverAddress: {serverAddress}, serverPort: {serverPort}");
var location = $"{nameof(DevicesManager)}.{nameof(WatchingOver)}";

Log.Information($"In {location}: " +
$"{nameof(foundMainDevice)} -> {foundMainDevice}, " +
$"{nameof(serverAddress)} -> {serverAddress}, " +
$"{nameof(serverPort)} -> {serverPort}");

if (hadMainDevice)
if (foundMainDevice)
{
Program.WebManager?.devicesServer?.AttendServer(serverAddress, serverPort);
var client = Program.WebManager?.devicesClient;

if (client is null) return;

await client
.SetServerAddress(serverAddress)
.SetServerPort(serverPort)
.Start()
;
}
else
{
Program.WebManager?.devicesServer?.BuildServer();
Program.WebManager?.devicesServer?.Start();
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions Managers/TasksManager.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Common.BasicHelper.Utils.Extensions;
using Serilog;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace KitX_Dashboard.Managers;

Expand Down Expand Up @@ -33,4 +35,40 @@ internal void SignalRun(string signal, Action action)
SignalTasks[signal].Enqueue(action);
else SignalTasks.Add(signal, new Queue<Action>().Push(action));
}

/// <summary>
/// 执行任务, 并带有更好的日志显示
/// </summary>
/// <param name="action">要执行的动作</param>
/// <param name="name">日志显示名称</param>
/// <param name="prompt">日志提示</param>
public static void RunTask(
Action action,
string name = nameof(Action),
string prompt = ">>> ")
{
Log.Information($"{prompt}Task `{name}` began.");

action();

Log.Information($"{prompt}Task `{name}` done.");
}

/// <summary>
/// 异步执行任务, 并带有更好的日志显示
/// </summary>
/// <param name="action">要执行的动作</param>
/// <param name="name">任务名称</param>
/// <param name="prompt">日志提示</param>
public static async Task RunTaskAsync(
Action action,
string name = nameof(Action),
string prompt = ">>> ")
{
Log.Information($"{prompt}Task `{name}` began.");

await Task.Run(action);

Log.Information($"{prompt}Task `{name}` done.");
}
}
Loading