Облачный MQTT-брокер Mosquitto (доступ из любой точки мира через Digital Ocean)

Узнайте, как установить брокер Mosquitto для MQTT-коммуникации на виртуальной машине Linux Ubuntu (VM), используя Digital Ocean. Запуск облачного MQTT-брокера Mosquitto позволяет подключать несколько плат ESP32/ESP8266 и других IoT-устройств из любой точки мира, используя различные сети, при условии наличия подключения к интернету. Мы также рассмотрим, как подключить ваши платы ESP к облачному MQTT-брокеру с помощью Arduino IDE.

Облачный MQTT-брокер Mosquitto на Digital Ocean

Вам может понравиться: SMART HOME with Raspberry Pi, ESP32, and ESP8266 – изучите Node-RED и InfluxDB на Raspberry Pi для создания системы домашней автоматизации с ESP32 и ESP8266.

Введение в протокол MQTT

MQTT расшифровывается как Message Queuing Telemetry Transport. Это легковесная система публикации и подписки, в которой вы можете публиковать и получать сообщения как клиент. Она широко используется в областях домашней автоматизации и IoT.

Чтобы узнать больше о MQTT, прочитайте наше полное руководство: What is MQTT and how it works.

MQTT-брокер в первую очередь отвечает за получение всех MQTT-сообщений, фильтрацию сообщений, определение того, кто заинтересован в каждом сообщении, и затем публикацию сообщений всем подписанным клиентам.

Пример сообщений публикации и подписки MQTT-брокера Mosquitto

Существует несколько брокеров, которые вы можете использовать. В наших проектах домашней автоматизации мы используем популярный Mosquitto MQTT Broker. Его легко установить, настроить и использовать.

В этом руководстве мы покажем вам, как установить MQTT-брокер Mosquitto в облаке – на виртуальной машине Linux Ubuntu (VM), работающей на хостинг-сервисе Digital Ocean.

Обзор облачного MQTT-брокера

В чем преимущество использования облачного MQTT-брокера и как он работает?

Использование облачного MQTT-брокера позволяет нескольким IoT-устройствам (таким как платы ESP32 и ESP8266) обмениваться данными друг с другом по MQTT, даже если они находятся в разных сетях (в разных местах, подключенных к разным маршрутизаторам). Вот общий обзор.

Обзор MQTT-брокера Mosquitto на ESP32 ESP8266 Digital Ocean
  • MQTT-брокер Mosquitto работает в облаке (хостинг-сервис от Digital Ocean). Таким образом, он может принимать сообщения от IoT-устройств со всего мира.

  • У вас может быть несколько плат ESP в разных сетях, которые подключаются к одному и тому же облачному MQTT-брокеру.

  • Каждая плата ESP должна быть подключена к маршрутизатору, обеспечивающему доступ в интернет, чтобы подключиться к брокеру.

  • Поскольку платы используют один и тот же MQTT-брокер, они могут обмениваться данными друг с другом, публикуя и подписываясь на одни и те же топики.

На следующей диаграмме показан пример возможного применения:

Обзор публикации и подписки MQTT-брокера Mosquitto на ESP32 ESP8266 Digital Ocean
  • На предыдущем изображении показаны две платы ESP32 в разных сетях. Каждая плата подключена к отдельному маршрутизатору с доступом в интернет.

  • Несмотря на то что они находятся в разных сетях, они могут обмениваться данными друг с другом через облачный MQTT-брокер, подписываясь и публикуя сообщения в одних и тех же топиках.

  • ESP32 #1 публикует сообщение в топик, на который подписана ESP32 #2 (board2/output1). Сообщение может указывать, должна ли ESP32 #2 включить или выключить выход. Таким образом, ESP32 #1 может управлять выходами ESP32 #2.

  • Аналогично, ESP32 #2 публикует показания температуры в топик board2/temperature. ESP32 #1 подписана на этот топик, поэтому она получает показания датчиков board2.

Вы также можете :doc:`установить Node-RED <../access-node-red-dashboard-anywhere-digital-ocean/index>`_ на том же облачном сервере (аккаунт хостинга Digital Ocean) для управления и мониторинга ваших плат из любой точки мира с помощью компьютера или смартфона. Вы можете следовать этому руководству: :doc:`Access Node-RED Dashboard from Anywhere using Digital Ocean <../access-node-red-dashboard-anywhere-digital-ocean/index>`_.

