公衆MQTTサーバでLチカする

HomeKitを使う

スイッチやセンサの状態や、リレーやサーボモータの制御コマンドを送受信する目的で、MQTT (Message Queueing Telemetry Transport)というプロトコルが使われます。MQTTは、Home AssistantやHomebridgeでもサポートされていますし、Arduinoでも使えるので、スマートホーム自作に活用できます。通常は家の中にMQTTサーバー(MQTTの用語ではブローカーと呼ぶので以下ではブローカー)を用意して使用しますが、インターネット上にも試作・実験で誰でも使える公開ブローカーが用意されてます。

今回は、そんな公衆MQTTブローカーを使って、ESP 32に接続したLEDをHomeKitから点滅(Lチカ)させます。以下の経路で接続します:

  1. LEDを接続したESP 32
  2. ESP 32をMQTTに接続するライブラリ: EspMQTTClient
  3. Eclipse Projectの公衆MQTTブローカー
  4. Homebridge + MQTTプラグイン
  5. iPhoneやMacのホーム.app

MQTTの使われ方

例えば、ArduinoやESP 32で無線スイッチを作って、人がon/offしたことをLAN経由で他のコンピュータに伝える仕組みを考えてみます。ソケット通信のライブラリを使って他のコンピュータにスイッチの状態を伝えるのが簡単で効率が良いのですが、プログラムを起動する手順が面倒です。Arduinoに簡単なWebサーバーのような応答をさせて、スイッチ状態をHTTPで送る方法もあります。下の写真はHTTP経由でLEDを点灯するLチカの例です。

https://i0.wp.com/randomnerdtutorials.com/wp-content/uploads/2018/07/esp32-we-server.jpg

( こちらから転載 )

この場合、コントロールするために普通のWebサーバやcurlコマンドも使えて便利です。でもHTTPは送りたいデータ以外にお約束のテキストを色々転送する必要があるので、せいぜい数バイトしか送る必要がないIoT的な用途には無駄(オーバーヘッド)が多いです。もともと制御用のプロトコルじゃないので、on/offの表現方法も自由過ぎて標準化が必要です。

そこでMQTTが使われます。短いメッセージを効率よく伝える用作られたIoT向きのプロトコルです。MQTTを使う場合、MQTTブローカーというサーバを別途用意して、それにデータ送信側と受信側がクライアントとして接続します。

手順には、雑誌や新聞の出版と購読をメタファーにした名前がついていて、サーバコンピュータは書籍取次業者(ブローカー)として機能します。データを送信したい側は、雑誌名・新聞名に相当するトピック (topic) に適当な名前をつけて、送りたいデータをメッセージ (message) として「出版 (publish) 」します。データを受信したい側は、雑誌名・新聞名であるtopicを指定して、「購読 (subscribe)」しておくと、送信側からデータがpublishされたときに、これをmessageとして受け取れます。

例えば、上の図のように、on/offスイッチ側がswitchというトピックを指定してoffという文字列をパブリッシュすると、switchをサブスクライブしている他のコンピュータにそれが伝わります。そのコンピュータでHomebridgeとMQTTプラグインが動いていれば、このon/offスイッチをHomeKitのアクセサリとして扱えます。

MQTTをインストールする

MQTTのソフトウェアを提供するオープンソースプロジェクトにはいろいろあるようですが、Mosquittoが定番の一つのようです。なのでこれを使います。Mosquitto一式をRaspberry Pi OSやUbuntuなどにインストールするには、

sudo apt install mosquitto mosquitto-clients

とします。MQTTクライアントのみで、ブローカを動かさないなら、mosquitto-clientsだけで良いです。Windows用もあります。個人的にはDOS窓はあまり好きではないので、WSLでUbuntuを使うのが良いのではと思います。その場合、Ubuntuのシェルウィンドウからaptコマンドで取り寄せます。

macOSの場合は、homebrewを使って以下のようにインストールします。

brew install mosquitto

これでMQTTブローカーにアクセスする2つのコマンド、mosquitto_subとmosquitto_pubコマンドが使えるようになります。

公衆MQTTブローカーを使ってみる

スマートホームで使うMQTTブローカーは、自宅で稼働させて、自家用に使うのが一般的だと思います。ただ、自前でサーバを建てたりメンテするのが煩わしいという人のために、インターネット上でMQTTブローカーを提供するサービスもあります。Mosquittoを作っているEclipse Fundationというところは、mqtt.eclipseprojects.ioというIPアドレスで、無料MQTTブローカーを提供してます。誰でもすぐに使えます。

(修正:今試したら、eclipseprojectsのブローカーが止まってました。broker.hivemq.com というところは動いていたので、こちらも試してください。)

例えば、

mosquitto_sub -h mqtt.eclipseprojects.io -t #

