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-2012 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 smart.EnableSmart(handle, index);
64 this.smartAttributes = new List<SmartAttribute>(smartAttributes);
66 string[] logicalDrives = smart.GetLogicalDrives(index);
67 List<DriveInfo> driveInfoList = new List<DriveInfo>(logicalDrives.Length);
68 foreach (string logicalDrive in logicalDrives) {
70 DriveInfo di = new DriveInfo(logicalDrive);
72 driveInfoList.Add(new DriveInfo(logicalDrive));
73 } catch (ArgumentException) { } catch (IOException) { }
75 driveInfos = driveInfoList.ToArray();
80 public static AbstractHarddrive CreateInstance(ISmart smart,
81 int driveIndex, ISettings settings)
83 IntPtr deviceHandle = smart.OpenDrive(driveIndex);
85 if (deviceHandle == smart.InvalidHandle)
89 string firmwareRevision;
90 bool nameValid = smart.ReadNameAndFirmwareRevision(deviceHandle,
91 driveIndex, out name, out firmwareRevision);
92 bool smartEnabled = smart.EnableSmart(deviceHandle, driveIndex);
94 DriveAttributeValue[] values = {};
96 values = smart.ReadSmartData(deviceHandle, driveIndex);
98 smart.CloseHandle(deviceHandle);
100 if (!nameValid || string.IsNullOrEmpty(name))
103 foreach (Type type in hddTypes) {
104 // get the array of name prefixes for the current type
105 NamePrefixAttribute[] namePrefixes = type.GetCustomAttributes(
106 typeof(NamePrefixAttribute), true) as NamePrefixAttribute[];
108 // get the array of the required SMART attributes for the current type
109 RequireSmartAttribute[] requiredAttributes = type.GetCustomAttributes(
110 typeof(RequireSmartAttribute), true) as RequireSmartAttribute[];
112 // check if all required attributes are present
113 bool allRequiredAttributesFound = true;
114 foreach (var requireAttribute in requiredAttributes) {
115 bool adttributeFound = false;
116 foreach (DriveAttributeValue value in values) {
117 if (value.Identifier == requireAttribute.AttributeId) {
118 adttributeFound = true;
122 if (!adttributeFound) {
123 allRequiredAttributesFound = false;
128 // if an attribute is missing, then try the next type
129 if (!allRequiredAttributesFound)
132 // check if there is a matching name prefix for this type
133 foreach (NamePrefixAttribute prefix in namePrefixes) {
134 if (name.StartsWith(prefix.Prefix, StringComparison.InvariantCulture))
135 return Activator.CreateInstance(type, smart, name, firmwareRevision,
136 driveIndex, settings) as AbstractHarddrive;
140 // no matching type has been found
144 private void CreateSensors() {
145 sensors = new Dictionary<SmartAttribute, Sensor>();
147 IList<Pair<SensorType, int>> sensorTypeAndChannels =
148 new List<Pair<SensorType, int>>();
150 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
152 foreach (SmartAttribute attribute in smartAttributes) {
153 if (!attribute.SensorType.HasValue)
157 foreach (DriveAttributeValue value in values) {
158 if (value.Identifier == attribute.Identifier) {
166 Pair<SensorType, int> pair = new Pair<SensorType, int>(
167 attribute.SensorType.Value, attribute.SensorChannel);
169 if (!sensorTypeAndChannels.Contains(pair)) {
170 Sensor sensor = new Sensor(attribute.Name,
171 attribute.SensorChannel, attribute.DefaultHiddenSensor,
172 attribute.SensorType.Value, this, attribute.ParameterDescriptions,
175 sensors.Add(attribute, sensor);
176 ActivateSensor(sensor);
177 sensorTypeAndChannels.Add(pair);
181 if (driveInfos.Length > 0) {
183 new Sensor("Used Space", 0, SensorType.Load, this, settings);
184 ActivateSensor(usageSensor);
188 public override HardwareType HardwareType {
189 get { return HardwareType.HDD; }
192 public virtual void UpdateAdditionalSensors(DriveAttributeValue[] values) {}
194 public override void Update() {
196 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
198 foreach (KeyValuePair<SmartAttribute, Sensor> keyValuePair in sensors) {
199 SmartAttribute attribute = keyValuePair.Key;
200 foreach (DriveAttributeValue value in values) {
201 if (value.Identifier == attribute.Identifier) {
202 Sensor sensor = keyValuePair.Value;
203 sensor.Value = attribute.ConvertValue(value, sensor.Parameters);
208 UpdateAdditionalSensors(values);
210 if (usageSensor != null) {
212 long totalFreeSpace = 0;
214 for (int i = 0; i < driveInfos.Length; i++) {
215 if (!driveInfos[i].IsReady)
218 totalSize += driveInfos[i].TotalSize;
219 totalFreeSpace += driveInfos[i].TotalFreeSpace;
220 } catch (IOException) { } catch (UnauthorizedAccessException) { }
223 usageSensor.Value = 100.0f - (100.0f * totalFreeSpace) / totalSize;
225 usageSensor.Value = null;
231 count %= UPDATE_DIVIDER;
234 public override string GetReport() {
235 StringBuilder r = new StringBuilder();
236 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
237 DriveThresholdValue[] thresholds =
238 smart.ReadSmartThresholds(handle, index);
240 if (values.Length > 0) {
241 r.AppendLine(this.GetType().Name);
243 r.AppendLine("Drive name: " + name);
244 r.AppendLine("Firmware version: " + firmwareRevision);
246 r.AppendFormat(CultureInfo.InvariantCulture,
247 " {0}{1}{2}{3}{4}{5}{6}{7}",
249 ("Description").PadRight(35),
250 ("Raw Value").PadRight(13),
251 ("Worst").PadRight(6),
252 ("Value").PadRight(6),
253 ("Thres").PadRight(6),
254 ("Physical").PadRight(8),
255 Environment.NewLine);
257 foreach (DriveAttributeValue value in values) {
258 if (value.Identifier == 0x00)
261 byte? threshold = null;
262 foreach (DriveThresholdValue t in thresholds) {
263 if (t.Identifier == value.Identifier) {
264 threshold = t.Threshold;
268 string description = "Unknown";
269 float? physical = null;
270 foreach (SmartAttribute a in smartAttributes) {
271 if (a.Identifier == value.Identifier) {
272 description = a.Name;
273 if (a.HasRawValueConversion | a.SensorType.HasValue)
274 physical = a.ConvertValue(value, null);
280 string raw = BitConverter.ToString(value.RawValue);
281 r.AppendFormat(CultureInfo.InvariantCulture,
282 " {0}{1}{2}{3}{4}{5}{6}{7}",
283 value.Identifier.ToString("X2").PadRight(3),
284 description.PadRight(35),
285 raw.Replace("-", "").PadRight(13),
286 value.WorstValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
287 value.AttrValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
288 (threshold.HasValue ? threshold.Value.ToString(
289 CultureInfo.InvariantCulture) : "-").PadRight(6),
290 (physical.HasValue ? physical.Value.ToString(
291 CultureInfo.InvariantCulture) : "-").PadRight(8),
292 Environment.NewLine);
297 foreach (DriveInfo di in driveInfos) {
298 r.AppendLine("Logical drive name: " + di.Name);
299 r.AppendLine("Format: " + di.DriveFormat);
300 r.AppendLine("Total size: " + di.TotalSize);
301 r.AppendLine("Total free space: " + di.TotalFreeSpace);
308 protected static float RawToInt(byte[] raw, byte value,
309 IReadOnlyArray<IParameter> parameters)
311 return (raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0];
314 public override void Close() {
315 smart.CloseHandle(handle);
319 public override void Traverse(IVisitor visitor) {
320 foreach (ISensor sensor in Sensors)
321 sensor.Accept(visitor);