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
}

スマートロック SESAME5 をスマホでもESP32でも操作できるように

スマートロックSESAME5

安価でいろいろな鍵に対応したスマートロック SESAME5 を導入しました。

https://jp.candyhouse.co/products/sesame5?variant=40074599792703【New】SESAME5

SESAMEの素晴らしいところは、スマホアプリでの操作はもちろん、Web APIの対応、さらにはBluetoothSDKまで公開されているところです(約一月前に公開されました)。

Web API の利用は手軽ですが、デメリットはWiFiモジュールが別途必要になる点、月に3000回を超えるAPI呼び出しは有料となる点です。
無料で使うとすると90秒に1度の状態取得が限界となるので、リアルタイムに反応するようなアプリケーションを作るのは厳しいでしょう。

そんな時はBluetoothSDKを使用することになります。SDKiOS/Mac向けAndroid 向け、 そしてなんと ESP32 向け が用意されています。今回はこの ESP32 向けを使ってみました。

続きを読む

AD-HD26TC のおかげでM1 MacBook ProでスマートグラスMOVERIO BT-40が使えるようになった

エプソンのMOVERIO BT-40というスマートグラスがあります。

エプソン MOVERIO スマートグラス BT-40
これはUSB Type-C DP Alt Mode出力に対応したPCやスマートフォンなどに接続して、FullHD (1920x1080) 60Hzの映像を仮想的な大画面で楽しめるというものです。
専用コントローラ(Androidバイスらしい)付きのモデルもあるのですが、コントローラなしのモデルをもっぱらディスプレイとして映像鑑賞などに使っていました。


過去形なのは、Intel CPUなMacBook Proでは全く問題なく使えていたのですが、M1のMacBook Proに接続するとなぜか映像が一瞬映っては消えてを繰り返すという状態になっていまい、互換性がないのかと諦めていたためです。


ところが最近、HDMI端子の出力をUSB Type-C DP Alt Mode接続に変換してくれるという、ありそうでなかったアダプタが発売されたのを見つけました。

サンワサプライ HDMI-Type-C(DP Altモード)変換アダプタ(4K/60Hz) AD-HD26TC

これはUSB Type-C接続で映像と電源を受け取るタイプのモバイルディスプレイを、HDMIしか出力できないデバイスで使うことが想定されている商品のようです。このスマートグラスでも入力方法は同じと言えるので、これを使ってM1 MacBook ProのHDMI出力に繋げば正常に動作するのでは?と思い試してみることにしました。*1


実際に試してみると、USB Type-C 接続の時と違って、途切れたりすることなく映像が出力できることが確認できました。EDIDもきちんと伝送され機種名や対応解像度もきちんと認識されます。
さらに意外なことに、給電用と書かれたUSBは実は出力先のデバイスのUSBの信号をパススルーしているようで、スマートグラスに搭載されたセンサーやUSBサウンドデバイスまで認識されました!
ただし、画面の最上部の1ピクセルに白い線が表示されたり消えたりを繰り返すという現象が起きるようです。 Windows PCに接続した場合も発生するので、アダプタとの相性でしょうか。。まあこれは白いメニューバーが表示されている状態ではほとんど気になりませんので、再び使えるようになったと言って良いのではないかな?と思います。


しかしMacとディスプレイの相性問題を気にしなければならないとは、ちょっと20年くらい前の話みたいですね。。

*1:M1 MacBook ProのUSB Type-CからHDMI変換器を通すと映らないが、HDMIポート直接接続なら映るという似たような現象を古い別のモニタでも経験したこともあります。この時もIntel Macでは変換器経由で動作していたので、おそらくM1 MacのUSB Type-Cからの映像出力には何らか対応範囲が狭いという問題があるのでしょう。。

macOS 13 Ventura で全ての通知を閉じるスクリプト

macOSの通知で、個々の通知をクリックするまで残しておきたいケースでは、通知のスタイルを「通知パネル」にし、かつ「通知をグループ化」をオフにして利用します。
(私の場合は Slack の自分宛メッセージの通知などでこうしています。)

しかし、時には通知が(場合によっては自動的に)大量に発行され、画面に大量に溜まってしまう、なんていうこともあります。
こんな時に一気に閉じたくなりますがそういったボタンはなく、連打してもゆっくり消えるアニメーションが入るためになかなか閉じられずにストレスになります。。

そんな時のために一気に閉じる AppleScript を用意しておくと良いでしょう。
似たようなスクリプトはあちこちで見つかりますが、内部的な通知センターのUIの作りに依存しているため、OSのバージョンが異なったりすると動作しません。
以下は Ventura で動作を確認しているものです。

なお、各通知に対して下から順番に閉じるアクションを発行してもなぜか一部の通知が閉じずに残ったりする時があるので、何度かループしてやり直すという苦肉の策をとっています。

