Skip to content

Commit c4c3619

Browse files
author
panwenbo
committed
One.Toolbox
新增网速测试功能;
1 parent b199c15 commit c4c3619

File tree

15 files changed

+569
-26
lines changed

15 files changed

+569
-26
lines changed

One.Toolbox/App.xaml.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using One.Toolbox.Messenger;
99
using One.Toolbox.ViewModels;
1010
using One.Toolbox.ViewModels.DataProcess;
11+
using One.Toolbox.ViewModels.NetSpeed;
1112
using One.Toolbox.ViewModels.Stick;
1213

1314
using System.Globalization;
@@ -82,6 +83,7 @@ private static IServiceProvider ConfigureServices()
8283

8384
services.AddSingleton<StickPageVM>();
8485
services.AddSingleton<TestPageVM>();
86+
services.AddSingleton<NetSpeedPageVM>();
8587

8688
//多例
8789
//services.AddTransient<StickItemVM>();

One.Toolbox/One.Toolbox.csproj

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,23 @@
3333

3434
<ItemGroup>
3535
<PackageReference Include="AvalonEdit" Version="6.3.0.90" />
36-
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
36+
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
3737
<PackageReference Include="HandyControl" Version="3.4.0" />
38-
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="5.0.2" />
39-
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="5.0.2" />
40-
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
38+
<PackageReference Include="LiveChartsCore.SkiaSharpView.WPF" Version="2.0.0-rc2" />
39+
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="5.0.3" />
40+
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="5.0.3" />
41+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
4142
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.49-beta">
4243
<PrivateAssets>all</PrivateAssets>
4344
</PackageReference>
4445
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
45-
<PackageReference Include="NLog" Version="5.2.4" />
46+
<PackageReference Include="NLog" Version="5.2.8" />
4647

4748
<PackageReference Include="RestSharp" Version="110.2.0" />
48-
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
49-
<PackageReference Include="System.Management" Version="7.0.2" />
50-
<PackageReference Include="Vanara.PInvoke.Security" Version="3.4.16" />
51-
<PackageReference Include="Vanara.PInvoke.SetupAPI" Version="3.4.16" />
49+
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
50+
<PackageReference Include="System.Management" Version="8.0.0" />
51+
<PackageReference Include="Vanara.PInvoke.Security" Version="3.4.17" />
52+
<PackageReference Include="Vanara.PInvoke.SetupAPI" Version="3.4.17" />
5253
<PackageReference Include="WebDav.Client" Version="2.8.0" />
5354
</ItemGroup>
5455

@@ -63,6 +64,9 @@
6364
<AutoGen>True</AutoGen>
6465
<DependentUpon>Settings.settings</DependentUpon>
6566
</Compile>
67+
<Compile Update="Views\NetSpeed\NetSpeedPage.xaml.cs">
68+
<SubType>Code</SubType>
69+
</Compile>
6670
<Compile Update="Views\TestPage.xaml.cs">
6771
<SubType>Code</SubType>
6872
</Compile>

One.Toolbox/Resources/Themes/Basic/Geometries.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@
3434
<Geometry x:Key="FontIncrease24Regular" o:Freeze="True">M15.195 5.754a.75.75 0 0 0 1.06.05l2.245-2.04l2.245 2.04a.75.75 0 0 0 1.01-1.109l-2.75-2.5a.75.75 0 0 0-1.01 0l-2.75 2.5a.75.75 0 0 0-.05 1.06zM12 4a.75.75 0 0 1 .697.473l5.75 14.5a.75.75 0 0 1-1.394.553L15.258 15H8.742l-1.795 4.526a.75.75 0 1 1-1.394-.553l5.75-14.5A.75.75 0 0 1 12 4zm-2.663 9.5h5.326L12 6.785L9.337 13.5z</Geometry>
3535
<Geometry x:Key="FontDecrease24Regular" o:Freeze="True">M16.255 2.195a.75.75 0 0 0-1.01 1.11l2.75 2.5a.75.75 0 0 0 1.01 0l2.75-2.5a.75.75 0 1 0-1.01-1.11L18.5 4.236l-2.245-2.04zM12 4a.75.75 0 0 1 .697.474l5.75 14.5a.75.75 0 0 1-1.394.552L15.258 15H8.742l-1.795 4.526a.75.75 0 1 1-1.394-.553l5.75-14.5A.75.75 0 0 1 12 4zm0 2.785L9.337 13.5h5.326L12 6.785z</Geometry>
3636

