Files
ReLibreHardwareMonitor/LibreHardwareMonitorLib/Hardware/Sensor.cs
T
PhyxionandRaINi_ f7278652b5 Add Zen 2 CCD temperatures and merged Tdie/Tctl.
Based on the work of @LeagueRaINi

Co-Authored-By: RaINi_ <razor13372k@gmail.com>
2020-01-17 12:10:15 +01:00

269 lines
9.0 KiB
C#

// Mozilla Public License 2.0
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Copyright (C) LibreHardwareMonitor and Contributors
// All Rights Reserved
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
namespace LibreHardwareMonitor.Hardware
{
internal class Sensor : ISensor
{
private readonly string _defaultName;
private readonly Hardware _hardware;
private readonly ISettings _settings;
private readonly List<SensorValue> _values = new List<SensorValue>();
private int _count;
private float? _currentValue;
private string _name;
private float _sum;
private TimeSpan _valuesTimeWindow = TimeSpan.FromDays(1.0);
public Sensor(string name, int index, SensorType sensorType, Hardware hardware, ISettings settings) :
this(name, index, sensorType, hardware, null, settings)
{ }
public Sensor(string name, int index, SensorType sensorType, Hardware hardware, ParameterDescription[] parameterDescriptions, ISettings settings) :
this(name, index, false, sensorType, hardware, parameterDescriptions, settings)
{ }
public Sensor(string name, int index, bool defaultHidden, SensorType sensorType, Hardware hardware, ParameterDescription[] parameterDescriptions, ISettings settings)
{
Index = index;
IsDefaultHidden = defaultHidden;
SensorType = sensorType;
_hardware = hardware;
Parameter[] parameters = new Parameter[parameterDescriptions?.Length ?? 0];
for (int i = 0; i < parameters.Length; i++)
{
if (parameterDescriptions != null)
parameters[i] = new Parameter(parameterDescriptions[i], this, settings);
}
Parameters = parameters;
_settings = settings;
_defaultName = name;
_name = settings.GetValue(new Identifier(Identifier, "name").ToString(), name);
GetSensorValuesFromSettings();
hardware.Closing += delegate { SetSensorValuesToSettings(); };
}
public IControl Control { get; internal set; }
public IHardware Hardware
{
get { return _hardware; }
}
public Identifier Identifier
{
get { return new Identifier(_hardware.Identifier, SensorType.ToString().ToLowerInvariant(), Index.ToString(CultureInfo.InvariantCulture)); }
}
public int Index { get; }
public bool IsDefaultHidden { get; }
public float? Max { get; private set; }
public float? Min { get; private set; }
public string Name
{
get { return _name; }
set
{
_name = !string.IsNullOrEmpty(value) ? value : _defaultName;
_settings.SetValue(new Identifier(Identifier, "name").ToString(), _name);
}
}
public IReadOnlyList<IParameter> Parameters { get; }
public SensorType SensorType { get; }
public float? Value
{
get { return _currentValue; }
set
{
if (_valuesTimeWindow != TimeSpan.Zero)
{
DateTime now = DateTime.UtcNow;
while (_values.Count > 0 && now - _values[0].Time > _valuesTimeWindow)
_values.RemoveAt(0);
if (value.HasValue)
{
_sum += value.Value;
_count++;
if (_count == 4)
{
AppendValue(_sum / _count, now);
_sum = 0;
_count = 0;
}
}
}
_currentValue = value;
if (Min > value || !Min.HasValue)
Min = value;
if (Max < value || !Max.HasValue)
Max = value;
}
}
public IEnumerable<SensorValue> Values
{
get { return _values; }
}
public TimeSpan ValuesTimeWindow
{
get { return _valuesTimeWindow; }
set
{
_valuesTimeWindow = value;
if (value == TimeSpan.Zero)
_values.Clear();
}
}
public void ResetMin()
{
Min = null;
}
public void ResetMax()
{
Max = null;
}
public void Accept(IVisitor visitor)
{
if (visitor == null)
throw new ArgumentNullException(nameof(visitor));
visitor.VisitSensor(this);
}
public void Traverse(IVisitor visitor)
{
foreach (IParameter parameter in Parameters)
parameter.Accept(visitor);
}
private void SetSensorValuesToSettings()
{
using (MemoryStream memoryStream = new MemoryStream())
{
using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
{
using (BufferedStream outputStream = new BufferedStream(gZipStream, 65536))
{
using (BinaryWriter binaryWriter = new BinaryWriter(outputStream))
{
long t = 0;
foreach (SensorValue sensorValue in _values)
{
long v = sensorValue.Time.ToBinary();
binaryWriter.Write(v - t);
t = v;
binaryWriter.Write(sensorValue.Value);
}
binaryWriter.Flush();
}
}
}
_settings.SetValue(new Identifier(Identifier, "values").ToString(), Convert.ToBase64String(memoryStream.ToArray()));
}
}
private void GetSensorValuesFromSettings()
{
string name = new Identifier(Identifier, "values").ToString();
string s = _settings.GetValue(name, null);
if (!string.IsNullOrEmpty(s))
{
try
{
byte[] array = Convert.FromBase64String(s);
DateTime now = DateTime.UtcNow;
using (MemoryStream memoryStream = new MemoryStream(array))
{
using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
{
using (MemoryStream destination = new MemoryStream())
{
gZipStream.CopyTo(destination);
destination.Seek(0, SeekOrigin.Begin);
using (BinaryReader reader = new BinaryReader(destination))
{
try
{
long t = 0;
long readLen = reader.BaseStream.Length - reader.BaseStream.Position;
while (readLen > 0)
{
t += reader.ReadInt64();
DateTime time = DateTime.FromBinary(t);
if (time > now)
break;
float value = reader.ReadSingle();
AppendValue(value, time);
readLen = reader.BaseStream.Length - reader.BaseStream.Position;
}
}
catch (EndOfStreamException)
{ }
}
}
}
}
}
catch
{
// Ignored.
}
}
if (_values.Count > 0)
AppendValue(float.NaN, DateTime.UtcNow);
//remove the value string from the settings to reduce memory usage
_settings.Remove(name);
}
private void AppendValue(float value, DateTime time)
{
if (_values.Count >= 2 && _values[_values.Count - 1].Value == value && _values[_values.Count - 2].Value == value)
{
_values[_values.Count - 1] = new SensorValue(value, time);
return;
}
_values.Add(new SensorValue(value, time));
}
}
}