とするとものすごい量のデータが流れてきます。コントロールCで止めてください。(修正:改めて試したら-t #の指定ができませんでした。仕様が変わったのかもしれません。)

-hがアドレス、-tがトピック名を表します。トピックの設定で#を使うと、全部の文字に合致する意味になるので、このブローカーに流れている全てのメッセージが表示されます。世界中の人たちがこのブローカーを使ってテストしている様子がわかります。

それっぽい名前のトピック、例えばtestとかsensorで始まるトピックに限定してみると、この記事を書いた時点では次のような情報が現れました(testの場合)。

mosquitto_sub -h mqtt.eclipseprojects.io -t test/# -v
test/dht11/temp_c 24.50
test/dht11/temp_f 76.10
test/dht11/humidity 53.00

トピックは任意の文字列なのですが、慣例としてスラッシュで区切って階層的に使います。-tで指定したtest/#というパラメータの意味は、test/で始まる全てのトピックという意味です。また-vオプションは、メッセージだけでなく、それのトピック名も表示するという意味です。その結果、誰かがtest/dht11/の名前で温度と湿度のデータを流しているようです。

ではこのMQTTブローカーに、何かデータを流してみましょう。他の人と被らないように、diysmarthomeというトピックをつけて流してみます。まずは、

mosquitto_sub -h mqtt.eclipseprojects.io -t diysmarthome/# -v

でサブスクライブしておきます。別のシェルウィンドウから、

mosquitto_pub -h mqtt.eclipseprojects.io -t diysmarthome -m hello
mosquitto_pub -h mqtt.eclipseprojects.io -t diysmarthome/sw -m on
mosquitto_pub -h mqtt.eclipseprojects.io -t diysmarthome/sw -m off

とパブリッシュすると(-mオプションがメッセージを表します)、サブスクライブ側には、

mosquitto_sub -h mqtt.eclipseprojects.io -t diysmarthome/# -v
diysmarthome hello
diysmarthome/sw on
diysmarthome/sw off

と表示されます。この公衆MQTTブローカーに流れる情報は、誰でも見ることができますし、トピックがバッティングする可能性もありますので、実際のスマートホームの制御には適してません。でも、動作チェックの目的なら十分に使えます。以下で試してみます。

HomebridgeでMQTTを使う

MQTTをHomeKitから使うために、HomebridgeにMQTTプラグインを追加します。HomegridgeにはMQTTを使うプラグインが多数あります。プラグインのページでmqttを検索すると30個見つかりました。

ここではHomebridge Mqttthingというプラグインを使ってみます。このプラグインで、HomeKitで定義されるほとんどのデバイスを作ることができ、その動作をMQTTトピック・メッセージに紐付け設定できます。このプラグインをインストールし、設定画面を開きます。アクセサリを追加するボタンを選び、Light bulb – on/offというアクセサリを作ってみます。名前はMQTT Lightにします。

URLには公衆MQTTブローカーのアドレスを入れておきます。ユーザ名やパスワードは不要なので空白にしておきます。

トピック名も決めておきます。タグで指定された名前そのままの、わかりやすい名前にしておきました。

この結果、configファイルには以下のような記述が書き込まれました。

{
  "type": "lightbulb-OnOff",
  "name": "MQTT Light",
  "url": "mqtt://mqtt.eclipseprojects.io",
  "topics": {
    "getOnline": "diysmarthome/getonline",
    "getOn": "diysmarthome/geton",
    "setOn": "diysmarthome/seton"
  },
  "accessory": "mqttthing"
}

Homebridgeを再起動すると、iPhoneやMacのホーム.appにこのアクセサリが現れます。

このアクセサリを操作する前に、Ubuntu, Windows, Macなどのシェルウィンドウで以下のコマンドを動かしておきます。

mosquitto_sub -h mqtt.eclipseprojects.io -t diysmarthome/# -v

ここで、ホーム.appからこのアクセサリをタップまたはクリックすると、表示はオン・オフするのですが、

  —>  

同時に、実行中のmosquitto_subのコマンドの応答として、以下のような結果が表示されて、

diysmarthome/seton true
diysmarthome/seton false

MQTTブローカーにデータが流れていることがわかります。このプラグインでは、デフォルトではtrue、falseという文字列が流されます(設定で変更可能です)。ホーム.appの操作で、このアクセサリがオンになるとsetonトピックにtrueと言うメッセージが、オフになるとfaseが流れてきます。

では、先ほど設定したgetonの方も試してみます。別のシェルウィンドウから、

mosquitto_pub -h mqtt.eclipseprojects.io -t diysmarthome/geton -m true

とタイプしてみます。ホーム.appの表示がオンになります。また-mとしてfalseを送ると表示がオフになります。

  —>  

ここで実行したmosquitto_sub, mosquitto_pubコマンドに相当するプログラムをArduinoやESP 32の上に書けば、on/off型の電球の動きをするアクセサリが作れるわけです。

MQTTでLチカする

ここで作ったMQTT Lightに応答するアクセサリを、ESP 32を使って作ります。そのために、Arduino IDEにMQTTを扱うためのライブラリを導入します。Arduino IDEの「ツール」「ライブラリを管理…」からライブラリマネージャを開き、ここでespmqttで検索すると、ライブラリが見つかります。このEspMQTTClientライブラリを使います。

ライブラリのサイトで配布されているサンプルをもとに、以下のように、LEDを点滅させるプログラムを作りました。

#include "EspMQTTClient.h"
EspMQTTClient *client;
const int LED=13; //pin for LED
const char SSID[] = "XXXXXXXX"; //WiFi SSID
const char PASS[] = "xxxxxxxx"; //WiFi password
char CLIENTID[] = "diysmarthome_cv3a2JTs";//unique ID
const char  MQTTADD[] = "mqtt.eclipseprojects.io"; //Broker addr
const short MQTTPORT = 1883; //Broker port
const char  MQTTUSER[] = "";//Can be omitted if not needed
const char  MQTTPASS[] = "";//Can be omitted if not needed
const char  SUBTOPIC[] = "diysmarthome/seton"; //sub topic
const char  PUBTOPIC[] = "diysmarthome/geton"; //pub topic
const char DBGTOPIC[] = "diysmarthome/debug"; //debug topic  

void setup() {
  pinMode(LED, OUTPUT);
  client = new EspMQTTClient(SSID,PASS,MQTTADD,MQTTUSER,MQTTPASS,CLIENTID,MQTTPORT);
}

void onMessageReceived(const String& msg) {
  client->publish(DBGTOPIC, "Message received.");
  if(msg.compareTo("true")==0) {
    digitalWrite(LED, HIGH);
    client->publish(PUBTOPIC,"true");
  }
  else if(msg.compareTo("false")==0) {
    client->publish(PUBTOPIC,"false");
    digitalWrite(LED, LOW);
  }
}

void onConnectionEstablished() {
  client->subscribe(SUBTOPIC, onMessageReceived); //set callback
  client->publish(DBGTOPIC, "Connection established.");
}

void loop() {
  client->loop();
  delay(100);//動作安定のため?効果は不明
}

CLIENTIDは、デバイス固有のIDにしておくべきらしいです。MACアドレスを使うことが多いらしいですが、ここではランダムな文字列を含ませておきました。

onConnectionEstablishedは、MQTTへのコネクションが成立したときに呼ばれる関数のようです。ここで、サブスクライブしたトピックにメッセージが到着したときに呼ばれる関数を、コールバック関数として登録します。

onMessageReceivedは、そのコールバック関数です。サブスクライブしたトピックにメッセージが流されると呼ばれます。メッセージの内容を判断してLEDを点滅してます。

メインloopの100ms遅延は、動作安定のために入れました。これを入れないでフルスピードでclient->loop()を呼び出すと、onConnectionEstablishedが何度も呼ばれてしまいました。インターネットの遅延に対して、接続できなかったと勘違いして再接続している様子でした。それで100ms遅延を入れました。

このプログラムをESP 32にダウンロードして動かすと、iPhoneやMacのホームのボタン操作で、

  —>    —>  

LEDが点滅します(写真は使い回しです)。

mosquitto_subの命令を稼働させておけば、対応するトピックの情報が見られます。

mosquitto_sub -h mqtt.eclipseprojects.io -t diysmarthome/# -v
diysmarthome/debug Connection established.
diysmarthome/seton true
diysmarthome/debug Message received.
diysmarthome/geton true
diysmarthome/seton false
diysmarthome/debug Message received.
diysmarthome/geton false

デバッグのために、/degugと言うトピックを使いました。デバッグメッセージはシリアルポートに流すことが多いですが、こうすると、MQTTで動作状態を確認することができます。

このESP 32のLEDは、mosquitto_pubコマンドからもon/offできます。

% mosquitto_pub -h mqtt.eclipseprojects.io -t diysmarthome/seton -m true
% mosquitto_pub -h mqtt.eclipseprojects.io -t diysmarthome/seton -m false

LEDが点滅するだけでなく、ホーム.appの表示も同期します。

  —>  

まとめ

MQTTブローカーを開発しているEclipse Projectの公衆MQTTブローカーを使って、HomeKitの電球アクセサリを作りました。MQTTはいろいろなIoT機器や関連するサーバーが採用しています。データをモニターするのも楽なので、デバッグも捗ります。

今回は公衆のブローカーを使いましたが、通常はLAN内に設置します。次回は、スマートホームサーバを動かしているRaspberry PiやUbuntuサーバにMQTTブローカーを設置します。

MQTTブローカーMosquittoを設置する
今回はMQTTブローカーをインストールします。MQTTがあると、スイッチ、センサ、リレー、サーボモータなどを接続したArduinoのようなコンピュータを、ネットワーク越しにIP接続したい時にとても便利です。また、MQTTを使うスマートホーム...

コメント

タイトルとURLをコピーしました