Improved the data compression for storing the recorded sensor values in the config file.
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/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Collections.Generic;
13 using System.Globalization;
15 using System.IO.Compression;
16 using OpenHardwareMonitor.Collections;
18 namespace OpenHardwareMonitor.Hardware {
20 internal class Sensor : ISensor {
22 private readonly string defaultName;
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;
40 public Sensor(string name, int index, SensorType sensorType,
41 Hardware hardware, ISettings settings) :
42 this(name, index, sensorType, hardware, null, settings) { }
44 public Sensor(string name, int index, SensorType sensorType,
45 Hardware hardware, ParameterDescription[] parameterDescriptions,
47 this(name, index, false, sensorType, hardware,
48 parameterDescriptions, settings) { }
50 public Sensor(string name, int index, bool defaultHidden,
51 SensorType sensorType, Hardware hardware,
52 ParameterDescription[] parameterDescriptions, ISettings settings)
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;
64 this.settings = settings;
65 this.defaultName = name;
66 this.name = settings.GetValue(
67 new Identifier(Identifier, "name").ToString(), name);
69 GetSensorValuesFromSettings();
71 hardware.Closing += delegate(IHardware h) {
72 SetSensorValuesToSettings();
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)) {
82 foreach (SensorValue sensorValue in values) {
83 long v = sensorValue.Time.ToBinary();
86 writer.Write(sensorValue.Value);
90 settings.SetValue(new Identifier(Identifier, "values").ToString(),
91 Convert.ToBase64String(m.ToArray()));
95 private void GetSensorValuesFromSettings() {
96 string name = new Identifier(Identifier, "values").ToString();
97 string s = settings.GetValue(name, null);
100 byte[] array = Convert.FromBase64String(s);
102 using (MemoryStream m = new MemoryStream(array))
103 using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
104 using (BinaryReader reader = new BinaryReader(c)) {
108 t += reader.ReadInt64();
109 DateTime time = DateTime.FromBinary(t);
110 float value = reader.ReadSingle();
111 AppendValue(value, time);
113 } catch (EndOfStreamException) { }
116 if (values.Count > 0)
117 AppendValue(float.NaN, DateTime.UtcNow);
119 // remove the value string from the settings to reduce memory usage
120 settings.Remove(name);
123 private void AppendValue(float value, DateTime time) {
124 if (values.Count >= 2 && values.Last.Value == value &&
125 values[values.Count - 2].Value == value) {
126 values.Last = new SensorValue(value, time);
130 values.Append(new SensorValue(value, time));
133 public IHardware Hardware {
134 get { return hardware; }
137 public SensorType SensorType {
138 get { return sensorType; }
141 public Identifier Identifier {
143 return new Identifier(hardware.Identifier,
144 sensorType.ToString().ToLowerInvariant(),
145 index.ToString(CultureInfo.InvariantCulture));
154 if (!string.IsNullOrEmpty(value))
158 settings.SetValue(new Identifier(Identifier, "name").ToString(), name);
163 get { return index; }
166 public bool IsDefaultHidden {
167 get { return defaultHidden; }
170 public IReadOnlyArray<IParameter> Parameters {
171 get { return parameters; }
174 public float? Value {
179 DateTime now = DateTime.UtcNow;
180 while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
183 if (value.HasValue) {
187 AppendValue(sum / count, now);
193 this.currentValue = value;
194 if (minValue > value || !minValue.HasValue)
196 if (maxValue < value || !maxValue.HasValue)
201 public float? Min { get { return minValue; } }
202 public float? Max { get { return maxValue; } }
204 public void ResetMin() {
208 public void ResetMax() {
212 public IEnumerable<SensorValue> Values {
213 get { return values; }
216 public void Accept(IVisitor visitor) {
218 throw new ArgumentNullException("visitor");
219 visitor.VisitSensor(this);
222 public void Traverse(IVisitor visitor) {
223 foreach (IParameter parameter in parameters)
224 parameter.Accept(visitor);
227 public IControl Control {
232 this.control = value;