forked from amkovkov/GranuSightSoftware2
feat: GSS2.Test refactor + ComputeResourcesService
This commit is contained in:
@@ -74,6 +74,8 @@ public static class DependencyInjectionHelper
|
|||||||
return new CameraService(logger, serviceConfiguration, autoInitialize);
|
return new CameraService(logger, serviceConfiguration, autoInitialize);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
public static IServiceCollection AddComputeResourcesService(this IServiceCollection services) => services
|
||||||
|
.AddSingleton<ComputeResourcesService>();
|
||||||
|
|
||||||
public static IServiceCollection AddAmineContentCalibrationContext(this IServiceCollection services, IConfigurationManager configuration) => services
|
public static IServiceCollection AddAmineContentCalibrationContext(this IServiceCollection services, IConfigurationManager configuration) => services
|
||||||
.AddDbContext<AmineContentCalibrationContext>(
|
.AddDbContext<AmineContentCalibrationContext>(
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
using GSS2.Core.Extentions;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace GSS2.Core.Hardware;
|
||||||
|
|
||||||
|
public class ComputeResourcesService
|
||||||
|
{
|
||||||
|
public record CpuUsage(double AllUsagePercent, List<double> CoreUsagePercents);
|
||||||
|
public record CpuTemperature(double Current, double Critical);
|
||||||
|
public record MemoryUsage(
|
||||||
|
long TotalB, long UsedB, long AvailableB,
|
||||||
|
double TotalkB, double UsedkB, double AvailablekB,
|
||||||
|
double TotalMB, double UsedMB, double AvailableMB,
|
||||||
|
double TotalGB, double UsedGB, double AvailableGB)
|
||||||
|
{
|
||||||
|
public MemoryUsage(long totalB, long usedB, long availableB) :
|
||||||
|
this(
|
||||||
|
TotalB: totalB, UsedB: usedB, AvailableB: availableB,
|
||||||
|
TotalkB: totalB / 1000, UsedkB: usedB / 1000, AvailablekB: availableB / 1000,
|
||||||
|
TotalMB: totalB / Math.Pow(1000.0, 2), UsedMB: usedB / Math.Pow(1000.0, 2), AvailableMB: availableB / Math.Pow(1000.0, 2),
|
||||||
|
TotalGB: totalB / Math.Pow(1000.0, 3), UsedGB: usedB / Math.Pow(1000.0, 3), AvailableGB: availableB / Math.Pow(1000.0, 3)
|
||||||
|
)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
public record ComputeResourcesSnapshot(CpuUsage CpuUsage, MemoryUsage MemoryUsage, CpuTemperature CpuTemperature, DateTime Timestamp);
|
||||||
|
private readonly ILogger<ComputeResourcesService> _logger;
|
||||||
|
|
||||||
|
private (long idle, long total)? _prevAll = null;
|
||||||
|
private Dictionary<int, (long idle, long total)?>? _prevCores = null;
|
||||||
|
|
||||||
|
public ComputeResourcesService(ILogger<ComputeResourcesService> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComputeResourcesSnapshot GetSnapshot()
|
||||||
|
{
|
||||||
|
return new ComputeResourcesSnapshot(
|
||||||
|
CpuUsage: GetCpuUsage(),
|
||||||
|
CpuTemperature: GetCpuTemperature(),
|
||||||
|
MemoryUsage: GetMemoryUsage(),
|
||||||
|
Timestamp: DateTime.UtcNow
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private CpuUsage GetCpuUsage()
|
||||||
|
{
|
||||||
|
static (double usage, long idle, long total) ParceLines(string line, (long idle, long total)? prev)
|
||||||
|
{
|
||||||
|
var parts = line.Split(' ', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
long user = long.Parse(parts[1]);
|
||||||
|
long nice = long.Parse(parts[2]);
|
||||||
|
long system = long.Parse(parts[3]);
|
||||||
|
long idle = long.Parse(parts[4]);
|
||||||
|
long iowait = line.Length > 5 ? long.Parse(parts[5]) : 0;
|
||||||
|
long irq = line.Length > 6 ? long.Parse(parts[6]) : 0;
|
||||||
|
long softirq = line.Length > 7 ? long.Parse(parts[7]) : 0;
|
||||||
|
|
||||||
|
long idleTime = idle + iowait;
|
||||||
|
long totalTime = idleTime + user + nice + system + irq + softirq;
|
||||||
|
|
||||||
|
double usage = 0;
|
||||||
|
|
||||||
|
if (prev is not null)
|
||||||
|
{
|
||||||
|
long totalDiff = totalTime - prev.Value.total;
|
||||||
|
long idleDiff = idleTime - prev.Value.idle;
|
||||||
|
|
||||||
|
|
||||||
|
if (totalDiff > 0)
|
||||||
|
usage = (double)(totalDiff - idleDiff) / totalDiff * 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (usage, idleTime, totalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines = File.ReadLines("/proc/stat").Where(l => l.StartsWith("cpu"));
|
||||||
|
if (lines.Count() == 0)
|
||||||
|
return new CpuUsage(0, new List<double>());
|
||||||
|
|
||||||
|
var (allUsage, allIdle, allTotal) = ParceLines(lines.First(), _prevAll);
|
||||||
|
_prevAll = (allIdle, allTotal);
|
||||||
|
|
||||||
|
var coreUsages = new List<double>();
|
||||||
|
|
||||||
|
foreach (var (i, line) in lines.Skip(1).Enumerate())
|
||||||
|
{
|
||||||
|
if (_prevCores is null)
|
||||||
|
_prevCores = new Dictionary<int, (long idle, long total)?>();
|
||||||
|
if (!_prevCores.ContainsKey(i))
|
||||||
|
_prevCores.Add(i, null);
|
||||||
|
var (coreUsage, coreIdle, coreTotal) = ParceLines(line, _prevCores[i]);
|
||||||
|
_prevCores[i] = (coreIdle, coreTotal);
|
||||||
|
coreUsages.Add(coreUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CpuUsage(
|
||||||
|
AllUsagePercent: allUsage,
|
||||||
|
CoreUsagePercents: coreUsages
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private CpuTemperature GetCpuTemperature()
|
||||||
|
{
|
||||||
|
var currentStr = File.ReadAllText("/sys/class/thermal/thermal_zone0/temp").Trim();
|
||||||
|
var current = int.Parse(currentStr) / 1000.0;
|
||||||
|
|
||||||
|
var criticalFile = Directory.GetFiles("/sys/class/thermal/thermal_zone0/", "trip_point_*_type")
|
||||||
|
.FirstOrDefault(f => File.ReadAllText(f).Trim() == "critical")?
|
||||||
|
.Replace("_type", "_temp");
|
||||||
|
|
||||||
|
double critical = 100.0;
|
||||||
|
if (criticalFile is not null)
|
||||||
|
{
|
||||||
|
var criticalStr = File.ReadAllText(criticalFile).Trim();
|
||||||
|
critical = int.Parse(criticalStr) / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CpuTemperature(
|
||||||
|
Current: current,
|
||||||
|
Critical: critical
|
||||||
|
);
|
||||||
|
}
|
||||||
|
private MemoryUsage GetMemoryUsage()
|
||||||
|
{
|
||||||
|
var memInfo = File.ReadAllLines("/proc/meminfo")
|
||||||
|
.Select(l => l.Split(':', 2))
|
||||||
|
.ToDictionary(
|
||||||
|
p => p[0],
|
||||||
|
p => long.Parse(p[1].Trim().Split(' ')[0], CultureInfo.InvariantCulture) * 1024
|
||||||
|
);
|
||||||
|
|
||||||
|
long total = memInfo["MemTotal"];
|
||||||
|
long available = memInfo.ContainsKey("MemAvailable") ? memInfo["MemAvailable"] : memInfo["MemFree"];
|
||||||
|
|
||||||
|
long used = total - available;
|
||||||
|
|
||||||
|
return new MemoryUsage(totalB: total, usedB: used, availableB: available);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ using Avalonia;
|
|||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
|
|
||||||
|
using GSS2.Test.ViewModels;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test;
|
||||||
|
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
@@ -13,13 +15,14 @@ public partial class App : Application
|
|||||||
|
|
||||||
public override void OnFrameworkInitializationCompleted()
|
public override void OnFrameworkInitializationCompleted()
|
||||||
{
|
{
|
||||||
var mainWindowViewModel = Program.ApplicationHost.Services.GetRequiredService<MainWindowViewModel>();
|
|
||||||
|
|
||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
desktop.MainWindow = new MainWindow()
|
|
||||||
{
|
{
|
||||||
DataContext = mainWindowViewModel
|
desktop.Startup += (_, _) => Program.ApplicationHost.RunAsync();
|
||||||
};
|
desktop.Exit += (_, _) => Program.ApplicationHost.StopAsync();
|
||||||
|
|
||||||
|
desktop.MainWindow = new MainWindow();
|
||||||
|
desktop.MainWindow.Activated += (_, _) => desktop.MainWindow.DataContext = Program.ApplicationHost.Services.GetRequiredService<MainWindowViewModel>();
|
||||||
|
}
|
||||||
base.OnFrameworkInitializationCompleted();
|
base.OnFrameworkInitializationCompleted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,17 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using GSS2.Test.Views;
|
||||||
using Microsoft.IdentityModel.Protocols.Configuration;
|
using GSS2.Test.ViewModels;
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
using GSS2.Core.Hardware;
|
|
||||||
using GSS2.Core.Analysis.AmineContent.Database;
|
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test;
|
||||||
|
|
||||||
public static class DependencyInjectionHelper
|
public static class DependencyInjectionHelper
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddUi(this IServiceCollection services) =>
|
public static IServiceCollection AddViewsAndModels(this IServiceCollection services) =>
|
||||||
services
|
services
|
||||||
.AddTransient<CameraView>()
|
.AddSingleton<MainWindowViewModel>()
|
||||||
.AddTransient<CameraViewModel>()
|
.AddSingleton<MainView>()
|
||||||
.AddTransient<MainWindowViewModel>();
|
.AddSingleton<MainViewModel>()
|
||||||
|
.AddSingleton<ResourcesView>()
|
||||||
|
.AddSingleton<ResourcesViewModel>();
|
||||||
|
// .AddSingleton<CameraView>()
|
||||||
|
// .AddSingleton<CameraViewModel>();
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
|
|
||||||
|
using GSS2.Test.ViewModels;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test;
|
||||||
|
|
||||||
public class DependencyInjectionViewLocator : IDataTemplate
|
public class DependencyInjectionViewLocator : IDataTemplate
|
||||||
@@ -10,7 +12,9 @@ public class DependencyInjectionViewLocator : IDataTemplate
|
|||||||
if (data is null)
|
if (data is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var name = data.GetType().FullName?.Replace("ViewModel", "View");
|
var name = data.GetType().FullName?
|
||||||
|
.Replace("ViewModels", "Views")
|
||||||
|
.Replace("ViewModel", "View");
|
||||||
if (name is null)
|
if (name is null)
|
||||||
return new TextBlock { Text = $"Not found: {data}" };
|
return new TextBlock { Text = $"Not found: {data}" };
|
||||||
var type = Type.GetType(name);
|
var type = Type.GetType(name);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc6.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0" />
|
||||||
<PackageReference Include="Avalonia" Version="11.3.11" />
|
<PackageReference Include="Avalonia" Version="11.3.11" />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test.Logging;
|
||||||
|
|
||||||
public sealed class ConsoleFormatter : Microsoft.Extensions.Logging.Console.ConsoleFormatter
|
public sealed class ConsoleFormatter : Microsoft.Extensions.Logging.Console.ConsoleFormatter
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace GSS2.Test;
|
namespace GSS2.Test.Logging;
|
||||||
|
|
||||||
public sealed class FileLogger : ILogger
|
public sealed class FileLogger : ILogger
|
||||||
{
|
{
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
namespace GSS2.Test.Logging;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
|
||||||
|
|
||||||
public sealed class FileLoggerProvider : ILoggerProvider
|
public sealed class FileLoggerProvider : ILoggerProvider
|
||||||
{
|
{
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
using LibCameraSharp;
|
using LibCameraSharp;
|
||||||
|
|
||||||
using Microsoft.Extensions.Logging;
|
namespace GSS2.Test.Logging;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
|
||||||
|
|
||||||
public sealed class LibCameraLogSink : IDisposable
|
public sealed class LibCameraLogSink : IDisposable
|
||||||
{
|
{
|
||||||
@@ -1,16 +1,11 @@
|
|||||||
<Window xmlns="https://github.com/avaloniaui"
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="using:GSS2.Test"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:vm="using:GSS2.Test.ViewModels"
|
||||||
|
x:DataType="vm:MainWindowViewModel"
|
||||||
x:Class="GSS2.Test.MainWindow"
|
x:Class="GSS2.Test.MainWindow"
|
||||||
x:DataType="local:MainWindowViewModel"
|
Title="{Binding Title}">
|
||||||
Title="GSS2.Test">
|
|
||||||
|
|
||||||
<Design.DataContext>
|
<ContentControl Content="{Binding MainViewModel}"/>
|
||||||
<local:MainWindowViewModel/>
|
|
||||||
</Design.DataContext>
|
|
||||||
|
|
||||||
<ContentControl x:Name="cameraView" Content="{Binding CameraViewModel}"/>
|
|
||||||
<!-- <local:CameraView x:Name="cameraView"/> -->
|
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Threading;
|
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test;
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
using Avalonia.Input;
|
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
|
||||||
|
|
||||||
using GSS2.Core.Hardware;
|
|
||||||
|
|
||||||
namespace GSS2.Test;
|
|
||||||
|
|
||||||
public partial class MainWindowViewModel : ViewModelBase
|
|
||||||
{
|
|
||||||
private readonly CameraService _cameraService;
|
|
||||||
private readonly IlluminatorService _illuminatorService;
|
|
||||||
private readonly LightsService _lightsService;
|
|
||||||
private readonly ILogger<MainWindowViewModel> _logger;
|
|
||||||
[ObservableProperty] private CameraViewModel _cameraViewModel;
|
|
||||||
|
|
||||||
public MainWindowViewModel(
|
|
||||||
CameraService cameraService,
|
|
||||||
IlluminatorService illuminatorService,
|
|
||||||
LightsService lightsService,
|
|
||||||
ILogger<MainWindowViewModel> logger,
|
|
||||||
CameraViewModel cameraViewModel
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_cameraService = cameraService;
|
|
||||||
_illuminatorService = illuminatorService;
|
|
||||||
_lightsService = lightsService;
|
|
||||||
_logger = logger;
|
|
||||||
CameraViewModel = cameraViewModel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,9 @@ using GSS2.Core.Analysis.AmineContent.Database;
|
|||||||
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Vulkan;
|
using Avalonia.Vulkan;
|
||||||
|
using GSS2.Test.Logging;
|
||||||
|
|
||||||
|
using ConsoleFormatter = GSS2.Test.Logging.ConsoleFormatter;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test;
|
||||||
|
|
||||||
@@ -21,7 +24,6 @@ public class Program
|
|||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
ApplicationHost.RunAsync();
|
|
||||||
BuildAvaloniaApp()
|
BuildAvaloniaApp()
|
||||||
.StartWithClassicDesktopLifetime(args);
|
.StartWithClassicDesktopLifetime(args);
|
||||||
}
|
}
|
||||||
@@ -44,8 +46,9 @@ public class Program
|
|||||||
builder.Services.AddTemperatureHumidityService("Hardware:TemperatureHumidity");
|
builder.Services.AddTemperatureHumidityService("Hardware:TemperatureHumidity");
|
||||||
builder.Services.AddIlluminatorService("Hardware:Illuminator");
|
builder.Services.AddIlluminatorService("Hardware:Illuminator");
|
||||||
builder.Services.AddCameraService("Hardware:Camera", true);
|
builder.Services.AddCameraService("Hardware:Camera", true);
|
||||||
|
builder.Services.AddComputeResourcesService();
|
||||||
|
|
||||||
builder.Services.AddUi();
|
builder.Services.AddViewsAndModels();
|
||||||
|
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
host.Services.GetRequiredService<LibCameraLogSink>();
|
host.Services.GetRequiredService<LibCameraLogSink>();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using GSS2.Core.Hardware;
|
|||||||
|
|
||||||
using LibCameraSharp;
|
using LibCameraSharp;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test.ViewModels;
|
||||||
|
|
||||||
public class CameraViewModel : ViewModelBase
|
public class CameraViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
@@ -13,6 +13,7 @@ public class CameraViewModel : ViewModelBase
|
|||||||
{
|
{
|
||||||
_cameraService = cameraService;
|
_cameraService = cameraService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_logger.LogInformation("Initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(FrameBuffer, StreamConfiguration)?> CaptureImage(int bufferId)
|
public async Task<(FrameBuffer, StreamConfiguration)?> CaptureImage(int bufferId)
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace GSS2.Test.ViewModels;
|
||||||
|
|
||||||
|
public partial class MainViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
private readonly ILogger<MainViewModel> _logger;
|
||||||
|
[ObservableProperty] private CameraViewModel _cameraViewModel;
|
||||||
|
[ObservableProperty] private ResourcesViewModel _resourcesViewModel;
|
||||||
|
|
||||||
|
public MainViewModel(ILogger<MainViewModel> logger, ResourcesViewModel resourcesViewModel)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
// CameraViewModel = cameraViewModel;
|
||||||
|
ResourcesViewModel = resourcesViewModel;
|
||||||
|
_logger.LogInformation("{} initialized", nameof(MainViewModel));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace GSS2.Test.ViewModels;
|
||||||
|
|
||||||
|
public partial class MainWindowViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
[ObservableProperty] private string _title;
|
||||||
|
[ObservableProperty] private MainViewModel _mainViewModel;
|
||||||
|
private readonly ILogger<MainWindowViewModel> _logger;
|
||||||
|
|
||||||
|
public MainWindowViewModel(ILogger<MainWindowViewModel> logger, MainViewModel mainViewModel)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
MainViewModel = mainViewModel;
|
||||||
|
Title = "GSS2.Test";
|
||||||
|
_logger.LogInformation("{} initialized", nameof(MainWindowViewModel));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,458 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
using Avalonia.Threading;
|
||||||
|
|
||||||
|
using LiveChartsCore;
|
||||||
|
using LiveChartsCore.SkiaSharpView;
|
||||||
|
using LiveChartsCore.SkiaSharpView.Painting;
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
using GSS2.Core.Hardware;
|
||||||
|
using LiveChartsCore.SkiaSharpView.Avalonia;
|
||||||
|
using LiveChartsCore.Defaults;
|
||||||
|
|
||||||
|
namespace GSS2.Test.ViewModels;
|
||||||
|
|
||||||
|
public partial class ResourcesViewModel : ViewModelBase, IDisposable
|
||||||
|
{
|
||||||
|
private bool _disposedValue;
|
||||||
|
private readonly ComputeResourcesService _computeResourcesService;
|
||||||
|
private readonly ILogger<ResourcesViewModel> _logger;
|
||||||
|
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpuUsageSeries;
|
||||||
|
[ObservableProperty] private ObservableCollection<Axis> _cpuUsageSeriesYAxes;
|
||||||
|
[ObservableProperty] private ObservableCollection<Axis> _cpuUsageSeriesXAxes;
|
||||||
|
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpuUsagePieSeries;
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpu0UsagePieSeries;
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpu1UsagePieSeries;
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpu2UsagePieSeries;
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpu3UsagePieSeries;
|
||||||
|
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpuTemperatureSeries;
|
||||||
|
|
||||||
|
[ObservableProperty] private ObservableCollection<Axis> _cpuTemperatureSeriesYAxes;
|
||||||
|
[ObservableProperty] private ObservableCollection<Axis> _cpuTemperatureSeriesXAxes;
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _cpuTemperaturePieSeries;
|
||||||
|
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _memoryUsageSeries;
|
||||||
|
[ObservableProperty] private ObservableCollection<Axis> _memoryUsageSeriesYAxes;
|
||||||
|
[ObservableProperty] private ObservableCollection<Axis> _memoryUsageSeriesXAxes;
|
||||||
|
[ObservableProperty] private ObservableCollection<ISeries> _memoryUsagePieSeries;
|
||||||
|
|
||||||
|
|
||||||
|
[ObservableProperty] private int _intervalMs = 500;
|
||||||
|
[ObservableProperty] private int _chartsHistorySize = 120;
|
||||||
|
private readonly System.Timers.Timer _updateTimer;
|
||||||
|
|
||||||
|
public ResourcesViewModel(ComputeResourcesService computeResourcesService, ILogger<ResourcesViewModel> logger)
|
||||||
|
{
|
||||||
|
_computeResourcesService = computeResourcesService;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
|
CpuUsageSeries = [
|
||||||
|
new LineSeries<double>
|
||||||
|
{
|
||||||
|
Name = "Нагрузка ЦПУ, %",
|
||||||
|
Values = new ObservableCollection<double>(Enumerable.Repeat(0.0, _chartsHistorySize)),
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(144), 0),
|
||||||
|
GeometrySize = 0,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
Stroke = new SolidColorPaint(SKColors.DeepSkyBlue, 1),
|
||||||
|
GeometryFill = new SolidColorPaint(SKColors.DeepSkyBlue, 0),
|
||||||
|
GeometryStroke = new SolidColorPaint(SKColors.Transparent, 0),
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
CpuUsageSeriesYAxes = [
|
||||||
|
new Axis
|
||||||
|
{
|
||||||
|
MinLimit = 0.0,
|
||||||
|
MaxLimit = 100.0,
|
||||||
|
Name = "Нагрузка ЦПУ, %",
|
||||||
|
NameTextSize = 14,
|
||||||
|
MinStep = 10,
|
||||||
|
ForceStepToMin = true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
CpuUsageSeriesXAxes = [
|
||||||
|
new Axis
|
||||||
|
{
|
||||||
|
Labels = new ObservableCollection<string>(){ $"{IntervalMs * ChartsHistorySize / 1000} сек" },
|
||||||
|
LabelsAlignment = LiveChartsCore.Drawing.Align.Start
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
CpuUsagePieSeries = [
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue),
|
||||||
|
InnerRadius = 100,
|
||||||
|
IsHoverable = false,
|
||||||
|
DataLabelsFormatter = value => $"{value.Model?.Value?.ToString("00.00")} %",
|
||||||
|
DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.ChartCenter,
|
||||||
|
DataLabelsSize = 14,
|
||||||
|
DataLabelsPaint = new SolidColorPaint(SKColors.White)
|
||||||
|
},
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(64)),
|
||||||
|
InnerRadius = 100,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
Cpu0UsagePieSeries = [
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue),
|
||||||
|
InnerRadius = 50,
|
||||||
|
IsHoverable = false,
|
||||||
|
DataLabelsFormatter = value => $"{value.Model?.Value?.ToString("00.00")} %",
|
||||||
|
DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.ChartCenter,
|
||||||
|
DataLabelsSize = 14,
|
||||||
|
DataLabelsPaint = new SolidColorPaint(SKColors.White)
|
||||||
|
},
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(64)),
|
||||||
|
InnerRadius = 50,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
Cpu1UsagePieSeries = [
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue),
|
||||||
|
InnerRadius = 50,
|
||||||
|
IsHoverable = false,
|
||||||
|
DataLabelsFormatter = value => $"{value.Model?.Value?.ToString("00.00")} %",
|
||||||
|
DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.ChartCenter,
|
||||||
|
DataLabelsSize = 14,
|
||||||
|
DataLabelsPaint = new SolidColorPaint(SKColors.White)
|
||||||
|
},
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(64)),
|
||||||
|
InnerRadius = 50,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
Cpu2UsagePieSeries = [
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue),
|
||||||
|
InnerRadius = 50,
|
||||||
|
IsHoverable = false,
|
||||||
|
DataLabelsFormatter = value => $"{value.Model?.Value?.ToString("00.00")} %",
|
||||||
|
DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.ChartCenter,
|
||||||
|
DataLabelsSize = 14,
|
||||||
|
DataLabelsPaint = new SolidColorPaint(SKColors.White)
|
||||||
|
},
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(64)),
|
||||||
|
InnerRadius = 50,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
Cpu3UsagePieSeries = [
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue),
|
||||||
|
InnerRadius = 50,
|
||||||
|
IsHoverable = false,
|
||||||
|
DataLabelsFormatter = value => $"{value.Model?.Value?.ToString("00.00")} %",
|
||||||
|
DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.ChartCenter,
|
||||||
|
DataLabelsSize = 14,
|
||||||
|
DataLabelsPaint = new SolidColorPaint(SKColors.White)
|
||||||
|
},
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(64)),
|
||||||
|
InnerRadius = 50,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
CpuTemperatureSeries = [
|
||||||
|
new LineSeries<double>
|
||||||
|
{
|
||||||
|
Name = "Температура ЦПУ, ℃",
|
||||||
|
Values = new ObservableCollection<double>(Enumerable.Repeat(0.0, _chartsHistorySize)),
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(144), 0),
|
||||||
|
GeometrySize = 0,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
Stroke = new SolidColorPaint(SKColors.DeepSkyBlue, 1),
|
||||||
|
GeometryFill = new SolidColorPaint(SKColors.DeepSkyBlue, 0),
|
||||||
|
GeometryStroke = new SolidColorPaint(SKColors.Transparent, 0),
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
CpuTemperatureSeriesYAxes = [
|
||||||
|
new Axis
|
||||||
|
{
|
||||||
|
MinLimit = 0.0,
|
||||||
|
MaxLimit = 100.0,
|
||||||
|
Name = "Температура ЦПУ, ℃",
|
||||||
|
NameTextSize = 14,
|
||||||
|
MinStep = 10,
|
||||||
|
ForceStepToMin = true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
CpuTemperatureSeriesXAxes = [
|
||||||
|
new Axis
|
||||||
|
{
|
||||||
|
Labels = new ObservableCollection<string>(){ $"{IntervalMs * ChartsHistorySize / 1000} сек" },
|
||||||
|
LabelsAlignment = LiveChartsCore.Drawing.Align.Start,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
CpuTemperaturePieSeries = [
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue),
|
||||||
|
InnerRadius = 100,
|
||||||
|
IsHoverable = false,
|
||||||
|
DataLabelsFormatter = value => $"{value.Model?.Value?.ToString("00.00")} ℃",
|
||||||
|
DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.ChartCenter,
|
||||||
|
DataLabelsSize = 14,
|
||||||
|
DataLabelsPaint = new SolidColorPaint(SKColors.White)
|
||||||
|
},
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(64)),
|
||||||
|
InnerRadius = 100,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
MemoryUsageSeries = [
|
||||||
|
new LineSeries<double>
|
||||||
|
{
|
||||||
|
Name = "Нагрузка ОЗУ, МБ",
|
||||||
|
Values = new ObservableCollection<double>(Enumerable.Repeat(0.0, _chartsHistorySize)),
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(144), 0),
|
||||||
|
GeometrySize = 0,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
Stroke = new SolidColorPaint(SKColors.DeepSkyBlue, 1),
|
||||||
|
GeometryFill = new SolidColorPaint(SKColors.Transparent, 0),
|
||||||
|
GeometryStroke = new SolidColorPaint(SKColors.Transparent, 0),
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
MemoryUsageSeriesYAxes = [
|
||||||
|
new Axis
|
||||||
|
{
|
||||||
|
MinLimit = 0.0,
|
||||||
|
MaxLimit = 1000.0,
|
||||||
|
Name = "Нагрузка ОЗУ, МБ",
|
||||||
|
NameTextSize = 14,
|
||||||
|
MinStep = 1000,
|
||||||
|
ForceStepToMin = true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
MemoryUsageSeriesXAxes = [
|
||||||
|
new Axis
|
||||||
|
{
|
||||||
|
Labels = new ObservableCollection<string>(){ $"{IntervalMs * ChartsHistorySize / 1000} сек" },
|
||||||
|
LabelsAlignment = LiveChartsCore.Drawing.Align.Start
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
MemoryUsagePieSeries = [
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue),
|
||||||
|
InnerRadius = 100,
|
||||||
|
IsHoverable = false,
|
||||||
|
DataLabelsFormatter = value => $"{value.Model?.Value?.ToString("000.00")} МБ",
|
||||||
|
DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.ChartCenter,
|
||||||
|
DataLabelsSize = 14,
|
||||||
|
DataLabelsPaint = new SolidColorPaint(SKColors.White)
|
||||||
|
},
|
||||||
|
new PieSeries<ObservableValue>
|
||||||
|
{
|
||||||
|
Values = new ObservableCollection<ObservableValue> { new ObservableValue(1) },
|
||||||
|
Fill = new SolidColorPaint(SKColors.DeepSkyBlue.WithAlpha(64)),
|
||||||
|
InnerRadius = 100,
|
||||||
|
ShowDataLabels = false,
|
||||||
|
IsHoverable = false
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
Update();
|
||||||
|
|
||||||
|
_updateTimer = new System.Timers.Timer(IntervalMs);
|
||||||
|
_updateTimer.Elapsed += UpdateTimerElapsed;
|
||||||
|
_updateTimer.AutoReset = true;
|
||||||
|
_updateTimer.Start();
|
||||||
|
_logger.LogInformation("{} initialized", nameof(ResourcesViewModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateTimerElapsed(object? sender, System.Timers.ElapsedEventArgs ea) => Update();
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var snapshot = _computeResourcesService.GetSnapshot();
|
||||||
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
if (CpuUsageSeries.Count() == 1 &&
|
||||||
|
CpuUsageSeries.First().Values is ObservableCollection<double> cpuUsageValues)
|
||||||
|
{
|
||||||
|
cpuUsageValues.Add(Math.Round(snapshot.CpuUsage.AllUsagePercent, 2));
|
||||||
|
while (cpuUsageValues.Count > ChartsHistorySize)
|
||||||
|
cpuUsageValues.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CpuUsagePieSeries.Count() == 2 &&
|
||||||
|
CpuUsagePieSeries.Skip(0).First().Values is ObservableCollection<ObservableValue> cpuUsagePieValue1 &&
|
||||||
|
cpuUsagePieValue1.Count() == 1 &&
|
||||||
|
CpuUsagePieSeries.Skip(1).First().Values is ObservableCollection<ObservableValue> cpuUsagePieValue2 &&
|
||||||
|
cpuUsagePieValue2.Count() == 1)
|
||||||
|
{
|
||||||
|
var roundedValue = Math.Round(snapshot.CpuUsage.AllUsagePercent, 2);
|
||||||
|
cpuUsagePieValue1.First().Value = roundedValue;
|
||||||
|
cpuUsagePieValue2.First().Value = 100 - roundedValue;
|
||||||
|
}
|
||||||
|
if (Cpu0UsagePieSeries.Count() == 2 &&
|
||||||
|
Cpu0UsagePieSeries.Skip(0).First().Values is ObservableCollection<ObservableValue> cpu0UsagePieValue1 &&
|
||||||
|
cpu0UsagePieValue1.Count() == 1 &&
|
||||||
|
Cpu0UsagePieSeries.Skip(1).First().Values is ObservableCollection<ObservableValue> cpu0UsagePieValue2 &&
|
||||||
|
cpu0UsagePieValue2.Count() == 1 &&
|
||||||
|
snapshot.CpuUsage.CoreUsagePercents.Count() == 4)
|
||||||
|
{
|
||||||
|
var roundedValue = Math.Round(snapshot.CpuUsage.CoreUsagePercents.Skip(0).First(), 2);
|
||||||
|
cpu0UsagePieValue1.First().Value = roundedValue;
|
||||||
|
cpu0UsagePieValue2.First().Value = 100 - roundedValue;
|
||||||
|
}
|
||||||
|
if (Cpu1UsagePieSeries.Count() == 2 &&
|
||||||
|
Cpu1UsagePieSeries.Skip(0).First().Values is ObservableCollection<ObservableValue> cpu1UsagePieValue1 &&
|
||||||
|
cpu1UsagePieValue1.Count() == 1 &&
|
||||||
|
Cpu1UsagePieSeries.Skip(1).First().Values is ObservableCollection<ObservableValue> cpu1UsagePieValue2 &&
|
||||||
|
cpu1UsagePieValue2.Count() == 1 &&
|
||||||
|
snapshot.CpuUsage.CoreUsagePercents.Count() == 4)
|
||||||
|
{
|
||||||
|
var roundedValue = Math.Round(snapshot.CpuUsage.CoreUsagePercents.Skip(1).First(), 2);
|
||||||
|
cpu1UsagePieValue1.First().Value = roundedValue;
|
||||||
|
cpu1UsagePieValue2.First().Value = 100 - roundedValue;
|
||||||
|
}
|
||||||
|
if (Cpu2UsagePieSeries.Count() == 2 &&
|
||||||
|
Cpu2UsagePieSeries.Skip(0).First().Values is ObservableCollection<ObservableValue> cpu2UsagePieValue1 &&
|
||||||
|
cpu2UsagePieValue1.Count() == 1 &&
|
||||||
|
Cpu2UsagePieSeries.Skip(1).First().Values is ObservableCollection<ObservableValue> cpu2UsagePieValue2 &&
|
||||||
|
cpu2UsagePieValue2.Count() == 1 &&
|
||||||
|
snapshot.CpuUsage.CoreUsagePercents.Count() == 4)
|
||||||
|
{
|
||||||
|
var roundedValue = Math.Round(snapshot.CpuUsage.CoreUsagePercents.Skip(2).First(), 2);
|
||||||
|
cpu2UsagePieValue1.First().Value = roundedValue;
|
||||||
|
cpu2UsagePieValue2.First().Value = 100 - roundedValue;
|
||||||
|
}
|
||||||
|
if (Cpu3UsagePieSeries.Count() == 2 &&
|
||||||
|
Cpu3UsagePieSeries.Skip(0).First().Values is ObservableCollection<ObservableValue> cpu3UsagePieValue1 &&
|
||||||
|
cpu3UsagePieValue1.Count() == 1 &&
|
||||||
|
Cpu3UsagePieSeries.Skip(1).First().Values is ObservableCollection<ObservableValue> cpu3UsagePieValue2 &&
|
||||||
|
cpu3UsagePieValue2.Count() == 1 &&
|
||||||
|
snapshot.CpuUsage.CoreUsagePercents.Count() == 4)
|
||||||
|
{
|
||||||
|
var roundedValue = Math.Round(snapshot.CpuUsage.CoreUsagePercents.Skip(3).First(), 2);
|
||||||
|
cpu3UsagePieValue1.First().Value = roundedValue;
|
||||||
|
cpu3UsagePieValue2.First().Value = 100 - roundedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CpuTemperatureSeries.Count() == 1 &&
|
||||||
|
CpuTemperatureSeries.First().Values is ObservableCollection<double> cpuTemperatureValues)
|
||||||
|
{
|
||||||
|
cpuTemperatureValues.Add(Math.Round(snapshot.CpuTemperature.Current, 2));
|
||||||
|
while (cpuTemperatureValues.Count > ChartsHistorySize)
|
||||||
|
cpuTemperatureValues.RemoveAt(0);
|
||||||
|
}
|
||||||
|
if (CpuTemperatureSeriesYAxes.Count() == 1)
|
||||||
|
CpuTemperatureSeriesYAxes.First().MaxLimit = Math.Round(snapshot.CpuTemperature.Critical);
|
||||||
|
|
||||||
|
if (CpuTemperaturePieSeries.Count() == 2 &&
|
||||||
|
CpuTemperaturePieSeries.Skip(0).First().Values is ObservableCollection<ObservableValue> cpuTemperaturePieValue1 &&
|
||||||
|
cpuTemperaturePieValue1.Count() == 1 &&
|
||||||
|
CpuTemperaturePieSeries.Skip(1).First().Values is ObservableCollection<ObservableValue> cpuTemperaturePieValue2 &&
|
||||||
|
cpuTemperaturePieValue2.Count() == 1)
|
||||||
|
{
|
||||||
|
var roundedValue = Math.Round(snapshot.CpuTemperature.Current, 2);
|
||||||
|
cpuTemperaturePieValue1.First().Value = roundedValue;
|
||||||
|
cpuTemperaturePieValue2.First().Value = snapshot.CpuTemperature.Critical - roundedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MemoryUsageSeries.Count() == 1 &&
|
||||||
|
MemoryUsageSeries.First().Values is ObservableCollection<double> memoryUsageValues)
|
||||||
|
{
|
||||||
|
memoryUsageValues.Add(Math.Round(snapshot.MemoryUsage.UsedMB, 2));
|
||||||
|
while (memoryUsageValues.Count > ChartsHistorySize)
|
||||||
|
memoryUsageValues.RemoveAt(0);
|
||||||
|
}
|
||||||
|
if (MemoryUsageSeriesYAxes.Count() == 1)
|
||||||
|
MemoryUsageSeriesYAxes.First().MaxLimit = Math.Round(snapshot.MemoryUsage.TotalMB);
|
||||||
|
|
||||||
|
if (MemoryUsagePieSeries.Count() == 2 &&
|
||||||
|
MemoryUsagePieSeries.Skip(0).First().Values is ObservableCollection<ObservableValue> memoryUsagePieValue1 &&
|
||||||
|
memoryUsagePieValue1.Count() == 1 &&
|
||||||
|
MemoryUsagePieSeries.Skip(1).First().Values is ObservableCollection<ObservableValue> memoryUsagePieValue2 &&
|
||||||
|
memoryUsagePieValue2.Count() == 1)
|
||||||
|
{
|
||||||
|
var roundedValue = Math.Round(snapshot.MemoryUsage.UsedMB, 2);
|
||||||
|
memoryUsagePieValue1.First().Value = roundedValue;
|
||||||
|
memoryUsagePieValue2.First().Value = snapshot.MemoryUsage.TotalMB - roundedValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogWarning(e, "Exception while update");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_disposedValue)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_updateTimer.Stop();
|
||||||
|
_updateTimer.Dispose();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposedValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(disposing: true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test.ViewModels;
|
||||||
|
|
||||||
public abstract class ViewModelBase : ObservableObject
|
public abstract class ViewModelBase : ObservableObject
|
||||||
{ }
|
{ }
|
||||||
@@ -2,11 +2,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="using:GSS2.Test"
|
xmlns:vm="using:GSS2.Test.ViewModels"
|
||||||
x:Class="GSS2.Test.CameraView"
|
x:DataType="vm:CameraViewModel"
|
||||||
x:DataType="local:CameraViewModel">
|
x:Class="GSS2.Test.Views.CameraView">
|
||||||
|
|
||||||
<Design.DataContext>
|
|
||||||
<local:CameraViewModel/>
|
|
||||||
</Design.DataContext>
|
|
||||||
</Control>
|
</Control>
|
||||||
@@ -1,23 +1,18 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.Cryptography;
|
|
||||||
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Avalonia.Rendering.Composition;
|
using Avalonia.Rendering.Composition;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
using GSS2.Test.ViewModels;
|
||||||
using GSS2.Vulkan;
|
using GSS2.Vulkan;
|
||||||
|
|
||||||
using LibCameraSharp;
|
using LibCameraSharp;
|
||||||
|
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using Silk.NET.Vulkan.Extensions.KHR;
|
using Silk.NET.Vulkan.Extensions.KHR;
|
||||||
|
|
||||||
using Image = Silk.NET.Vulkan.Image;
|
using Image = Silk.NET.Vulkan.Image;
|
||||||
|
|
||||||
namespace GSS2.Test;
|
namespace GSS2.Test.Views;
|
||||||
|
|
||||||
interface IImage
|
interface IImage
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:vm="using:GSS2.Test.ViewModels"
|
||||||
|
xmlns:local="using:GSS2.Test.Views"
|
||||||
|
x:DataType="vm:MainViewModel"
|
||||||
|
x:Class="GSS2.Test.Views.MainView">
|
||||||
|
<!-- <ContentControl Content="{Binding CameraViewModel}"/> -->
|
||||||
|
<ContentControl Content="{Binding ResourcesViewModel}"/>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace GSS2.Test.Views;
|
||||||
|
|
||||||
|
public partial class MainView : UserControl
|
||||||
|
{
|
||||||
|
public MainView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:GSS2.Test.ViewModels"
|
||||||
|
xmlns:lvc="using:LiveChartsCore.SkiaSharpView.Avalonia"
|
||||||
|
x:Class="GSS2.Test.Views.ResourcesView"
|
||||||
|
x:DataType="vm:ResourcesViewModel">
|
||||||
|
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="*,Auto">
|
||||||
|
<lvc:CartesianChart
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
Series="{Binding CpuUsageSeries}"
|
||||||
|
YAxes="{Binding CpuUsageSeriesYAxes}"
|
||||||
|
XAxes="{Binding CpuUsageSeriesXAxes}"
|
||||||
|
Height="300"
|
||||||
|
ZoomMode="None"
|
||||||
|
EasingFunction="{x:Null}" />
|
||||||
|
<lvc:CartesianChart
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="0"
|
||||||
|
Series="{Binding CpuTemperatureSeries}"
|
||||||
|
YAxes="{Binding CpuTemperatureSeriesYAxes}"
|
||||||
|
XAxes="{Binding CpuTemperatureSeriesXAxes}"
|
||||||
|
Height="300"
|
||||||
|
ZoomMode="None"
|
||||||
|
EasingFunction="{x:Null}" />
|
||||||
|
<lvc:CartesianChart
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="0"
|
||||||
|
Series="{Binding MemoryUsageSeries}"
|
||||||
|
YAxes="{Binding MemoryUsageSeriesYAxes}"
|
||||||
|
XAxes="{Binding MemoryUsageSeriesXAxes}"
|
||||||
|
Height="300"
|
||||||
|
ZoomMode="None"
|
||||||
|
EasingFunction="{x:Null}" />
|
||||||
|
|
||||||
|
<Grid Grid.Row="0" Grid.Column="1" RowDefinitions="Auto,Auto" ColumnDefinitions="Auto,Auto,Auto">
|
||||||
|
<lvc:PieChart
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
Grid.Column="0"
|
||||||
|
Height="200"
|
||||||
|
Width="200"
|
||||||
|
Series="{Binding CpuUsagePieSeries}" />
|
||||||
|
<lvc:PieChart
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="1"
|
||||||
|
Height="120"
|
||||||
|
Width="120"
|
||||||
|
Series="{Binding Cpu0UsagePieSeries}" />
|
||||||
|
<lvc:PieChart
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.Column="2"
|
||||||
|
Height="120"
|
||||||
|
Width="120"
|
||||||
|
Series="{Binding Cpu1UsagePieSeries}" />
|
||||||
|
<lvc:PieChart
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
Height="120"
|
||||||
|
Width="120"
|
||||||
|
Series="{Binding Cpu2UsagePieSeries}" />
|
||||||
|
<lvc:PieChart
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="2"
|
||||||
|
Height="120"
|
||||||
|
Width="120"
|
||||||
|
Series="{Binding Cpu3UsagePieSeries}" />
|
||||||
|
</Grid>
|
||||||
|
<lvc:PieChart
|
||||||
|
Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
Height="300"
|
||||||
|
Width="300"
|
||||||
|
Series="{Binding CpuTemperaturePieSeries}" />
|
||||||
|
<lvc:PieChart
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="1"
|
||||||
|
Height="300"
|
||||||
|
Width="300"
|
||||||
|
Series="{Binding MemoryUsagePieSeries}" />
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace GSS2.Test.Views;
|
||||||
|
|
||||||
|
public partial class ResourcesView : UserControl
|
||||||
|
{
|
||||||
|
public ResourcesView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user