moel@1: /* moel@1: moel@1: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@1: moel@1: The contents of this file are subject to the Mozilla Public License Version moel@1: 1.1 (the "License"); you may not use this file except in compliance with moel@1: the License. You may obtain a copy of the License at moel@1: moel@1: http://www.mozilla.org/MPL/ moel@1: moel@1: Software distributed under the License is distributed on an "AS IS" basis, moel@1: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@1: for the specific language governing rights and limitations under the License. moel@1: moel@1: The Original Code is the Open Hardware Monitor code. moel@1: moel@1: The Initial Developer of the Original Code is moel@1: Michael Möller . moel@1: Portions created by the Initial Developer are Copyright (C) 2009-2010 moel@1: the Initial Developer. All Rights Reserved. moel@1: moel@1: Contributor(s): moel@1: moel@1: Alternatively, the contents of this file may be used under the terms of moel@1: either the GNU General Public License Version 2 or later (the "GPL"), or moel@1: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@1: in which case the provisions of the GPL or the LGPL are applicable instead moel@1: of those above. If you wish to allow use of your version of this file only moel@1: under the terms of either the GPL or the LGPL, and not to allow others to moel@1: use your version of this file under the terms of the MPL, indicate your moel@1: decision by deleting the provisions above and replace them with the notice moel@1: and other provisions required by the GPL or the LGPL. If you do not delete moel@1: the provisions above, a recipient may use your version of this file under moel@1: the terms of any one of the MPL, the GPL or the LGPL. moel@1: moel@1: */ moel@1: moel@1: using System; moel@1: using System.Collections.Generic; moel@1: using System.Configuration; moel@1: using System.Drawing; moel@1: using System.IO; moel@1: using System.IO.Ports; moel@1: using System.Text; moel@1: moel@1: namespace OpenHardwareMonitor.Hardware.TBalancer { moel@1: public class TBalancer : IHardware { moel@1: moel@57: private string portName; moel@1: private Image icon; moel@1: private SerialPort serialPort; moel@33: private byte protocolVersion; moel@1: private Sensor[] digitalTemperatures = new Sensor[8]; moel@1: private Sensor[] analogTemperatures = new Sensor[4]; moel@57: private Sensor[] sensorhubTemperatures = new Sensor[6]; moel@57: private Sensor[] sensorhubFlows = new Sensor[2]; moel@1: private Sensor[] fans = new Sensor[4]; moel@57: private Sensor[] miniNGTemperatures = new Sensor[4]; moel@57: private Sensor[] miniNGFans = new Sensor[4]; moel@1: private List active = new List(); moel@1: private List deactivating = new List(); moel@57: private int[] primaryData = new int[0]; moel@57: private int[] alternativeData = new int[0]; moel@1: moel@1: public const byte STARTFLAG = 100; moel@57: public const byte ENDFLAG = 254; moel@57: moel@57: private delegate void MethodDelegate(); moel@57: private MethodDelegate alternativeRequest; moel@1: moel@33: public TBalancer(string portName, byte protocolVersion) { moel@57: this.portName = portName; moel@57: this.icon = Utilities.EmbeddedResources.GetImage("bigng.png"); moel@33: this.protocolVersion = protocolVersion; moel@1: moel@63: ParameterDescription[] parameter = new ParameterDescription[] { moel@63: new ParameterDescription("Offset", "Temperature offset.", 0) moel@63: }; moel@57: int offset = 0; moel@57: for (int i = 0; i < digitalTemperatures.Length; i++) moel@57: digitalTemperatures[i] = new Sensor("Digital Sensor #" + (i + 1), moel@63: offset + i, null, SensorType.Temperature, this, parameter); moel@57: offset += digitalTemperatures.Length; moel@57: moel@57: for (int i = 0; i < analogTemperatures.Length; i++) moel@57: analogTemperatures[i] = new Sensor("Analog Sensor #" + (i + 1), moel@63: offset + i, null, SensorType.Temperature, this, parameter); moel@57: offset += analogTemperatures.Length; moel@57: moel@57: for (int i = 0; i < sensorhubTemperatures.Length; i++) moel@57: sensorhubTemperatures[i] = new Sensor("Sensorhub Sensor #" + (i + 1), moel@63: offset + i, null, SensorType.Temperature, this, parameter); moel@57: offset += sensorhubTemperatures.Length; moel@57: moel@57: for (int i = 0; i < sensorhubFlows.Length; i++) moel@57: sensorhubFlows[i] = new Sensor("Flowmeter #" + (i + 1), moel@63: offset + i, null, SensorType.Flow, this, new ParameterDescription[] { moel@63: new ParameterDescription("Impulse Rate", moel@63: "The impulse rate of the flowmeter in pulses/L", 509) moel@63: }); moel@57: offset += sensorhubFlows.Length; moel@57: moel@57: for (int i = 0; i < miniNGTemperatures.Length; i++) moel@63: miniNGTemperatures[i] = new Sensor("miniNG #" + (i / 2 + 1) + moel@63: " Sensor #" + (i % 2 + 1), offset + i, null, SensorType.Temperature, moel@63: this, parameter); moel@57: offset += miniNGTemperatures.Length; moel@57: moel@57: alternativeRequest = new MethodDelegate(DelayedAlternativeRequest); moel@57: moel@1: try { moel@1: serialPort = new SerialPort(portName, 19200, Parity.None, 8, moel@1: StopBits.One); moel@1: serialPort.Open(); moel@1: Update(); moel@57: } catch (IOException) { } moel@1: } moel@1: moel@1: private void ActivateSensor(Sensor sensor) { moel@1: deactivating.Remove(sensor); moel@1: if (!active.Contains(sensor)) { moel@1: active.Add(sensor); moel@15: if (SensorAdded != null) moel@15: SensorAdded(sensor); moel@1: } moel@1: } moel@1: moel@1: private void DeactivateSensor(Sensor sensor) { moel@1: if (deactivating.Contains(sensor)) { moel@1: active.Remove(sensor); moel@1: deactivating.Remove(sensor); moel@15: if (SensorRemoved != null) moel@15: SensorRemoved(sensor); moel@1: } else if (active.Contains(sensor)) { moel@1: deactivating.Add(sensor); moel@1: } moel@1: } moel@1: moel@57: private void ReadminiNG(int[] data, int number) { moel@57: int offset = 1 + number * 65; moel@57: moel@57: if (data[offset + 61] != ENDFLAG) moel@57: return; moel@57: moel@57: for (int i = 0; i < 2; i++) { moel@57: Sensor sensor = miniNGTemperatures[number * 2 + i]; moel@57: if (data[offset + 7 + i] > 0) { moel@63: sensor.Value = 0.5f * data[offset + 7 + i] + moel@63: sensor.Parameters[0].Value; moel@57: ActivateSensor(sensor); moel@57: } else { moel@57: DeactivateSensor(sensor); moel@57: } moel@57: } moel@57: moel@57: for (int i = 0; i < 2; i++) { moel@57: float maxRPM = 20.0f * data[offset + 44 + 2 * i]; moel@57: moel@57: if (miniNGFans[number * 2 + i] == null) moel@57: miniNGFans[number * 2 + i] = moel@57: new Sensor("miniNG #" + (number + 1) + " Fan #" + (i + 1), moel@57: 4 + number * 2 + i, maxRPM, SensorType.Fan, this); moel@57: moel@57: Sensor sensor = miniNGFans[number * 2 + i]; moel@57: moel@57: sensor.Value = 20.0f * data[offset + 43 + 2 * i]; moel@57: ActivateSensor(sensor); moel@57: } moel@57: } moel@57: moel@1: private void ReadData() { moel@1: int[] data = new int[285]; moel@1: for (int i = 0; i < data.Length; i++) moel@1: data[i] = serialPort.ReadByte(); moel@1: moel@57: if (data[0] != STARTFLAG) { moel@1: serialPort.DiscardInBuffer(); moel@1: return; moel@1: } moel@1: moel@73: if (data[1] == 255 || data[1] == 88) { // bigNG moel@57: moel@57: if (data[274] != protocolVersion) moel@57: return; moel@57: moel@57: this.primaryData = data; moel@57: moel@57: for (int i = 0; i < digitalTemperatures.Length; i++) moel@57: if (data[238 + i] > 0) { moel@63: digitalTemperatures[i].Value = 0.5f * data[238 + i] + moel@63: digitalTemperatures[i].Parameters[0].Value; moel@57: ActivateSensor(digitalTemperatures[i]); moel@57: } else { moel@57: DeactivateSensor(digitalTemperatures[i]); moel@57: } moel@57: moel@57: for (int i = 0; i < analogTemperatures.Length; i++) moel@57: if (data[260 + i] > 0) { moel@63: analogTemperatures[i].Value = 0.5f * data[260 + i] + moel@63: analogTemperatures[i].Parameters[0].Value; moel@57: ActivateSensor(analogTemperatures[i]); moel@57: } else { moel@57: DeactivateSensor(analogTemperatures[i]); moel@57: } moel@57: moel@57: for (int i = 0; i < sensorhubTemperatures.Length; i++) moel@57: if (data[246 + i] > 0) { moel@63: sensorhubTemperatures[i].Value = 0.5f * data[246 + i] + moel@63: sensorhubTemperatures[i].Parameters[0].Value; moel@57: ActivateSensor(sensorhubTemperatures[i]); moel@57: } else { moel@57: DeactivateSensor(sensorhubTemperatures[i]); moel@57: } moel@57: moel@57: for (int i = 0; i < sensorhubFlows.Length; i++) moel@57: if (data[231 + i] > 0 && data[234] > 0) { moel@66: float pulsesPerSecond = (data[231 + i] * 4.0f) / data[234]; moel@63: float pulsesPerLiter = sensorhubFlows[i].Parameters[0].Value; moel@57: sensorhubFlows[i].Value = pulsesPerSecond * 3600 / pulsesPerLiter; moel@57: ActivateSensor(sensorhubFlows[i]); moel@57: } else { moel@57: DeactivateSensor(sensorhubFlows[i]); moel@57: } moel@57: moel@57: for (int i = 0; i < fans.Length; i++) { moel@57: float maxRPM = 11.5f * ((data[149 + 2 * i] << 8) | data[148 + 2 * i]); moel@57: moel@57: if (fans[i] == null) moel@57: fans[i] = new Sensor("Fan #" + (i + 1), i, maxRPM, SensorType.Fan, moel@63: this, new ParameterDescription[] { moel@63: new ParameterDescription("MaxRPM", moel@63: "Maximum revolutions per minute (RPM) of the fan.", maxRPM) moel@63: }); moel@57: moel@63: if ((data[136] & (1 << i)) == 0) // pwm mode moel@75: fans[i].Value = fans[i].Parameters[0].Value * 0.02f * data[137 + i]; moel@63: else // analog mode moel@63: fans[i].Value = fans[i].Parameters[0].Value * 0.01f * data[141 + i]; moel@57: ActivateSensor(fans[i]); moel@1: } moel@1: moel@57: } else if (data[1] == 253) { // miniNG #1 moel@57: this.alternativeData = data; moel@1: moel@57: ReadminiNG(data, 0); moel@57: moel@57: if (data[66] == 252) // miniNG #2 moel@57: ReadminiNG(data, 1); moel@57: } moel@1: } moel@1: moel@1: public Image Icon { moel@1: get { return icon; } moel@1: } moel@1: moel@1: public string Name { moel@1: get { return "T-Balancer bigNG"; } moel@1: } moel@1: moel@1: public string Identifier { moel@1: get { return "/bigng/" + moel@57: this.portName.TrimStart(new char[]{'/'}).ToLower(); } moel@1: } moel@1: moel@64: public IHardware[] SubHardware { moel@64: get { return new IHardware[0]; } moel@64: } moel@64: moel@1: public ISensor[] Sensors { moel@1: get { return active.ToArray(); } moel@1: } moel@1: moel@1: public string GetReport() { moel@1: StringBuilder r = new StringBuilder(); moel@1: moel@1: r.AppendLine("T-Balancer bigNG"); moel@1: r.AppendLine(); moel@1: r.Append("Port Name: "); r.AppendLine(serialPort.PortName); moel@1: r.AppendLine(); moel@57: moel@57: r.AppendLine("Primary System Information Answer"); moel@1: r.AppendLine(); moel@1: r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); moel@1: r.AppendLine(); moel@1: for (int i = 0; i <= 0x11; i++) { moel@1: r.Append(" "); r.Append((i << 4).ToString("X3")); r.Append(" "); moel@1: for (int j = 0; j <= 0xF; j++) { moel@1: int index = ((i << 4) | j); moel@57: if (index < primaryData.Length) { moel@1: r.Append(" "); moel@57: r.Append(primaryData[index].ToString("X2")); moel@1: } moel@1: } moel@1: r.AppendLine(); moel@1: } moel@1: r.AppendLine(); moel@1: moel@57: if (alternativeData.Length > 0) { moel@57: r.AppendLine("Alternative System Information Answer"); moel@57: r.AppendLine(); moel@57: r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); moel@57: r.AppendLine(); moel@57: for (int i = 0; i <= 0x11; i++) { moel@57: r.Append(" "); r.Append((i << 4).ToString("X3")); r.Append(" "); moel@57: for (int j = 0; j <= 0xF; j++) { moel@57: int index = ((i << 4) | j); moel@57: if (index < alternativeData.Length) { moel@57: r.Append(" "); moel@57: r.Append(alternativeData[index].ToString("X2")); moel@57: } moel@57: } moel@57: r.AppendLine(); moel@57: } moel@57: r.AppendLine(); moel@57: } moel@57: moel@1: return r.ToString(); moel@1: } moel@1: moel@57: private void DelayedAlternativeRequest() { moel@57: System.Threading.Thread.Sleep(500); moel@57: try { moel@57: if (serialPort.IsOpen) moel@57: serialPort.Write(new byte[] { 0x37 }, 0, 1); moel@57: } catch (Exception) { } moel@57: } moel@57: moel@1: public void Update() { moel@1: while (serialPort.BytesToRead >= 285) moel@1: ReadData(); moel@57: if (serialPort.BytesToRead == 1) moel@57: serialPort.ReadByte(); moel@57: moel@1: serialPort.Write(new byte[] { 0x38 }, 0, 1); moel@57: alternativeRequest.BeginInvoke(null, null); moel@1: } moel@1: moel@1: public void Close() { moel@1: serialPort.Close(); moel@1: } moel@1: moel@1: public event SensorEventHandler SensorAdded; moel@1: public event SensorEventHandler SensorRemoved; moel@1: } moel@1: }