Smart HomeをDIYする

Apple HomeKit は対応製品が少なくて高価なのでHomebridgeでがんばります

ESP32で赤外線リモコンを作ってHomeKitから使う

ESP32に赤外線LEDを取り付けて、スマート赤外線リモコンとして動作させます。今回は、シーリング照明をon/offする赤外線パターンを用意して、赤外線LEDを点滅させる簡単な構成です。さらに、MQTT経由でメッセージが来た時に発光するようにし、Homebridge/HomeKitに接続しました。これでiPhone/Macのホーム画面に照明として表示され、操作可能です。

Nature RemoのローカルAPI

Nature Remoの回で、Nature RemoのローカルAPIを使う方法を紹介しました。

diysmarthome.hatenablog.com

この方法を使えば、Nature Remo

から、任意の赤外線パターンを送出させることができます。例えば、以下のターミナルコマンドを打つと、ここの部屋の赤外線リモコン対応のシーリングライトがon/offします。

curl -XPOST "http://192.168.xxx.xxx/messages" -H "X-Requested-With: local" -d '{"format":"us","freq":40,"data":[7000,4760,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,560,280,1400,280,1400,280,1400,280,1400,280]}'

IPアドレス部分はNature Remoのアドレスです。Nature Remoがhttpサーバになっていて、そこに赤外線明滅パターンをjson形式で送れば、それを送出してくれる仕掛けです。dataというキーで指定した整数型配列の部分が明滅パターンです。単位はマイクロ秒で、この例ですと、

  1. 7000μs発光する
  2. 4760μs消灯する(この長いペアが開始の印です)
  3. 280μs発光する
  4. 560μs消灯する(このペアがビット0です)
  5. 280μs発光する
  6. 1400μs消灯する(このペアがビット1です)
  7. (省略)
  8. 280μs発光する
  9. 1400μs消灯する(最後のビットです。1です)
  10. 280μs発光する(これに続く長い消灯により終了を示します)

という手順を示してます。消灯時間を確定するために、発光期間で始まり、発光期間で終了します。なので、配列の要素数は必ず奇数個です。

この明滅パターンさえ用意できれば、任意の赤外線リモコン信号をNature Remoから送出できます。Natureのクラウドを利用しないので、クラウドサービスに障害があっても、サービスが中断されても大丈夫です。でも、赤外線パターンを送出するだけの簡単な機能なら、高価なNature Remoを買う必要もない気がします。DIYしましょう!

赤外線パターンの解析

Nature Remoの記事にも簡単に書きましたが、今回は図入りで説明します。対象としたシーリング照明は、Amazaonでかなり昔に購入した格安製品です(今は売られてません)。リモコンには6個のボタンがついています。上で紹介した点滅パターンは、リモコンの「切/入」ボタンを押した時のパターンです。Nature Remoの学習機能を使って、web apiで取得した結果を、280μsの整数倍に整形した数列です。時系列でグラフにすると以下のようになってます。

1が点灯、0が消灯です。最初に長めのon/offがあって、その後280μsのパルスが17個出ます。パルスの間隔は、パルス幅の2倍のものと、パルス幅の5倍のものがあります。間隔が狭い方を0、広い方を1だと考えると、図のように0101010101001111と読めます。ちょうど16ビットあります。各バイトのMSBから順番に送信されていると仮定すると、16進数で0x554Fです。

いろいろ試したところ、最初の1バイトはリモコンのチャンネルを切り替えると変化し、CH2が0x55, CH1が0xAAでした。次の1バイト(ここでは0x4F)が命令のようです。

リモコンにはこのほかに、常夜灯(暗い点灯)、明るく、暗くのボタンがあります。4個のボタンの命令バイトは、

  • 0x4F: 「切/入」
  • 0xDF:「常夜灯」
  • 0x67:「明るく」
  • 0xCD:「暗く」

でした。「切/入」はトグルなので、状態を把握できないので使いにくいです。リモコン電源ボタンがトグル式でも、隠しコマンドで、on/off専用コマンドが存在することもあるらしいです。このリモコンは、チャンネル指定が1バイト、コマンドが1バイトなので、256通りの命令が可能です。すべての命令をプログラムで試してみたのですが、onだけ、offだけのコマンドは残念ながら見つかりませんでした。

赤外線リモコンサーバを設計する

LAN経由でコマンドを受け取って、赤外線パターンを送出するサーバのようなものを作ります。今回の構成は以下です。

マイコンにはESP32を使います。WiFiがあって無線サーバに仕上げやすいですし、安価です。さらには赤外線リモコンのための回路も備わっているらしいです。Nature Remo(他の会社のスマートリモコンもそうですが)などがWeb API使っているのに対して、これから作るサーバはMQTTを使うことにします。オーバーヘッドが少ないし、HomebridgeのMqttthingプラグインからも利用できて便利です。MQTTブローカには、いつものようにRaspberry Piで動かしているMosquittoを使います。同じRaspberry PiでHomebridgeも動いてます。

ESP32には、「MQTTの特定のトピックにメッセージがやってきたら、プログラムで用意した赤外線パターンを送出する」という機能を実現したいと思います。

部品を集める

秋月電子のページを見ながらLEDとFETを選びました。

  • 赤外線LED:赤外線リモコンで使われる波長は950nmらしいので、近い波長にしました。945nmです。標準電流は50mAです。
  • MOS FET:一番普通そうなMOS FET。ドレイン電流は200mA流せるようです。赤外線LEDを十分点灯させられます。

ESP32が送料込み700円くらいに加えて、LED 10円、FET 20円、抵抗など部品代がかかっても1000円程度で作れます。

Arduino IDEにIRライブラリを入れる

Arduino IDEに赤外線リモコン用のライブラリを入れました。ライブラリマネージャで、irremoteという単語で検索したところ、IRRemoteESP8266というのが見つかりました。ESP8266という名前ですが、ESP32でも動くようです。これをインストールしました。

ライブラリをインストールすると、Arduino IDEのスケッチ例にIRremoteESP8266というメニュー項目が増えていました。これを参考に、簡単なプログラムを作ります。このライブラリは、いろいろなメーカーの赤外線パターンに対応しているようです。Panasonic, Daikin, Mitsubishiなどほとんどの製品が揃ってます。今後はそのような高度な機能も活用したいですが、今回は、一番簡単な、生の赤外線パターンを出すプログラムを作りました。

最初に、部屋のシーリング照明をon/offするパターンを5秒ごとに送出するプログラムを作りました。以下のようにとても簡単に作れます。

/*IRremoteESP8266:demonstrates sending IR codes with IRsend.*/
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>

const uint16_t kIrLed = 4;  //GPIO pin. Recommended: 4 (D2).
IRsend irsend=IRsend(kIrLed);  // Set the GPIO to be used.

uint16_t rawData[35] = {  7000,4760,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,560,280,1400,280,1400,280,1400,280,1400,280
};

void setup() {
  irsend.begin();
  Serial.begin(115200);
}

void loop() {
  Serial.println("Sending a rawData.");
  irsend.sendRaw(rawData, 35, 38);  //Send a raw data at 38kHz.
  delay(5000);
}

回路を組む

赤外線LEDをドライブする回路を作っておきます。GPIOの出力そのままでは光量が少ないので、FETを介して赤外線LEDを点灯させます。以下の回路にしました。

MOS FETの2N7000は、onになるゲート電圧が標準2.1V, max 3Vらしいです。ESP32の3.3V出力でもonにできるように、高めに分圧してあります。onの時のゲート電圧は、ほぼ3.3Vのままになると思います。GPIO直結じゃなくて分圧したのは、過渡状態が良くなるらしいからです。セキュリティシステムでブザーを動かした時と同じ構成です。

LEDは、明るく点灯するように5V供給にしました。LEDの順方向電圧降下を測定したところ1.2Vでした。FETのonの時の順方向電圧は0.14Vくらいらしいので無視できます。保護抵抗を100Ωにしたので、FETがonの時には、40mA弱流れると思います。( 正確には(5-1.2-0.14) / 100 = 37mA と見積もってましたが、実測したらもう少し少なかったです)

ブレッドボードの配置図は以下です。

実際に配線した様子が以下です。この写真を撮った時は、デバッグのために可視光青色LEDを取り付けてます。

点灯消灯プログラムのテスト

回路が完成したので、上記で紹介したプログラムを走らせます。プログラムの内容は簡単です。sendRawという関数で、赤外線パターンを送出させてます。引数は信号パターンの配列、配列要素数、赤外線変調周波数(kHz)です。これを5秒ごとに繰り返してます。可視光LEDを付けると、5秒ごとに一瞬光っているのがわかります。光っている前後2秒を切り出したGIFアニメです。

赤外線LEDに変えると、部屋の照明が5秒ごとに消灯・点灯しました。とてもウザいのですが、動いて嬉しいです。

前述のように、この照明のリモコンには、on/offトグルスイッチしかありません。なのでこの信号パターンを送るたびに、点灯、または消灯します。トグル動作は、現在の状態が不明なので、家電制御としては使いにくいです。

MQTTから操作する

MQTTのメッセージで、赤外線信号を出すようにプログラムしました。ewpmqttclientを使います。詳しくはこちらをご覧ください。

diysmarthome.hatenablog.com

今回は、irremote/ceilinglightというトピックに、何らかのメッセージが来たら、シーリング照明をトグルするパターンを出すというプログラムです。極力簡単にしました。クライアントIDも適当にランダムな文字列にしておきました。

setup()でMQTTクライアントの初期化をします。初期化が完了すると、onConnectionEstablished()という関数が呼ばれるので、その中でコールバック関数(特定のトピックを受信したら呼び出される関数)を指定します。ここでは、onMessageReceived()という名前にしました。この関数の中で赤外線を送出します。main()は、MQTTクライアントの処理を行うだけの仕事をしてます。

/* IRremoteESP8266 over MQTT */
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <espmqttclient.h>

EspMQTTClient *client;

//WiFi
const char SSID[] = "XXXXXXXX"; //WiFi SSID
const char PASS[] = "xxxxxxxx"; //WiFi password
//MQTT
char CLIENTID[] = "IRremote_3835782"; //something random
const char  MQTTADD[] = "192.168.xxx.xxx"; //Broker IP address
const short MQTTPORT = 1883; //Broker port
const char  MQTTUSER[] = "xxxx";//Can be omitted if not needed
const char  MQTTPASS[] = "XXXX";//Can be omitted if not needed
const char  SUBTOPIC[] = "irremote/ceilinglight";

const uint16_t kIrLed = 4;  //GPIO pin. Recommended: 4 (D2).
IRsend irsend=IRsend(kIrLed);  // Set the GPIO to be used.

// IR-data to toggle a ceiling light
uint16_t rawData[35] = {
7000,4760,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,560,280,1400,280,1400,280,1400,280,1400,280
};

void setup() {
  irsend.begin();
  Serial.begin(115200);
  while (!Serial);      //  wait for serial port to connect.
  client = new EspMQTTClient(SSID,PASS,MQTTADD,MQTTUSER,MQTTPASS,CLIENTID,MQTTPORT); 
}

void onMessageReceived(const String& msg) {
  Serial.println("a rawData capture from Nature Remo");
  irsend.sendRaw(rawData, 35, 38);  // Send a data at 38kHz.
}

void onConnectionEstablished() {
  Serial.println("MQTT connection established.");
  client->subscribe(SUBTOPIC, onMessageReceived); //set callback
}

void loop() {
  client->loop();  
  delay(100);
}

どんなメッセージを受け取っても動作します。NULLでも良いです。例えば、ターミナルから、mosquitto_pubコマンドを使ってこのトピックに空白文字を送ってみます。

% mosquitto_pub -h 192.168.xxx.xxx -u xxxx -P XXXX-t irremote/ceilinglight -m ''

その結果、シーリング照明が消灯または点灯しました。これで、MQTTメッセージを使って赤外線パターンを送出できるようになりました。

Homebridgeで設定する

MQTTで動作するプログラムができたので、Homebridgeで設定して、HomeKitから使えるようにします。Homebridgeは、MQTTブローカと同じRaspberry Piの上で動いてます。

 

 

このHomebridgeにインストールされているMqttthingプラグインを使い、その設定をします。Mqttthingプラグインの設定画面から、スイッチアクセサリを一つ作って、ここで使ったirremote/ceilinglightトピックを指定します。Homebridgeのwebインタフェースで、以下のように設定します。

 

設定をテキストで確認すると以下のようになってます。HomebridgeとMQTTブローカが同じRaspberry Piで動いているので、アドレスはlocalhostです。デフォルトなので、設定では省略されてます。

{
    "type": "lightbulb-OnOff",
    "name": "Ceiling Light",
    "username": "xxxx",
    "password": "XXXX",
    "topics": {
        "setOn": "irremote/ceilinglight"
    },
    "accessory": "mqttthing"
}

この設定で、iPhone/Macでon/offする操作を行うと、setOnで指定したトピックにtrue/falseという文字列を送ります。今回はtrueかfalseに関係なく、どちらの場合も設定した同じ赤外線パターンを送出します。

HomeKitから操作する

Homebridgeを再起動すると、iPhoneMacのホーム.appに、今回設定した照明が現れました。Ceiling Lightという名前の照明です。

これをクリックすると、ESP32が赤外線パターンを送出します。天井の照明が、消灯または点灯します。画面の表示とシーリング照明のon/off状態は、どちらも操作するたびにトグルしているだけなので、不一致になる可能性もあります。

なので実際のシーリング照明のon/offには、隣の「あかり」と書かれたボタンを使ってます。こちらは、壁に取り付けたZigbeeスイッチをコントロールします。

まとめ

ESP32に赤外線LEDをつけて、MQTTメッセージで動作するスマートリモコンを作りました。今回はシーリングライトの電源トグル信号を送るだけの簡単な機能です。使用したライブラリIRremoteESP8266には、生の赤外線明滅パターンを送るだけではなく、各社家電製品のフォーマットに対応した機能もあります。これを使えば、エアコンなどの複雑な制御も実現できると考えてます。

温度湿度センサDHT20をRaspberry Piに接続してHomeKitから使う

