ESP8266とMQTTを使ったLEDのリモートコントロール

![ESP8266とMQTTを使ったLEDのリモートコントロール](https://assets.emqx.com/images/6fb7c126223dbfab7819eeb40403c65d.png?imageMogr2/thumbnail/1520x684)

[MQTT](https://mqtt.org/)は、IoTメッセージの交換とデータの配信を行うための軽量で柔軟なプロトコルです。IoT開発者にとって、柔軟性とハードウェア/ネットワークリソースのバランスを実現することに専念しています。

[NodeMCU](https://www.nodemcu.com/)はオープンソースのIoTプラットフォームです。Lua言語を使用してプログラミングします。このプラットフォームはeLuaオープンソースプロジェクトに基づいており、その基礎層はESP8266 SDK 0.9.5を使用しています。

このプロジェクトでは、NodeMCU(ESP8266)と[EMQX Cloud](https://www.emqx.com/en/cloud)によって運営され維持される無料の[公開MQTTブローカー](https://www.emqx.com/en/mqtt/public-mqtt5-broker)を使用して、LEDライトをリモートで制御する方法を実装します。Arduino IDEを使用してNodeMCU ESP8266をプログラムします。EMQX Cloudは、EMQによって開始された[MQTT IoTクラウドサービスプラットフォーム](https://www.emqx.com/en/cloud)であり、ワンストップの運用保守管理とユニークな隔離環境を持つ**MQTT 5.0**アクセスサービスを提供します。

> もっと学ぶ: [ESP32が無料の公開MQTTブローカーに接続する](https://www.emqx.com/en/blog/esp32-connects-to-the-free-public-mqtt-broker)

## 必要なコンポーネント

- NodeMCU
- Arduino IDE
- LED * 1、330 Ω抵抗
- [MQTTX](https://mqttx.app/): クロスプラットフォームMQTT 5.0クライアントツール
- 無料の公開MQTTブローカー
  - ブローカー: **broker.emqx.io**
  - TCPポート: **1883**
  - Websocketポート: **8083**

## NodeMCU ESP8266とLEDの接続図

![project](https://assets.emqx.com/images/esp8266_control_led.png?imageMogr2/thumbnail/1520x)

## ソースコード

1. まず、**ESP8266WiFi**と**PubSubClient**のライブラリをインポートします。ESP8266WiFiライブラリはESP8266をWiFiネットワークに接続することができ、PubSubClientライブラリはMQTTブローカーに接続し、トピックを公開/購読することができます。

   ```
   #include <ESP8266WiFi.h>
   #include <PubSubClient.h>
   ```

2. NodeMCU ESP8266の**D1**ピンを使用してLEDに接続します。実際には、このピンの内部はESP8266モジュールの**GPIO5**に接続されています。

   ```
   // GPIO 5 D1
   #define LED 5
   ```

3. WiFiの名前とパスワード、およびMQTTブローカーの接続アドレスとポートを設定します。

   ```
   // WiFi
   const char *ssid = "mousse"; // WiFi名を入力
   const char *password = "qweqweqwe";  // WiFiパスワードを入力
   
   // MQTTブローカー
   const char *mqtt_broker = "broker.emqx.io";
   const char *topic = "esp8266/led";
   const char *mqtt_username = "emqx";
   const char *mqtt_password = "public";
   const int mqtt_port = 1883;
   ```

4. WiFiネットワークに接続し、プログラムの結果を出力するためにシリアル接続を開始します。

   ```
   // ソフトウェアシリアルのボーレートを115200に設定;
   Serial.begin(115200);
   // WiFiネットワークに接続
   WiFi.begin(ssid, password);
   while (WiFi.status() != WL_CONNECTED) {
       delay(500);
       Serial.println("WiFiに接続中..");
   }
   ```

5. MQTTブローカーを設定し、シリアルモニターに接続情報を表示します。

   ```
    // MQTTブローカーに接続
   client.setServer(mqtt_broker, mqtt_port);
   client.setCallback(callback);
   while (!client.connected()) {
       String client_id = "esp8266-client-";
       client_id += String(WiFi.macAddress());
       Serial.println("公開emqx mqttブローカーに接続中.....");
       if (client.connect(client_id, mqtt_username, mqtt_password)) {
           Serial.println("公開emqx mqttブローカーに接続しました");
       } else {
           Serial.print("接続失敗、状態 ");
           Serial.print(client.state());
           delay(2000);
       }
   }
   ```

6. MQTTブローカーに正常に接続した後、ESP8266はメッセージを公開し、MQTTブローカーを購読します。

   ```
   // メッセージの公開と購読
   client.publish(topic, "hello emqx");
   client.subscribe(topic);
   ```

7. シリアルモニターから送信されたコマンドを読み取り、LEDのオン/オフを制御するコールバック関数を記述します。

   ```
   void callback(char *topic, byte *payload, unsigned int length) {
       Serial.print("トピックにメッセージが到着: ");
       Serial.println(topic);
       Serial.print("メッセージ: ");
       String message;
       for (int i = 0; i < length; i++) {
           message += (char) payload[i];  // byteをStringに変換
       }
       Serial.print(message);
       if (message == "on" && !ledState) {
           digitalWrite(LED, HIGH);  // LEDを点灯
           ledState = true;
       }
       if (message == "off" && ledState) {
           digitalWrite(LED, LOW); // LEDを消灯
           ledState = false;
       }
       Serial.println();
       Serial.println("-----------------------");
   }
   ```

8. 完全なコード。

   ```
   #include <ESP8266WiFi.h>
   #include <PubSubClient.h>
   
   // GPIO 5 D1
   #define LED 5
   
   // WiFi
   const char *ssid = "mousse"; // WiFi名を入力
   const char *password = "qweqweqwe";  // WiFiパスワードを入力
   
   // MQTTブローカー
   const char *mqtt_broker = "broker.emqx.io";
   const char *topic = "esp8266/led";
   const char *mqtt_username = "emqx";
   const char *mqtt_password = "public";
   const int mqtt_port = 1883;
   
   bool ledState = false;
   
   WiFiClient espClient;
   PubSubClient client(espClient);
   
   void setup() {
       // ソフトウェアシリアルのボーレートを115200に設定;
       Serial.begin(115200);
       delay(1000); // 安定性のために遅延
   
       // WiFiネットワークに接続
       WiFi.begin(ssid, password);
       while (WiFi.status() != WL_CONNECTED) {
           delay(500);
           Serial.println("WiFiに接続中...");
       }
       Serial.println("WiFiネットワークに接続しました");
   
       // LEDピンを出力として設定
       pinMode(LED, OUTPUT);
       digitalWrite(LED, LOW);  // 最初はLEDを消灯
   
       // MQTTブローカーに接続
       client.setServer(mqtt_broker, mqtt_port);
       client.setCallback(callback);
       while (!client.connected()) {
           String client_id = "esp8266-client-";
           client_id += String(WiFi.macAddress());
           Serial.printf("クライアント %s が公開MQTTブローカーに接続しています\n", client_id.c_str());
           if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
               Serial.println("公開EMQX MQTTブローカーに接続しました");
           } else {
               Serial.print("失敗しました ステート ");
               Serial.print(client.state());
               delay(2000);
           }
       }
   
       // メッセージの公開と購読
       client.publish(topic, "hello emqx");
       client.subscribe(topic);
   }
   
   void callback(char *topic, byte *payload, unsigned int length) {
       Serial.print("トピックにメッセージが到着: ");
       Serial.println(topic);
       Serial.print("メッセージ: ");
       String message;
       for (int i = 0; i < length; i++) {
           message += (char) payload[i];  // byteをStringに変換
       }
       Serial.print(message);
       if (message == "on" && !ledState) {
           digitalWrite(LED, HIGH);  // LEDを点灯
           ledState = true;
       }
       if (message == "off" && ledState) {
           digitalWrite(LED, LOW); // LEDを消灯
           ledState = false;
       }
       Serial.println();
       Serial.println("-----------------------");
   }
   
   void loop() {
       client.loop();
       delay(100); // ループの各反復で短い遅延
   }
   ```

## テスト

1. [Arduino IDE](https://www.arduino.cc/en/Main/Software)を使用してESP8266に完全なコードをアップロードし、シリアルモニターを開いてください。

   ![esp_con](https://assets.emqx.com/images/esp8266_connect_successful.png?imageMogr2/thumbnail/1520x)

2. MQTTXクライアントとMQTTブローカーとの接続を確立し、ESP8266にコマンドを送信します。

   ![esp_con](https://assets.emqx.com/images/esp8266_control_led_publish.png?imageMogr2/thumbnail/1520x)

## まとめ

これまでに、NodeMCU ESP8266と無料の公開MQTTブローカーを使用してLEDライトのリモートコントロールを成功させました。この例ではシンプルなシナリオのみを説明していますが、実際のプロジェクトでは、よりセキュアな接続方法とIoTデータの永続化が必要です。

次に、EMQが提供する[MQTTプロトコルに関する簡単なガイド](https://www.emqx.com/en/mqtt-guide)シリーズの記事で、MQTTプロトコルの特徴について学び、MQTTのより高度なアプリケーションを探求し、MQTTアプリケーションおよびサービス開発を始めることができます。

## リソース

- [ESP32でのMQTTの使い方: 初心者ガイド](https://www.emqx.com/en/blog/esp32-connects-to-the-free-public-mqtt-broker)
- [Raspberry PiでPaho Pythonクライアントを使ってMQTTを使用する方法](https://www.emqx.com/en/blog/use-mqtt-with-raspberry-pi)
- [Raspberry PiをベースにしたMicroPython MQTTチュートリアル](https://www.emqx.com/en/blog/micro-python-mqtt-tutorial-based-on-raspberry-pi) -[Arduinoを使ってESP8266がMQTTブローカーに接続する](https://www.emqx.com/en/blog/esp8266-connects-to-the-public-mqtt-broker)
- [NodeMCU (ESP8266)を使ってセンサーデータをMQTTクラウドサービスにアップロードする](