スプレッドシートでRaspberryPiのリソースモニタを作ってみた

## はじめに
RaspberryPiでMinecraftサーバーを動かしているのですが、時々CPU温度や使用率を確認したくなる時がありました。

また、公開予定から1週間以上過ぎたアドベントカレンダーの記事をまだ全く書いていなかったのもあり、外出先でもCPU温度などを確認できるリソースモニタ的な何かを作ることにしました。

なお、ソースコードは全て[GitHub](https://github.com/Takahiro55555/PiResourceMonitor)上に公開しています。

### RaspberryPi側環境
- 機種: RaspberryPi4B （多分他の機種でも行けるはず...）
- OS: Raspbian Buster Lite
- 言語: Python 3.7.3
- Pythonパッケージ: requests （バージョン: 2.21.0）
- 使用コマンド：`vcgencmd`、`free`、`cat`、`grep`

## 作ったもの
RaspberryPiのCPU使用率やCPU温度、メモリ使用率などをGoogleスプレッドシートで随時確認できるリソースモニタ的な何かを作りました（下画像）。

なお、グラフは手動で作成します。
![online_resouce_monitor_on_minecraft05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202199/317aae7c-ceca-2d76-42a5-ee1f6f54125b.png)

## 使い方
RaspberryPi側はPythonで、スプレッドシートへデータを設定するためにGoogleAppsScriptを使用しました。

### GoogleAppsScript側の準備
#### 1. スプレッドシートを作成する
（省略）
#### 2. スクリプトエディタを開く
![スクリプトエディタ01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202199/9eba70b5-744d-bc9e-46e0-e31cd1d3ba74.png)
#### 3. コードをコピペする。
[コードはこちらから](https://raw.githubusercontent.com/Takahiro55555/PiResourceMonitor/master/src/gas/index.gs)取得できます。

下画像を参考にコードを貼り付けてください。
![スクリプトエディタ03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202199/44326860-918a-b133-3434-04d14d04d6de.png)
#### 4. 公開する

下の画像と同じ設定にし、`deploy` ボタンを押す
![スクリプトエディタ05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202199/6ca3613d-637d-ef6e-0a61-67ab439e8d6e.png)

#### 5. アカウントの設定など（初回のみ）
下画像の`許可を確認`ボタンを押してください。
![スクリプトエディタ06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202199/37862328-28bf-2fca-3bf5-e720f51887d7.png)
その後の画面の指示に従って、ボタンを押していってください。

#### 6. URLの確認
RaspberryPi側の準備で必要になるため、表示されたURLをメモしておいてください。
![スクリプトエディタ09.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202199/f19cc06c-a752-3698-8e5c-9f303ef2828d.png)

これでGoogleAppsScript側の準備は完了です。

### RaspberryPi側の準備
#### 1. ファイルを取得する

```bash
$ wget https://raw.githubusercontent.com/Takahiro55555/PiResourceMonitor/master/src/raspberry/monitor.py
$ wget https://raw.githubusercontent.com/Takahiro55555/PiResourceMonitor/master/src/raspberry/settings.py
```

#### 2. 設定ファイルを編集する
ここで、先ほどメモしておいたURLを`GAS_URL`に設定してください。

```settings.py
# GoogleAppsScriptのURL
GAS_URL = "GoogleAppsScript側の準備の際にメモしておいたURL"
HOST_NAME = "raspberrypi_test"  # 一意な名前を設定
MAX_LINE = 60  # スプレッドシート側の最大行数（この行数を超えると古い行から削除される）
SAMPLING_INTERVAL_SEC = 3  # 各リソースの状態を取得する間隔
```

これでRaspberryPi側の準備は完了です。

### 動作確認とグラフの作成
#### 1. RaspberryPi側の確認
正常に動作することを確認するために、試しに動かしてみます。

```
$ python3 monitor.py
```

#### 2. スプレッドシートを確認
下画像のように、新しいシートが作成されデータが設定されていたら成功です。
動作を確認したら、RaspberryPi側のプログラムを`Ctrl+C`などを使って停止させます。

なお、シート名は設定ファイルの`HOST_NAME`に設定したものを使います。

![スプレッドシート01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202199/b729b8aa-4f59-5db7-e399-927f55521a7a.png)

#### 3. グラフを適宜作成する

自由にグラフなどを作成してください。

ポイントとして、一旦RaspberryPi側のプログラムを停止させないと、グラフの作成が困難になります。
また、グラフ用のシートとGoogleAppsScriptにより作成されたシートは別にしたほうが見やすいかもしれません。

#### 4. プログラムを起動する
以下のようにすると、端末を閉じてもプログラムを動かし続けることができます。

```
$ nohup python3 monitor.py &
```

## 実装
CPU温度や使用率などは、RaspberryPiからコマンドを実行することで取得・計算しています。
その結果を、GoogleAppsScript側で受け取り、スプレッドシートに記録します。

### RaspberryPi側
Python3を使用し実装しました。
CPU温度や使用率などを取得するために、`subprocess`モジュールを使用しました。
また、データの送信するためのライブラリとして`requests`を使用しました。

### GoogleAppsScript側
GoogleAppsScript側では、受信したデータからシート名やデータのキーから列名を作成、設定するようにしました。
そのため、送信するデータが多少変わってもGoogleAppsScript側のコードの修正が必要になることは少ないと思います。

また、データの行数が設定ファイルの`MAX_LINE`を超えた分は古い順（タイムスタンプは関係ない）に削除するようにしています。

## 終わりに

### ハマったところ
#### 1. CPU使用率
RaspberryPiのCPU使用率を取得する際、`vmstat`コマンドを使用していました。しかし、CPU使用率がほぼ変動しないという現象に悩まされました。いろいろ調べてみると、[とある記事](https://qiita.com/ta-hoshi/items/c59d9727e974083fa203)にたどり着きました。

> topコマンドを実行するとCPUやメモリ使用率のサマリ情報がヘッダとして表示されるが、最初に表示されるCPU使用率はOSを起動してからの平均値なので、無風状態が長いほど低い数値が出る。
> なお、vmstatで表示されるCPU使用率も同じ仕様なので、パフォーマンス調査などの際には最初の表示は見ない方がいい。

また、`man`コマンドで`vmstat`を確認してみたところ、
> The first report produced gives averages since the last reboot.  Additional reports give information on a sampling period of length delay.  The process and memory reports are instantaneous in either case.

同様の記述がありました...

ということで、`vmstat`コマンドを使用することはあきらめ、[こちらのサイト](http://my-web-site.iobb.net/~yuki/2017-10/raspberry-pi/cpustat/)を参考にCPU使用率を計算しています。

### このシステムの不備について
現在自分は3秒おきにデータを取得・送信しているのですが、データの並びがタイムスタンプ順にならないことがあります。
順序がおかしいと、グラフがおかしくなるので今後気が向いたら修正したいと思います。

---

### 参考文献
- [Raspberry Pi CPU 周波数、CPU 温度、CPU 使用率の取得 Python スクリプト](http://my-web-site.iobb.net/~yuki/2017-10/raspberry-pi/cpustat/)
- [Python の subprocess で出力を受け取るときは communicate() を使おう](https://qiita.com/mokemokechicken/items/a84b0aa96b94d1931f08)
- [top コマンドで CPU 使用率を見る時の注意](https://qiita.com/ta-hoshi/items/c59d9727e974083fa203)
- [Python で定周期で実行する方法と検証](https://qiita.com/montblanc18/items/05715730d99d450fd0d3)
- [Google Apps Script セキュリティ診断にひっかかったときは](https://sleepygamersmemo.blogspot.com/2018/04/google-apps-script-onlycurrentdoc.html)
- [【保存版】初心者向け実務で使えるGoogle Apps Script完全マニュアル](https://tonari-it.com/google-apps-script-manual/)