スマートホーム

たくろーどんさんの記事を見ながらBOCCO emoをNode-REDから発話させてみた

ユカイ工学さんのファミリーロボットBOCCO emoをつい先日知り、自分のやっているスマートホームに組み合わせられそうだなのでとても期待しています。

前回は、スマートホームで人とデバイスとのインターフェースとしてBOCCOemoはAPI使えるから可能性を感じている件という記事でAPIを試してみました。

今回はたくろーどん(@takudooon)さんがzennに「BOCCO emo をNode-REDから入力したテキストで発話させてみる」という記事を書かれていたので、この記事を見ながらNode-REDとBOCCO emoを連携させてみたいと思います。

アクセストークンの定期取得

UntitledImage

たくろーどんさんのフローをそのままインポート。

取得したアクセストークンをchangeノードでglobalに格納してるんですね!いままでこういうことはfunctionノードでやってたけど、こっちのほうがわかりやすい!勉強になります。

リフレッシュトークンはアクセストークンを取得するときだけ必要だから、これもchangeノードにいれているので、すごくシンプルにわかりやすくできてる。

UntitledImage

そして、グローバル変数がコンテキストデータから確認できることも知らなかった!

この記事読んだだけで、Node-REDの経験値がかなり上がります。

部屋一覧の取得

たくろーどんさんのフローをそのままコピペして部屋の一覧を取得するフローを動かします。

“部屋のIDもグローバル変数で管理し呼び出して使っても良いと思います。”

とたくろーどんさんが書かれていたので、部屋のIDをグローバル変数”uuid”に格納するフローを追加しました。

UntitledImage

http requestからのレスポンスをjsonにした後、

UntitledImage

部屋のIDをglobal.uuidに格納します。

UntitledImage

コンテキストデータからも確認できました。