Хостинг-сервис – Digital Ocean

Для запуска облачного MQTT-брокера Mosquitto вам нужен хостинг-сервис, который позволяет работать с командной строкой и устанавливать любое необходимое программное обеспечение. Я рекомендую использовать Digital Ocean, который предлагает сервер Ubuntu, которым можно управлять через командную строку.

Я использую его с 2015 года и лично рекомендую, но вы можете использовать любой другой хостинг-сервис. Любой хостинг-сервис, предлагающий виртуальную машину Linux Ubuntu с полным консольным доступом, должен подойти.

Если у вас нет аккаунта хостинга, я рекомендую зарегистрироваться на Digital Ocean. При регистрации на Digital Ocean вы можете попробовать его в течение 60 дней (вам предоставляются бесплатные кредиты для тестирования платформы). Вам нужно перейти по этой ссылке, чтобы получить бесплатные кредиты: https://randomnerdtutorials.com/digitalocean.

Получить виртуальную машину Linux Ubuntu на Digital Ocean >>

Если вам нравятся наши проекты, вы можете рассмотреть возможность регистрации на рекомендуемом хостинг-сервисе, потому что вы будете поддерживать нашу работу.

Примечание

Вы также можете запустить MQTT-брокер Mosquitto в вашей локальной сети, используя плату Raspberry Pi. Однако цель этого руководства – запустить MQTT-брокер в облаке для обмена данными с платами (или другими IoT-устройствами) в различных сетях.

Создание аккаунта Digital Ocean

Чтобы создать аккаунт Digital Ocean, перейдите на Digital Ocean и зарегистрируйтесь, используя один из доступных вариантов.

Установка MQTT-брокера Mosquitto на Digital Ocean

Создайте свой аккаунт, и вы получите кредит в размере $200, который можно использовать в течение 60 дней для тестирования платформы. Возможно, вам потребуется ввести действительную кредитную карту, но вы можете отменить свой аккаунт в любое время, если вы больше не заинтересованы в использовании сервиса после бесплатного 60-дневного пробного периода.

Подтвердите свой аккаунт и войдите. На вкладке Project нажмите на свое имя. Вы должны увидеть аналогичную панель управления.

Панель управления Digital Ocean для MQTT-брокера Mosquitto

Создание Droplet (виртуальная машина Linux Ubuntu)

Чтобы создать новую виртуальную машину, нажмите кнопку «Create» в правом верхнем углу и выберите опцию «Droplets». Digital Ocean называет свои виртуальные машины Droplets.

Важно

Если вы уже запускаете :doc:`Droplet с установленным Node-RED <../access-node-red-dashboard-anywhere-digital-ocean/index>`_, вы можете пропустить следующие шаги (создание Droplet). Вы можете запустить Node-RED и MQTT-брокер Mosquitto на одном сервере.

Создание Droplet на Digital Ocean для MQTT-брокера Mosquitto

Затем выберите следующие параметры:

  • Дистрибутив: Ubuntu

  • Выберите план: Shared CPU Basic – мы рекомендуем выбрать вариант за $6/месяц (план за $4 тоже будет работать, но может быть немного медленным).

Выбор плана Linux на Digital Ocean для установки MQTT-брокера

Выберите регион дата-центра – выберите ближайший к вашему местоположению.

Расположение сервера Linux Ubuntu на Digital Ocean для установки MQTT-брокера Mosquitto

Создайте пароль root, который позволяет получить доступ к вашему Droplet (сохраните этот пароль, потому что он понадобится вам для доступа к серверу).

Установка пароля на сервере Linux Ubuntu Digital Ocean

Затем вы можете выбрать любые дополнительные опции, которые считаете полезными для вашего проекта.

Дополнительные опции сервера Linux Ubuntu на Digital Ocean

Наконец, выберите имя хоста (hostname), чтобы легко идентифицировать, с какой виртуальной машиной вы работаете. Я назвал свой Droplet home-automation-system.

Вот и все, вам просто нужно нажать большую зеленую кнопку Create Droplet, чтобы завершить процесс.

Выбор имени хоста на Digital Ocean для сервера Linux Ubuntu

Подождите несколько минут, и когда полоса прогресса завершится, ваш Droplet будет готов.

Доступ к консоли виртуальной машины Linux Ubuntu

Теперь, если вы нажмете на вкладку Droplets, ваш только что созданный droplet должен быть там.

