131 lines
4.9 KiB
C#
131 lines
4.9 KiB
C#
// Copyright 2025 Takuto Nakamura
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
using RunCat365.Properties;
|
|
using System.Globalization;
|
|
|
|
namespace RunCat365
|
|
{
|
|
struct TemperatureInfo
|
|
{
|
|
internal float AverageCelsius { get; set; }
|
|
internal float MaximumCelsius { get; set; }
|
|
}
|
|
|
|
internal static class TemperatureInfoExtension
|
|
{
|
|
private const float CELSIUS_TO_FAHRENHEIT_SCALE = 9.0f / 5.0f;
|
|
private const float CELSIUS_TO_FAHRENHEIT_OFFSET = 32.0f;
|
|
|
|
internal static string GetDescription(this TemperatureInfo temperatureInfo, TemperatureUnit unit)
|
|
{
|
|
var resolvedUnit = unit.Resolve();
|
|
return $"{Strings.SystemInfo_Temperature}: {temperatureInfo.MaximumCelsius.ToLocalizedTemperatureText(resolvedUnit)}";
|
|
}
|
|
|
|
internal static List<string> GenerateIndicator(this TemperatureInfo temperatureInfo, TemperatureUnit unit)
|
|
{
|
|
var resolvedUnit = unit.Resolve();
|
|
return [
|
|
TreeFormatter.CreateRoot($"{Strings.SystemInfo_Temperature}:"),
|
|
TreeFormatter.CreateNode($"{Strings.SystemInfo_Average}: {temperatureInfo.AverageCelsius.ToLocalizedTemperatureText(resolvedUnit)}", false),
|
|
TreeFormatter.CreateNode($"{Strings.SystemInfo_Maximum}: {temperatureInfo.MaximumCelsius.ToLocalizedTemperatureText(resolvedUnit)}", true)
|
|
];
|
|
}
|
|
|
|
private static string ToLocalizedTemperatureText(this float temperatureCelsius, TemperatureUnit resolvedUnit)
|
|
{
|
|
var useFahrenheit = resolvedUnit == TemperatureUnit.Fahrenheit;
|
|
var value = useFahrenheit
|
|
? temperatureCelsius * CELSIUS_TO_FAHRENHEIT_SCALE + CELSIUS_TO_FAHRENHEIT_OFFSET
|
|
: temperatureCelsius;
|
|
var format = useFahrenheit
|
|
? Strings.SystemInfo_TemperatureFahrenheitFormat
|
|
: Strings.SystemInfo_TemperatureCelsiusFormat;
|
|
return string.Format(CultureInfo.CurrentCulture, format, value);
|
|
}
|
|
}
|
|
|
|
internal sealed class TemperaturePerformanceCounters : InstancedPerformanceCounters
|
|
{
|
|
protected override string CategoryName => "Thermal Zone Information";
|
|
protected override string CounterName => "Temperature";
|
|
|
|
internal static TemperaturePerformanceCounters? TryCreate()
|
|
{
|
|
var instance = new TemperaturePerformanceCounters();
|
|
return instance.TryInitialize() ? instance : null;
|
|
}
|
|
}
|
|
|
|
internal class TemperatureRepository
|
|
{
|
|
private const float KELVIN_TO_CELSIUS_OFFSET = 273.15f;
|
|
private const float MIN_VALID_TEMPERATURE_CELSIUS = -50.0f;
|
|
private const float MAX_VALID_TEMPERATURE_CELSIUS = 150.0f;
|
|
private const int REFRESH_INTERVAL_TICKS = 30;
|
|
|
|
private readonly TemperaturePerformanceCounters? counters;
|
|
private TemperatureInfo? temperatureInfo;
|
|
private int ticksSinceLastRefresh;
|
|
|
|
internal bool IsAvailable => counters is not null;
|
|
|
|
internal TemperatureRepository()
|
|
{
|
|
counters = TemperaturePerformanceCounters.TryCreate();
|
|
}
|
|
|
|
internal void Update()
|
|
{
|
|
if (counters is null) return;
|
|
|
|
ticksSinceLastRefresh += 1;
|
|
if (REFRESH_INTERVAL_TICKS <= ticksSinceLastRefresh)
|
|
{
|
|
ticksSinceLastRefresh = 0;
|
|
counters.RefreshInstances();
|
|
}
|
|
|
|
var rawValues = counters.ReadValues();
|
|
var temperaturesCelsius = new List<float>(rawValues.Count);
|
|
foreach (var temperatureKelvin in rawValues)
|
|
{
|
|
if (temperatureKelvin <= 0) continue;
|
|
var temperatureCelsius = temperatureKelvin - KELVIN_TO_CELSIUS_OFFSET;
|
|
if (temperatureCelsius is < MIN_VALID_TEMPERATURE_CELSIUS or > MAX_VALID_TEMPERATURE_CELSIUS) continue;
|
|
temperaturesCelsius.Add(temperatureCelsius);
|
|
}
|
|
|
|
temperatureInfo = temperaturesCelsius.Count == 0
|
|
? null
|
|
: new TemperatureInfo
|
|
{
|
|
AverageCelsius = temperaturesCelsius.Average(),
|
|
MaximumCelsius = temperaturesCelsius.Max()
|
|
};
|
|
}
|
|
|
|
internal TemperatureInfo? Get()
|
|
{
|
|
return temperatureInfo;
|
|
}
|
|
|
|
internal void Close()
|
|
{
|
|
counters?.Close();
|
|
}
|
|
}
|
|
}
|