ESP32:Примеры/Подключение ESP32 к Node-RED при помощи MQTT

Материал из Онлайн справочника
Перейти к: навигация, поиск

Перевод: Максим Кузьмин (Cubewriter)
Перевел 29293 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Pixel Art Mini Meow Animated.gif Черновик


Содержание

Подключение ESP32 к Node-RED при помощи MQTT

В этом примере мы продемонстрируем, как использовать панель управления Node-RED для управления GPIO-контактами ESP32 и показывать на графике данные, считанные с температурного датчика. Мы создадим простой проект, с помощью которого научимся нескольким важным вещам – тому, как настроить подписку и публикацию при помощи Node-RED.

Вот общая схема проекта, который мы сделаем:

Node-red esp32 project.png
  • ESP32 подключена к кнопке. При нажатии на эту кнопку ESP32 опубликует сообщение в топик «esp32/led/toggle», на который подписана Node-RED. Получив это сообщение, Node-RED переключит состояние у переключателя «LED» на панели управления;
  • Когда состояние у переключателя «LED» на панели управления изменится, сообщение об этом будет опубликовано в топик «esp32/led», на который подписана плата ESP32. Таким образом, получив это сообщение, ESP32 переключит состояние подключенного к ней светодиода (вместо него можно использовать любое другое устройство вывода данных);
  • ESP32 будет считывать данные о температуре с температурного датчика DS18B20 и публиковать их в топик «esp32/temperature»;
  • Node-RED подписана на топик «esp32/temperature» и потому будет получать температурные данные от датчика DS18B20, а затем публиковать их в график.

Справочная информация

Использование MQTT с ESP32: введение

Этот Раздел будет введением в тему MQTT и то, как ее можно использовать вместе с ESP32.

Аббревиатура MQTT означает «message queuing telemetry transport», что можно перевести как «передача сообщений о телеметрии при помощи очереди». Это упрощенная система публикации и подписки, позволяющая публиковать сообщения и, будучи клиентом, получать их.

Publish-subscribe.png

MQTT – это простой протокол передачи данных, предназначенный для устройств с низкой пропускной способностью. Это делает его идеальным для проектов в области интернета вещей. MQTT позволяет отправлять команды для управления устройствами вывода данных, считывать и публиковать данные от датчиков и многое другое.

Базовые концепты MQTT

В MQTT есть несколько базовых концептов, которые нужно знать и понимать:

  • Публикация/подписка;
  • Сообщения;
  • Топики;
  • Брокер;
Публикация/подписка

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

Publish-subscribe 2.png

Для примера представьте такую ситуацию:

  • Устройство 1 публикует данные в топик;
  • Устройство 2 подписано на топик, куда публикует свои данные Устройство 1;
  • Это позволяет Устройству 2 получать сообщения Устройства 1;

Сообщения – это фрагменты информации, переходящие от одного устройства к другому. Это могут быть и данные, и команды.

Топики

Еще один важный концепт MQTT – это топики. Для устройства-отправителя это место, куда оно может публиковать свои сообщения, а для устройства-получателя это место, к сообщениям которого оно может проявить заинтересованность.

Топики представляются в виде строк, разбитых на части при помощи прямых слешей («/»). Каждый слеш означает уровень топика. Ниже – пример топика для лампы, находящейся кабинете, который в свою очередь находится у вас дома.

Topic levels.png

Примечание: Топики чувствительны к регистру, поэтому топики на изображении ниже – это разные топики.

Topic levels2.PNG

Итак, если представить сценарий, при котором вы управляете лампой в своем домашнем кабинете при помощи ESP32 и MQTT, то он будет выглядеть примерно так:

MQTT home-office-lamp.png
  1. У нас есть устройство, которое публикует сообщения «вкл» и «выкл» в топик «home/office/lamp»;
  2. На этот топик подписана ESP32, управляющая включением/выключением лампы;
  3. Таким образом, когда в этом топике публикуется новое сообщение, ESP32 получает команду «вкл» или «выкл» и, соответственно, включает либо выключает лампу;

Первым устройством может быть ESP32, ESP8266 или контроллер, на который установлена платформа для домашней автоматизации вроде Node-RED, Home Assistant, Domoticz или OpenHAB.

Брокер

Наконец, вам также нужно понимать, что такое «брокер». Он в основном ответственен за получение всех сообщений, фильтрацию сообщений, принятие решений о том, кто в них заинтересован, и отправку этих сообщений всем подписанным клиентам.

Mqtt broker.png

