NodeMCU（ESP8266）を使用してMQTTクラウドサービスにセンサーデータをアップロード

![NodeMCU（ESP8266）を使用してMQTTクラウドサービスにセンサーデータをアップロード](https://assets.emqx.com/images/7746e3f2c2fde2e5461be12cefb42a6e.png?imageMogr2/thumbnail/1520x684)

### はじめに

この例では、ESP8266ベースのNodeMCUを使用し、[MQTTプロトコル](https://www.emqx.com/en/blog/the-easiest-guide-to-getting-started-with-mqtt)を通じてDHT11センサーによって収集された温度と湿度データをクラウドのMQTTサービスに報告する方法をデモンストレーションします。また、アプリケーションがデータを購読して処理する方法を示します。この記事でMQTTプロトコルが使用される理由は、軽量で省エネであるため、IoTの使用シナリオに非常に適しているためです。現在、すべての主要な公共クラウドプロバイダーは基本的にMQTTプロトコルに基づいたIoTハブサービスを開始しています。例えば、AWSのIoT CoreやAzureのIoT Hubなど、これらの公共クラウドサービスにMQTTプロトコルを介して簡単にデータをアクセスできます。

この例の全体的なアーキテクチャは以下の通りです：

![全体的なアーキテクチャ](https://assets.emqx.com/images/1d8de4c8e46b6e7e8d48ce64c3f46c64.png?imageMogr2/thumbnail/1520x)

### 設定

#### ハードウェア設定

- NodeMCUボード x 1: NodeMCUはオープンソースのIoTプラットフォームです。ESP8266 Wi-Fi SoC上で動作するファームウェアと、ESP-12モジュールに基づくハードウェアが含まれています。デフォルトでは、「NodeMCU」という用語は開発キットではなくファームウェアを指します。このファームウェアはLuaスクリプト言語を使用します。
- DHT11温度/湿度センサー x 1: DHT11デジタル温度および湿度センサーは、校正されたデジタル信号出力を備えた複合センサーです。
- ブレッドボード x 1
- ジャンパーワイヤー数本
- 接続図については、以下のスクリーンショットを参照してください。

![接続図](https://assets.emqx.com/images/ab1d6dee2e4870a45ada34fb584f8328.png?imageMogr2/thumbnail/1520x)

#### Arduino設定

- [CH340G USB](https://kig.re/downloads/CH34x_Install.zip)ドライバをダウンロードしてインストール

- ESP8266モジュールのインストール

- PubSubClientライブラリのインストール（作者：Nick O'Leary）

  Sketch -> Include Library -> Manage Libraries... -> 検索フィールドにPubSubと入力 -> インストール

#### MQTTクラウドサービス

NodeMCUを介してデータが正常に収集された後、クラウドのMQTTクラウドサービスに送信する必要があります。この記事では、EMQXが提供するMQTTクラウドサービスを使用します。読者は状況に応じて、Azure IoT HubやAWS IoT Coreなど、他のMQTTクラウドサービスを選択することもできます。各クラウドサービスでは、アクセス時に異なる認証方法を提供する必要があります。そのため、NodeMCU経由でクラウドのMQTTサービスに接続する際には、対象クラウドサービスのセキュリティ要件に応じた接続方法を設定する必要があります。簡単にするために、この記事では非セキュア接続方法を使用しています。公式の生産環境では、セキュアな認証方法を持つ接続を設定する必要があります。

- [EMQX Cloud](https://accounts.emqx.io/signin?continue=https://cloud.emqx.io)の登録アドレスにアクセスして登録

- 登録後、[EMQX Cloud](https://cloud.emqx.io/console/deployments/0?oper=new)にアクセスして、15日間の無料トライアルを申し込む

  ![EMQX Cloud](https://assets.emqx.com/images/de696779fd64a2fb880e69893ed2dab5.png?imageMogr2/thumbnail/1520x)

- ブローカー接続アドレスを表示

  ![ブローカー接続アドレス](https://assets.emqx.com/images/504ec89295d41afc72daa8e1ebcdc302.png?imageMogr2/thumbnail/1520x)

### ソースコード

```
#include <ESP8266WiFi.h>

#include <PubSubClient.h>

#include "DHT.h"

#define DHTPIN D4     // 接続するピン
#define wifi_ssid "xxxxx"
#define wifi_password "xxxxx"

#define mqtt_server "broker-internet-facing-f1429d8cb54ca4a7.elb.us-east-1.amazonaws.com"  // MQTTクラウドアドレス
#define humidity_topic "humidity"
#define temperature_topic "temperature"

#define DHTTYPE DHT11   // DHT 11

WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE);

void setup() {
    Serial.begin(115200);
    setup_wifi();
    client.setServer(mqtt_server, 1883);
    dht.begin();
}

void setup_wifi() {
    delay(10);
    WiFi.begin(wifi_ssid, wifi_password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
}

void reconnect() {
    // 再接続するまでループ
    while (!client.connected()) {
        Serial.print("MQTT接続を試みています...");
        if (client.connect("nodeMcuDHT11")) {
            Serial.println("接続しました");
        } else {
            Serial.print("失敗, rc=");
            Serial.print(client.state());
            Serial.println(" 5秒後に再試行");
            delay(5000);
        }
    }
}

bool checkBound(float newValue, float prevValue, float maxDiff) {
    return newValue < prevValue - maxDiff || newValue > prevValue + maxDiff;
}

long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diff = 1.0;

void loop() {
    if (!client.connected()) {
        reconnect();
    }
    client.loop();

    long now = millis();
    if (now - lastMsg > 30000) {
        // 測定間の数秒間待機
        lastMsg = now;

        float newTemp = dht.readTemperature();
        float newHum = dht.readHumidity();
        if (checkBound(newTemp, temp, diff)) {
            temp = newTemp;
            Serial.print("新しい温度:");
            Serial.println(String(temp).c_str());
            client.publish(temperature_topic, String(temp).c_str(), true);
        }

        if (checkBound(newHum, hum, diff)) {
            hum = newHum;
            Serial.print("新しい湿度:");
            Serial.println(String(hum).c_str());
            client.publish(humidity_topic, String(hum).c_str(), true);
        }
    }
}
```

自身のWi-FiとMQTT設定に合わせて、以下の手順でコードを編集してください。

- Wi-Fi設定

  ```
  #define wifi_ssid "あなたのWi-Fi名"
  #define wifi_password "あなたのWi-Fiパスワード"
  ```

- ブローカーサーバー設定

  ```
  #define mqtt_server "あなたのMQTTブローカーアドレス"
  ```

- Arduino設定

  ![Arduino設定](https://assets.emqx.com/images/f30399b37a8c03b2f4faf47a01ab984f.png?imageMogr2/thumbnail/1520x)

### 実行

- コードアップロード

  NodeMCUをPCにUSB経由で接続し、Arduion IDEで115200ポートを選択します。アップロードボタンを使用してスケッチをコンパイルし、デバイスにアップロードします。

- Arduinoモニターウィンドウを開いて、データ報告を表示します。

  ![Arduinoモニターウィンドウ](https://assets.emqx.com/images/e1932131cf52075fbbfb09fa89f8ba91.png?imageMogr2/thumbnail/1520x)

- MQTTクライアントがメッセージを受信

  この投稿では、ブラウザアクセスをサポートする[MQTTX](https://mqttx.app/)が提供するMQTTクライアントツールを使用します：http://www.emqx.io/online-mqtt-client。MQTT Xは[デスクトップクライアント](https://mqttx.app/)と[コマンドラインツール](https://mqttx.app/cli)も提供しています。

  1. MQTT接続を作成します ![MQTT接続を作成](https://assets.emqx.com/images/6b70ac640041ab7aadb211553bc729e8.png?imageMogr2/thumbnail/1520x)

  2. トピックを購読し、テストメッセージを受信します

     ![購読](https://assets.emqx.com/images/16d0f34e02926530e021ad9e6f2d3de5.png?imageMogr2/thumbnail/1520x)

- [Python MQTTクライアント](https://www.emqx.com/en/blog/python-async-mqtt-client-hbmqtt)を使用して報告されたメッセージを表示

```
from paho.mqtt import client as mqtt

def on_connect(client, userdata, flags, rc):
    # MQTTブローカーに接続
    client.subscribe([("temperature", 0), ("humidity", 0)])

def on_message(client, userdata, msg):
    # DHT11温度/湿度データを購読
    print(f"{msg.topic}: {msg.payload.decode()}")

def run():
    client = mqtt.Client()
    # MQTTクラウドアドレスを編集
    client.connect("あなたのMQTTブローカーアドレス", 1883)
    client.on_connect = on_connect
    client.on_message = on_message
    client.loop_forever()

if __name__ == '__main__':
    run()
```

Pythonスクリプト実行のスクリーンショット：

![Pythonスクリプト実行](https://assets.emqx.com/images/4ebd3963243c0af2a75e46f19fcbd5fb.png?imageMogr2/thumbnail/1520x)

- トラブルシューティング：トラブルシューティングを行うために、USBアダプタをPCに接続し、Arduino IDEでUSB-TTLアダプタのポートを選択します。シリアル出力によって生成されたデバッグ情報を表示するためにシリアルモニターを開きます。

### まとめ

これまでに、NodeMCUからデータを収集し、EMQによって提供されるMQTTクラウドサービスにアップロードし、Pythonで書かれたバックエンドプログラムによってデータを処理する簡単なプロセスを完了しました。しかし、実際の生産アプリケーションでは、より高い要求が必要になります。例えば、

- より安全な接続方法
- IoTデータのリアルタイム処理
- データの永続化
- 大規模な接続

[EMQX Enterprise](https://www.emqx.com/en/products/emqx)とその[クラウドサービス](https://www.emqx.com/en/cloud)は、上記の問題を解決するための良いソリューションを提供しています。読者は関連リンクで詳細情報を参照できます。

データセキュリティを高め（クラウドへのアップロードを避ける）、ビジネス処理の遅延を減らし、データ伝送コストを削減するために、ソリューションにエッジコンピューティングを検討することができます。Azure IoT EdgeやAWSのGreengrassは、エッジでのソリューションを提供しています。EMQは、オープンソースの超軽量エッジIoTエッジストリーミング分析ソリューション[eKuiper](https://github.com/lf-edge/ekuiper)も提供しています。詳細については、[この記事](https://medium.com/@emqtt/lightweight-edge-computing-emq-x-kuiper-and-azure-iot-hub-integration-solution-151134ead024)を参照してください。

## リソース

- [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)
- [ESP8266とMQTTを使ったLEDのリモートコントロール](https://www.emqx.com/en/blog/esp8266_mqtt_led)
- [Arduinoを使ってESP8266がMQTTブローカーに接続する](