diff --git a/LibreHardwareMonitor/LibreHardwareMonitor.csproj b/LibreHardwareMonitor/LibreHardwareMonitor.csproj index f2dd072..25a9fce 100644 --- a/LibreHardwareMonitor/LibreHardwareMonitor.csproj +++ b/LibreHardwareMonitor/LibreHardwareMonitor.csproj @@ -169,7 +169,6 @@ PortForm.cs - @@ -303,9 +302,6 @@ - - - diff --git a/LibreHardwareMonitor/Resources/acicon.png b/LibreHardwareMonitor/Resources/acicon.png deleted file mode 100644 index 26ae763..0000000 Binary files a/LibreHardwareMonitor/Resources/acicon.png and /dev/null differ diff --git a/LibreHardwareMonitor/Resources/bigng.png b/LibreHardwareMonitor/Resources/bigng.png deleted file mode 100644 index 229c3d8..0000000 Binary files a/LibreHardwareMonitor/Resources/bigng.png and /dev/null differ diff --git a/LibreHardwareMonitor/UI/HardwareTypeImage.cs b/LibreHardwareMonitor/UI/HardwareTypeImage.cs index c80401e..979a4e0 100644 --- a/LibreHardwareMonitor/UI/HardwareTypeImage.cs +++ b/LibreHardwareMonitor/UI/HardwareTypeImage.cs @@ -38,30 +38,21 @@ namespace LibreHardwareMonitor.UI case HardwareType.Storage: image = Utilities.EmbeddedResources.GetImage("hdd.png"); break; - case HardwareType.Heatmaster: - image = Utilities.EmbeddedResources.GetImage("bigng.png"); - break; case HardwareType.Motherboard: image = Utilities.EmbeddedResources.GetImage("mainboard.png"); break; case HardwareType.SuperIO: image = Utilities.EmbeddedResources.GetImage("chip.png"); break; - case HardwareType.TBalancer: - image = Utilities.EmbeddedResources.GetImage("bigng.png"); - break; case HardwareType.Memory: image = Utilities.EmbeddedResources.GetImage("ram.png"); break; - case HardwareType.AquaComputer: - image = Utilities.EmbeddedResources.GetImage("acicon.png"); - break; - case HardwareType.AeroCool: - image = Utilities.EmbeddedResources.GetImage("chip.png"); - break; case HardwareType.Network: image = Utilities.EmbeddedResources.GetImage("nic.png"); break; + case HardwareType.Cooler: + image = Utilities.EmbeddedResources.GetImage("fan.png"); + break; default: image = new Bitmap(1, 1); break; diff --git a/LibreHardwareMonitor/Utilities/HttpServer.cs b/LibreHardwareMonitor/Utilities/HttpServer.cs index 02b1280..69a8184 100644 --- a/LibreHardwareMonitor/Utilities/HttpServer.cs +++ b/LibreHardwareMonitor/Utilities/HttpServer.cs @@ -631,20 +631,14 @@ namespace LibreHardwareMonitor.Utilities return "ati.png"; case HardwareType.Storage: return "hdd.png"; - case HardwareType.Heatmaster: - return "bigng.png"; case HardwareType.Motherboard: return "mainboard.png"; case HardwareType.SuperIO: return "chip.png"; - case HardwareType.TBalancer: - return "bigng.png"; case HardwareType.Memory: return "ram.png"; - case HardwareType.AquaComputer: - return "acicon.png"; - case HardwareType.AeroCool: - return "chip.png"; + case HardwareType.Cooler: + return "fan.png"; case HardwareType.Network: return "nic.png"; default: diff --git a/LibreHardwareMonitorLib/Hardware/Computer.cs b/LibreHardwareMonitorLib/Hardware/Computer.cs index 34c5090..d9a1dde 100644 --- a/LibreHardwareMonitorLib/Hardware/Computer.cs +++ b/LibreHardwareMonitorLib/Hardware/Computer.cs @@ -12,6 +12,7 @@ using System.Security.Permissions; using LibreHardwareMonitor.Hardware.Controller.AeroCool; using LibreHardwareMonitor.Hardware.Controller.AquaComputer; using LibreHardwareMonitor.Hardware.Controller.Heatmaster; +using LibreHardwareMonitor.Hardware.Controller.Nzxt; using LibreHardwareMonitor.Hardware.Controller.TBalancer; using LibreHardwareMonitor.Hardware.Gpu; using LibreHardwareMonitor.Hardware.Memory; @@ -94,6 +95,7 @@ namespace LibreHardwareMonitor.Hardware Add(new HeatmasterGroup(_settings)); Add(new AquaComputerGroup(_settings)); Add(new AeroCoolGroup(_settings)); + Add(new NzxtGroup(_settings)); } else { @@ -101,6 +103,7 @@ namespace LibreHardwareMonitor.Hardware RemoveType(); RemoveType(); RemoveType(); + RemoveType(); } } @@ -387,6 +390,7 @@ namespace LibreHardwareMonitor.Hardware Add(new HeatmasterGroup(_settings)); Add(new AquaComputerGroup(_settings)); Add(new AeroCoolGroup(_settings)); + Add(new NzxtGroup(_settings)); } if (_storageEnabled) diff --git a/LibreHardwareMonitorLib/Hardware/Controller/AeroCool/P7-H1.cs b/LibreHardwareMonitorLib/Hardware/Controller/AeroCool/P7-H1.cs index 5a49195..57cb955 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/AeroCool/P7-H1.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/AeroCool/P7-H1.cs @@ -41,7 +41,7 @@ namespace LibreHardwareMonitor.Hardware.Controller.AeroCool public override HardwareType HardwareType { - get { return HardwareType.AeroCool; } + get { return HardwareType.Cooler; } } public int HubNumber { get; } diff --git a/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquastreamXT.cs b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquastreamXT.cs index 94b5a75..c79d9bb 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquastreamXT.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquastreamXT.cs @@ -79,7 +79,7 @@ namespace LibreHardwareMonitor.Hardware.Controller.AquaComputer public override HardwareType HardwareType { - get { return HardwareType.AquaComputer; } + get { return HardwareType.Cooler; } } public string Status diff --git a/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/MPS.cs b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/MPS.cs index 0d5b0b5..e76f007 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/MPS.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/MPS.cs @@ -47,7 +47,7 @@ namespace LibreHardwareMonitor.Hardware.Controller.AquaComputer public override HardwareType HardwareType { - get { return HardwareType.AquaComputer; } + get { return HardwareType.Cooler; } } public string Status diff --git a/LibreHardwareMonitorLib/Hardware/Controller/Heatmaster/Heatmaster.cs b/LibreHardwareMonitorLib/Hardware/Controller/Heatmaster/Heatmaster.cs index 15727b5..a575660 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/Heatmaster/Heatmaster.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/Heatmaster/Heatmaster.cs @@ -102,7 +102,7 @@ namespace LibreHardwareMonitor.Hardware.Controller.Heatmaster public override HardwareType HardwareType { - get { return HardwareType.Heatmaster; } + get { return HardwareType.Cooler; } } public void Dispose() diff --git a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/KrakenX3.cs b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/KrakenX3.cs new file mode 100644 index 0000000..2711ea9 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/KrakenX3.cs @@ -0,0 +1,159 @@ +using HidSharp; +using System; +using System.Linq; +using System.Threading; + +namespace LibreHardwareMonitor.Hardware.Controller.Nzxt +{ + /** + * Support for the Kraken X3 devices from NZXT + */ + internal sealed class KrakenX3 : Hardware + { + // Some fixed messages to send to the pump for basic monitoring and control + private static readonly byte[] _getFirmareInfo = { 0x10, 0x01 }; + private static readonly byte[] _initialize1 = { 0x70, 0x02, 0x01, 0xb8, 0x0b }; + private static readonly byte[] _initialize2 = { 0x70, 0x01 }; + private static readonly byte[][] _setPumpTargetMap = new byte[101][]; // Sacrifice memory to speed this up with a lookup instead of a copy operation + + static KrakenX3() + { + byte[] set_pump_speed_header = { 0x72, 0x01, 0x00, 0x00 }; + + for (byte speed = 0; speed < _setPumpTargetMap.Length; speed++) + { + _setPumpTargetMap[speed] = set_pump_speed_header.Concat(Enumerable.Repeat(speed, 40).Concat(new byte[20])).ToArray(); + } + } + + private volatile bool _controlling = false; + private readonly Sensor _pump; + private readonly Control _pumpControl; + private readonly Sensor _pumpRpm; + private readonly byte[] _rawData = new byte[64]; + private readonly HidStream _stream; + private readonly Sensor _temperature; + + public string FirmwareVersion { get; private set; } + + public KrakenX3(HidDevice dev, ISettings settings) : base("Nzxt Kraken X3", new Identifier("nzxt", "krakenx3", dev.GetSerialNumber().TrimStart('0')), settings) + { + if (dev.TryOpen(out _stream)) + { + _stream.ReadTimeout = 5000; // The NZXT device returns with data that we need periodically without writing... + _stream.Write(_initialize1); + _stream.Write(_initialize2); + + _stream.Write(_getFirmareInfo); + do + { + _stream.Read(_rawData); + if (_rawData[0] == 0x11 && _rawData[1] == 0x01) + { + FirmwareVersion = $"{_rawData[0x11]}.{_rawData[0x11]}.{_rawData[0x13]}"; + } + } while (FirmwareVersion == null); + + Name = $"Nzxt Kraken X3"; + + _pump = new Sensor("Pump Control", 0, SensorType.Control, this, new ParameterDescription[0], settings); + _pumpControl = new Control(_pump, settings, 0, 100); + _pump.Control = _pumpControl; + _pumpControl.ControlModeChanged += SoftwareControlValueChanged; + _pumpControl.SoftwareControlValueChanged += SoftwareControlValueChanged; + SoftwareControlValueChanged(_pumpControl); + ActivateSensor(_pump); + + _pumpRpm = new Sensor("Pump", 0, SensorType.Fan, this, new ParameterDescription[0], settings); + ActivateSensor(_pumpRpm); + + _temperature = new Sensor("Internal Water", 0, SensorType.Temperature, this, new ParameterDescription[0], settings); + ActivateSensor(_temperature); + + ThreadPool.UnsafeQueueUserWorkItem(ContinuousRead, _rawData); + } + } + + private void SoftwareControlValueChanged(Control control) + { + if (control.ControlMode == ControlMode.Software) + { + float value = control.SoftwareValue; + byte pump_speed_index = (byte)((value > 100) ? 100 : (value < 0) ? 0 : value); // Clamp the value, anything out of range will fail + + _controlling = true; + _stream.Write(_setPumpTargetMap[pump_speed_index]); + _pump.Value = value; + } + else if (control.ControlMode == ControlMode.Default) + { // There isn't a "default" mode with this pump, but a safe setting is 40% + _stream.Write(_setPumpTargetMap[40]); + } + } + + public override HardwareType HardwareType => HardwareType.Cooler; + + public string Status => (FirmwareVersion != "2.1.0" ? $"Status: Untested Firmware Version {FirmwareVersion}! Please consider Updating to Version 2.1.0" : "Status: OK"); + + public override void Close() + { + base.Close(); + _stream.Close(); + } + + private void ContinuousRead(object state) + { + byte[] buffer = new byte[_rawData.Length]; + while (_stream.CanRead) + { + try + { + _stream.Read(buffer); // This is a blocking call, will wait for bytes to become available + + lock (_rawData) + { + Array.Copy(buffer, _rawData, buffer.Length); + } + } + catch (TimeoutException ex) + { + // Don't care, just make sure the stream is still open + Thread.Sleep(500); + } + catch (ObjectDisposedException ex) + { + // Could be unplugged, or the app is stopping... + } + } + } + + public override void Update() + { + // The NZXT Kraken X3 series sends updates periodically. We have to read it in a seperate thread, this call just reads that data. + lock (_rawData) + { + + if (_rawData[0] == 0x75 && _rawData[1] == 0x02) + { + _temperature.Value = _rawData[15] + _rawData[16] / 10.0f; + _pumpRpm.Value = (_rawData[18] << 8) | _rawData[17]; + + // The following logic makes sure the pump is set to the controlling value. This pump sometimes sets itself to 0% when instructed to a value. + if (!_controlling) + { + _pump.Value = _rawData[19]; + } + else if (_pump.Value != _rawData[19]) + { + byte pump_speed_index = (byte)_pump.Value; + _stream.Write(_setPumpTargetMap[pump_speed_index]); + } + else + { + _controlling = false; + } + } + } + } + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/NzxtGroup.cs b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/NzxtGroup.cs new file mode 100644 index 0000000..5c9eec5 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/NzxtGroup.cs @@ -0,0 +1,70 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. +// All Rights Reserved. + +using System.Collections.Generic; +using System.Text; +using HidSharp; + +namespace LibreHardwareMonitor.Hardware.Controller.Nzxt +{ + internal class NzxtGroup : IGroup + { + private readonly List _hardware = new List(); + private readonly StringBuilder _report = new StringBuilder(); + + public NzxtGroup(ISettings settings) + { + _report.AppendLine("Nzxt Hardware"); + _report.AppendLine(); + + foreach (HidDevice dev in DeviceList.Local.GetHidDevices(0x1e71)) + { + string productName = dev.GetProductName(); + + switch (dev.ProductID) + { + case 0x2007: + { + var device = new KrakenX3(dev, settings); + _report.AppendLine($"Device name: {productName}"); + _report.AppendLine($"Firmware version: {device.FirmwareVersion}"); + _report.AppendLine($"{device.Status}"); + _report.AppendLine(); + _hardware.Add(device); + break; + } + default: + { + _report.AppendLine($"Unknown Hardware PID: {dev.ProductID} Name: {productName}"); + _report.AppendLine(); + break; + } + } + } + + if (_hardware.Count == 0) + { + _report.AppendLine("No Nzxt Hardware found."); + _report.AppendLine(); + } + } + + public IEnumerable Hardware => _hardware; + + public void Close() + { + foreach (IHardware iHardware in _hardware) + { + if (iHardware is Hardware hardware) + hardware.Close(); + } + } + + public string GetReport() + { + return _report.ToString(); + } + } +} diff --git a/LibreHardwareMonitorLib/Hardware/Controller/TBalancer/TBalancer.cs b/LibreHardwareMonitorLib/Hardware/Controller/TBalancer/TBalancer.cs index aff562d..c3d306f 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/TBalancer/TBalancer.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/TBalancer/TBalancer.cs @@ -90,7 +90,7 @@ namespace LibreHardwareMonitor.Hardware.Controller.TBalancer public override HardwareType HardwareType { - get { return HardwareType.TBalancer; } + get { return HardwareType.Cooler; } } protected override void ActivateSensor(ISensor sensor) diff --git a/LibreHardwareMonitorLib/Hardware/IHardware.cs b/LibreHardwareMonitorLib/Hardware/IHardware.cs index 2ab1325..49d1af5 100644 --- a/LibreHardwareMonitorLib/Hardware/IHardware.cs +++ b/LibreHardwareMonitorLib/Hardware/IHardware.cs @@ -12,16 +12,13 @@ namespace LibreHardwareMonitor.Hardware { Motherboard, SuperIO, - AquaComputer, Cpu, Memory, GpuNvidia, GpuAmd, - TBalancer, - Heatmaster, Storage, Network, - AeroCool + Cooler } public interface IHardware : IElement diff --git a/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj b/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj index 877f8a7..ea8f96f 100644 --- a/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj +++ b/LibreHardwareMonitorLib/LibreHardwareMonitorLib.csproj @@ -43,6 +43,8 @@ + +