スクリプトエディタに下記を入力して、アプリケーションとして保存してダブルクリックで利用できます。なお初回実行時に許可を求められるので、保存したアプリケーションを「設定 > プライバシーとセキュリティ」の「オートメーション」と「アクセシビリティ」でアクセスを許可しておく必要があります。


activate application "NotificationCenter"
tell application "System Events"
	tell process "NotificationCenter"
		tell UI element 1 of scroll area 1 of group 1 of window "Notification Center"
			set loop to true
			
			repeat while loop
				set theWindows to every UI element as list
				set n to (count theWindows)
				set closedCount to 0
				repeat with i from n to 1 by -1
					try
						set theWindow to item i of theWindows
						set theActions to actions of theWindow
						repeat with theAction in theActions
							if description of theAction is "Close" then
								tell theWindow
									set closedCount to closedCount + 1
									perform theAction
									exit repeat
								end tell
							end if
						end repeat
					end try
				end repeat
				if closedCount = 0 then
					set loop to false
				end if
			end repeat
		end tell
	end tell
end tell

安価なToFセンサ MaixSense-A010

MaixSense-A010 (または MetaSense A010 ) という3Dデプスセンサ(ToFセンサ)がSipeedから発売されていたので使用してみました。
100x100の解像度で、2.5mまでの距離を8bit精度で、最大19psで取得できるという性能を持っています。
接続はUSB Type-Cとシリアルを利用できます (後述しますが、シリアル接続だと100x100 最大fpsでの利用は厳しめです)。
下記写真のようにLCDを搭載したモデルもあり、これだと他にマイコン等を使うことなく手軽に動作や視野の確認ができて便利です。

下記はAmazon.co.jpのリンクですが、慣れている人はSeeed studioやAliExpress等で購入した方が安く(おそらく5000円前後くらいで)購入できます。

Sipeed MaixSense A010

使い方

PC用のツールで画像取得でき、こちらのWikiに方法がまとまっています。
が、今回はこちらは使わず、プログラムからデータを取得してみました。

USB接続すると、2つのシリアルポート(FTDI)として認識されます。そのうち若い番号のほうでコマンド送信やデータの受信をします。なおこのUSBシリアルでは通信速度設定などは無視されます。

$ lsusb
Bus 001 Device 004: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 011: ID 0403:6010 Future Technology Devices International, Ltd FT2232C/D/H Dual UART/FIFO IC

ATコマンドを送って、転送開始や解像度・fps設定などを指示をします。
最も単純には、データ送信先としてUSBを指定し、ISP(画像信号処理)を開始させる2つのコマンドを送ればOKです。

MaixSense-A010 Development - Sipeed Wiki

この時注意点として、データ送信先としてシリアルを指定すると、1fps程度でしかデータが取得できなくなります。これはシリアルの通信速度がデフォルトだと115200bpsであり、これでは100x100x8bitのデータはせいぜい1秒に1枚程度を送るのが限界だからで、USBやLCDもそれに引きづられるためです。シリアルの速度を AT+BAUD=コマンドで上げればfpsも上がりますが、ESP32マイコンのHardwareSerialで受信してみた限りでは230400bpsが限界で、それ以上にしてしまうと同期が取れずに正常にデータが受信できませんでした。このためシリアルしか接続手段のないマイコン等では解像度またはfpsを下げないと厳しいと思われます。

USBであれば通信速度の問題はありませんので、マイコンを使うならRaspberryPi等USBが使えるものが良いでしょう。ただしちょくちょくdmesgを見ているとパケットロストのようなエラーが出たりハングしたりするので、下記プログラムではエラーチェックやリトライは厳しめにしています。

データフォーマットも上記にWikiにある通りですが、ざっくり下記のようなフォーマットで流れてきます。

<ff> <00> <size (little endian 2byte)> <header (16B)> <data (10000B)> <checksum (1B)> <0xdd>

これをパースして、WebSocketに流すプログラムをRubyで書いてみました。

続きを読む

冷凍庫の温度変化を無線センサーで測ってみた

冷凍庫にちょっとまだ暖かいものを入れた時、周囲のものにどれくらい影響があるのか気になりませんか? ということで、小型の無線センサーで温度変化を計測してみました。

使用機器

TWELITE ARIAは小型の無線センサータグです。-30℃〜85℃の温度範囲を0.01℃の分解能で計測できるため、冷凍庫でも動作するはず。
温湿度や扉の開閉等を磁気で計測して無線送信でき、2.5cm × 2.5cm × 1.0cm と小型です。コイン型電池(CR2032)1つで動作し、1分ごとの計測だと4年以上も動作するという省電力も良いですね。

