first commit
This commit is contained in:
@@ -0,0 +1,276 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 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.
|
||||
// Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> 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 bool _trackMinMax;
|
||||
private readonly List<SensorValue> _values = new();
|
||||
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,
|
||||
bool disableHistory = false)
|
||||
{
|
||||
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);
|
||||
_trackMinMax = !disableHistory;
|
||||
if (disableHistory)
|
||||
{
|
||||
_valuesTimeWindow = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
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 virtual 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 (_trackMinMax)
|
||||
{
|
||||
if (!Min.HasValue || Min > value)
|
||||
Min = value;
|
||||
|
||||
if (!Max.HasValue || Max < value)
|
||||
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 ClearValues()
|
||||
{
|
||||
_values.Clear();
|
||||
}
|
||||
|
||||
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();
|
||||
using GZipStream gZipStream = new(memoryStream, CompressionMode.Compress);
|
||||
using BufferedStream outputStream = new(gZipStream, 65536);
|
||||
using (BinaryWriter binaryWriter = new(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(array);
|
||||
using GZipStream gZipStream = new(memoryStream, CompressionMode.Decompress);
|
||||
using MemoryStream destination = new();
|
||||
|
||||
gZipStream.CopyTo(destination);
|
||||
destination.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
using BinaryReader reader = new(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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user