WindowsでCPUパッケージ・コア温度をPowerShellで取得する

1.28インチ丸形ディスプレイにCPU温度を表示するというデバイスを作りました。
これ自体はシリアルで温度を受け取り、LVGLでグラフや数字を描画するという簡単なものです。

CPU温度の取得はPC(Windows)上で動くプログラムで取得して送信しています。

CPU温度といってもマザーボード上のセンサやCPUに内蔵されたパッケージおよびコアの温度など、いろいろあります。
今回はCPUのパッケージ温度や平均コア温度を取得したかったのですが、いざやってみるとプログラムから簡単に取得できる方法が見つかりにくく手こずりました。

検索すると出てくるのが、管理者権限のあるPowerShellで以下のように取得する方法。単位はケルビンの10倍で出てきます。

(Get-WmiObject MSAcpi_ThermalZoneTemperature -Namespace "root/wmi").CurrentTemperature

しかしこの方法ではマザーボードにも依存するのかもしれませんが常に一定の値しか取れず、有効ではありませんでした。

他の方法として、LibreHardwareMonitor というOSSのDLLを利用する方法を見つけました。
github.com

これはOpen Hardware Monitorというツールの後継として開発されているもので、マザーボードやCPU,GPUなどの温度などの計測値を取得できるツールで、GUIでも閲覧できるものですが、DLL単体から関数を呼んで利用することも可能になっています。

上記GitHubページのReleasesから最新版のZIPファイルを取得できます。
なお最近のWindowsではインターネットから取得したDLLをロードしようとするとデフォルトでブロックされるようになっているため、ダウンロード・展開後に LibreHardwareMonitorLib.dll のプロパティを開き、ブロックの解除にチェックをつけてやる必要があります。

このDLLを利用して、以下のようにPowerShellからCPU温度などを取得することができます。
以下ではCPUの各コアの温度とその平均、およびCPUパッケージ温度を取得しています。
また、パッケージ温度についてはシリアルポートにも書き出しており、丸形ディスプレイの表示に反映させています。

# シリアルポートを開く
$c = New-Object System.IO.Ports.SerialPort "COM3", 115200, ([System.IO.Ports.Parity]::None)
$c.NewLine = "`r"
$c.Open()
$c.DiscardInBuffer()

# DLLを読み込み
$dll = ".\LibreHardwareMonitor-net472\LibreHardwareMonitorLib.dll"
Add-Type -Path $dll

# 1秒ごとに温度取得
while ($true) {
    $temp = 0
    $count = 0
    $pkg = 0

    $monitor = [LibreHardwareMonitor.Hardware.Computer]::new()
    $monitor.IsCPUEnabled = $true
    $monitor.Open()
    foreach ($sensor in $monitor.Hardware.Sensors) {
        if ($sensor.SensorType -eq 'Temperature' -and $sensor.Name -eq "CPU Package") {
            $pkg = $sensor.Value
        }
        if ($sensor.SensorType -eq 'Temperature' -and $sensor.Name.Startswith('CPU Core #') -and -not $sensor.Name.Contains("Distance")) {
            write-host $sensor.Name, ":", $sensor.Value
            $temp += $sensor.Value
            $count++
        }
    }
    $monitor.Close()

    $avg = [math]::Round($temp / $count)
    write-host "CPU Core Average : ", $avg -f y
    write-host "CPU Package :      ", $pkg -f y

    # 温度をシリアルに出力
    $c.WriteLine($pkg)

    sleep 1
}

自動起動したいところですが、管理者権限も必要だし、どうせならサービス化したほうが良いので、下記記事の方法を使うのがよさそうです。
qiita.com