エンジニアのはしがき

プログラミングの日々の知見を書き連ねているブログです

Siriに喋りかけるだけで家電操作できる環境をつくる

以前の記事でWebアプリを赤外線リモコン化したのですが、使い続けているうちに不満も出てきました。 tm-progapp.hatenablog.com

Webアプリで家電を操作するには最低でもスマホを取り出して、アプリを開かなければいけません。 例えば、買い物をして両手が塞がった状態では、スマホを取り出してWebアプリを操作するのに手間がかかります。 f:id:tansantktk:20201115101721p:plain 日常のちょっとした動作なんですが面倒です。 なんとかしましょう。

今回やりたいこと

  • Siriに「Hey Siri! 〇〇オン!」と喋りかけたら、家電の電源がONになるようにします。

システム構成図

f:id:tansantktk:20201115103337p:plain 今回はSiri、Homeアプリ、ラズパイのHomeBridgeサーバの3つを連携させることで、Siriに話しかけるだけでラズパイを操作して、最終的に赤外線を家電に発信させています。

Siriに対して、Homeアプリに登録したアクセサリの名称を話しかけると、アクセサリの状態を変更することができます。(例:「Hey, Siri. "テレビ"をONにして。」)
ラズパイ側のHomeBridgeサーバでは、アクセサリの状態が変更されたことを検知して、特定のコマンドを実行することが可能です。
今回は、jsファイルを実行してRealtimeDatabaseの家電の値を更新させます。 RealtimeDatabaseを常時監視するNode.jsサーバは、更新を検知したらPythonコードを実行し、GPIOから電気信号が出力され、赤外線LEDから赤外線が発信されます。

RealtimeDatabaseとそれを常時監視するNode.jsサーバについては、単純に赤外線を発信したいだけなら不要です。 HomeBridgeで家電の状態の変更検知をしたら、そのままPythonコードを実行する処理フローでも構いません。
私の場合、以前作ったWebアプリとSiriの両方から家電操作をしたかったので、このような構成となっています。

前提条件

$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 9.9 (stretch)
Release:    9.9
Codename:   stretch

ラズパイにHomeBridgeをインストールする

まずはHomeBridgeの利用に必要なライブラリをインストール

$ sudo apt install libavahi-compat-libdnssd-dev

HomeBridgeをnpmインストール。

$ sudo npm install -g homebridge

HomeBridgeの設定

まずは、家電をON/OFFにした際に実行されるjsファイルupdate-params.jsを作成しておきます。 以下のソースでは、コマンドライン引数で指定されたRealtimeDatabaseのキーと値を参照して更新処理をしています。

// update-params.js
const firebase = require("firebase");
const exec = require("child_process").exec;
const nodeEnv = require('./nodeEnv.js'); # Firebaseの認証情報を外部ファイルからロード

console.log(nodeEnv);

// firebase init
const firebaseConfig = {
  apiKey: nodeEnv.apiKey,
  authDomain: nodeEnv.authDomain,
  databaseURL: nodeEnv.databaseURL,
  projectId: nodeEnv.projectId,
  storageBucket: nodeEnv.storageBucket,
  messagingSenderId: nodeEnv.messagingSenderId,
};
firebase.initializeApp(firebaseConfig);

if (!process.argv || process.argv.length === 0 || !process.argv[2] || !process.argv[3]) {
    console.log('no command line args...');
    return;
}

// DBをUPDATE
console.log(`update => {${[process.argv[2]]}: ${process.argv[3]}}`);
const dbKeyName = firebase.database().ref().child(process.argv[2]);
firebase.database().ref().update({
    [process.argv[2]]: process.argv[3]
});

setTimeout(() => {
    process.exit();    
}, 3000);

操作したい家電の情報を設定します。

