Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
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-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
8 Copyright (C) 2010 Paul Werelds
9 Copyright (C) 2011 Roland Reinl <roland-reinl@gmx.de>
14 using System.Collections.Generic;
15 using System.Globalization;
18 using OpenHardwareMonitor.Collections;
20 namespace OpenHardwareMonitor.Hardware.HDD {
21 internal abstract class AbstractHarddrive : Hardware {
23 private const int UPDATE_DIVIDER = 30; // update only every 30s
25 // array of all harddrive types, matching type is searched in this order
26 private static Type[] hddTypes = {
33 typeof(GenericHarddisk)
36 private string firmwareRevision;
37 private readonly ISmart smart;
39 private readonly IntPtr handle;
40 private readonly int index;
43 private IList<SmartAttribute> smartAttributes;
44 private IDictionary<SmartAttribute, Sensor> sensors;
46 private DriveInfo[] driveInfos;
47 private Sensor usageSensor;
49 protected AbstractHarddrive(ISmart smart, string name,
50 string firmwareRevision, int index,
51 IEnumerable<SmartAttribute> smartAttributes, ISettings settings)
52 : base(name, new Identifier("hdd",
53 index.ToString(CultureInfo.InvariantCulture)), settings)
55 this.firmwareRevision = firmwareRevision;
57 handle = smart.OpenDrive(index);
59 if (handle != smart.InvalidHandle)
60 smart.EnableSmart(handle, index);
65 this.smartAttributes = new List<SmartAttribute>(smartAttributes);
67 string[] logicalDrives = smart.GetLogicalDrives(index);
68 List<DriveInfo> driveInfoList = new List<DriveInfo>(logicalDrives.Length);
69 foreach (string logicalDrive in logicalDrives) {
71 DriveInfo di = new DriveInfo(logicalDrive);
73 driveInfoList.Add(new DriveInfo(logicalDrive));
74 } catch (ArgumentException) {
75 } catch (IOException) {
76 } catch (UnauthorizedAccessException) {
79 driveInfos = driveInfoList.ToArray();
84 public static AbstractHarddrive CreateInstance(ISmart smart,
85 int driveIndex, ISettings settings)
87 IntPtr deviceHandle = smart.OpenDrive(driveIndex);
90 string firmwareRevision = null;
91 DriveAttributeValue[] values = { };
93 if (deviceHandle != smart.InvalidHandle) {
94 bool nameValid = smart.ReadNameAndFirmwareRevision(deviceHandle,
95 driveIndex, out name, out firmwareRevision);
96 bool smartEnabled = smart.EnableSmart(deviceHandle, driveIndex);
99 values = smart.ReadSmartData(deviceHandle, driveIndex);
101 smart.CloseHandle(deviceHandle);
105 firmwareRevision = null;
108 string[] logicalDrives = smart.GetLogicalDrives(driveIndex);
109 if (logicalDrives == null || logicalDrives.Length == 0)
112 bool hasNonZeroSizeDrive = false;
113 foreach (string logicalDrive in logicalDrives) {
115 DriveInfo di = new DriveInfo(logicalDrive);
116 if (di.TotalSize > 0) {
117 hasNonZeroSizeDrive = true;
120 } catch (ArgumentException) {
121 } catch (IOException) {
122 } catch (UnauthorizedAccessException) {
126 if (!hasNonZeroSizeDrive)
130 if (string.IsNullOrEmpty(name))
131 name = "Generic Hard Disk";
133 if (string.IsNullOrEmpty(firmwareRevision))
134 firmwareRevision = "Unknown";
136 foreach (Type type in hddTypes) {
137 // get the array of name prefixes for the current type
138 NamePrefixAttribute[] namePrefixes = type.GetCustomAttributes(
139 typeof(NamePrefixAttribute), true) as NamePrefixAttribute[];
141 // get the array of the required SMART attributes for the current type
142 RequireSmartAttribute[] requiredAttributes = type.GetCustomAttributes(
143 typeof(RequireSmartAttribute), true) as RequireSmartAttribute[];
145 // check if all required attributes are present
146 bool allRequiredAttributesFound = true;
147 foreach (var requireAttribute in requiredAttributes) {
148 bool adttributeFound = false;
149 foreach (DriveAttributeValue value in values) {
150 if (value.Identifier == requireAttribute.AttributeId) {
151 adttributeFound = true;
155 if (!adttributeFound) {
156 allRequiredAttributesFound = false;
161 // if an attribute is missing, then try the next type
162 if (!allRequiredAttributesFound)
165 // check if there is a matching name prefix for this type
166 foreach (NamePrefixAttribute prefix in namePrefixes) {
167 if (name.StartsWith(prefix.Prefix, StringComparison.InvariantCulture))
168 return Activator.CreateInstance(type, smart, name, firmwareRevision,
169 driveIndex, settings) as AbstractHarddrive;
173 // no matching type has been found
177 private void CreateSensors() {
178 sensors = new Dictionary<SmartAttribute, Sensor>();
180 if (handle != smart.InvalidHandle) {
181 IList<Pair<SensorType, int>> sensorTypeAndChannels =
182 new List<Pair<SensorType, int>>();
184 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
186 foreach (SmartAttribute attribute in smartAttributes) {
187 if (!attribute.SensorType.HasValue)
191 foreach (DriveAttributeValue value in values) {
192 if (value.Identifier == attribute.Identifier) {
200 Pair<SensorType, int> pair = new Pair<SensorType, int>(
201 attribute.SensorType.Value, attribute.SensorChannel);
203 if (!sensorTypeAndChannels.Contains(pair)) {
204 Sensor sensor = new Sensor(attribute.Name,
205 attribute.SensorChannel, attribute.DefaultHiddenSensor,
206 attribute.SensorType.Value, this, attribute.ParameterDescriptions,
209 sensors.Add(attribute, sensor);
210 ActivateSensor(sensor);
211 sensorTypeAndChannels.Add(pair);
216 if (driveInfos.Length > 0) {
218 new Sensor("Used Space", 0, SensorType.Load, this, settings);
219 ActivateSensor(usageSensor);
223 public override HardwareType HardwareType {
224 get { return HardwareType.HDD; }
227 public virtual void UpdateAdditionalSensors(DriveAttributeValue[] values) {}
229 public override void Update() {
231 if (handle != smart.InvalidHandle) {
232 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
234 foreach (KeyValuePair<SmartAttribute, Sensor> keyValuePair in sensors)
236 SmartAttribute attribute = keyValuePair.Key;
237 foreach (DriveAttributeValue value in values) {
238 if (value.Identifier == attribute.Identifier) {
239 Sensor sensor = keyValuePair.Value;
240 sensor.Value = attribute.ConvertValue(value, sensor.Parameters);
245 UpdateAdditionalSensors(values);
248 if (usageSensor != null) {
250 long totalFreeSpace = 0;
252 for (int i = 0; i < driveInfos.Length; i++) {
253 if (!driveInfos[i].IsReady)
256 totalSize += driveInfos[i].TotalSize;
257 totalFreeSpace += driveInfos[i].TotalFreeSpace;
258 } catch (IOException) { } catch (UnauthorizedAccessException) { }
261 usageSensor.Value = 100.0f - (100.0f * totalFreeSpace) / totalSize;
263 usageSensor.Value = null;
269 count %= UPDATE_DIVIDER;
272 public override string GetReport() {
273 StringBuilder r = new StringBuilder();
275 r.AppendLine(this.GetType().Name);
277 r.AppendLine("Drive name: " + name);
278 r.AppendLine("Firmware version: " + firmwareRevision);
281 if (handle != smart.InvalidHandle) {
282 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
283 DriveThresholdValue[] thresholds =
284 smart.ReadSmartThresholds(handle, index);
286 if (values.Length > 0) {
287 r.AppendFormat(CultureInfo.InvariantCulture,
288 " {0}{1}{2}{3}{4}{5}{6}{7}",
290 ("Description").PadRight(35),
291 ("Raw Value").PadRight(13),
292 ("Worst").PadRight(6),
293 ("Value").PadRight(6),
294 ("Thres").PadRight(6),
295 ("Physical").PadRight(8),
296 Environment.NewLine);
298 foreach (DriveAttributeValue value in values) {
299 if (value.Identifier == 0x00)
302 byte? threshold = null;
303 foreach (DriveThresholdValue t in thresholds) {
304 if (t.Identifier == value.Identifier) {
305 threshold = t.Threshold;
309 string description = "Unknown";
310 float? physical = null;
311 foreach (SmartAttribute a in smartAttributes) {
312 if (a.Identifier == value.Identifier) {
313 description = a.Name;
314 if (a.HasRawValueConversion | a.SensorType.HasValue)
315 physical = a.ConvertValue(value, null);
321 string raw = BitConverter.ToString(value.RawValue);
322 r.AppendFormat(CultureInfo.InvariantCulture,
323 " {0}{1}{2}{3}{4}{5}{6}{7}",
324 value.Identifier.ToString("X2").PadRight(3),
325 description.PadRight(35),
326 raw.Replace("-", "").PadRight(13),
327 value.WorstValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
328 value.AttrValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
329 (threshold.HasValue ? threshold.Value.ToString(
330 CultureInfo.InvariantCulture) : "-").PadRight(6),
331 (physical.HasValue ? physical.Value.ToString(
332 CultureInfo.InvariantCulture) : "-").PadRight(8),
333 Environment.NewLine);
339 foreach (DriveInfo di in driveInfos) {
343 r.AppendLine("Logical drive name: " + di.Name);
344 r.AppendLine("Format: " + di.DriveFormat);
345 r.AppendLine("Total size: " + di.TotalSize);
346 r.AppendLine("Total free space: " + di.TotalFreeSpace);
348 } catch (IOException) { } catch (UnauthorizedAccessException) { }
354 protected static float RawToInt(byte[] raw, byte value,
355 IReadOnlyArray<IParameter> parameters)
357 return (raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0];
360 public override void Close() {
361 if (handle != smart.InvalidHandle)
362 smart.CloseHandle(handle);
367 public override void Traverse(IVisitor visitor) {
368 foreach (ISensor sensor in Sensors)
369 sensor.Accept(visitor);