s平面の左側

左側なので安定してます(制御工学の話は出てきません)

Nature Remo + Google Apps Scripts(GAS) + Slack App を使ってサーバ管理不要でプログラム可能なスマートホームを実現する 前編

この記事は「ウィルゲート Advent Calendar 2022」の 1 日目の記事です。

adventar.org

12 月に入り寒さも厳しくなってきました。 我が家ではスマートリモコンである Nature Remo を活用してエアコンを含む家電操作の自動化をしています。

日常にスッと溶け込むシンプルなデザイン

そしてこの Nature Remo、実は Web API が提供されいるので自分で書いたプログラムから制御できてしまうのです。

そこで今回は、インタラクティブな動作をする(=ユーザの入力を受け付ける)Slack App の実装方法の習得も兼ねて部屋のコンディションを通知したり、エアコンを操作できる Slack App を作りました。 また「余分な運用コストや金銭的コストをかけたくない」という観点から、それらのプログラムを Google Apps Script(以下、GAS)で動かすことで「無料」かつ「サーバ管理不要」で実現しています。

本記事では、これらの実装や設定の手順をまとめています。 なお、記事を書いていたら思いのほか長くなってしまったので、2 つに分割しています。

  • 前編(本記事)に書いてあること
    • Nature Remo のセンサ値を取得して Slack に投稿する
  • 後編に書いてあること
    • Slack にインタラクティブな要素(ボタン等)を含んだメッセージを投稿する
    • 上記の入力を受け取って Nature Remo 経由でエアコンの電源を ON にする

各種概要

作ったもの

まず、プログラムから操作するリモコン(家電)を何にするかですが、

  • 照明に関するオートメーションは公式アプリで設定できる範疇で充分
  • 室温など、常に変動する条件に基づいて操作できると嬉しい
  • 単純な ON/OFF だけでなく、設定温度など細かい状態が存在する

といった観点からエアコンに決定しました。

そこからエアコンを操作したいケースを考え、以下の機能を持たせました。

  • 人の居る部屋が寒かったら(暑かったら)Slack に通知し、ボタンをクリックすると暖房(冷房)を ON にできる
  • エアコンがついている部屋の室温が一定の範囲を超えたら、そのエアコンの設定温度を自動で調整する
    • 調整した際はその旨を Slack に投稿する

センサー情報をもとに通知をしたり、エアコンを操作したりしてくれる Slack App

余談ながら 2022 年 12 月現在、我が家には 2 台の Nature Remo が設置してあり、1 台は Nature Remo 3、もう 1 台は Nature Remo Mini 2 のモデルです。 後者は人感センサを搭載していないのですが、設置箇所が書斎であり、在室時は昼間でも照明をつけていることがほとんどのため「照明がついているか」で在室の判定をしています。

nature.global

Nature API

Nature Remo に対して Web API からできることのうち、主要なものは以下の通りです。

  • Nature Remo(device)のセンサ値を取得
  • Nature Remo に登録されているリモコン(≒家電、appliance)の操作
    • エアコン(AC)、テレビ(TV)、照明(LIGHT)に分類され、それぞれエンドポイントが異なる

他にもアカウントのニックネームを変えたり登録されているリモコン(家電)の情報を更新したりもできるようですが、あえて Web API 経由でやる必要はないと思います。

また、5 分間に 30 リクエストまでの制限がかけられています。

(ドキュメント)

developer.nature.global

swagger.nature.global

Google Apps Script(GAS)

Google が提供するローコードプラットフォームです。 V8 ランタイムをサポートしており、通常の開発で JavaScript を書くのとほぼ同じ感覚で利用できます。

workspace.google.co.jp

制限事項はあるものの、今回のようなおもちゃ程度の用途に利用するなら充分です。 書いたコードをその場で、ボタンひとつで実行できるのも嬉しい。

他、Google のサービス(カレンダーやスプレッドシート、Google Analytics や BigQuery まで)との連携が簡単にできたり、Web ページを表示させることもできたりと、このあたりの知見を説明するだけでもう 1, 2 記事書けるくらいには重用しており、便利なものです。

Nature Remo のセンサ値を取得して Slack に投稿するまでの手順

手順 1:Nature API アクセストークンの発行

Nature Remo の Web API の呼び出しにはアクセストークンが必要になります。

以下のページにアクセスし、遷移した先の「Generate Access Token」ボタンからアクセストークンを発行することができます。