BLUE(送信出力1mW)とRED(10mW)があり、冷凍庫の壁で隔てられた内側から送信することもあってRED版を使います。というか出力以外はほぼ同スペックのようなので、ほとんどのケースでREDを選ぶのが良さそうです。

モノワイヤレス 磁気・湿度・温度センサー無線タグ TWELITE ARIA RED


受信機として、USB接続できるMONOSTICKがあると簡単です。

モノワイヤレス USBスティック MONOSTICK レッド

セットアップ

初期設定として、送信チャンネルなどを設定します。設定方法はMONOSTICK側から設定を送信するOTAか、シリアルで直接接続して行います。
今回はすでに他の用途でMONOSTICKを使用していたので、それに合わせるようにシリアルで設定を行いました。

設定用のUSBアダプタ も販売されていますが、適当な3.3V FTDI - USBボードをすでに持っていればそれでも問題ありません。適当なターミナルソフトウェアで115200bpsでUSB FTDIにシリアル接続しておき、バッテリーを抜いてシリアルTX/RXと電源をARIAに接続します。SET端子をGNDに落とした状態でRSTをLO→HIにしてリセットをかけると,シリアルに以下のようなメニューが出てきて設定を行えます。

 a: set Application ID (0xabcd1234) 
 i: set Device ID (42=0x2a)
 c: set Channels (12)
 x: set Tx Power (13) 
 b: set UART baud (38400) 
 B: set UART option (8N1) 
 k: set Enc Key (0xa5a5a5a5)
 o: set Option Bits (0x00000000) 
 t: set Transmission Interval (15) 
 p: set Senser Parameter (0x00000000) 
 d: set Temperature Coefficient (0) 
 D: set Temperature Offset (0) 
 f: set Humidity Coefficient (0) 
 F: set Humidity Offset (0) 

MONOSTICK側では、標準で入っている App_Wings というソフトウェアを利用します。ファームウェアを書き換えている場合は Wings への書き換えが必要です*1。PC等に接続するとUSBシリアルとして認識されるので、そこに115200bpsで接続して + キーを1-2秒ほどかけて3回押すと、インタラクティブモードに入って同様に設定を行えます。

ここで計測値の送信間隔のほか、ARIAとMONOSTICK側に同じApplication IDと通信チャンネルを設定します。また、もし暗号化等を行う場合は暗号キーやその有効化フラグ(Option Bits)を設定します。他に、複数台のARIAを使用する場合は識別用にDevice IDを設定しておきます。ちなみにUARTの速度もメニューに出て来ますが、特定のOption Bitsを有効化しないとこの設定は使用されません。

詳細は商品紹介ページやドキュメントを確認してください。

どちらも設定がうまくいったら S を入力して設定値を保存すると、リセットがかかってその設定で動作し始めますので、通信が確認できたらARIAはバッテリー動作に切り替えます。

受信してみる

無事データを受信できると、MONOSTICKのシリアルにHEXで以下のようなデータが流れてきます。

:80000000D201858201C1BB2A800607003400038135001205350401000000113008020DAC113001020550000000018005010002063F010200021204FCB2

形式は以下ページに記載されています。
アリアアプリ - WINGS

がこのままでは読みづらいので、プログラムで温度に変換してやります。
MacLinux (RaspberryPi) で動作確認しています。使用する場合はシリアルのデバイス名を環境に合わせて書き換えてください。

なおこのプログラムはARIAの他に無線タグアプリの温湿度データも読めるようになっています。

#!/usr/bin/env python3
import datetime
import serial

ser = serial.Serial('/dev/ttyUSB0', 115200)  # Linux
# ser = serial.Serial('/dev/cu.usbserial-MW3NRDHG', 115200)  # macOS

def to_int(data, start, len, signed=False):
    ret = 0
    for x in data[start:start+len]:
        ret = ret * 256 + x
    if signed:
        ret = ret - 65536 if ret > 32768 else ret
    return ret

def parse(line):
    line = line[1:].rstrip()
    data = [x for x in bytes.fromhex(line)]
    pos = 0
    result = []
    if len(data) == 23:
        # 8000000030F523810C5978003A6F03B1022D039914445A
        # ^^^^^^^1^2^^^3^^^^^^^4^5^6^7^^^8^^^9^^^a^^^b^c
        for l in [4, 1, 2, 4, 1, 1, 1, 2, 2, 2, 2]:
            result.append(to_int(data, pos, l))
            pos += l
        result[6] = 1950+result[6]*5 if result[6] < 170 else 2800+(result[6]-170)*10
        result[9] = result[9] - 65536 if result[9] > 32768 else result[9]
        result[10] = result[10] - 65536 if result[10] > 32768 else result[10]
        return "relay=%X LQI=%d seq=%X id=%X sid=%X type=%X mV=%d adc1=%d adc2=%d temp=%d hum=%d" % tuple(result)
    else:
        for l in [4, 1, 2, 4, 1, 1]:
            result.append(to_int(data, pos, l))
            pos += l
        result.append(to_int(data, 34, 2))
        result.append(to_int(data, 51, 2, True))
        result.append(to_int(data, 57, 2, True))
        result.append(to_int(data, 46, 1))
        return "relay=%X LQI=%d seq=%X id=%X sid=%X type=%X mV=%d temp=%d hum=%d mag=%X" % tuple(result)

