# HG changeset patch # User moel.mich # Date 1308487278 0 # Node ID 96263190189a8222d1240a11d4a88fa1051ebf56 # Parent 21504f47aedf7c76f190c736a3a17f81f8aba749 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. diff -r 21504f47aedf -r 96263190189a Collections/RingCollection.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Collections/RingCollection.cs Sun Jun 19 12:41:18 2011 +0000 @@ -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 . + 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 : IEnumerable { + + 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 IEnumerable.GetEnumerator() { + return new RingCollection.Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() { + return new RingCollection.Enumerator(this); + } + + private struct Enumerator : IEnumerator, IEnumerator { + + private RingCollection collection; + private int index; + + public Enumerator(RingCollection 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; + } + } + } +} diff -r 21504f47aedf -r 96263190189a GUI/MainForm.cs --- a/GUI/MainForm.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/GUI/MainForm.cs Sun Jun 19 12:41:18 2011 +0000 @@ -501,12 +501,11 @@ } private void MainForm_FormClosed(object sender, FormClosedEventArgs e) { - Visible = false; - SaveConfiguration(); - + Visible = false; systemTray.IsMainIconEnabled = false; timer.Enabled = false; computer.Close(); + SaveConfiguration(); systemTray.Dispose(); } diff -r 21504f47aedf -r 96263190189a GUI/PlotPanel.cs --- a/GUI/PlotPanel.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/GUI/PlotPanel.cs Sun Jun 19 12:41:18 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - 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 @@ foreach (ISensor sensor in temperatures) { IEnumerable 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 @@ 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 grid = new List(countTime + 1); for (int i = 0; i <= countTime; i++) { @@ -149,7 +155,6 @@ } protected override void OnPaint(PaintEventArgs e) { - now = DateTime.Now - new TimeSpan(0, 0, 4); List timeGrid = GetTimeGrid(); @@ -196,14 +201,18 @@ IEnumerable 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; + } } } } diff -r 21504f47aedf -r 96263190189a GUI/UserRadioGroup.cs --- a/GUI/UserRadioGroup.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/GUI/UserRadioGroup.cs Sun Jun 19 12:41:18 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - 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): diff -r 21504f47aedf -r 96263190189a Hardware/ATI/ATIGPU.cs --- a/Hardware/ATI/ATIGPU.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/ATI/ATIGPU.cs Sun Jun 19 12:41:18 2011 +0000 @@ -208,12 +208,13 @@ } } - public void Close() { + public override void Close() { this.fanControl.ControlModeChanged -= ControlModeChanged; this.fanControl.SoftwareControlValueChanged -= SoftwareControlValueChanged; RestoreDefaultFanSpeed(); + base.Close(); } } } diff -r 21504f47aedf -r 96263190189a Hardware/CPU/AMD10CPU.cs --- a/Hardware/CPU/AMD10CPU.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/CPU/AMD10CPU.cs Sun Jun 19 12:41:18 2011 +0000 @@ -348,10 +348,11 @@ } } - public override void Close() { + public override void Close() { if (temperatureStream != null) { temperatureStream.Close(); } + base.Close(); } } } diff -r 21504f47aedf -r 96263190189a Hardware/CPU/GenericCPU.cs --- a/Hardware/CPU/GenericCPU.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/CPU/GenericCPU.cs Sun Jun 19 12:41:18 2011 +0000 @@ -333,9 +333,5 @@ totalLoad.Value = cpuLoad.GetTotalLoad(); } } - - public virtual void Close() { - - } } } diff -r 21504f47aedf -r 96263190189a Hardware/HDD/HDD.cs --- a/Hardware/HDD/HDD.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/HDD/HDD.cs Sun Jun 19 12:41:18 2011 +0000 @@ -123,8 +123,9 @@ count++; count %= UPDATE_DIVIDER; } - public void Close() { + public override void Close() { SMART.CloseHandle(handle); + base.Close(); } public override void Traverse(IVisitor visitor) { diff -r 21504f47aedf -r 96263190189a Hardware/Hardware.cs --- a/Hardware/Hardware.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/Hardware.cs Sun Jun 19 12:41:18 2011 +0000 @@ -113,6 +113,13 @@ 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"); diff -r 21504f47aedf -r 96263190189a Hardware/Heatmaster/Heatmaster.cs --- a/Hardware/Heatmaster/Heatmaster.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/Heatmaster/Heatmaster.cs Sun Jun 19 12:41:18 2011 +0000 @@ -285,10 +285,11 @@ return r.ToString(); } - public void Close() { + public override void Close() { serialPort.Close(); serialPort.Dispose(); serialPort = null; + base.Close(); } public void Dispose() { diff -r 21504f47aedf -r 96263190189a Hardware/IHardware.cs --- a/Hardware/IHardware.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/IHardware.cs Sun Jun 19 12:41:18 2011 +0000 @@ -38,7 +38,7 @@ namespace OpenHardwareMonitor.Hardware { public delegate void SensorEventHandler(ISensor sensor); - + public enum HardwareType { Mainboard, SuperIO, diff -r 21504f47aedf -r 96263190189a Hardware/Mainboard/Mainboard.cs --- a/Hardware/Mainboard/Mainboard.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/Mainboard/Mainboard.cs Sun Jun 19 12:41:18 2011 +0000 @@ -47,7 +47,7 @@ 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 @@ 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 @@ public void Close() { if (lmSensors != null) lmSensors.Close(); + foreach (Hardware hardware in superIOHardware) + hardware.Close(); } public IHardware[] SubHardware { diff -r 21504f47aedf -r 96263190189a Hardware/Nvidia/NvidiaGroup.cs --- a/Hardware/Nvidia/NvidiaGroup.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/Nvidia/NvidiaGroup.cs Sun Jun 19 12:41:18 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - 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 @@ internal class NvidiaGroup : IGroup { - private readonly List hardware = new List(); + private readonly List hardware = new List(); private readonly StringBuilder report = new StringBuilder(); public NvidiaGroup(ISettings settings) { @@ -125,6 +125,9 @@ return report.ToString(); } - public void Close() { } + public void Close() { + foreach (Hardware gpu in hardware) + gpu.Close(); + } } } diff -r 21504f47aedf -r 96263190189a Hardware/Sensor.cs --- a/Hardware/Sensor.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/Sensor.cs Sun Jun 19 12:41:18 2011 +0000 @@ -16,7 +16,7 @@ The Initial Developer of the Original Code is Michael Möller . - 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 @@ private readonly int index; private readonly bool defaultHidden; private readonly SensorType sensorType; - private readonly IHardware hardware; + private readonly Hardware hardware; private readonly ReadOnlyArray parameters; private float? currentValue; private float? minValue; private float? maxValue; - private readonly Queue values = - new Queue(MAX_MINUTES * 15); + private readonly RingCollection + values = new RingCollection(); 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 @@ 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 @@ 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; } diff -r 21504f47aedf -r 96263190189a Hardware/TBalancer/TBalancer.cs --- a/Hardware/TBalancer/TBalancer.cs Sat Jun 04 13:27:11 2011 +0000 +++ b/Hardware/TBalancer/TBalancer.cs Sun Jun 19 12:41:18 2011 +0000 @@ -340,8 +340,9 @@ alternativeRequest.BeginInvoke(null, null); } - public void Close() { + public override void Close() { FTD2XX.FT_Close(handle); + base.Close(); } } diff -r 21504f47aedf -r 96263190189a OpenHardwareMonitorLib.csproj --- a/OpenHardwareMonitorLib.csproj Sat Jun 04 13:27:11 2011 +0000 +++ b/OpenHardwareMonitorLib.csproj Sun Jun 19 12:41:18 2011 +0000 @@ -56,6 +56,7 @@ +