ESP8266 как multicast транслятор в MQTT
Продолжая тему управления Xiaomi Gateway. Решение на Node-Red с двумя UDP нодами, оказалось не совсем рабочим: через какое-то время Node-Red перестает получать сообщения со слушающей ноды, при этом продолжая успешно их отправлять с другой. Вполне возможно, что две ноды, висящих на одном порту – это все таки не совсем правильно, а поэтому пришлось думать как этого избежать. А заодно попробовать и решить остальные мои To-Do.
Напомню завязку проблемы: шлюз Xiaomi находится в другом сегменте сети относительно основного сервера управления умным домом. В связи с этим невозможно получить рассылаемые шлюзом сообщения о текущем сессионном токене.
Варианты в голову приходили самые разные, включая установку еще одного НА на другую малину и размещение ее в сети смарт устройств. Но все таки я его отмел, как не самое рациональное. Но потом вспомнил, что у меня валяются несколько модулей esp8266, которые вполне можно задействовать. Все таки цена вопроса по сравнению с малиной отличается в разы, а мощностей под мою задачу esp8266 вполне достаточно.
А задачу для себя я сформулировал так: получать все мультикаст сообщения от шлюза и отправлять их в MQTT-брокер. А уж что с ними делать дальше – тут вопросов не возникает.
Сказано – сделано. До этого я использовал только ESPEasy, поэтому первым делом полез искать нет ли у них подходящих плагинов под мою задачу. Но либо плохо искал, либо хорошо спрятали, либо просто действительно нет, но ничего подходящего не нашел. Ок, хочешь сделать что-то хорошо да хоть как-нибудь – сделай это сам. Поэтому через несколько часов изыскания и попыток вспомнить как же писать на С++, родился следующий код:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>
const char* ssid = ""; // Enter your WiFi name
const char* password = ""; // Enter WiFi password
const char* mqttServer = ""; // Enter MQTT Broker name or IP
const int mqttPort = 1883;
const char* mqttUser = ""; // Enter MQTT User
const char* mqttPassword = ""; // Enter MQTT Password
unsigned int multicast_port = 9898;
IPAddress multicast_ip_addr=IPAddress(224, 0, 0, 50);
char incomingPacket[255];
WiFiUDP Udp;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
Serial.println();
Serial.printf("Connecting to %s ", ssid);
WiFi.hostname("ESP-MQTT-Translator");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("Connected to the WiFi network");
Udp.beginMulticast(WiFi.localIP(), multicast_ip_addr, multicast_port);
Serial.printf("Now listening at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), multicast_port);
client.setServer(mqttServer, mqttPort);
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
Serial.println("connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
}
void loop() {
int packetSize = Udp.parsePacket();
if (packetSize) {
Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
int len = Udp.read(incomingPacket, 255);
if (len > 0) {
incomingPacket[len] = 0;
}
char jsonPacket[255];
strcpy(jsonPacket, incomingPacket);
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, jsonPacket);
char topic[30] = "esp/";
strcat (topic, doc["sid"].as<char*>());
Serial.printf("UDP packet contents: %s\n", incomingPacket);
client.publish(topic, incomingPacket);
}
if(WiFi.status() != WL_CONNECTED) {
setup();
}
client.loop();
}
(Актуальный код всегда можно так же найти на GitHub)
Записываем значение параметров для подключения к Wi-Fi и для MQTT-брокера, заливаем его на esp через Arduino IDE и все. Теперь esp начнет слушать мультикаст сообщения от шлюза и отправлять их в MQTT в топик esp/SID_ШЛЮЗА
Для отладки получаемая информация так же пишется в консоль, и ее можно посмотреть через Arduino IDE
Ну а как модифицировать Node-Red флоу, для работы с этой информацией – напишу с следующей публикации.
Один ответ к «ESP8266 как multicast транслятор в MQTT»