Raspberry Pi でのコード開発を想定しています。ラズパイにSSH接続できたらPythonコードを作成してください。
目次
1. ラズパイのCPU温度を表示する
LED点灯で学習したように、PCのハードウェア情報はファイルに記述されているので、ファイルを読むと情報がわかる。
コンピュータのCPU温度もファイルを読んで表示できるので試してみよう。
新しいファイルを[$ nano try-gettemp.py]で作る
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def get_cpu_temp():
""" Raspberry Pi のCPU温度を取得するコード """
f = open("/sys/class/thermal/thermal_zone0/temp", "r")
t = int(f.read().strip())
f.close()
return(t / 1000.0)
if __name__ == "__main__":
temp = get_cpu_temp()
print(f"CPU温度: {temp:.1f} °C")実行してみる
$ python try-gettemp.py
CPU温度: 39.4 °CLEVEL UP
ファイルを読めなかったなどエラーが発生したとき f.close() が実行されずファイルを閉じれない場合に備えてエラー対策をしたコード例
try: で実行したコードが失敗しても finally: の次が実行される
def get_cpu_temp():
try:
f = open("/sys/class/thermal/thermal_zone0/temp", "r")
t = int(f.read().strip())
finally:
f.close()
return(t / 1000.0)さらにLEVEL UP
ファイル open と close を一行で実行する書き方。
温度情報が存在しなかった場合の例外も考慮した書き方。つまり完璧版
def get_cpu_temp():
try:
with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
t = int(f.read().strip())
return t / 1000.0 # ミリ度 → 度C
except Exception:
return None練習
CPU情報を表示してみる。下記を実行してどんな情報がわかるか調べてみよう
例えば、プロセッサー番号(processor)が何個あるか調べるとCPUコア数がわかる
$ cat /proc/cpuinfo今度はメモリ情報を表示してみる。
MemTotal(kB)に1024をかけるとGB表記になる[8008420 kB × 1024 = 8,200,622,080 バイト(約 8GB)]
$ cat /proc/meminfo2. CPU情報を表示するAPIアプリをFlaskサーバーで動かす
最初にFlaskサーバーが動くか復習しよう。下記コードを新規作成する[$ nano try-gettemp-api.py]。
# !/usr/bin/env python3
# -*- coding: utf-8 -*-
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'ラズパイからの応答です。'
if __name__ == "__main__":
app.run(host='0.0.0.0', port=3001)APIアプリを起動する
$ python try-gettemp-api.pyブラウザで実行してみる(ラズパイ番号は自分の番号にすること)
http://razpi00.local:3001/使っていないポート番号を使う。もし、既にポートが使われている場合はポート番号を変更する
ポート番号が使われているか確認するコマンド。下記を実行して、使われていたらポート番号が表示される
$ ss | grep :3001CPU情報を表示する。[if name == “main”:]より前に下記[/cpu_temp]機能を追加する。
@app.route('/cpu_temp')
def get_cpu_temp():
""" Raspberry Pi のCPU温度を取得して表示するコード """
try:
with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
t = int(f.read().strip())
temp = t / 1000.0
except Exception as e:
temp = 0
finally:
return f"CPU温度: {temp:.1f} °C"ブラウザで実行してみる(ラズパイ番号は自分の番号にすること)
http://razpi00.local:3001/cpu_temp3. CPU情報表示を5秒毎に更新するHTMLをつくる
HTMLファイルは、pythonコードと同じフォルダから配信するので[send_from_directory]モジュールを追加する
新しいファイルを作成する[$ nano try-gettemp-api-html.py]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Raspberry Pi の CPU 温度を
1) ブラウザから HTTP で取りに行く
2) 5 秒ごとに画面を自動更新する
ためのシンプルな学習用サーバです。
- /cpu_temp : 今の CPU 温度を文字で返す API
- /monitoring : CPU 温度を表示する HTML ページ
"""
from flask import Flask, send_from_directory
app = Flask(__name__)
def read_cpu_temp():
"""Raspberry Pi の CPU 温度(℃)を 1 回だけ読み取って返す関数"""
try:
# /sys/class/thermal/... という特別なファイルから温度(ミリ度)を読む
with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
t = int(f.read().strip())
# 例えば 38000 → 38.0 ℃ に直す
return t / 1000.0
except Exception:
# 何かエラーが起きたら None を返す
return None
@app.route("/cpu_temp")
def get_cpu_temp():
"""ブラウザから /cpu_temp にアクセスされたときに呼ばれる関数"""
temp = read_cpu_temp()
if temp is None:
# 温度が読めなかったときのメッセージ
return "CPU温度を取得できませんでした"
# 正常に読めたときは「CPU温度: 38.9 °C」のような文字列を返す
return f"CPU温度: {temp:.1f} °C"
@app.route("/monitoring")
def monitoring_page():
"""CPU 温度を 5 秒ごとに見るための HTML を返す"""
# この Python ファイルと同じフォルダにある try-gettemp.html を返す
return send_from_directory(".", "try-gettemp.html")
if __name__ == "__main__":
# 0.0.0.0:3001 で待ち受ける
# ブラウザから http://ラズパイのIPアドレス:3001/monitoring にアクセスする
app.run(host="0.0.0.0", port=3001)
HTMLファイルを作成する[$ nano try-gettemp.html]
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Raspberry Pi CPU温度モニタ (5秒ごと更新)</title>
<style>
body {
font-family: sans-serif;
margin: 2rem;
}
h1 {
font-size: 1.8rem;
}
#cpu-temp {
font-size: 2rem;
margin-top: 1rem;
}
#updated-at {
margin-top: 0.5rem;
font-size: 1rem;
color: #555;
}
#status {
margin-top: 0.5rem;
font-size: 0.9rem;
color: #0066cc;
}
</style>
</head>
<body>
<!-- 画面のタイトル -->
<h1>Raspberry Pi CPU温度モニタ</h1>
<!-- 今の CPU 温度を表示する場所 -->
<div id="cpu-temp">CPU温度: --.- °C</div>
<!-- 最後に更新した時刻を表示する場所 -->
<div id="updated-at">更新時刻: --:--:--</div>
<!-- 通信の状態(成功 / 失敗など)を表示する場所 -->
<div id="status">状態: まだ取得していません</div>
<script>
// HTML から要素を 3 つ取り出して、変数に入れる
const cpuTempDiv = document.getElementById("cpu-temp");
const updatedAtDiv = document.getElementById("updated-at");
const statusDiv = document.getElementById("status");
// 1回だけ /cpu_temp にアクセスして、CPU温度をとってくる関数
function fetchCpuTempOnce() {
// 状態を「取得中」にしておく
statusDiv.textContent = "状態: CPU温度を取得中...";
// 同じサーバー(3001番ポート)の /cpu_temp にアクセスする
// HTML も同じサーバーから配信されているので、相対パスでOK
fetch("/cpu_temp")
.then(function (response) {
// サーバーからの返事(response)が OK (200系) かどうかをチェック
if (!response.ok) {
throw new Error("HTTPエラー: " + response.status);
}
// 返事の中身を「文字」として取り出す
return response.text();
})
.then(function (text) {
// text には「CPU温度: 38.9 °C」などが入っている
// その文字を、そのまま画面に表示する
cpuTempDiv.textContent = text;
// ここで「今の時刻」を作って、きれいな形(時:分:秒)にする
const now = new Date();
const hh = String(now.getHours()).padStart(2, "0");
const mm = String(now.getMinutes()).padStart(2, "0");
const ss = String(now.getSeconds()).padStart(2, "0");
// 最終更新時刻を画面に表示
updatedAtDiv.textContent = "更新時刻: " + hh + ":" + mm + ":" + ss;
// 状態を「成功」に更新
statusDiv.textContent = "状態: 最新のCPU温度を取得しました";
})
.catch(function (error) {
// ネットワークエラーなどが起きたときにここに来る
statusDiv.textContent = "状態: CPU温度の取得に失敗しました (" + error.message + ")";
});
}
// ページを開いたときに、まず1回だけ取得してみる
fetchCpuTempOnce();
// そのあと、5秒(5000ミリ秒)ごとに繰り返し取得する
const intervalMs = 5000; // ミリ秒単位
setInterval(fetchCpuTempOnce, intervalMs);
</script>
</body>
</html>
2つのステップで検査する。
STEP1. APIアプリを起動する[$ python try-gettemp-api-html.py]
STEP2. ブラウザでアクセスする[http://razpi00.local:3001/monitoring]

4. CPU情報をグラフ表示する
グラフ描画は Google Charts を使う。さまざまなグラフがあるのでWEBサイトを見学しておいてください。
pythonコード[try-gettemp-api-html.py]に下記コードを追加する
@app.route("/graph")
def graph_page():
"""CPU 温度の時系列グラフを表示する HTML を返す"""
# 同じフォルダにある try-gettemp-graph.html を返す
return send_from_directory(".", "try-gettemp-graph.html")
新しいHTML[$ nano try-gettemp-graph.html]を作ります
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Raspberry Pi CPU温度グラフ</title>
<!-- 画面の見た目を少し整えるCSS -->
<style>
body {
font-family: sans-serif;
margin: 2rem;
}
h1 {
font-size: 1.8rem;
margin-bottom: 1rem;
}
#current-temp {
font-size: 1.4rem;
margin-top: 0.5rem;
}
#current-time {
margin-top: 0.3rem;
color: #555;
}
#status {
margin-top: 0.3rem;
font-size: 0.9rem;
color: #0066cc;
}
/* グラフを表示するエリア(幅100%、高さ400px) */
#chart-container {
width: 100%;
height: 400px;
margin-top: 1.5rem;
border: 1px solid #ccc;
}
</style>
<!-- Google Charts のライブラリを読み込むスクリプト -->
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script>
// ================================================
// 1. Google Charts の準備
// ================================================
// "corechart" というパッケージを使う(折れ線グラフなど)
google.charts.load("current", { packages: ["corechart"] });
// ライブラリの読み込みが終わったら、initChart 関数を呼ぶように予約する
google.charts.setOnLoadCallback(initChart);
// グラフの「元データ」を入れておく表(DataTable)
let dataTable;
// 折れ線グラフを表示するためのオブジェクト
let chart;
// グラフの見た目の設定(タイトルや軸ラベルなど)
let chartOptions;
// 「直近何点までグラフに表示するか」を決める(例: 60点 → 約5分分など)
const MAX_POINTS = 60;
// ================================================
// 2. 初期化処理(最初の1回だけ呼ばれる)
// ================================================
function initChart() {
// HTML 上のいろいろな要素を JavaScript から触れるようにしておく
const currentTempDiv = document.getElementById("current-temp");
const currentTimeDiv = document.getElementById("current-time");
const statusDiv = document.getElementById("status");
const chartContainer = document.getElementById("chart-container");
// ---- DataTable(表)の作成 ----
// new DataTable() で「表」を作るイメージ
dataTable = new google.visualization.DataTable();
// 列(カラム)を2つ追加する
// 1列目: 時刻(Date型)
dataTable.addColumn("datetime", "時刻");
// 2列目: CPU温度(数値)
dataTable.addColumn("number", "CPU温度(℃)");
// ---- グラフオブジェクトの作成 ----
// 折れ線グラフ(LineChart)を、この chartContainer の中に描く
chart = new google.visualization.LineChart(chartContainer);
// ---- グラフの見た目の設定 ----
chartOptions = {
title: "CPU温度の推移",
legend: { position: "bottom" },
hAxis: {
title: "時刻",
// 時刻のフォーマット(例: 12:34:56)
format: "HH:mm:ss",
},
vAxis: {
title: "CPU温度 (℃)",
},
// 線をなめらかにする(true にすると曲線、false だと直線)
curveType: "function",
};
// 最初に「空のグラフ」を1回描いておく
chart.draw(dataTable, chartOptions);
// ---- 最初の1回だけデータを取りに行く ----
fetchAndUpdateOnce(currentTempDiv, currentTimeDiv, statusDiv);
// ---- その後は一定間隔(ここでは5秒)ごとに繰り返す ----
const intervalMs = 5000; // 5000ミリ秒 = 5秒
setInterval(function () {
fetchAndUpdateOnce(currentTempDiv, currentTimeDiv, statusDiv);
}, intervalMs);
}
// ================================================
// 3. 1回分のデータ取得とグラフ更新の処理
// ================================================
function fetchAndUpdateOnce(currentTempDiv, currentTimeDiv, statusDiv) {
// 状態を「取得中」にする
statusDiv.textContent = "状態: CPU温度を取得中...";
// 同じサーバー上の /cpu_temp にアクセスして、温度の文字列をもらう
// 例: 「CPU温度: 38.9 °C」
fetch("/cpu_temp")
.then(function (response) {
if (!response.ok) {
// 200番台以外のステータスコードならエラーとみなす
throw new Error("HTTPエラー: " + response.status);
}
// レスポンスの中身を「文字」として取り出す
return response.text();
})
.then(function (text) {
// text には例えば「CPU温度: 38.9 °C」が入っている
// ---- 文字列から数値の部分だけを取り出す ----
// コロン(:)で分けて、右側をさらに空白で分ける…など簡単な方法でOK
let tempValue = null;
try {
// 「CPU温度: 38.9 °C」を["CPU温度", " 38.9 °C"]に分割
const parts = text.split(":");
if (parts.length >= 2) {
// 右側 " 38.9 °C" から数値だけを取り出す
const right = parts[1];
// 空白で分けて、最初の要素を数値に変換
const numStr = right.trim().split(" ")[0];
tempValue = parseFloat(numStr);
}
} catch (e) {
tempValue = null;
}
if (isNaN(tempValue)) {
throw new Error("温度の数値を読み取れませんでした: " + text);
}
// ---- ここからグラフ用の処理 ----
// 今の時刻を取得(Dateオブジェクト)
const now = new Date();
// DataTable に 1 行追加する
// [今の時刻, 温度の数値] という形
dataTable.addRow([now, tempValue]);
// データが多くなりすぎないように、古い行を削除する
const numRows = dataTable.getNumberOfRows();
if (numRows > MAX_POINTS) {
// 一番古い行(0行目)を1つ削除
dataTable.removeRow(0);
}
// 現在の温度を画面に表示
currentTempDiv.textContent = "現在のCPU温度: " + tempValue.toFixed(1) + " ℃";
// 現在時刻を「HH:MM:SS」形式の文字列にする
const hh = String(now.getHours()).padStart(2, "0");
const mm = String(now.getMinutes()).padStart(2, "0");
const ss = String(now.getSeconds()).padStart(2, "0");
currentTimeDiv.textContent = "最終更新: " + hh + ":" + mm + ":" + ss;
// 状態を「成功」に更新
statusDiv.textContent = "状態: 最新のCPU温度を取得しました";
// グラフを再描画する(同じ dataTable と chartOptions を使う)
chart.draw(dataTable, chartOptions);
})
.catch(function (error) {
// ネットワークエラーや、上で投げたエラーが来たときにここに入る
statusDiv.textContent = "状態: CPU温度の取得に失敗しました (" + error.message + ")";
});
}
</script>
</head>
<body>
<h1>Raspberry Pi CPU温度グラフ</h1>
<!-- 現在のCPU温度を文字で表示する場所 -->
<div id="current-temp">現在のCPU温度: --.- ℃</div>
<!-- 最後にデータを更新した時刻を表示する場所 -->
<div id="current-time">最終更新: --:--:--</div>
<!-- 通信状態(取得中 / 成功 / 失敗など)を表示する場所 -->
<div id="status">状態: まだ取得していません</div>
<!-- 折れ線グラフを描くための箱(div) -->
<div id="chart-container"></div>
</body>
</html>
APIアプリを停止して再起動します。
ブラウザでアクセスします[http://razpi00.local:3001/graph]

グラフの見た目を変更
折れ線グラフにするには107行目の[curveType: “function”,]をコメントアウトします(先頭に//を追加)
// curveType: "function",棒グラフにするには92行目のグラフ名を変更します
// chart = new google.visualization.LineChart(chartContainer); // 折れ線グラフ
chart = new google.visualization.ColumnChart(chartContainer); // 棒グラフ今月はここまで。