diff --git a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/GridV3.cs b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/GridV3.cs index 127a944..57f8215 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/GridV3.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/GridV3.cs @@ -15,34 +15,30 @@ namespace LibreHardwareMonitor.Hardware.Controller.Nzxt; /// internal sealed class GridV3 : Hardware { + private const int FANS_COUNT = 6; + // Some initialization messages to send to the controller. No visible effects but NZXT CAM send them. private static readonly byte[] _initialize1 = { 0x01, 0x5c }; private static readonly byte[] _initialize2 = { 0x01, 0x5d }; private static readonly byte[] _initialize3 = { 0x01, 0x59 }; - private const int FANS_COUNT = 6; - - private readonly byte[] _setFanSpeedMsg; - private readonly HidStream _stream; - private readonly Dictionary _rawData = new(); - - private readonly Sensor _noise; private readonly Sensor[] _currents = new Sensor[FANS_COUNT]; + private readonly Control[] _fanControls = new Control[FANS_COUNT]; + private readonly Sensor _noise; private readonly Sensor[] _powers = new Sensor[FANS_COUNT]; private readonly Sensor[] _pwmControls = new Sensor[FANS_COUNT]; + private readonly Dictionary _rawData = new(); private readonly Sensor[] _rpmSensors = new Sensor[FANS_COUNT]; + private readonly byte[] _setFanSpeedMsg; + private readonly HidStream _stream; private readonly Sensor[] _voltages = new Sensor[FANS_COUNT]; - private readonly Control[] _fanControls = new Control[FANS_COUNT]; - public GridV3(HidDevice dev, ISettings settings) : base("NZXT GRID+ V3", new Identifier("nzxt", "gridv3", dev.GetSerialNumber().TrimStart('0')), settings) { if (dev.TryOpen(out _stream)) { - for (int fanID = 0; fanID < FANS_COUNT; fanID++) - { - _rawData[fanID] = new byte[21]; - } + for (int fanId = 0; fanId < FANS_COUNT; fanId++) + _rawData[fanId] = new byte[21]; _setFanSpeedMsg = new byte[65]; _setFanSpeedMsg[0] = 0x02; @@ -90,11 +86,14 @@ internal sealed class GridV3 : Hardware // NZXT GRID does not report current PWM value. So we need to initialize it with some value to keep GUI and device values in sync. _fanControls[i].SetDefault(); } + _noise = new Sensor("GRID Noise", 0, SensorType.Noise, this, Array.Empty(), settings); ActivateSensor(_noise); Thread readGridReports = new(ContinuousRead) { IsBackground = true }; readGridReports.Start(_rawData); + + IsValid = true; } } @@ -102,30 +101,33 @@ internal sealed class GridV3 : Hardware public override HardwareType HardwareType => HardwareType.Cooler; + public bool IsValid { get; } + private void SoftwareControlValueChanged(Control control) { - if (control.ControlMode == ControlMode.Software) + switch (control.ControlMode) { - float value = control.SoftwareValue; - byte fanSpeed = (byte)(value > 100 ? 100 : value < 0 ? 0 : value); // Clamp the value, anything out of range will fail + case ControlMode.Software: + float value = control.SoftwareValue; + byte fanSpeed = (byte)(value > 100 ? 100 : value < 0 ? 0 : value); // Clamp the value, anything out of range will fail - //_controlling = true; - _setFanSpeedMsg[2] = (byte)control.Sensor.Index; - _setFanSpeedMsg[4] = fanSpeed; + //_controlling = true; + _setFanSpeedMsg[2] = (byte)control.Sensor.Index; + _setFanSpeedMsg[4] = fanSpeed; - _stream.Write(_setFanSpeedMsg); + _stream.Write(_setFanSpeedMsg); - _pwmControls[control.Sensor.Index].Value = value; - } - else if (control.ControlMode == ControlMode.Default) - { - // There isn't a "default" mode, but let's say a safe setting is 40% - _setFanSpeedMsg[2] = (byte)control.Sensor.Index; - _setFanSpeedMsg[4] = 40; + _pwmControls[control.Sensor.Index].Value = value; + break; + case ControlMode.Default: + // There isn't a "default" mode, but let's say a safe setting is 40% + _setFanSpeedMsg[2] = (byte)control.Sensor.Index; + _setFanSpeedMsg[4] = 40; - _stream.Write(_setFanSpeedMsg); + _stream.Write(_setFanSpeedMsg); - _pwmControls[control.Sensor.Index].Value = 40; + _pwmControls[control.Sensor.Index].Value = 40; + break; } } @@ -147,8 +149,8 @@ internal sealed class GridV3 : Hardware { lock (_rawData) { - int fanID = (buffer[15] >> 4) & 0x0f; - Array.Copy(buffer, _rawData[fanID], buffer.Length); + int fanId = (buffer[15] >> 4) & 0x0f; + Array.Copy(buffer, _rawData[fanId], buffer.Length); } } } @@ -167,16 +169,17 @@ internal sealed class GridV3 : Hardware public override void Update() { - // The NZXT GRID+ V3 series sends updates periodically. We have to read it in a seperate thread, this call just reads that data. + // The NZXT GRID+ V3 series sends updates periodically. We have to read it in a separate thread, this call just reads that data. lock (_rawData) { - for (int fanID = 0; fanID < FANS_COUNT; fanID++) + for (int fanId = 0; fanId < FANS_COUNT; fanId++) { - _rpmSensors[fanID].Value = (_rawData[fanID][3] << 8) | _rawData[fanID][4]; - _voltages[fanID].Value = _rawData[fanID][7] + _rawData[fanID][8] / 100.0f; - _currents[fanID].Value = _rawData[fanID][9] + _rawData[fanID][10] / 100.0f; - _powers[fanID].Value = _currents[fanID].Value * _voltages[fanID].Value; + _rpmSensors[fanId].Value = (_rawData[fanId][3] << 8) | _rawData[fanId][4]; + _voltages[fanId].Value = _rawData[fanId][7] + _rawData[fanId][8] / 100.0f; + _currents[fanId].Value = _rawData[fanId][9] + _rawData[fanId][10] / 100.0f; + _powers[fanId].Value = _currents[fanId].Value * _voltages[fanId].Value; } + _noise.Value = _rawData[2][1]; } } diff --git a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/KrakenV3.cs b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/KrakenV3.cs index dd2acb0..6007de1 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/KrakenV3.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/KrakenV3.cs @@ -9,62 +9,53 @@ namespace LibreHardwareMonitor.Hardware.Controller.Nzxt; internal sealed class KrakenV3 : Hardware { private static readonly byte[] _getFirmwareInfo = { 0x10, 0x01 }; - private static readonly byte[] _status_req = { 0x74, 0x01 }; - private static readonly byte[] _setPumpTarget = new byte[64]; private static readonly byte[] _setFanTarget = new byte[64]; + private static readonly byte[] _setPumpTarget = new byte[64]; + private static readonly byte[] _statusRequest = { 0x74, 0x01 }; + private readonly Sensor _fan; + private readonly bool _fanControl; + private readonly Sensor _fanRpm; private readonly Sensor _pump; private readonly Sensor _pumpRpm; - private readonly Sensor _fan; - private readonly Sensor _fanRpm; private readonly byte[] _rawData = new byte[64]; private readonly HidStream _stream; - private readonly Sensor _temperature; - private readonly bool _fanControl; private readonly string _supportedFirmware; + private readonly Sensor _temperature; private volatile bool _controllingFans; private volatile bool _controllingPump; - private static void FillTargetArray(byte[] targetArray, byte value) - { - for (byte i = 4; i < targetArray.Length; i++) - targetArray[i] = value; - } - public KrakenV3(HidDevice dev, ISettings settings) : base("Nzxt Kraken Z", new Identifier("nzxt", "krakenz", dev.GetSerialNumber().TrimStart('0')), settings) { - if (dev.ProductID == 0x3008) + switch (dev.ProductID) { - Name = "NZXT Kraken Z3"; - _fanControl = true; - _supportedFirmware = "5.7.0"; - Array.Copy(new byte[] { 0x72, 0x01, 0x00, 0x00 }, 0, _setPumpTarget, 0, 4); - Array.Copy(new byte[] { 0x72, 0x02, 0x00, 0x00 }, 0, _setFanTarget, 0, 4); - - } - else if (dev.ProductID == 0x300C) - { - Name = "NZXT Kraken Elite"; - _fanControl = true; - _supportedFirmware = "1.2.4"; - Array.Copy(new byte[] { 0x72, 0x01, 0x01, 0x00 }, 0, _setPumpTarget, 0, 4); - Array.Copy(new byte[] { 0x72, 0x02, 0x01, 0x01 }, 0, _setFanTarget, 0, 4); - - } - else if (dev.ProductID == 0x300E) - { - Name = "NZXT Kraken"; - _fanControl = true; - _supportedFirmware = "1.2.4"; // Firmware version to be confirmed - Array.Copy(new byte[] { 0x72, 0x01, 0x01, 0x00 }, 0, _setPumpTarget, 0, 4); - Array.Copy(new byte[] { 0x72, 0x02, 0x01, 0x01 }, 0, _setFanTarget, 0, 4); - } - else - { - Name = "NZXT Kraken X3"; - _fanControl = false; - _supportedFirmware = "2.1.0"; - Array.Copy(new byte[] { 0x72, 0x01, 0x00, 0x00 }, 0, _setPumpTarget, 0, 4); + case 0x3008: + Name = "NZXT Kraken Z3"; + _fanControl = true; + _supportedFirmware = "5.7.0"; + Array.Copy(new byte[] { 0x72, 0x01, 0x00, 0x00 }, 0, _setPumpTarget, 0, 4); + Array.Copy(new byte[] { 0x72, 0x02, 0x00, 0x00 }, 0, _setFanTarget, 0, 4); + break; + case 0x300C: + Name = "NZXT Kraken Elite"; + _fanControl = true; + _supportedFirmware = "1.2.4"; + Array.Copy(new byte[] { 0x72, 0x01, 0x01, 0x00 }, 0, _setPumpTarget, 0, 4); + Array.Copy(new byte[] { 0x72, 0x02, 0x01, 0x01 }, 0, _setFanTarget, 0, 4); + break; + case 0x300E: + Name = "NZXT Kraken"; + _fanControl = true; + _supportedFirmware = "1.2.4"; // Firmware version to be confirmed + Array.Copy(new byte[] { 0x72, 0x01, 0x01, 0x00 }, 0, _setPumpTarget, 0, 4); + Array.Copy(new byte[] { 0x72, 0x02, 0x01, 0x01 }, 0, _setFanTarget, 0, 4); + break; + default: + Name = "NZXT Kraken X3"; + _fanControl = false; + _supportedFirmware = "2.1.0"; + Array.Copy(new byte[] { 0x72, 0x01, 0x00, 0x00 }, 0, _setPumpTarget, 0, 4); + break; } FillTargetArray(_setPumpTarget, 60); @@ -75,15 +66,19 @@ internal sealed class KrakenV3 : Hardware _stream.ReadTimeout = 5000; _stream.Write(_getFirmwareInfo); - do + + int tries = 0; + + while (FirmwareVersion == null && tries++ < 10) { _stream.Read(_rawData); + if (_rawData[0] == 0x11 && _rawData[1] == 0x01) - { FirmwareVersion = $"{_rawData[0x11]}.{_rawData[0x12]}.{_rawData[0x13]}"; - } } - while (FirmwareVersion == null); + + if (FirmwareVersion == null) + return; // Liquid temperature _temperature = new Sensor("Liquid", 0, SensorType.Temperature, this, Array.Empty(), settings); @@ -117,6 +112,8 @@ internal sealed class KrakenV3 : Hardware _fanRpm = new Sensor("Fans", 1, SensorType.Fan, this, Array.Empty(), settings); ActivateSensor(_fanRpm); } + + IsValid = true; } } @@ -124,33 +121,41 @@ internal sealed class KrakenV3 : Hardware public override HardwareType HardwareType => HardwareType.Cooler; - public string Status => FirmwareVersion != _supportedFirmware ? $"Status: Untested Firmware Version {FirmwareVersion}! Please consider Updating to Version {_supportedFirmware}" : "Status: OK"; + public bool IsValid { get; } + + public string Status => FirmwareVersion != _supportedFirmware ? $"Status: Untested firmware version {FirmwareVersion}! Please consider updating to version {_supportedFirmware}" : "Status: OK"; + + private static void FillTargetArray(byte[] targetArray, byte value) + { + for (byte i = 4; i < targetArray.Length; i++) + targetArray[i] = value; + } private void PumpSoftwareControlValueChanged(Control control) { try { - if (control.ControlMode == ControlMode.Software) + switch (control.ControlMode) { - float value = control.SoftwareValue; + case ControlMode.Software: + float value = control.SoftwareValue; - FillTargetArray(_setPumpTarget, (byte)(value > 100 ? 100 : value < 0 ? 0 : value)); + FillTargetArray(_setPumpTarget, (byte)(value > 100 ? 100 : value < 0 ? 0 : value)); - _controllingPump = true; - _stream.Write(_setPumpTarget); - _pump.Value = value; - } - else if (control.ControlMode == ControlMode.Default) - { - // There isn't a "default" mode with this pump, but a safe setting is 60% - FillTargetArray(_setPumpTarget, 60); - _stream.Write(_setPumpTarget); + _controllingPump = true; + _stream.Write(_setPumpTarget); + _pump.Value = value; + break; + case ControlMode.Default: + // There isn't a "default" mode with this pump, but a safe setting is 60% + FillTargetArray(_setPumpTarget, 60); + _stream.Write(_setPumpTarget); + break; } } catch (ObjectDisposedException) { // Could be unplugged, or the app is stopping... - return; } } @@ -158,26 +163,26 @@ internal sealed class KrakenV3 : Hardware { try { - if (control.ControlMode == ControlMode.Software) + switch (control.ControlMode) { - float value = control.SoftwareValue; - FillTargetArray(_setFanTarget, (byte)(value > 100 ? 100 : value < 0 ? 0 : value)); + case ControlMode.Software: + float value = control.SoftwareValue; + FillTargetArray(_setFanTarget, (byte)(value > 100 ? 100 : value < 0 ? 0 : value)); - _controllingFans = true; - _stream.Write(_setFanTarget); - _fan.Value = value; - } - else if (control.ControlMode == ControlMode.Default) - { - // There isn't a "default" mode with this fan, but a safe setting is 40% - FillTargetArray(_setFanTarget, 40); - _stream.Write(_setFanTarget); + _controllingFans = true; + _stream.Write(_setFanTarget); + _fan.Value = value; + break; + case ControlMode.Default: + // There isn't a "default" mode with this fan, but a safe setting is 40% + FillTargetArray(_setFanTarget, 40); + _stream.Write(_setFanTarget); + break; } } catch (ObjectDisposedException) { // Could be unplugged, or the app is stopping... - return; } } @@ -191,11 +196,13 @@ internal sealed class KrakenV3 : Hardware { try { - _stream.Write(_status_req); + _stream.Write(_statusRequest); + do { _stream.Read(_rawData); - } while (_rawData[0] != 0x75 || _rawData[1] != 0x1); + } + while (_rawData[0] != 0x75 || _rawData[1] != 0x1); _temperature.Value = _rawData[15] + (_rawData[16] / 10.0f); _pumpRpm.Value = (_rawData[18] << 8) | _rawData[17]; @@ -238,7 +245,6 @@ internal sealed class KrakenV3 : Hardware catch (ObjectDisposedException) { // Could be unplugged, or the app is stopping... - return; } } } diff --git a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/NzxtGroup.cs b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/NzxtGroup.cs index f8ffc05..267d168 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/NzxtGroup.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/Nzxt/NzxtGroup.cs @@ -36,18 +36,21 @@ internal class NzxtGroup : IGroup _report.AppendLine($"Firmware version: {krakenV3.FirmwareVersion}"); _report.AppendLine($"{krakenV3.Status}"); _report.AppendLine(); - _hardware.Add(krakenV3); - break; + if (krakenV3.IsValid) + _hardware.Add(krakenV3); + + break; case 0x1711: var gridv3 = new GridV3(dev, settings); _report.AppendLine($"Device name: {productName}"); _report.AppendLine($"Firmware version: {gridv3.FirmwareVersion}"); _report.AppendLine(); - _hardware.Add(gridv3); + + if (gridv3.IsValid) + _hardware.Add(gridv3); + break; - - default: _report.AppendLine($"Unknown Hardware PID: {dev.ProductID} Name: {productName}"); _report.AppendLine();