• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь Publish и Subscribe в один и тот же топик

Sever44

Member
Всем привет!
С дружеской помощью участников форума освоил передачу данных на CloudMQTT в "intopic" и считывание данных из "outtopic".
Возникла задача:
Первый модуль публикует данные в определенный топик.
Второй модуль считывает данные из ЭТОГО ЖЕ топика.
И вот это и не получается.
При ручном вводе названия топика и его содержания на сайт MQTT все исправно выводится в порт.
При подключении "передатчика", "приемник начинает повторять подключения:
Connecting to MQTT server
Connected to MQTT server
1
и в порт ничего не выводит.
Вот топики:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
int N;
const char *ssid = "***";
const char* const staPass = "***";
const char *mqtt_server = "***";
const int mqtt_port = ***;
const char *mqtt_user = "***";
const char *mqtt_pass = "***";
const char *mqtt_client_name = "Neptun";
#define BUFFER_SIZE 100

WiFiClient wclient;
PubSubClient client(wclient, mqtt_server, mqtt_port);

void setup() {
Serial.setTimeout(10);
Serial.begin(9600);
N = 0;
}

void loop() {

// подключаемся к wi-fi
if (WiFi.status() != WL_CONNECTED) {
Serial.println("...");
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.println("...");
WiFi.begin(ssid, staPass);

if (WiFi.waitForConnectResult() != WL_CONNECTED)
return;
Serial.println("WiFi connected");
}

// подключаемся к MQTT серверу
if (WiFi.status() == WL_CONNECTED) {
if (!client.connected()) {
Serial.println("Connecting to MQTT server");
if (client.connect(MQTT::Connect("Neptun")
.set_auth(mqtt_user, mqtt_pass))) {
Serial.println("Connected to MQTT server");
Serial.println("1");
} else {
Serial.println("Could not connect to MQTT server");
}
}
if (client.connected()){
client.loop();
}
}
N++;
client.publish("Nept_Mess","Message number = "+ String(N));
delay(3000);
}

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid = "***";
const char* const staPass = "***";
const char *mqtt_server = "****";
const int mqtt_port = ***;
const char *mqtt_user = "***";
const char *mqtt_pass = "***";
const char *mqtt_client_name = "Neptun";
#define BUFFER_SIZE 100

WiFiClient wclient;
PubSubClient client(wclient, mqtt_server, mqtt_port);

void setup() {
Serial.setTimeout(10);
Serial.begin(9600);
}

void loop() {

// подключаемся к wi-fi
if (WiFi.status() != WL_CONNECTED) {
Serial.println("...");
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.println("...");
WiFi.begin(ssid, staPass);

if (WiFi.waitForConnectResult() != WL_CONNECTED)
return;
Serial.println("WiFi connected");
}

// подключаемся к MQTT серверу
if (WiFi.status() == WL_CONNECTED) {
if (!client.connected()) {
Serial.println("Connecting to MQTT server");
if (client.connect(MQTT::Connect("Neptun")
.set_auth(mqtt_user, mqtt_pass))) {
Serial.println("Connected to MQTT server");
client.set_callback(callback);
client.subscribe("Nept_Mess");
Serial.println("1");
} else {
Serial.println("Could not connect to MQTT server");
}
}
if (client.connected()){
client.loop();
}
}
}

void callback(const MQTT::publish& pub)
{
Serial.println("2");
Serial.println(pub.topic());
Serial.println(pub.payload_string());
}
Шестая от конца строка без пробела после::
"void callback(const MQTT:: Publish& pub)"
Почему-то иначе в спойлере появляется какая-то рожица.

Может, я чего-то не понимаю, и это принципиально невозможно?
Или есть ошибки?
Прошу помочь.
Заранее спасибо.
 

Алексей.