Брокеры бывают разными. Есть, к примеру, брокер Mosquitto, установленный на Raspberry Pi, или бесплатный облачный брокер CloudMQTT.

Мы будем использовать брокер Mosquitto, установленный на Raspberry Pi.

Итого

Итак, в этом Разделе мы научились следующему:

  • MQTT – это коммуникационный протокол, хорошо подходящий для проектов в области интернета вещей;
  • В MQTT устройства могут публиковать сообщения в топики и быть подписаны на другие топики, чтобы получать их сообщения;
  • При использовании MQTT необходим брокер. Он получает все сообщения и отправляет их подписанным клиентам;

Node-RED

Этот Раздел – краткое введение в тему Node-RED. Здесь мы расскажем о том, что такое Node-RED и как ее установить. Мы также покажем, как установить ноды панели управления Node-RED.

Node-red-icon.png

Примечание: Этот Раздел не предназначен для того, чтобы научить вас создавать сложные потоки при помощи платформы Node-RED или объяснять, как работает весь ее функционал. В этом и следующем Разделах мы лишь предоставим необходимую информацию о том, как подключить ESP32 к Node-RED при помощи коммуникационного протокола MQTT. Многие мейкеры используют Node-RED для своих проектов в сфере домашней автоматизации, и им может быть интересно, как наладить коммуникацию между ESP32 и Node-RED. Эти два Раздела предназначены как раз для этой аудитории.

Что такое Node-RED?

Node-RED – это мощный open-source инструмент для создания проектов в области интернета вещей при помощи визуального программирования.

Визуальное программирование – это способ создания программ с помощью подключения друг к другу блоков кода (называемых «нодами»), что сильно упрощает значительную часть программирования. Последовательность подключенных друг к другу нод называется «потоком».

Node red browser window 1.PNG

Почему Node-RED – это хорошее решение?

Node-RED – это open-source проект, который разработан IBM и отлично работает на Raspberry Pi.

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

Что можно сделать при помощи Node-RED?

Node-RED упрощает:

  • Доступ к GPIO-контактам Raspberry Pi;
  • Настройку MQTT-коммуникации с другими платами (ESP32, ESP8266, Arduino и т.д.);
  • Создание отзывчивого GUI для проектов (при помощи панели управления Node-RED);
  • Коммуникацию со сторонними сервисами (IFTTT.com, Adafruit.io, Thing Speak и т.д.);
  • Считывание данных из сети (прогнозы погоды, курсы акций, имейлы и т.д.);
  • Создание событий, управляемых с помощью времени;
  • Хранение и считывание информации из базы данных;

Вот библиотека с примерами потоков и нод для Node-RED.

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

Нам нужно установить в IDE Arduino необходимые библиотеки, которые понадобятся для того, чтобы использовать вместе с ESP32 протокол MQTT – «AsyncTCP» и «async MQTT client».

Устанавливаем библиотеку «AsyncTCP»

  1. Кликните тут, чтобы загрузить ZIP-архив библиотеки;
  2. Распакуйте скачанный архив. У вас должна получиться папка «AsyncTCP-master»;
  3. Переименуйте ее на «AsyncTCP»;
  4. Переместите папку «AsyncTCP» в папку «libraries», которая находится в папке, куда установлена ваша IDE Arduino;
  5. Перезапустите IDE Arduino если она была запущена;

Устанавливаем библиотеку «async MQTT client»

  1. Кликните тут, чтобы загрузить ZIP-архив библиотеки;
  2. Распакуйте скачанный архив. У вас должна получиться папка «async-mqtt-client-master»;
  3. Переименуйте ее на «async_mqtt_client»;
  4. Переместите папку «async_mqtt_client» в папку «libraries», которая находится внутри папки, куда установлена ваша IDE Arduino;
  5. Перезапустите IDE Arduino если она была запущена;

Нам также нужно установить библиотеки «OneWire» (автор – Пол Стоффреген) и «Arduino Temperature Control» – они необходимы для использования датчика DS18B20.

Устанавливаем библиотеку «OneWire»

  1. Кликните тут, чтобы скачать ZIP-архив библиотеки;
  2. Распакуйте скачанный архив. У вас должна получиться папка «OneWire-master»;
  3. Переименуйте папку «OneWire-master» на «OneWire»;
  4. Переместите папку «OneWire» в папку «libraries», которая находится внутри папки, куда установлена ваша IDE Arduino;
  5. Перезапустите IDE Arduino если она была запущена;

