Added support for saving and restoring the sensor history for the last 24h. The sensor history is now saved in a reduced format (duplicate values are removed, gaps are marked with a NAN sensor value.

This commit is contained in:
Michael Möller 2011-06-19 12:41:18 +00:00
parent 357498a063
commit 330e93ea64
16 changed files with 356 additions and 46 deletions

View File

@ -0,0 +1,235 @@
/*
Version: MPL 1.1/GPL 2.0/LGPL 2.1
The contents of this file are subject to the Mozilla Public License Version
1.1 (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.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the License.
The Original Code is the Open Hardware Monitor code.
The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>.
Portions created by the Initial Developer are Copyright (C) 2011
the Initial Developer. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
*/
using System;
using System.Collections;
using System.Collections.Generic;
namespace OpenHardwareMonitor.Collections {
public class RingCollection<T> : IEnumerable<T> {
private T[] array;
// first item of collection
private int head;
// index after the last item of the collection
private int tail;
// number of items in the collection
private int size;
public RingCollection() : this(0) { }
public RingCollection(int capacity) {
if (capacity < 0)
throw new ArgumentOutOfRangeException("capacity");
this.array = new T[capacity];
this.head = 0;
this.tail = 0;
this.size = 0;
}
public int Capacity {
get {
return array.Length;
}
set {
T[] newArray = new T[value];
if (size > 0) {
if (head < tail) {
Array.Copy(array, head, newArray, 0, size);
} else {
Array.Copy(array, head, newArray, 0, array.Length - head);
Array.Copy(array, 0, newArray, array.Length - head, tail);
}
}
this.array = newArray;
this.head = 0;
this.tail = size == value ? 0 : size;
}
}
public void Clear() {
// remove potential references
if (head < tail) {
Array.Clear(array, head, size);
} else {
Array.Clear(array, 0, tail);
Array.Clear(array, head, array.Length - head);
}
this.head = 0;
this.tail = 0;
this.size = 0;
}
public void Append(T item) {
if (size == array.Length) {
int newCapacity = array.Length * 3 / 2;
if (newCapacity < array.Length + 8)
newCapacity = array.Length + 8;
Capacity = newCapacity;
}
array[tail] = item;
tail = tail + 1 == array.Length ? 0 : tail + 1;
size++;
}
public T Remove() {
if (size == 0)
throw new InvalidOperationException();
T result = array[head];
array[head] = default(T);
head = head + 1 == array.Length ? 0 : head + 1;
size--;
return result;
}
public int Count {
get {
return size;
}
}
public T this[int index] {
get {
if (index < 0 || index >= size)
throw new IndexOutOfRangeException();
int i = head + index;
if (i >= array.Length)
i -= array.Length;
return array[i];
}
set {
if (index < 0 || index >= size)
throw new IndexOutOfRangeException();
int i = head + index;
if (i >= array.Length)
i -= array.Length;
array[i] = value;
}
}
public T First {
get {
if (size == 0)
throw new InvalidOperationException();
return array[head];
}
set {
if (size == 0)
throw new InvalidOperationException();
array[head] = value;
}
}
public T Last {
get {
if (size == 0)
throw new InvalidOperationException();
return array[tail == 0 ? array.Length - 1 : tail - 1];
}
set {
if (size == 0)
throw new InvalidOperationException();
array[tail == 0 ? array.Length - 1 : tail - 1] = value;
}
}
IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return new RingCollection<T>.Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator() {
return new RingCollection<T>.Enumerator(this);
}
private struct Enumerator : IEnumerator<T>, IEnumerator {
private RingCollection<T> collection;
private int index;
public Enumerator(RingCollection<T> collection) {
this.collection = collection;
this.index = -1;
}
public void Dispose() {
this.index = -2;
}
public void Reset() {
this.index = -1;
}
public T Current {
get {
if (index < 0)
throw new InvalidOperationException();
return collection[index];
}
}
object IEnumerator.Current {
get {
if (index < 0)
throw new InvalidOperationException();
return collection[index];
}
}
public bool MoveNext() {
if (index == -2)
return false;
index++;
if (index == collection.size) {
index = -2;
return false;
}
return true;
}
}
}
}

View File

@ -501,12 +501,11 @@ namespace OpenHardwareMonitor.GUI {
}
private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
Visible = false;
SaveConfiguration();
Visible = false;
systemTray.IsMainIconEnabled = false;
timer.Enabled = false;
computer.Close();
SaveConfiguration();
systemTray.Dispose();
}