秋月電子で売られている温度湿度センサDHT20(380円) Raspberry Pi 4に取り付けました。これから温度・湿度を取り込み、MQTTに流すPythonプログラムを書きました。それをHomebridgeで受け取ってHomeKitから使えるようにしました。以下の構成です。これで左端のセンサからのデータが、右端のiPhone/Macに表示されます。温度・湿度の値に応じたオートメーションも設定できます。

 

 

温度湿度センサDHT20

これから乾燥する時期を迎えて、湿度によって加湿器をコントロールするなどやってみたくなりました。そうなるとちゃんとした湿度センサが欲しくなります。I2C接続の温度・湿度センサならRaspberry PiArduinoと簡単に接続できると聞いていたので、秋月電子のセンサを買いました。I2Cを使うのは初めてのことでしたが、線を4本接続するだけで簡単に使えました。

ASAIRというブランドのセンサで、3.3Vでも5Vでも稼働し、キャリブレーションされた温度と湿度が、I2Cインタフェースでデジタルに得られます。精度は温度が+/- 0.5度、湿度が+/- 3%だそうです。申し分ない性能で、しかも安いです。下の写真はセンサの裏側です。

I2C接続

I2Cは2本の信号線を、複数のセンサやコンピュータが共有し、データをシリアルに交換する規格です。信号線の1本がデータ線で、もう一本は同期タイミングのための線です。接続されたそれぞれのデバイスは固有のアドレスをもち、アドレスとデータの組み合わせを送受信します。

Raspberry PiArduinoには、I2C接続のためのファームウェアが組み込まれていますし、開発環境にはI2Cのライブラリが用意されているので、あまり苦労することなくインタフェースが作れます。

DHT20をRaspberry Piに接続する

秋月電子の商品ページからDHT20のデータシートがダウンロードできます。

https://akizukidenshi.com/download/ds/aosong/DHT20.pdf

これによると4本のピンは、左から、電源、SDA, GND, SCLです。SDAとSCLがI2Cの信号線です。

電圧レベルは3.3Vと5Vに対応しているようです。Raspberry PiのGPIOは3.3Vなので、3.3Vを供給して使います。また、Raspberry PiのGPIOピンの3番と4番がI2CのSDAとSCLピンです。これらのピンは、GPIO2とGPIO3として普通のデジタル入出力にも使えます。I2Cで使う場合には、I2C通信を実現する際に必要なクロック回路やバッファに接続されるのだと思います。なので、DHT20の1番をRaspberry Piの1番に、2番を3番に、3番を9番に、4番を5番に接続しました。

こんな感じです。

こういう接続には、フラットケーブルになったジャンパ線が便利です。割いて使えるので、必要な本数をまとめて配線できます。たくさん入っていて安いです。

メスーメスのジャンパ線を使ったところ、センサの足にも、GPIOにもささりました。半田付けすることなく、センサとコンピュータを接続できました。Raspberry Piのケースからジャンパ線を引き出して、センサをケースの側面に両面テープで貼り付けました。

ちなみに使用しているケースはこれです。蓋が開けやすくて便利です。

Raspberry PiのI2Cを有効にする

まずはRaspberry PiのI2Cピンを有効にするよう設定します。$ sudo raspi-configとタイプして、設定画面を出します。

ここで、Interface Optionsを選んで、

I2CをEnableします。この後Raspberry Piを一応再起動しましたが、しなくても良かったかもしれません。

I2C関係のコマンドがインストールされていると便利なようです。i2cdetectというコマンドで、接続されたデバイスが確認できるらしいのですが、コマンドがありませんでした。aptでインストールします。長らくupdateしていなかったので、一応アップデートしました。

$ sudo apt update
$ sudo apt upgrade

この後、i2c-toolsというのをインストールします。

$ sudo apt install i2c-tools 

これで、i2c関係のコマンドが使えるようになります。例えば、以下のようにすると、

$ i2cdetect -y  1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- 38 -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --  

接続されているI2Cデバイスを検出し、そのアドレスを表示してくれます。この結果によると0x38番のアドレスを持ったデバイスが接続されていることがわかりました。前出のDHT20のデータシートによると、このセンサは0x38番のアドレスを使っています。正しく接続されているようでした。

DHT20用プラグインを探す(該当なし)

有名なI2Cセンサなので、Homebridgeのプラグインで読めるかもしれないと、最初は思っていました。HomebridgeのwebインタフェースのプラグインのページでDHTで検索すると13個ほどのプラグインが見つかりました。説明によると、Raspberry PiにI2C接続したDHTセンサを動かすプラグインもありました。 

ただ、DHT20を対象としたものは無く、DHT11 / DHT12 / DHT21 / DHT22 / DHT33 / DHT44などが対象でした。DHT20は、前述のデータシートによるとDHT11の改良版らしいです。なので別の型番で動くかなと思ったのですが、どれもエラーが出たり、おかしな値が表示されたりします。

データフォーマットが異なっているのかもしれません。またDHTセンサというのはditigal humidity and temperatureセンサの略だそうです。一般的な名前なので、同じ名前を使った他社のセンサがあるのかもしれません。

ということで、専用プラグインでお手軽に設定するのは諦めて、Pythonプログラム、MQTT、Mqttthingプラグインの組み合わせで進めることにしました。

追記:DHT11とDHT21をネット上で見つけたのですが、なんとI2C方式じゃないのですね。シリアルでデータが出てくるだけのようでした。GNDピンの位置も違います。どうりで使えなかったはずです。秋月にはDHT11も売っているようです(DHT20よりも高い)。そのうち試したいと思います。

Pythonでセンサ値を読む

こちらを参考にさせていただき、Pythonでセンサ値を読むプログラムを作りました。

s-design-tokyo.com

DHT20のデータシートには、I2Cでセンサ値を読む手順が説明されています。それによると、

  1. 電源投入後100ms待つ
  2. 0x71を送ってstatus wordを得る
  3. status wordと0x18のANDが0x18だったら次に進む。そうでない場合は、レジスタを初期化する必要がある
  4. 10ms待つ
  5. 測定をトリガするコマンド0xAC, 0x33, 0x00を送る
  6. 80ms待つ
  7. 7バイトのデータを読む。1バイト目のMSBが1だったらまだ測定できていないので、もう少し待つ。0だったら次に進む
  8. 2,3,4,5,6バイトに、湿度・温度の情報が12ビットずつ入っているので分離する
  9. 7バイト目にはCRCが入っているので必要ならば確認する
  10. 湿度、温度の情報は、正規化された仮数のような表現になっているので、換算して浮動小数点10進数に変換する
  11. 必要に応じて5以下を繰り返す。測定の間隔は2秒以上にする

という手順のようです。これをPythonでプログラムします。ただし、I2C用のライブラリが足りませんでした。

pip3 install smbus

でインストールします。プログラムは、以下のようになりました。30秒間隔で測定します。

#!/usr/bin/python3
import smbus
import time

i2c = smbus.SMBus(1)
ADDRESS = 0x38

#setup for DHT20
statusword = i2c.read_byte_data(ADDRESS, 0x71)
if statusword & 0x18 != 0x18:
    print("Registers should be initialized.")
    sys.exit()
time.sleep(0.01) #10ms sleep after setup

while True:
    #trigger measurement
    i2c.write_i2c_block_data(ADDRESS,0,[0xAC,0x33,0x00])
    while True:
        #wait the measurement to be completed
        time.sleep(0.08)
        data = i2c.read_i2c_block_data(ADDRESS, 0x00, 0x07)
        if data[0] & 0x80 ==0:
            break;
    #Concatenation
    humi = data[1] << 12 | data[2] << 4 | data[3] >> 4
    temp = ((data[3] & 0x0F) << 16) | data[4] << 8 | data[5]
    #Conversion
    humidity = round(humi / 2**20 * 100)
    temperature = round((temp / 2**20 * 200 - 50),1)
    #Print results
    results='{"temperature":'+str(temperature)+\
           ',"humidity":'+str(humidity)+'}'
    print(results)
    time.sleep(30)

 これを動かすと、以下のように、30秒間隔で温度・湿度が表示されました。温度は四捨五入して小数点以下第1位で、湿度は整数で表示しています。

$ ./dhtread.py 
{"temperature":23.7,"humidity":64}
{"temperature":23.7,"humidity":63}
{"temperature":23.7,"humidity":63}

print文はjson風にしてみました。

センサ値をMQTTにパブリッシュする

この結果を、MQTTブローカーパブリッシュします。MQTTに関しては以下の記事をご覧ください。

diysmarthome.hatenablog.com

MQTTブローカーを、同じRaspberry Piで動かしているので、IPアドレスlocalhostです。トピックは、後でHomebridgeのmqttthingプラグインを使うので、mqttthing/dht20/getにしました。ここにjson形式で測定結果を流します。またデバッグ用のメッセージをmqttthing/dht20/debugに流すことにしました。MQTTライブラリにはmahoを使います。

長くなったのでメインプログラムをmain()にしました。初期化、データ読み込み、メインを分けて分かりやすくしました。MQTTのために追加した部分は太字にしてあります。

#!/usr/bin/python3
import smbus
import time
from paho.mqtt import client as mqtt_client

## for I2C ##
i2c = smbus.SMBus(1)
ADDRESS = 0x38
## MQTT ##
address='localhost'
port=1883
debug_topic='mqttthing/dht20/debug'
pub_topic='mqttthing/dht20/get'
client_id=b'dht20_02648259' #something random
username='xxxxxxxx'
password='XXXXXXXX'

def setup():
  ## setup for MQTT ##
  client=mqtt_client.Client(client_id)
  client.username_pw_set(username,password)
  client.connect(address,port)
  time.sleep(2) #wait for MQTT connection
  ## setup for DHT20 ##
  statusword = i2c.read_byte_data(ADDRESS, 0x71)
  if statusword & 0x18 != 0x18:
    print("The 0x1B, 0x1C, 0x1E registers should be initialized.")
    client.publish(debug_topic,"Initialization required.")
    sys.exit()
  time.sleep(0.01) #10ms sleep after setup
  client.publish(debug_topic,"DHT20 is ready.")
return client def readData(): #trigger measurement i2c.write_i2c_block_data(ADDRESS,0,[0xAC,0x33,0x00]) #read data while True: #wait the measurement to be completed time.sleep(0.08) data = i2c.read_i2c_block_data(ADDRESS, 0x00, 0x07) if data[0] & 0x80 ==0: break; #Concatenation humi = data[1] << 12 | data[2] << 4 | data[3] >> 4 temp = ((data[3] & 0x0F) << 16) | data[4] << 8 | data[5] #Conversion humidity = round(humi / 2**20 * 100) temperature = round((temp / 2**20 * 200 - 50),1) results='{"temperature":'+str(temperature)+\ ',"humidity":'+str(humidity)+'}' return results def main(): client=setup() while 1: results=readData() print(results) client.publish(pub_topic,results) client.loop() time.sleep(180) if __name__ == "__main__":

更新頻度を3分にしました。別のターミナルウィンドウでmosquitto_subコマンドを動かし、サブスクライブしておきます。結果は以下のようになりました。

mqttthing/dht20/debug DHT20 is ready.
mqttthing/dht20/get {"temperature":22.8,"humidity":59}
mqttthing/dht20/get {"temperature":22.8,"humidity":59}
mqttthing/dht20/get {"temperature":22.9,"humidity":59}

プログラムを自動起動する

センサから値を読んでMQTTに流すこのプログラムは、Raspberry Piが起動したらいつでも動いていて欲しいです。なので、systemctlを使って自動起動させます。systemctlに関しては、いろいろなサイトに分かりやすい説明がありますので、ここはメモ程度に書いておきます。

まずは設定ファイルを作ります。/etc/systemd/systemに、dht20.serviceという名前のファイルを作り、内容を以下にしました。ホームディレクトリがpiの場合です。そこに、servicesというディレクトリを作り、その中に上記で作成したファイルをdht20.pyという名前で置いておくという設定です。

[Unit]
Description=dht20
After=network.target

[Service]
Type=simple
WorkingDirectory=/home/pi/services
ExecStart=/home/pi/services/dht20.py
TimeoutStopSec=5
StandardOutput=null
Restart=always

[Install]
WantedBy = multi-user.target

この後、

$ sudo systemctl daemon-reload  #設定ファイル有効化
$ sudo systemctl start dht20.service  #スタートさせる
$ sudo systemctl status dht20.service  #動作を確認
$ sudo systemctl stop dht20.service  #ストップする
$ sudo systemctl enable dht20.service  #電源を入れた時に動くように設定する

などのコマンドで動作させたり、次回のリブートで自動起動させたりできます。

Homebridgeで受け取る

HomebridgeにはMqttthingプラグインを入れてあります。MQTTメッセージで動くアクセサリを実装できます。今回もこれを使います。

diysmarthome.hatenablog.com

github.com

Mqttthinの設定から、tenmeratureSensorとhumiditySensorを使いました。MQTTの設定は、プラグインの設定画面からGUIで入力できます。最終的に出来上がったconfigの部分は以下になりました。

{
    "type": "temperatureSensor",
    "name": "DHT20_temp",
    "username": "xxxxxxxx",
    "password": "XXXXXXXX",
    "topics": {
        "getCurrentTemperature": "mqttthing/dht20/get$.temperature"
    },
    "accessory": "mqttthing"
},
{
    "type": "humiditySensor",
    "name": "DHT20_humi",
    "username": "xxxxxxxx",
    "password": "XXXXXXXX",
    "topics": {
        "getCurrentRelativeHumidity": "mqttthing/dht20/get$.humidity"
    },
    "accessory": "mqttthing"
}

Mqttthingは、json形式のデータも扱えます。上の設定で、

mqttthing/dht20/get$.temperature

としたことで、mqttthing/dht20/getトピックに流れてくるjson形式のデータ:

{"temperature":23.0,"humidity":56}

のtemperatureキーの部分(23.0という値)を取得できます。humidityも同様です。

HomeKitから使ってみる

この結果、iPhoneMacのホーム.appの上に、

というような表示が現れ、これをクリックすると、