Доступ к Droplets на сервере Linux Ubuntu Digital Ocean

Нажмите на имя droplet. Откроется новая страница. В правом верхнем углу есть ссылка Console. Если вы нажмете на нее, откроется новое окно консоли/терминала, в котором вы можете вводить команды Linux для установки программного обеспечения или выполнения команд точно так же, как вы делаете это на Raspberry Pi через SSH.

Запуск консоли на сервере Linux Ubuntu Digital Ocean

Введите имя пользователя для входа (root) и ранее определенный пароль, нажмите клавишу Enter для доступа к серверу.

Вход в консоль сервера Linux Ubuntu Digital Ocean с именем пользователя и паролем

Есть необязательный шаг, но он выходит за рамки данного руководства. Он не требуется для работы этого проекта: подготовьте ваш сервер с пользователем без прав root, но с поддержкой sudo, и базовым брандмауэром, следуя этому руководству Initial Server Setup with Ubuntu 20.04.

Установка MQTT-брокера Mosquitto на виртуальной машине Linux Ubuntu Digital Ocean

Давайте установим брокер Mosquitto на Digital Ocean.

Логотип MQTT-брокера Mosquitto

1) Выполните следующую команду для обновления вашей системы:

sudo apt update && sudo apt upgrade -y

2) Когда появится запрос, нажмите Y и Enter. Обновление займет некоторое время.

3) Для установки брокера Mosquitto введите следующую команду:

sudo apt install -y mosquitto mosquitto-clients

Вот и все! MQTT-брокер Mosquitto установлен.

4) Чтобы Mosquitto автоматически запускался при загрузке сервера, вам нужно выполнить следующую команду (этот шаг необязательный, но он гарантирует, что пока сервер работает, Mosquitto будет работать даже после перезапуска сервера):

sudo systemctl enable mosquitto.service

5) Теперь проверьте установку, выполнив следующую команду:

mosquitto -v

Эта команда выводит версию Mosquitto, которая в данный момент работает на вашем сервере. Она будет 2.0.11 или выше.

Версия Mosquitto на Droplet Digital Ocean

Вы можете игнорировать сообщение об ошибке «Error: Address already in use».

Включение удаленного доступа / аутентификации

Чтобы включить удаленный доступ для обмена данными с IoT-устройствами, нам нужно отредактировать/создать файл конфигурации.

Мы добавим аутентификацию с именем пользователя и паролем.

1) Выполните следующую команду, но замените YOUR_USERNAME на имя пользователя, которое вы хотите использовать:

sudo mosquitto_passwd -c /etc/mosquitto/passwd YOUR_USERNAME

Я буду использовать MQTT-пользователя sara, поэтому выполняю команду следующим образом:

sudo mosquitto_passwd -c /etc/mosquitto/passwd sara

Когда вы выполните предыдущую команду с желаемым именем пользователя, вам будет предложено ввести пароль. Никакие символы не будут отображаться при вводе пароля. Введите пароль и запомните комбинацию пользователь/пароль, она понадобится вам позже в ваших проектах для подключения к брокеру.

Эта предыдущая команда создает файл паролей с именем passwd в директории /etc/mosquitto. Теперь нам нужно отредактировать файл конфигурации mosquitto, чтобы он разрешал аутентификацию только с именем пользователя и паролем, которые мы определили.

2) Установите правильные разрешения для файла passwd:

sudo chown mosquitto /etc/mosquitto/passwd

3) Выполните следующую команду для редактирования файла конфигурации:

sudo nano /etc/mosquitto/mosquitto.conf

4) Добавьте следующую строку в начало файла (убедитесь, что она находится в начале файла, иначе это не будет работать):

per_listener_settings true

5) Также добавьте следующие три строки, чтобы разрешить подключение для аутентифицированных пользователей и указать Mosquitto, где находится файл с именем пользователя и паролем.

allow_anonymous false
listener 1883
password_file /etc/mosquitto/passwd

Ваш файл конфигурации будет выглядеть следующим образом (новые строки выделены жирным шрифтом):

# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

per_listener_settings true

pid_file /run/mosquitto/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d
allow_anonymous false
listener 1883
password_file /etc/mosquitto/passwd
Файл конфигурации Mosquitto на Digital Ocean

6) Нажмите CTRL-X, затем Y, и наконец нажмите Enter, чтобы выйти и сохранить изменения.

7) Перезапустите Mosquitto, чтобы изменения вступили в силу.

