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

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

View File

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

View File

@@ -16,7 +16,7 @@
The Initial Developer of the Original Code is The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>. 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. the Initial Developer. All Rights Reserved.
Contributor(s): 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.ControlModeChanged -= ControlModeChanged;
this.fanControl.SoftwareControlValueChanged -= this.fanControl.SoftwareControlValueChanged -=
SoftwareControlValueChanged; SoftwareControlValueChanged;
RestoreDefaultFanSpeed(); RestoreDefaultFanSpeed();
base.Close();
} }
} }
} }

View File

@@ -352,6 +352,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
if (temperatureStream != null) { if (temperatureStream != null) {
temperatureStream.Close(); temperatureStream.Close();
} }
base.Close();
} }
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -16,7 +16,7 @@
The Initial Developer of the Original Code is The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>. 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. the Initial Developer. All Rights Reserved.
Contributor(s): Contributor(s):
@@ -43,7 +43,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
internal class NvidiaGroup : IGroup { 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(); private readonly StringBuilder report = new StringBuilder();
public NvidiaGroup(ISettings settings) { public NvidiaGroup(ISettings settings) {
@@ -125,6 +125,9 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
return report.ToString(); 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 The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>. 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. the Initial Developer. All Rights Reserved.
Contributor(s): Contributor(s):
@@ -38,6 +38,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO;
using System.IO.Compression;
using OpenHardwareMonitor.Collections; using OpenHardwareMonitor.Collections;
namespace OpenHardwareMonitor.Hardware { namespace OpenHardwareMonitor.Hardware {
@@ -49,33 +51,31 @@ namespace OpenHardwareMonitor.Hardware {
private readonly int index; private readonly int index;
private readonly bool defaultHidden; private readonly bool defaultHidden;
private readonly SensorType sensorType; private readonly SensorType sensorType;
private readonly IHardware hardware; private readonly Hardware hardware;
private readonly ReadOnlyArray<IParameter> parameters; private readonly ReadOnlyArray<IParameter> parameters;
private float? currentValue; private float? currentValue;
private float? minValue; private float? minValue;
private float? maxValue; private float? maxValue;
private readonly Queue<SensorValue> values = private readonly RingCollection<SensorValue>
new Queue<SensorValue>(MAX_MINUTES * 15); values = new RingCollection<SensorValue>();
private readonly ISettings settings; private readonly ISettings settings;
private IControl control; private IControl control;
private float sum; private float sum;
private int count; private int count;
private const int MAX_MINUTES = 120;
public Sensor(string name, int index, SensorType sensorType, public Sensor(string name, int index, SensorType sensorType,
IHardware hardware, ISettings settings) : Hardware hardware, ISettings settings) :
this(name, index, sensorType, hardware, null, settings) { } this(name, index, sensorType, hardware, null, settings) { }
public Sensor(string name, int index, SensorType sensorType, public Sensor(string name, int index, SensorType sensorType,
IHardware hardware, ParameterDescription[] parameterDescriptions, Hardware hardware, ParameterDescription[] parameterDescriptions,
ISettings settings) : ISettings settings) :
this(name, index, false, sensorType, hardware, this(name, index, false, sensorType, hardware,
parameterDescriptions, settings) { } parameterDescriptions, settings) { }
public Sensor(string name, int index, bool defaultHidden, public Sensor(string name, int index, bool defaultHidden,
SensorType sensorType, IHardware hardware, SensorType sensorType, Hardware hardware,
ParameterDescription[] parameterDescriptions, ISettings settings) ParameterDescription[] parameterDescriptions, ISettings settings)
{ {
this.index = index; this.index = index;
@@ -92,6 +92,59 @@ namespace OpenHardwareMonitor.Hardware {
this.defaultName = name; this.defaultName = name;
this.name = settings.GetValue( this.name = settings.GetValue(
new Identifier(Identifier, "name").ToString(), name); 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 { public IHardware Hardware {
@@ -140,15 +193,15 @@ namespace OpenHardwareMonitor.Hardware {
return currentValue; return currentValue;
} }
set { set {
while (values.Count > 0 && DateTime now = DateTime.Now;
(DateTime.Now - values.Peek().Time).TotalMinutes > MAX_MINUTES) while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
values.Dequeue(); values.Remove();
if (value.HasValue) { if (value.HasValue) {
sum += value.Value; sum += value.Value;
count++; count++;
if (count == 4) { if (count == 4) {
values.Enqueue(new SensorValue(sum / count, DateTime.Now)); AppendValue(sum / count, now);
sum = 0; sum = 0;
count = 0; count = 0;
} }

View File

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

View File

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