Active member
С дружеской помощью участников форума освоил передачу данных на CloudMQTT в "intopic" и считывание данных из "outtopic".
Что это означает?
Вы научились выполнять публикацию и подписчиком получать сообщения, это так?
Первый модуль публикует данные в определенный топик.
На обычном ПК, вы подписчиком получаете эти сообщения, которые публикует первый модуль?
Почему-то иначе в спойлере появляется какая-то рожица.
Код дополнительно помещайте в тег CODE

Вы забыли указать окружение, в котором выполняется сборка. Нет ссылки на библиотеку mqtt, не указана версия библиотеки.
Как повторить ваш код не понятно.
 

Sever44

Member
Что это означает?
Вы научились выполнять публикацию и подписчиком получать сообщения, это так?
На обычном ПК, вы подписчиком получаете эти сообщения, которые публикует первый модуль?

Код дополнительно помещайте в тег CODE

Вы забыли указать окружение, в котором выполняется сборка. Нет ссылки на библиотеку mqtt, не указана версия библиотеки.
Как повторить ваш код не понятно.
 

Sever44

Member
Что это означает?
Вы научились выполнять публикацию и подписчиком получать сообщения, это так?

Код дополнительно помещайте в тег CODE

Вы забыли указать окружение, в котором выполняется сборка. Нет ссылки на библиотеку mqtt, не указана версия библиотеки.
Как повторить ваш код не понятно.
На обычном ПК, вы подписчиком получаете эти сообщения, которые публикует первый модуль?

Да, есть работающий проект, передающий температуру в смартфон в топик "TEMP" и включающий или выключающий нагреватель при публикации "on" или "off" в топик "Mode" в смартфоне.

Да в ПК на сайте CloudMQTT сообщения видны.

Для повторения кода нужно указать все параметры сервера mqtt_server?

Библиотека в приложенном файле
 

Вложения

Алексей.

Active member
Да, есть работающий проект, передающий температуру в смартфон в топик "TEMP" и включающий или выключающий нагреватель при публикации "on" или "off" в топик "Mode" в смартфоне.
В скетче выполняете публикацию топика "Nept_Mess" и подписчиком поверяете получение топика "TEMP"??? Типа ищем не там где потерял, а там где светло.
Да в ПК на сайте CloudMQTT сообщения видны.
А сайт-то тут причем, подписчик у вас на сайт смотрит?
У клаудМКУТТ есть ограничения на количество соединений, какой смысл проверять что там на сайте появляется. Клиентом бы проверили (на ПК), чтоб убедится что публикация топика "Nept_Mess" доходит до клиента.
Библиотека в приложенном файле
Фото библиотеки :) Обычно ссылки на библиотеки иначе выглядят.
 

Sever44

Member
В скетче выполняете публикацию топика "Nept_Mess" и подписчиком поверяете получение топика "TEMP"??? Типа ищем не там где потерял, а там где светло.
А сайт-то тут причем, подписчик у вас на сайт смотрит?
У клаудМКУТТ есть ограничения на количество соединений, какой смысл проверять что там на сайте появляется. Клиентом бы проверили (на ПК), чтоб убедится что публикация топика "Nept_Mess" доходит до клиента.
Фото библиотеки :) Обычно ссылки на библиотеки иначе выглядят.
Nept_Mess и TEMP это разные проекты. Вы спрашивали, научился ли я выполнять публикацию и подписчиком получать сообщения, я упрощенно описал работающий проект с топиками TEMP и Mode.
Скетчи "Передатчик" и "Приемник" загружены в модули, посмотреть, что видит ПК, я могу только на сайте КлаудМКУТТ. Эта фраза "Клиентом бы проверили (на ПК)" мне непонятна. Я же написал,что в ПК сообщения в топик Nept_Mess видны.
Ограничения не превышены.
Я знаю, как выглядят ссылки, просто картинка информативнее - есть и название библиотеки и автор и версия
 

Алексей.