[{"id":"8ca880b35b47dd26","type":"http request","z":"55d10d43.443754","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://platform-api.bocco.me/v1/rooms","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":650,"y":460,"wires":[["adf288e08fe3212b","5b9f5124484cf86b"]]},{"id":"adf288e08fe3212b","type":"debug","z":"55d10d43.443754","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":750,"y":540,"wires":[]},{"id":"3d72358292317ea7","type":"inject","z":"55d10d43.443754","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"アカウント情報の取得","payload":"","payloadType":"str","x":310,"y":340,"wires":[["0777324a798680aa"]]},{"id":"0777324a798680aa","type":"function","z":"55d10d43.443754","name":"JSONのデータ作成","func":"//globa.get()でglobal変数の値を取得する\n//「Bearer 」を連結する(※空白も含める)\nmsg.payload = \"Bearer \" + global.get(\"access_token\");\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":400,"wires":[["44f3270c0852a2ad"]]},{"id":"44f3270c0852a2ad","type":"change","z":"55d10d43.443754","name":"アクセストークンの指定","rules":[{"t":"set","p":"headers.Authorization","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":460,"wires":[["8ca880b35b47dd26"]]},{"id":"5b9f5124484cf86b","type":"json","z":"55d10d43.443754","name":"","property":"payload","action":"","pretty":false,"x":670,"y":400,"wires":[["11291ac5b21bbfc2"]]},{"id":"11291ac5b21bbfc2","type":"change","z":"55d10d43.443754","name":"UUIDをグローバルに格納","rules":[{"t":"set","p":"uuid","pt":"global","to":"payload.rooms[0].uuid","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":400,"wires":[[]]}]

メッセージを送信

UntitledImage

こちらもたくろーどんさんのフローをコピペした後、部屋のIDをglobalから取得してhttp requestノードのURLに反映させるように修正しました。

UntitledImage
msg.payload = "Bearer " + global.get("access_token");
msg.url = "https://platform-api.bocco.me/v1/rooms/"+ global.get("uuid") +"/messages/text";
return msg;

“JSONのデータ作成”のfunctionノードにはグローバル変数からuuidを取得してそれをmsg.urlに入れています。

UntitledImage

こうすることで、http requestノードのURLにはmsg.urlの値が使われるようになります。

全体のフロー

UntitledImage

ということで、たくろーどんさんのフローで勉強しながら、部屋のIDをグローバルにしたぷち改良フローです。

[{"id":"5eafc934.ac5ce8","type":"http request","z":"55d10d43.443754","name":"POST","method":"POST","ret":"obj","paytoqs":false,"url":"https://platform-api.bocco.me/oauth/token/refresh","tls":"","persist":false,"proxy":"","authType":"","x":570,"y":200,"wires":[["1fbb154b.05fc2b","cabbc063.e76e6","3e2532c5.c690de"]]},{"id":"e4065ab5.88d4b8","type":"inject","z":"55d10d43.443754","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"1800","crontab":"","once":true,"onceDelay":0.1,"topic":"アクセストークンを定期的に取得","payload":"","payloadType":"str","x":220,"y":140,"wires":[["961c87ca.1ced18"]]},{"id":"1fbb154b.05fc2b","type":"debug","z":"55d10d43.443754","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.access_token","targetType":"msg","x":820,"y":240,"wires":[]},{"id":"6d7e2f2e.18bbe","type":"change","z":"55d10d43.443754","name":"リフレッシュトークン","rules":[{"t":"set","p":"payload","pt":"msg","to":"{   \"refresh_token\": \"リフレッシュトークン\" }","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":200,"wires":[["5eafc934.ac5ce8"]]},{"id":"961c87ca.1ced18","type":"change","z":"55d10d43.443754","name":"Content-Type","rules":[{"t":"set","p":"headers.Content-Type","pt":"msg","to":"application/json","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":180,"y":200,"wires":[["6d7e2f2e.18bbe"]]},{"id":"cabbc063.e76e6","type":"debug","z":"55d10d43.443754","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.refresh_token","targetType":"msg","x":820,"y":280,"wires":[]},{"id":"3e2532c5.c690de","type":"change","z":"55d10d43.443754","name":"グローバル変数に格納","rules":[{"t":"set","p":"access_token","pt":"global","to":"payload.access_token","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":800,"y":200,"wires":[[]]},{"id":"8ca880b35b47dd26","type":"http request","z":"55d10d43.443754","name":"","method":"GET","ret":"txt","paytoqs":"ignore","url":"https://platform-api.bocco.me/v1/rooms","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":650,"y":460,"wires":[["adf288e08fe3212b","5b9f5124484cf86b"]]},{"id":"adf288e08fe3212b","type":"debug","z":"55d10d43.443754","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":750,"y":540,"wires":[]},{"id":"3d72358292317ea7","type":"inject","z":"55d10d43.443754","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"アカウント情報の取得","payload":"","payloadType":"str","x":310,"y":340,"wires":[["0777324a798680aa"]]},{"id":"0777324a798680aa","type":"function","z":"55d10d43.443754","name":"JSONのデータ作成","func":"//globa.get()でglobal変数の値を取得する\n//「Bearer 」を連結する(※空白も含める)\nmsg.payload = \"Bearer \" + global.get(\"access_token\");\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":400,"wires":[["44f3270c0852a2ad"]]},{"id":"44f3270c0852a2ad","type":"change","z":"55d10d43.443754","name":"アクセストークンの指定","rules":[{"t":"set","p":"headers.Authorization","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":460,"wires":[["8ca880b35b47dd26"]]},{"id":"77cbb5f693e457a6","type":"http request","z":"55d10d43.443754","name":"","method":"POST","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":710,"y":720,"wires":[["4d826a8e72d0952f"]]},{"id":"5518b982d529d5eb","type":"inject","z":"55d10d43.443754","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"メッセージ送信","payload":"","payloadType":"str","x":220,"y":640,"wires":[["5dc2065fd9736ab4"]]},{"id":"4d826a8e72d0952f","type":"debug","z":"55d10d43.443754","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":750,"y":800,"wires":[]},{"id":"ae9777d36d97f2ec","type":"change","z":"55d10d43.443754","name":"発話内容","rules":[{"t":"set","p":"payload","pt":"msg","to":"{   \"text\": \"おはよう。\" }","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":540,"y":720,"wires":[["77cbb5f693e457a6"]]},{"id":"889d6b90fea26727","type":"change","z":"55d10d43.443754","name":"Content-Type","rules":[{"t":"set","p":"headers.Content-Type","pt":"msg","to":"application/json","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":720,"wires":[["ae9777d36d97f2ec"]]},{"id":"5dc2065fd9736ab4","type":"function","z":"55d10d43.443754","name":"JSONのデータ作成","func":"msg.payload = \"Bearer \" + global.get(\"access_token\");\nmsg.url = \"https://platform-api.bocco.me/v1/rooms/\"+ global.get(\"uuid\") +\"/messages/text\";\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":640,"wires":[["ef760e4ea79b4e66"]]},{"id":"ef760e4ea79b4e66","type":"change","z":"55d10d43.443754","name":"アクセストークンの指定","rules":[{"t":"set","p":"headers.Authorization","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":640,"wires":[["889d6b90fea26727"]]},{"id":"5b9f5124484cf86b","type":"json","z":"55d10d43.443754","name":"","property":"payload","action":"","pretty":false,"x":670,"y":400,"wires":[["11291ac5b21bbfc2"]]},{"id":"11291ac5b21bbfc2","type":"change","z":"55d10d43.443754","name":"UUIDをグローバルに格納","rules":[{"t":"set","p":"uuid","pt":"global","to":"payload.rooms[0].uuid","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":870,"y":400,"wires":[[]]}]

まとめ

以上、たくろーどんさんのフローを元に、Node-REDからBOCCO emoにメッセージを送るテストをしてみました。

次は、KNXやModbusなどのセンサーデータをBOCCO emoに喋らせることなど試していきたいとおもいます。

引き続き、BOCCO emoの可能性を探っていきます。

ABOUT ME
中畑 隆拓
スマートライト㈱ 代表取締役。IoTソリューションの開発、スマートホーム&オフィスのコンサルティング、DALI,KNX,EnOceanなどのインテグレーションを行っています。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です