Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9409

Alexa SmartHomeSkillの開発 公式チュートリアルに加え、アカウントリンクの実装、ModeControllerの追加

$
0
0

はじめに

AlexaのSmartHomeSkillは、照明や扇風機などの家電を、Alexaを使って操作するための機能です。PowerOnOffやModeControllerなどのあらかじめ決められたインターフェイスがあり、それらを利用して機能を組み立てていきます。
SmartHomeSkillでは、音声認識から意図解釈まではAmazon側でビルドされたモデルによって実行するため、開発者が意図解釈のために対話エージェントを訓練する必要はありません。
CustomSkillでは、意図解釈は、開発者が、Dialogflowのようなエージェントを訓練する必要があります。

目指す姿

スマートフォンのAlexaアプリから、SmartHomeSkillを呼び出します。
SmartHomeSkillを使って、PowerOnOffおよび、ModeControllerを使えるようにします。
本記事では、Alexaを通じて、洗濯機のオン、オフ、および、洗濯モードをデリケートモードに設定するのを目指します。
基本的には、公式のチュートリアルに従って進めます。
https://developer.amazon.com/ja-JP/docs/alexa/smarthome/steps-to-build-a-smart-home-skill.html
チュートリアルに出てくるlambdaのNode.jsのコードにアカウントリンクとModeControllerのインターフェイスを追加する形で説明します。
分かりにくいところを補完しながら進めます。

アカウントリンクの実装

まずは、アカウントリンク部分の実装を説明します。
アカウントリンクのため、本記事では、Login with Amazon(LWA)を使います。
セキュリティプロファイルを作成すると、クライアントIDとクライアントシークレットが発行されます。
lwa.png.jpg

バックエンドでは、下記の通り、Authorizationのハンドリングのための関数を追加します。
下記のコードのOAUTH_CLIENT_IDに上記のLWAのクライアントID、OAUTH_CLIENT_SECRETに、クライアントシークレットを設定します。
下記の関数は、以下の記事からコピペしました(https://qiita.com/poruruba/items/5e31b82bfbdeef20519d)。

node.js
functionhandleAuthorization(request,context){console.log("handleAuthorization function was called.");varcode=request.directive.payload.grant.code;varoptions={url:'https://api.amazon.com/auth/o2/token',method:'POST',headers:{'Content-Type':'application/json'},json:{grant_type:'authorization_code',code:code,client_id:OAUTH_CLIENT_ID,client_secret:OAUTH_CLIENT_SECRET}};returnnewPromise((resolve,reject)=>{Request(options,function(error,response,body){if(error){console.log('error: ',error);returnreject(error);}console.log(body);accessToken=body.accessToken;varheader=JSON.parse(JSON.stringify(request.directive.header));header.name='AcceptGrant.Response';context.succeed({event:{header:header,payload:{}}});returnresolve();});});}

Lambda関数の冒頭の、リクエストの種類によって処理を振り分けている箇所にて、アカウントリンクを実施する場合、上記の関数を呼び出す処理を追加します。

node.js
elseif(request.directive.header.namespace=='Alexa.Authorization'){log("DEBUG:","Authorization request",JSON.stringify(request));handleAuthorization(request,context);}

ここまでできた時点で、スマホのAlexaアプリから、スマートホームスキルのアカウントリンクができるようになっているはずです。

ModeControllerの追加

ModeControllerインターフェイス
https://developer.amazon.com/ja-JP/docs/alexa/device-apis/alexa-modecontroller.html
handleDiscovery関数内にて、デバイスのCapabilityを定義している箇所があります。ここに、ModeControllerのインターフェイスを追加します。

node.js
{"type":"AlexaInterface","interface":"Alexa.ModeController","instance":"Washer.Mode","version":"3","properties":{"supported":[{"name":"mode"}],"retrievable":true,"proactivelyReported":true,"nonControllable":false},"capabilityResources":{"friendlyNames":[{"@type":"text","value":{"text":"モード","locale":"ja-JP"}}]},"configuration":{"ordered":false,"supportedModes":[{"value":"Mode.Delicate","modeResources":{"friendlyNames":[{"@type":"text","value":{"text":"デリケート","locale":"ja-JP"}}]}}]}}// end of modecontroller interface

これで、アカウントリンク済みの状態で、「デリケートモードにして」と発話すると、Alexa側としては、デリケートモードがデバイスに存在していることは認識してくれます。
ただ、デリケートモードにしてくれと言われた時の実際の動作が規定されていないので、そこを決めてやります。
以下のデモコードを追加します。

node.js
functionhandleModeControl(request,context){log("DEBUG handleModeControl called.");// 検出中に渡されたデバイスIDを取得しますvarrequestMethod=request.directive.header.name;varinstance=request.directive.header.instance;varresponseHeader=request.directive.header;responseHeader.namespace="Alexa";responseHeader.name="Response";responseHeader.messageId=responseHeader.messageId+"-R";// リクエスト中のユーザートークンパスを取得しますvarrequestToken=request.directive.endpoint.scope.token;varmodeResult=request.directive.payload.mode;// 本来は、ここで洗濯機の制御APIを呼び出しますvarcontextResult={"properties":[{"namespace":"Alexa.ModeController","instance":instance,"name":"mode","value":modeResult,"timeOfSample":"2017-09-03T16:20:50.52Z",//結果から取得します。"uncertaintyInMilliseconds":50}]};varresponse={context:contextResult,event:{header:responseHeader,endpoint:{scope:{type:"BearerToken",token:requestToken},endpointId:"demo_id"},payload:{}}};log("DEBUG Alexa.PowerController ",JSON.stringify(response));context.succeed(response);}

さらに、Lambdaの冒頭の処理分岐部分に以下を追記します。

node.js
elseif(request.directive.header.namespace=='Alexa.ModeController'){log("DEBUG:",JSON.stringify(request));handleModeControl(request,context);}

これで、スマホアプリからデリケートモードにして、と発話すると、handleModeControl()が呼ばれるようになります。
ほぼ同様にして、他のインターフェイスも実装することができます。

おわりに

AlexaのSmartHomeSkillを使い、電源オンオフとモード切り替えを実装しました。
SmartHomeSkillを使うことで、簡単にIoT家電を操作できるようになります。
これが足りないぞというのがありましたら、コメントお願いします。


Viewing all articles
Browse latest Browse all 9409

Trending Articles