Active member
Первый модуль публикует данные в определенный топик.
Второй модуль считывает данные из ЭТОГО ЖЕ топика.
Спрашиваю
На обычном ПК, вы подписчиком получаете эти сообщения, которые публикует первый модуль?
Вы отвечаете
Да, есть работающий проект, передающий температуру в смартфон в топик "TEMP" и включающий или выключающий нагреватель при публикации "on" или "off" в топик "Mode" в смартфоне.
про какой то другой проект а не публикации первого модуля.
Эта фраза "Клиентом бы проверили (на ПК)" мне непонятна.
Для ПК есть бесплатные утилиты mosquitto_pub и mosquitto_sub, для публикации и получения сообщений.
Подписываюсь на сообщения
Код:
alex@my-test-pc:~$ mosquitto_sub -h m21.cloudmqtt.com -p 12345 -u myUser -P myPassword -t 'top1980' -d
Client mosqsub|31666-my-test-pc sending CONNECT
Client mosqsub|31666-my-test-pc received CONNACK
Client mosqsub|31666-my-test-pc sending SUBSCRIBE (Mid: 1, Topic: top1980, QoS: 0)
Client mosqsub|31666-my-test-pc received SUBACK
Subscribed (mid: 1): 0
Публикую
Код:
alex@my-test-pc:~$ mosquitto_pub -h m21.cloudmqtt.com -p 12345 -u myUser -P myPassword -t 'top1980' -m 'test message' -d
Client mosqpub|31668-my-test-pc sending CONNECT
Client mosqpub|31668-my-test-pc received CONNACK
Client mosqpub|31668-my-test-pc sending PUBLISH (d0, q0, r0, m1, 'top1980', ... (12 bytes))
Client mosqpub|31668-my-test-pc sending DISCONNECT
И в подписчике вижу
Код:
Client mosqsub|31666-my-test-pc received PUBLISH (d0, q0, r0, m0, 'top1980', ... (12 bytes))
test message
Client mosqsub|31666-my-test-pc sending PINGREQ
Client mosqsub|31666-my-test-pc received PINGRESP
Client mosqsub|31666-my-test-pc sending PINGREQ
Client mosqsub|31666-my-test-pc received PINGRESP
...
 

Sever44

Member
Все, сам разобрался.
Дело было не в бобине...
Просто в "Передатчике" и "Приемнике" должны быть разные mqtt_client_name!!!
 

Sever44

Member
Все, сам разобрался.
Дело было не в бобине...
Просто в "Передатчике" и "Приемнике" должны быть разные mqtt_client_name!!!
Спрашиваю

Вы отвечаете
про какой то другой проект а не публикации первого модуля.

Для ПК есть бесплатные утилиты mosquitto_pub и mosquitto_sub, для публикации и получения сообщений.
Подписываюсь на сообщения
Код:
alex@my-test-pc:~$ mosquitto_sub -h m21.cloudmqtt.com -p 12345 -u myUser -P myPassword -t 'top1980' -d
Client mosqsub|31666-my-test-pc sending CONNECT
Client mosqsub|31666-my-test-pc received CONNACK
Client mosqsub|31666-my-test-pc sending SUBSCRIBE (Mid: 1, Topic: top1980, QoS: 0)
Client mosqsub|31666-my-test-pc received SUBACK
Subscribed (mid: 1): 0
Публикую
Код:
alex@my-test-pc:~$ mosquitto_pub -h m21.cloudmqtt.com -p 12345 -u myUser -P myPassword -t 'top1980' -m 'test message' -d
Client mosqpub|31668-my-test-pc sending CONNECT
Client mosqpub|31668-my-test-pc received CONNACK
Client mosqpub|31668-my-test-pc sending PUBLISH (d0, q0, r0, m1, 'top1980', ... (12 bytes))
Client mosqpub|31668-my-test-pc sending DISCONNECT
И в подписчике вижу
Код:
Client mosqsub|31666-my-test-pc received PUBLISH (d0, q0, r0, m0, 'top1980', ... (12 bytes))
test message
Client mosqsub|31666-my-test-pc sending PINGREQ
Client mosqsub|31666-my-test-pc received PINGRESP
Client mosqsub|31666-my-test-pc sending PINGREQ
Client mosqsub|31666-my-test-pc received PINGRESP
...
Спасибо за ссылки
 

