AWS IoT Enterprise ButtonのデータをGoogle Spreadsheetに記録する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

育児休業中の五十嵐です。

【国内販売開始】AWS IoT Enterprise Button試してみたらホンマに簡単にLambda関数を実行できた | Developers.IO の記事を読んで、脊髄反射的に「AWS IoT Enterprise Button(以下、IoT Buttonといいます)」をポチりました。

そして到着。

なにか作ろうと、家の中でネタを探したところ、ちょうど良さそうなものを見つけました。

これは新生児の生活を記録するノートです。我が家では主に排泄と授乳の回数を記録していましたので、これをIoT Buttonで記録できるようにしてみました。

仕様

IoT Buttonが押されたら、押された時間と、Click Typeを記録します。Click Typeの意味付けは以下の通りです。

  • シングルクリックで「おしっこ」
  • ダブルクリックで「うんち」
  • 長押しクリックで「おっぱい」

データはGoogle Spreadsheetに記録します。記録したデータを可視化するUIを作るのが面倒だったので、Google Spreadsheetに書いておけばどうにかなるだろうという魂胆です。

環境

  • Node v8.10.0

作業手順

1. IoT Buttonのセットアップをする

IoT Buttonのセットアップは冒頭でも紹介した記事の通りですのでそちらを参照してください。

2. Google SpreadsheetにAPI経由で値を書き込むプログラムを作成する

2.1 Google APIs のプロジェクトとサービスアカウントを作成する

まずは以下の手順に従い、Google APIs のプロジェクトとサービスアカウントを作成します。手順では OAuth client ID を作成するようになっていますが、 サービスアカウント を作成してください。

Node.js Quickstart  |  Sheets API  |  Google Developers

OAuth client ID は、OAuth2.0の認可コードフローによりユーザアカウントとパスワードによる認証を行う方式です。Lambdaのようなバックエンドアプリケーションでは認証に秘密鍵を用いる サービスアカウント を使用します。また、 APIキー というキーのみで認可する方式もあるのですが、Sheets APIで試したところGET系のリクエストはできましたが、POST系のリクエストは401エラーとなりました。(このことについてはドキュメントでの言及が見つかりませんでしたが、Stack Overflowでも同様の質問がありました。)

Google APIsの認証については以下のドキュメントが詳しいです。

Cloud API サービスに対する認証  |  Google Cloud Speech API ドキュメント  |  Google Cloud

サービスアカウントができたら、認証情報のJSONファイルをダウンロードします。

また、スプレッドシートを作成して、「共有」にサービスアカウントのメールアドレスを追加します。これでサービスアカウントからスプレッドシートの操作が可能になります。

2.2 Google Sheets API v4でGoogle Spreadsheetに値を追加する

spreadsheets.values.append API を使ってGoogle Spreadsheetに行を追加します。spreadsheetId はGoogle SpreadsheetのURLの /d/ の後ろの長い文字列です。以下のページからはAPIの動作確認も行うことが出来ます。

Method: spreadsheets.values.append  |  Sheets API  |  Google Developers

Node.jsのライブラリを使う場合の、サービスアカウントでの認証方法は以下のとおりです。

google/google-api-nodejs-client | Service to Service Authentication

環境変数 GCLOUD_PROJECT に Google APIs のプロジェクトID、 GOOGLE_APPLICATION_CREDENTIALS にサービスアカウントの認証情報のJSONファイルのパスを設定します。ローカル環境では、direnvを使いました。

$ direnv edit .
export GCLOUD_PROJECT=プロジェクトIDをここに埋める
export GOOGLE_APPLICATION_CREDENTIALS=secret.json

また、 googleapis モジュールもインストールしておきます。

$ npm install googleapis --save

雑にできたプログラムがこちらです。

'use strict'

const {google} = require('googleapis')
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets']

appendData('うんち')

async function appendData(message) {
  // This method looks for the GCLOUD_PROJECT and GOOGLE_APPLICATION_CREDENTIALS
  // environment variables.
  const auth = await google.auth.getClient({
    // Scopes can be specified either as an array or as a single, space-delimited string.
    scopes: SCOPES
  })

  const sheets = google.sheets({version: 'v4', auth: auth})
  const res = await sheets.spreadsheets.values.append({
    spreadsheetId: 'スプレッドシートIDをここに埋める',
    range: "A1:B1",
    valueInputOption: "USER_ENTERED",
    resource: {
      values: [
        [
          new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''),
          message
        ]
      ]
    }
  }).catch((err) => {
    console.log('The API returned an error: ' + err)
    throw err
  })

  console.log("Successed")
  console.log("Status: " + res.status)
}

これでプログラムからGoogle Spreadsheetに行が追記されるようになりました。

3. IoT ButtonとLambdaを連携する

3.1 プログラムをLambdaにする

Lambdaに必要なhandlerの関数を作成します。Click Typeはhandlerの引数のeventから取得することできますので、これをメッセージに置き換えます。

'use strict'

const {google} = require('googleapis')
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets']

exports.handler = (event, context, callback) => {
  console.log('Received event:', event)

  let message = ''
  switch(event.deviceEvent.buttonClicked.clickType){
    case 'SINGLE':
      message = 'おしっこ'
      break
    case 'DOUBLE':
      message = 'うんち'
      break
    case 'LONG':
      message = 'おっぱい'
      break
  }

  appendData(message)
}

async function appendData(message) {
    // 先ほどと同じなので省略
}

そして必要なファイルをzipにしてデプロイします。

$ zip -r lambda.zip index.js secret.json node_modules/

また、Lambda側にもdirenvで設定したのと同じ環境変数を設定します。

3.2 IoT ButtonとLambdaを連携する

AWS IoT 1-Clickにて、登録したIoT Buttonと、作成したLambdaを関連付けます。

また、IoT Buttonをプレイスメントとして登録します。

このあたりも冒頭の記事と同じです。

感想

  • IoT ButtonをLambdaと連携するのは本当に簡単でした。今までも他のデバイスでやろうと思えばできたことですが、敷居が高かったので、この簡単さは画期的です。あとはLambdaでできることを考えれば良いので、アイディアは無限大です。
  • ボタンをクリックして緑に光って(データが送信されて?)から、Lambdaを起動するまでのレイテンシは体感的に1秒程度で、とても早かったです。AWSのリージョンはVirginiaでした。
  • UI/UX的には、シングルクリック・ダブルクリックは良いのですが、長押しクリックは成功したかどうかがわかりにくいのであまり良くないと感じました。(短すぎるとシングルクリックになるし、長すぎるとメンテモード?になります。)操作が2つ以上ある場合は、複数のIoT Buttonを組み合わせて使ったほうがいいかもしれません。
  • 用途として向いているのは、「正確性・確実性を求めない」「操作のパターンは1つか2つ」「1クリックあたり5秒かかっても問題ない(連打はできない)」あたりの要件が満たされるものかなと思います。