$ sudo vim /home/pi/.homebridge/config.json
{
    "bridge": {
        "name": "Homebridge",
        "username": "**:**:**:**:**:**", #ラズパイのMACアドレス
        "port": 51826,
        "pin": "***-**-***"  #Homeアプリとの連携に必要なPIN
    },
    "description": "this is a connection setting for iOS Siri with HomeBridge. / [Note]username: your MAX address. you need to input uppercase alphabet",
    "accessories": [
        {
            "accessory": "CMD",
            "name": "エアコン",
            "on_cmd": "node /home/pi/webcon-node/update-params.js airconPower cool",
            "off_cmd": "node /home/pi/webcon-node/update-params.js airconPower off"
        },
        {
            "accessory": "CMD",
            "name": "電気",
            "on_cmd": "node /home/pi/air-controller2/update-params.js bedroomLight on & node /home/pi/webcon-node/update-params.js diningLight on",
            "off_cmd": "node /home/pi/air-controller2/update-params.js bedroomLight off & node /home/pi/webcon-node/update-params.js diningLight off"
        },
        {
            "accessory": "CMD",
            "name": "テレビ",
            "on_cmd": "node /home/pi/webcon-node/update-params.js tv on",
            "off_cmd": "node /home/pi/webcon-node/update-params.js tv off"
        }
    ]
}

accessoriesに操作対象となる下記の家電の情報を配列で追記していきます。 上記のソースでは、家電がON/OFFになると、update-params.jsが実行されるように設定しています。

accessory: "CMD"を指定

name: Siriに話しかける時の家電の名称を指定

on_cmd: 家電をONにしたときにラズパイで実行する処理

off_cmd: 家電をOFFにしたときにラズパイで実行する処理

HomeBridgeの準備は整ったので、Siriからのリクエストを受信するためのサーバを起動しましょう。

$ homebridge

CUIQRコードとハイフン区切りの8桁のコードが表示されますが、後で使うので消さずにそのままにしておいてください。 以上でラズパイ側の準備は完了です。

iPhoneのHomeアプリとHomeBridgeを連携させる

iPhoneのHomeアプリを開きます。無ければAppStoreからDLしてきましょう。 f:id:tansantktk:20201115110715p:plain

アクセサリを追加をタップ。
f:id:tansantktk:20201115110747p:plain:w300

カメラが起動するので、ラズパイのCUIに表示されているQRコードを読み取ります。 f:id:tansantktk:20201115110811p:plain:w300

HomeBridgeで設定した家電が表示されたら、Homeアプリの設定は終わりです。 f:id:tansantktk:20201115111039p:plain:w300

Siriに話しかけてみる

それでは、Siriに話しかけてみましょう。

例えば、Homeアプリに「テレビ」というアクセサリを追加したなら、
「Hey, Siri. テレビをONにして」
「Hey, Siri. テレビをOFFにして」
と話しかけてみましょう。

うまくHomeBridgeと連携ができていれば、ラズパイのCUIに以下のようなログが出力され、家電が動くはずです。

[2020-11-15 11:14:00] [テレビ] Setting power state to on
[2020-11-15 11:14:04] [テレビ] power function succeeded!

課題

  • Siriに話しかけてから赤外線発信までは割とタイムラグがあります。Siriはそれなりに正確に聞き取ってはくれますがレスポンスは遅め。
    • Siriがうまく聞き取ってくれた場合でも10秒前後かかる。
  • Siriに話しかけるのに慣れるまではなんだか恥ずかしい。
    • これは慣れですが、最初は機械に対して何度も独り言を喋るというのに抵抗を感じました。外出時はちょっとムリかな…。
  • 実装後に分かったのですが、Siriが動作する端末がラズパイと同じネットワークに接続されている必要があるようです。4G通信の状態でSiriからHomeBridgeには通信できませんでした。

余談

  • HomeアプリとHomeBridgeを連携した状態なら、シンプルにHomeアプリ上から登録した家電のON/OFFができます。UI的に問題無いなら操作用のWebアプリは無くてもいいかも…。
    • ただしHomeアプリの家電の状態はHomeアプリ内で保持されている値なので、使い方によってはRealtimeDatabaseや実際の家電の状態とズレる場合があります。
  • AppleWatchでもHomeアプリが使えるので、腕時計型リモコンとして運用もできそうです。

参考

Install Homebridge on Raspbian · homebridge/homebridge Wiki · GitHub