/**
* Oshi (https://github.com/oshi/oshi)
*
* Copyright (c) 2010 - 2017 The Oshi Project Team
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Maintainers:
* dblock[at]dblock[dot]org
* widdis[at]gmail[dot]com
* enrico.bianchi[at]gmail[dot]com
*
* Contributors:
* https://github.com/oshi/oshi/graphs/contributors
*/
package oshi.hardware.platform.windows;
import java.util.List;
import java.util.Map;
import oshi.hardware.Sensors;
import oshi.util.platform.windows.WmiUtil;
public class WindowsSensors implements Sensors {
private static final long serialVersionUID = 1L;
// Successful (?) WMI namespace, path and property
private String wmiTempNamespace = null;
private String wmiTempClass = null;
private String wmiTempProperty = null;
// Successful (?) WMI path and property
private String wmiVoltNamespace = null;
private String wmiVoltClass = null;
private String wmiVoltProperty = null;
/**
* {@inheritDoc}
*/
@Override
public double getCpuTemperature() {
// Initialize
double tempC = 0d;
// Attempt to fetch value from Open Hardware Monitor if it is running
String cpuIdentifier = WmiUtil.selectStringFrom("root\\OpenHardwareMonitor", "Hardware", "Identifier",
"WHERE HardwareType=\"CPU\"");
if (cpuIdentifier.length() > 0) {
Map<String, List<Float>> vals = WmiUtil.selectFloatsFrom("root\\OpenHardwareMonitor", "Sensor", "Value",
"WHERE Parent=\"" + cpuIdentifier + "\" AND SensorType=\"Temperature\"");
if (!vals.get("Value").isEmpty()) {
double sum = 0;
for (double val : vals.get("Value")) {
sum += val;
}
tempC = sum / vals.get("Value").size();
}
return tempC;
}
// If we get this far, OHM is not running.
// Try to get from conventional WMI
long tempK;
if (this.wmiTempClass == null) {
this.wmiTempNamespace = "root\\cimv2";
this.wmiTempClass = "Win32_Temperature";
this.wmiTempProperty = "CurrentReading";
tempK = WmiUtil.selectUint32From(this.wmiTempNamespace, this.wmiTempClass, this.wmiTempProperty, null);
if (tempK == 0) {
this.wmiTempClass = "Win32_TemperatureProbe";
tempK = WmiUtil.selectUint32From(this.wmiTempNamespace, this.wmiTempClass, this.wmiTempProperty, null);
}
if (tempK == 0) {
this.wmiTempClass = "Win32_PerfFormattedData_Counters_ThermalZoneInformation";
this.wmiTempProperty = "Temperature";
tempK = WmiUtil.selectUint32From(this.wmiTempNamespace, this.wmiTempClass, this.wmiTempProperty, null);
}
if (tempK == 0) {
this.wmiTempNamespace = "root\\wmi";
this.wmiTempClass = "MSAcpi_ThermalZoneTemperature";
this.wmiTempProperty = "CurrentTemperature";
tempK = WmiUtil.selectUint32From(this.wmiTempNamespace, this.wmiTempClass, this.wmiTempProperty, null);
}
} else {
// We've successfully read a previous time, or failed both here and
// with OHM, so keep using same values
tempK = WmiUtil.selectUint32From(this.wmiTempNamespace, this.wmiTempClass, this.wmiTempProperty, null);
}
// Convert K to C and return result
if (tempK > 2732) {
tempC = tempK / 10d - 273.15;
} else if (tempK > 274) {
tempC = tempK - 273d;
}
if (tempC <= 0d) {
// Unable to get temperature via WMI.
tempC = 0d;
}
return tempC;
}
/**
* {@inheritDoc}
*/
@Override
public int[] getFanSpeeds() {
// Initialize
int[] fanSpeeds = new int[1];
// Attempt to fetch value from Open Hardware Monitor if it is running
String cpuIdentifier = WmiUtil.selectStringFrom("root\\OpenHardwareMonitor", "Hardware", "Identifier",
"WHERE HardwareType=\"CPU\"");
if (cpuIdentifier.length() > 0) {
Map<String, List<Float>> vals = WmiUtil.selectFloatsFrom("root\\OpenHardwareMonitor", "Sensor", "Value",
"WHERE Parent=\"" + cpuIdentifier + "\" AND SensorType=\"Fan\"");
if (!vals.get("Value").isEmpty()) {
fanSpeeds = new int[vals.get("Value").size()];
for (int i = 0; i < vals.get("Value").size(); i++) {
fanSpeeds[i] = vals.get("Value").get(i).intValue();
}
}
return fanSpeeds;
}
// If we get this far, OHM is not running.
// Try to get from conventional WMI
int rpm = WmiUtil.selectUint32From(null, "Win32_Fan", "DesiredSpeed", null).intValue();
// Set in array and return
if (rpm > 0) {
fanSpeeds[0] = rpm;
}
return fanSpeeds;
}
/**
* {@inheritDoc}
*/
@Override
public double getCpuVoltage() {
// Initialize
double volts = 0d;
// Attempt to fetch value from Open Hardware Monitor if it is running
Map<String, List<String>> voltIdentifiers = WmiUtil.selectStringsFrom("root\\OpenHardwareMonitor", "Hardware",
"Identifier", "WHERE SensorType=\"Voltage\"");
// Look for identifier containing "cpu"
String voltIdentifierStr = null;
for (String id : voltIdentifiers.get("Identifier")) {
if (id.toLowerCase().contains("cpu")) {
voltIdentifierStr = id;
break;
}
}
// If none contain cpu just grab the first one
if (voltIdentifierStr == null && !voltIdentifiers.get("Identifier").isEmpty()) {
voltIdentifierStr = voltIdentifiers.get("Identifier").get(0);
}
if (voltIdentifierStr != null) {
return WmiUtil.selectFloatFrom("root\\OpenHardwareMonitor", "Sensor", "Value",
"WHERE Parent=\"" + voltIdentifierStr + "\" AND SensorType=\"Voltage\"");
}
// If we get this far, OHM is not running.
// Try to get from conventional WMI
int decivolts;
if (this.wmiVoltClass == null) {
this.wmiVoltNamespace = "root\\cimv2";
this.wmiVoltClass = "Win32_Processor";
this.wmiVoltProperty = "CurrentVoltage";
decivolts = WmiUtil.selectUint32From(this.wmiVoltNamespace, this.wmiVoltClass, this.wmiVoltProperty, null)
.intValue();
// If the eighth bit is set, bits 0-6 contain the voltage
// multiplied by 10. If the eighth bit is not set, then the bit
// setting in VoltageCaps represents the voltage value.
if ((decivolts & 0x80) == 0 && decivolts > 0) {
this.wmiVoltProperty = "VoltageCaps";
// really a bit setting, not decivolts, test later
decivolts = WmiUtil
.selectUint32From(this.wmiVoltNamespace, this.wmiVoltClass, this.wmiVoltProperty, null)
.intValue();
}
} else {
// We've successfully read a previous time, or failed both here and
// with OHM
decivolts = WmiUtil.selectUint32From(this.wmiVoltNamespace, this.wmiVoltClass, this.wmiVoltProperty, null)
.intValue();
}
// Convert dV to V and return result
if (decivolts > 0) {
if ("VoltageCaps".equals(this.wmiVoltProperty)) {
// decivolts are bits
if ((decivolts & 0x1) > 0) {
volts = 5.0;
} else if ((decivolts & 0x2) > 0) {
volts = 3.3;
} else if ((decivolts & 0x4) > 0) {
volts = 2.9;
}
} else {
// Value from bits 0-6
volts = (decivolts & 0x7F) / 10d;
}
}
return volts;
}
}