Настройка MQTT на ThingSpeak и CloudMQTT для работы с IoT устройствами

Для ‘быстрого прототипирования устройств удобно использовать MQTT брокеры с конструкторами мобильных приложений, вроде IoT MQTT Panel. У распространенных MQTT broker-ов есть один недостаток — у них нет встроенной базы данных, т.е. они только принимают и передают сообщения.

ThingSpeak выгодно отличается в этом плане, поскольку поддерживает работу в качестве MQTT Brocker-а и позволяет сохранять данные в своей СУБД. Удобный сервис для быстрого прототипирования IoT устройств, хотя не без проблем. 🙁

Разберемся, как использовать ThingSpeak с IoT устройствами. Приложений-конструкторов для работы с MQTT много. Для Android поиск по строке MQTT Dashboard. Я выбрал в качестве MQTT клиента для Android IoT MQTT Panel. Приложение работает идеально.

К сожалению, MQTT broker ThingSpeak-а на бесплатном аккаунте, похоже, не всегда помещает сообщения в очередь, т.е. подписка (subscribe) отрабатывает ненадежно. Кроме того есть ограничение по количеству одновременных подключений (возможно, под одним UserID). На бесплатном аккаунте количество одновременных подключений не более трех. Я специально ограничивал количество подключений до одного, сообщения все равно приходят через раз. Написал в техподдержку ThingSpeak.

При publish сообщений на ThingSpeak на бесплатном аккаунте нужно интервал отправки выставлять не менее 25 сек, а не 15 сек, как указано. Если интервал менее 25 сек, то сообщения будут пропадать.

Простой интерфейс IoT MQTT Panel позволяет очень быстро разрабатывать мобильные приложения для тестирования прототипов или для управления домашними DIY IoT устройствами.

Для тестирования передачи данных по MQTT с ThingSpeak работают следующие клиенты:

Соединение с ThingSpeak по MQTT

