This is my life.

There are many like it, but this one is mine.

aibo と Nature Remo を組み合わせて aibo に部屋の電気を消してもらう

まずはこちらをご覧ください。


部屋の電気を消してくれる aibo

うちの aibo は部屋の電気を消すことができます。賢いです。

2017年に現在のモデルで再登場した aibo ですが、最近ではセコムや家電との連携が発表されていて、まだまだアップデートされています。

aibo の バージョン2.7 で aibo Events API が公開された

2020年6月16日に公開された バージョン2.7 から、 aibo Events API が公開されました。

これまでも aibo Web API は公開されていたのですが、 これにより、 aibo のイベント(音声認識)をきっかけにあらかじめ指定しておいた URL にリクエストを投げることができます。

同時に、 aibo認識する言葉を登録できるようになりました。好きな言葉を認識させることができます。

認識する言葉は aibo 1体に対して3つまでです。aibo に色々させたい場合は工夫が必要ですね。 f:id:duck8823:20200708145537p:plain

これによって、例えば「電気消して(でんきけして)」という言葉に反応してリクエストを飛ばすことができるようになります。
イベントの通知も aibo 1体に対して音声コマンド3つまでで、ちょっと少ない印象ですね。

f:id:duck8823:20200708145126p:plain

僕が aibo を購入する決め手になったのがこの aibo Events API です。
これを使えば、 aibo を起点としたピタゴラスイッチが作れますね。

Nature Remo Cloud API

Nature Remo は最近流行っているスマートリモコンの一つです。
Nature Remo Cloud API が公開されていて、これを利用することでインターネット経由で家電を操作できるようになります。

まずは通常の使用の通りアプリなどから家電を登録しましょう。公式のスマホアプリから利用するだけでも CoL が爆上がりしました。

f:id:duck8823:20200708150120p:plainf:id:duck8823:20200708150137p:plain

APIで操作する準備としては、トークンを生成する必要があります。
https://home.nature.global/ からトークンを生成することができます。

続いて、操作したい家電の appliance id を取得しましょう。
[GET] /1/appliances で登録した家電の一覧が取得できます。
操作したい家電を選んだら appliance id を控えておきます。今回は操作したいのは部屋の電気です。 LIGHT として登録されています。 レスポンスの内容には、操作可能なボタンも含まれています。

{
  "id": "<appliance id>",
  ...
  "light": {
      "buttons": [
        {
          "name": "on",
          "image": "ico_on",
          "label": "Light_on"
        },
        {
          "name": "off",
          "image": "ico_off",
          "label": "Light_off"
        },
        ...
      ],
      ...
  }
}

[POST] /1/appliances/{appliance}/light でライトを操作することができます。 リクエストパラメーターには操作したいボタンを指定します。今回の場合は off を指定することで電気を消します。

Web API なので curl でも操作できます。

curl -X POST "https://api.nature.global/1/appliances/<取得した appliance id>/light" \ 
       -H "accept: application/json" \
       -H "Authorization: Bearer <予め生成したトークン>" \ 
       -H "Content-Type: application/x-www-form-urlencoded" \ 
       -d "button=off"

AWS lambda で二つのAPIをつなぐ

aibo で言葉に反応してリクエストを投げられるようになりました。
また、 Nature Remo でリクエストを受け取って家電を操作できるようになりました。

aibo が投げるリクエストは Nature Remo Cloud API が認識する形ではありません。
AWSlambda を使って aibo のリクエストを受け取り、 Nature Remo にリクエストを投げるようにしてみます。

図にすると以下のような形
f:id:duck8823:20200707214644p:plain ※実際にはそれぞれのデバイスのサーバーを介して通信することになります。

関数自体は Nature Remo Cloud API にリクエストを投げるものなので簡単ですが、
必ずセキュリティトークンの設定を行って、lambda 関数で検証するようにしましょう。
注意点としては API Gateway から lambda にリクエストを渡した時に、ヘッダーのキーが小文字になっていること。
なので、 x-security-token で取得することができます。

また、音声認識に対してイベントが通知されるので、登録した言葉かどうかの判定が必要になります。

aiboデベロッパーサイトにはエンドポイントアプリケーションの実装例 があるので、lambda関数 も Python で記述すれば参考になると思います。

今回使った lambda関数は以下です。

import urllib.request
import urllib.parse
import json

def lambda_handler(event, context):
    # セキュリティートークンのチェック
    if 'x-security-token' not in event['headers'] or event['headers']['x-security-token'] != '<aiboのイベント通知で登録したセキュリティトークン>':
        return {
            'statusCode': 400,
            'body': 'not authorized'
        }

    # aibo Events API から送られてきたリクエスト
    request_body = json.loads(event['body'])

    # aibo にエンドポイントを登録する時の検証
    if request_body['eventId'] == 'endpoint_verification':
        return {
            'statusCode': 200,
            'body': json.dumps({ 'challenge': request_body['challenge'] })
        }
    
    deviceId = request_body['deviceId']
    eventId = request_body['eventId']
    return execute_action(deviceId, eventId)
    

def execute_action(deviceId, eventId):
    ## usercommand1 = 登録した「でんき / でんきけして」に反応した場合 Nature Remo Cloud API にリクエストを投げる
    if eventId == 'voice_command::usercommand1':

        req = urllib.request.Request(
            'https://api.nature.global/1/appliances/<取得した appliance id >/light', 
            data=urllib.parse.urlencode({'button': 'off'}).encode(),
            method='POST', 
            headers={
                'accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded',
                'Authorization': 'Bearer <Nature Remo で予め生成したトークン>',
            }
        )
    
        try:
            with urllib.request.urlopen(req) as response:
                return {
                    'statusCode': response.getcode(),
                    'body': response.read()
                }
    
        except urllib.error.URLError as e:
            print(e)
            return {
                'statusCode': 500,
                'body': json.dumps(e.reason)
            }
        
    elif eventId == 'voice_command::usercommand2':
        return {
            'statusCode': 200,
            'body': 'nothing to do usercommand2'
        }

    elif eventId == 'voice_command::usercommand3':
        return {
            'statusCode': 200,
            'body': 'nothing to do usercommand3'
        }

まとめ

aibo と Nature Remo の2つデバイスが提供しているAPIを組み合わせて、言葉に反応して家電を操作することができました。

APIを眺めながら、これとこれ組み合わせたらこんなことできるなー。って考えるのはとても楽しいです。
今回は「電気を消して」に対して電気を消すボタンにしましたが、 aibo あるいは Nature Remo のどちらにも照度センサーがついているので、現在の照度に合わせて電気を消すかつけるかのふるまいを切り替えることも可能だと思います。

Google Home でいいやん?それはそう。