熱中症から始まったアラートシステム、雨雲接近も検知できるようにしてみた ― 設定一元化とON/OFFスイッチ導入編

みなさん、こんにちは。

これまで2回にわたって、我が家の熱中症アラートシステムについてご紹介してきました。

前回、AmbientからThingSpeakへの移行を無事に終えたことで、熱中症アラート(heatstrok_alert.py)とCO2アラート(co2_alert.py)の2本がThingSpeak経由で安定して動くようになりました。

今回はそこからさらに一歩進んで、次の3つの改修を行いました!続々編としてまとめておきます。

  1. 雨雲接近アラート(rain_cloud_alert.py)の新規追加
  2. 3つのプログラムに散らばっていた設定のconfig.pyへの一元化
  3. 3つのプログラムをまとめて実行し、アラートごとにON/OFFを切り替えられるrun_alerts.shの追加

現在のシステム構成

現時点でのリポジトリ構成はこんな感じになりました!

参考:https://github.com/taoman26/heatstroke_alert

heatstroke_alert/
├── config.py             # 3プログラム共通の設定ファイル
├── heatstrok_alert.py    # 熱中症アラート(ThingSpeakの温度・湿度を監視)
├── co2_alert.py          # CO2アラート(ThingSpeakのCO2濃度を監視)
├── rain_cloud_alert.py   # 雨雲接近アラート(Yahoo! YOLPの降水強度を監視)
└── run_alerts.sh         # 上記3プログラムをまとめて実行するシェルスクリプト

それでは、今回追加した3つの改修ポイントを順番にご紹介していきます。


1. 雨雲接近アラート(rain_cloud_alert.py)を追加

温度・湿度・CO2と揃ってきたら、次に欲しくなるのはやっぱり「そろそろ雨が降りそう!」という情報ですよね。洗濯物を干しっぱなしにして突然の雨で痛い目を見た経験、みなさんもありますよね?(私は何度もあります…笑)

そこで今回は、Yahoo!デベロッパーネットワークが提供している YOLP(Yahoo! Open Local Platform)気象情報API を利用してみることにしました。

指定した緯度経度の降水強度(Rainfall、mm/h)をJSON形式でサクッと取得できる便利なAPIで、地図タイルや画像を返す複雑なエンドポイントは使っていません。データがJSONだけで完結するため、これまでの2本と同じ構成にとても自然に組み込むことができました。

APIからは、このような形でレスポンスが返ってきます(該当部分のみ抜粋)。

{
  "Feature": [
    {
      "Property": {
        "WeatherList": {
          "Weather": [
            { "Type": "observation", "Date": "202608261100", "Rainfall": 0.5 }
          ]
        }
      }
    }
  ]
}

この Feature[0].Property.WeatherList.Weather[0].Rainfall の値が現在の降水強度です。ここから数値を取り出して、以下のロジックで状態を判定しています。

降水強度判定結果
0 mm/h雨雲なし
0.1〜1 mm/h未満雨雲接近
1〜10 mm/h未満雨雲通過中
10 mm/h以上強い雨(警戒)
def judge_rainfall(rainfall):
    if rainfall <= 0:
        return "雨雲なし"
    elif rainfall < 1:
        return "雨雲接近"
    elif rainfall < 10:
        return "雨雲通過中"
    else:
        return "強い雨(警戒)"

ここで少し悩んだ「Alexaの発話タイミング」

実装にあたって少し考えたのが、「Alexaにどのタイミングで喋らせるか」という点です。

熱中症アラートやCO2アラートは「閾値を超えたら知らせる」というシンプルな二値判定でした。一方で雨雲アラートは4段階の判定があります。もし「強い雨(警戒)」までAlexaが逐一喋り出すと、家の中がちょっと騒がしくなってしまいますよね。

そこで、Alexaが発話するのは「雨雲接近」と判定されたときだけ! という仕様に絞りました。

「洗濯物を取り込もう」「傘を用意しよう」とすぐ行動に移せる、まさに「接近中」のベストタイミングだけを教えてもらう形です。それ以外の判定結果(雨雲なし・雨雲通過中・強い雨)は、他のプログラム同様ログ出力のみに留めています。

if judgement == "雨雲接近":
    send_alexa_alert(speech)
else:
    logger.info(f"「雨雲接近」ではないため、Alexaへの発話は行いません(判定結果: {judgement})")

2. 設定パラメータを config.py に一元化

3本目のプログラムを書いているときに改めて気づいたのですが、THINGSPEAK_CHANNEL_IDALEXA_DEVICE_NAMEALEXA_CONTROL_PATH といった設定値は、実はどのプログラムでもまったく同じ値を使います。

これまでは各 .py ファイルの冒頭に同じ設定ブロックをコピペしていたのですが、さすがに3本目ともなると「これは1箇所にまとめるべきだ…!」となりまして、設定ファイルへ集約することにしました。

変更前(各プログラムが個別に設定を記述)

# heatstrok_alert.py
THINGSPEAK_CHANNEL_ID = ""
ALEXA_DEVICE_NAME = "リビングルーム"
ALEXA_CONTROL_PATH = "/path/to/alexa_remote_control.sh"
TEMPERATURE_THRESHOLD = 28.0
HUMIDITY_THRESHOLD = 60.0

# co2_alert.py(ほぼ同じ内容が重複…)
THINGSPEAK_CHANNEL_ID = ""
ALEXA_DEVICE_NAME = "リビングルーム"
ALEXA_CONTROL_PATH = "/path/to/alexa_remote_control.sh"
CO2_THRESHOLD = 1000.0

