Hardware/Sensor.cs
author moel.mich
Sat, 14 Jul 2012 19:24:04 +0000
changeset 363 daa9590e1bee
parent 344 3145aadca3d2
child 365 a8a8ff22d959
permissions -rw-r--r--
Fixed Issue 269.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Collections.Generic;
    13 using System.Globalization;
    14 using System.IO;
    15 using System.IO.Compression;
    16 using OpenHardwareMonitor.Collections;
    17 
    18 namespace OpenHardwareMonitor.Hardware {
    19 
    20   internal class Sensor : ISensor {
    21 
    22     private readonly string defaultName;
    23     private string name;
    24     private readonly int index;
    25     private readonly bool defaultHidden;
    26     private readonly SensorType sensorType;
    27     private readonly Hardware hardware;
    28     private readonly ReadOnlyArray<IParameter> parameters;
    29     private float? currentValue;
    30     private float? minValue;
    31     private float? maxValue;
    32     private readonly RingCollection<SensorValue> 
    33       values = new RingCollection<SensorValue>();
    34     private readonly ISettings settings;
    35     private IControl control;
    36     
    37     private float sum;
    38     private int count;
    39    
    40     public Sensor(string name, int index, SensorType sensorType,
    41       Hardware hardware, ISettings settings) : 
    42       this(name, index, sensorType, hardware, null, settings) { }
    43 
    44     public Sensor(string name, int index, SensorType sensorType,
    45       Hardware hardware, ParameterDescription[] parameterDescriptions, 
    46       ISettings settings) :
    47       this(name, index, false, sensorType, hardware,
    48         parameterDescriptions, settings) { }
    49 
    50     public Sensor(string name, int index, bool defaultHidden, 
    51       SensorType sensorType, Hardware hardware, 
    52       ParameterDescription[] parameterDescriptions, ISettings settings) 
    53     {           
    54       this.index = index;
    55       this.defaultHidden = defaultHidden;
    56       this.sensorType = sensorType;
    57       this.hardware = hardware;
    58       Parameter[] parameters = new Parameter[parameterDescriptions == null ?
    59         0 : parameterDescriptions.Length];
    60       for (int i = 0; i < parameters.Length; i++ ) 
    61         parameters[i] = new Parameter(parameterDescriptions[i], this, settings);
    62       this.parameters = parameters;
    63 
    64       this.settings = settings;
    65       this.defaultName = name; 
    66       this.name = settings.GetValue(
    67         new Identifier(Identifier, "name").ToString(), name);
    68 
    69       GetSensorValuesFromSettings();      
    70 
    71       hardware.Closing += delegate(IHardware h) {
    72         SetSensorValuesToSettings();
    73       };
    74     }
    75 
    76     private void SetSensorValuesToSettings() {
    77       using (MemoryStream m = new MemoryStream()) {
    78         using (GZipStream c = new GZipStream(m, CompressionMode.Compress))
    79         using (BinaryWriter writer = new BinaryWriter(c)) {
    80           foreach (SensorValue sensorValue in values) {
    81             writer.Write(sensorValue.Time.ToBinary());
    82             writer.Write(sensorValue.Value);
    83           }
    84         }
    85         settings.SetValue(new Identifier(Identifier, "values").ToString(),
    86            Convert.ToBase64String(m.ToArray()));
    87       }
    88     }
    89 
    90     private void GetSensorValuesFromSettings() {
    91       string name = new Identifier(Identifier, "values").ToString();
    92       string s = settings.GetValue(name, null);
    93 
    94       try {
    95         byte[] array = Convert.FromBase64String(s);
    96         s = null;
    97         using (MemoryStream m = new MemoryStream(array))
    98         using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
    99         using (BinaryReader reader = new BinaryReader(c)) {
   100           try {
   101             while (true) {
   102               DateTime time = DateTime.FromBinary(reader.ReadInt64());
   103               float value = reader.ReadSingle();
   104               AppendValue(value, time);
   105             }
   106           } catch (EndOfStreamException) { }
   107         }
   108       } catch { }
   109       if (values.Count > 0)
   110         AppendValue(float.NaN, DateTime.UtcNow);
   111 
   112       // remove the value string from the settings to reduce memory usage
   113       settings.Remove(name);
   114     }
   115 
   116     private void AppendValue(float value, DateTime time) {
   117       if (values.Count >= 2 && values.Last.Value == value && 
   118         values[values.Count - 2].Value == value) {
   119         values.Last = new SensorValue(value, time);
   120         return;
   121       } 
   122 
   123       values.Append(new SensorValue(value, time));
   124     }
   125 
   126     public IHardware Hardware {
   127       get { return hardware; }
   128     }
   129 
   130     public SensorType SensorType {
   131       get { return sensorType; }
   132     }
   133 
   134     public Identifier Identifier {
   135       get {
   136         return new Identifier(hardware.Identifier,
   137           sensorType.ToString().ToLowerInvariant(),
   138           index.ToString(CultureInfo.InvariantCulture));
   139       }
   140     }
   141 
   142     public string Name {
   143       get { 
   144         return name; 
   145       }
   146       set {
   147         if (!string.IsNullOrEmpty(value)) 
   148           name = value;          
   149         else 
   150           name = defaultName;
   151         settings.SetValue(new Identifier(Identifier, "name").ToString(), name);
   152       }
   153     }
   154 
   155     public int Index {
   156       get { return index; }
   157     }
   158 
   159     public bool IsDefaultHidden {
   160       get { return defaultHidden; }
   161     }
   162 
   163     public IReadOnlyArray<IParameter> Parameters {
   164       get { return parameters; }
   165     }
   166 
   167     public float? Value {
   168       get { 
   169         return currentValue; 
   170       }
   171       set {
   172         DateTime now = DateTime.UtcNow;
   173         while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
   174           values.Remove();
   175 
   176         if (value.HasValue) {
   177           sum += value.Value;
   178           count++;
   179           if (count == 4) {
   180             AppendValue(sum / count, now);
   181             sum = 0;
   182             count = 0;
   183           }
   184         }
   185 
   186         this.currentValue = value;
   187         if (minValue > value || !minValue.HasValue)
   188           minValue = value;
   189         if (maxValue < value || !maxValue.HasValue)
   190           maxValue = value;
   191       }
   192     }
   193 
   194     public float? Min { get { return minValue; } }
   195     public float? Max { get { return maxValue; } }
   196 
   197     public void ResetMin() {
   198       minValue = null;
   199     }
   200 
   201     public void ResetMax() {
   202       maxValue = null;
   203     }
   204 
   205     public IEnumerable<SensorValue> Values {
   206       get { return values; }
   207     }    
   208 
   209     public void Accept(IVisitor visitor) {
   210       if (visitor == null)
   211         throw new ArgumentNullException("visitor");
   212       visitor.VisitSensor(this);
   213     }
   214 
   215     public void Traverse(IVisitor visitor) {
   216       foreach (IParameter parameter in parameters)
   217         parameter.Accept(visitor);
   218     }
   219 
   220     public IControl Control {
   221       get {
   222         return control;
   223       }
   224       internal set {
   225         this.control = value;
   226       }
   227     }
   228   }
   229 }