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