のように、今回取り付けたセンサーの値が表示されました。これをもとにオートメーションも作れます。室温が下がったらエアコンを動作させるとか、湿度が下がったら加湿器をonにするなどの自動化が可能です。例えば、上のDHT20_humiの表示をクリックして、「オートメーションを追加」のメニューを選択すると、数クリックの操作で、下のようなオートメーションが完成します。

まとめ

秋月で380円で買えるI2C温度・湿度センサをRaspberry Piに接続して、iPhoneMacのホーム.appから利用できるように設定しました。Raspberry PiでHomebridgeを動かしているなら、4本の線を配線するだけで温度・湿度センサが作れます。結果をMQTTのメッセージで流すようにしたので、他のプログラムやスマートホームシステムからも利用できると思います。

Homebridge/HomeKitで使えるRingのドアベル

ちょっと前にRing Video Doorbell 4を買ってHomeKitに接続しました。Ringのアプリを使ってのビデオドアベルとして、そこそこ使えます。Homebridgeのプラグインがあり、それを使うとHomeKitからも一応使えます。「そこそこ」とか「一応」とかの歯切れの悪い状態だったのでボツネタにしてたのですが、ブラックフライデーセールでなんと半額になってました。この金額なら試しに使ってみる価値があると思います。(追記:半額セールが終了して元の価格に戻ってました。)

Ringのドアベル

日本では全然流行っていないWiFi接続のビデオインターフォンです。パナソニックアイホンの製品は一般的ですが、これらは専用子機を使って家の中で使うことを主に想定してます。スマホからアクセスできる機種もなくはないですが、割高です。Google, Amaozn, Appleのエコシステムと連携できる機種に至っては皆無です。

海外では、中国メーカの格安製品(多くはGoogle, Alexa対応を謳ってます)から、Apple HomeKitにも対応する高級品まで、色々と選択肢があります。Ring Doorbellは、メーカーとしてはHomeKit非対応ですが、オープンソースの完成度の高いHomebridgeプラグインがあり、Homebridgeユーザの中では人気の機種でした。少し前から、日本のAmazonでも取り扱われるようになっていたので、その時に購入してHomeKitから使ってみました。

通常価格は高めですが、冒頭で紹介したようにセールで半額になってます。

通常のセットアップする

まずは製品マニュアルに従って、通常のセットアップをします。玄関に取り付けて、Ringのスマホアプリをダウンロードして、ユーザ登録して、WiFiを設定します。これで普通に使用開始できました。ボタンを押すと、アプリに通知が来て、スマホ画面で来客者とビデオ会話できます。

映像は綺麗なのですが、ドアベルが押されてから、ビデオ会話できるまでの時間は少し長いです。場合によっては20秒くらいかかります。玄関の外と接続するので家の中のWiFiが届きにくいこともあります。バッテリーが1ヶ月弱でなくなるので充電が必要です。それで、玄関に古いインターフォンの配線が来ていたので、これに12V ACを流して常時充電できるように改造しました。バッテリー無しの有線給電専用モデルも出して欲しいと思いました。

Homebridgeから使う

Ring DoorbellをRaspberry Pi 4で動作させているHmebridgeに接続して、HomeKitから使用します。このために、Homebridgeプラグイン, homebridge-ringを使用しました。Homebridgeのwebインタフェースのプラグインページから、Ringと検索すると現れます。

こちらがgithubのサイトです。

github.com

インストール後に、「設定」ボタンを押すと、Ringアプリのアカウント情報の入力を求められます。Ringアプリの方で2段階認証を済ませておくと良いです。

ここで「LOG IN」ボタンを押すと、コードの入力を求められます。2段階認証で登録してある電話番号にsmsで届いた数字を入力します。

この結果、自動的にRefresh Tokenが設定されます。Refresh Tokenは、ターミナルのコマンドライン操作でも入手可能らしいですが、homebridge-ringプラグインGUIで取得できるようになってます。

ちなみにこのTokenは、いったん使用すると2分後に無効になって、新しいTokenが交付されるようです。homebridge-ringプラグインはそれを自動的に更新して、configファイルに書き込んでくれるらしいです。configファイルには、以下の項目が追加されていました。

{
    "refreshToken": "XXXX..実際は長いです..XXXX",
    "platform": "Ring"
}

これで設定は終了で非常に簡単でした。iPhoneMacのホームからビデオドアベルの映像が見られます。クリックすると、ライブビデオが見られて、会話することもできました。

Ringアプリとホーム.appの違い

こちらのページに、Ringアプリでできることと、HomebridgeでHomeKitに接続した場合にできることの比較表がありました。

linkdhome.com

ほぼ同じでした。HomeKitに接続するとApple TVから使えるのですが、Ringアプリの方が、応答時間と置き配検出で優れてます。HomeKitから使う場合、Ringのクラウド以外に、場合によってはiCloudも使うことになるので、応答速度は仕方ないところです。

https://images.squarespace-cdn.com/content/v1/58fb28d7e3df282054f72a55/1604668897685-0XGV80E7LEU9G4UZJZ6E/Homebridge-flow.jpg?format=2500w