Алексей.

Active member
Разве это не "использование".

if (client.connect(MQTT::Connect("Neptun")
.set_auth(mqtt_user, mqtt_pass))) {
В какой строчке кода используется mqtt_client_name, не mqtt_pass и не mqtt_user, а именно mqtt_client_name???

П.С.
У публикатора и подписчика, для проверки на клаудМКУТТ я использовал только одного пользователя с одним паролем, по этому и спрашиваю.
 

Sever44

Member
В какой строчке кода используется mqtt_client_name, не mqtt_pass и не mqtt_user, а именно mqtt_client_name???

П.С.
У публикатора и подписчика, для проверки на клаудМКУТТ я использовал только одного пользователя с одним паролем, по этому и спрашиваю.
Строка 11 - объявляем, строка 41 - используем.
Код:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

//const char *ssid = "***";
const char *ssid = "***";
const char* const staPass = "***";
const char *mqtt_server = "m13.cloudmqtt.com";
const int mqtt_port = ***;
const char *mqtt_user = "***";
const char *mqtt_pass = "***";
const char *mqtt_client_name = "Neptun2";
#define BUFFER_SIZE 100

WiFiClient wclient;
PubSubClient client(wclient, mqtt_server, mqtt_port);

void setup() {
Serial.setTimeout(10);
Serial.begin(9600);
}

void loop() {

// подключаемся к wi-fi
if (WiFi.status() != WL_CONNECTED) {
Serial.println("..."); 
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.println("...");
WiFi.begin(ssid, staPass);

if (WiFi.waitForConnectResult() != WL_CONNECTED)
return;
Serial.println("WiFi connected");
}

// подключаемся к MQTT серверу
if (WiFi.status() == WL_CONNECTED) {
if (!client.connected()) {
Serial.println("Connecting to MQTT server");
if (client.connect(MQTT::Connect("Neptun2")
.set_auth(mqtt_user, mqtt_pass))) {
Serial.println("Connected to MQTT server");
client.set_callback(callback);
client.subscribe("Nept_Mess");
Serial.println("1");
} else {
Serial.println("Could not connect to MQTT server");
}
}
if (client.connected()){
client.loop();
}
}
} // callback_Neptun_1
Вы путаете понятия mqtt_user (задается при регистрации на сайте КлаудМКТТ) и mqtt_client_name (задаете вы в разделе USER&ACL).
Следующие данные должны быть одинаковыми в обоих топиках:
const char *mqtt_server = "m13.cloudmqtt.com";
const int mqtt_port = ***;
const char *mqtt_user = "***";
const char *mqtt_pass = "***";

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

Алексей.

Active member
Просто в "Передатчике" и "Приемнике" должны быть разные mqtt_client_name!!!
В приведённом коде для передатчика и приемника в строке 10
Код:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid = "***";
const char* const staPass = "***";
const char *mqtt_server = "****";
const int mqtt_port = ***;
const char *mqtt_user = "***";
const char *mqtt_pass = "***";
const char *mqtt_client_name = "Neptun";
#define BUFFER_SIZE 100
вы объявляете mqtt_client_name
и говорите что mqtt_client_name должны быть разными, а код приводите
Код:
if (client.connect(MQTT::Connect("Neptun")
Объясните по каким признакам догадаться что MQTT :: Connect как то связан с тем mqtt_client_name?
 

Sever44

Member
В приведённом коде для передатчика и приемника в строке 10
Код:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid = "***";
const char* const staPass = "***";
const char *mqtt_server = "****";
const int mqtt_port = ***;
const char *mqtt_user = "***";
const char *mqtt_pass = "***";
const char *mqtt_client_name = "Neptun";
#define BUFFER_SIZE 100
вы объявляете mqtt_client_name
и говорите что mqtt_client_name должны быть разными, а код приводите
Код:
if (client.connect(MQTT::Connect("Neptun")
Объясните по каким признакам догадаться что MQTT :: Connect как то связан с тем mqtt_client_name?
Именно эту ошибку я исправил. В первой версии топиков mqtt_client_name были одинаковыми и в Передатчике и в Приемнике. В испрвленной версии кода Приемника mqtt_client_name изменен на Neptun2.

if (client.connect(MQTT::Connect("Neptun2")
.set_auth(mqtt_user, mqtt_pass))) - это стандартная запись, используется во всех примерах указанной выше библиотеки. Что тут непонятного?
 

Алексей.

Active member
if (client.connect(MQTT::Connect("Neptun2")
.set_auth(mqtt_user, mqtt_pass))) - это стандартная запись, используется во всех примерах указанной выше библиотеки. Что тут непонятного?
Во всех пяти примерах (всего их шесть) используется
Код:
if (client.connect("arduinoClient")) {
Метод connect для строки объявлен как
Код:
//! Connect to the server with a client id
   /*!
     \param id Client id for this device
    */
   bool connect(String id);
в одном из шести примеров используется
Код:
if (client.connect(MQTT::Connect("arduinoClient")
                     .set_auth("testeruser", "testpass"))) {
в стеке строится класс MQTT::Connect конструктор которого опять же использует Client id
Код:
//! Connect with a client ID
    Connect(String cid);
и у этого класса вызывается метод set_auth для передачи имени пользователя и пароля
Код:
//! Set the username and password for authentication
    Connect& set_auth(String u, String p)       { _username = u; _password = p; return *this; }
Нет никаких mqtt_client_name, идентификатор клиента есть, имя пользователя и пароль есть.
Вы исправили идентификатор клиента, а рассказали что исправили mqtt_client_name, который объявлен у вас на десятой строке и не используется. Для чего вы так сказали, уже не важно. :)
 

Sever44

Member
Во всех пяти примерах (всего их шесть) используется
Код:
if (client.connect("arduinoClient")) {
Метод connect для строки объявлен как
Код:
//! Connect to the server with a client id
   /*!
     \param id Client id for this device
    */
   bool connect(String id);
в одном из шести примеров используется
Код:
if (client.connect(MQTT::Connect("arduinoClient")
                     .set_auth("testeruser", "testpass"))) {
в стеке строится класс MQTT::Connect конструктор которого опять же использует Client id
Код:
//! Connect with a client ID
    Connect(String cid);
и у этого класса вызывается метод set_auth для передачи имени пользователя и пароля
Код:
//! Set the username and password for authentication
    Connect& set_auth(String u, String p)       { _username = u; _password = p; return *this; }
Нет никаких mqtt_client_name, идентификатор клиента есть, имя пользователя и пароль есть.
Вы исправили идентификатор клиента, а рассказали что исправили mqtt_client_name, который объявлен у вас на десятой строке и не используется. Для чего вы так сказали, уже не важно. :)
Разумеется, используется:
if (client.connect(MQTT::Connect("arduinoClient")
.set_auth("testeruser", "testpass")))
Это же пример!
mqtt_client_name вы не находите потому, что в примерах используется
IPAddress server(172, 16, 0, 2);
а не CloudMQTT.
Давайте закончим дискуссию.
 

Deonis

New member
Вы исправили идентификатор клиента, а рассказали что исправили mqtt_client_name, который объявлен у вас на десятой строке и не используется. Для чего вы так сказали, уже не важно. :)
По всей видимости Sever44 взял готовый пример, скопировал его не разобравшись (сам грешен) и теперь просто не понимает, что вы пытаетесь ему втолковать зачем объявлять
Код:
const char *mqtt_client_name = "Neptun";
если потом при создании подключения он забивает имя клиента вручную...
Код:
client.connect(MQTT::Connect("Neptun") .set_auth(mqtt_user, mqtt_pass))
Я думаю, что мысль у него правильная не должно быть двух клиентов с одним именем, а проблема либо с пониманием кода, либо "переклинило" бывает...
 
Сверху Снизу