Устанавливаем библиотеку «Arduino Temperature Control»

  1. Кликните тут, чтобы скачать ZIP-архив библиотеки;
  2. Распакуйте скачанный архив. У вас должна получиться папка «Arduino-Temperature-Control-Library-master»;
  3. Переименуйте папку «Arduino-Temperature-Control-Library-master» на «DallasTemperature»;
  4. Переместите папку «DallasTemperature» в папку «libraries», находящуюся внутри папки, куда установлена ваша IDE Arduino;
  5. Перезапустите IDE Arduino если она была запущена;

Установка MQTT-брокера Mosquitto на Raspberry Pi

В этом Разделе мы установим брокер Mosquitto на Raspberry Pi. Как уже говорилось в предыдущем разделе, брокер в основном ответственен за получение всех сообщений, фильтрацию сообщений, принятие решение о том, кто в них заинтересован, и публикацию этих сообщений для всех подписанных клиентов.

Mqtt broker.png

Брокеры бывают разными. В этом примере мы будем использовать брокер Mosquitto, установленный на Raspberry Pi.

Примечание: Вы также можете воспользоваться бесплатным брокером CloudMQTT (он поддерживает до 5 подключенных устройств). О том, как использовать его вместе с ESP32, можно почитать тут.

Откройте новое окно терминала Raspberry Pi.

Чтобы установить брокер Mosquitto, введите следующие команды:

  1. sudo apt update
  2. sudo apt install -y mosquitto mosquitto-clients

Чтобы Mosquitto автоматически запускался при загрузке, впишите следующее:

sudo systemctl enable mosquitto.service

Проверяем, установлен ли Mosquitto

Отправляем команду:

mosquitto -v

Эта команда возвращает версию Mosquitto, установленную на Raspberry Pi. Она должна быть 1.4.x или выше.

Примечание: Иногда после введения команды «mosquitto -v» может появиться сообщение-предупреждение «Error: Address already in use». Оно значит, что брокер Mosquitto уже запущен, поэтому ничего страшного в нем нет.

IP-адрес Raspberry Pi

Чтобы узнать IP-адрес своей Raspberry Pi, впишите в терминал следующую команду:

hostname -I
Rpi hostname i terminal 1.PNG

В нашем случае IP-адрес Raspberry Pi – это «192.168.1.2». Сохраните его, т.к. он понадобится нам далее, чтобы ESP32 можно было подключить к MQTT-брокеру Mosquitto.

Итого

Итак, в этом Разделе мы научились устанавливать брокер Mosquitto на Raspberry Pi.

Устанавливаем Node-RED

Node-RED устанавливается на Raspberry Pi очень быстро и просто. Откройте терминал Raspberry Pi и введите туда следующую команду:

bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)

Через несколько минут установка должна завершиться.

Настраиваем автоматический запуск Node-RED при загрузке

Чтобы Node-RED автоматически запускалась при загрузке Raspberry Pi, вам нужно ввести следующую команду:

sudo systemctl enable nodered.service

Теперь перезапустите Raspberry Pi, чтобы автозапуск вступил в силу:

sudo reboot

Ищем IP-адрес Raspberry Pi

Чтобы узнать IP-адрес Raspberry Pi, впишите в терминале следующую команду:

hostname -I
Rpi hostname i terminal 1.PNG

В моем случае IP-адрес Raspberry Pi – это «192.168.1.2». Сохраните IP-адрес, который получился у вас, потому что он еще пригодится нам в этом и следующем Разделах.

Проверяем, установилась ли Node-RED

Когда Raspberry Pi снова включится, мы можем протестировать установку Node-RED, введя в браузере IP-адрес Raspberry Pi, который мы узнали выше, а после него – номер порта «1880».

http://IP_АДРЕС_ВАШЕЙ_RPi:1880

В моем случаем он выглядит так:

http://192.168.1.2:1880

В результате в браузере должна загрузиться вот такая страница:

Node red browser window 2.PNG

Обзор интерфейса Node-RED

В левой части находится список блоков. Эти блоки называются нодами, и они разделены на группы по функциональности. Выбрав ноду, взгляните на вкладку info – там должна появиться информация о том, как работает выбранная нода.

В центре расположена область для потока – сюда вы будете помещать свои ноды.

Node-red gui.png

Установка панели управления Node-RED

Панель управления Node-RED – это набор нод, предоставляющих инструменты для создания пользовательского интерфейса, который оснащен кнопками, графиками, текстом и так далее.

Более подробно о панели управления Node-RED можно почитать по этим ссылкам:

Чтобы установить панель управления Node-RED, перейдите в меню Settings (это кнопка с тремя горизонтальными полосками в правом верхнем углу страницы) и нажмите на Manage palette:

Node red manage palette 1.PNG

Откроется меню пользовательских настроек – User Settings. Кликните на вкладку Install, вбейте в поиске «node-red-dashboard» и нажмите на кнопку Install:

Node red manage palette 2.PNG

Закройте это меню. В левой панели появится новая группа нодов под названием «dashboard»:

Node red dashboard 1.PNG

Теперь у вас все готово, чтобы встроить Node-RED в систему с ESP32 и создать пользовательский интерфейс для взаимодействия с ESP32.

Создаем поток Node-RED

Перед созданием потока на вашей Raspberry Pi должны быть установлены:

Импортируем поток

После этого импортируем поток Node-RED. Для этого копируем RAW-версию этого потока:

[{"id":"9e58624.7faaba","type":"mqtt out","z":"c02b79b2.501998","name":"","topic":"esp32/led","qos":"","retain":"","broker":"10e78a89.5b4fd5","x":740,"y":520,"wires":[]},{"id":"abf7079a.653be8","type":"mqtt in","z":"c02b79b2.501998","name":"","topic":"esp32/temperature","qos":"2","broker":"10e78a89.5b4fd5","x":430,"y":300,"wires":[["cc79021b.9a751","46e7770d.86d9e8"]]},{"id":"83cf37cf.c76988","type":"ui_switch","z":"c02b79b2.501998","name":"","label":"LED","group":"61285987.c20328","order":0,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"","style":"","onvalue":"on","onvalueType":"str","onicon":"","oncolor":"","offvalue":"off","offvalueType":"str","officon":"","offcolor":"","x":590,"y":520,"wires":[["9e58624.7faaba"]]},{"id":"cc79021b.9a751","type":"debug","z":"c02b79b2.501998","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":630,"y":260,"wires":[]},{"id":"dd25cb97.5921d8","type":"mqtt in","z":"c02b79b2.501998","name":"","topic":"esp32/led/toggle","qos":"2","broker":"10e78a89.5b4fd5","x":420,"y":480,"wires":[["83cf37cf.c76988","b9659d3c.bf3d3"]]},{"id":"b9659d3c.bf3d3","type":"debug","z":"c02b79b2.501998","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":610,"y":440,"wires":[]},{"id":"46e7770d.86d9e8","type":"ui_chart","z":"c02b79b2.501998","name":"","group":"61285987.c20328","order":0,"width":0,"height":0,"label":"Temperature","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"x":630,"y":340,"wires":[[],[]]},{"id":"10e78a89.5b4fd5","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"61285987.c20328","type":"ui_group","z":"","name":"Main","tab":"e7c46d5e.a1283","disp":true,"width":"6","collapse":false},{"id":"e7c46d5e.a1283","type":"ui_tab","z":"","name":"Dashboard","icon":"dashboard"}]

Далее в Node-RED жмем на кнопку в правом верхнем углу (с тремя горизонтальными полосками), а затем на Import > Clipboard.

Node red import clipboard 1.PNG

Затем вставляем скопированный поток в поле и жмем на кнопку Import.

Node red import clipboard 2.PNG

В поток должны загрузиться следующие ноды:

Node red import clipboard 3.PNG

Внеся в поток необходимые изменения, кликните на кнопку Deploy, чтобы сохранить их.

Node red import clipboard 4.PNG

Что это за поток

Теперь давайте поближе взглянем на каждую ноду этого потока, чтобы понять, как он работает.

Нода MQTT-подписки (mqtt in)

Самая первая нода – это нода MQTT-подписки (mqtt in). Если дважды кликнуть по ней, откроется такое окно:

Node red mqtt node esp32 temp 1.PNG

В этой ноде можно задать топик, на который вы хотите подписаться. В данном случае мы подписываемся на топик «esp32/temperature», чтобы получать от него данные о температуре.

В поле Server вписывается IP-адрес MQTT-брокера. В нашем случае брокер Mosquitto и Node-RED работают на одной и той же Raspberry Pi, что позволяет нам использовать «localhost».

В поле QoS вписывается уровень качества обслуживания MQTT, а в поле Name – название ноды.

Нода графика (chart)

При помощи этой ноды мы, получив из топика «esp32/temperature» данные о температуре, будем показывать их на графике. Дважды кликните по этой ноде – откроется новое окно, где можно отредактировать свойства этой ноды.