( https://linkdhome.com/articles/ring-homekit-how-to )

HomeKitで使う一番のメリットは、他のアクセサリと統合できる点ですね。ドアベルは、カメラ映像から画像解析していて、モーションセンサとしても動作します。なのでHomeKitオートメーションで誰かがきたら玄関先の明かりをつけるなどの設定が可能です。

ただ、実際に使ってみたところ、HomeKit経由でビデオ会話を行うと、音声がかなり歪んでいました。WiFiの状況がたまたま悪かった、インターネットの接続がたまたま遅かったなどの要因も考えられるので、いつでもそうとは限りませんが、同じ時点で、Ringアプリでは割と明瞭に会話できました。

RingアプリとHomeKit側は、同時に稼働させることができるので、HomeKitは玄関の様子を見守る用途で使っていきたいと思います。

Chime Pro

オプションとしてChime Pro(チャイムプロ)があります。これがあると、ドアベルを鳴らした時に、チャイムが鳴ります。それだけではなく、WiFiのリピーターになってます。マンションのような鉄筋構造で、ドアも金属の場合は、ドア外のビデオドアベルWiFiが届きにくいです。なので、これを玄関内側に置いておくと、接続が安定します。

少し高価ですが(6,000円弱)、とりあえずはチャイムが鳴るので、システムが不安定な時にもあると安心です。ただ、かなり発熱します。

チャイムプロの良いところは、これもHomebridgeのプラグインのおかげで、HomeKitから複数のスイッチとして見えることです。それぞれのスイッチが、登録された音に対応しているので、オートメーションで色々な音が出せます。

まとめ

RingのドアベルをHomeKitから使いました。ドアベル製品としては、ビデオ会話を開始するのに20秒くらいかかることがあることもあり、応答速度が気になりました。

一方、Homebridge経由でHomeKitからも使用できました。プラグインがよくできていて設定はとても簡単です。ただ、ネットワーク環境のせいだとは思いますが、音声が歪んでしましました。玄関の様子を見る手段には問題なく使えます。

Matterの最初のバージョンにはビデオドアベルの規格もあります。Matter対応のドアベルが製品化されることに期待してます。

ミリ波を使ったZigbee人感センサー FP1 をHomeKitから使う

Aqaraのミリ波を使った人感センサをHomeKitから使いました。Zigbeeで通信するので、Zigbee2MQTTとHomebridgeを使用します。一般的なPIR(パッシブ赤外線)人感センサーと比較して、安定していて非常に使いやすいです。Zigbee2MQTTのwebインタフェースから感度などの設定が可能です。また人の検知以外に、人の移動のイベントもHomeKitから利用可能でした。

AqaraのFP1

独身の日セールで買いたいもの、としてネットで話題になっていたFP1を入手しました。送料込み5,700円でしたが、4,000円台で買えるところもあったらしいです。現在は7,000円台のようです。こちらの製品です.

そこそこ綺麗な白い箱に入ってます。箱には「精准感知空间有人和无人(無人),支持静止人体的存在识别(識別)」と書いてあります。漢字の雰囲気から「空間の有人と無人を正確に感知して、静止している人体の存在識別もサポートしている」という意味に読み取れます。漢字の力はすごい。

USB ACアダプタ、長めの電源(USB)ケーブル、取り付け用鉄板、両面テープなどが付属してます。付属品もしっかりしてました。

本体は丸くて洒落てます。グッドデザイン賞も受賞しているようです。ベースには強力な磁石が入ってます。ベースと本体には可動部分があって角度を調整できます。添付冊子によると、検出範囲は5m、横120度、縦40度程度とのことです。

本来の接続方法

Zigbee通信方式のセンサなので、省電力で、WiFiへの負担も無く使いやすいです。ただそのままではスマホやインターネットに接続できないので、通常はAqaraのHUB製品(例えばAqara E1)と一緒に使います。HUBがZigbeeとLANの橋渡しをしてくれるので、AqaraのスマホアプリやAqaraのクラウドからセンサが利用できるようになります。また嬉しいことに、Aqara HUBは、Apple HomeKitにも対応してます。なのでHUBを用意すればすぐにiPhoneMacのホームから使えるはずです。

今回の接続方法と比較すると、Aqara Hubを買う方が簡単で良いかもしれません。

ただし、試していませんので詳細不明ですが、上記の販売サイトにはAndroidスマホをオンラインにしておかないとHomeKitへの接続作業ができないようなことが書いてあります。これがセットアップ時の場合だけなのか、常時Androidスマホが必要なのか不明で、ちょっと不安です。

今回の接続方法

今回はFP1を、Zigbee-USBアダプター、Zigbee2MQTT、MQTTブローカ(Mosquitto)、Homebridgeを使ってHomeKitに接続しました。Zigbee2MQTT, MQTT, HomebridgeはRaspberry Pi 4 (4GB)で動いています。AqaraのHUBは使いません。

 

 

Aqara HubにはAqara社製品しか使えませんが、Zigbee2MQTTならば、市販のほとんどのZigbee製品が使えます。これからもZigbee製品を増やしていく予定があるならば、Zigbee2MQTTで頑張るのが良いと思います。Zigbee2MQTTインストールの詳細に関しては以下をご覧ください。

diysmarthome.hatenablog.com

背面ボタン長押しでペアリング

箱から出したFP1にUSB電源を接続したら、次にFP1をZigbee2MQTTにペアリングします。Zigbee2MQTTのペアリングモードがoffに設定してある場合は、webインタフェース右上のPermit join (All)のメニューをクリックしてペアリングを許可します。すると5分間、ペアリングが可能になります。

この状態でFP1の裏にあるリセットボタンを5秒程度長押しします。するとFP1の青色LEDが点滅してペアリングモードに入ります。この後20秒くらいでペアリングが終了します。WebインタフェースからDashboardメニューを選べば、FP1の情報が得られます。

人が近づいたことを検出しているようです。また温度も測定されています。ただしこの温度表示は、いつ見ても摂氏23度でした。もしかしたら測定しているふりをしているだけなのかもしれません。

Homebridge/HomeKitから使用する

HomebridgeにすでにZigbee2MQTT用のプラグインがインストール・設定されていれば、FP1が自動的にHomeKit上に現れます。iPhoneまたはMacのホームを見ると、上部に「人感検知」のアイコンが現れています。

これをクリックするとFP1が表示されます。初期状態ではZigbeeのIDが名前になってますが、以下ではAqaraFP1という名前に変更してあります。

また温度計も表示されました。ただしいつも23度なので動作しているのかどうかは怪しいです。

追記です。本日確認したら24度になってました。動作していないということは無く、多少は気温を反映しているようです。ただ隣に置いたDHT20のセンサは22度で、割と変化してます。FP1の温度は、変化がほとんど無く、実際より2度程度高い感じです。FP1のパッケージで密閉された場所の温度で、部品発熱の影響を受けているのかもしれないです。

HomeKitからできること

iPhone/MacのホームアプリケーションでFP1のアイコンをタップすると、以下のメニューが現れます。作成できるオートメーションは、「人を検知した」と「人の検知を停止した」です。

FP1をパソコン部屋の上部に設置して、このオートメーションで部屋の照明と、足元暖房(小さなホットカーペット)の電源をon/offするように設定しました。部屋の照明はZigbee壁スイッチで、ホットカーペットMerossのスマートプラグで制御しています。

理想的な人センサ

使用したところ大変快適でした。部屋に滞在中はずっと検知してくれます。PIRセンサのように、人が静止していると検知されなくなる不具合は皆無でした。PIRセンサは、人の体温に相当する長波長赤外線の揺らぎを検出します。なので、人が動いていないと、検知されなくなってしまいます。FP1はミリ波を使って距離の変化を測定してます。ミリメーター程度の解像度があるので、呼吸による変動も測定できて人検知するようです。試しに息を止めて動かないよう頑張りましたが、それでも検知されました。脈動のような微小な体の動きを人検知に使っているようです。

人が部屋に入れば10秒から15秒程度で検知されます。部屋から出ると10秒から30秒程度で検知されなくなります。人検知センサとして期待できる機能を実現できていると思いました。

Zigbee2MQTTでの詳細設定

Aqaraのスマホアプリを使うと、検知領域などを細かく設定できるようです。でもZigbee2MQTTのwebインタフェースからもかなりの設定が可能でした。以下のように、

  • monitoring_mode:人を無指向で検知するか、左右の入出も検知するかの切り替え。undirectedの場合、presence_eventとしてenter, leve, approach, awayが得られ、reft_rightに切り替えると、加えてright_enter, left_enter, right_leave, left_leaveが得られる。
  • approach_distance:人が近づくことを検知する際の検知距離
  • motion_sensitivity:検知感度
  • reset_nopresence_status:検知結果をリセットする

の設定が可能でした。ここまでのHomeKit設定で使用されるのは、presense(人が検知されたかどうか)の値と、温度の情報だけです。なので、ここの設定もデフォルトでok、もしくは、motion_sensitivity (検知感度)の調整だけで良いと思います。上記のように、FP1は検知領域の左右から出入りしたとか、近づいた・離れたなどのイベントも検知します。これらの情報をHomeKitで利用する方法については、後ほど紹介します。

MQTTメッセージを見る

Zigbee2MQTTがパブリッシュするMQTTメッセージを見ると、詳細な状況がわかります。mosquitto_subコマンドでサブスクライブしてみます。9999...のところには、FP1の実際の値を入れてください。

mosquitto_sub -h 192.168.x.x -t zigbee2mqtt/0x9999999999999999/# -v

この結果、以下のような情報が得られます。

zigbee2mqtt/0x9999999999999999 {"approach_distance":"medium","device_temperature":23,"linkquality":200,"monitoring_mode":"undirected","motion_sensitivity":"high","power_outage_count":0,"presence":true,"update":{"state":"idle"},"update_available":false}

色々な情報がjson方式で書かれています。内容は、

  • "approach_distance" 近づく検知を行う場合の距離設定
  • "device_temperature" デバイスの温度(いつも23度)
  • "linkquality" 電波強度
  • "monitoring_mode" 検知モード
  • "motion_sensitivity" 感度
  • "power_outage_count" 電源遮断回数
  • "presence" 人の検知

などです。

MQTTメッセージを要求する

このメッセージは、人の検知状況が変化した場合など、内容が変化した場合にパブリッシュされます。また、何の変化がない場合でも5分経過すると同じ内容がパブリッシュされます。

5分待つことなく、今すぐに情報が欲しい場合は、MQTTのトピックの最後にgetとつけて、欲しい情報を要求することができます。例えば、presenseが必要ならば、その値を空白にしたjson表記をパブリッシュします。

% mosquitto_pub -h 192.168.x.x -t zigbee2mqtt/0x9999999999999999/get -m '{"presence":""}'

するとmosquitto_subしている側に、結果がすぐに現れます。

zigbee2mqtt/0x9999999999999999/get {"presence":""}
zigbee2mqtt/0x9999999999999999 {"approach_distance":"medium","device_temperature":23,"linkquality":207,"monitoring_mode":"undirected","motion_sensitivity":"medium","power_outage_count":0,"presence":true,"update":{"state":"idle"},"update_available":false}

このように、結局は全部の情報が得られることになります。

MQTTから設定する

Zigbee2MQTTのweb画面から設定変更すると、その情報がすぐにパブリッシュされます。例えばZigbee2MQTTの設定画面で、感度をmediumに下げてみます。

すると、メッセージも以下のようになります。

zigbee2mqtt/0x9999999999999999 {"approach_distance":"medium","device_temperature":23,"linkquality":207,"monitoring_mode":"undirected","motion_sensitivity":"medium","power_outage_count":0,"presence":true,"update":{"state":"idle"},"update_available":false}

motion_sensitivityがmediumに変わってます。

同じ設定はmosquitto_pubコマンドでも可能です。Zigbee2MQTTのwebインタフェースの裏でMQTTメッセージを出しているので当然可能なのです。MQTTのトピックの最後に今度は、setをつけます。そして設定したい項目を記述します。今度は感度をhighに戻してみましょう。

mosquitto_pub -h 192.168.x.x -t zigbee2mqtt/0x9999999999999999/set -m '{"motion_sensitivity":"high"}'

 この結果、感度が再びhighに戻りました。

zigbee2mqtt/0x9999999999999999 {"approach_distance":"medium","device_temperature":23,"linkquality":207,"monitoring_mode":"undirected","motion_sensitivity":"high","power_outage_count":0,"presence":true,"update":{"state":"idle"},"update_available":false}

HomeKitでpresence_eventを利用する

ここまでの設定では、HomeKitから使用できる情報は、人の検知であるpresenceだけです。その値はtrue/falseの2値です。ここまででも十分便利です。FP1は他に、presence_eventとして、 "enter", "leave", "left_enter", "right_leave", "right_enter", "left_leave", "approach", "away"という値を提供します。これを利用する方法を考えます。

このために、HomebridgeプラグインのMQTTThingを使います。MQTTThingを使えば、Zigbee2MQTTが出してくれるMQTTメッセージを利用できます。

そこで、MQTTThingの設定メニューからMotion Sensorを1個追加します。モーションセンサの名前をFP1_approachとしました。最終的なconfig設定は以下のようにしました。

{
    "type": "motionSensor",
    "name": "FP1_approach",
    "url": "mqtt://localhost:1883",
    "topics": {
        "getMotionDetected": "zigbee2mqtt/0x9999999999999999$.presence_event"
    },
    "onValue": "approach",
    "offValue": "away",
    "accessory": "mqttthing"
}

MQTTThingの最近のバージョンではjson表記のメッセージも扱えるようになってます。トピックの最後に$.をつけてjsonのキーの名前を指定できます。ここではpresence_eventの値を取得したいので、$.presense_eventと追加してます。これがapproachの場合にonとみなし、awayの場合にoffとみなすように設定しました。

これを保存してHomebridgeをリセットすると、ホームに、このモーションセンサが現れます。

設定のところでは、動きを検知したとき(ここではapproachの場合)と検知しなかったとき(awayの場合)に行うオートメーションを書きます。テストのためにNanoleafの電球をon/offさせるようにしました。

試したところ、FP1に近づく動きをすると電球が点灯し、FP1から離れる動きをすると電球が消灯しました。このようにしてセンサーに向かって近づく・離れる、センサーに左右から近づく・離れるなどの動きにHomeKitで対応できました。

まとめ

ミリ波を使ったZigbee人感センサーFP1を使ってみました。遠赤外線を使った一般的なPIRセンサと比べて3倍くらい高価ですが、応答速度は早くて動作が安定していて、人の存在を確実に検出できました。Zigbee2MQTT用のプラグインでは人の検知のみがサポートされていますが、MQTTThingプラグインを使うことで、人の移動も検出できました。MQTTメッセージに対応するPythonプログラムなどを書けば、さまざまな用途にも使えると思います。

Tuyaクラウドのお試し期間(1ヶ月)が終了して動作停止

こちらに移転しましたので自動転送します。

Tuyaの開発者向けクラウドを利用してWiFi赤外線リモコンを使用していたところ、「サブスクが期限切れになりました」というエラーメッセージを受け取るようになり、動作しなくなりました。代替案を試しましたが使えなさそうでした。今後は、Zigbee対応のTuyaデバイスを、Zigbee2MQTT経由で使用するのが良いようです。

Tuyaリモコンが不調

Tuyaのデバイスは安いのに(リモコンなどは最安530円)、Homebridgeから使えてとても良いです、という紹介を先月くらいに書いたばかりでした。Tuyaの開発者向けクラウドで無料のアカウントを取得して、Tuyaの公式プラグインを使えば、さまざまなTuya製品がHomebridgeから使用できるはずでした。

diysmarthome.hatenablog.com

ところが、今月になりこれが動作しなくなりました。Tuyaのクラウドからの応答を見ると、

TuyaOpenAPI response: {"code":xxxxxxxx,"msg":"No permissions. Your subscription to cloud development plan has expired.","success":false,"t":xxxx,"tid":"xxxx"} path = /v1.0/iot-01/associated-users/devices
Failed to get device information. Please check if the config.json is correct.

というメッセージが返ってきています。サブスクリプションが期限切れになったので使用できないという内容のようです。色々なサイトやYoutubeで、Home AssistantやHomebridgeからTuyaのクラウドを使用する方法が数多く紹介されていますが、クラウド利用に期限があるような注意事項は記載されていませんでした。なのでずっと使用できると思ってました。

いろいろ調べたところ、Tuyaの開発者アカウントのお試し版 (Trial Edition) の有効期限は1ヶ月とのことでした。

以前は無料プランでもずっと利用できたようですが、ここ半年くらいでお試し期間が1ヶ月になったようです。上記のリモコンを設定してから、エラーが出るようになったのがちょうど1ヶ月くらいでした。ちなみに有料プランの料金がいくらくらいかというと、

developer.tuya.com

一番安いStandard版で年額3,300USドルです。自宅のデバイスをHome AssistantやHomebridgeで制御しようという一般人向けの価格では無いです。おそらくは、Tuyaのチップを使って自社製品を開発するメーカー向けの価格だと思われます。

Tuyaのクラウドを使用しないでデバイスを利用する方法には、

  1. LocalTuyaインテグレーションを使う
  2. Zigbee方式のデバイスならばZigbee2MQTTを使う

の2通りがあるようです。ただし、どちらも使えるデバイスに制約があります。

LocalTuyaインテグレーション

Home Assistantには、Tuya公式のTuyaインテグレーションのほかに、LocalTuyaという名前のインテグレーションがあります。(インテグレーションというのは機能拡張というような意味合いだと理解してます。)公式インテグレーションは、Tuyaクラウドを使うので、現在では設定後1ヶ月で利用できなくなります。新しいメールアドレスで開発者アカウントを取り直せば再開できますが、毎月それを行うのは現実的ではないです。

github.com

一方、LocalTuyaというのはHome Assistantの上で、Tuyaクラウドの機能を実現する仕組みのようです。これがあればTuyaクラウドに接続する必要も、さらにはインターネットに接続する必要もなく、Tuyaデバイスが利用できます。HomebridgeにはLocalTuyaに相当する機能を持つプラグインはありません。でも、Home Assistantには、デバイスをHomeKitにブリッジする機能があるので、HomeKitからもLocalTuyaを利用できるはずです。

Tuyaクラウドをローカルに実現するのは結構大変な処理だと思うので、いろいろ制約はあると思いました。特に、赤外線リモコンは、クラウド側で各種家電メーカーの赤外線信号パターンを管理していると思われるので、サポートされていないのではと思いました。確認のためにLocalTuyaをインストールしました。

結論を先に書いておくと、LocalTuyaでは赤外線リモコンは使えませんでした。リモコン以外のTuyaデバイスには有効かと思われます。

LocalTuyaをインストールする

LocalTuyaはHome Assistant (以下HA) 公式ではなく、有志の人たちが実験的に作っているインテグレーションのようです。なので、HA初心者にはインストールが大変でした。LocalTuyaのサイトによるとおすすめのインストール手順は、

  1. (ユーザ名)・プロファイルで「詳細モード」をonにする
  2. 設定・アドオン・アドオンストアからTerminal & SSHを入れる
  3. sshを操作してHACS (HA Comunity Store) を入れる
  4. 設定・デバイスとサービス・統合・統合を追加から、HACS統合を入れる
  5. HACS・IntegrationsからLocalTuyaを入れる
  6. Tuyaクラウドからデバイスのlocal_keyを入手してLocalTuyaに設定する

です。箇条書きにすると単純ですが、それぞれのステップが大変でした。(ただし、HA初心者なので、回り道している可能性はあります。)

まずは、ステップ2でつまづきました。手元ではHAをDockerでインストールしていたのですが、Docker版ではアドオンが使えないそうです。どうしても動かしたい場合は、別のコンテナを作るらしいですが、大変そうなので諦めました。そこで手元にあったRaspberry Pi 3に、HAをイメージでインストールしました。本当はPi 4を使いたかったのですが、今の品薄で入手できません。

Dockerを使わずにベアメタルなインストールをしたおかげで、アドオンがメニューに現れるようになりました。これでsshのインストールが終わります。この後、再起動し、設定・デバイスとサービス・統合・統合を追加から、HACSインテグレーションのインストールができました。詳しい手順はHACSのサイトを見ていただくとして、結構大変でした。HACSってHA本体の開発陣から嫌われているのかなと邪推したくらいです。

HACS統合がインストールできれば、サイドバーにHACSが現れます。これを選択して、Integrationsを選び、右下の「EXPLORE & DOWNLOAD REPOSITORIES」を選ぶと、LocalTuyが選択できるようになります。

右下のDOWNLOADボタンを押すとLocalTuyaをダウンロードできます。次に再起動して、設定・デバイスとサービス・統合・統合を追加からHACSからLocalTuyaをインストールできます。

設定・デバイスとサービス・統合のページにLocalTuyaが現れるようになりますので、ここからデバイスを登録できます。

慣れてないこともありますが、Home Assistantは設定が難しいですね。Homebridgeの5倍くらい難しい気がします。

LocalTuyaで使えるデバイス

LocalTuyaで現在使えるデバイスは、

  • Switches
  • Lights
  • Covers
  • Fans
  • Climates
  • Vacuums

です。この中には赤外線リモコンはありません。ただ、Tuyaの赤外線リモコンユニットで、エアコンや照明器具を登録すると、Tuyaのアプリでは、エアコン、照明デバイスとして扱われます。エアコンはClimates、照明器具はLightsに相当します。これらがLocalTuyaで使えるかどうかが心配の点でした。

そこでLocalTuyaのデバイス登録を進めたところ:

の4項目が必須情報でした。このうちHostというのは、そのデバイスIPアドレスだそうです。赤外線リモコンにはIPアドレスがありますが、その先に接続されているエアコンや照明器具は、リモコンがコントロールしているのでIPアドレスがありません。

ということで、赤外線リモコンがLocalTuyaでサポートされていない現状では、使用できないようでした。赤外線リモコンをローカルにサポートするのは大変なので、なかなか実現できないのではと思いました。

以前の記事では、TuyaのWiFi磁気接触センサも紹介しました。これもTuyaクラウドを利用します。これも1ヶ月制限で使えなくなっていました。

diysmarthome.hatenablog.com

WiFi接触センサは応答が遅かったのでZigbee方式のものに置き換えてしまいました。なのでテストできていませんが、もしかしたらこちらはLocalTuyaで使えるかもしれません。

Zigbee2MQTTを使う

Tuyaの製品ならばクラウド利用してHomeKitから使えると喜んでいたのですが、どうも制限が厳しくなっていたようです。一方、Tuyaの製品のうち、Zigbee接続のデバイスなら、ほとんどがZigbee2MQTTでサポートされています。今後は、Zigbee接続製品だけをアテにするのが良いと思いました。

まとめ

Tuya開発者向けクラウドの1ヶ月お試し期間が終了したら、Home AssistantやHomebridgeからのクラウド経由でのアクセスができなくなりました。LocalTuyaなどのツールも試しましたが、赤外線リモコンは使えませんでした。

アプリであるTuya Smartからは引き続き使用できますし、本来の使い方ではないので打ち切られても仕方ない側面もあります。でもクラウドに依存する危うさを再確認しました。TuyaはMatterのメンバーですし、対応製品の予定もアナウンスされています。今後に期待したいところです。

PoE IPカメラ (2,059円) をHomeKitから使う

Ethernetに接続する安価な有線IPカメラを、Raspberry Pi4にインストールしたFFmpegとHomebridgeを使って、HomeKitに接続しました。Power over Ethernet接続の機種を選べば、カメラへの配線は1本で済みます。

IPカメラが安い

セキュリティ目的のカメラにはいろいろなタイプのものがあります。その中でもIP接続するカメラは、柔軟に接続できるので使いやすいです。これらのカメラは、一般的にはWiFiEthernetで接続して、RTSP (Real Time Streaming Protocol) で動画データを配信します。

WiFi接続のIPカメラは、配線が楽ですが、WiFiの帯域に動画データが負荷をかけます。また、WiFiであっても、電源ケーブルが必要な場合が一般的なので、配線が全く不要というわけではないです。

一方、Ethernet方式のIPカメラの中には、PoE (Power over Ethernet) に対応したものもあります。これならばEthernetだけの配線で、電力も供給できるので配線が楽です。 ということで、今回はPoE対応有線IPカメラを使いました。

PoEハブを揃える

PoE機器を使用するためには、Ethernetに電力を供給するデバイスが必要です。Ethernetはもともと通信データを送る配線の規格で、電力を供給する配線は含まれていませんでした。でも、電力も送れると便利なので、使われない配線を電力線に使うPoE規格が作られてます。いくつか規格があるようですが、基本的なもの (IEEE 802.3af) は48V15Wを供給する方式です。IPカメラは消費電力が少ないので、この規格のPoEで機能します。

Ethernetで使われるケーブルの中には、2本ずつ捻り合わされた4対の銅線(合計8本)が使われてます。

( http://www.aim-ele.co.jp/tech/metal-tech6/ )

100Base-Tではこのうちの2対が使われるので、2対が余ります。上の図でPin 4, 5, 7, 8が余ります。その余った2対(合計4本)の線を電力供給に使ってしまおうというのがPoE (IEEE 802.3af) の規格です。余った配線に48Vの電圧をかけて、電力を送ります。一方で、現在一般的に使われている1000Base-TEthernetでは、転送速度を稼ぐために4対全部の配線を通信に使用してます。なので、この規格のPoE機器は、必然的に100Base-Tで機能します。

PoEを使う場合は、PoEハブを用意すると簡単です。PoEハブは上流から1000Base-TEthernetを受けて、これを下流100Base-TのPoEに流します。PoEに必要な電力はハブから供給されます。また、PoEのコネクタに、PoE非対応の1000Base-T機器が接続された場合は、自動判定して1000Base-Tでの接続をします。

PoEハブは、以前は日本で買うと高価でしたが(AliExpressなどでは安かった)、最近は日本のAmazonでも手頃な価格で買えるようになりました。

IPカメラを選ぶ

ネット通販でPoE接続のIPカメラを探しました。これも少し前はAliExpressの品揃えが豊富でしたが、最近は日本のAmazonでもそこそこの価格で買えるようになりました。でもやはりAliExpressの方が安くて豊富です。ということで、この機種を選びました。

品定ポイントの第一は、PoE対応かどうかです。48V PoEと書いてあれば、規格に沿っていると思われるのでより安心です。

素数が1M画素の機種は1280x720の標準HDで、2M画素が1920x1080のフルHDです。あまり高画素だとデータが大きくて負担になるので、1M画素にしました。またレンズの焦点距離が、2.8mm, 3.6mm, 6mmとあるのは、広角・標準・望遠のような位置付けです。これは使用目的次第ですが、セキュリティカメラとしては広角の方が何かと使いやすいです。なので2.8mmにしました。

IPカメラを選択する際に、RTSPの仕様がわかっている機種が望ましいです。RTPSはHTTPと同様に、IPアドレスディレクトリ構造、ファイル名などを指定してアクセスします。その詳細が不明でも、色々と試せば発見できるのですが(それはそれで謎解きのようで楽しいのですが)、すでにわかっているメーカならば手間が省けます。それには、こちらのサイトが役立ちます。

www.ispyconnect.com

ここに、いろいろなブランドがアルファベット順に記載されてます。ここにURLが掲載されたブランドの該当機種ならば、ほぼ問題なくFFmegから接続可能です。今回の製品は、Xmeyeというブランドのようで、上記のサイトにも掲載されています。なので、安心して購入できました。

分解してみる

1M画素のPoEモデルの価格は送料無料で2,059円でした。人感センサと同じくらいの価格で、カメラが買えてしまうのはすごいかと思います。

品物は、適切に梱包されていて問題なく到着しました。全体に肉薄の軽いプラスチックで作られていて、コストダウンされている感じです。でも角度調整(雲台)の部分は、3軸の回転が可能で、調整後はネジで固定できるようになってます。堅牢ではないですが、価格を考えたらよく作られていると思いました。

カメラを傾けると、カサカサと音がするので、プラスチック片でも混入しているのかなと思って蓋を開けました。背面のネジ3個で裏蓋を開けることができます。中の基盤は綺麗に作られてます。

蓋はゴムでパッキングされていて、ケーブルの入り口はホットボンドでしっかり固めてあります。一応の防水はできているようです。傾けると音が出る正体は、乾燥剤でした。接着剤で止めてありました。湿気対策のようです。

全体に高級感はありませんがしっかりと作られてます。この基板の裏側には、レンズ、撮像素子、照明用赤外LEDがあるわけで、これらが2,000円ちょっとで販売されているのは驚きです。コスパがすごいです。

Webインタフェースは使えない

PoEハブに接続すると、青いLEDが点灯して、しばらく経つとリレー音が聞こえます。赤外線照明LEDのon/offだと思われます。動作しているようです。

製品と一緒に入っていた説明書によると、工場出荷時には192.168.1.10にアドレス設定されているようです。LANのネットワークアドレスは別の値だったので、コンピュータの方を手動で192.168.1.XXXに設定して、webブラウザでアクセスします。こんなページが現れました。

ユーザ名admin、パスワードなしでログインできるのですが、カメラ画像の表示は出ません。Macなのでダメなのかと思い、Windowsで試しても「このプラグインはサポートされていません」という表示が出るだけです。説明書によるとActiveXが必要とのことです。今更ActiveXに対応させる気にはならないです。さらに説明書によると、webからは映像が確認できるだけで、設定はできないようです。Webインタフェースは、カメラのアドレス、ユーザ名、パスワードが正しく設定できたかどうかの確認用に使うのが良いと思いました。

設定アプリが必要

このwebページが現れるタイプのIPカメラは、今までも使ったことがあります。格安の製品に多いです。おそらくは、昔に開発された仕組みを使った部品が出回っていて、複数の会社がそれを使ってカメラを商品化しているのだと思います。

このタイプのカメラは、設定に専用のWindowsアプリが必要です。MacLinuxスマホからは設定できません。Windowsを起動し、説明書に書いてあるURLからVMSという名前のアプリをダウンロードしました。こんな画面のアプリです。

上のDevice Managerというボタン

から現れるページで、IPアドレスを使ってカメラを登録します。ここでIPアドレスとパスワードが変更できます。IPアドレスをLANで使っている範囲に書き換えた後、Windowsのアドレスも元に戻して、再びVMSで接続します。

この後は、Device Configのボタンを押して、タイムゾーンとかNTPの設定をします。設定項目としては、

の設定くらいをしておけば良いと思います。他にも細かい設定が可能なので、一通り見ておくのも良いと思います。ちなみに、このVMSアプリでも、カメラの映像は表示されませんでした。今のWindowsでは使われていない古い仕組みを使っているのかと思われます。

FFmpegを使う

ネットワーク関係の設定が終了したら、Macから(Windows, Linuxでも良いですが)FFmpegでIPカメラ映像取得のテストをします。以前の記事で、FFmpegを使ってUSBカメラの映像を利用しました。今回も同様です。FFmpegの説明は、こちらの記事を見てください。

diysmarthome.hatenablog.com

FFmpegのコマンドの一つであるffplayを使って、IPカメラの映像を確認します。

ffplay -i rtsp://192.168.xxx.xxx/ ...

のようにして、IPカメラのRTSPのURLを指定すると、映像が表示されるはずです。問題は、このURLが何かという点です。この辺りの規格化はされていないらしく、カメラによってバラバラです。それを調べ上げてまとめてくれているのが、上で紹介したサイトです。今回使用したXmeyeというブランドのURLは、こちらのページに書かれてます。

www.ispyconnect.com

このページでは、URL雛形リストをクリックすると、環境に合わせたURLを自動生成するダイアログパネルが現れます。ここのアドレス、パスワードなどの項目に使用中の値を入れて、「Generate URL」ボタンを押します。生成されたURLをターミナルにコピペすれば、すぐに動作確認できます。&などが含まれるURLをffplayの引数に使う場合は、その前に逆スラッシュを入れておく必要はあります。この生成結果をいろいろ試して、動作するURLを探します。

このページのURLを試したところ、

ffplay -i rtsp://192.168.x.x/user=admin_password=xxx_channel=1_stream=0.sdp

で720pのHD画像が、また、

ffplay -i ffplay -i rtsp://192.168.x.x/user=admin_password=xxx_channel=1_stream=1.sdp

でその半分のサイズの画像が表示されました。以下のようなウィンドウです。

Homebridgeの設定

見つかったURLを使って、HomeKit対応カメラとして設定します。前回の記事と同様に、HomebridgeにHomebridge Camera FFmpegプラグインを使用しました。今回は、Raspberry Pi4で動かしているサーバにインストールしました。前回の記事のUbuntuで行ったのと全く同じ手順ですので、詳しくはこちらをご覧ください。

Homebridgeのコンフィグでカメラの名前をSky Cameraとしました。"source"の設定には、上で動作確認できたハーフサイズの映像のURLを使いました。

{
    "name": "Camera FFmpeg",
    "cameras": [
        {
            "name": "Sky Camera",
            "videoConfig": {
                "source": "-i rtsp://192.168.x.x/user=admin_password=xxx_channel=1_stream=1.sdp"             
} } ], "platform": "Camera-ffmpeg" }

その結果、iPhoneMacのホーム.appにカメラ映像が表示されます。以下はiPhoneスクリーンショットです。

映像の部分をタップすると、拡大表示されます。

Homebridge Camera FFmpegプラグインのデフォルトは、音声を伝えない設定です。これを伝える設定にしてみましたが、音声は伝わりませんでした。このカメラにはマイクロフォンやスピーカが搭載されていないようです。監視カメラとしては一般的な仕様だと思います。

Amazonで買えるIPカメラ

Amazonで見つけたPoE IPカメラのうち、RTSP URLが特定されているブランドの1万円未満の製品を以下にまとめておきます。AliExpressほど安くは無いですが、お試しするのに適当ではないかと思います。

Amazonでは、有線接続よりも、WiFi接続のカメラの方が豊富でした。PoEハブが不要なことを考えると、有線よりも安く導入できます。ペットや子供の見守りが目的の製品のようで、音声を伝える機能もついています。以下は、RTSP URLが判明しているとされている型番のWiFi IP カメラです。型番末尾が1番違いくらいでしたら、おそらくは旧製品のバージョンアップなので使えると思います(この一覧からは外してあります)。

これらはFFmpegとHomebridgeの組み合わせでHomeKitから使用できると考えられます。

まとめ

送料込み2,000円ほどのIPカメラを入手して、HomeKitカメラとして使用しました。他にも安価なIPカメラをいくつか使ったことがありますが、今回使用した製品は、さらにコスパが高いです。Webインタフェースや設定ソフトがしょぼいのも許せます。

PoE IPカメラは、この他にも、AliExpressやAmazonでいろいろな製品が揃ってます。RTSPのURLがわかっているブランドや品番を選べば、大体はFFmpegとHomebridgeで使用可能だと思います。また、今回の製品では厄介だった初期設定ですが、製品によってはwebインタフェースから全ての設定ができる製品もあります。ただ、雲台部分の作りがあまり良くなかった印象があります。

TuyaのZigbee磁気接触センサ(1200円くらい)

以前、格安のWiFi接触センサを紹介しました。

diysmarthome.hatenablog.com

今度はZigbee版です。WiFiに比べるとそこそこ高いです。こちらの商品です。買った時は送料込み1200円くらいでした。今は1300円くらいでしょうか。たくさん買うと安くなり、8個で単価900円くらいです。このセンサはZigbee2MQTTでサポートされているので、Homebridge経由でHomeKitから使用できます。

www.zigbee2mqtt.io

開封して中身を見る

外箱はこんな感じでした。Smart Life(家のアイコン), Tuya smart(tの文字), Zigbeeのロゴが入ってます。ただ、製造している会社の名前はありません。Tuyaのエコシステムで動くけど、Tuyaが製造している様子ではないみたいです。

開けると本体とマグネットが入っています。WiFiの磁気接触センサと比べるとかなり小型です。あちらは単3電池が2本でしたが、こちらはCR2032のボタン電池が1個です。

分解すると、中にはZTUと書かれた無線ユニットが入ってました。写真下端の黒い部分が磁気接触スイッチです。これは単純なリードスイッチが使われているようです。改造が楽そうです。

無線ユニットのことを調べてみたところ、Tuyaが開発しているZigbee対応のワンチップコンピュータでした。

developer.tuya.com

他にもいろいろなバリエーションのチップを開発しているようです。メーカは、このチップを仕入れてくれば、簡単にIoTデバイスを商品化できるようです。部品としてTuyaから買ってきて、組み込むだけで、自社製品が作れるようです。クラウドやアプリの開発、サポート、カスタマーサービスは全部Tuyaがやってくれる仕組みです。これがTuyaの強みなのかなと思いました。

アプリは使わない

WiFiセンサの時はWiFiの設定をするためにTuyaのスマホアプリを使用しました。今回は使用しません。それ以前に、Tuya SmartやSmart Lifeアプリを使うためには、TuyaのZigbee-LANブリッジが必要です。今回は、Zigbee2MQTTに接続するので、アプリもブリッジも使用しません。

ペアリングする

こちらで設定したZigbee2MQTTにペアリングします。

diysmarthome.hatenablog.com

設定の時に、webインタフェースをonにしてあったので、webブラウザで操作できます。ペアリングはoffに設定してありましたので、webページ右上のボタンをクリックして一時的にペアリングonにします。一回クリックすると5分間ペアリング可能状態になります。

接触センサの方をペアリングモードにするためには、付属のピンなどでリセット穴の中のスイッチを長押しします。マニュアルには6秒長押しすると書いてありましたが、実際には4秒くらいでリセットモードになりました。するとまもなくペアリングが完了して動作開始しました。Ziegbee2MQTTのwebページでは以下のように見えます。

Homebridgeにはz2mプラグインが入っているので、iPhoneMacのホームに、以下のように現れました。(名前は変更しました)

     

WiFi接触センサに比べて応答速度は速いです。HomeKitのオートメーションを作って、磁石の接触NanoleafのThread電球をon/offさせてみました。開放も閉鎖も一瞬で応答します。ストップウォッチも間に合いません。0.5秒未満くらいの感じです。ただ、開放から閉鎖の時は、10回に1回くらい、応答が3秒くらい待たされることもありました。でもWiFiのセンサが30秒くらいかかったのに比べると早いです。

まとめ

TuyaのZigbee接続接触センサをHomeKitから使いました。磁石と併用して、ドアや窓の開閉を検出するスイッチです。以前使ったWiFiのセンサに比べて3倍くらい高価ですが、サイズは小さく応答速度が早かったです。HomeKitで使える磁気接触センサは数種類あるようですが(Thread接続やBLE接続のようです)、国内で販売されている製品は皆無です。早くMatter over Threadが一般的になって、こういう基本的なセンサ・スイッチが誰にでも使えるようになると良いと思います。

HomeKitでZigbeeを使う:Zigbee2MQTTを導入する

Zigbeeバイスは省電力でメッシュも構成するし応答も早くて、スマートホームに欠かせません。AmazonやAliExpressでは、お値打ちなZigbeeバイスが豊富に揃ってます。今回は、Zigbee機器をHomeKitから使えるようにするため、Zigbee2MQTTなどをインストールして設定しました。

ZigbeeバイスをHomeKitで使う2通りの方法

国内で簡単に入手できて、HomeKitでも使えるZigbee製品として、Philips HueまたはIKEAの製品があります。

Zigbee接続デバイスをLAN側から使う第一の方法は、それぞれの会社が提供するハブを買うことです。Zigbeeハブは、Zigbee無線ネットワークとLANを接続します。さらに、HomeKitに対応したIKEA/Philipsのハブには、ZigbeeバイスをHAP対応デバイスに見せてくれるブリッジ機能が備わってます。これによりHomeKitからZigbeeバイスが使えるようになります。こんな順番の接続です。

[HueとIkeaのデバイス]---[HueとIkeaのハブ]--(HAP)--[HomeKit]

2番目の方法は、メーカが提供しているハブを利用せずに、Zigbee2MQTTとHomebridgeを使う方法です。

[Zigbee]---[Zigbee2MQTT]--[Homebridgeなど]--(HAP)--[HomeKit]

ただ、ZigbeeバイスをHomebridgeで使うためには、プラグインに加えてハードウェア、ソフトウェアが必要です。Zigbeeの側から情報の流れに従って書くと、以下のユニットが必要です。

  1. USB送受信器:Zigbeeバイスと無線送受信するUSBアダプター
  2. Zigbee2MQTT:Zigbeeバイスと通信してMQTTブローカに伝えるデーモン
  3. Mosquitto:MQTTブローカーです
  4. Homebridgeとプラグイン:MQTT経由でZigbee2MQTTとやりとりするプラグイン

1, 2, 3までのユニットは、Home AssistantでZigbeeバイスを制御する場合にも使われるものです。また、2, 3, 4の部分は、WindowsmacOSNASなどでも動かせますが、通常はLinux系のサーバーで動かします。処理能力も要求されないので、Raspberry Piがよく使われます。

下の図に、必要なユニットを信号の流れる順番に示しました。左端のZigbee機器(たとえば電球)を右端のHomeKitに接続するためには、いろいろ用意する必要があります。

このうち、HomebridgeとMosquittoについては、以前の記事で詳しく説明してあります。

diysmarthome.hatenablog.com

diysmarthome.hatenablog.com

これらがすでに設定されている前提で、USBトランシーバ、Zigbee2MQTT、Homebridgeプラグインを追加する方法を説明します。なお、Zigbee2MQTTに関しては、プロジェクトのホームページに詳細な情報があります。これを参考にしました。

www.zigbee2mqtt.io

Zigbee2MQTTを使う理由

上で述べたように、メーカーが用意してくれるハブを買えば、ZigbeeバイスをHomeKitから使えます。しかし、Zigbee2MQTTを使えば、使えるZigbeeバイスが圧倒的に増えます。メーカーハブを買ってくるだけの方法に比べて、いろいろ揃えてインストールする手間は面倒ですが、その価値はあります。

Zigbeeは、情報のやり取りは決まってますが、上位のプロトコルまでは統一されていないようです。なので、たとえば同じ電球でも各社で互換性がありません。メーカのハブは、基本的に自社製品しかサポートしていないので、メーカーごとにハブを用意する必要があります。それに国内で買えるHomeKit対応Zigbeeハブは、IKEAのTRÅDFRIゲートウェイPhilips Hueブリッジだけです。

それに対して、Zigbee2MQTTのコミュニティでは、自分たちが入手したZigbee製品のデータを持ち寄って、対応デバイスを増やし続けています。なので、ある程度知られたデバイスなら、ほぼ使用可能です。もちろんIKEAPhilipsZigbee製品も使えます。またIKEAの場合、Zigbeeスイッチや人感センサは電球とペアリングして使うことになっていて、スイッチ・センサの情報をHomeKit側には公開していません。でもZigbee2MQTTを使えばこれらもHomeKit側から利用可能になります。

Zigbee2MQTTの対応デバイスこちらから確認できます

USBトランシーバ

WiFi, BLEはどのスマホにもノートPCにも搭載されていますが、Zigbeeは搭載されてません。なので、Zigbee電波を送受信するアダプターが必要です。ただそのアダプタも、WiFiやBLEのように豊富には出回ってません。

Zigbee2MQTTで使えるおすすめアダプターはこちらで紹介されてます。それによるとTexas Instruments社のCC2652というチップを使用した製品が推奨されてます。実際に購入して、Raspberry PiUbuntuマシンのUSBポートに挿すだけで、Zigbee2MQTTで使えた製品を2種類ご紹介します。

一つは、こちらの製品です。CC2652Pの方を買いましたが、CC2652Rでも動くのではと思います。検索してみたらPとRの違いはGPIOの数が違うくらいのようです。Zigbee2MQTT対応と書かれてます。

もう一つは、こちらのSonoffの製品です。上の製品よりも造りがしっかりしていて、価格も安くおすすめです。

ただし、Sonoff社には、別のSilicon Labs社チップを使った新製品があり、名前が紛らわしくて注意が必要です。失敗談はこちらをご覧ください。

diysmarthome.hatenablog.com

ちなみにSonoffのアダプタはAmazonでも売っているようですが、価格が高いです。

これらのUSBトランシーバを、Raspberry PiLinuxマシンのUSBポートに差し込むと認識されます。手元のRaspberry Pi 4でlsusbコマンドを発行すると、こんなふうに見えました。

$ lsusb
Bus 001 Device 003: ID 1a86:7523 QinHeng Electronics CH340 serial converter

シリアル変換のチップが入っているのでそれが認識されてます。シリアルチップは、特別にドライバをインストールしなくても、そのまま/dev/tty*に見えました。

$ ls /dev/tty*
/dev/tty    /dev/tty0  /dev/tty1  (略)  /dev/ttyUSB0

今まで使ったところでは、/dev/ttyUSB0もしくは/dev/ttyACM0という名前で現れることが多いです。macOSでもこの名前で現れました。USBトランシーバーを抜き差しすると、消えたり出現したりしますので、その挙動でも確認できます。この名前はZigbee2MQTTの設定で必要なので、メモしておきます。

Mosquittoのインストール

Zigbee2MQTTにはMQTTブローカーが必須なので、簡単に説明しておきます。こちらに書いた手順で、MQTTブローカであるMosquittoをインストールします。

diysmarthome.hatenablog.com

基本的には、aptコマンドでインストールするだけです。

sudo apt install mosquitto mosquitto-clients

また、OS起動時に自動的にMQTTブローカが立ち上がるように以下の設定をしました。

sudo systemctl enable mosquitto.service

Zigbee2MQTTをインストール

ではいよいよ、Zigbee2MQTTを公式ページの手順に従ってインストールします。色々なハードウェアにインストール可能ですが、Raspberry PiLinuxマシンにインストールするには、以下の公式ページのガイドが参考になります。

www.zigbee2mqtt.io

それによると、

# nodejsなどをインストールします。すでに入っているかもしれません。
# 公式ガイドのページではapt-getを使ってますが、aptに統一したいと思っているのでaptでインストールしました

sudo curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt install -y nodejs git make g++ gcc

# nodeとnpmのバージョンを確認します
node --version  # Should output v14.X, V16.x, V17.x or V18.X
npm --version  # Should output 6.X, 7.X or 8.X

# zigbee2mqtt用のディレクトリを作ります
sudo mkdir /opt/zigbee2mqtt
sudo chown -R ${USER}: /opt/zigbee2mqtt

# Zigbee2MQTT リポジトリをクローンします(よくわかってないです)
git clone --depth 1 https://github.com/Koenkk/zigbee2mqtt.git /opt/zigbee2mqtt

# ディペンデンシーをインストールします(同上)
# ユーザを"pi"にしてますが、いつもログインするユーザが良いです
cd /opt/zigbee2mqtt
npm ci

これでエラーらしい表示が出なければokです。

次に設定ファイルを用意します。/opt/zigbee2mqtt/data/configuration.yamlにあるテキストファイルです。公式ページの設定例は以下です。

# MQTTの設定
mqtt:
  # MQTT base topic、なんでも良いです
  base_topic: zigbee2mqtt
  # MQTT server URL、ブローカーのアドレスです
  server: 'mqtt://localhost'
  # MQTT のユーザ、パスワードを設定している場合は以下を記入
  # user: my_user
  # password: my_password

# Serial の設定
serial:
  # USBトランシーバの接続場所です。今までの経験ではttyUSB0かttyACM0です。
  port: /dev/ttyUSB0
  # 以下の設定はおすすめらしいです
  advanced:
    network_key: GENERATE
  # 以下を指定しておくとwebから操作できます。とても簡単なのでお勧めです
  frontend: true

Zigbee2MQTTを起動する

起動させるには、

cd /opt/zigbee2mqtt
npm start

とします。いろいろメッセージが出ますが、エラーらしきものが出なければ成功です。止めるにはコントロールCを押します。

このコマンドで起動すると、自動起動などが面倒なので、systemctlを使います。まずは、/etc/systemd/system/zigbee2mqtt.serviceというファイルを作って、内容を、

[Unit]
Description=zigbee2mqtt
After=network.target

[Service]
ExecStart=/usr/bin/npm start
WorkingDirectory=/opt/zigbee2mqtt
StandardOutput=null
StandardError=inherit
Restart=always
RestartSec=10s
User=pi

[Install]
WantedBy=multi-user.target

とします。ユーザ名piで起動することになってますので、別の名前を使う場合は書き換えます。これで、

sudo systemctl enable zigbee2mqtt.service

とすれば、以後、自動的に起動します。とりあえず起動しておきたいので、

sudo systemctl start zigbee2mqtt.service

としておきます。startの代わりに、stop, restart, statusなどのコマンドが使えます。

プラグインを入れる

ここまでの作業で、

のほとんどが用意できました。Zigbee2MQTTは結果をMosquittoにパブリッシュしますので、HomebridgeはMosquittoとやりとりします。Mosquittoとのやりとりには、以前こちら

diysmarthome.hatenablog.com

で紹介したMqttthingを使うことも可能です。ただ、Zigbee2MQTTが出すMQTTメッセージに特化したプラグインがあるので、それを使ったほうが楽です。Homebridge z2mというプラグインで、Mqttthingを元に、Zigbee2MQTT向けに機能拡張されたプラグインだそうです。

z2m.dev

このプラグインの設定項目はほとんどありません。上で設定したMQTTブローカーのアドレスやbase topicなどを設定するだけです。他は全部未設定でokです。あとはZigbee2MQTTが検出したデバイスが自動的にHomeKitアクセサリとして現れるようになります。

以前に紹介したZigbeeバイスに関しては以下をご覧ください。いずれも今回の設定で、HomeKitから動かしています。

diysmarthome.hatenablog.com

diysmarthome.hatenablog.com

diysmarthome.hatenablog.com

diysmarthome.hatenablog.com

MQTTで設定する

Zigbee2MQTTは、MQTT経由で、いろいろな機能を提供しています。たとえば動作のすべての情報が、MQTTに流されているので、これをmosquitto_subコマンドでサブスクライブすれば確認できます。

mosquitto_sub -h localhost -t zigbee2mqtt/# -v

これにより、Zigbeeバイスをペアリングする場合、Zigbeeスイッチをon/offする場合など、その都度メッセージが表示されるので、動作確認ができます。

Zigbee2MQTTに対する命令も、mosquitto_pubで指示できます。たとえば、とあるidのZigbeeバイスのペアリングを外したい場合は、以下のようにします。

mosquitto_pub -h localhost -t zigbee2mqtt/bridge/request/device/remove -m '{"id":"0x9999999999999999"}'

ただ、次に説明するwebインタフェースの方が簡単です。MQTT経由での確認や操作は、あまり必要ないかもしれません。

Webで設定する

先のconfiguration.yamlファイルでfrontend: trueと設定しました。この設定により、webからの操作が可能になってます。デフォルトではポートが8080です。Webブラウザから、Zigbee2MQTTが稼働しているIPアドレスを指定して、http://192.168.xxx.xxx:8080/でアクセスします。するとZigbee2MQTTの動作確認、操作のためのページが以下のように表示されます。

いろいろな機能がありますが、GUIなので、操作を試して理解できます。

たとえば、上で、MQTT経由で試みたデバイス削除操作は、この画面のゴミ箱ボタンから可能です。ゴミ箱ボタンを押すと、下のようなダイアログパネルが出ます。

オプションのスイッチ、Force removeとBlock from joining againは重要です。まず、Zigbee2MQTTでのデバイス削除操作は、デフォルトでは、デバイスが接続している時のみ可能です。接続していないデバイスも、強制的にペアリング解消するスイッチがForce removeです。Force removeしても、またそのデバイスからの電波が届くと、通常はペアリング再開します。それも阻止するのがBlock from joining againボタンです。これらのスイッチを使ってペアリング解除したデバイスは、デバイスをリセットする操作(ボタンを長押しするとか、何回かon/offを繰り返すなど)をして、ペアリングモードに戻してから、他のシステムで再利用することになります。

また、右上のPermit join (All)のメニューは、ペアリングを開始するメニューです。先のconfiguration.yamlで、permit_join: trueという指定をすると、Zigbee2MQTTが常時ペアリングする設定になります。デフォルトではpermit_join: falseで、ペアリングしません。それを一時的にペアリング可能状態にするのがこのメニューです。クリックすると5分間有効になります。その状態で、ペアリングモードにしたデバイスを近づければ、ペアリングされます。 

Dashboardメニューを選べば、それぞれのデバイスの状態を見て、操作が可能です。

また、Mapメニューを使うとデバイスの接続状態を見ることができます。

この例では、デバイスが少なく、end deviceしかありません。routerになるデバイスがあるとZigbeeのメッシュ接続の様子がわかって面白いです。電球などの消費電力に制約のないデバイスが電波を中継するルータになってくれます。

Zigbee2MQTTを更新する

対応するZigbee製品は増え続けているので、時々アップデートしたいところです。手順は公式ページのここに書いてあります。

# Zigbee2MQTTを停止する
sudo systemctl stop zigbee2mqtt
cd /opt/zigbee2mqtt

# 設定情報をバックアップする
cp -R data data-backup

# 更新する
git pull
npm ci

# 設定情報を復帰する
cp -R data-backup/* data
rm -rf data-backup

# Zigbee2MQTTを始動する
sudo systemctl start zigbee2mqtt

data以下をバックアップしておけば、ペアリング情報や設定状態は保存しておけるようです。

まとめ

Zigbee2MQTTを使って、市販のZigbeeバイスをHomeKitから使うための設定手順をまとめました。これで、市販されている大半のZigbee対応製品を、HomeKitから使用できるようになります。

Zigbeeは、WiFiと比較すると省電力にもかかわらず、メッシュネットワークを構成するので、広い範囲をカバーできます。BLEも似た特徴を持ちますが、安定性や応答速度などでZigbeeの方が優れているような印象があります。これからはZigbeeはThreadに移行していくらしいですが、物理層データリンク層Zigbeeと共通なので、低電力で応答の良いという特長は引き継がれると思います。

Nature RemoをHomebridge / HomeKitから使う

ネットから操作できる赤外線リモコンNature RemoをHomeKitから使えるように設定します。クラウド経由の設定と、ローカルAPIを使った設定の2種類の方法があります。

Nature Remo製品案内

Natureは日本(横浜市)の会社で、ネットからコントロールする赤外線リモコンユニットNature Remoを作ってます。いくつか製品がありますが、Nature Remo mini 2が一番安価で良いかと思います。

類似のネット接続リモコンはこの他にも多数出回ってます。Tuyaのソフトで動く廉価な製品もあります。

diysmarthome.hatenablog.com

これに比べるとNature Remoは高価ですが、日本の製品にきめ細かに対応しているとのことです。今回試したところでは、Tuyaの格安リモコンでも家のエアコンは操作できました。でも、場合によってはNature Remoじゃないと操作できないこともあるらしいです。また、Nature Remo mini 2には温度センサがついていますが、格安リモコンにはついていません。

赤外線制御の照明器具は絶滅危惧

今回、HomeKitから操作できるようにした器具は、シーリングライト(天井照明)とエアコンです。天井照明は、Amazonで売っている格安のLEDシーリングライトです。赤外線リモコンを使用する製品です。

確認したところ、今回使用した照明器具は、もはや販売されてませんでした。他に赤外線を使用しているらしい製品は、たとえばこんな製品です。

     

最近の照明器具では、赤外線リモコンがBLEに置き換わりつつあるようです。 BLEにしておけば、スマホからの操作が可能になり、スマホ用のリモコンアプリも簡単に提供できます。

Nature Remoは赤外線を送出する製品なので、電波を使うBLEリモコンは使用できません。なので、赤外線リモコンを使用する製品を選ぶ必要があります。困ったことにほとんどの販売ページでは、リモコンが赤外線式なのかBLE方式なのか記載がありません。リモコンにLEDらしきものが付いていても、それは動作確認用のLEDで、実際の通信はBLEという場合もあります。注意が必要です。

ちなみに、上位機種のNature Remo 3はBLEにも対応しているらしいです。ただし赤外線学習リモコンのようにどんなBLE製品でも登録できるわけではなく、対応している少数の製品だけが対象です。BLEで接続できても、上位のプロトコルが各社でバラバラなのですね。近い将来には、Matter + Threadで統一されていくのかと思います。

スマホアプリでリモコンを登録

HomeKitの設定をする前に、まずは、Nature Remoを通常通り設定します。スマホアプリ、Nature Remoをダウンロードして、手持ちの赤外線リモコンを登録します。今回は、以下の2個のリモコンを登録しました。

  • 天井照明リモコンのon/offボタン
  • エアコン

天井照明は、照明器具付属のリモコンをNature Remoに向けて、on/offボタンを学習させました。エアコンは、アプリの指示に従って赤外線リモコンを操作すると、メーカを自動検出してくれました。これで問題なく登録できました。

バイス登録の結果、Nature Remoアプリの画面は以下のようになりました。照明ボタンをタップすると、シーリングライトがon/offを繰り返します。エアコンをタップすると、on/off、動作切り替え、温度設定、風量調整、風向調整が可能になります。

クラウドの役割

Nature Remoの機能は、ほぼクラウドが担当してます。Nature Remoは、クラウドから送られたパターンの赤外線信号を送出していると思われます。エアコンを赤外リモコンで操作する場合は、登録したメーカに合わせて、温度、風量、風向などを総合した長い赤外線信号を組み立てる必要があります。おそらくそれはクラウドが全てやってくれて、最終的に発信すべき赤外線信号がNature Remoに伝えられるのだと想像してます。

Amazon AlexaGoogleのスマートスピーカとの連携もクラウドが担当しているようです。HomeKitは、基本的にクラウドに依存しないプロトコル(HAP)なので、連携が難しいのかサポートされてません。NatureのiPhoneアプリはショートカット対応しているので、Siriからショートカット経由でコントロールすることは可能です。HomeKitで使えないのは残念です。

Cloudからトークンを取得する

そこでHomebridgeの出番です。HAPで受け取った指示に従って、Natureのクラウドにアクセスするプラグインを用意すれば、HomeKitからNature Remoをコントロールできます。

そのためにはまずNatureクラウドへアクセスするためのトークンを入手します。Tuyaのリモコンで行ったように、Natureの特別なページにアクセスします。そこでトークンを生成してもらいます。アクセスするページは以下です。

home.nature.global

このページのLoginボタンを押して、

スマホアプリに登録したメールアドレスを入力すると、メールが来ます。

メールに書かれたアドレスにアクセスし、「許可する」ボタンを押します。

そうすると、アクセストークンを新たに作成したり、消去したりできるページが現れます。生成したアクセストークンは二度と表示されないので、必ずコピーしておきます。

使わなくなったトークンはRevokeボタンを押して消すこともできます。以下のサンプルではこの長いトークンを$TOKENとして表記します。あとはNature社のwebサーバにアクセスすることで、必要なすべての処理が可能です。まずは登録情報を確認します。以下の長いcurlコマンドを発行します。

% curl -H "Authorization: Bearer $TOKEN" -H "accept: application/json" "https://api.nature.global/1/appliances"

すると長いjson形式のテキストが返ってきます。このままでは読みにくいので、jqコマンドに渡して、さらにlessして表示を止めておきます。jqコマンドは、ベタ書きされたjsonテキストを、見やすくフォーマットして表示します。macOSには入っていないのでbrewコマンドなどでインストールします。Raspberry Piには入ってました。何かと一緒にいれたのかもしれません。

% curl -H "Authorization: Bearer $TOKEN" -H "accept: application/json" "https://api.nature.global/1/appliances" | jq | less

Cloudに信号IDを送る

上のcurlコマンドで得た情報の中から、照明のボタンに割り当てた信号のIDを探します。器具の名前を「照明」として、照明のアイコンをつけて、ボタンには「オン」という名前がついてました。それらしきところを見ると、「オン」のボタンに割り当てられたIDがわかります。下のxxxxで書いた部分です。

    "model": null,
    "type": "IR",
    "nickname": "照明",
    "image": "ico_light",
    "settings": null,
    "aircon": null,
    "signals": [
      {
        "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "name": "オン",
        "image": "ico_on"
      }
    ]

このIDを利用して、curlコマンドでクラウドに依頼して、Nature Remoから赤外線信号を送出させることができます。

% curl -H "accept: application/json" -H "Authorization: Bearer $TOKEN" -X POST "https://api.nature.global/1/signals/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/send"

これでシーリングライトがon/offします。

CloudからデバイスIDを得る

上のスマホ画面スクショで示したように、現在「Myhouse Office」という場所に照明とエアコンの2個のデバイスを登録しています。先のcurlコマンドで得たjson情報の最上位の部分を見ると、登録されたデバイスが要素になった配列になっています。

[ {照明の情報}, {エアコンの情報} ]

それぞれの情報の部分にidという変数名があります。エアコンのidは、エアコン情報が書かれた部分の最初の方に見つかります。

  {
    "id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
    "device": {
      "name": "Myhouse Office",

このidは、次のセクションで、Homebridgeを使用するために必要になります。

照明をHomebridgeに追加する

まずは「照明」をHomeKitに追加します。Homebridgeのプラグインのタブで、natureという名前で検索すると、Nature Remo用のプラグインが多数表示されます。現時点で24個ありました。日本の製品なので日本の方が作ってくれているプラグインがほとんどです。皆さんに感謝です。

「照明」を使用するために、この中からhomebridge-nature-airconを使わせていただくことにしました。

github.com

他にも、シーリングライトのためのプラグインが多数あります。シーリングライトによっては、リモコンボタンを押すと明るい点灯-->暗い点灯-->消灯と変化するものもあります。その場合、消灯-->明るい点灯には1回押し、明るい点灯-->消灯には2回押しする必要があります。その回数を設定できるプラグインもありました。また点灯・消灯をNature Remo 3の照度センサで判定するプラグインもあります。今回のプラグインは、一番シンプルなものです。

インストールするとaccessoryとnameの設定項目だけ追加されますので、これに、access_tokenとsignal_IDの項目を追加して設定します。access_tokenは、上記で調べた$TOKENの値です。signal_IDも、上で調べたxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxの値です。

設定を保存して、Homebridgeを再起動するとiPhone, Macのホームに照明が現れます。

   

クリックするとシーリングライトがon/offします。ただ、on/off状態を把握できていないので、逆の動作になっている場合もあります。そのような場合は、リモコンから一回on/offすれば同期します。もちろん、またズレるかもしれません。

エアコンをHomeKitに追加する

今度はエアコンを追加します。Homebridgeのプラグインの中から、homebridge-nature-airconを使わせていただくことにしました。

www.npmjs.com

ここまで準備が終わっていれば、プラグインの設定は簡単です。accessTokenの場所に、上で説明した$TOKENの文字列を書き、airconIDの場所に、これも先ほど入手したid(yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyyの部分)を書きます。

これを保存し、Homebridgeを再起動すれば、iPhoneMacのホームにエアコンが現れます。

これをクリックするとon/offします。詳細を開ければ、運転切り替え、温度設定が可能です。Nature Remoには温度センサが搭載されているので、現在の室温も表示されます。

ローカルAPIを使う

ここまではNatureのクラウドを利用していました。NatureはNature RemoのローカルAPIを公開しています。ローカルAPIを利用すれば、LAN内からNature Remoにhttpで接続して操作可能です。インターネット上のクラウドを使用しないので、Natureのサイトが止まってもリモコンを動かすことができます。応答速度も速いはずです。公式の案内ページは以下です。

local-swagger.nature.global

これによると、Bonjourの仕組みを使ってIPアドレスを取得できるようです。まずはdns-sd -BコマンドでInstance Nameを取得します。次にその名前を使ってdns-sd -Gコマンドで数値のIPアドレスを取得します。以下の太字の部分が入力するコマンドです。

% dns-sd -B _remo._tcp
Browsing for _remo._tcp
DATE: ---Fri 28 Oct 2022---
20:15:44.225  ...STARTING...
Timestamp     A/R    Flags  if Domain           Service Type         Instance Name
20:15:45.450  Add        3   4 local.           _remo._tcp.          Remo-XXXXXX
^C
% dns-sd -G v4 Remo-XXXXXX.local
DATE: ---Fri 28 Oct 2022---
20:16:13.033  ...STARTING...
Timestamp     A/R  Flags         IF  Hostname               Address                 TTL
20:16:13.034  Add  40000003       4  Remo-XXXXXX.local.     192.168.xxx.xxx         120
^C

これで、アドレス名がRemo-XXXXXX.localで、数字のIPアドレスは192.168.xxx.xxxであることがわかりました。このアドレスに、赤外線の信号パターンを送れば、それを発信してくれます。問題は、信号パターンをどうやって知るかです。

方法の一つが、Nature Remoの学習リモコン機能を使う方法です。まずは、赤外線リモコンをNature Remoに向けて学習させます。ここでは、シーリングライトのリモコンをNature Remoに向けて、そのon/offボタンを押しました。学習完了するとNature Remoの青いリングが点滅します。その直後に、ターミナルから以下のコマンドを発行します(太字部分です)。その結果、赤外線パターンを示す情報が得られます。

% curl http://Remo-XXXXXX.local/messages -H "X-Requested-With: local" 
{"format":"us","freq":40,"data":[6830,4629,283,573,283,1409,286,569,286,1426,259,573,291,1399,259,597,283,1409,258,597,285,1408,282,573,281,579,285,1401,280,1407,283,1405,281,1409,310]}

アドレス部分には文字の名前を使いましたが、数字のアドレスでもokです。文字の名前は応答が悪いことがありました。数字のアドレスの方が確実です。

リモコンのデータが判明したので、次にこれを送信してみます。以下のコマンドです。

% curl -XPOST http://Remo-XXXXXX.local/messages -H "X-Requested-With: local" -d '{"format":"us","freq":40,"data":[6830,4629,283,573,283,1409,286,569,286,1426,259,573,291,1399,259,597,283,1409,258,597,285,1408,282,573,281,579,285,1401,280,1407,283,1405,281,1409,310]}'

この結果、点灯しているシーリングライトが消灯します。もう一度発行すれば点灯します。

リモコンコードを解析する

リモコンコードを解析してみました。ただ、これは手元のシーリングライトのリモコンのコードなので、他の方には何の参考にもならないです。

数字の配列部分は、おそらくは信号パターンの1, 0の持続時間を列挙していると思われます。データの部分を、試しに280の倍数にして、以下のようにしてみたのですが、同様に動作しました。

% curl -XPOST http://Remo-XXXXXX.local/messages -H "X-Requested-With: local" -d '{"format":"us","freq":40,"data":[7000,4760,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,560,280,1400,280,1400,280,1400,280,1400,280]}' 

280,560が0で、280,1400が1の位相変調だと考えると、0101010101001111というビット列にも見えます。ちょうど16ビットなので正しそうです。ちなみに、リモコンにはCH1とCH2というボタンがあって長押しするとチャンネルが切り替わるのですが、現在はCH2でした。CH1に切り替えると、on/offボタンのビット列が1010101010011111となりました。チャンネルを切り替えると、時系列で最初の8ビットが全部反転するようです。

リモコンには他に、常夜灯、明るく、暗くというボタンがあるのですが、それぞれの後半8ビットのビット列は、11011111, 01100111, 11001101でした。

まとめると、ビット列がMSBから流されるとして、16進数で表した場合

  • 0xAA4F: CH1のon/off
  • 0xAADF: CH1の常夜灯
  • 0xAA67: CH1の「明るく」
  • 0xAACD: CH1の「暗く」
  • 0x554F: CH2のon/off
  • 0x55DF: CH2の常夜灯
  • 0x5567: CH2の「明るく」
  • 0x55CD: CH2の「暗く」

でした。

ローカルAPIをHomeKitで使う

次にローカルAPIをHomeKitから使えるように設定します。ローカルAPIを使うプラグインがあったのでそちらを使ってみました。このプラグインです。

www.npmjs.com

でも、[NatureRemo] No Nature Remo device foundというエラーメッセージが出てしまいました。Bonjourに失敗しているのかもしれません。

HomeKitのプラグインにはシェルコマンドを実行するプラグインもあります。次善の策としてそれを利用して、上記のcurlコマンドを実行すれば良いと考えました。homebridge-shell-switchという名前のプラグインです。

github.com

インストールして、configの部分に以下のように設定しました。

{
    "accessory": "ShellSwitch",
    "name": "ShellSwitch",
    "onCmd": "myswitch.sh",
    "offCmd": "myswitch.sh",
    "stateful": true
}

onCmdとoffCmdには、onとoffを行うときに実行すべきシェルコマンドを書きます。トグルスイッチなので同じmyswitch.shというシェルスクリプを名を書きました。ここにcurlコマンドを直接書いても良いかと思いましたが、うまく実行できませんでした。シェルの実行環境などの関係かと思います。引用記号を逆スラッシュで無効にすることに失敗しているのかもしれません。そこで、以下のようなシェルスクリプトを書いて、これを/usr/local/bin/myswitch.shにおきました。それをconfigに書いたonCmdとoffCmdで実行します。

#!/bin/sh
curl -XPOST http://192.168.xxx.xxx/messages -H "X-Requested-With: local" -d '{"format":"us","freq":40,"data":[7000,4760,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,1400,280,560,280,560,280,1400,280,1400,280,1400,280,1400,280]}'

 Homebridgeを再起動すると、PhoneとMacのホームに以下のように現れます。

   

(追記) ローカルAPIを使う他のプラグイン

追記です。上で紹介したhomebridge-nature-remo-localがうまく動かなかったと書きました。デバイスが発見できなかったようです。探したところ、IPアドレスを直接各方式の、ローカルAPI対応プラグインがありました。こちらです。

github.com

これも日本の方が作ってくれているようで、gitの説明も日本語です。複数の機器のコントロールマルチタスクで行うような機能もあるようです。一番シンプルに使うなら、

{
  "accessory": "remo",
"name": "Light", "host": "192.168.xxx.xxx", "command": { "power": { "format": "us", "freq": 40, "data": [7000,4760,280,560,280,1400,280,560,280,1400,280,560, 280,1400,280,560,280,1400,280,560,280,1400,280,560,280,560,280,1400,280,1400,280,1400,280,1400,280] } }, "on": [ "power" ], "off": [ "power" ] }

のような設定で良いようでした。

クラウドとローカル

これでローカルAPIを使ってシーリングライトをon/offできます。クラウドを使用しないので、クラウドやネットワークが不調でも動作しますし、応答速度も高速なはずです。また、クラウド仕様には、5分間に30回までの制限があります。デバッグなどで何度も使っていると、しばらく応答しなくなってしまいます。ローカルで使用する場合は、この制約は無関係です。

ただ、ローカルAPIを使用するためには、上記のように赤外線信号タイミングを用意する必要があります。エアコンのように、設定温度や風量・風向なども含めてコマンドが複雑になる場合は簡単ではありません。複雑な赤外線タイミングが必要な操作はクラウドの任せるのが良いと思います。ローカルAPIは、シンプルなリモコン操作に適していると思います。

リモコンの限界

赤外線リモコンはコマンドを送出しているだけで、機器の状態を把握できていません。なので、HomeKit側では、赤外線信号が正しく受信されたと仮定して、現在の状態を推定することしかできません。なので、他のリモコンで操作されたり、シーリングライトのように壁スイッチで操作されると、実際の状態と乖離してしまいます。エアコンリモコンのコマンドに、設定温度・風量・風向などの情報が全て含まれているのも、リモコン上の表示を実際エアコンの状態にできる限り合わせたいためです。

さらには、今回使用したシーリングライトのリモコンのように、on/offがトグルで動作するタイプもあります。この場合は、ライトが点灯しているか、消灯しているかを推定することもできません。

HomeKitが正しく状態把握するためには、機器と双方向に通信して、現在の状態を問い合わせできる仕組みが理想です。その点で赤外線リモコンは不完全です。エアコンならば、WiFiで通信するような仕組みを利用したいところです。シーリングライトは、壁スイッチをスマートスイッチにして、人手による壁スイッチ操作もシステムで把握できるようにするのが良いです。壁スイッチを自動化する記事はこちらをご覧ください。

diysmarthome.hatenablog.com

まとめ

Nature RemoをHomeKitで使う方法を説明しました。Natureのクラウドを使う方法と、ローカルAPIを使う方法があります。クラウドを使う場合は、NatureのサーバからトークンやID情報を入手して設定します。ローカルAPIを使う場合は、赤外線パターンを学習昨日により取得し、Nature Remoにhttp送信します。赤外線リモコンを使えば機器の操作が容易ですが、実際の状態を把握できない欠点もあります。

追記

この後、スマート赤外線リモコンをDIYしました。赤外線LEDを取り付けたESP32で動作して、HomebridgeとはMQTT経由で通信します。以下の記事をご覧ください。

diysmarthome.hatenablog.com

diysmarthome.hatenablog.com

diysmarthome.hatenablog.com

diysmarthome.hatenablog.com

クラウドが止まった時のスマートホーム

インターネット接続しているケーブルを引き抜いて、外部接続が停止した時のHomeKit動作を確認しました。外部接続が遮断されても、HAPで接続するHomeKitアクセサリ類は動きます。また、MQTT・Zigbee・BLEで接続するアクセサリも動作しました。クラウドサービスを参照するアクセサリは動かなくなりました。

クラウドの利点・欠点

スマートホームの機器には、インターネット上のサーバで動いているクラウドサービスを利用するもの、利用しないもの、どちらも可能なものがあります。家の外から機器をコントロールすることを考えると、クラウドを利用する方が設定が楽で安全です。また自社のエコシステムへの囲い込みも容易になります。なので多くの機器が、メーカが用意したクラウドサービスを利用する方式で設計されてます。

Home Assistantを作った人たちは、これに異を唱えて、自分の家の機器は自分の家のサーバで制御すべきだと言ってます。実際に、クラウドサービスが終了してしまい、機器が使用できなくなる事例が多数あることから、クラウドを避けたい気持ちには共感します。

wired.jp

kaden.watch.impress.co.jp

クラウドが終了する事態にならなくても、不調だったり、遅延することも多いので、全部自前で揃えるメリットは大きいです。

ただ、家の外から安全にアクセスできる段階まで自前で設定するのは大変です。できる限りローカルに動作させつつ、外部からの接続に関してだけは信頼できるクラウドサービスを使うのが最適解ではないかと思います。Home Assistantも関連会社が有料のクラウドサービスを運営しています。

HomeKitを使っている場合は、Appleの信頼できるクラウドサービスを無料で使用できます。HomeKitでは、家庭内からの機器制御はローカルに実行可能で、外からの制御にはクラウドを使用する使い分けがうまく取り込まれています。

今回はインターネットへの接続を一時的に切断して、スマートホームのどの部分がクラウドに依存しているか、実感したいと思いました。

HomeKit実験環境

クラウド依存を実験した機器の構成は以下です。

「ホームサーバ」(HomeKitで外部接続を担当するサーバ)としてHomePod miniを使用しています。HomeKit対応デバイスは、Merossのスマートプラグだけです。HomeKit非対応機器をHAP (HomeKit Accessory Protocol)接続するために、Homebridgeを稼働させています。同じマシンで、MQTTブローカーとZigbee2MQTTが動いています。Tuya, Nature, SwitchBotのデバイスも、Homebridgeに接続しています。このうち、TuyaとNatureのプラグインは、それぞれの会社のクラウドサービスが提供するAPIを使用しています。SwitchBotに関しては、ローカルなBLE接続で制御しているので、クラウドを使用していません。

HomePod: Siriは動かないけどサーバは稼働

この状態で、インターネット接続を遮断しました。具体的には、インターネットプロバイダに接続しているケーブルをルーターから抜きました。

この結果、まずはHomePodのSiriは動かなくなりました。Siriへ呼びかけすると「インターネット接続されていない」という内容の返事を返します。Siriの本体はクラウド上にあるので、動かなくなって当然です。HomePodは外出先からの接続も担当しています。外部接続を遮断したので、当然ですが外部接続も不可能になっているはずです。

一方、HomePodは、例えば「センサに反応があったら照明を点灯する」というような、オートメーションやアクションも管理しています。オートメーションやアクションをiPhoneMacに任せることはできません。必ず家にあって、常時稼働しているデバイスが対応する必要があります。そこで、HomePodやAppleTVがホームサーバとして、オートメーションやアクションを担当しています。この機能は、外部接続が遮断されても動いていました。

HAP機器は動く

HAP接続している機器(ここではMerossのスマートプラグ)は、問題なく安定して稼働しました。HomeKitは、クラウドがなくても機器を操作できるということがメリットであると聞いたことがありますが、それを確認できました。

Homebridgeは要調整

想定外だったことは、Homebridgeが動かなくなったことです。それも、インターネット切断した直後は動作していて、ZigbeeやMQTT経由のデバイスが正しく稼働してました。それが一つ一つ徐々に反応しなくなり、最後には全て「応答なし」の表示になってしまいました。Homebridge接続のセンサ類も応答なくなりました。HAPデバイスのスマートプラグだけは健気に動いています。

Homebridgeのwebインタフェースを開いて、そこのエラーメッセージから、原因を特定できました。Nature Remoのプラグインが、Natureのサーバーに接続しようとして失敗しているのですが、その結果、Homebridgeにシグナルを送って再起動させているようでした。Homebridgeが再起動を繰り返しているために、ブリッジとしての機能が果たせていませんでした。そこで、Nature Remoのプラグインを停止したところ、Homebridgeは正常に機能再開しました。この結果、スマートホームの多くの部分が復旧しました。

MQTTとZigbeeは動く

Homebridgeが動作したので、MQTT経由でWiFi接続していた自作のESP32類が動くようになりました。またZigbee2MQTTで接続しているセンサ類、照明、壁スイッチなどが全て動くようになりました。センサ類・スイッチ類の動作に紐付けされる機器操作(「スイッチを入れると照明が点灯する」などのアクション)は、HomePodが管理していますが、これも動作します。

BLEも動く

BLEで接続しているSwitchBot製品も動きました。SwitchBot社のクラウドAPIを使用しておらず、内部のBLE接続だけを使用しているので、インターネット接続が不通になっても、問題なく動きます。

クラウド連携機器は動かない

動作しなかったのは、予想通りTuyaとNatureの機器です。どちらもそれぞれの会社のクラウドAPIを使用しているので、外部接続がないと使用できません。

まとめ

インターネットへの接続を外しても、引き続き動作するデバイスを確認しました。その結果、クラウドAPIを使うTuyaとNatureの機器を除いて、動作を確認できました。家にあるデバイスの8割以上は外部接続ができなくても動作する感じです。また、外部接続ができない場合に、停止しなければならないHomebridgeプラグイン (Natureのプラグイン) があることも確認できました。クラウドサービスが停止したり終了した場合や、何かの理由でインターネット接続できなくなった場合のシミュレーションにもなりました。