前回の「Nest MiniでLocal Home SDKを使ってお家のIoTロボットを操作する 第4回」では、コードラボの「Smart Home Local Execution」で使用していた仮想デバイス(仮想スマートウォッシャー)を、ピッコロボIoTに置き換えるように実装しました。
ピッコロボIoTについては、「Nest MiniでLocal Home SDKを使ってお家のIoTロボットを操作する 第1回」をご覧ください。
今回は、今までは「洗濯機」として扱っていたピッコロボIoTですが、適切なデバイス名で呼ぶように実装していきます。
GoogleHomeデバイスで利用できる家電デバイス
以前にも少し触れましたが、GoogleHomeデバイスでは、家電をアプリ呼び出しなしに操作できる機能があります。
Smart Homeのリファレンスに「Smart Home Device Types」というページがあり、ここの一覧のDeviceが、操作可能な家電になります。
また、各家電の操作コマンドは、Recommended Traitsに書かれているものが対象になります。
今まで「洗濯機」として扱ってきたのは、「Washer」というDeviceで、「Modes」「OnOff」「RunCycle」「StartStop」「Toggles」の5つのRecommended Traitsがあります。
「Switch」というDeviceで、「OnOff」というRecommended Traitsがあるので、これに変えて、ピッコロボIoTを「スイッチを入れて」で動かして、「スイッチを切って」で止めるようにしてみようと思います。
クラウドフルフィルメントの修正
「smarthome-local/app-start/functions」の「index.js」を以下のように変更します。
コメントアウトしたところは、説明上残しているだけで、除去してもらって構わないです。
「washer」から「switch」に変更し、状態がOnOffだけになったので、不要なものを除去しています。
また、デバイス名も「Piccorobo IoT」に変更してみました。
app.onSync((body) => { return { requestId: body.requestId, payload: { agentUserId: '123', devices: [{ /* washer から switch に変更 */ id: 'switch', type: 'action.devices.types.SWITCH', traits: [ 'action.devices.traits.OnOff', ], name: { /* Piccorobo IoTに変更 */ defaultNames: ['Piccorobo IoT'], name: 'PiccoroboIoT', nicknames: ['PiccoroboIoT'], }, ... }], }, }; }); const queryFirebase = async (deviceId) => { const snapshot = await firebaseRef.child(deviceId).once('value'); const snapshotVal = snapshot.val(); return { on: snapshotVal.OnOff.on, /* 不要なのでコメントアウト */ //isPaused: snapshotVal.StartStop.isPaused, //isRunning: snapshotVal.StartStop.isRunning, }; } const queryDevice = async (deviceId) => { const data = await queryFirebase(deviceId); return { on: data.on, /* 不要なのでコメントアウト */ /* isPaused: data.isPaused, isRunning: data.isRunning, currentRunCycle: [{ currentCycle: 'rinse', nextCycle: 'spin', lang: 'en', }], currentTotalRemainingTime: 1212, currentCycleRemainingTime: 301, */ }; } ... const updateDevice = async (execution,deviceId) => { const {params,command} = execution; let state, ref; switch (command) { case 'action.devices.commands.OnOff': state = {on: params.on}; ref = firebaseRef.child(deviceId).child('OnOff'); break; /* 不要なのでコメントアウト */ /* case 'action.devices.commands.StartStop': state = {isRunning: params.start}; ref = firebaseRef.child(deviceId).child('StartStop'); break; case 'action.devices.commands.PauseUnpause': state = {isPaused: params.pause}; ref = firebaseRef.child(deviceId).child('StartStop'); break; */ } return ref.update(state) .then(() => state); }; ... exports.reportstate = functions.database.ref('{deviceId}').onWrite(async (change, context) => { ... const requestBody = { ... payload: { devices: { states: { /* Report the current state of our washer */ [context.params.deviceId]: { on: snapshot.OnOff.on, /* 不要なのでコメントアウト */ //isPaused: snapshot.StartStop.isPaused, //isRunning: snapshot.StartStop.isRunning, }, ... }); ... exports.updateState = functions.https.onRequest((request, response) => { /* washer から switch に変更 */ firebaseRef.child('switch').update({ OnOff: { on: request.body.on, }, /* 不要なのでコメントアウト */ /* StartStop: { isPaused: request.body.isPaused, isRunning: request.body.isRunning, } */ }); return response.status(200).end(); });
下記コマンドを実行して、functionsディレクトリに移動し、デプロイします。
cd functions firebase deploy --only functions
ローカル実行の実装を修正する
「smarthome-local/app-start/local」の「index.ts」を以下のように変更します。
コメントアウトしたところは、説明上残しているだけで、除去してもらって構わないです。
「washer」から「switch」に変更し、状態がOnOffだけになったので、不要なものを除去しています。
identifyHandler(request: IntentFlow.IdentifyRequest): Promise<IntentFlow.IdentifyResponse> { ... const response: IntentFlow.IdentifyResponse = { intent: Intents.IDENTIFY, requestId: request.requestId, payload: { device: { id: 'switch', // washer から switch に変更 verificationId: localDeviceId.toString(), } } }; ... } ... getDataForCommand(command: string, params: IWasherParams): unknown { switch (command) { case 'action.devices.commands.OnOff': return { on: params.on ? true : false }; /* 不要なのでコメントアウト */ /* case 'action.devices.commands.StartStop': return { isRunning: params.start ? true : false }; case 'action.devices.commands.PauseUnpause': return { isPaused: params.pause ? true : false }; */ default: console.error('Unknown command', command); return {}; } }
下記コマンドを実行して、localディレクトリに移動し、コンパイルとデプロイをします。
cd local npm run build firebase deploy --only hosting
ピッコロボIoTの実装を修正する
「LocalHomeSDK_PiccoroboIoT」の「httpsrv.h」を以下のように変更します。
コメントアウトしたところは、説明上残しているだけで、除去してもらって構わないです。
状態がOnOffだけになったので、不要なものを除去しています。
... class Status { public: bool on; /* 不要なのでコメントアウト */ // bool isRunning; // bool isPaused; }; ... void LocalHomeServer::begin() { ... server->on("/", HTTP_POST, [](){ ... if(doc.containsKey("on")) { status.on = doc["on"]; } /* 不要なのでコメントアウト */ // if(doc.containsKey("isRunning")) { // status.isRunning = doc["isRunning"]; // } // if(doc.containsKey("isPaused")) { // status.isPaused = doc["isPaused"]; // } Serial.printf("on:%d\n", status.on); ... }); server->begin(); Serial.printf("Http Server at port %d\n", LOCAL_HOME_SERVER_PORT); status.on = false; /* 不要なのでコメントアウト */ // status.isRunning = false; // status.isPaused = false; } ... void LocalHomeServer::reportState() { StaticJsonDocument<200> doc; doc["on"] = status.on; /* 不要なのでコメントアウト */ // doc["isRunning"] = status.isRunning; // doc["isPaused"] = status.isPaused; ... }
「LocalHomeSDK_PiccoroboIoT」を以下のように変更します。
「SoundSensor_PiccoroboIoT」の「motion.h」をコピーしてきて、インクルードするようにします。
「motion.h」については、「Nest MiniでLocal Home SDKを使ってお家のIoTロボットを操作する 第1回」を参照ください。
スイッチONの状態で動作するようにモーションを設定し、スイッチOFFでは初期姿勢(正面を向いている状態)のモーションを一度だけ呼んで動作を停止させています。
... #include "motion.h" ... void setup() { ... // 各サーボを有効化 servoEnable(1, 1); servoEnable(2, 1); servoEnable(3, 1); servoEnable(4, 1); } void loop() { ... detectMotion(); selectMotion(); } void detectMotion() { int motionNum = M_NUM0; // スイッチONの状態で動作するモーションを設定する if(status.on){ motionNum = M_NUM1; } // モーション番号を設定する setMotionNumber(motionNum); } void selectMotion(){ // 設定していたモーション番号を取得し、その番号毎にモーションを実行する switch(getMotionNumber()){ case M_NUM0: // 初期姿勢(正面を向いている状態)のモーションを一度だけ実行する playMotionOnce(motion0, 1); break; case M_NUM1: // モーションを繰り返し実行する playMotion(motion3, 5); break; } }
Googleアシスタントへのリンクを変更する
Googleアシスタントへのリンクを変更する必要があります。
スマートフォンでGoogleアシスタントの設定を開きます。
設定の開き方や以降の手順についての詳細は、「Nest MiniでLocal Home SDKを使ってお家のIoTロボットを操作する 第2回」を参照ください。
Googleアシスタントの設定画面を開いたら、「アシスタント > スマートホーム」を選択し、「デバイス」を選択した状態で、右下にあるプラス(+)アイコンを選択します。
デバイスの追加画面で、「リンクされたサービス」の中に「[test]」から始まるものがあると思います。(以前追加したものです。)
これをタップします。
「アカウントをリンク解除」が表示されるので、それをタップします。
一度リンクを解除して、この後、「[test]」から始まるものを再度追加しなおします。
部屋の割り当てで、以前は洗濯機のアイコンだったのが、スイッチのアイコンに変わっていると思います。
タップして、部屋を割り当てたら、完了ボタンを押下してください。
音声コマンドで動かす
Google Homeデバイス(Nest Mini)の電源を入れなおしてください。
ピッコロボIoTは、サーボを動かすので、電池を接続しておく必要があります。
Google Homeデバイス(Nest Mini)へ下記のように話し、音声コマンドを介してコマンドをピッコロボIoTに送信します。
- スイッチを入れて
- スイッチを切って
ピッコロボIoTが「スイッチを入れて」で動きだし、「スイッチを切って」で停止しますね!
なお、今回のソースコードはGithubのvstoneofficial/LocalHomeSDK_PiccoroboIoT_Switchに上げています。
Local Home SDKを使ってIoTロボットを操作するシリーズは以上になります。
ピッコロボIoTのV-duinoを使うと、ピッコロボIoTのページの「V-duinoを組み込んだ作例を公開」にあるようなロボット(下図)も作れます。
これらはソースファイルだけでなく、CADデータも公開されています。
V-duinoでIoT家電を作って、それをNest Miniから操作する、ということも出来そうですね!
Local Home SDKを使えば、IoT家電側のサーバは不要なので(Firebaseは使いますが)、手軽なのも良いですね。
また何か作ったら、ブログに上げていこうと思います。