forked from amkovkov/GranuSightSoftware2
458 lines
21 KiB
C#
458 lines
21 KiB
C#
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);
|
|
}
|
|
} |