37-
37+
<Geometry x:Key="TopSpeed20Regular" o:Freeze="True">M5.416 4.71A6.97 6.97 0 0 1 9.5 3.017V4.5a.5.5 0 0 0 1 0V3.018A7.003 7.003 0 0 1 16.93 9H15a.5.5 0 0 0 0 1h2a7.171 7.171 0 0 1-2.211 5.17a.5.5 0 0 0 .686.727A8.17 8.17 0 0 0 18 10a8 8 0 1 0-16 0c0 2.295 1.02 4.44 2.563 5.897a.5.5 0 0 0 .686-.728C3.895 13.89 3 12.003 3 10h2a.5.5 0 1 0 0-1H3.07a6.972 6.972 0 0 1 1.64-3.583l1.436 1.437a.5.5 0 0 0 .708-.708L5.416 4.71zm8.033 1.097a.5.5 0 0 1 .746.638l-.11.196a343.946 343.946 0 0 1-1.214 2.126a123.6 123.6 0 0 1-.99 1.69c-.145.243-.277.459-.384.628c-.1.157-.198.306-.27.39a1.5 1.5 0 0 1-2.282-1.948c.072-.084.203-.205.343-.328c.15-.133.343-.296.56-.479c.436-.364.982-.81 1.514-1.24a295.19 295.19 0 0 1 1.91-1.532l.177-.14z</Geometry>
3838
<Geometry x:Key="Note24Regular" o:Freeze="True">M17.75 3A3.25 3.25 0 0 1 21 6.25v6.879a2.25 2.25 0 0 1-.659 1.59l-5.621 5.622a2.25 2.25 0 0 1-1.591.659H6.25A3.25 3.25 0 0 1 3 17.75V6.25A3.25 3.25 0 0 1 6.25 3h11.5zm0 1.5H6.25A1.75 1.75 0 0 0 4.5 6.25v11.5c0 .966.784 1.75 1.75 1.75H13v-3.25a3.25 3.25 0 0 1 3.066-3.245L16.25 13h3.25V6.25a1.75 1.75 0 0 0-1.75-1.75zm.689 10H16.25a1.75 1.75 0 0 0-1.744 1.607l-.006.143v2.189l3.939-3.939z</Geometry>
3939
</ResourceDictionary>

One.Toolbox/ViewModels/DataProcess/StringConvertPageVM.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ private void DoConvert2()
8585
OutputString = Encoding.Default.GetString(row);
8686
}
8787

88-
[CommunityToolkit.Mvvm.Input.RelayCommand]
88+
[RelayCommand]
8989
private void AddNewTask()
9090
{
9191
if (SelectedConverterTask == null)

One.Toolbox/ViewModels/MainWindow/MainWindowVM.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using One.Toolbox.ViewModels.Base;
33
using One.Toolbox.Views.Dashboard;
44
using One.Toolbox.Views.DataProcess;
5+
using One.Toolbox.Views.NetSpeed;
56
using One.Toolbox.Views.Network;
67
using One.Toolbox.Views.Serialport;
78
using One.Toolbox.Views.Settings;
@@ -90,6 +91,13 @@ public MainWindowVM()
9091
//TargetPageType = typeof(Views.NotePad.NotePadPage),
9192
Content = new Views.BingImage.BingImagePage(),
9293
},
94+
new()
95+
{
96+
Header = "NetSpeed",
97+
Icon = ResourceHelper.Dic["TopSpeed20Regular"],
98+
//TargetPageType = typeof(Views.NotePad.NotePadPage),
99+
Content = new Views.NetSpeed.NetSpeedPage(),
100+
},
93101

