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.
authormoel.mich
Sun, 19 Jun 2011 12:41:18 +0000
changeset 29896263190189a
parent 297 21504f47aedf
child 299 072989c22a87
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.
Collections/RingCollection.cs
GUI/MainForm.cs
GUI/PlotPanel.cs
GUI/UserRadioGroup.cs
Hardware/ATI/ATIGPU.cs
Hardware/CPU/AMD10CPU.cs
Hardware/CPU/GenericCPU.cs
Hardware/HDD/HDD.cs
Hardware/Hardware.cs
Hardware/Heatmaster/Heatmaster.cs
Hardware/IHardware.cs
Hardware/Mainboard/Mainboard.cs
Hardware/Nvidia/NvidiaGroup.cs
Hardware/Sensor.cs
Hardware/TBalancer/TBalancer.cs
OpenHardwareMonitorLib.csproj
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Collections/RingCollection.cs	Sun Jun 19 12:41:18 2011 +0000
     1.3 @@ -0,0 +1,235 @@
     1.4 +/*
     1.5 +  
     1.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     1.7 +
     1.8 +  The contents of this file are subject to the Mozilla Public License Version
     1.9 +  1.1 (the "License"); you may not use this file except in compliance with
    1.10 +  the License. You may obtain a copy of the License at
    1.11 + 
    1.12 +  http://www.mozilla.org/MPL/
    1.13 +
    1.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    1.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    1.16 +  for the specific language governing rights and limitations under the License.
    1.17 +
    1.18 +  The Original Code is the Open Hardware Monitor code.
    1.19 +
    1.20 +  The Initial Developer of the Original Code is 
    1.21 +  Michael Möller <m.moeller@gmx.ch>.
    1.22 +  Portions created by the Initial Developer are Copyright (C) 2011
    1.23 +  the Initial Developer. All Rights Reserved.
    1.24 +
    1.25 +  Contributor(s):
    1.26 +
    1.27 +  Alternatively, the contents of this file may be used under the terms of
    1.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    1.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    1.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    1.31 +  of those above. If you wish to allow use of your version of this file only
    1.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    1.33 +  use your version of this file under the terms of the MPL, indicate your
    1.34 +  decision by deleting the provisions above and replace them with the notice
    1.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    1.36 +  the provisions above, a recipient may use your version of this file under
    1.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    1.38 + 
    1.39 +*/
    1.40 +
    1.41 +using System;
    1.42 +using System.Collections;
    1.43 +using System.Collections.Generic;
    1.44 +
    1.45 +namespace OpenHardwareMonitor.Collections {
    1.46 +  public class RingCollection<T> : IEnumerable<T> {
    1.47 +
    1.48 +    private T[] array;
    1.49 +
    1.50 +    // first item of collection
    1.51 +    private int head;
    1.52 +
    1.53 +    // index after the last item of the collection
    1.54 +    private int tail;
    1.55 +
    1.56 +    // number of items in the collection
    1.57 +    private int size;
    1.58 +
    1.59 +    public RingCollection() : this(0) { }
    1.60 +
    1.61 +    public RingCollection(int capacity) {
    1.62 +      if (capacity < 0)
    1.63 +        throw new ArgumentOutOfRangeException("capacity");
    1.64 +      this.array = new T[capacity];
    1.65 +      this.head = 0; 
    1.66 +      this.tail = 0;
    1.67 +      this.size = 0;
    1.68 +    }
    1.69 +
    1.70 +    public int Capacity {
    1.71 +      get {
    1.72 +        return array.Length;
    1.73 +      }
    1.74 +      set {
    1.75 +        T[] newArray = new T[value];
    1.76 +        if (size > 0) {
    1.77 +          if (head < tail) {
    1.78 +            Array.Copy(array, head, newArray, 0, size);
    1.79 +          } else {
    1.80 +            Array.Copy(array, head, newArray, 0, array.Length - head);
    1.81 +            Array.Copy(array, 0, newArray, array.Length - head, tail);
    1.82 +          }
    1.83 +        }
    1.84 +        this.array = newArray;
    1.85 +        this.head = 0;
    1.86 +        this.tail = size == value ? 0 : size;
    1.87 +      }
    1.88 +    }
    1.89 +
    1.90 +    public void Clear() {
    1.91 +      
    1.92 +      // remove potential references 
    1.93 +      if (head < tail) {
    1.94 +        Array.Clear(array, head, size);
    1.95 +      } else {
    1.96 +        Array.Clear(array, 0, tail);
    1.97 +        Array.Clear(array, head, array.Length - head);
    1.98 +      }
    1.99 +
   1.100 +      this.head = 0;
   1.101 +      this.tail = 0;
   1.102 +      this.size = 0;
   1.103 +    }
   1.104 +
   1.105 +    public void Append(T item) {
   1.106 +      if (size == array.Length) {
   1.107 +        int newCapacity = array.Length * 3 / 2;
   1.108 +        if (newCapacity < array.Length + 8)
   1.109 +          newCapacity = array.Length + 8;
   1.110 +        Capacity = newCapacity;
   1.111 +      }
   1.112 +
   1.113 +      array[tail] = item;
   1.114 +      tail = tail + 1 == array.Length ? 0 : tail + 1;
   1.115 +      size++;
   1.116 +    }
   1.117 +
   1.118 +    public T Remove() {
   1.119 +      if (size == 0)
   1.120 +        throw new InvalidOperationException();
   1.121 +
   1.122 +      T result = array[head];
   1.123 +      array[head] = default(T);
   1.124 +      head = head + 1 == array.Length ? 0 : head + 1;
   1.125 +      size--;
   1.126 +
   1.127 +      return result;
   1.128 +    }
   1.129 +
   1.130 +    public int Count {
   1.131 +      get {
   1.132 +        return size;
   1.133 +      }
   1.134 +    }
   1.135 +
   1.136 +    public T this[int index] {
   1.137 +      get {
   1.138 +        if (index < 0 || index >= size)
   1.139 +          throw new IndexOutOfRangeException();
   1.140 +        int i = head + index;
   1.141 +        if (i >= array.Length)
   1.142 +          i -= array.Length;
   1.143 +        return array[i];
   1.144 +      }
   1.145 +      set {
   1.146 +        if (index < 0 || index >= size)
   1.147 +          throw new IndexOutOfRangeException();
   1.148 +        int i = head + index;
   1.149 +        if (i >= array.Length)
   1.150 +          i -= array.Length;
   1.151 +        array[i] = value;
   1.152 +      }
   1.153 +    }
   1.154 +
   1.155 +    public T First {
   1.156 +      get {
   1.157 +        if (size == 0)
   1.158 +          throw new InvalidOperationException();
   1.159 +        return array[head];
   1.160 +      }
   1.161 +      set {
   1.162 +        if (size == 0)
   1.163 +          throw new InvalidOperationException();
   1.164 +        array[head] = value;
   1.165 +      }
   1.166 +    }
   1.167 +
   1.168 +    public T Last {
   1.169 +      get {
   1.170 +        if (size == 0)
   1.171 +          throw new InvalidOperationException();
   1.172 +        return array[tail == 0 ? array.Length - 1 : tail - 1];
   1.173 +      }
   1.174 +      set {
   1.175 +        if (size == 0)
   1.176 +          throw new InvalidOperationException();
   1.177 +        array[tail == 0 ? array.Length - 1 : tail - 1] = value;
   1.178 +      }
   1.179 +    }
   1.180 +
   1.181 +    IEnumerator<T> IEnumerable<T>.GetEnumerator() {
   1.182 +      return new RingCollection<T>.Enumerator(this);
   1.183 +    }
   1.184 +
   1.185 +    IEnumerator IEnumerable.GetEnumerator() {
   1.186 +      return new RingCollection<T>.Enumerator(this);
   1.187 +    }
   1.188 +
   1.189 +    private struct Enumerator : IEnumerator<T>, IEnumerator {
   1.190 +
   1.191 +      private RingCollection<T> collection;
   1.192 +      private int index;
   1.193 +
   1.194 +      public Enumerator(RingCollection<T> collection) {
   1.195 +        this.collection = collection;
   1.196 +        this.index = -1;
   1.197 +      }
   1.198 +
   1.199 +      public void Dispose() {
   1.200 +        this.index = -2;
   1.201 +      }
   1.202 +
   1.203 +      public void Reset() {
   1.204 +        this.index = -1;
   1.205 +      }
   1.206 +
   1.207 +      public T Current {
   1.208 +        get {
   1.209 +          if (index < 0)
   1.210 +            throw new InvalidOperationException();
   1.211 +          return collection[index];
   1.212 +        }
   1.213 +      }
   1.214 +
   1.215 +      object IEnumerator.Current {
   1.216 +        get {
   1.217 +          if (index < 0)
   1.218 +            throw new InvalidOperationException();
   1.219 +          return collection[index];
   1.220 +        }
   1.221 +      }
   1.222 +
   1.223 +      public bool MoveNext() {
   1.224 +        if (index == -2)
   1.225 +          return false;
   1.226 +
   1.227 +        index++;
   1.228 +
   1.229 +        if (index == collection.size) {
   1.230 +          index = -2;
   1.231 +          return false;
   1.232 +        }
   1.233 +
   1.234 +        return true;
   1.235 +      }
   1.236 +    }
   1.237 +  }
   1.238 +}
     2.1 --- a/GUI/MainForm.cs	Sat Jun 04 13:27:11 2011 +0000
     2.2 +++ b/GUI/MainForm.cs	Sun Jun 19 12:41:18 2011 +0000
     2.3 @@ -501,12 +501,11 @@
     2.4      }
     2.5      
     2.6      private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
     2.7 -      Visible = false;
     2.8 -      SaveConfiguration();
     2.9 -
    2.10 +      Visible = false;      
    2.11        systemTray.IsMainIconEnabled = false;
    2.12        timer.Enabled = false;            
    2.13        computer.Close();
    2.14 +      SaveConfiguration();
    2.15        systemTray.Dispose();
    2.16      }
    2.17  
     3.1 --- a/GUI/PlotPanel.cs	Sat Jun 04 13:27:11 2011 +0000
     3.2 +++ b/GUI/PlotPanel.cs	Sun Jun 19 12:41:18 2011 +0000
     3.3 @@ -16,7 +16,7 @@
     3.4  
     3.5    The Initial Developer of the Original Code is 
     3.6    Michael Möller <m.moeller@gmx.ch>.
     3.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2010
     3.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2011
     3.9    the Initial Developer. All Rights Reserved.
    3.10  
    3.11    Contributor(s):
    3.12 @@ -88,10 +88,12 @@
    3.13        foreach (ISensor sensor in temperatures) {
    3.14          IEnumerable<SensorValue> values = sensor.Values;
    3.15          foreach (SensorValue value in values) {
    3.16 -          if (!minTempNullable.HasValue || minTempNullable > value.Value)
    3.17 -            minTempNullable = value.Value;
    3.18 -          if (!maxTempNullable.HasValue || maxTempNullable < value.Value)
    3.19 -            maxTempNullable = value.Value;
    3.20 +          if (!float.IsNaN(value.Value)) {
    3.21 +            if (!minTempNullable.HasValue || minTempNullable > value.Value)
    3.22 +              minTempNullable = value.Value;
    3.23 +            if (!maxTempNullable.HasValue || maxTempNullable < value.Value)
    3.24 +              maxTempNullable = value.Value;
    3.25 +          }
    3.26          }
    3.27        }
    3.28        if (!minTempNullable.HasValue) {
    3.29 @@ -140,6 +142,10 @@
    3.30          deltaTime += 2;
    3.31        while (deltaTime + 5 < maxTime && deltaTime < 100)
    3.32          deltaTime += 5;
    3.33 +      while (deltaTime + 50 < maxTime && deltaTime < 1000)
    3.34 +        deltaTime += 50;
    3.35 +      while (deltaTime + 100 < maxTime && deltaTime < 10000)
    3.36 +        deltaTime += 100;
    3.37  
    3.38        List<float> grid = new List<float>(countTime + 1);
    3.39        for (int i = 0; i <= countTime; i++) {
    3.40 @@ -149,7 +155,6 @@
    3.41      }
    3.42  
    3.43      protected override void OnPaint(PaintEventArgs e) {
    3.44 -
    3.45        now = DateTime.Now - new TimeSpan(0, 0, 4);
    3.46  
    3.47        List<float> timeGrid = GetTimeGrid();
    3.48 @@ -196,14 +201,18 @@
    3.49              IEnumerable<SensorValue> values = sensor.Values;
    3.50              PointF last = new PointF();
    3.51              bool first = true;
    3.52 -            foreach (SensorValue value in values) {
    3.53 -              PointF point = new PointF(
    3.54 -                  x0 + w - w * (float)(now - value.Time).TotalMinutes / deltaTime,
    3.55 -                  y0 + h - h * (value.Value - tempGrid[0]) / deltaTemp);
    3.56 -              if (!first)
    3.57 -                g.DrawLine(pen, last, point);
    3.58 -              last = point;
    3.59 -              first = false;
    3.60 +            foreach (SensorValue v in values) {
    3.61 +              if (!float.IsNaN(v.Value)) {
    3.62 +                PointF point = new PointF(
    3.63 +                    x0 + w - w * (float)(now - v.Time).TotalMinutes / deltaTime,
    3.64 +                    y0 + h - h * (v.Value - tempGrid[0]) / deltaTemp);
    3.65 +                if (!first) 
    3.66 +                  g.DrawLine(pen, last, point);                
    3.67 +                last = point;
    3.68 +                first = false;
    3.69 +              } else {
    3.70 +                first = true;
    3.71 +              }
    3.72              }
    3.73            }
    3.74          }
     4.1 --- a/GUI/UserRadioGroup.cs	Sat Jun 04 13:27:11 2011 +0000
     4.2 +++ b/GUI/UserRadioGroup.cs	Sun Jun 19 12:41:18 2011 +0000
     4.3 @@ -16,7 +16,7 @@
     4.4  
     4.5    The Initial Developer of the Original Code is 
     4.6    Michael Möller <m.moeller@gmx.ch>.
     4.7 -  Portions created by the Initial Developer are Copyright (C) 20011
     4.8 +  Portions created by the Initial Developer are Copyright (C) 2011
     4.9    the Initial Developer. All Rights Reserved.
    4.10  
    4.11    Contributor(s):
     5.1 --- a/Hardware/ATI/ATIGPU.cs	Sat Jun 04 13:27:11 2011 +0000
     5.2 +++ b/Hardware/ATI/ATIGPU.cs	Sun Jun 19 12:41:18 2011 +0000
     5.3 @@ -208,12 +208,13 @@
     5.4        }
     5.5      }
     5.6  
     5.7 -    public void Close() {
     5.8 +    public override void Close() {
     5.9        this.fanControl.ControlModeChanged -= ControlModeChanged;
    5.10        this.fanControl.SoftwareControlValueChanged -=
    5.11          SoftwareControlValueChanged;
    5.12  
    5.13        RestoreDefaultFanSpeed();
    5.14 +      base.Close();
    5.15      }
    5.16    }
    5.17  }
     6.1 --- a/Hardware/CPU/AMD10CPU.cs	Sat Jun 04 13:27:11 2011 +0000
     6.2 +++ b/Hardware/CPU/AMD10CPU.cs	Sun Jun 19 12:41:18 2011 +0000
     6.3 @@ -348,10 +348,11 @@
     6.4        }
     6.5      }
     6.6  
     6.7 -    public override void Close() {
     6.8 +    public override void Close() {      
     6.9        if (temperatureStream != null) {
    6.10          temperatureStream.Close();
    6.11        }
    6.12 +      base.Close();
    6.13      }
    6.14    }
    6.15  }
     7.1 --- a/Hardware/CPU/GenericCPU.cs	Sat Jun 04 13:27:11 2011 +0000
     7.2 +++ b/Hardware/CPU/GenericCPU.cs	Sun Jun 19 12:41:18 2011 +0000
     7.3 @@ -333,9 +333,5 @@
     7.4            totalLoad.Value = cpuLoad.GetTotalLoad();
     7.5        }
     7.6      }
     7.7 -
     7.8 -    public virtual void Close() {
     7.9 -
    7.10 -    }
    7.11    }
    7.12  }
     8.1 --- a/Hardware/HDD/HDD.cs	Sat Jun 04 13:27:11 2011 +0000
     8.2 +++ b/Hardware/HDD/HDD.cs	Sun Jun 19 12:41:18 2011 +0000
     8.3 @@ -123,8 +123,9 @@
     8.4        count++; count %= UPDATE_DIVIDER; 
     8.5      }
     8.6  
     8.7 -    public void Close() {
     8.8 +    public override void Close() {
     8.9        SMART.CloseHandle(handle);
    8.10 +      base.Close();
    8.11      }
    8.12  
    8.13      public override void Traverse(IVisitor visitor) {
     9.1 --- a/Hardware/Hardware.cs	Sat Jun 04 13:27:11 2011 +0000
     9.2 +++ b/Hardware/Hardware.cs	Sun Jun 19 12:41:18 2011 +0000
     9.3 @@ -113,6 +113,13 @@
     9.4  
     9.5      public abstract void Update();
     9.6  
     9.7 +    public event HardwareEventHandler Closing;
     9.8 +
     9.9 +    public virtual void Close() {
    9.10 +      if (Closing != null)
    9.11 +        Closing(this);
    9.12 +    }
    9.13 +
    9.14      public void Accept(IVisitor visitor) {
    9.15        if (visitor == null)
    9.16          throw new ArgumentNullException("visitor");
    10.1 --- a/Hardware/Heatmaster/Heatmaster.cs	Sat Jun 04 13:27:11 2011 +0000
    10.2 +++ b/Hardware/Heatmaster/Heatmaster.cs	Sun Jun 19 12:41:18 2011 +0000
    10.3 @@ -285,10 +285,11 @@
    10.4        return r.ToString();
    10.5      }
    10.6  
    10.7 -    public void Close() {
    10.8 +    public override void Close() {
    10.9        serialPort.Close();
   10.10        serialPort.Dispose();
   10.11        serialPort = null;
   10.12 +      base.Close();
   10.13      }
   10.14  
   10.15      public void Dispose() {
    11.1 --- a/Hardware/IHardware.cs	Sat Jun 04 13:27:11 2011 +0000
    11.2 +++ b/Hardware/IHardware.cs	Sun Jun 19 12:41:18 2011 +0000
    11.3 @@ -38,7 +38,7 @@
    11.4  namespace OpenHardwareMonitor.Hardware {
    11.5  
    11.6    public delegate void SensorEventHandler(ISensor sensor);
    11.7 -
    11.8 +  
    11.9    public enum HardwareType {
   11.10      Mainboard,
   11.11      SuperIO,
    12.1 --- a/Hardware/Mainboard/Mainboard.cs	Sat Jun 04 13:27:11 2011 +0000
    12.2 +++ b/Hardware/Mainboard/Mainboard.cs	Sun Jun 19 12:41:18 2011 +0000
    12.3 @@ -47,7 +47,7 @@
    12.4      private readonly ISettings settings;
    12.5      private readonly LPCIO lpcio;
    12.6      private readonly LMSensors lmSensors;
    12.7 -    private readonly IHardware[] superIOHardware;
    12.8 +    private readonly Hardware[] superIOHardware;
    12.9  
   12.10      public Mainboard(ISettings settings) {
   12.11        this.settings = settings;
   12.12 @@ -80,7 +80,7 @@
   12.13          superIO = lpcio.SuperIO;
   12.14        }
   12.15        
   12.16 -      superIOHardware = new IHardware[superIO.Length];
   12.17 +      superIOHardware = new Hardware[superIO.Length];
   12.18        for (int i = 0; i < superIO.Length; i++)
   12.19          superIOHardware[i] = new SuperIOHardware(this, superIO[i], 
   12.20            smbios.Board != null ? smbios.Board.Manufacturer : 
   12.21 @@ -132,6 +132,8 @@
   12.22      public void Close() {
   12.23        if (lmSensors != null)
   12.24          lmSensors.Close();
   12.25 +      foreach (Hardware hardware in superIOHardware)
   12.26 +        hardware.Close();
   12.27      }
   12.28  
   12.29      public IHardware[] SubHardware {
    13.1 --- a/Hardware/Nvidia/NvidiaGroup.cs	Sat Jun 04 13:27:11 2011 +0000
    13.2 +++ b/Hardware/Nvidia/NvidiaGroup.cs	Sun Jun 19 12:41:18 2011 +0000
    13.3 @@ -16,7 +16,7 @@
    13.4  
    13.5    The Initial Developer of the Original Code is 
    13.6    Michael Möller <m.moeller@gmx.ch>.
    13.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2010
    13.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2011
    13.9    the Initial Developer. All Rights Reserved.
   13.10  
   13.11    Contributor(s):
   13.12 @@ -43,7 +43,7 @@
   13.13  
   13.14    internal class NvidiaGroup : IGroup {
   13.15     
   13.16 -    private readonly List<IHardware> hardware = new List<IHardware>();
   13.17 +    private readonly List<Hardware> hardware = new List<Hardware>();
   13.18      private readonly StringBuilder report = new StringBuilder();
   13.19  
   13.20      public NvidiaGroup(ISettings settings) {
   13.21 @@ -125,6 +125,9 @@
   13.22        return report.ToString();
   13.23      }
   13.24  
   13.25 -    public void Close() { }
   13.26 +    public void Close() {
   13.27 +      foreach (Hardware gpu in hardware)
   13.28 +        gpu.Close();      
   13.29 +    }
   13.30    }
   13.31  }
    14.1 --- a/Hardware/Sensor.cs	Sat Jun 04 13:27:11 2011 +0000
    14.2 +++ b/Hardware/Sensor.cs	Sun Jun 19 12:41:18 2011 +0000
    14.3 @@ -16,7 +16,7 @@
    14.4  
    14.5    The Initial Developer of the Original Code is 
    14.6    Michael Möller <m.moeller@gmx.ch>.
    14.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2010
    14.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2011
    14.9    the Initial Developer. All Rights Reserved.
   14.10  
   14.11    Contributor(s):
   14.12 @@ -38,6 +38,8 @@
   14.13  using System;
   14.14  using System.Collections.Generic;
   14.15  using System.Globalization;
   14.16 +using System.IO;
   14.17 +using System.IO.Compression;
   14.18  using OpenHardwareMonitor.Collections;
   14.19  
   14.20  namespace OpenHardwareMonitor.Hardware {
   14.21 @@ -49,33 +51,31 @@
   14.22      private readonly int index;
   14.23      private readonly bool defaultHidden;
   14.24      private readonly SensorType sensorType;
   14.25 -    private readonly IHardware hardware;
   14.26 +    private readonly Hardware hardware;
   14.27      private readonly ReadOnlyArray<IParameter> parameters;
   14.28      private float? currentValue;
   14.29      private float? minValue;
   14.30      private float? maxValue;
   14.31 -    private readonly Queue<SensorValue> values =
   14.32 -      new Queue<SensorValue>(MAX_MINUTES * 15);
   14.33 +    private readonly RingCollection<SensorValue> 
   14.34 +      values = new RingCollection<SensorValue>();
   14.35      private readonly ISettings settings;
   14.36      private IControl control;
   14.37      
   14.38      private float sum;
   14.39      private int count;
   14.40 -
   14.41 -    private const int MAX_MINUTES = 120;
   14.42     
   14.43      public Sensor(string name, int index, SensorType sensorType,
   14.44 -      IHardware hardware, ISettings settings) : 
   14.45 +      Hardware hardware, ISettings settings) : 
   14.46        this(name, index, sensorType, hardware, null, settings) { }
   14.47  
   14.48      public Sensor(string name, int index, SensorType sensorType,
   14.49 -      IHardware hardware, ParameterDescription[] parameterDescriptions, 
   14.50 +      Hardware hardware, ParameterDescription[] parameterDescriptions, 
   14.51        ISettings settings) :
   14.52        this(name, index, false, sensorType, hardware,
   14.53          parameterDescriptions, settings) { }
   14.54  
   14.55      public Sensor(string name, int index, bool defaultHidden, 
   14.56 -      SensorType sensorType, IHardware hardware, 
   14.57 +      SensorType sensorType, Hardware hardware, 
   14.58        ParameterDescription[] parameterDescriptions, ISettings settings) 
   14.59      {           
   14.60        this.index = index;
   14.61 @@ -92,6 +92,59 @@
   14.62        this.defaultName = name; 
   14.63        this.name = settings.GetValue(
   14.64          new Identifier(Identifier, "name").ToString(), name);
   14.65 +
   14.66 +      GetSensorValuesFromSettings();
   14.67 +
   14.68 +      hardware.Closing += delegate(IHardware h) {
   14.69 +        SetSensorValuesToSettings();
   14.70 +      };
   14.71 +    }
   14.72 +
   14.73 +    private void SetSensorValuesToSettings() {
   14.74 +      using (MemoryStream m = new MemoryStream()) {
   14.75 +        using (GZipStream c = new GZipStream(m, CompressionMode.Compress))
   14.76 +        using (BinaryWriter writer = new BinaryWriter(c)) {
   14.77 +          foreach (SensorValue sensorValue in values) {
   14.78 +            writer.Write(sensorValue.Time.ToBinary());
   14.79 +            writer.Write(sensorValue.Value);
   14.80 +          }
   14.81 +        }
   14.82 +        settings.SetValue(new Identifier(Identifier, "values").ToString(),
   14.83 +           Convert.ToBase64String(m.ToArray()));
   14.84 +      }
   14.85 +    }
   14.86 +
   14.87 +    private void GetSensorValuesFromSettings() {
   14.88 +      string s = settings.GetValue(
   14.89 +        new Identifier(Identifier, "values").ToString(), null);
   14.90 +
   14.91 +      byte[] array = null;
   14.92 +      try {
   14.93 +        array = Convert.FromBase64String(s);
   14.94 +        using (MemoryStream m = new MemoryStream(array))
   14.95 +        using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
   14.96 +        using (BinaryReader reader = new BinaryReader(c)) {
   14.97 +          try {
   14.98 +            while (true) {
   14.99 +              DateTime time = DateTime.FromBinary(reader.ReadInt64());
  14.100 +              float value = reader.ReadSingle();
  14.101 +              AppendValue(value, time);
  14.102 +            }
  14.103 +          } catch (EndOfStreamException) { }
  14.104 +        }
  14.105 +      } catch { }
  14.106 +      if (values.Count > 0)
  14.107 +        AppendValue(float.NaN, DateTime.Now);
  14.108 +    }
  14.109 +
  14.110 +    private void AppendValue(float value, DateTime time) {
  14.111 +      if (values.Count >= 2 && values.Last.Value == value && 
  14.112 +        values[values.Count - 2].Value == value) {
  14.113 +        values.Last = new SensorValue(value, time);
  14.114 +        return;
  14.115 +      } 
  14.116 +
  14.117 +      values.Append(new SensorValue(value, time));
  14.118      }
  14.119  
  14.120      public IHardware Hardware {
  14.121 @@ -140,15 +193,15 @@
  14.122          return currentValue; 
  14.123        }
  14.124        set {
  14.125 -        while (values.Count > 0 && 
  14.126 -          (DateTime.Now - values.Peek().Time).TotalMinutes > MAX_MINUTES)
  14.127 -          values.Dequeue();
  14.128 +        DateTime now = DateTime.Now;
  14.129 +        while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
  14.130 +          values.Remove();
  14.131  
  14.132          if (value.HasValue) {
  14.133            sum += value.Value;
  14.134            count++;
  14.135            if (count == 4) {
  14.136 -            values.Enqueue(new SensorValue(sum / count, DateTime.Now));
  14.137 +            AppendValue(sum / count, now);
  14.138              sum = 0;
  14.139              count = 0;
  14.140            }
    15.1 --- a/Hardware/TBalancer/TBalancer.cs	Sat Jun 04 13:27:11 2011 +0000
    15.2 +++ b/Hardware/TBalancer/TBalancer.cs	Sun Jun 19 12:41:18 2011 +0000
    15.3 @@ -340,8 +340,9 @@
    15.4        alternativeRequest.BeginInvoke(null, null);
    15.5      }
    15.6  
    15.7 -    public void Close() {
    15.8 +    public override void Close() {
    15.9        FTD2XX.FT_Close(handle);
   15.10 +      base.Close();
   15.11      }
   15.12  
   15.13    }
    16.1 --- a/OpenHardwareMonitorLib.csproj	Sat Jun 04 13:27:11 2011 +0000
    16.2 +++ b/OpenHardwareMonitorLib.csproj	Sun Jun 19 12:41:18 2011 +0000
    16.3 @@ -56,6 +56,7 @@
    16.4      <Reference Include="System.Management" />
    16.5    </ItemGroup>
    16.6    <ItemGroup>
    16.7 +    <Compile Include="Collections\RingCollection.cs" />
    16.8      <Compile Include="Hardware\ATI\ADL.cs" />
    16.9      <Compile Include="Hardware\ATI\ATIGPU.cs" />
   16.10      <Compile Include="Hardware\ATI\ATIGroup.cs" />