sudo systemctl restart mosquitto

8) Подождите несколько секунд. Чтобы проверить, работает ли Mosquitto, вы можете ввести следующую команду:

sudo systemctl status mosquitto

Теперь у вас установлен MQTT-брокер Mosquitto в облаке с включенной аутентификацией по имени пользователя и паролю.

В вашем коде Arduino для ESP32/ESP8266, в поле MQTT Host, вы должны использовать IP-адрес вашего droplet.

Тестирование установки MQTT-брокера Mosquitto

Чтобы протестировать установку MQTT-брокера, вы можете использовать другое окно терминала (Terminal window #2) и установить SSH-соединение с вашим сервером (вы можете использовать PuTTY или аналогичный SSH-клиент). Введите IP-адрес droplet и попробуйте установить SSH-соединение.

SSH-клиент подключается к серверу Digital Ocean через PuTTY

Войдите как root и введите свой пароль.

Затем введите следующую команду для подписки на топик testTopic. Замените user вашим именем пользователя и pass вашим паролем.

mosquitto_sub -h localhost -t testTopic -u user -P pass

В вашем окне Terminal window #1 используйте следующую команду для публикации сообщения «Hello, world!» в тестовый топик. Замените user вашим именем пользователя и pass вашим паролем.

mosquitto_pub -h localhost -t testTopic -m "Hello, world!" -u user -P pass

Terminal window #2 должно получить сообщение.

Тестирование MQTT-брокера Mosquitto на Digital Ocean

Вы можете использовать следующую таблицу в качестве справки по параметрам, которые можно передать в командах mosquitto_sub и mosquitto_pub:

-h

Имя хоста (Hostname)

-t

MQTT-топик

-m

MQTT-сообщение

-u

Имя пользователя MQTT

-P

Пароль MQTT


Подключение ESP32 к MQTT-брокеру Mosquitto

Мы часто используем наши платы ESP32 и ESP8266 в наших MQTT-проектах. Поэтому мы покажем вам, как подключить плату ESP32 к вашему облачному MQTT-брокеру – для ESP8266 процедура аналогична, просто убедитесь, что вы используете функции, специфичные для ESP8266.

Прежде чем продолжить это руководство, убедитесь, что вы выполнили следующие предварительные условия.

Arduino IDE

Мы будем программировать плату ESP32 с помощью Arduino IDE, поэтому убедитесь, что у вас установлено дополнение ESP32.

Библиотеки MQTT

Для использования MQTT с ESP32 мы будем использовать библиотеку Async MQTT Client.

Установка библиотеки Async MQTT Client

  1. Нажмите здесь, чтобы скачать библиотеку Async MQTT client. У вас должен появиться .zip файл в папке Downloads.

  2. Перейдите в Sketch > Include Library > Add .ZIP library и выберите библиотеку, которую вы только что скачали.

Установка библиотеки Async TCP

Для использования MQTT с ESP вам также понадобится библиотека Async TCP.

  1. Нажмите здесь, чтобы скачать библиотеку Async TCP client. У вас должен появиться .zip файл в папке Downloads.

  2. Перейдите в Sketch > Include Library > Add .ZIP library и выберите библиотеку, которую вы только что скачали.

ESP32: публикация MQTT-сообщений в облачный MQTT-брокер

Скопируйте следующий код в вашу Arduino IDE. Чтобы он работал у вас, вам нужно ввести ваши сетевые учетные данные, а также данные MQTT-брокера (IP-адрес вашего Droplet на Digital Ocean, имя пользователя и пароль брокера).

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/cloud-mqtt-mosquitto-broker-access-anywhere-digital-ocean/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>
extern "C" {
  #include "freertos/FreeRTOS.h"
  #include "freertos/timers.h"
}
#include <AsyncMqttClient.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

// Digital Ocean MQTT Mosquitto Broker
#define MQTT_HOST IPAddress(XXX, XXX, XXX, XXX)
// For a cloud MQTT broker, type the domain name
//#define MQTT_HOST "example.com"
#define MQTT_PORT 1883

#define MQTT_USERNAME "REPLACE_WITH_YOUR_MQTT_USER"
#define MQTT_PASSWORD "REPLACE_WITH_YOUR_MQTT_PASSWORD"

// Test MQTT Topic
#define MQTT_PUB_TEST "test"

AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;

unsigned long previousMillis = 0;   // Stores last time temperature was published
const long interval = 5000;         // Interval at which to publish sensor readings

int i = 0;

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void connectToMqtt() {
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

void WiFiEvent(WiFiEvent_t event) {
  Serial.printf("[WiFi-event] event: %d\n", event);
  switch(event) {
    case ARDUINO_EVENT_WIFI_STA_GOT_IP:
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      connectToMqtt();
      break;
    case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
      Serial.println("WiFi lost connection");
      xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
      xTimerStart(wifiReconnectTimer, 0);
      break;
  }
}

void onMqttConnect(bool sessionPresent) {
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");
  if (WiFi.isConnected()) {
    xTimerStart(mqttReconnectTimer, 0);
  }
}

/*void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
  Serial.println("Subscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  Serial.print("  qos: ");
  Serial.println(qos);
}
void onMqttUnsubscribe(uint16_t packetId) {
  Serial.println("Unsubscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}*/

void onMqttPublish(uint16_t packetId) {
  Serial.print("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup() {
  Serial.begin(115200);
  Serial.println();

  mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
  wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));

  WiFi.onEvent(WiFiEvent);

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  /*mqttClient.onSubscribe(onMqttSubscribe);
  mqttClient.onUnsubscribe(onMqttUnsubscribe);*/
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  // If your broker requires authentication (username and password), set them below
  mqttClient.setCredentials(MQTT_USERNAME, MQTT_PASSWORD);
  connectToWifi();
}

void loop() {
  unsigned long currentMillis = millis();
  // Every X number of seconds (interval = 5 seconds)
  // it publishes a new MQTT message
  if (currentMillis - previousMillis >= interval) {
    // Save the last time a new reading was published
    previousMillis = currentMillis;

    String testString = "Hello, world! #" + String(i);
    // Publish an MQTT message on topic test
    uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEST, 1, true, String(testString).c_str());
    Serial.printf("Publishing on topic %s at QoS 1, packetId: %i", MQTT_PUB_TEST, packetIdPub1);
    Serial.printf(" Message: %.2f \n", testString);
    i++;
  }
}

