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.
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) 2010-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Globalization;
14 using System.IO.Ports;
16 using System.Text.RegularExpressions;
17 using System.Threading;
19 namespace OpenHardwareMonitor.Hardware.Heatmaster {
20 internal class Heatmaster : Hardware, IDisposable {
22 private readonly string portName;
23 private SerialPort serialPort;
25 private readonly int hardwareRevision;
26 private readonly int firmwareRevision;
27 private readonly int firmwareCRC;
29 private readonly Sensor[] fans;
30 private readonly Sensor[] controls;
31 private readonly Sensor[] temperatures;
32 private readonly Sensor[] flows;
33 private readonly Sensor[] relays;
35 private readonly bool available;
37 private readonly StringBuilder buffer = new StringBuilder();
39 private string ReadLine(int timeout) {
41 StringBuilder builder = new StringBuilder();
42 while (i <= timeout) {
43 while (serialPort.BytesToRead > 0) {
44 byte b = (byte)serialPort.ReadByte();
46 case 0xAA: return ((char)b).ToString();
47 case 0x0D: return builder.ToString();
48 default: builder.Append((char)b); break;
54 throw new TimeoutException();
57 private string ReadField(int device, char field) {
58 serialPort.WriteLine("[0:" + device + "]R" + field);
59 for (int i = 0; i < 5; i++) {
60 string s = ReadLine(200);
61 Match match = Regex.Match(s, @"-\[0:" +
62 device.ToString(CultureInfo.InvariantCulture) + @"\]R" +
63 Regex.Escape(field.ToString(CultureInfo.InvariantCulture)) + ":(.*)");
65 return match.Groups[1].Value;
70 protected string ReadString(int device, char field) {
71 string s = ReadField(device, field);
72 if (s != null && s[0] == '"' && s[s.Length - 1] == '"')
73 return s.Substring(1, s.Length - 2);
78 protected int ReadInteger(int device, char field) {
79 string s = ReadField(device, field);
81 if (int.TryParse(s, out i))
87 private bool WriteField(int device, char field, string value) {
88 serialPort.WriteLine("[0:" + device + "]W" + field + ":" + value);
89 for (int i = 0; i < 5; i++) {
90 string s = ReadLine(200);
91 Match match = Regex.Match(s, @"-\[0:" +
92 device.ToString(CultureInfo.InvariantCulture) + @"\]W" +
93 Regex.Escape(field.ToString(CultureInfo.InvariantCulture)) +
101 protected bool WriteInteger(int device, char field, int value) {
102 return WriteField(device, field,
103 value.ToString(CultureInfo.InvariantCulture));
106 protected bool WriteString(int device, char field, string value) {
107 return WriteField(device, field, '"' + value + '"');
110 public Heatmaster(string portName, ISettings settings)
111 : base("Heatmaster", new Identifier("heatmaster",
112 portName.TrimStart(new [] {'/'}).ToLowerInvariant()), settings)
114 this.portName = portName;
116 serialPort = new SerialPort(portName, 38400, Parity.None, 8,
119 serialPort.NewLine = ((char)0x0D).ToString();
121 hardwareRevision = ReadInteger(0, 'H');
122 firmwareRevision = ReadInteger(0, 'V');
123 firmwareCRC = ReadInteger(0, 'C');
125 int fanCount = Math.Min(ReadInteger(32, '?'), 4);
126 int temperatureCount = Math.Min(ReadInteger(48, '?'), 6);
127 int flowCount = Math.Min(ReadInteger(64, '?'), 1);
128 int relayCount = Math.Min(ReadInteger(80, '?'), 1);
130 fans = new Sensor[fanCount];
131 controls = new Sensor[fanCount];
132 for (int i = 0; i < fanCount; i++) {
134 string name = ReadString(device, 'C');
135 fans[i] = new Sensor(name, device, SensorType.Fan, this, settings);
136 fans[i].Value = ReadInteger(device, 'R');
137 ActivateSensor(fans[i]);
139 new Sensor(name, device, SensorType.Control, this, settings);
140 controls[i].Value = (100 / 255.0f) * ReadInteger(device, 'P');
141 ActivateSensor(controls[i]);
144 temperatures = new Sensor[temperatureCount];
145 for (int i = 0; i < temperatureCount; i++) {
147 string name = ReadString(device, 'C');
149 new Sensor(name, device, SensorType.Temperature, this, settings);
150 int value = ReadInteger(device, 'T');
151 temperatures[i].Value = 0.1f * value;
153 ActivateSensor(temperatures[i]);
156 flows = new Sensor[flowCount];
157 for (int i = 0; i < flowCount; i++) {
159 string name = ReadString(device, 'C');
160 flows[i] = new Sensor(name, device, SensorType.Flow, this, settings);
161 flows[i].Value = 0.1f * ReadInteger(device, 'L');
162 ActivateSensor(flows[i]);
165 relays = new Sensor[relayCount];
166 for (int i = 0; i < relayCount; i++) {
168 string name = ReadString(device, 'C');
170 new Sensor(name, device, SensorType.Control, this, settings);
171 relays[i].Value = 100 * ReadInteger(device, 'S');
172 ActivateSensor(relays[i]);
175 // set the update rate to 2 Hz
176 WriteInteger(0, 'L', 2);
180 } catch (IOException) { } catch (TimeoutException) { }
183 public override HardwareType HardwareType {
184 get { return HardwareType.Heatmaster; }
187 private void ProcessUpdateLine(string line) {
188 Match match = Regex.Match(line, @">\[0:(\d+)\]([0-9:\|-]+)");
191 if (int.TryParse(match.Groups[1].Value, out device)) {
192 foreach (string s in match.Groups[2].Value.Split('|')) {
193 string[] strings = s.Split(':');
194 int[] ints = new int[strings.Length];
196 for (int i = 0; i < ints.Length; i++)
197 if (!int.TryParse(strings[i], out ints[i])) {
205 if (ints.Length == 3 && ints[0] <= fans.Length) {
206 fans[ints[0] - 1].Value = ints[1];
207 controls[ints[0] - 1].Value = (100 / 255.0f) * ints[2];
211 if (ints.Length == 2 && ints[0] <= temperatures.Length)
212 temperatures[ints[0] - 1].Value = 0.1f * ints[1];
215 if (ints.Length == 3 && ints[0] <= flows.Length)
216 flows[ints[0] - 1].Value = 0.1f * ints[1];
219 if (ints.Length == 2 && ints[0] <= relays.Length)
220 relays[ints[0] - 1].Value = 100 * ints[1];
228 public override void Update() {
232 while (serialPort.IsOpen && serialPort.BytesToRead > 0) {
233 byte b = (byte)serialPort.ReadByte();
235 ProcessUpdateLine(buffer.ToString());
238 buffer.Append((char)b);
243 public override string GetReport() {
244 StringBuilder r = new StringBuilder();
246 r.AppendLine("Heatmaster");
249 r.AppendLine(portName);
250 r.Append("Hardware Revision: ");
251 r.AppendLine(hardwareRevision.ToString(CultureInfo.InvariantCulture));
252 r.Append("Firmware Revision: ");
253 r.AppendLine(firmwareRevision.ToString(CultureInfo.InvariantCulture));
254 r.Append("Firmware CRC: ");
255 r.AppendLine(firmwareCRC.ToString(CultureInfo.InvariantCulture));
261 public override void Close() {
263 serialPort.Dispose();
268 public void Dispose() {
269 if (serialPort != null) {
270 serialPort.Dispose();