# HG changeset patch # User moel.mich # Date 1282513991 0 # Node ID 81ab5e53122ec44f16699b982f23fca5523fc425 # Parent 31858ba46e9c3cf0573db9eeca11594e3b12c4d8 Added a first implementation for the Heatmaster fan controller. diff -r 31858ba46e9c -r 81ab5e53122e GUI/HardwareNode.cs --- a/GUI/HardwareNode.cs Tue Aug 17 21:44:02 2010 +0000 +++ b/GUI/HardwareNode.cs Sun Aug 22 21:53:11 2010 +0000 @@ -68,6 +68,9 @@ case HardwareType.HDD: this.Image = Utilities.EmbeddedResources.GetImage("hdd.png"); break; + case HardwareType.Heatmaster: + this.Image = Utilities.EmbeddedResources.GetImage("bigng.png"); + break; case HardwareType.Mainboard: this.Image = Utilities.EmbeddedResources.GetImage("mainboard.png"); break; diff -r 31858ba46e9c -r 81ab5e53122e Hardware/Computer.cs --- a/Hardware/Computer.cs Tue Aug 17 21:44:02 2010 +0000 +++ b/Hardware/Computer.cs Sun Aug 22 21:53:11 2010 +0000 @@ -99,8 +99,9 @@ Add(new Mainboard.MainboardGroup(settings)); Add(new CPU.CPUGroup(settings)); Add(new ATI.ATIGroup(settings)); - Add(new Nvidia.NvidiaGroup(settings)); + Add(new Nvidia.NvidiaGroup(settings)); Add(new TBalancer.TBalancerGroup(settings)); + Add(new Heatmaster.HeatmasterGroup(settings)); if (hddEnabled) Add(new HDD.HDDGroup(settings)); diff -r 31858ba46e9c -r 81ab5e53122e Hardware/Heatmaster/Heatmaster.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/Heatmaster/Heatmaster.cs Sun Aug 22 21:53:11 2010 +0000 @@ -0,0 +1,287 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Ports; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; + +namespace OpenHardwareMonitor.Hardware.Heatmaster { + internal class Heatmaster : Hardware { + + private string portName; + private SerialPort serialPort; + + private int hardwareRevision; + private int firmwareRevision; + private int firmwareCRC; + + private Sensor[] fans; + private Sensor[] controls; + private Sensor[] temperatures; + private Sensor[] flows; + private Sensor[] relays; + + private bool available = false; + + private string ReadLine(int timeout) { + int i = 0; + StringBuilder builder = new StringBuilder(); + while (i <= timeout) { + while (serialPort.BytesToRead > 0) { + byte b = (byte)serialPort.ReadByte(); + switch (b) { + case 0xAA: return ((char)b).ToString(); + case 0x0D: return builder.ToString(); + default: builder.Append((char)b); break; + } + } + i++; + Thread.Sleep(1); + } + throw new TimeoutException(); + } + + private string ReadField(int device, char field) { + serialPort.WriteLine("[0:" + device + "]R" + field); + for (int i = 0; i < 5; i++) { + string s = ReadLine(100); + Match match = Regex.Match(s, @"-\[0:" + device.ToString() + @"\]R" + + Regex.Escape(field.ToString()) + ":(.*)"); + if (match.Success) + return match.Groups[1].Value; + } + return null; + } + + private string ReadString(int device, char field) { + string s = ReadField(device, field); + if (s != null && s[0] == '"' && s[s.Length - 1] == '"') + return s.Substring(1, s.Length - 2); + else + return null; + } + + private int ReadInteger(int device, char field) { + string s = ReadField(device, field); + int i; + if (int.TryParse(s, out i)) + return i; + else + return 0; + } + + private bool WriteField(int device, char field, string value) { + serialPort.WriteLine("[0:" + device + "]W" + field + ":" + value); + for (int i = 0; i < 5; i++) { + string s = ReadLine(100); + Match match = Regex.Match(s, @"-\[0:" + device.ToString() + @"\]W" + + Regex.Escape(field.ToString()) + ":" + value); + if (match.Success) + return true; + } + return false; + } + + private bool WriteInteger(int device, char field, int value) { + return WriteField(device, field, value.ToString()); + } + + private bool WriteString(int device, char field, string value) { + return WriteField(device, field, '"' + value + '"'); + } + + public Heatmaster(string portName, ISettings settings) { + + this.portName = portName; + try { + serialPort = new SerialPort(portName, 38400, Parity.None, 8, + StopBits.One); + serialPort.Open(); + serialPort.NewLine = ((char)0x0D).ToString(); + + hardwareRevision = ReadInteger(0, 'H'); + firmwareRevision = ReadInteger(0, 'V'); + firmwareCRC = ReadInteger(0, 'C'); + + int fanCount = ReadInteger(32, '?'); + int temperatureCount = ReadInteger(48, '?'); + int flowCount = ReadInteger(64, '?'); + int relayCount = ReadInteger(80, '?'); + + fans = new Sensor[fanCount]; + controls = new Sensor[fanCount]; + for (int i = 0; i < fanCount; i++) { + int device = 33 + i; + string name = ReadString(device, 'C'); + fans[i] = new Sensor(name, device, SensorType.Fan, this, settings); + fans[i].Value = ReadInteger(device, 'R'); + ActivateSensor(fans[i]); + controls[i] = + new Sensor(name, device, SensorType.Control, this, settings); + controls[i].Value = (100 / 255.0f) * ReadInteger(device, 'P'); + ActivateSensor(controls[i]); + } + + for (int i = 0; i < fanCount; i++) { + int device = 33 + i; + string name = ReadString(device, 'C'); + + fans[i].Value = ReadInteger(device, 'R'); + ActivateSensor(fans[i]); + } + + temperatures = new Sensor[temperatureCount]; + for (int i = 0; i < temperatureCount; i++) { + int device = 49 + i; + string name = ReadString(device, 'C'); + temperatures[i] = + new Sensor(name, device, SensorType.Temperature, this, settings); + int value = ReadInteger(device, 'T'); + temperatures[i].Value = 0.1f * value; + if (value != -32768) + ActivateSensor(temperatures[i]); + } + + flows = new Sensor[flowCount]; + for (int i = 0; i < flowCount; i++) { + int device = 65 + i; + string name = ReadString(device, 'C'); + flows[i] = new Sensor(name, device, SensorType.Flow, this, settings); + flows[i].Value = 0.1f * ReadInteger(device, 'L'); + ActivateSensor(flows[i]); + } + + relays = new Sensor[relayCount]; + for (int i = 0; i < relayCount; i++) { + int device = 81 + i; + string name = ReadString(device, 'C'); + relays[i] = + new Sensor(name, device, SensorType.Control, this, settings); + relays[i].Value = 100 * ReadInteger(device, 'S'); + ActivateSensor(relays[i]); + } + + // set the update rate to 2 Hz + WriteInteger(0, 'L', 2); + + available = true; + + } catch (IOException) { } catch (TimeoutException) { } + } + + public override HardwareType HardwareType { + get { return HardwareType.Heatmaster; } + } + + public override Identifier Identifier { + get { + return new Identifier("heatmaster", + serialPort.PortName.TrimStart(new char[]{'/'}).ToLowerInvariant()); + } + } + + public override string Name { + get { return "Heatmaster"; } + } + + public override void Update() { + if (!available) + return; + + while (serialPort.BytesToRead > 0) { + Match match = Regex.Match(ReadLine(0), @">\[0:(\d+)\]([0-9:\|-]+)"); + if (match.Success) { + int device; + if (int.TryParse(match.Groups[1].Value, out device)) { + foreach (string s in match.Groups[2].Value.Split('|')) { + string[] strings = s.Split(':'); + int[] ints = new int[strings.Length]; + for (int i = 0; i < ints.Length; i++) + ints[i] = int.Parse(strings[i]); + switch (device) { + case 32: + if (ints.Length == 3 && ints[0] <= fans.Length) { + fans[ints[0] - 1].Value = ints[1]; + controls[ints[0] - 1].Value = (100 / 255.0f) * ints[2]; + } + break; + case 48: + if (ints.Length == 2 && ints[0] <= temperatures.Length) + temperatures[ints[0] - 1].Value = 0.1f * ints[1]; + break; + case 64: + if (ints.Length == 3 && ints[0] <= flows.Length) + flows[ints[0] - 1].Value = 0.1f * ints[1]; + break; + case 80: + if (ints.Length == 2 && ints[0] <= relays.Length) + relays[ints[0] - 1].Value = 100 * ints[1]; + break; + } + } + } + } + } + } + + public override string GetReport() { + StringBuilder r = new StringBuilder(); + + r.AppendLine("Heatmaster"); + r.AppendLine(); + r.Append("Port: "); + r.AppendLine(portName); + r.Append("Hardware Revision: "); + r.AppendLine(hardwareRevision.ToString()); + r.Append("Firmware Revision: "); + r.AppendLine(firmwareRevision.ToString()); + r.Append("Firmware CRC: "); + r.AppendLine(firmwareCRC.ToString()); + r.AppendLine(); + + return r.ToString(); + } + + public void Close() { + serialPort.Close(); + } + } +} diff -r 31858ba46e9c -r 81ab5e53122e Hardware/Heatmaster/HeatmasterGroup.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/Heatmaster/HeatmasterGroup.cs Sun Aug 22 21:53:11 2010 +0000 @@ -0,0 +1,172 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Text; +using System.Threading; + +namespace OpenHardwareMonitor.Hardware.Heatmaster { + internal class HeatmasterGroup : IGroup { + + private List hardware = new List(); + private StringBuilder report = new StringBuilder(); + + private static string ReadLine(SerialPort port, int timeout) { + int i = 0; + StringBuilder builder = new StringBuilder(); + while (i < timeout) { + while (port.BytesToRead > 0) { + byte b = (byte)port.ReadByte(); + switch (b) { + case 0xAA: return ((char)b).ToString(); + case 0x0D: return builder.ToString(); + default: builder.Append((char)b); break; + } + } + i++; + Thread.Sleep(1); + } + throw new TimeoutException(); + } + + public HeatmasterGroup(ISettings settings) { + + string[] portNames = SerialPort.GetPortNames(); + for (int i = portNames.Length - 1; i >= 0; i--) { + try { + + SerialPort serialPort = + new SerialPort(portNames[i], 38400, Parity.None, 8, StopBits.One); + serialPort.NewLine = ((char)0x0D).ToString(); + + bool isValid = false; + report.Append("Port Name: "); report.AppendLine(portNames[i]); + + try { + serialPort.Open(); + } catch (UnauthorizedAccessException) { + report.AppendLine("Exception: Access Denied"); + } + + if (serialPort.IsOpen) { + if (serialPort.CtsHolding) { + serialPort.DiscardInBuffer(); + serialPort.DiscardOutBuffer(); + serialPort.Write(new byte[] { 0xAA }, 0, 1); + + int j = 0; + while (serialPort.BytesToRead == 0 && j < 10) { + Thread.Sleep(20); + j++; + } + if (serialPort.BytesToRead > 0) { + bool flag = false; + while (serialPort.BytesToRead > 0 && !flag) { + flag |= (serialPort.ReadByte() == 0xAA); + } + if (flag) { + serialPort.WriteLine("[0:0]RH"); + try { + int k = 0; + int revision = 0; + while (k < 5) { + string line = ReadLine(serialPort, 100); + if (line.StartsWith("-[0:0]RH:")) { + int.TryParse(line.Substring(9), out revision); + break; + } + k++; + } + isValid = (revision == 770); + if (!isValid) { + report.Append("Status: Wrong Hardware Revision " + + revision.ToString()); + } + } catch (TimeoutException) { + report.AppendLine("Status: Timeout Reading Revision"); + } + } else { + report.AppendLine("Status: Wrong Startflag"); + } + } else { + report.AppendLine("Status: No Response"); + } + } else { + report.AppendLine("Status: Not Clear to Send"); + } + serialPort.DiscardInBuffer(); + serialPort.Close(); + serialPort.Dispose(); + } else { + report.AppendLine("Status: Port not Open"); + } + if (isValid) { + report.AppendLine("Status: OK"); + hardware.Add(new Heatmaster(portNames[i], settings)); + return; + } + } catch (Exception e) { + report.AppendLine(e.ToString()); + } + report.AppendLine(); + } + } + + public IHardware[] Hardware { + get { + return hardware.ToArray(); + } + } + + public string GetReport() { + if (report.Length > 0) { + report.Insert(0, "Serial Port Heatmaster" + Environment.NewLine + + Environment.NewLine); + report.AppendLine(); + return report.ToString(); + } else + return null; + } + + public void Close() { + foreach (Heatmaster heatmaster in hardware) + heatmaster.Close(); + } + } +} diff -r 31858ba46e9c -r 81ab5e53122e Hardware/IHardware.cs --- a/Hardware/IHardware.cs Tue Aug 17 21:44:02 2010 +0000 +++ b/Hardware/IHardware.cs Sun Aug 22 21:53:11 2010 +0000 @@ -46,6 +46,7 @@ CPU, GPU, HDD, + Heatmaster, Mainboard, SuperIO, TBalancer diff -r 31858ba46e9c -r 81ab5e53122e OpenHardwareMonitorLib.csproj --- a/OpenHardwareMonitorLib.csproj Tue Aug 17 21:44:02 2010 +0000 +++ b/OpenHardwareMonitorLib.csproj Sun Aug 22 21:53:11 2010 +0000 @@ -71,6 +71,8 @@ + + @@ -128,6 +130,7 @@ true +