Просмотреть исходный код

Введите ваши сетевые учетные данные в следующих строках.

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

Вставьте IP-адрес Droplet Digital Ocean, чтобы ESP32 подключилась к вашему брокеру (в моем случае это 178.62.83.231).

#define MQTT_HOST IPAddress(178, 62, 83, 231)

Если ваш брокер требует аутентификации, введите ваше имя пользователя MQTT и пароль MQTT.

#define MQTT_USERNAME "YOUR_USER"
#define MQTT_PASSWORD "YOUR_PASSWORD"

Тестирование публикации MQTT-сообщений ESP32

Если ваша ESP32 выполняет загруженный код и вы откроете Serial Monitor в Arduino IDE, вы увидите, что ваша ESP32 публикует новые сообщения каждые 5 секунд.

Установите SSH-соединение с вашим облачным сервером (используя PuTTY, например) и введите (замените user вашим именем пользователя и pass вашим паролем):

mosquitto_sub -h localhost -t test -u user -P pass

Вы должны начать получать новые MQTT-сообщения, опубликованные вашей ESP32.

ESP32 ESP8266 подписка на MQTT-топик и получение сообщений от облачного MQTT-брокера Mosquitto

Публикация сообщений из облачного MQTT-брокера в ESP32

Следующий скетч заставляет ESP32 подписаться на облачный MQTT-топик для получения сообщений. Скопируйте его в вашу Arduino IDE, затем вставьте ваши сетевые учетные данные, а также данные MQTT-брокера (IP-адрес вашего Droplet на Digital Ocean и имя пользователя и пароль брокера).

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com/cloud-mqtt-mosquitto-broker-access-anywhere-digital-ocean/
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*/
#include <WiFi.h>
extern "C" {
  #include "freertos/FreeRTOS.h"
  #include "freertos/timers.h"
}
#include <AsyncMqttClient.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

// Digital Ocean MQTT Mosquitto Broker
#define MQTT_HOST IPAddress(XXX, XXX, XXX, XXX)
// For a cloud MQTT broker, type the domain name
//#define MQTT_HOST "example.com"
#define MQTT_PORT 1883

#define MQTT_USERNAME "REPLACE_WITH_YOUR_MQTT_USER"
#define MQTT_PASSWORD "REPLACE_WITH_YOUR_MQTT_PASSWORD"

// Test MQTT Topic
#define MQTT_SUB_TEST "test"

AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;

unsigned long previousMillis = 0;   // Stores last time temperature was published
const long interval = 5000;         // Interval at which to publish sensor readings

int i = 0;

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void connectToMqtt() {
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

void WiFiEvent(WiFiEvent_t event) {
  Serial.printf("[WiFi-event] event: %d\n", event);
  switch(event) {
    case ARDUINO_EVENT_WIFI_STA_GOT_IP:
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      connectToMqtt();
      break;
    case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
      Serial.println("WiFi lost connection");
      xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
      xTimerStart(wifiReconnectTimer, 0);
      break;
  }
}

// Add more topics that want your ESP to be subscribed to
void onMqttConnect(bool sessionPresent) {
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);

  // ESP subscribed to test topic
  uint16_t packetIdSub = mqttClient.subscribe(MQTT_SUB_TEST, 0);
  Serial.println("Subscribing at QoS 0");
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");
  if (WiFi.isConnected()) {
    xTimerStart(mqttReconnectTimer, 0);
  }
}

void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
  Serial.println("Subscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  Serial.print("  qos: ");
  Serial.println(qos);
}

void onMqttUnsubscribe(uint16_t packetId) {
  Serial.println("Unsubscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

// You can modify this function to handle what happens when you receive a certain message in a specific topic
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
  String messageTemp;
  for (int i = 0; i < len; i++) {
    //Serial.print((char)payload[i]);
    messageTemp += (char)payload[i];
  }
  // Check if the MQTT message was received on topic test
  if (strcmp(topic, MQTT_SUB_TEST) == 0) {
    Serial.println("TRUE");
  }

  Serial.println("Publish received.");
  Serial.print("  message: ");
  Serial.println(messageTemp);
  Serial.print("  topic: ");
  Serial.println(topic);
  Serial.print("  qos: ");
  Serial.println(properties.qos);
  Serial.print("  dup: ");
  Serial.println(properties.dup);
  Serial.print("  retain: ");
  Serial.println(properties.retain);
  Serial.print("  len: ");
  Serial.println(len);
  Serial.print("  index: ");
  Serial.println(index);
  Serial.print("  total: ");
  Serial.println(total);
}

/*void onMqttPublish(uint16_t packetId) {
  Serial.print("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}*/

void setup() {
  Serial.begin(115200);
  Serial.println();

  mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
  wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));

  WiFi.onEvent(WiFiEvent);

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onSubscribe(onMqttSubscribe);
  mqttClient.onUnsubscribe(onMqttUnsubscribe);
  //mqttClient.onPublish(onMqttPublish);
  mqttClient.onMessage(onMqttMessage);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  // If your broker requires authentication (username and password), set them below
  mqttClient.setCredentials(MQTT_USERNAME, MQTT_PASSWORD);
  connectToWifi();
}

void loop() {

}

Просмотреть исходный код

Введите ваши сетевые учетные данные в следующих строках.

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

Вставьте IP-адрес Droplet Digital Ocean, чтобы ESP32 подключилась к вашему брокеру (в моем случае это 178.62.83.231).

#define MQTT_HOST IPAddress(178, 62, 83, 231)

Если ваш брокер требует аутентификации, введите ваше имя пользователя MQTT и пароль MQTT.

#define MQTT_USERNAME "YOUR_USER"
#define MQTT_PASSWORD "YOUR_PASSWORD"

Тестирование подписки ESP32 на MQTT-топик