Esp32 node-red mqtt node chart temp 1.PNG

Еще одна нода MQTT-подписки (mqtt in)

Это вторая в потоке MQTT-нода для подписки, но теперь – на топик «esp32/led/toggle», в который будут приходить данные об управлении (включении/выключении) светодиодом. В него может прийти сообщение «on» или «off».

Esp32 node-red mqtt node led toggle 1.PNG

Нода переключателя светодиода (switch)

Сконструированная нами система позволит управлять светодиодом двумя способами:

  • При помощи программного переключателя на панели управления Node-RED. В этом случае при изменении положения переключателя в топик «esp32/led» будет опубликовано MQTT-сообщение, дающее команду включить/выключить светодиод;
  • При помощи нажатия на аппаратную кнопку, подключенную к ESP32. После нажатия на нее ESP32 опубликует в топик «esp32/led/toggle» соответствующее сообщение. Поскольку на этот топик подписан программный переключатель на панели управления Node-RED (о котором рассказывалось выше), он автоматически переключится согласно присланному сообщению и, соответственно, изменит состояние светодиода.
Esp32 node red mqtt node led switch 1.PNG

Нода MQTT-публикации (mqtt out)

Это нода для публикации MQTT-сообщения от переключателя светодиода в топик «esp32/led».

Esp32 node red mqtt node esp32 led out 1.PNG

Логику взаимодействия этих нод будет проще понять, если взглянуть на схему проекта в самом начале этого руководства.

Настройки MQTT-брокера

Все вышесказанное строится на том, что Node-RED и MQTT-брокер установлены на одной и той же Raspberry Pi. Но если вы используете другой MQTT-брокер, то вам нужно будет сделать еще кое-что. Во-первых, дважды кликните по одной из MQTT-нод:

Esp32 node red mqtt broker settings 1.PNG

Затем нажмите на кнопку Edit рядом с полем Server:

Esp32 node red mqtt broker settings 2.PNG

Впишите туда IP-адрес и номер порта вашего MQTT-сервера:

Esp32 node red mqtt broker settings 3.PNG

Примечание: Поскольку в нашем случае брокер Mosquitto работает на Raspberry Pi локально, мы можем оставить в поле Server «localhost», а в поле Port – «1883». В вашем случае эти настройки, возможно, нужно будет поменять (и сохранить внесенные изменения), чтобы Node-RED могла установить MQTT-подключение с вашим брокером.

Панель управления Node-RED

Итак, проект готов. Чтобы открыть панель управления Node-RED и посмотреть, как выглядит наше приложение, откройте любой браузер в вашей локальной сети и впишите туда следующее:

http://IP-адрес-вашей-Raspberry-Pi:1880/ui

Ваше приложение должно выглядеть примерно как на скриншоте ниже:

Esp32 node red dashboard 1.PNG

Что нужно сделать перед загрузкой кода

Чтобы этот скетч заработал сразу, вставьте в трех строчках ниже SSID и пароль для своей WiFi-сети, а также IP-адрес MQTT-брокера.

  1. // впишите в двух строчках ниже SSID и пароль для своей WiFi-сети,
  2. // чтобы ваша ESP32 могла подключиться к WiFi-роутеру:
  3. #define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
  4. #define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"
  5.  
  6. // вставьте в переменную «MQTT_HOST» IP-адрес своей Raspberry Pi,
  7. // чтобы ESP32 могла подключиться к MQTT-брокеру Mosquitto:
  8. #define MQTT_HOST IPAddress(192, 168, 1, X)

Температура в градусах Цельсия/Фаренгейта

По умолчанию этот скетч публикует температуру в градусах Цельсия. Если вы хотите, чтобы он публиковал температуру в градусах Фаренгейта, перейдите в блок loop() и закомментируйте вот эти две строчки кода:

  1.     // публикуем в топик «esp32/temperature»
  2.     // MQTT-сообщение с температурой в градусах Цельсия:
  3.     // uint16_t packetIdPub2 = mqttClient.publish("esp32/temperature",
  4.     // 2, true, String(sensors.getTempCByIndex(0)).c_str());

Затем раскомментируйте вот эти две строчки:

  1.     // публикуем в топик «esp32/temperature»
  2.     // MQTT-сообщение с температурой в градусах Фаренгейта:
  3.     uint16_t packetIdPub2 = mqttClient.publish("esp32/temperature",
  4.     2, true, String(sensors.getTempFByIndex(0)).c_str());

Демонстрация

Попробуйте включить/выключить светодиод, щелкая переключатель «LED»:

