はじめに
ゲーミングPC等で、CPU・GPU他の稼働状況をLCDモニターに出力していることがあります。
しかし、オフィシャルのソフトウエアはWindowsにしか対応していないケースが多いです。
MacでもLCDモニターへリソースの使用状況を表示してみたいと思い、独自のプログラムを作ってみたのでその技術解説をしてみます。
MacのシステムモニターというとiStat Menusが有名ですが、作成したのはそのLCDモニター出力版のようなものです。
作ったプログラムの実行イメージと完全なソースは以下になります。
概要
LCDモニター
今回使用したLCDモニターは以下のものです。
他の製品と比べて価格がお安めなことからちょっと話題になっていました。
LCDモニターの製品としては以下のような種類があります。
| 種類 | COMポート型 | HIDデバイス型 | USBバルク転送型 |
|---|---|---|---|
| 制御難易度 | 低(シリアル通信) | 低(OS標準ドライバ) | 中(低レイヤ制御が必要) |
| 転送速度 | 低速 | 低速~中速 | 高速 |
| ドライバ | OS標準で動作 | 不要(OS標準で認識) | 専用 or WinUSB/libusb |
COMポート型の製品としてはTuring Smart Screen等があり、3.5インチのものは格安で入手できますが、転送速度は低速です。
また、USBバルク転送型としてはTuring Smart Screen 8インチ Revision 1.1等があります。
今回使用したThermalright Trofeo Vision LCDはUSB HIDデバイスタイプの製品であり、Macでもドライバ不要で使用できること、画素数も1280x480とシステム情報の表示には十分なことから選択しました。
環境
以下の環境で動作確認をしています。
| 項目 | 概要 |
|---|---|
| Mac | Mac Mini M2 |
| OS | macOS 26.3.1 |
| 言語/ランタイム | C#/.NET 10 |
| LCDモニター | Thermalright Trofeo Vision LCD |
LCD制御
HID制御
USB HIDデバイスの制御にはHIDSharpを使用しました。
HIDSharpはWindows、Mac、Linuxに対応しているので、今回作成したプログラムはシステム情報取得部分を差し替えればMac以外への移植も簡単です。
Trofeo Vision LCD
| 項目 | 値 |
|---|---|
| VendorId | 0x0416 |
| ProductId | 0x5302 |
HIDSharp
HIDSharpの基本的な使用方法は以下になります。
// HidDeviceを取得
var hidDevice = DeviceList.Local.GetHidDevices(0x0416, 0x5302).FirstOrDefault();
// HidStreamのオープン
var hidStream = hidDevice.Open();
// データの送信
hidStream.Write(packet);
プロトコル
Trofeo Vision LCDのプロトコルは、513バイトの固定部を送信した後、続けてJpeg画像データのバイト配列を送信する形です。
固有の注意点として、Trofeo Vision LCDでは定期的に画像送信を行なわないとLCDモニタ側で画面をクリアしてしまうので、作成したプログラムでは1秒毎に画像送信をするようにしています。
HIDレポート構造
| オフセット | サイズ | 内容 |
|---|---|---|
| 0 | 1 byte | Report ID (0x00) |
| 1〜512 | 512 bytes | データ領域 |
ヘッダ(データ領域の先頭20バイト)
| オフセット | サイズ | 内容 |
|---|---|---|
| 0〜3 | 4 bytes | マジックバイト DA DB DC DD
|
| 4 | 1 byte | コマンド種別(0x02 = 画像) |
| 5〜7 | 3 bytes | 未使用 |
| 8〜9 | 2 bytes | 幅 (LE, 1280) |
| 10〜11 | 2 bytes | 高さ (LE, 480) |
| 12 | 1 byte | 圧縮形式 (0x02 = Jpeg) |
| 13〜15 | 3 bytes | 未使用 (0埋め) |
| 16〜19 | 4 bytes | 画像データ長 (LE, int32) |
完全なソース
ライブラリ化したものはこちらになります。
システム情報取得
Macでのシステム情報取得
iStat Menusのようなものを作る場合、各種情報は次のようなライブラリ・フレームワークから取得することができます。
使用するライブラリ・フレームワーク
| ライブラリ / フレームワーク | 主な用途 | 使用する主な関数 |
|---|---|---|
| libSystem.dylib | Mach カーネル操作、VM 統計 |
mach_host_self, host_statistics64, host_processor_info, vm_deallocate
|
| libc | sysctl、ファイルシステム、ネットワーク |
sysctlbyname, getloadavg, getfsstat, statfs, getifaddrs
|
| libproc | プロセス情報取得 |
proc_listpids, proc_pidinfo, proc_pidpath, proc_pid_rusage
|
| IOKit | デバイス列挙、SMC アクセス、センサー |
IOServiceMatching, IOServiceGetMatchingService, IOConnectCallStructMethod, IORegistryEntryCreateCFProperty
|
| libIOReport | CPU 周波数・電力モニタリング | IOReport サンプリング API |
| SystemConfiguration | ネットワーク構成情報 | ネットワークサービス列挙、インターフェース状態取得 |
取得出来るシステム情報
| カテゴリ | 取得情報 | 使用ネイティブ API |
|---|---|---|
| CPU 使用率 | コア別負荷 (User/System/Idle/Nice)、P/E コア判別 | Mach host_processor_info
|
| CPU 周波数 | コア別周波数、レジデンシー追跡 | libIOReport |
| メモリ | アクティブ/非アクティブ/ワイヤード/空きページ、圧縮、ページフォルト | Mach host_statistics64
|
| スワップ | 合計/使用/空きスワップ、暗号化状態 | sysctl |
| ディスク I/O | R/W バイト数・回数、バス種別、デバイス名 | IOKit (IOMedia) |
| ファイルシステム | マウントポイント、ブロック数、FS タイプ | libc getfsstat / statfs
|
| ネットワーク | RX/TX バイト・パケット、エラー、IF タイプ判別 | libc getifaddrs, SystemConfiguration |
| プロセス | PID、CPU 時間、メモリ、スレッド数、ディスク I/O | libproc |
| センサー | 温度/電圧/電流/電力/ファン回転数 | IOKit SMC (IOConnectCallStructMethod) |
| GPU | GPU 使用率、VRAM 使用量 | IOKit |
| 電力 | 消費電力トラッキング | libIOReport |
| 負荷平均 | 1/5/15 分負荷 | libc getloadavg
|
| 稼働時間 | 起動からの経過時間 | sysctl (ブート時刻) |
.NETでの取得
今回のプログラムは.NET/C#で作成しています。
なぜ.NETなのかと言えば、単に自分が.NETを好きだからです。
P/Invokeを使うことで、.NETでもシステム情報を扱うようなネイティブライブラリも問題なく使えます。
なお、ターゲットフレームワークはnet10.0-macosではなくnet10.0で作成しています。
本当はnet10.0-macosを使えばMac固有機能の利用が簡単にできるのですが、net10.0-macosだとInfo.plistが必要になる等、単なるコンソールアプリケーションで扱いが面倒になるため、自前でP/Invokeの定義をする形にしています。
完全なソース
ライブラリ化したものはこちら。
このライブラリは元々自前Prometheus Exporter用に作成したものですが、今回それを流用しました。
ちなみに、バッテリー情報の取得も追加したいところですが、Bookは持っていないので動作確認が出来ないため、未実装となっています。
うさコメ
PCを光らせる事に興味は無いですが、こういうダッシュボード的なものは大好きなので、Macでも実現できて満足です( ˙ω˙)
今回、画面デザイン等AIを使用して作成していますが、こういうおもちゃを簡単に作れるようになったのは良いですね。
あとは、.NETはこのようにMacでのシステムプログラミングにも使用できるということを知っていただけたらと思います。