View File

@ -16,7 +16,7 @@
The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>.
Portions created by the Initial Developer are Copyright (C) 2009-2010
Portions created by the Initial Developer are Copyright (C) 2009-2011
the Initial Developer. All Rights Reserved.
Contributor(s):
@ -88,10 +88,12 @@ namespace OpenHardwareMonitor.GUI {
foreach (ISensor sensor in temperatures) {
IEnumerable<SensorValue> values = sensor.Values;
foreach (SensorValue value in values) {
if (!minTempNullable.HasValue || minTempNullable > value.Value)
minTempNullable = value.Value;
if (!maxTempNullable.HasValue || maxTempNullable < value.Value)
maxTempNullable = value.Value;
if (!float.IsNaN(value.Value)) {
if (!minTempNullable.HasValue || minTempNullable > value.Value)
minTempNullable = value.Value;
if (!maxTempNullable.HasValue || maxTempNullable < value.Value)
maxTempNullable = value.Value;
}
}
}
if (!minTempNullable.HasValue) {
@ -140,6 +142,10 @@ namespace OpenHardwareMonitor.GUI {
deltaTime += 2;
while (deltaTime + 5 < maxTime && deltaTime < 100)
deltaTime += 5;
while (deltaTime + 50 < maxTime && deltaTime < 1000)
deltaTime += 50;
while (deltaTime + 100 < maxTime && deltaTime < 10000)
deltaTime += 100;
List<float> grid = new List<float>(countTime + 1);
for (int i = 0; i <= countTime; i++) {
@ -149,7 +155,6 @@ namespace OpenHardwareMonitor.GUI {
}
protected override void OnPaint(PaintEventArgs e) {
now = DateTime.Now - new TimeSpan(0, 0, 4);
List<float> timeGrid = GetTimeGrid();
@ -196,14 +201,18 @@ namespace OpenHardwareMonitor.GUI {
IEnumerable<SensorValue> values = sensor.Values;
PointF last = new PointF();
bool first = true;
foreach (SensorValue value in values) {
PointF point = new PointF(
x0 + w - w * (float)(now - value.Time).TotalMinutes / deltaTime,
y0 + h - h * (value.Value - tempGrid[0]) / deltaTemp);
if (!first)
g.DrawLine(pen, last, point);
last = point;
first = false;
foreach (SensorValue v in values) {
if (!float.IsNaN(v.Value)) {
PointF point = new PointF(
x0 + w - w * (float)(now - v.Time).TotalMinutes / deltaTime,
y0 + h - h * (v.Value - tempGrid[0]) / deltaTemp);
if (!first)
g.DrawLine(pen, last, point);
last = point;
first = false;
} else {
first = true;
}
}
}
}

View File

@ -16,7 +16,7 @@
The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>.
Portions created by the Initial Developer are Copyright (C) 20011
Portions created by the Initial Developer are Copyright (C) 2011
the Initial Developer. All Rights Reserved.
Contributor(s):

View File

@ -208,12 +208,13 @@ namespace OpenHardwareMonitor.Hardware.ATI {
}
}
public void Close() {
public override void Close() {
this.fanControl.ControlModeChanged -= ControlModeChanged;
this.fanControl.SoftwareControlValueChanged -=
SoftwareControlValueChanged;
RestoreDefaultFanSpeed();
base.Close();
}
}
}

View File

@ -348,10 +348,11 @@ namespace OpenHardwareMonitor.Hardware.CPU {
}
}
public override void Close() {
public override void Close() {
if (temperatureStream != null) {
temperatureStream.Close();
}
base.Close();
}
}
}

View File

@ -333,9 +333,5 @@ namespace OpenHardwareMonitor.Hardware.CPU {
totalLoad.Value = cpuLoad.GetTotalLoad();
}
}
public virtual void Close() {
}
}
}