Esp32 node red dashboard 1.PNG

Кроме того, если нажать на кнопку, подключенную к ESP32, это тоже должно изменить состояние светодиода, т.к. его автоматически обновляет переключатель на панели управления Node-RED.

Наконец, каждые 10 секунд на графике будут показываться новые данные о температуре от датчика DS18B20.

Итого

В этом проекте-примере мы продемонстрировали, как настроить коммуникацию между ESP32 и Node-RED при помощи MQTT. В частности, мы показали, как публиковать в топик (чтобы управлять контактами ESP32) и подписываться на топики (чтобы получать команды и данные о температуре).

Теперь вы можете без труда создать систему для управления ESP32 при помощи панели управления Node-RED – например, для какого-нибудь проекта домашней автоматизации.

Необходимое оборудование

Схема

Esp32 mqtt rpi 1.PNG

Код

  1. /*********
  2.   Руи Сантос
  3.   Более подробно о проекте на: https://randomnerdtutorials.com  
  4. *********/
  5.  
  6. #include <WiFi.h>
  7. extern "C" {
  8.   #include "freertos/FreeRTOS.h"
  9.   #include "freertos/timers.h"
  10. }
  11. #include <AsyncMqttClient.h>
  12. #include <OneWire.h>
  13. #include <DallasTemperature.h>
  14.  
  15. // впишите в двух строчках ниже SSID и пароль для своей WiFi-сети,
  16. // чтобы ваша ESP32 могла подключиться к WiFi-роутеру:
  17. #define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
  18. #define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"
  19.  
  20. // вставьте в переменную «MQTT_HOST» IP-адрес своей Raspberry Pi,
  21. // чтобы ESP32 могла подключиться к MQTT-брокеру Mosquitto:
  22. #define MQTT_HOST IPAddress(192, 168, 1, X)
  23. #define MQTT_PORT 1883
  24.  
  25. // создаем объекты для управления MQTT-клиентом:
  26. AsyncMqttClient mqttClient;
  27. TimerHandle_t mqttReconnectTimer;
  28. TimerHandle_t wifiReconnectTimer;
  29.  
  30. unsigned long previousMillis = 0;  // время, когда в последний раз
  31.                                    // была опубликована температура
  32. const long interval = 10000;       // интервал, с которым будут
  33.                                    // публиковаться данные от датчика
  34.  
  35. const int ledPin = 25;             // GPIO-контакт,
  36.                                    // к которому подключен светодиод
  37. int ledState = LOW;                // текущее состояние
  38.                                    // выходного контакта
  39.  
  40. // GPIO-контакт, к которому подключен датчик DS18B20:
  41. const int oneWireBus = 27;          
  42. // создаем объект «oneWire» для коммуникации с OneWire-устройствами:
  43. OneWire oneWire(oneWireBus);
  44. // передаем объект «oneWire» объекту температурного датчика:
  45. DallasTemperature sensors(&oneWire);
  46.  
  47. const int buttonPin = 32;            // задаем GPIO-контакт,
  48.                                      // к которому подключена кнопка
  49. int buttonState;                     // текущее состояние
  50.                                      // входного контакта (кнопки)
  51. int lastButtonState = LOW;           // предыдущее состояние
  52.                                      // входного контакта (кнопки)
  53. unsigned long lastDebounceTime = 0;  // время, когда в последний раз
  54.                                      // был переключен
  55.                                      // выходной контакт
  56. unsigned long debounceDelay = 50;    // время антидребезга
  57.                                      // (увеличьте это значение,
  58.                                      //  если выходной сигнал
  59.                                      //  по-прежнему «прыгает»)
  60.  
  61. void connectToWifi() {
  62.   Serial.println("Connecting to Wi-Fi...");
  63.              //  "Подключаемся к WiFi..."
  64.   WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  65. }
  66.  
  67. void connectToMqtt() {
  68.   Serial.println("Connecting to MQTT...");
  69.              //  "Подключаемся к MQTT..."
  70.   mqttClient.connect();
  71. }
  72.  
  73. void WiFiEvent(WiFiEvent_t event) {
  74.   Serial.printf("[WiFi-event] event: %d\n", event);
  75.   switch(event) {
  76.     case SYSTEM_EVENT_STA_GOT_IP:
  77.       Serial.println("WiFi connected");  //  "Подключились к WiFi"
  78.       Serial.println("IP address: ");  //  "IP-адрес: "
  79.       Serial.println(WiFi.localIP());
  80.       connectToMqtt();
  81.       break;
  82.     case SYSTEM_EVENT_STA_DISCONNECTED:
  83.       Serial.println("WiFi lost connection");
  84.                  //  "WiFi-связь потеряна"
  85.       // делаем так, чтобы
  86.       // ESP32 не переподключалась к MQTT
  87.       // во время переподключения к WiFi:
  88.       xTimerStop(mqttReconnectTimer, 0);
  89.       xTimerStart(wifiReconnectTimer, 0);
  90.       break;
  91.   }
  92. }
  93.  
  94. // в этой функции можно добавить новые топики для подписки:
  95. void onMqttConnect(bool sessionPresent) {
  96.   Serial.println("Connected to MQTT.");  //  "Подключились к MQTT."
  97.   Serial.print("Session present: ");  //  "Текущая сессия: "
  98.   Serial.println(sessionPresent);
  99.   // подписываем ESP32 на топик «esp32/led»:
  100.   uint16_t packetIdSub = mqttClient.subscribe("esp32/led", 0);
  101.   Serial.print("Subscribing at QoS 0, packetId: ");
  102.            //  "Подписываемся при QoS 0, ID пакета: "
  103.   Serial.println(packetIdSub);
  104. }
  105.  
  106. void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  107.   Serial.println("Disconnected from MQTT.");
  108.              //  "Отключились от MQTT."
  109.   if (WiFi.isConnected()) {
  110.     xTimerStart(mqttReconnectTimer, 0);
  111.   }
  112. }
  113.  
  114. void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
  115.   Serial.println("Subscribe acknowledged.");
  116.              //  "Подписка подтверждена."
  117.   Serial.print("  packetId: ");  //  "  ID пакета: "
  118.   Serial.println(packetId);
  119.   Serial.print("  qos: ");  //  "  уровень качества обслуживания: "
  120.   Serial.println(qos);
  121. }
  122.  
  123. void onMqttUnsubscribe(uint16_t packetId) {
  124.   Serial.println("Unsubscribe acknowledged.");
  125.              //  "Отписка подтверждена."
  126.   Serial.print("  packetId: ");  //  "  ID пакета: "
  127.   Serial.println(packetId);
  128. }
  129.  
  130. void onMqttPublish(uint16_t packetId) {
  131.   Serial.println("Publish acknowledged.");
  132.              //  "Публикация подтверждена."
  133.   Serial.print("  packetId: ");  //  "  ID пакета: "
  134.   Serial.println(packetId);
  135. }
  136.  
  137. // в этой функции задается, что произойдет,
  138. // когда ESP32 получит то или иное сообщение в топик «esp32/led»
  139. // (эту функцию можно отредактировать):
  140. void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
  141.   String messageTemp;
  142.   for (int i = 0; i < len; i++) {
  143.     //Serial.print((char)payload[i]);
  144.     messageTemp += (char)payload[i];
  145.   }
  146.   // проверяем, пришло ли MQTT-сообщение в топик «esp32/led»:
  147.   if (strcmp(topic, "esp32/led") == 0) {
  148.     // если светодиод выключен, включаем его (и наоборот):
  149.     if (messageTemp == "on") {
  150.       digitalWrite(ledPin, HIGH);
  151.     }
  152.     else if (messageTemp == "off") {
  153.       digitalWrite(ledPin, LOW);
  154.     }
  155.   }
  156.  
  157.   Serial.println("Publish received.");  
  158.              //  "Опубликованные данные получены."
  159.   Serial.print("  message: ");  //  "  сообщение: "
  160.   Serial.println(messageTemp);
  161.   Serial.print("  topic: ");  //  "  топик: "
  162.   Serial.println(topic);
  163.   Serial.print("  qos: ");  //  "  уровень качества обслуживания: "
  164.   Serial.println(properties.qos);
  165.   Serial.print("  dup: ");  //  "  дублирование сообщения: "
  166.   Serial.println(properties.dup);
  167.   Serial.print("  retain: ");  //  "  сохраненные сообщения: "
  168.   Serial.println(properties.retain);
  169.   Serial.print("  len: ");  //  "  размер: "
  170.   Serial.println(len);
  171.   Serial.print("  index: ");  //  "  индекс: "
  172.   Serial.println(index);
  173.   Serial.print("  total: ");  //  "  суммарно: "
  174.   Serial.println(total);
  175. }
  176.  
  177. void setup() {
  178.   // запускаем датчик DS18B20:
  179.   sensors.begin();
  180.  
  181.   // делаем контакт светодиода выходным (OUTPUT)
  182.   // и задаем ему значение «LOW»:
  183.   pinMode(ledPin, OUTPUT);
  184.   digitalWrite(ledPin, LOW);
  185.  
  186.   // делаем контакт кнопки входным (INPUT):
  187.   pinMode(buttonPin, INPUT);
  188.  
  189.   Serial.begin(115200);
  190.  
  191.   mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
  192.   wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));
  193.  
  194.   WiFi.onEvent(WiFiEvent);
  195.  
  196.   mqttClient.onConnect(onMqttConnect);
  197.   mqttClient.onDisconnect(onMqttDisconnect);
  198.   mqttClient.onSubscribe(onMqttSubscribe);
  199.   mqttClient.onUnsubscribe(onMqttUnsubscribe);
  200.   mqttClient.onMessage(onMqttMessage);
  201.   mqttClient.onPublish(onMqttPublish);
  202.   mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  203.  
  204.   connectToWifi();
  205. }
  206.  
  207. void loop() {
  208.   unsigned long currentMillis = millis();
  209.   // каждые Х секунд («interval» = 5 секунд)
  210.   // ESP32 будет публиковать новое MQTT-сообщение
  211.   // в топик «esp32/temperature»:
  212.   if (currentMillis - previousMillis >= interval) {
  213.     // сохраняем время, когда в последний раз
  214.     // были опубликованы новые данные от датчика:
  215.     previousMillis = currentMillis;
  216.     // новые температурные данные:
  217.     sensors.requestTemperatures();
  218.  
  219.     // публикуем в топик «esp32/temperature»
  220.     // MQTT-сообщение с температурой в градусах Цельсия:
  221.     uint16_t packetIdPub2 = mqttClient.publish("esp32/temperature", 2,
  222.     true, String(sensors.getTempCByIndex(0)).c_str());
  223.                            
  224.     // публикуем в топик «esp32/temperature»
  225.     // MQTT-сообщение с температурой в градусах Фаренгейта:
  226.     // uint16_t packetIdPub2 = mqttClient.publish("esp32/temperature",
  227.     // 2, true, String(sensors.getTempFByIndex(0)).c_str());
  228.                            
  229.     Serial.print("Publishing on topic esp32/temperature at QoS 2, packetId: ");
  230.              //  "Публикуем в топик «esp32/temperature»
  231.              //   при QoS 2, ID пакета: "
  232.     Serial.println(packetIdPub2);
  233.   }
  234.  
  235.   // считываем состояние кнопки
  236.   // и сохраняем его в локальную переменную:
  237.   int reading = digitalRead(buttonPin);
  238.  
  239.   // если состояние кнопки изменилось (из-за шума или нажатия),
  240.   // сбрасываем таймер:
  241.   if (reading != lastButtonState) {
  242.     // сбрасываем таймер «антидребезга»:
  243.     lastDebounceTime = millis();
  244.   }
  245.  
  246.   // если состояние кнопки изменилось после периода «антидребезга»:
  247.   if ((millis() - lastDebounceTime) > debounceDelay) {
  248.     // и если новое значение отличается от того,
  249.     // что хранится сейчас в переменной «buttonState»:
  250.     if (reading != buttonState) {
  251.       buttonState = reading;
  252.       // публикуем MQTT-сообщение в топик «esp32/led/toggle»
  253.       // чтобы переключить состояние светодиода
  254.       // (т.е. чтобы включить или выключить его):
  255.       if ((buttonState == HIGH)) {
  256.         if (!digitalRead(ledPin)) {
  257.           mqttClient.publish("esp32/led/toggle", 0, true, "on");
  258.           Serial.println("Publishing on topic esp32/led/toggle topic at QoS 0");
  259.                      //  "Публикуем в топик «esp32/led/toggle»
  260.                      //   при QoS 0"
  261.         }
  262.         else if (digitalRead(ledPin)) {
  263.           mqttClient.publish("esp32/led/toggle", 0, true, "off");
  264.           Serial.println("Publishing on topic esp32/led/toggle topic at QoS 0");
  265.                      //  "Публикуем в топик «esp32/led/toggle»
  266.                      //   при QoS 0"
  267.         }
  268.       }
  269.     }
  270.   }
  271.   // сохраняем новое значение кнопки в переменную «lastButtonState»;
  272.   // в результате при следующем проходе через loop()
  273.   // новое значение кнопки будет считаться ее предыдущим значением:
  274.   lastButtonState = reading;
  275. }

См.также

Внешние ссылки