久しぶりの投稿になりますが、今回はサーバーのCPU負荷をフルカラーLEDで可視化をすることにチャレンジします。
動機ですが、LEDテープが余っておりサーバーのフロントパネルに仕込んだところ、いい感じの見た目になり、「CPU負荷に応じて色が変わったら面白いのでは」と思ったからです。
ハードウェアの製作
まずハードウェアを製作します。と言ってもLEDテープをフロントパネルの裏に取り付け、Arduino Pro Miniをはんだ付けするだけです。使用したLEDテープはAdafruitのNeoPixel系のものですが、正確な型番は不明です。マルツで購入しました。
回路図は以下のようにシンプルです。
ソフトウェアの製作
今回のプロジェクトではプログラムは2つ必要です。まず、サーバー上でCPU負荷の情報を読み取りシリアル通信で送信するPythonプログラムと、その情報を受け取りLEDを制御するArduino用のプログラムです。
またPython側では日本標準時を読み取り、夜間にLEDを消灯する機能も搭載します。
まずはPythonのコードを以下に示します。
import serial import time import psutil import datetime COM="/dev/ttyUSB0" bitRate=15200 ser = serial.Serial(COM, bitRate) time.sleep(2) while 1: cpu = int(psutil.cpu_percent(interval=0.1)) data="B"+str(cpu) ser.write(str.encode(data)) while datetime.time(1, 0, 0)<datetime.datetime.now().time() and datetime.datetime.now().time()<datetime.time(7, 0, 0): ser.write(str.encode("A0")) time.sleep(10) time.sleep(2) ser.close()
PythonなのでLinuxでもWindowsでもMacでも動作すると思いますが、6行目のシリアルデバイスのポートは各自の環境に合わせて変更する必要があります。(Windowsなら「COM6」みたいな感じです)
プログラムとしてはpsutil.cpu_percentでCPU負荷を取得し、昼間は「B+{CPU負荷率}」の形式で送信し、夜間(午前1時~7時)は「A0」を送信します。Arduino側では一文字目がAかBかで点灯・消灯を判断し、以降の文字でCPU負荷を受け取ります。
昼間はCPU負荷に俊敏に反応できるように約2秒おきに送信し、夜間は消灯するだけなので10秒おきに送信しています。夜間は一回だけの送信でもよいのですが、確実に消灯する為と、1時以降にプログラムを実行し始めても消灯するように10秒間隔で消灯信号を送り続けています。
次にArduinoのコードも示します。
#include <Adafruit_NeoPixel.h> #include <string.h> #ifdef __AVR__ #include <avr/power.h> #endif #define PIN 9 #define NUMPIXELS 30 //使用するLEDの数 int data=0; int val=0; String command; Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); void setup() { pixels.begin(); Serial.begin(15200); } void loop() { if(Serial.available()){ delay(10); command = Serial.readString(); } data = command.substring(1).toInt(); if(command.charAt(0)=='A'){pixels.setBrightness(0);} if(command.charAt(0)=='B'){pixels.setBrightness(255);} if(data!=val){ if(data>val){val++;} if(data<val){val--;} } if(val>=100){val=100;} if(val<=0){val=0;} int r=val*255/100; int b=255-r; pixels.clear(); pixels.fill(pixels.Color(r, 0, b), 0, NUMPIXELS); pixels.show(); delay(10); }
Arduino側ではCPU負荷に応じて青色から赤色のグラデーションで負荷率を表現します。また夜間信号を受け取った際は輝度をゼロに設定します。
if(data!=val){ if(data>val){val++;} if(data<val){val--;} }
この部分ではCPU負荷変化に敏感に反応し過ぎて色が飛び飛びにならないように、受け取った値を直接表示するのではなく、受け取った値を目標にして値を1ずつ変化させています。これにより色の変化が滑らかになります。
ちなみにPythonのCPU負荷取得のインターバルやsleep時間、Arduinoのdelay時間を変更するとLEDが激しく明滅したり、色が変わらなくなることがあります。たぶんArduinoのシリアル割り込みを使ってないのが原因だと思いますが、もう面倒なのでこのままにします。いいアイデアがある方はコメントで教えていただけると幸いです。
プログラムの実行
ではプログラムを動かしてみます。
まずUSBシリアル変換とサーバーマシンをUSBケーブルで接続します。
私の場合はVMware ESXiで仮想化しているので管理画面からUSBデバイスをマイクラサーバーに割り当てます。
ホストの設定画面上部の「その他のデバイスの追加」で新規USBデバイスを追加しプルダウンからUSBシリアル変換デバイスを選択します。
これで仮想マシンに目に見えないUSBコネクタを差し込んだことになります。
サーバーとのSSHを開きPython3をインストールし、pipでserialライブラリ等必要なものをインストールします。
以下のコマンドを実行し割り当てられたシリアルポートを確認します。
root@server3:/$ ls -l /dev/serial/by-id/ total 0 lrwxrwxrwx 1 root root 13 Sep 19 20:41 usb-1a86_USB2.0-Serial-if00-port0 -> ../../ttyUSB0
これによりシリアルデバイスが”/dev/ttyUSB0″に割り当てられたことがわかります。これをもとにPythonコードの6行目を適宜書き換えます。
Windowsの場合はデバイスマネージャーで確認できます。
あとはPythonコードを実行し、負荷を掛ければLEDの色が変化するはずです。自分の環境ではCronで自動的に走るようにしてます。
完成前にCineBenchでWindowsに負荷を掛けたときの動画も載せておきます。
現在はマイクラサーバーの負荷表示に使っていますが、夜間はきちんと消灯し問題なく動作しています。
様々なデバイスで動作すると思いますので、面白そうだと思った方はぜひ作ってみてください。
ここまで読んでいただきありがとうございました。
この記事を書いた人
-
とある理系大学に通う逸般的なオタク。
趣味は電子工作、オーディオ、サーバー管理など。
最新の投稿
オーディオ08/14/2023I2S信号の量子化ビット数をSPLDで判定する 電子工作04/02/2023NTP+スタティック方式なニキシー管時計を作る (3) 電子工作03/20/2023NTP+スタティック方式なニキシー管時計を作る (2) 電子工作03/19/2023NTP+スタティック方式なニキシー管時計を作る (1)