forked from amkovkov/GranuSightSoftware2
feat: GSS2.Test refactor + ComputeResourcesService
This commit is contained in:
@@ -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">
|
||||
|
||||
<Design.DataContext>
|
||||
<local:MainWindowViewModel/>
|
||||
</Design.DataContext>
|
||||
Title="{Binding Title}">
|
||||
|
||||
<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