昨日構築したArduino環境でESP8266にてMQTTクライアント(MQTT Subscriber/Publisher)を動かしてみます。接続先はInternet上のMQTTサーバ(MQTT Broker)をターゲットにします。ですので、通信路がSSLで保護されるのが最低条件です。
先日インストールしたAdafruit MQTTライブラリでいろいろ試してみたのですが上手く行かず、異なる方法を模索しました。また、その他のライブラリなども検討したり試してみたりしましたが、一長一短で、結構悩みました。
で、たどり着いた方法はこちらのサイトを参考にさせていただいて、 PubSubClient というMQTTクライアントを使いました。(基本的には、記載されている内容そのままです)
まずは「ツール」⇒「ライブラリを管理」を選択します。そして、「PubSub」で検索して「PubSubClient」をインストールします。
インストール後、スケッチ例の PubSubClient の中の mqtt_esp8266 というサンプルプログラムを開きます。
変更箇所は、初めの方の
WiFiClient espClient;
を
WiFiClientSecure espClient; // 接続にTLSを使う
に変更します。また、後半の
setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback);
を
setup_wifi(); espClient.allowSelfSignedCerts(); // 接続先のサーバーのFingerPrintを確認する espClient.setFingerprint(mqttFingerPrint); // 照合すべき値を設定する client.setServer(mqtt_server, 8883); // 接続先のポートを 1883 ⇒ 8883 に変更する client.setCallback(callback);
また、SSL接続時のエラーを表示するため、真ん中やや下の部分を
Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000);
から
Serial.print("failed, rc="); Serial.println(client.state()); // 改行追加 char buf[256]; // SSLエラー表示のためのバッファ確保 espClient.getLastSSLError(buf,256); // エラーメッセージ取得 Serial.print("SSL error: "); // エラーメッセージ表示 Serial.println(buf); // Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000);
に変更します。この少し前にある部分で、
// Attempt to connect if (client.connect(clientId.c_str())) { Serial.println("connected");
を今回はMQTTサーバでパスワード認証をかけているので、
// Attempt to connect if (client.connect(clientId.c_str(),mqtt_user,mqtt_pass)) { Serial.println("connected");
に変更します。
さらに、冒頭の部分に、接続用のパラメータを記述します。
const char* ssid = "接続先WiFiのSSID"; // WiFiの接続先のSSID const char* password = "WiFiのパスワード"; // WiFiの接続用のパスワード const char* mqtt_server = "MQTTサーバのFQDN"; // MQTTサーバーのホスト名 const char* mqtt_user = "MQTTサーバのユーザー名"; // MQTTのユーザー名 const char* mqtt_pass = "MQTTサーバのパスワード"; // MQTTのパスワード const char* mqttFingerPrint = "接続先のフィンガープリント" // ホストのフィンガープリント
フィンガープリントは以下のようにして取得した値です。
~$ openssl s_client -connect MQTTサーバのFQDN:8883 < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin SHA1 Fingerprint=XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
これでESP8266を搭載したボードに書き込んでやると、無事にテストができました。
(シリアルモニタでモニタすると確認できます)
ESP8266からは outTopic に向けて2秒周期でPublishされ続けるとともに、inTopicをScbscribeしています。ですので、別のPC上で
~$ mosquitto_sub -h MQTTサーバのFQDN -t outTopic -p 8883 --capath /etc/ssl/certs/ -u MQTTサーバのユーザー名 -P MQTTサーバのパスワード
として、Subscribeしてやると、MQTTにてESP8266がSubscribeした内容が確認できます。また、別のPC上で
~$ mosquitto_pub -h MQTTサーバのFQDN -t inTopic -p 8883 --capath /etc/ssl/certs/ -m "メッセージ" -u MQTTサーバのユーザー名 -P MQTTサーバのパスワード
で Publish したメッセージを確認できます。また、メッセージの先頭が “1” の場合にはESP-WROOM02が乗った基板に搭載されているLEDが点灯します。”1″以外の場合には消灯しますので、こちらでも確認できます。