home.nature.global

アクセストークンは発行したときしか確認ができないので、その場で控えておきましょう。

アクセストークン管理画面。Google アシスタントや Alexa も API を利用していることがわかる。

手順 2:Slack App の新規作成および incoming webhook URL の発行

まず、以下のページの「Create New App」から作成します。

api.slack.com

app manifest を利用して作成する方法もあるようですが、今回は「From scratch」を選択しました。

App の名前を入力し、対象の Slack ワークスペースを選択して作成

App には様々な権限と機能を持たせることができますが、ひとまずこの時点では incoming webhooks だけ有効化します。

App 作成後に遷移した画面の「Add features and functinality」>「Incoming Webhooks」またはサイドバーの「Features」>「Incoming Webhooks」をクリックし、遷移した画面のトグルスイッチを On にします。

incoming webhooks の有効化

続いてページ下部に「Webhook URLs for Your Workspace」というセクションが追加されるので、下部の「Add New Webhook to Workspace」をクリックします。

認可の画面が表示されるので、App からメッセージを投稿したいチャンネルを選択して「Allow」をクリックします。

すると、先ほどの画面にあった表に行が追加されており、「Webhook URL」を確認することができます。

手順 3:GAS プロジェクトを作成

以下のページから「新しいプロジェクト」をクリックしてプロジェクトを作成します。

script.google.com

この際、トークンの値や incoming webhook URL を「スクリプトプロパティ」として保存しておくことで、ソースコード中に直に書かなくて済みます。

スクリプトプロパティはサイドバーの「プロジェクトの設定」から設定できる

手順 4:Nature Remo のセンサ値を取得し、Slack に投稿する

先述の Nature API ドキュメントを参照しながら Web API を叩くコードを GAS で書きます。 アクセストークンは Bearer トークンとして、Authorization ヘッダに付与してリクエストします。

取得した結果を今度は Slack App の incoming webhook URL に対して所定のフォーマットで POST することで投稿が行われます。

以下にサンプルコードを示します(実際のコードは共通化やファイルの分割などを行っており、もう少し複雑です)。 GAS において HTTP リクエストを送信するには UrlFetchApp を利用します。 また、関数名の末尾を _ で終わらせるとプロジェクトのコード以外から呼び出せないようにできます。

const fetchDevices_ = () => {
  const options = {
    headers: {
      'Authorization': `Bearer ${ScriptProperties.getProperty('NATURE_API_ACCESS_TOKEN')}`,
    },
  };

  // Nature API にリクエストを送信し、レスポンスの JSON をパース
  return JSON.parse(UrlFetchApp.fetch('https://api.nature.global/1/devices', options).getContentText());
};

const postToSlack_ = (payload) => {
  const url = ScriptProperties.getProperty('SLACK_WEBHOOK_URL');

  // Slack App の incoming webhook URL に所定形式で POST リクエスト
  UrlFetchApp.fetch(url, {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload),
  });
};

const main = () => {
  const devices = fetchDevices_();

  // センサ値は device の newest_events からアクセス可能。室温は te(temperature の略)。
  const message = devices.map((device) => `${device.name}${device.newest_events.te.val}℃`).join('\n');

  postToSlack_({text: message});
};

コードを書いたら関数を指定して「実行」をクリックします。

初回実行時には Google の認可の画面が表示されるので「許可」をクリックします。

もし「このアプリは Google で確認されていません」という警告が表示される場合は「詳細を表示」>「(安全ではないページ)に移動」をクリックします*1

Nature Remo から取得したセンサ値が Slack に投稿される

前編まとめ

前編にあたる本記事では基本的な設定および、動作確認のためのスクリプトを書くまでの手順を説明しました。 ここまでのものでも、例えば「人のいる部屋が乾燥していたら、Slack にメンションを含んだ投稿をして加湿器をつけることを促す」のようなことができます。

後編ではそこから、インタラクティブな動作をする(=ユーザの入力を受け付ける)Slack App を実装して、Slack 上からエアコンを電源を ON にできるように追加の実装、設定をします。

そして「ウィルゲート Advent Calendar 2022」、翌日の投稿は西本さんによる「【GAS】GA4の特定のイベント数を毎日スプレッドシートに自動取得してみた」です。 お楽しみに!

*1:自分で実装したアプリケーションなので信頼できる、ということ。普段は不用意にこの操作を行わないこと