Experiment record

SwitchBot CO₂をGoogle Apps Scriptで判定し家族LINEグループへ換気通知する

約5分周期のSwitchBot CO₂収集系へ継続判定・ヒステリシス・LINEグループPush通知を追加した。初回警報に加え、初回警報から30分後の再警告、900 ppm未満10分以上後の無通知解除の効果、解除後の新しいINITIAL警報まで実動で確認した。

概要

既存のSwitchBot住宅環境収集系に、CO₂濃度を判定して非公開の家族LINEグループへ換気を促す自動通知経路を追加しました。

本番の通知経路は、SwitchBot MeterPro(CO2) → SwitchBot Hub Mini (W0202200) → SwitchBot Cloud → SwitchBot OpenAPI v1.1 → Google Apps Script → 非公開Google Sheets測定ログ → CO₂警報状態判定 → LINE Messaging API Push → 非公開家族グループ です。

2026年8月16日の初回機能試験では、CO₂センサー付近で呼気を与えて測定値を意図的に上昇させ、16:38 JSTに対象グループへ換気警告が届くことを確認しました。通知には2812 ppm、高CO₂継続4分と表示されました。

その後の追試で、2026年8月26日に初回警報から30分後の再警告、同日中に900 ppm未満が10分以上継続した状態、2026年8月27日にその後の新しい高CO₂状態でREPEATではなく新しいINITIAL警報が送信されることまで確認しました。主要な警報状態分岐を実動確認できたため、Experiment StatusはCOMPLETEDです。

実験の背景

目的は新しいダッシュボードを増やすことではなく、設定した高CO₂条件が続いたときにだけ、家族へ換気を促すことでした。既存の住宅環境収集系ではCO₂を約5分周期で取得しているため、別の監視トリガーを追加せず、同じ測定経路に通知判定を接続しました。

単純な「1000 ppmを超えたら毎回通知」では、測定周期ごとにLINEが増えるため、継続判定、ヒステリシス、再通知間隔を組み合わせました。

実験方法

実験対象

既存のSwitchBot MeterPro(CO2)から取得しているCO₂測定値を使い、状態遷移を持つ換気警報ロジックから非公開LINEグループへのPush通知までを一つの経路として評価しました。

実験環境

本実験で使用したHub Miniは、AIEL-2026-0006で機材情報を確認したものと同じ実機です。本実験の構成では、MeterPro(CO2)の測定値をSwitchBotクラウド/OpenAPI経路で取得するためのデータ収集ハブとして使用しました。

通知判定より先に元の測定値を保存し、測定データと通知状態を分離する構成です。

警報状態設計

NORMAL
  │
  │ 1000 ppm超を2回連続で測定
  ▼
ALERT
  │
  ├─ 高CO₂条件が再成立し、前回通知から30分以上
  │       → 再警告
  │
  ├─ 900~1000 ppm
  │       → 通知なし、ALERT維持
  │
  └─ 900 ppm未満が10分以上
          → 無通知でNORMALへ復帰

1000 ppmで警報を開始し、900 ppm未満を解除側の条件とすることで、閾値付近で状態が頻繁に切り替わることを抑える設計です。設計上、CO₂値の欠測やSwitchBot APIエラーは、高い状態または低い状態が継続した証拠として扱いません。

機能試験方法

初回警報と解除後再発報は、設置済みCO₂センサー付近で呼気を与えてCO₂濃度を意図的に上げ、状態判定から対象の非公開LINEグループへPush通知が届くかを観測しました。再警告は高CO₂状態を維持して通知間隔を観測し、解除条件は非公開Google Sheets測定ログで900 ppm未満の継続を確認しました。

欠測やSwitchBot APIエラーを意図的に発生させるフォールト試験は、本実験の主要成功基準には含めず実施していません。

実験ログ

LINEグループ送信先の設定

LINE Messaging APIのPush送信先には、LINE公式アカウントが参加している非公開グループのgroupIdを使用しました。groupIdとチャネルアクセストークンはGoogle Apps ScriptのScript Propertiesへ非公開で保存しました。後述のWebhookは、このgroupIdを一度取得するためだけに使用しました。

GAS Web AppをWebhookに直接使用 — 不採用

一時Webhook受信先としてGoogle Apps Script Web Appを試したところ、設定途中ではHTTP 404、その後URLとデプロイを修正した状態ではWebhook検証に対してHTTP 302が返ることを確認しました。この経路はgroupId取得用途には継続採用しませんでした。

一時的なCloudflare Workerで回避

次にgroupId取得専用のCloudflare Workerを作り、LINE Webhook POSTの受信、x-line-signatureのHMAC-SHA256検証、管理下ログでのgroupId確認、HTTP 200応答だけを担当させました。この経路ではLINE DevelopersのWebhook検証に成功しました。

取得したgroupIdをScript Propertiesへ保存した後、Workerは削除し、LINE DevelopersのWebhook利用もOFFにしました。現在のCO₂通知経路はCloudflareへ依存していません。

2026-08-16 — 初回警報の機能試験

設置済みCO₂センサー付近で呼気を与え、測定濃度を短時間だけ意図的に高くしました。

