How2Homebridge

はじめに

HomeKitのデバイスを、他のコンピュータのコマンドラインから動かす方法を説明します。 Homebridge, Mosquittoを使います。

Raspberry Piの上に、Homebridge, Mosquittoが動いていて、 Appleのホーム.appのにHomebridgeが接続されていて、 パソコン(Mac)の上にMosquittoのクライアント機能がインストールされていることが前提です。 以下のページを見てください。

How2Homebridge

How2MQTT

MQTT Thingプラグインをインストールする

Homebridgeのコントロールページから、プラグインを選び、検索窓にmqttthingとタイプします。するとHomebridge Mqttthingというプラグインが現れます。

mqttt2.png

これをインストールします。 インストールが終わると設定画面が出ます。これはいつでも設定できるのですが、 とりあえず、Stateless Programmable Switchを選んでみます。 また、名前をSwitch1とし、MQTTのタイプ名も適当に入れておきます。 タイプ名は、mqtttで始まるようにしました。MQTTTプラグイン関係であることがわかりやすいかとおもいました。

mqttt3.png

これで保存して、Homebridgeを再起動します(右上方の電源スイッチのようなアイコンを押す)。 再起動後に、アクセサリのタブを見ると、押しボタンスイッチのようなアイコンが見えます。 stateless programmable switchは、テレビのリモコンみたいに押しボタン方式のスイッチです。

mqttt5.png

コンフィグボタンを押すと、Homebridgeの全体の設定が見えます。まだMQTT Thingしか入れてないのでわかりやすいです。

mqttt4.png

このうち、

"accessories": [
        {
            "type": "statelessProgrammableSwitch",
            "name": "Switch1",
            "topics": {
                "getOnline": "mqttt/online",
                "getSwitch": "mqttt/switch"
            },
            "accessory": "mqttthing"
        }
    ],

の部分がMQTT Thingの部分です。このプラグインのページに詳しい説明があります。

https://github.com/arachnetech/homebridge-mqttthing#readme

変更したり書き換えたりする場合は、このコンフィグファイルを編集するのが簡単で良いと思います。 テレビのリモコンのように、多数の押しボタンスイッチをまとめて定義することもできます。 LEDの調光器リモコンのように、on/off/明るさ/色合いなどのスイッチをまとめて定義するのに便利です。 これ以外にも多くの特性を持つデバイスが用意されています。

MQTT Thingで使えるデバイス

ここではstateless programmable switchを使いましたが、他にも多数のデバイスが使えます。

stateless programmable switchは、(HomeKitから見て)入力専用ですが、 Switchは入出力に対応しています。 設定して、mosquitto_subコマンドでモニターすると動きがわかります。 これを使えば、HomeKitからのon/offを受け取ってLEDを光らせるなどの仕掛けをArduinoで作れます。

ホーム.appで設定する

HomebridgeがHomeKit環境に登録してあれば、ここで定義したSwitch1がホーム.appに現れています。

mqttt6.png

このアイコンを右クリックして、「設定」を選ぶと動作をしてできます。

mqttt7.png

1回押し、2回押し(ダブルクリック)、長押しの選択があります。ここでは1回押しで、隣のIkeaの電球、をonにする設定をしました。

mqttt8.png

MQTTへの出版で電球をonにする

今までの設定で、

でした。Switch1には、1回押し、2回押し(ダブルクリック)、長押しの3種類があります。それぞれに対応するメッセージは、1,2,Lです。 これは設定ファイルで変更することも可能ですが、1,2,Lがデフォルトです。 なので、MQTTの出版をすれば、IKEAの電球をonにできます。パソコンから、

% mosquitto_pub -h 192.168.0.134 -t mqttt/switch -m 1

とすれば良いです。他のターミナルのウィンドウから、

% mosquitto_sub -h 192.168.0.134 -t # -v 

として、メッセージをモニターしておくとデバッグに役立ちます。

電球をon/offとトグルする

電球をoffにしたい場合は、2回押しや長押しに電球offを割り当てても良いです。 また、1回押しのたびに反転することもできます。 1回押しに実行されるショートカットを以下のように記述すれば良いです。

mqttt9.png

これで、

% mosquitto_pub -h 192.168.0.134 -t mqttt/switch -m 1

