第10章 · 実例 2

センサーデータ 1 週間 → SQLite → グラフ + Markdown レポート

第 09 章「組み込みを作る ── Pythonで考え、Claudeに翻訳させる」の 2 番目の角度: 実機の前段(データ可視化と異常検知)を Python で完成させる

章のどの主張に対応するか

センサデータの可視化: 自前で Web ダッシュボードを作ると 1 週間。 Python の matplotlibplot() 1 行 + Claude に「これを HTML レポートにして」と 頼むと 30 分で実用レベル。

(章本文「実例: 数字で見る」より)

example-1 が「温度制御ロジックの C 翻訳」、これは データ収集 → 可視化 → 判定 → レポート までの周辺パイプラインを実演する。

やること

  1. collect.py: 1 週間ぶん(7×24×12 = 2,016 件 × 3 センサ = 6,048 件)を SQLite に投入(実機がまだ無くても、データの形を決めて先にコードを書く)
  2. analyze.py: SQL で集計 + matplotlib で 3 段グラフ + 自動観察コメント
  3. 出力:
    • out/sensor.db ── 生データ
    • out/sensor.png ── 温度・湿度・土壌水分の推移グラフ(日本語タイトル)
    • out/report.md ── 統計表 + 観察コメントの Markdown

構成

example-2/
├── README.md
├── collect.py    ── 模擬センサーから SQLite へ 6,048 件
├── analyze.py    ── SQL 集計 + matplotlib グラフ + Markdown
├── Makefile
├── results.md
└── out/
    ├── sensor.db        ── SQLite(約 220 KB)
    ├── sensor.png       ── 3 段グラフ(温度/湿度/土壌)
    └── report.md        ── 自動観察コメント付き

実行

pip install matplotlib
sudo apt install fonts-noto-cjk
make clean && make all

数秒で 6,048 件投入 + グラフ + レポートが完成。

なぜこれが「実例」になるのか

組み込み開発で詰まりやすい順:

  1. ハードを買う(数日〜数週間、調達待ち)
  2. 配線・はんだ付け(物理作業)
  3. ファーム書き込み(実機ループの遅さ ── 章 example-1 の主題)
  4. データを集める(動き始めたが、見方がわからない)
  5. 可視化(ここで詰まる)

このフォルダが (4) と (5) を実機抜きで完成させる:

これは章 09 の主軸 ── 「Python で全部完成 → 実機側は最後の一行だけ」周辺パイプライン版

自動観察コメント

analyze.py の最後にあるルール:

if t["max"] - t["min"] > 8:
    md.append(f"- 温度の日内変動が **{t['max']-t['min']:.1f}℃** ── 大きい。")
if sm["max"] - sm["min"] > 5:
    md.append(f"- 土壌水分が低下 ── 灌水が必要。")

数値しきい値で「気づき」を Markdown に出す。これは エージェントを呼ばずに 判断ができる例 ── 章 10「コードに凍結する」と一致する。 基準が変わったら if 文を書き換えるだけ。


計測結果 — 第 09 章 example-2

実行環境: Linux 6.18 / Python 3.11 / matplotlib 3.x / SQLite 3.45 / Noto Sans CJK JP

データ投入

=== センサーデータ投入 ===
  期間          : 2026-04-25 〜 2026-05-01 (7 日)
  サンプリング  : 5 分間隔 × 3 センサ
  投入件数      : 6,048 件 (DB: 220 KB)
  投入時間      : 約 30 ms
センサ 件数
temperature 2,016
humidity 2,016
soil_moisture 2,016

集計結果(out/report.md より)

センサ 最小 平均 最大
temperature (°C) 10.9 20.0 29.3
humidity (%) 38.4 69.9 100.0
soil_moisture (%) 21.3 30.0 39.6

グラフ(out/sensor.png)

3 段表示で温度・湿度・土壌水分の 1 週間ぶん:

日内サイクル(温度: 朝低い → 昼高い)が見える。土壌水分はじわっと 低下していて、最終日に灌水が必要。

SQL クエリの例

-- 1 時間ごとの温度平均
SELECT strftime('%Y-%m-%d %H:00', ts) AS hour, AVG(value)
FROM measurements
WHERE sensor = 'temperature'
GROUP BY hour
ORDER BY hour;

これだけで 2,016 点 → 168 点 に集約。グラフの「重なって読めない」を 解消する。

自動観察コメント(out/report.md の末尾)

## 観察(自動)

- 温度の日内変動が **18.4℃** ── 大きい。換気またはシェード検討。
- 土壌水分が **39.6% → 21.3%** に低下 ── 灌水が必要。

これは エージェントを呼ばずに 判断ができる典型例。閾値で気づきを 出す。閾値はコードに 3 行。

エージェントに「このデータをどう思う?」と毎回聞くと、

このスクリプトは:

コードに凍結できるものはエージェントに任せない(章 10 と一致)。

来月の運用

cron に登録:

*/5  * * * *   curl http://esp32.local/sensor | python3 ingest.py  # 実機収集(別途)
0    7 * * 1   cd /home/me/greenhouse && make analyze              # 毎週月曜 7:00 に集計

毎週月曜の朝、out/report.mdout/sensor.png が更新される。それを LINE に投げれば「気づき通知」も自動。

章本文との対応

1 週間 → 30 分 (matplotlib + Claude)

このフォルダは:

実プロジェクトでも、ここから 50 行追加すれば Slack 通知 / メール送信 / HTML ダッシュボードに発展できる。

再現手順

pip install matplotlib
sudo apt install fonts-noto-cjk
make clean && make all

ファイル一覧

out/

第10章「組み込みを作る ── Pythonで考え、Claudeに翻訳させる」に戻る