Hardware/Sensor.cs
author moel.mich
Sun, 21 Jul 2013 14:17:11 +0000
changeset 413 362c5e77197d
parent 365 a8a8ff22d959
permissions -rw-r--r--
Added experimental support for the Nuvoton NCT6791D super I/O chip.
     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-2012 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 (BufferedStream b = new BufferedStream(c, 65536))
    80         using (BinaryWriter writer = new BinaryWriter(b)) {
    81           long t = 0;
    82           foreach (SensorValue sensorValue in values) {
    83             long v = sensorValue.Time.ToBinary();
    84             writer.Write(v - t);
    85             t = v;
    86             writer.Write(sensorValue.Value);
    87           }
    88           writer.Flush();
    89         }
    90         settings.SetValue(new Identifier(Identifier, "values").ToString(),
    91           Convert.ToBase64String(m.ToArray()));
    92       }
    93     }
    94 
    95     private void GetSensorValuesFromSettings() {
    96       string name = new Identifier(Identifier, "values").ToString();
    97       string s = settings.GetValue(name, null);
    98 
    99       try {
   100         byte[] array = Convert.FromBase64String(s);
   101         s = null;
   102         DateTime now = DateTime.UtcNow;
   103         using (MemoryStream m = new MemoryStream(array))
   104         using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
   105         using (BinaryReader reader = new BinaryReader(c)) {
   106           try {
   107             long t = 0;
   108             while (true) {
   109               t += reader.ReadInt64();
   110               DateTime time = DateTime.FromBinary(t);
   111               if (time > now)
   112                 break;
   113               float value = reader.ReadSingle();
   114               AppendValue(value, time);
   115             }
   116           } catch (EndOfStreamException) { }
   117         }
   118       } catch { }
   119       if (values.Count > 0)
   120         AppendValue(float.NaN, DateTime.UtcNow);
   121 
   122       // remove the value string from the settings to reduce memory usage
   123       settings.Remove(name);
   124     }
   125 
   126     private void AppendValue(float value, DateTime time) {
   127       if (values.Count >= 2 && values.Last.Value == value && 
   128         values[values.Count - 2].Value == value) {
   129         values.Last = new SensorValue(value, time);
   130         return;
   131       } 
   132 
   133       values.Append(new SensorValue(value, time));
   134     }
   135 
   136     public IHardware Hardware {
   137       get { return hardware; }
   138     }
   139 
   140     public SensorType SensorType {
   141       get { return sensorType; }
   142     }
   143 
   144     public Identifier Identifier {
   145       get {
   146         return new Identifier(hardware.Identifier,
   147           sensorType.ToString().ToLowerInvariant(),
   148           index.ToString(CultureInfo.InvariantCulture));
   149       }
   150     }
   151 
   152     public string Name {
   153       get { 
   154         return name; 
   155       }
   156       set {
   157         if (!string.IsNullOrEmpty(value)) 
   158           name = value;          
   159         else 
   160           name = defaultName;
   161         settings.SetValue(new Identifier(Identifier, "name").ToString(), name);
   162       }
   163     }
   164 
   165     public int Index {
   166       get { return index; }
   167     }
   168 
   169     public bool IsDefaultHidden {
   170       get { return defaultHidden; }
   171     }
   172 
   173     public IReadOnlyArray<IParameter> Parameters {
   174       get { return parameters; }
   175     }
   176 
   177     public float? Value {
   178       get { 
   179         return currentValue; 
   180       }
   181       set {
   182         DateTime now = DateTime.UtcNow;
   183         while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
   184           values.Remove();
   185 
   186         if (value.HasValue) {
   187           sum += value.Value;
   188           count++;
   189           if (count == 4) {
   190             AppendValue(sum / count, now);
   191             sum = 0;
   192             count = 0;
   193           }
   194         }
   195 
   196         this.currentValue = value;
   197         if (minValue > value || !minValue.HasValue)
   198           minValue = value;
   199         if (maxValue < value || !maxValue.HasValue)
   200           maxValue = value;
   201       }
   202     }
   203 
   204     public float? Min { get { return minValue; } }
   205     public float? Max { get { return maxValue; } }
   206 
   207     public void ResetMin() {
   208       minValue = null;
   209     }
   210 
   211     public void ResetMax() {
   212       maxValue = null;
   213     }
   214 
   215     public IEnumerable<SensorValue> Values {
   216       get { return values; }
   217     }    
   218 
   219     public void Accept(IVisitor visitor) {
   220       if (visitor == null)
   221         throw new ArgumentNullException("visitor");
   222       visitor.VisitSensor(this);
   223     }
   224 
   225     public void Traverse(IVisitor visitor) {
   226       foreach (IParameter parameter in parameters)
   227         parameter.Accept(visitor);
   228     }
   229 
   230     public IControl Control {
   231       get {
   232         return control;
   233       }
   234       internal set {
   235         this.control = value;
   236       }
   237     }
   238   }
   239 }