94102
//NavigationItems.Add(new MainMenuItemViewModel()
95103
//{
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
using One.Toolbox.ViewModels.Base;
2+
3+
using System.Net.Mail;
4+
using System.Net.NetworkInformation;
5+
6+
using static System.Runtime.InteropServices.JavaScript.JSType;
7+
8+
namespace One.Toolbox.ViewModels.NetSpeed;
9+
10+
public partial class NetSpeedItemVM : BaseVM
11+
{
12+
private readonly NetworkInterface adapter;
13+
private DateTime lastUpdate;
14+
15+
[ObservableProperty]
16+
private string speedSentHuman;
17+
18+
[ObservableProperty]
19+
private string speedReceivedHuman;
20+
21+
public string InterfaceName { get; set; }
22+
public string PhysicalAddress { get; private set; }
23+
private long LastBytesSent { get; set; }
24+
private long LastBytesReceived { get; set; }
25+
26+
private int UpdateInterval { get; set; }
27+
28+
public Action<NetSpeedEventArgs> SpeedAction;
29+
30+
public NetSpeedItemVM(NetworkInterface networkInterface, int updateInterval = 1000)
31+
{
32+
adapter = networkInterface;
33+
UpdateInterval = updateInterval;
34+
35+
InterfaceName = adapter.Name;
36+
var macAddress = networkInterface.GetPhysicalAddress();
37+
38+
PhysicalAddress = BitConverter.ToString(macAddress.GetAddressBytes()).Replace("-", ":");
39+
}
40+
41+
public void Start(CancellationToken cancellationToken = default)
42+
{
43+
lastUpdate = DateTime.Now;
44+
_ = Task.Run(async () =>
45+
{
46+
while (true)
47+
{
48+
try
49+
{
50+
if (cancellationToken.IsCancellationRequested)
51+
return;
52+
53+
UpdateSpeed();
54+
await Task.Delay(UpdateInterval);
55+
}
56+
catch (TaskCanceledException)
57+
{
58+
WriteDebugLog($"Task canceled.");
59+
60+
break;
61+
}
62+
catch (Exception e)
63+
{
64+
WriteDebugLog(e.ToString() + "Failed to update net speed.");
65+
}
66+
}
67+
});
68+
}
69+
70+
public override string ToString()
71+
{
72+
return $"{InterfaceName}({PhysicalAddress})";
73+
}
74+
75+
public bool First { get; set; } = true;
76+
77+
private void UpdateSpeed()
78+
{
79+
// Check if the interface is up (Up表示 网络接口已打开;它可以传输数据包。)
80+
if (!adapter.OperationalStatus.Equals(OperationalStatus.Up))
81+
{
82+
WriteDebugLog($"Net interface {ToString()} is {adapter.OperationalStatus}");
83+
return;
84+
}
85+
86+
// Get the current bytes sent and received
87+
var bytesSent = adapter.GetIPStatistics().BytesSent;
88+
var bytesReceived = adapter.GetIPStatistics().BytesReceived;
89+
90+
//Debug.WriteLine($"BytesSent: {bytesSent}, BytesReceived: {bytesReceived}");
91+
92+
// Calculate the speed
93+
94+
var speedSent = (bytesSent - LastBytesSent) / (DateTime.Now - lastUpdate).TotalSeconds;
95+
var speedReceived = (bytesReceived - LastBytesReceived) / (DateTime.Now - lastUpdate).TotalSeconds;
96+
97+
// Update the last update time
98+
lastUpdate = DateTime.Now;
99+
100+
// Update the last bytes sent and received
101+
LastBytesSent = bytesSent;
102+
LastBytesReceived = bytesReceived;
103+
104+
if (First)
105+
{
106+
First = false;
107+
return;
108+
}
109+
110+
SpeedAction?.Invoke(new NetSpeedEventArgs(Math.Round(speedSent, 2), Math.Round(speedReceived, 2)));
111+
SpeedSentHuman = HumanReadableSpeed(speedSent);
112+
SpeedReceivedHuman = HumanReadableSpeed(speedReceived);
113+
114+
//Debug.WriteLine($"Sent: {speedSent}, Received: {speedReceived}");
115+
116+
//Debug.WriteLine($"SentHuman: {SpeedSentHuman}, ReceivedHuman: {SpeedReceivedHuman}");
117+
}
118+
119+
public static string HumanReadableSpeed(double bytesPerSecond)
120+
{
121+
if (bytesPerSecond < 1024)
122+
{
123+
return $"{bytesPerSecond:0.00} B/s";
124+
}
125+
else if (bytesPerSecond < 1024 * 1024)
126+
{
127+
return $"{(bytesPerSecond / 1024.0):0.00} KB/s";
128+
}
129+
else if (bytesPerSecond < 1024 * 1024 * 1024)
130+
{
131+
return $"{(bytesPerSecond / 1024.0 / 1024.0):0.00} MB/s";
132+
}
133+
else
134+
{
135+
return $"{(bytesPerSecond / 1024.0 / 1024.0 / 1024.0):0.00} GB/s";
136+
}
137+
}
138+
}
139+
140+
public class NetSpeedEventArgs
141+
{
142+
public double SpeedSent { get; set; }
143+
public double SpeedReceived { get; set; }
144+
145+
public NetSpeedEventArgs(double speedSent, double speedReceived)
146+
{
147+
SpeedSent = speedSent;
148+
SpeedReceived = speedReceived;
149+
}
150+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
3+
using One.Core.ExtensionMethods;
4+
using One.Toolbox.Services;
5+
using One.Toolbox.ViewModels.Base;
6+
7+
using System.Collections.ObjectModel;
8+
using System.Net.NetworkInformation;
9+
using System.Windows.Controls;
10+
11+
namespace One.Toolbox.ViewModels.NetSpeed;
12+
13+
public partial class NetSpeedPageVM : BaseVM
14+
{
15+
[ObservableProperty]
16+
private NetSpeedItemVM netSpeedSelectItemVM;
17+
18+
public ObservableCollection<NetSpeedItemVM> NetSpeedItems { get; set; } = new ObservableCollection<NetSpeedItemVM>();
19+
20+
private CancellationTokenSource cts = new CancellationTokenSource();
21+
22+
public NetSpeedPlotVM NetSpeedPlot { get; set; } = new NetSpeedPlotVM();
23+
24+
public NetSpeedPageVM()
25+
{
26+
var interfaces = NetworkInterface.GetAllNetworkInterfaces();
27+
NetSpeedItems.AddRange(interfaces.Select(i => new NetSpeedItemVM(i)).ToList());
28+
29+
NetSpeedItems.ForEach(i => i.Start(cts.Token));
30+
}
31+
32+
public string LastAdapterName { get; set; }
33+
34+
public override void InitializeViewModel()
35+
{
36+
LoadSetting();
37+
NetSpeedSelectItemVM = NetSpeedItems.FirstOrDefault(i => i.InterfaceName == LastAdapterName);
38+
39+
base.InitializeViewModel();
40+
}
41+
42+
public override void OnNavigatedLeave()
43+
{
44+
base.OnNavigatedLeave();
45+
46+
LastAdapterName = NetSpeedSelectItemVM.InterfaceName;
47+
48+
SaveSetting();
49+
}
50+
51+
private void LoadSetting()
52+
{
53+
var service = App.Current.Services.GetService<SettingService>();
54+
LastAdapterName = service.AllConfig.NetSpeedSetting.LastAdapterName;
55+
}
56+
57+
private void SaveSetting()
58+
{
59+
var service = App.Current.Services.GetService<SettingService>();
60+
service.AllConfig.NetSpeedSetting.LastAdapterName = LastAdapterName;
61+
service.Save();
62+
}
63+
64+
[RelayCommand]
65+
private void SelectedNetSpeedItemChanged(SelectionChangedEventArgs obj)
66+
{
67+
if (obj.RemovedItems.Count > 0)
68+
{
69+
var removedItem = obj.RemovedItems[0] as NetSpeedItemVM;
70+
removedItem.SpeedAction -= NetSpeedPlot.OnSpeedChange;
71+
}
72+
73+
if (obj.AddedItems[0] is NetSpeedItemVM addItem)
74+
{
75+
addItem.SpeedAction += NetSpeedPlot.OnSpeedChange;
76+
//addItem.Start(cts.Token);
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)