while True:
    line = ser.readline().strip()
    if not line.startswith(b':'):
        continue
    data = '{0:%F %T}\t{1}'.format(datetime.datetime.now(), parse(line.decode()))
    print(data, flush=True)

実行するとこんな感じの出力が出ます。tempの値が温度(℃)の100倍、humは湿度(%)の100バイです。他に磁気センサ(mag、HEX)や電池電圧(mV)、電波強度(LQI)等が出ます。
この例では -19.53℃ です。冷凍庫に入っているので冷えてますねw

2023-02-04 05:39:17	relay=80000000 LQI=30 seq=68D5 id=8201C1BB sid=2A type=80 mV=2530 temp=-1953 hum=4773 mag=80

出力をリダイレクトしてファイルに記録しておきます。

冷凍庫の温度変化をグラフ化してみる

さて、ARIAを冷凍庫に入れてみたところ、庫外の5-6mほど離れたMONOSTICKで無事庫内からのデータを受信できました。
十分ARIAが冷えたところで,炊き立てご飯を粗熱をとって冷凍庫のARIAの少し離れたところに入れてみた結果をプロットしたのが以下です。

30分周期くらいで山ができていて、冷凍庫の作動状況が見て取れますね。21:00くらいに3-4℃ほど上がったところで庫内に食品を入れています。ちょっと山が潰れているところがありますが、この期間はバースト的に通信に失敗してデータが欠落していたようです。2.4GHzで通信しているので、他の同周波数帯の通信の影響を受けてしまったのかもしれません。

特に冷凍庫は動きっぱなしになるでもなく、徐々に数時間かけて冷えていっているのが分かります。庫内には他に保冷剤なども入っていたので、それらと暖かい食品が冷えていく過程と冷却動作がそれぞれ影響しあっているようなイメージでしょうか。


というわけで、冷凍庫のような冷えた環境でもちゃんとTWELITE ARIAが動作することが確認できました。

*1:最初、無線タグアプリの親機モードで受信したところ、途中でデータ出力が止まってしまいました。ARIAはデータが大きくWingsでないとダメなようです。

片手用Bluetoothキーボードを買ったのでカスタマイズツールを作ってみた

Amazonで、2つのノブの付いた片手用Bluetoothキーボードを買ってみました。Bluetooth付きのもの・USB専用のものや、6/9/12キー他、3ノブのものなど、色々種類があるようです。
いろんなブランド名で出品されており怪しげなのですが、念のためAmazon出荷のものを選んでみました。

片手キーボード (Bluetooth接続 3層レイヤー機能付き ノブ2個付き 9キー) 黒
片手キーボード (Bluetooth接続 3層レイヤー機能付き ノブ2個付き 9キー) 白


接続はUSB Type-Cです。Bluetooth対応版だとリチウムイオン電池を内蔵していて、USB接続中に充電されます(USB接続中はUSBキーボードとして振る舞います)。ノブ付きの片手キーボードデバイスは意外と高価なものが多いので、多少安価な部類に思います(それでもBluetooth版だと価格は上がりますが)。質感もアクリルパネルで悪くはないのですが、裏面がネジ露出でそのままだと置いた場所が傷だらけになるので、ゴム足なりビニールテープなりを貼る等の対策が必須です。
Bluetooth版だと3つのレイヤーに違うキーを割り当ててボタンで切り替えて使うこともできます。

しかし最大の欠点は設定ツールで、商品説明のGoogleDriveリンクで配布されている未署名のWindows用アプリしかなく、ちょっと怪しげな感じで作りも最低限のものです。商品名にはLinux/Macなどと書いてあるのですが、設定するにはWindowsが必須になってしまいます*1


そこでLinux/Mac、あるいはWinでもこのアプリを使わずに設定できるよう、どうやって設定されているのか調べてみました。
やり方は簡単(?)で、Windows(念のため環境が壊れてもいいように仮想環境でやりました)上でこのアプリを動かし、WiresharkでUSBキャプチャして設定時の通信内容からプロトコルを調べます。

*1:一旦設定さえしてしまえばツールがなくてもキー割当はデバイスが記憶してくれるのですが

続きを読む