View File

@ -123,8 +123,9 @@ namespace OpenHardwareMonitor.Hardware.HDD {
count++; count %= UPDATE_DIVIDER;
}
public void Close() {
public override void Close() {
SMART.CloseHandle(handle);
base.Close();
}
public override void Traverse(IVisitor visitor) {

View File

@ -113,6 +113,13 @@ namespace OpenHardwareMonitor.Hardware {
public abstract void Update();
public event HardwareEventHandler Closing;
public virtual void Close() {
if (Closing != null)
Closing(this);
}
public void Accept(IVisitor visitor) {
if (visitor == null)
throw new ArgumentNullException("visitor");

View File

@ -285,10 +285,11 @@ namespace OpenHardwareMonitor.Hardware.Heatmaster {
return r.ToString();
}
public void Close() {
public override void Close() {
serialPort.Close();
serialPort.Dispose();
serialPort = null;
base.Close();
}
public void Dispose() {

View File

@ -38,7 +38,7 @@
namespace OpenHardwareMonitor.Hardware {
public delegate void SensorEventHandler(ISensor sensor);
public enum HardwareType {
Mainboard,
SuperIO,

View File

@ -47,7 +47,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
private readonly ISettings settings;
private readonly LPCIO lpcio;
private readonly LMSensors lmSensors;
private readonly IHardware[] superIOHardware;
private readonly Hardware[] superIOHardware;
public Mainboard(ISettings settings) {
this.settings = settings;
@ -80,7 +80,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
superIO = lpcio.SuperIO;
}
superIOHardware = new IHardware[superIO.Length];
superIOHardware = new Hardware[superIO.Length];
for (int i = 0; i < superIO.Length; i++)
superIOHardware[i] = new SuperIOHardware(this, superIO[i],
smbios.Board != null ? smbios.Board.Manufacturer :
@ -132,6 +132,8 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
public void Close() {
if (lmSensors != null)
lmSensors.Close();
foreach (Hardware hardware in superIOHardware)
hardware.Close();
}
public IHardware[] SubHardware {

View File

@ -16,7 +16,7 @@
The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>.
Portions created by the Initial Developer are Copyright (C) 2009-2010
Portions created by the Initial Developer are Copyright (C) 2009-2011
the Initial Developer. All Rights Reserved.
Contributor(s):
@ -43,7 +43,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
internal class NvidiaGroup : IGroup {
private readonly List<IHardware> hardware = new List<IHardware>();
private readonly List<Hardware> hardware = new List<Hardware>();
private readonly StringBuilder report = new StringBuilder();
public NvidiaGroup(ISettings settings) {
@ -125,6 +125,9 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
return report.ToString();
}
public void Close() { }
public void Close() {
foreach (Hardware gpu in hardware)
gpu.Close();
}
}
}

View File

@ -16,7 +16,7 @@
The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>.
Portions created by the Initial Developer are Copyright (C) 2009-2010
Portions created by the Initial Developer are Copyright (C) 2009-2011
the Initial Developer. All Rights Reserved.
Contributor(s):
@ -38,6 +38,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using OpenHardwareMonitor.Collections;
namespace OpenHardwareMonitor.Hardware {
@ -49,33 +51,31 @@ namespace OpenHardwareMonitor.Hardware {
private readonly int index;
private readonly bool defaultHidden;
private readonly SensorType sensorType;
private readonly IHardware hardware;
private readonly Hardware hardware;
private readonly ReadOnlyArray<IParameter> parameters;
private float? currentValue;
private float? minValue;
private float? maxValue;
private readonly Queue<SensorValue> values =
new Queue<SensorValue>(MAX_MINUTES * 15);
private readonly RingCollection<SensorValue>
values = new RingCollection<SensorValue>();
private readonly ISettings settings;
private IControl control;
private float sum;
private int count;
private const int MAX_MINUTES = 120;
public Sensor(string name, int index, SensorType sensorType,
IHardware hardware, ISettings settings) :
Hardware hardware, ISettings settings) :
this(name, index, sensorType, hardware, null, settings) { }
public Sensor(string name, int index, SensorType sensorType,
IHardware hardware, ParameterDescription[] parameterDescriptions,
Hardware hardware, ParameterDescription[] parameterDescriptions,
ISettings settings) :
this(name, index, false, sensorType, hardware,
parameterDescriptions, settings) { }
public Sensor(string name, int index, bool defaultHidden,
SensorType sensorType, IHardware hardware,
SensorType sensorType, Hardware hardware,
ParameterDescription[] parameterDescriptions, ISettings settings)
{
this.index = index;
@ -92,6 +92,59 @@ namespace OpenHardwareMonitor.Hardware {
this.defaultName = name;
this.name = settings.GetValue(
new Identifier(Identifier, "name").ToString(), name);
GetSensorValuesFromSettings();
hardware.Closing += delegate(IHardware h) {
SetSensorValuesToSettings();
};
}
private void SetSensorValuesToSettings() {
using (MemoryStream m = new MemoryStream()) {
using (GZipStream c = new GZipStream(m, CompressionMode.Compress))
using (BinaryWriter writer = new BinaryWriter(c)) {
foreach (SensorValue sensorValue in values) {
writer.Write(sensorValue.Time.ToBinary());
writer.Write(sensorValue.Value);
}
}
settings.SetValue(new Identifier(Identifier, "values").ToString(),
Convert.ToBase64String(m.ToArray()));
}
}
private void GetSensorValuesFromSettings() {
string s = settings.GetValue(
new Identifier(Identifier, "values").ToString(), null);
byte[] array = null;
try {
array = Convert.FromBase64String(s);
using (MemoryStream m = new MemoryStream(array))
using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
using (BinaryReader reader = new BinaryReader(c)) {
try {
while (true) {
DateTime time = DateTime.FromBinary(reader.ReadInt64());
float value = reader.ReadSingle();
AppendValue(value, time);
}
} catch (EndOfStreamException) { }
}
} catch { }
if (values.Count > 0)
AppendValue(float.NaN, DateTime.Now);
}
private void AppendValue(float value, DateTime time) {
if (values.Count >= 2 && values.Last.Value == value &&
values[values.Count - 2].Value == value) {
values.Last = new SensorValue(value, time);
return;
}
values.Append(new SensorValue(value, time));
}
public IHardware Hardware {
@ -140,15 +193,15 @@ namespace OpenHardwareMonitor.Hardware {
return currentValue;
}
set {
while (values.Count > 0 &&
(DateTime.Now - values.Peek().Time).TotalMinutes > MAX_MINUTES)
values.Dequeue();
DateTime now = DateTime.Now;
while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
values.Remove();
if (value.HasValue) {
sum += value.Value;
count++;
if (count == 4) {
values.Enqueue(new SensorValue(sum / count, DateTime.Now));
AppendValue(sum / count, now);
sum = 0;
count = 0;
}

View File

@ -340,8 +340,9 @@ namespace OpenHardwareMonitor.Hardware.TBalancer {
alternativeRequest.BeginInvoke(null, null);
}
public void Close() {
public override void Close() {
FTD2XX.FT_Close(handle);
base.Close();
}
}

View File

@ -56,6 +56,7 @@
<Reference Include="System.Management" />
</ItemGroup>
<ItemGroup>
<Compile Include="Collections\RingCollection.cs" />
<Compile Include="Hardware\ATI\ADL.cs" />
<Compile Include="Hardware\ATI\ATIGPU.cs" />
<Compile Include="Hardware\ATI\ATIGroup.cs" />