とするたびに、電球がon/offします。

PythonからMQTTブローカにアクセスする

pahoというライブラリを使いました。

https://www.eclipse.org/paho/index.php?page=clients/python/index.php

以下のプログラムでHomeKitで設定された灯を点滅させることができました。

#!/Library/Frameworks/Python.framework/Versions/3.9/bin/python3

import paho.mqtt.client as mqtt     # import MQTT lib.

broker_address="192.168.0.134" 
client = mqtt.Client()              #create new instance
client.connect(broker_address)      #connect to broker
client.publish("mqttt/switch","1")  #publish

ArduinoからMQTTブローカにアクセスする

同じくArduinoからの例です。

https://github.com/knolleary/pubsubclient

にある、pubsubclientライブラリを使ってます。

上のページにあるサンプルを参考にしたプログラムが以下です。 ここでは、13番に接続したスイッチが押された時に、MQTTに1を送ります。それでHomeKitが灯をon/offしてくれるはずです。

元のサンプルは、送受信に対応していたので、subscribeの部分も残ってます。その部分は今回は使っていないです。 HomeKitからの指示でArduinoでLEDを点灯させるなどの場合には、このcallbackの関数のところに、その処理を書けば良いです。。 WiFiの設定もしているので、長いですが、多分これで動きます。

#include <WiFi.h>
#include <PubSubClient.h>

//input & output ping
const int PUSHSW=13; //external push switch

//WiFi
const char SSID[] = "siiolab408_2G";
const char PASSWORD[] = "xxxxxxx";
//PubSubClient (MQTT)
const char mqttbroker[] = "192.168.0.134"; //MQTT broker address
const int mqttport=1883; //MQTT port
const char subtopic[] = "mqttthing/sub"; //mqtt topic to subscribe これは今回使用しません
const char pubtopic[] = "mqttthing/switch"; //mqtt topic to publish 
char clientID[] = "ESP32_xx:xx:xx:xx:xx:xx"; //MAC address is set in setup()
WiFiClient wifiClient; 
PubSubClient mqttClient(wifiClient);

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");Serial.print(topic);Serial.print("] ");
  String msg = String((char*) payload);
  Serial.println(msg); 
}

//connecting MQTT
void connectMQTT() {
  mqttClient.setServer(mqttbroker, mqttport);
  mqttClient.setCallback(callback);
  Serial.println("Attempting MQTT connection. ");
  // Loop until we're reconnected
  while (! mqttClient.connected() ) {
    // Attempt to connect
    if (mqttClient.connect(clientID)) {
      Serial.println("Connected. ");
      // Once connected, publish an announcement...
      mqttClient.publish(pubtopic,"Arduino is ready.");
      // ... and subscribe
      mqttClient.subscribe(subtopic);
    } else {
      Serial.print("Failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(", try again in 5 seconds. ");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

//connecting WiFi
void connectWiFi() {
  WiFi.begin(SSID, PASSWORD);
  Serial.print("Attempting WiFi connection. SSID: "); Serial.print(SSID);
  while (WiFi.status() != WL_CONNECTED) {
      Serial.print(".");
      delay(1000);
  }
  Serial.print("\nWiFi connected. Assigned address is: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  pinMode(PUSHSW, INPUT_PULLUP);
  Serial.begin(115200);        //  ESP standard speed 115200
  while (!Serial) ;            //  wait for serial port to connect.
  String wifiMACString = WiFi.macAddress(); //WiFi MAC address
  wifiMACString.toCharArray(&clientID[6], 18, 0); //"EPS32_xx:xx:xx:xx:xx:xx"
  Serial.print("\nMQTT clientID: ");Serial.println(clientID);
  
  connectWiFi();
  connectMQTT();
}


//last state of the PUSHSW
int lastSWstate;

void loop() {
  
  if( WiFi.status() == WL_DISCONNECTED) 
    connectWiFi();
  if (! mqttClient.connected()) 
    connectMQTT();
    
  mqttClient.loop();

  int newSWstate=digitalRead(PUSHSW);
  if(lastLSWstate!=newLSWstate) { //update only when SW changed
     if(newLSWstate==LOW) mqttClient.publish(pubtopic,"1");
  }
 lastSWstate=newSWstate;
 
  delay(2000);
}

トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS