ASUS Ryzen and Threadripper motherboards with ITE superIO chips have a WMI interface in their BIOS that allows reading sensor values. This was originally implemented as an interface for monitoring software to use, as multiple applications accessing the SuperIO IC directly could cause lockups.
In this post I will explore how to query the WMI sensors interface from PowerShell.
First open a PowerShell console with administrator privileges:
There are two ways of querying WMI, the WMI commands, and the more recent and general CIM commands.I’m using the WMI methods as the syntax of the older commands is easier.
Now we can get a list of all WMI objects with ASUS in the name:
Get-CimClass -namespace root/WMI | Where-Object CimClassName -Match ".*ASUS.*"
NameSpace: ROOT/WMI
CimClassName CimClassMethods CimClassProperties
------------ --------------- ------------------
AsusWpbtWmi {get_wpbt_status} {Active, InstanceName}
ASUSHW {read_smbus_byte,... {Active, InstanceName}
ASUSManagement {initialize, set_... {Active, InstanceName}
The ASUSHW object looks interesting, lets see what methods are available on it
Get-CimClass -namespace root/WMI -ClassName ASUSHW | %{$_.CimClassMethods}
Name ReturnType Parameters Qualifiers
---- ---------- ---------- ----------
read_smbus_byte Boolean {cmd, slave, data, Result} {Implemented, WmiMethodId}
write_smbus_byte Boolean {cmd, data, slave, Result} {Implemented, WmiMethodId}
read_smbus_word Boolean {cmd, slave, data, Result} {Implemented, WmiMethodId}
write_smbus_word Boolean {cmd, data, slave, Result} {Implemented, WmiMethodId}
read_smbus_block Boolean {cmd, slave, data, Result} {Implemented, WmiMethodId}
write_smbus_block Boolean {cmd, count, data, slave...} {Implemented, WmiMethodId}
asio_hw_fun07 Boolean {wPort, bData} {Implemented, WmiMethodId}
asio_hw_fun08 Boolean {bData, wPort} {Implemented, WmiMethodId}
asio_hw_fun42 Boolean {wPort, wData} {Implemented, WmiMethodId}
asio_hw_fun43 Boolean {wData, wPort} {Implemented, WmiMethodId}
asio_hw_fun44 Boolean {wPort, dwData} {Implemented, WmiMethodId}
asio_hw_fun45 Boolean {dwData, wPort} {Implemented, WmiMethodId}
asio_hw_fun09 Boolean {dwAddr, Width, dwData} {Implemented, WmiMethodId}
asio_hw_fun10 Boolean {dwAddr, dwData, Width} {Implemented, WmiMethodId}
asio_hw_fun11 Boolean {Bus, Dev, Func, Reg...} {Implemented, WmiMethodId}
asio_hw_fun12 Boolean {Bus, Dev, dwData, Func...} {Implemented, WmiMethodId}
asio_hw_fun13 Boolean {Index, wIndexPort, Data} {Implemented, WmiMethodId}
asio_hw_fun14 Boolean {Data, Index, wIndexPort} {Implemented, WmiMethodId}
asio_hw_fun15 Boolean {Index, DataHi, DataLo} {Implemented, WmiMethodId}
asio_hw_fun16 Boolean {DataHi, DataLo, Index} {Implemented, WmiMethodId}
asio_hw_fun17 Boolean {Index, Eax, Ebx, Ecx...} {Implemented, WmiMethodId}
asio_hw_fun28 Boolean {Index, Data} {Implemented, WmiMethodId}
asio_hw_fun29 Boolean {Data, Index} {Implemented, WmiMethodId}
asio_hw_fun19 Boolean {Index, LDN, Data} {Implemented, WmiMethodId}
asio_hw_fun20 Boolean {Data, Index, LDN} {Implemented, WmiMethodId}
asio_hw_fun21 Boolean {Bank, Index, Data} {Implemented, WmiMethodId}
asio_hw_fun22 Boolean {Bank, Data, Index} {Implemented, WmiMethodId}
asio_hw_fun46 Boolean {LdnIndexArray, DataArray} {Implemented, WmiMethodId}
asio_hw_fun47 Boolean {LdnIndexDataArray} {Implemented, WmiMethodId}
asio_hw_fun23 Boolean {BankIndexArray, DataArray} {Implemented, WmiMethodId}
asio_hw_fun24 Boolean {BankIndexDataArray} {Implemented, WmiMethodId}
asio_hw_fun25 Boolean {BankIndexArray, DataArray} {Implemented, WmiMethodId}
asio_hw_fun26 Boolean {BankIndexDataArray} {Implemented, WmiMethodId}
sensor_get_value Boolean {Index, Data} {Implemented, WmiMethodId}
sensor_update_buffer Boolean {Source, Data} {Implemented, WmiMethodId}
sensor_get_info Boolean {Index, Data_Type, Location, Name...} {Implemented, WmiMethodId}
sensor_get_number Boolean {Data} {Implemented, WmiMethodId}
sensor_get_buffer_address Boolean {Address} {Implemented, WmiMethodId}
sensor_get_version Boolean {Data} {Implemented, WmiMethodId}
Sensor_get_version looks interesting, let’s call that:
$asushw = Get-CimInstance -Namespace root/wmi -ClassName ASUSHW
Invoke-CimMethod $asushw -MethodName sensor_get_version
Data ReturnValue PSComputerName
---- ----------- --------------
3 True
OK great, now let’s see how many sensors we have:
Invoke-CimMethod $asushw -MethodName sensor_get_number
Data ReturnValue PSComputerName
---- ----------- --------------
32 True
Awesome, 32 sensors!
Right so now lets see what the info about each of the sensors:
0..31 | %{Invoke-CimMethod $asushw -MethodName sensor_get_info -Arguments @{Index=$_ } } | Format-Table
Data_Type Location Name Source Type ReturnValue PSComputerName
--------- -------- ---- ------ ---- ----------- --------------
3 0 CPU Core Voltage 1 0 True
3 1 CPU SOC Voltage 1 0 True
3 2 DRAM Voltage 1 0 True
3 3 VDDP Voltage 1 0 True
3 3 1.8V PLL Voltage 1 0 True
3 3 +12V Voltage 1 0 True
3 3 +5V Voltage 1 0 True
3 3 3VSB Voltage 1 0 True
3 3 VBAT Voltage 1 0 True
3 3 AVCC3 Voltage 1 0 True
0 0 CPU Temperature 1 1 True
0 0 CPU Socket Temperature 1 1 True
0 3 Motherboard Temperature 1 1 True
1 3 CPU Fan 1 2 True
1 3 Chassis Fan 1 1 2 True
1 3 Chassis Fan 2 1 2 True
1 3 Chassis Fan 3 1 2 True
1 3 HAMP Fan 1 2 True
1 3 Water Pump 1 2 True
3 3 SB 1.05V Voltage 2 0 True
0 4 Chipset Temperature 2 1 True
0 5 Tsensor 1 Temperature 2 1 True
0 6 CPU VRM Temperature 2 1 True
1 6 CPU VRM Output Current 2 3 True
1 3 CPU OPT 2 2 True
0 7 Water In 2 1 True
0 7 Water Out 2 1 True
1 7 Water Flow 2 4 True
1 3 AIO Pump 2 2 True
3 0 CPU Core Voltage 2 0 True
3 1 CPU SOC Voltage 2 0 True
3 2 DRAM Voltage 2 0 True
Okay, cool.
Let’s get the value for the CPU VRM temperature. That has a source of 2, so first let’s update buffer 2:
%{Invoke-CimMethod $asushw -MethodName sensor_update_buffer -Arguments @{Source=2 } }
Data ReturnValue PSComputerName
---- ----------- --------------
0 True
Now we can read the value for sensor 22
%{Invoke-CimMethod $asushw -MethodName sensor_get_value -Arguments @{Index=22 } }
Data ReturnValue PSComputerName
---- ----------- --------------
56 True
The same effect could also be achieved using the older WMI commands, which also make it easier to pass parameters to the methods:
get-WmiObject -Namespace "root\WMI" -List | Where-Object Name -Match ".*ASUS.*"
get-WmiObject -class ASUSHW -Namespace "root\WMI" | Get-Member -MemberType method
$asushw = get-WmiObject -class ASUSHW -Namespace root\WMI -Impersonation Impersonate
$asushw.sensor_get_version()
$asushw.sensor_update_buffer(2)
$asushw.sensor_get_value(22)
Finally, all these commands can be combined together into a program to report on all the sensor values
# Asus WMI test sensor program for Windows
# Tested on the Asus Crosshair VII
# Run as administrator
function getUnits($type) {
return $(switch ($type) {
0 { "V" }
1 { "C" }
2 { "RPM" }
3 { "A" }
4 { "L/h" }
})
}
function getScaledValue($val, $Data_Type) {
return $(If ($Data_Type -eq 3) { $val / 1000000 } else { $val });
}
$asushw = get-WmiObject -class ASUSHW -Namespace root\WMI -Impersonation Impersonate
if ($asushw.sensor_get_version().Data -le 2) {
Write-Output "Only supports ASUSHW >= v2"
return
}
0..($asushw.sensor_get_number().Data - 1) | ForEach-Object {
$sensor = $asushw.sensor_get_info($_)
if ($currentSource -ne $sensor.Source) {
$asushw.sensor_update_buffer($sensor.Source) > $null
$currentSource = $sensor.Source
}
return New-Object -TypeName psobject -Property @{
Value = "$(getScaledValue -val $asushw.sensor_get_value($_).Data -Data_Type $sensor.Data_Type) $(getUnits -type $sensor.Type)"
Name = $sensor.Name
}
} | Format-Table
PS C:\WINDOWS\system32> C:\Users\ebwib\asus-sensors.ps1
Name Value
---- -----
CPU Core Voltage 1.3734 V
CPU SOC Voltage 1.1227 V
DRAM Voltage 1.3298 V
VDDP Voltage 0.6213 V
1.8V PLL Voltage 1.853 V
+12V Voltage 11.663 V
+5V Voltage 4.98675 V
3VSB Voltage 3.3354 V
VBAT Voltage 3.2046 V
AVCC3 Voltage 3.379 V
CPU Temperature 72 C
CPU Socket Temperature 51 C
Motherboard Temperature 34 C
CPU Fan 1371 RPM
Chassis Fan 1 0 RPM
Chassis Fan 2 1153 RPM
Chassis Fan 3 1119 RPM
HAMP Fan 1138 RPM
Water Pump 0 RPM
SB 1.05V Voltage 1.071875 V
Chipset Temperature 48 C
Tsensor 1 Temperature 216 C
CPU VRM Temperature 56 C
CPU VRM Output Current 58 A
CPU OPT 1378 RPM
Water In 216 C
Water Out 35 C
Water Flow 0 L/h
AIO Pump 1358 RPM
CPU Core Voltage 1.386 V
CPU SOC Voltage 1.13 V
DRAM Voltage 1.36 V