Для соединения с ThingSpeak нужны следующие параметры (на английском даны названия как требуются для IoT MQTT Panel:

  • Connection name — удобное имя для идентификации MQTT broker. Соединений может быть несколько.
  • Client ID — уникальный идентификатор клиента. Может быть произвольным.
  • Адрес MQTT брокера (Broker Web/IP address): mqtt.thingspeak.com
  • Номер порта (Port number) — он зависит от выбранного типа сетевого протокола и безопасности:
PortNetwork protocolEncryption
1883TCPNone
8883TCPTLS/SSL
80WebSocketNone
443WebSocketTLS/SSL
  • Device list — устройства, которые усправляются в рамкахх текущего соединения. Для каждого соединения можно задать несколько устройствсо своими панелями управления.
  • Имя пользователя (username) — можно использовать ЛЮБОЕ уникальное имя пользователя. Использовать логин, используемый для авторизации в личный кабинет ThingSpeak-а не нужно!
  • Пароль ( password ) — в качестве пароля для соединения в ThingSpeak используется MQTT API Key. Взять можно в разделе Account > My Profile.

В мобильном приложении IoT MQTT Panel:

Настройка соединения с MQTT broker ThingSpeak в IoT MQTT Panel
Добавления имени IoT устройства в IoT MQTT Panel

Передача и прием данных в ThingSpeak по MQTT

В IoT MQTT Panel для выбранного IoT устройства можно добавить несколько элементов управления (в терминологии приложения — Panel).

IoT MQTT Panel User Guide

Для некоторых элементов управления можно задать как topic для publish, так и subscribe.

  • Channel ID для нужного устройства:
  • Write/Read API Key. Доступно поссылке: https://thingspeak.com/channels/<Channel_ID>/api_keys
  • Topic для publish — при передаче данных может быть два варианта строк:
    • Одновременная передача данных для нескольких полей: channels/<Channel_ID>/publish/<WRITE_API_KEYS> — при такой строке Payload выглядит, например, так: field1=1&field2=2&field3=3. В документации в примере в конце добавлен &status=MQTTPUBLISH.
    • Передача данных для выбранного поля: channels/ <Channel_ID>/publish/fields/field<fieldnumber>/<WRITE_API_KEYS> — при такой строке поле в которое писать уже выбрано и в Payload достаточно передать значение, но ни в коем случае не field1=1. ThingSpeak такой pyload не примет.
  • Topic для subscribe — для подписки на измененния данных в облаке ThingSpeak могут использоватьсяследующие варианты строк:
    • Прием данных для выбранного поля: channels/<Channel_ID> /subscribe/fields/field <fieldnumber>/<READ_API_KEYS>
    • Получение последних доступных данных в канале: channels/<Channel_ID>/subscribe/<format>/< READ_API_KEYS>, где format: json, xml, csv. 
    • При подписке на обновление данных достаточно использовать API_KEY на чтение.
    • Если подписка идет на публичный канал, то указывать <API_KEYS> необязательно.

Пример настройки IoT MQTT Panel для ThingSpeak

Для демонстрации управления некоторым IoT устройством через приложение IoT MQTT Panel добавл следующие типы элементов управления (Panels):

  • Switch (Line switch) — переключатель изменяет поле field1 на 1 при включении и на 0, при выключении, а также подписан на обновление состояния этого поля.
  • Switch (Line switcher) — переключатель изменяет поле field1 на 1 при включении и на 0, при выключении, а также подписан на обновление состояния этого поля. Этот выключатель я добавил для демонстрации синхронного изменения состояния переключателей.
  • LED indicator — для отображения состояния «Line switch».
  • Button(OPEN DOOR) — отправка состояния кнопки в поле field2, когда кнопка нажата — 1, когда отпущена — 0.

В Topic прописываем строку <Channel_ID>/publish/fields/field<fieldnumber>/<WRITE_API_KEYS> и указываем для Payload on = 1, а для Payload off = 0, где dvtcnj fieldnumber стоит 1.

В Subscribe Topic нужно прописать строку для subscribe: channels/<Channel_ID> /subscribe/fields/field <fieldnumber>/<READ_API_KEYS>

При включении одного переключателя переключается и второй и загорается светодиод. Однако, есть плохой момент. Подписка на события MQTT broker от ThingSpeak работает крайне нестабильно.

Это не из-за приложения IoT MQTT Panel. Проблема с MQTT subscribe определенно из-за ThingSpeak. Я в ESP8266 написал код для работы с MQTT, рекомендуемый ThingSpeak. Подписался на уведомления об изменении поля field1. Затем начал отправлять publish данных в field1. Уведомления приходят также нестабильно. Причем чаще всего они вообще не приходят. Причина непонятна.

Попробовал также MQTTBox для отправки и получения сообщений по подписке. Результат такой-же, payload приходит через раз.

В общем, нужно осторожно разбираться с MQTT subscribe на ThingSpeak. Он временами перестает работать. При этом если через IoT MQTT Panel работать с cloudMQTT, то отправка MQTT работает замечательно. Publish MQTT ThingSpeak работает стабильно, данные обновляются и по subscribe корректно возвращаются.

Настройка CloudMQTT для работы с ESP8266

С настройкой CloudMQTT, в отличие от ThingSpeak, все предельно просто.

  1. Зайти на Cloudmqtt и зарегистрироваться.
  2. Нажать на зеленую кнопку “+ create new instance”, чтобы создать экземпляр MQTT cloud broker.
  3. Ввести произвольное имя экземпляра брокера, например: “MQTT_Broker_Instance” и нажать “create new instance”
  4. Зайти в CloudMQTT и выбрать созданный экземпляр MQTT брокера.
  5. На закладке details есть нужная информация:
    • Server: ????.cloudmqtt.com
    • Port: 11528
    • Логин и пароль из Details не потребуются.
  6. Нужно зайти в раздел «Users and ACL».
  1. Добавить нового пользователя задав имя и пароль.
  2. В ACLs предоставить этому пользователю доступ на чтение и запись.
  3. В Pattern нужно ОБЯЗАТЕЛЬНО выбрать созданного клиента и прописать для него pattern — #, как указано на скриншоте. Если этого не сделать, то подписка на сообщения работать не будет.
  1. Настройка закончена, можно отпавлять и подписываться на сообщения MQTT брокера.
  2. Протестировать отправку и получение сообщений можно в разделе Websocket UI. В блоке «Send Message» в Topic указываете произвольный уникальный топик. Некоторое уникальное имя переменной, на которое устройство будет отправлять данные. В поле «Message» нужно ввести произвольные данные для отправки. После нажатия на кнопку «Send» в блоке «Received messages» появится отправленное сообщение.

И пример точно такой-же проверки через Windows 10 приложение MQTTBox. Передаваемое сообщение указывается в поле Payload. Это могут быть данные различных типов (задаются в Payload type).

Код для отправки MQTT сообщений в CloudMQTT

Код для отправки и получения сообщений на ESP8266 очень простой. В данном случае задействован один PIN (LINE_SW), который управляет включением и отключением реле.

#include &lt;PubSubClient.h>
#include &lt;ESP8266WiFi.h>
#include &lt;WiFiManager.h>

#define LINE_SW   5
#define DOOR_OPEN 4

const char* mqttServer = "farmer.cloudmqtt.com"; //The server name from "Details"
const int mqttPort = 11528; //The port number from "Details"
const char* mqttUser = "test"; //The User name from "Users and ACLs"
const char* mqttPassword = "XXXXXXXXX";  //The password from "Users and ACLs"

WiFiClient espClient;
PubSubClient client(espClient);

void callback(char* topic, byte* payload, unsigned int length) {
 
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
 
  Serial.print("Message:");
  String result = "";
  for (int i = 0; i &lt; length; i++) {
    result += (char)payload[i];
  }  
  Serial.print(result);
  if (result == "on")
  {
    digitalWrite(LINE_SW, HIGH);
  }
  else
  {
    digitalWrite(LINE_SW, LOW);
  }
 
  Serial.println();
  Serial.println("-----------------------");
}

void setup() 
{
  pinMode(LINE_SW, OUTPUT); 
  pinMode(DOOR_OPEN, OUTPUT);
  Serial.begin(9600);
  //WiFi.begin(ssid, password);
  WiFiManager wifiManager;
  wifiManager.autoConnect("DomofonAP");
  
  Serial.println("Connected to WiFi successfully.");
 
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.println("Connecting to WiFi..");
  }
 
  Serial.println("Connected to the WiFi network");

  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);

  while (!client.connected()) 
  {
    Serial.println("Connecting to MQTT...");
 
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) 
    {
      Serial.println("connected");  
    } 
    else 
    {
      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
 
  client.publish("switch", "on");
  client.subscribe("switch");
}

String state = "on"; 
int lastMillis = 0;
String topic = "switch";

void loop() 
{
  client.loop();
  if (millis() - lastMillis > 60*1000)
  {
    state = (state == "off") ? "on" : "off";
    Serial.println("Change state to [" + state + "]");
    
    client.publish(topic.c_str(), state.c_str());
    lastMillis = millis();
  }
}

Полезные ссылки

Spread the love
Запись опубликована в рубрике IT рецепты. Добавьте в закладки постоянную ссылку.

Добавить комментарий