diff --git a/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquaComputerGroup.cs b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquaComputerGroup.cs index 44fc1e3..69c78a8 100644 --- a/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquaComputerGroup.cs +++ b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/AquaComputerGroup.cs @@ -56,6 +56,15 @@ namespace LibreHardwareMonitor.Hardware.Controller.AquaComputer _hardware.Add(device); break; } + case 0xF011: + { + var device = new Octo(dev, settings); + _report.AppendLine($"Device name: {productName}"); + _report.AppendLine($"Firmware version: {device.FirmwareVersion}"); + _report.AppendLine(); + _hardware.Add(device); + break; + } default: { _report.AppendLine($"Unknown Hardware PID: {dev.ProductID} Name: {productName}"); diff --git a/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/Octo.cs b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/Octo.cs new file mode 100644 index 0000000..12613c1 --- /dev/null +++ b/LibreHardwareMonitorLib/Hardware/Controller/AquaComputer/Octo.cs @@ -0,0 +1,188 @@ +// 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; +using HidSharp; + +namespace LibreHardwareMonitor.Hardware.Controller.AquaComputer +{ + internal sealed class Octo : Hardware + { + private readonly byte[] _rawData = new byte[1025]; + private readonly Sensor[] _rpmSensors = new Sensor[8]; + private readonly HidStream _stream; + private readonly Sensor[] _temperatures = new Sensor[4]; + private readonly Sensor[] _voltages = new Sensor[9]; + private readonly Sensor[] _currents = new Sensor[8]; + private readonly Sensor[] _powers = new Sensor[8]; + + public Octo(HidDevice dev, ISettings settings) : base("Octo", new Identifier(dev.DevicePath), settings) + { + if (dev.TryOpen(out _stream)) + { + //Reading output report instead of feature report, as the measurements are in the output report + _stream.Read(_rawData); + + Name = $"OCTO"; + FirmwareVersion = GetConvertedValue(OctoDataIndexes.FIRMWARE_VERSION).GetValueOrDefault(0); + + // Initialize the 4 temperature sensors + for (int i = 0; i < 4; i++) + { + _temperatures[i] = new Sensor($"Temperature {i+1}", i, SensorType.Temperature, this, Array.Empty(), settings); + ActivateSensor(_temperatures[i]); + } + + // Initialize the 8 fan speed sensors + for (int i = 0; i < 8; i++) + { + _rpmSensors[i] = new Sensor($"Fan {i+1}", i, SensorType.Fan, this, Array.Empty(), settings); + ActivateSensor(_rpmSensors[i]); + } + + // Initialize the input voltage sensor + _voltages[0] = new Sensor("Input", 0, SensorType.Voltage, this, Array.Empty(), settings); + ActivateSensor(_voltages[0]); + + // Initialize the 8 fan voltage sensors + for (int i = 1; i < 9; i++) + { + _voltages[i] = new Sensor($"Fan {i}", i, SensorType.Voltage, this, Array.Empty(), settings); + ActivateSensor(_voltages[i]); + } + + // Initialize the 8 fan current sensors + for (int i = 0; i < 8; i++) + { + _currents[i] = new Sensor($"Fan {i+1}", i, SensorType.Current, this, Array.Empty(), settings); + ActivateSensor(_currents[i]); + } + + // Initialize the 8 fan power sensors + for (int i = 0; i < 8; i++) + { + _powers[i] = new Sensor($"Fan {i+1}", i, SensorType.Power, this, Array.Empty(), settings); + ActivateSensor(_powers[i]); + } + } + } + + public ushort FirmwareVersion { get; private set; } + + public override HardwareType HardwareType + { + get { return HardwareType.Cooler; } + } + + public override void Close() + { + _stream.Close(); + base.Close(); + } + + public override void Update() + { + //Reading output report instead of feature report, as the measurements are in the output report + _stream.Read(_rawData); + + _temperatures[0].Value = GetConvertedValue(OctoDataIndexes.TEMP_1) / 100f; // Temp 1 + _temperatures[1].Value = GetConvertedValue(OctoDataIndexes.TEMP_2) / 100f; // Temp 2 + _temperatures[2].Value = GetConvertedValue(OctoDataIndexes.TEMP_3) / 100f; // Temp 3 + _temperatures[3].Value = GetConvertedValue(OctoDataIndexes.TEMP_4) / 100f; // Temp 4 + + _rpmSensors[0].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_1); // Fan 1 speed + _rpmSensors[1].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_2); // Fan 2 speed + _rpmSensors[2].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_3); // Fan 3 speed + _rpmSensors[3].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_4); // Fan 4 speed + _rpmSensors[4].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_5); // Fan 5 speed + _rpmSensors[5].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_6); // Fan 6 speed + _rpmSensors[6].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_7); // Fan 7 speed + _rpmSensors[7].Value = GetConvertedValue(OctoDataIndexes.FAN_SPEED_8); // Fan 8 speed + + _voltages[0].Value = GetConvertedValue(OctoDataIndexes.VOLTAGE) / 100f; // Input voltage + _voltages[1].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_1) / 100f; // Fan 1 voltage + _voltages[2].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_2) / 100f; // Fan 2 voltage + _voltages[3].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_3) / 100f; // Fan 3 voltage + _voltages[4].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_4) / 100f; // Fan 4 voltage + _voltages[5].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_5) / 100f; // Fan 5 voltage + _voltages[6].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_6) / 100f; // Fan 6 voltage + _voltages[7].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_7) / 100f; // Fan 7 voltage + _voltages[8].Value = GetConvertedValue(OctoDataIndexes.FAN_VOLTAGE_8) / 100f; // Fan 8 voltage + + _currents[0].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_1) / 1000f; // Fan 1 current + _currents[1].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_2) / 1000f; // Fan 2 current + _currents[2].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_3) / 1000f; // Fan 3 current + _currents[3].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_4) / 1000f; // Fan 4 current + _currents[4].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_5) / 1000f; // Fan 5 current + _currents[5].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_6) / 1000f; // Fan 6 current + _currents[6].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_7) / 1000f; // Fan 7 current + _currents[7].Value = GetConvertedValue(OctoDataIndexes.FAN_CURRENT_8) / 1000f; // Fan 8 current + + _powers[0].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_1) / 100f; // Fan 1 power + _powers[1].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_2) / 100f; // Fan 2 power + _powers[2].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_3) / 100f; // Fan 3 power + _powers[3].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_4) / 100f; // Fan 4 power + _powers[4].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_5) / 100f; // Fan 5 power + _powers[5].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_6) / 100f; // Fan 6 power + _powers[6].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_7) / 100f; // Fan 7 power + _powers[7].Value = GetConvertedValue(OctoDataIndexes.FAN_POWER_8) / 100f; // Fan 8 power + } + + private sealed class OctoDataIndexes + { + public const int FIRMWARE_VERSION = 13; + + public const int TEMP_1 = 61; + public const int TEMP_2 = 63; + public const int TEMP_3 = 65; + public const int TEMP_4 = 67; + + public const int FAN_SPEED_1 = 133; + public const int FAN_SPEED_2 = 146; + public const int FAN_SPEED_3 = 159; + public const int FAN_SPEED_4 = 172; + public const int FAN_SPEED_5 = 185; + public const int FAN_SPEED_6 = 198; + public const int FAN_SPEED_7 = 211; + public const int FAN_SPEED_8 = 224; + + public const int FAN_POWER_1 = 131; + public const int FAN_POWER_2 = 144; + public const int FAN_POWER_3 = 157; + public const int FAN_POWER_4 = 170; + public const int FAN_POWER_5 = 183; + public const int FAN_POWER_6 = 196; + public const int FAN_POWER_7 = 209; + public const int FAN_POWER_8 = 222; + + public const int VOLTAGE = 117; + public const int FAN_VOLTAGE_1 = 127; + public const int FAN_VOLTAGE_2 = 140; + public const int FAN_VOLTAGE_3 = 153; + public const int FAN_VOLTAGE_4 = 166; + public const int FAN_VOLTAGE_5 = 179; + public const int FAN_VOLTAGE_6 = 192; + public const int FAN_VOLTAGE_7 = 205; + public const int FAN_VOLTAGE_8 = 218; + + public const int FAN_CURRENT_1 = 129; + public const int FAN_CURRENT_2 = 142; + public const int FAN_CURRENT_3 = 155; + public const int FAN_CURRENT_4 = 168; + public const int FAN_CURRENT_5 = 181; + public const int FAN_CURRENT_6 = 194; + public const int FAN_CURRENT_7 = 207; + public const int FAN_CURRENT_8 = 220; + } + + private ushort? GetConvertedValue(int index) + { + if (_rawData[index] == sbyte.MaxValue) + return null; + + return Convert.ToUInt16(_rawData[index + 1] | (_rawData[index] << 8)); + } + } +}