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);
|
||||
}
|
||||
);
|
||||
public static IServiceCollection AddComputeResourcesService(this IServiceCollection services) => services
|
||||
.AddSingleton<ComputeResourcesService>();
|
||||
|
||||
public static IServiceCollection AddAmineContentCalibrationContext(this IServiceCollection services, IConfigurationManager configuration) => services
|
||||
.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.Markup.Xaml;
|
||||
|
||||
using GSS2.Test.ViewModels;
|
||||
|
||||
namespace GSS2.Test;
|
||||
|
||||
public partial class App : Application
|
||||
@@ -13,13 +15,14 @@ public partial class App : Application
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
var mainWindowViewModel = Program.ApplicationHost.Services.GetRequiredService<MainWindowViewModel>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,17 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Protocols.Configuration;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using GSS2.Core.Hardware;
|
||||
using GSS2.Core.Analysis.AmineContent.Database;
|
||||
using GSS2.Test.Views;
|
||||
using GSS2.Test.ViewModels;
|
||||
|
||||
namespace GSS2.Test;
|
||||
|
||||
public static class DependencyInjectionHelper
|
||||
{
|
||||
public static IServiceCollection AddUi(this IServiceCollection services) =>
|
||||
public static IServiceCollection AddViewsAndModels(this IServiceCollection services) =>
|
||||
services
|
||||
.AddTransient<CameraView>()
|
||||
.AddTransient<CameraViewModel>()
|
||||
.AddTransient<MainWindowViewModel>();
|
||||
.AddSingleton<MainWindowViewModel>()
|
||||
.AddSingleton<MainView>()
|
||||
.AddSingleton<MainViewModel>()
|
||||
.AddSingleton<ResourcesView>()
|
||||
.AddSingleton<ResourcesViewModel>();
|
||||
// .AddSingleton<CameraView>()
|
||||
// .AddSingleton<CameraViewModel>();
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
using GSS2.Test.ViewModels;
|
||||
|
||||
namespace GSS2.Test;
|
||||
|
||||
public class DependencyInjectionViewLocator : IDataTemplate
|
||||
@@ -10,7 +12,9 @@ public class DependencyInjectionViewLocator : IDataTemplate
|
||||
if (data is 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)
|
||||
return new TextBlock { Text = $"Not found: {data}" };
|
||||
var type = Type.GetType(name);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<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.Hosting" Version="10.0.0" />
|
||||
<PackageReference Include="Avalonia" Version="11.3.11" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
namespace GSS2.Test;
|
||||
namespace GSS2.Test.Logging;
|
||||
|
||||
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
|
||||
{
|
||||
@@ -1,6 +1,4 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace GSS2.Test;
|
||||
namespace GSS2.Test.Logging;
|
||||
|
||||
public sealed class FileLoggerProvider : ILoggerProvider
|
||||
{
|
||||
@@ -1,8 +1,6 @@
|
||||
using LibCameraSharp;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace GSS2.Test;
|
||||
namespace GSS2.Test.Logging;
|
||||
|
||||
public sealed class LibCameraLogSink : IDisposable
|
||||
{
|
||||
@@ -1,16 +1,11 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
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: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:DataType="local:MainWindowViewModel"
|
||||
Title="GSS2.Test">
|
||||
Title="{Binding Title}">
|
||||
|
||||
<Design.DataContext>
|
||||
<local:MainWindowViewModel/>
|
||||
</Design.DataContext>
|
||||
|
||||
<ContentControl x:Name="cameraView" Content="{Binding CameraViewModel}"/>
|
||||
<!-- <local:CameraView x:Name="cameraView"/> -->
|
||||
<ContentControl Content="{Binding MainViewModel}"/>
|
||||
</Window>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
|
||||
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.Vulkan;
|
||||
using GSS2.Test.Logging;
|
||||
|
||||
using ConsoleFormatter = GSS2.Test.Logging.ConsoleFormatter;
|
||||
|
||||
namespace GSS2.Test;
|
||||
|
||||
@@ -21,7 +24,6 @@ public class Program
|
||||
[STAThread]
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
ApplicationHost.RunAsync();
|
||||
BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
}
|
||||
@@ -44,8 +46,9 @@ public class Program
|
||||
builder.Services.AddTemperatureHumidityService("Hardware:TemperatureHumidity");
|
||||
builder.Services.AddIlluminatorService("Hardware:Illuminator");
|
||||
builder.Services.AddCameraService("Hardware:Camera", true);
|
||||
builder.Services.AddComputeResourcesService();
|
||||
|
||||
builder.Services.AddUi();
|
||||
builder.Services.AddViewsAndModels();
|
||||
|
||||
var host = builder.Build();
|
||||
host.Services.GetRequiredService<LibCameraLogSink>();
|
||||
|
||||
@@ -2,7 +2,7 @@ using GSS2.Core.Hardware;
|
||||
|
||||
using LibCameraSharp;
|
||||
|
||||
namespace GSS2.Test;
|
||||
namespace GSS2.Test.ViewModels;
|
||||
|
||||
public class CameraViewModel : ViewModelBase
|
||||
{
|
||||
@@ -13,6 +13,7 @@ public class CameraViewModel : ViewModelBase
|
||||
{
|
||||
_cameraService = cameraService;
|
||||
_logger = logger;
|
||||
_logger.LogInformation("Initialized");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
namespace GSS2.Test;
|
||||
namespace GSS2.Test.ViewModels;
|
||||
|
||||
public abstract class ViewModelBase : ObservableObject
|
||||
{ }
|
||||
@@ -2,11 +2,7 @@
|
||||
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:local="using:GSS2.Test"
|
||||
x:Class="GSS2.Test.CameraView"
|
||||
x:DataType="local:CameraViewModel">
|
||||
|
||||
<Design.DataContext>
|
||||
<local:CameraViewModel/>
|
||||
</Design.DataContext>
|
||||
xmlns:vm="using:GSS2.Test.ViewModels"
|
||||
x:DataType="vm:CameraViewModel"
|
||||
x:Class="GSS2.Test.Views.CameraView">
|
||||
</Control>
|
||||
@@ -1,23 +1,18 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using Avalonia.Threading;
|
||||
|
||||
using GSS2.Test.ViewModels;
|
||||
using GSS2.Vulkan;
|
||||
|
||||
using LibCameraSharp;
|
||||
|
||||
using Silk.NET.Vulkan;
|
||||
using Silk.NET.Vulkan.Extensions.KHR;
|
||||
|
||||
using Image = Silk.NET.Vulkan.Image;
|
||||
|
||||
namespace GSS2.Test;
|
||||
namespace GSS2.Test.Views;
|
||||
|
||||
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