Hardware/Sensor.cs
author moel.mich
Sun, 19 Jun 2011 12:41:18 +0000
changeset 298 96263190189a
parent 247 6dc755f1970e
child 314 d19c6b4d625e
permissions -rw-r--r--
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.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2011
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.Globalization;
    41 using System.IO;
    42 using System.IO.Compression;
    43 using OpenHardwareMonitor.Collections;
    44 
    45 namespace OpenHardwareMonitor.Hardware {
    46 
    47   internal class Sensor : ISensor {
    48 
    49     private readonly string defaultName;
    50     private string name;
    51     private readonly int index;
    52     private readonly bool defaultHidden;
    53     private readonly SensorType sensorType;
    54     private readonly Hardware hardware;
    55     private readonly ReadOnlyArray<IParameter> parameters;
    56     private float? currentValue;
    57     private float? minValue;
    58     private float? maxValue;
    59     private readonly RingCollection<SensorValue> 
    60       values = new RingCollection<SensorValue>();
    61     private readonly ISettings settings;
    62     private IControl control;
    63     
    64     private float sum;
    65     private int count;
    66    
    67     public Sensor(string name, int index, SensorType sensorType,
    68       Hardware hardware, ISettings settings) : 
    69       this(name, index, sensorType, hardware, null, settings) { }
    70 
    71     public Sensor(string name, int index, SensorType sensorType,
    72       Hardware hardware, ParameterDescription[] parameterDescriptions, 
    73       ISettings settings) :
    74       this(name, index, false, sensorType, hardware,
    75         parameterDescriptions, settings) { }
    76 
    77     public Sensor(string name, int index, bool defaultHidden, 
    78       SensorType sensorType, Hardware hardware, 
    79       ParameterDescription[] parameterDescriptions, ISettings settings) 
    80     {           
    81       this.index = index;
    82       this.defaultHidden = defaultHidden;
    83       this.sensorType = sensorType;
    84       this.hardware = hardware;
    85       Parameter[] parameters = new Parameter[parameterDescriptions == null ?
    86         0 : parameterDescriptions.Length];
    87       for (int i = 0; i < parameters.Length; i++ ) 
    88         parameters[i] = new Parameter(parameterDescriptions[i], this, settings);
    89       this.parameters = parameters;
    90 
    91       this.settings = settings;
    92       this.defaultName = name; 
    93       this.name = settings.GetValue(
    94         new Identifier(Identifier, "name").ToString(), name);
    95 
    96       GetSensorValuesFromSettings();
    97 
    98       hardware.Closing += delegate(IHardware h) {
    99         SetSensorValuesToSettings();
   100       };
   101     }
   102 
   103     private void SetSensorValuesToSettings() {
   104       using (MemoryStream m = new MemoryStream()) {
   105         using (GZipStream c = new GZipStream(m, CompressionMode.Compress))
   106         using (BinaryWriter writer = new BinaryWriter(c)) {
   107           foreach (SensorValue sensorValue in values) {
   108             writer.Write(sensorValue.Time.ToBinary());
   109             writer.Write(sensorValue.Value);
   110           }
   111         }
   112         settings.SetValue(new Identifier(Identifier, "values").ToString(),
   113            Convert.ToBase64String(m.ToArray()));
   114       }
   115     }
   116 
   117     private void GetSensorValuesFromSettings() {
   118       string s = settings.GetValue(
   119         new Identifier(Identifier, "values").ToString(), null);
   120 
   121       byte[] array = null;
   122       try {
   123         array = Convert.FromBase64String(s);
   124         using (MemoryStream m = new MemoryStream(array))
   125         using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
   126         using (BinaryReader reader = new BinaryReader(c)) {
   127           try {
   128             while (true) {
   129               DateTime time = DateTime.FromBinary(reader.ReadInt64());
   130               float value = reader.ReadSingle();
   131               AppendValue(value, time);
   132             }
   133           } catch (EndOfStreamException) { }
   134         }
   135       } catch { }
   136       if (values.Count > 0)
   137         AppendValue(float.NaN, DateTime.Now);
   138     }
   139 
   140     private void AppendValue(float value, DateTime time) {
   141       if (values.Count >= 2 && values.Last.Value == value && 
   142         values[values.Count - 2].Value == value) {
   143         values.Last = new SensorValue(value, time);
   144         return;
   145       } 
   146 
   147       values.Append(new SensorValue(value, time));
   148     }
   149 
   150     public IHardware Hardware {
   151       get { return hardware; }
   152     }
   153 
   154     public SensorType SensorType {
   155       get { return sensorType; }
   156     }
   157 
   158     public Identifier Identifier {
   159       get {
   160         return new Identifier(hardware.Identifier,
   161           sensorType.ToString().ToLowerInvariant(),
   162           index.ToString(CultureInfo.InvariantCulture));
   163       }
   164     }
   165 
   166     public string Name {
   167       get { 
   168         return name; 
   169       }
   170       set {
   171         if (!string.IsNullOrEmpty(value)) 
   172           name = value;          
   173         else 
   174           name = defaultName;
   175         settings.SetValue(new Identifier(Identifier, "name").ToString(), name);
   176       }
   177     }
   178 
   179     public int Index {
   180       get { return index; }
   181     }
   182 
   183     public bool IsDefaultHidden {
   184       get { return defaultHidden; }
   185     }
   186 
   187     public IReadOnlyArray<IParameter> Parameters {
   188       get { return parameters; }
   189     }
   190 
   191     public float? Value {
   192       get { 
   193         return currentValue; 
   194       }
   195       set {
   196         DateTime now = DateTime.Now;
   197         while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
   198           values.Remove();
   199 
   200         if (value.HasValue) {
   201           sum += value.Value;
   202           count++;
   203           if (count == 4) {
   204             AppendValue(sum / count, now);
   205             sum = 0;
   206             count = 0;
   207           }
   208         }
   209 
   210         this.currentValue = value;
   211         if (minValue > value || !minValue.HasValue)
   212           minValue = value;
   213         if (maxValue < value || !maxValue.HasValue)
   214           maxValue = value;
   215       }
   216     }
   217 
   218     public float? Min { get { return minValue; } }
   219     public float? Max { get { return maxValue; } }
   220 
   221     public void ResetMin() {
   222       minValue = null;
   223     }
   224 
   225     public void ResetMax() {
   226       maxValue = null;
   227     }
   228 
   229     public IEnumerable<SensorValue> Values {
   230       get { return values; }
   231     }    
   232 
   233     public void Accept(IVisitor visitor) {
   234       if (visitor == null)
   235         throw new ArgumentNullException("visitor");
   236       visitor.VisitSensor(this);
   237     }
   238 
   239     public void Traverse(IVisitor visitor) {
   240       foreach (IParameter parameter in parameters)
   241         parameter.Accept(visitor);
   242     }
   243 
   244     public IControl Control {
   245       get {
   246         return control;
   247       }
   248       internal set {
   249         this.control = value;
   250       }
   251     }
   252   }
   253 }