Чтобы проверить, получает ли ваша ESP32 MQTT-сообщения, в вашей консоли Digital Ocean начните публиковать различные сообщения (например, «Hi #1!», «Hi #2!» и т.д.). Замените user вашим именем пользователя и pass вашим паролем.

mosquitto_pub -h localhost -t test -m "Hi #1!" -u user -P pass
mosquitto_pub -h localhost -t test -m "Hi #2!" -u user -P pass
mosquitto_pub -h localhost -t test -m "Hi #3!" -u user -P pass
Облачный MQTT-брокер Mosquitto публикует MQTT-сообщения в ESP32 ESP8266 NodeMCU

Ваша ESP32 должна получить каждое сообщение и вывести его в Serial Monitor, как показано на изображении ниже.

ESP32 ESP8266 NodeMCU подписана на MQTT-топик и получает MQTT-сообщения от облачного MQTT-брокера

В этих простых примерах мы показали вам, как публиковать и подписываться на MQTT-сообщения, используя облачный MQTT-брокер. Идея состоит в том, чтобы использовать несколько плат ESP32 или ESP8266, которые публикуют и подписываются на одни и те же топики для обмена данными друг с другом и/или использовать :doc:`Node-RED в облаке <../access-node-red-dashboard-anywhere-digital-ocean/index>`_ для взаимодействия с этими платами.

(Дополнительно) Дальнейшие шаги – зашифрованные запросы MQTT-брокера Mosquitto

Лучший способ добавить SSL-сертификат на ваш сервер – это иметь доменное имя, указывающее на ваш сервер, и использовать сертификаты Let’s Encrypt.

Имея доменное имя и SSL-сертификаты Let’s Encrypt, следуйте инструкциям ниже для защиты вашего брокера Mosquitto.

Чтобы включить SSL-шифрование, нам нужно указать Mosquitto, где хранятся наши сертификаты Let’s Encrypt. Откройте файл конфигурации, который мы ранее начали настраивать:

sudo nano /etc/mosquitto/mosquitto.conf

Добавьте следующие строки, чтобы ваш default.conf добавил сертификаты Let’s Encrypt.

allow_anonymous false
password_file /etc/mosquitto/passwd

listener 1883 localhost

listener 8883
certfile /etc/letsencrypt/live/example.com/cert.pem
cafile /etc/letsencrypt/live/example.com/chain.pem
keyfile /etc/letsencrypt/live/example.com/privkey.pem

Listener 1883 – это стандартный незашифрованный порт MQTT. Параметр localhost указывает Mosquitto привязать этот порт только к интерфейсу localhost, поэтому он больше не доступен извне.

С другой стороны, listener 8883 настраивает зашифрованный слушатель на порту 8883. Следующие три строки указывают Mosquitto на соответствующие файлы Let’s Encrypt для настройки зашифрованных соединений.

Сохраните и выйдите из файла (Ctrl+X, Y, клавиша Enter), затем перезапустите Mosquitto для применения настроек:

sudo systemctl restart mosquitto

Обновите брандмауэр, чтобы разрешить подключения на порт 8883.

sudo ufw allow 8883

Теперь подпишитесь на тестовый MQTT-топик через зашифрованный порт (8883). Не забудьте заменить example.com вашим доменным именем в командах подписки и публикации.

mosquitto_sub -h example.com -t test -p 8883 --capath /etc/ssl/certs/ -u user -P pass

Вы можете публиковать зашифрованные сообщения:

mosquitto_pub -h example.com -t test -m "Secure message" -p 8883 --capath /etc/ssl/certs/ -u user -P pass

С этой настройкой вам нужно будет подготовить вашу ESP32/ESP8266 для выполнения зашифрованных MQTT-запросов на порту 8883.

Заключение

Это полное руководство было протестировано и должно работать. Здесь много шагов, и они должны быть выполнены именно так, как мы описываем, в правильном порядке. В противном случае что-то может не работать правильно.

Во всех наших руководствах и проектах мы всегда стараемся помочь, если кто-то застрял. Однако в данном конкретном случае существует так много шагов, что может быть сложно помочь вам без доступа к серверу и его тестирования (конечно, у нас нет ресурсов для персональной помощи каждому).

Если у вас возникли проблемы с установкой MQTT-брокера Mosquitto, подготовкой вашего сервера Linux Ubuntu, запуском Node-RED или установкой SSL-сертификата, обратитесь в службу поддержки Digital Ocean и опишите, что именно происходит. Я использую их сервис с 2015 года, и у них всегда чрезвычайно отзывчивая служба поддержки (или просто используйте их форум).

Теперь, если вы хотите установить Node-RED на Digital Ocean, следуйте следующему руководству: :doc:`Access Node-RED Dashboard from Anywhere using Digital Ocean <../access-node-red-dashboard-anywhere-digital-ocean/index>`_.

Если вам нравится этот тип проектов, обязательно ознакомьтесь с нашим курсом SMART HOME, где вы узнаете, как настроить систему домашней автоматизации с использованием MQTT, Node-RED, InfluxDB и многого другого:

Прочитайте следующие руководства, чтобы узнать больше о MQTT:


Источник: :doc:`Run Your Cloud MQTT Mosquitto Broker (access from anywhere using Digital Ocean) <../cloud-mqtt-mosquitto-broker-access-anywhere-digital-ocean/index>`_