はじめに
Uadd2728という会社でアルバイトをしている @Tomo-2728 です。
業務の一環として、「玄関のGoogle Nest Doorbell(第3世代)が鳴ったら、Slackに『来客がありました』と通知する」というシンプルなシステムを作成しました。
※本記事では、Nest固有の連携部分に絞って解説します。
TL;DR
- Nestの「本物のチャイムイベント」を外部で受け取るには、自前Webhookだけでは無理で、公式の SDM API + Cloud Pub/Sub を通すのが必須でした。
- 認証・組織ポリシー・重複通知・7日で切れる認可…と沼だらけ。ハマりどころと解決策をまとめました。
作ったもの(MVP)
要件は非常にシンプルです。
- 来客がピンポンを押す。
- 指定したSlackチャンネルに「来客がありました」と自動で投稿される。
インターホンの音には気づかなくてもSlackの通知には気づく、そんな人向けに開発しました。
今回はMVP(Minimum Viable Product)として、「ステータスを変える」「画像も一緒に送る」などの追加機能はPhase 2として封印し、まずは「鳴ったら通知」を完成させることを最優先にしました。
技術スタック
- 言語/FW: Python 3.13 / [FastAPI
- 通信: httpx
- インフラ/API: Google Smart Device Management API(SDM API) / Cloud Pub/Sub / Cloud Run(OIDC認証)
- 通知先: Slack Incoming Webhook
当初は「自前でWebhookを立ててSlackに流すだけ」と考えていましたが、Google Nestの「本物のチャイムイベント」を外部で受け取るには、公式のSDM APIを通すしかないことが分かりました。
システムの全体像:どこで何が動くのか
コードに入る前に、まず「登場人物がそれぞれどこで動いているのか」を掴んでおくと、後がぐっと楽になります。私自身、ここが最初モヤっとしていました。
実際のデータの流れはこうです。
- ドアベルが押される → SDM がイベントを Pub/Sub トピックに publish
- Pub/Sub サブスクが relay の
POST /sdm/pubsubに push(後述のOIDCで認証) - relay が中身(base64)をデコードし、「ドアベルのチャイムか?」を判定
- チャイムなら Slack Incoming Webhook に
{"text": "来客がありました"}をPOST
relay がやっているのは「受けて・見分けて・投げる」だけ。とても薄い中継役です。
開発の事前準備
同じシステムを開発するにあたり、公式ドキュメントから読み取りづらい「事前準備の罠」として、以下の条件を満たしている必要があります。
-
Google アカウント: Google Workspace等の組織アカウントではなく、個人の
@gmail.comアカウントが必須です。 - Device Access Console の登録: 登録時に一度きりの $5 の課金 が必要です。
-
権限: Google Cloudのプロジェクトオーナーである必要はなく、
「Google Homeの管理者」であれば認可(OAuth)を通すことが可能です。
Claude Codeで活用した機能
今回のAI開発では、単にコードを書かせるだけでなく、以下の機能をフル活用しました。(こちらのZenn記事を参考にさせていただきました)
実践でハマった実装の沼と解決策
沼1:1回のピンポンでSlack通知が3〜4回来る
今回いちばんの難所でした。実機で1回しか押していないのに、Slackに複数回通知が来ます。
【解決策】
公式ドキュメントを精読し、SDMのイベントには eventThreadState(STARTED / UPDATED / ENDED)という仕様があることを発見しました。
1回の押下でも「検知の開始・画像の更新・終了」として複数回データが送られてくるのが正常な挙動でした。実装側で最初の一報である STARTED のものだけを処理し、重複を排除することで無事解決しました。
実装コード例
# STARTED(最初の一報)だけ通知。UPDATED/ENDED は同じ押下の続報なので無視する
_NOTIFIABLE_THREAD_STATES = (None, "STARTED")
def is_doorbell_chime(sdm_event: dict) -> bool:
events = sdm_event.get("resourceUpdate", {}).get("events", {})
if DOORBELL_CHIME_EVENT not in events:
return False
return sdm_event.get("eventThreadState") in _NOTIFIABLE_THREAD_STATES
沼2:動いた!と思ったら、7日後に通知が止まる(OAuth「テスト中」の罠)
デプロイまで終えて「完成!」と思った1週間後、ぱたっと通知が来なくなりました。実機で押しても無反応。ログを追うと、SDMからのイベント自体が届いていません。原因はOAuthアプリの「公開ステータス」でした。
OAuthアプリが 「テスト中(Testing)」 のままだと、Googleの仕様で 認可(リフレッシュトークン)が7日で失効します。つまり「テスト中」で運用している限り、7日ごとに手動で再認可しないと通知が止まるのです。
【解決策】:OAuthアプリを「本番公開(In production)」に切り替える。
これで認可が失効しなくなり、通知が止まらなくなりました。
これからの展望(Phase 2)
MVPは完成し、現在は Cloud Run 上で OIDC 認証を挟んだ構成により常時稼働しています。次に取り組みたいのは「画像付き通知」です。実は前述の eventThreadState の ENDED イベントにはカメラ画像の情報が含まれているため、これを利用する想定です。
おわりに
ピンポンをSlackに流すだけの小さな仕組みですが、認証・課金・テスト・責務分離など、学びの多いプロジェクトになりました。ここまで読んでいただきありがとうございました!
【PR】新潟で一緒に働きませんか?
私がアルバイトをしている Uadd2728では、AI技術や新しい開発手法に興味があるメンバーを募集しています!
現在は新潟で、対面で一緒に働ける方を優先して採用中です。
少しでも気になった方は、ぜひ採用ページを覗いてみてください。