変更後(config.py に集約してインポートするだけ!)

# config.py
THINGSPEAK_CHANNEL_ID = ""
TEMPERATURE_THRESHOLD = 28.0
HUMIDITY_THRESHOLD = 60.0
CO2_THRESHOLD = 1000.0
ALEXA_DEVICE_NAME = "リビングルーム"
ALEXA_CONTROL_PATH = "/path/to/alexa_remote_control.sh"

# heatstrok_alert.py
from config import (
    THINGSPEAK_CHANNEL_ID,
    TEMPERATURE_THRESHOLD,
    HUMIDITY_THRESHOLD,
    ALEXA_DEVICE_NAME,
    ALEXA_CONTROL_PATH,
)

これで、ThingSpeakのAPIキーを変えたいときも、Alexaのデバイス名を変更したいときも、触るファイルは config.py だけになりました!地味な作業ですが、「1つのファイルだけ修正し忘れて動かない…」といううっかり事故を防げるのはかなり大きいです。

※なお、前回アラート時刻の保存先(LAST_ALERT_TIME_FILE)のようにプログラムごとに固有の値は、HEATSTROKE_LAST_ALERT_TIME_FILECO2_LAST_ALERT_TIME_FILE のように名前を分けて config.py に整理しています。


3. run_alerts.sh でまとめて実行&ON/OFFスイッチを導入

3本のプログラムが揃ったところで、次に「これらをまとめてスマートに実行したい!」という欲が出てきました。これまでは cron にそれぞれの .py を個別登録していたのですが、ログがあちこちに分散して管理しづらかったんですよね。

そこで作成したのが run_alerts.sh です!

#!/usr/bin/env bash
set -uo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_FILE="/tmp/alert.log"

{
    echo "===== $(date '+%Y-%m-%d %H:%M:%S') 実行開始 ====="
    run_if_enabled ENABLE_RAIN_CLOUD_ALERT rain_cloud_alert.py
    run_if_enabled ENABLE_HEATSTROKE_ALERT heatstrok_alert.py
    run_if_enabled ENABLE_CO2_ALERT co2_alert.py
    echo "===== $(date '+%Y-%m-%d %H:%M:%S') 実行終了 ====="
} > "${LOG_FILE}" 2>&1

ここでのこだわりポイントは2つあります。

  • ログは実行ごとに上書き(>
    • 常に「直近の実行結果」だけをサクッと確認できるように上書きにしています。過去のログをしっかり追いたい場合は、各プログラムが出力しているsyslogを見ればOKという割り切りです。
  • set -e はあえて外す
    • 万が一3本のうち1本がエラーで失敗しても、残りの2本は止めずにしっかり実行してほしいためです。

さらに、config.py 側にアラートごとのON/OFFスイッチ(フラグ)も用意してみました。

# config.py
ENABLE_HEATSTROKE_ALERT = True
ENABLE_CO2_ALERT = True
ENABLE_RAIN_CLOUD_ALERT = True

シェルスクリプト(run_alerts.sh)側からは、以下のようにPythonを経由して直接設定値を読みに行かせています。

is_enabled() {
    python3 -c "import sys; sys.path.insert(0, '${SCRIPT_DIR}'); import config; print(bool(getattr(config, '$1')))"
}

run_if_enabled() {
    local flag_name="$1"
    local script_name="$2"

    if [ "$(is_enabled "${flag_name}")" = "True" ]; then
        echo "--- ${script_name} ---"
        python3 "${SCRIPT_DIR}/${script_name}"
    else
        echo "--- ${script_name} (${flag_name}=Falseのためスキップ) ---"
    fi
}

こうしておけば、「梅雨の時期だけ雨雲アラートを有効にしたい」「長期不在の間はCO2アラートだけ OFF にしておきたい」といった調整が、config.pyTrue / False を書き換えるだけでカンタンに行えます!

シェルスクリプトとPythonをまたぐので少しトリッキーに見えるかもしれませんが、「すべての設定は config.py にまとめる」というルールを徹底できたので大満足です。


拡張可能な見守りシステムに進化!

今回の改修内容をまとめると以下の通りです!

  1. Yahoo! YOLP 気象情報APIを使った雨雲接近アラートを追加(発話は「接近時」のみに最適化)
  2. 3つのプログラムの設定を config.py に一元化して管理を一発化
  3. run_alerts.sh でまとめて実行しつつ、config.py のフラグで個別に ON/OFF できるように改修

熱中症・CO2・雨雲接近と、暮らしに役立つ3つのアラートが一つの仕組みとしてまとまり、我が家の見守りシステムとしてかなり実用的な形になってきました!

今後新しいセンサーやアラートを増やしたくなった際も、config.py に設定を追加して run_alerts.sh に1行書き足すだけで拡張できます。どんなセンサーがどんな困りごとを解決してくれるのか、想像するだけでも楽しいですよね!


「自分も何か作ってみたい」と思われた方、そのアイデア、頭の中で寝かせておくのはもったいないかもしれません。

ビューローみかみでは、構想段階の壁打ちからPoC・実装・現場導入まで、現場で「使い続けられる」ものづくりを支援しています。

アイデアを短期間で「動くもの」にし、PoCで終わらせず、実運用まで伴走します。まずは「これ、作る価値ありますか?」という壁打ちからでも大歓迎です。

▶ PoC・MVP開発サービスの詳細はこちら

気になることがあればお気軽にご相談ください。

本日も最後までお読みいただきありがとうございました!

それでは、よいIoTライフを!

カテゴリ: IoT, Raspberry Pi

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール