前回の「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は使いますが)、手軽なのも良いですね。
また何か作ったら、ブログに上げていこうと思います。