16:38 JSTに意図した非公開家族LINEグループへ換気通知が届き、次が表示されました。

この観測によって、初回警報についてCO₂測定 → Hub Mini → SwitchBot Cloud/OpenAPI → 自動閾値・状態判定 → LINE Messaging API Push → 意図した非公開グループの経路を確認しました。

2026-08-26 — 30分再警告の実動試験

リビングのCO₂が高い状態で、7:18に初回の換気通知、7:48に再警告が届きました。

非公開Google Sheetsの実行ログにも、7:18:20にCO2Alert / SUCCESS / INITIAL通知を送信しました。、7:48:20にCO2Alert / SUCCESS / REPEAT通知を送信しました。と記録されました。実行ログ上の間隔はちょうど30分であり、設定した再通知分岐が実動したことを確認しました。

2026-08-26〜27 — 無通知解除と解除後再発報の実動試験

再警告後、非公開Google Sheets測定ログでリビングのCO₂が900 ppm未満の状態を10分以上継続したことを確認しました。この間、解除を知らせるLINE通知は送られておらず、無通知解除という設計と整合しました。

翌8月27日にセンサー付近で再びCO₂を意図的に高くしたところ、6:03に新しい換気通知が届きました。

非公開Google Sheetsの実行ログは6:03:22にCO2Alert / SUCCESS / INITIAL通知を送信しました。と記録しました。前回警報の継続であればREPEATとなるところ、新しいINITIALとして発報したため、900 ppm未満10分以上後の無通知解除が状態遷移として機能し、その後、再び高CO₂状態になった際に新しい初回警報として通知できたことを確認しました。

結論

本実験では、既存のSwitchBot CO₂収集経路で得た測定値を状態判定へ入力し、LINE Push通知を意図した非公開グループまで届ける警報の状態遷移ロジックの主要分岐を実動確認しました。

確認できたのは、初回警報、初回警報から30分後に観測した再警告、900 ppm未満10分以上後の無通知解除の効果、解除後に新しいINITIAL警報が送信されたことです。これら主要成功基準が成立したため、Experiment StatusはCOMPLETEDです。

欠測やSwitchBot APIエラーを意図的に発生させたフォールト試験は実施していません。これは未解決の不具合ではなく、主要成功基準には含めなかった追加検証です。

証拠区分のまとめ

このExperimentで得られた情報のEvidence Stateは次のとおりです。

記録内容Evidence State本実験での根拠
初回警報のエンドツーエンド経路が動作したVERIFIED2026-08-16の2812 ppm試験および2026-08-26のINITIAL通知を実観測
高CO₂状態が継続する中、初回警報から30分後に再警告したVERIFIED7:18:20のINITIALと7:48:20のREPEATをLINE表示と非公開実行ログで照合
900 ppm未満10分以上後に無通知解除の効果が生じたVERIFIED非公開測定ログの低CO₂継続と、その後にREPEATではなくINITIALが発生した状態遷移を照合
解除後の新しい高CO₂状態で再発報したVERIFIED2026-08-27 6:03:22に新しいINITIAL通知を実行ログとLINE表示で確認

各Evidence Stateの意味はEvidence State(証拠状態)を参照してください。

運用上の示唆

通知判定を既存の約5分収集トリガーへ接続したため、通知用に別のSwitchBot APIポーリングループを増やしていません。LINE通知の根拠値と非公開Google Sheetsへ保存される値を同じ観測経路にそろえられます。

一方、約5分周期のスケジュールと「1000 ppm超を2回連続」という条件を組み合わせるため、警報開始までの実時間はトリガー実行タイミングに依存します。通知に表示された4分という継続時間も、状態管理ロジックが保持した時間情報であり、センサー自体が4分間連続測定したという意味には一般化できません。

本実験では欠測・APIエラーを意図的に発生させるフォールト試験を実施していないため、この異常系の実動挙動は検証していません。長期運用では、欠測やAPIエラーを有効な高CO₂・低CO₂観測とは別に扱い、データ欠損による誤った継続判定や解除判定を避ける設計が必要です。

再現に必要なもの

本実験で使用した機材・実験環境と、実験結果とは区別した現在の購入情報を次のページにまとめています。

SwitchBot CO₂換気通知 — 使用機材・実験環境と購入情報

再現時の注意事項

再現時には、認証・送信先などの機微情報をソースコードや公開ログへ直接記録せず、Script Properties等の適切な秘密情報ストアで管理してください。主要な状態遷移を再現する場合は、初回警報、再警告、解除、解除後再発報を別々に確認すると切り分けやすくなります。欠測・APIエラーのフォールト試験は本実験では実施していない追加の堅牢性検証であり、必要に応じて主要状態遷移の再現試験とは分けて実施してください。

機械可読な実験記録

このExperimentの機械可読な正本記録をJSONとして公開しています。

AIEL-2026-0004 experiment.json

関連実験

基礎となる約5分周期の住宅環境収集系は、SwitchBotとGoogle Apps Scriptによる住宅環境の長期収集・外部気象連携・解析(改訂版)として別途公開しています。