Снова MQTT
- Войдите на сайт для отправки комментариев
Осваиваю wemos. Хочу порулить через cloudmqtt.com.
Что сделано
1. Заведен mqtt брокер с именем home.
2. в телефоне поставлено mqtt dashboard. Оформлена подписка на тему home/temp. Добавлен виджет паблишера svetik.
3. Скетч в порт выдает
-
-
Connecting to xxxxx...WiFi connectedIP: 192.168.4.105MAC: 60:01:94:14:E9:60Mask: 255.255.255.0Gateway: 192.168.4.1SSID: xxxxxSignal lvl: -84Connecting to MQTT serverConnected to MQTT server
-
1
-
1
-
1
-
НО в дашбоард эта единичка не прилетает. И светодиодом поморгать не могу... уже и видео посмотрел ... что то похоже не сделал .. а вот что хз...
Если при подключеном дашборде сменить состояние светодиода, отключится и снова сменить то при подключении оно восстанавливается.. так что связь телефон cloudmqtt есть... проблемка со стороны wemos`a
а как он вообще должен читать я не пойму... процедура проверки паблика запукается только при подключении к брокеру... я правильно понял ? Или библиотека PubSubClient.h будет прерывать программу при изменении темы?
P.s Сори что сюда, на профильном народу мало ) молчат все как рыбы. Кроме того буду дальше вязать их с ардуинкой ).
P.s.s
#include <MQTT.h>
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
const char *ssid = "xxxxx"; // Имя вайфай точки доступа
const char *pass = "xxxxx"; // Пароль от точки доступа
const char *mqtt_server = "m11.cloudmqtt.com"; // Имя сервера MQTT
const int mqtt_port = 17427; // Порт для подключения к серверу MQTT
const char *mqtt_user = "xxxxx"; // Логи от сервер
const char *mqtt_pass = "xxxxx"; // Пароль от сервера
WiFiClient wclient;
PubSubClient client(wclient, mqtt_server, mqtt_port);
#define BUFFER_SIZE 100
int tm, temp;
void setup() {
pinMode (D1, OUTPUT);
Serial.begin(115200);
digitalWrite (D1, HIGH);
delay(500);
digitalWrite (D1, LOW);
}
void loop() {
if (!client.connected()) { // переподключаемся к MQTT серверу
reconnect();
}
if (client.connected()) {
client.loop();
TempSend();
}
}
// Функция отправки показаний с термодатчика
void TempSend() {
if (tm == 0)
{
temp = 1;
client.publish("Home/temp", String(temp)); // отправляем в топик для термодатчика значение температуры
Serial.println(temp);
tm = 300; // пауза меду отправками значений температуры коло 3 секунд
}
tm--;
delay(10);
}
void callback(const MQTT::Publish & pub)
{
Serial.print(pub.topic()); // выводим в сериал порт название топика
Serial.print(" => ");
Serial.print(pub.payload_string()); // выводим в сериал порт значение полученных данных
String payload = pub.payload_string();
if (String(pub.topic()) == "Home/svetik") // проверяем из нужного ли нам топика пришли данные
{
int stled = payload.toInt(); // преобразуем полученные данные в тип integer
digitalWrite(D1, stled); // включаем или выключаем светодиод в зависимоти от полученных значений данных
}
}
void reconnect() {
if (WiFi.status() != WL_CONNECTED) { // подключаемся к WIFI
Serial.print("Connecting to ");
Serial.print(ssid);
Serial.println("...");
WiFi.begin(ssid, pass);
if (WiFi.waitForConnectResult() != WL_CONNECTED)
return;
Serial.println("WiFi connected");
Serial.print ("IP: ");
Serial.println(WiFi.localIP());//получаем IP WeMos, этот IP необходимо ввести в адресной строке браузера, чтобы получить доступ к WeMos
Serial.print ("MAC: ");
Serial.println(WiFi.macAddress()); //получаем MAC-адрес WeMos
Serial.print ("Mask: ");
Serial.println(WiFi.subnetMask()); //маску подсети
Serial.print ("Gateway: ");
Serial.println(WiFi.gatewayIP()); //IP- шлюза
Serial.print ("SSID: ");
Serial.println(WiFi.SSID());// имя сети, к которой подключен WeMos
Serial.print ("Signal lvl: ");
Serial.println(WiFi.RSSI()); //и уровень сигнала
}
if (WiFi.status() == WL_CONNECTED) { // если вафля подключена
if (!client.connected()) { // подключаемся к MQTT серверу
Serial.println("Connecting to MQTT server");
if (client.connect(MQTT::Connect("arduinoClient2")
.set_auth(mqtt_user, mqtt_pass))) {
Serial.println("Connected to MQTT server");
client.set_callback(callback);
client.subscribe("Home/svetik"); // подписывааемся по топик с данными для светодиода
} else {
Serial.println("Could not connect to MQTT server");
}
}
}
}
Разобрался наконец то с подключением и тп...
При загрузке прочитывает только топик Home/rgbr, второй топик Home/svetdiap не читает...
Но если я меняю их с телефона то читатет оба.
как заставить читать либо все при старте ... либо принудительно читать топик ?
#include <MQTT.h> // Подключаем библиотеку для работы протоколом MQTT #include <PubSubClient.h> // Подключаем библиотеку для получения и публикации топиков от/на брокере #include <ESP8266WiFi.h> // Подключаем библиотеку для работы с WiFi //const char *ssid = ""; // Имя вайфай точки доступа //const char *pass = ""; // Пароль от точки доступа const char *ssid = ""; // Имя вайфай точки доступа const char *pass = ""; // Пароль от точки доступа const char *mqtt_server = ""; // Имя сервера MQTT const int mqtt_port = ; // Порт для подключения к серверу MQTT const char *mqtt_user = ""; // Логи от сервер const char *mqtt_pass = ""; // Пароль от сервера WiFiClient wclient; // создаем обьект клиента Wifi PubSubClient client(wclient, mqtt_server, mqtt_port); // создаем обьект клиента MQTT #define BUFFER_SIZE 100 int tm, temp; int rgbr; String putcomand; // Создаём массив для отправки данных String getcomand; // Создаем массив для приема данных int hour1, hour2, hour3, hour4; //переменные для временных диапозонов. часы. int min1, min2, min3, min4; //переменные для временных диапозонов. минуты. int svetdiap; // количество световых диапазонов void setup() { pinMode (D1, OUTPUT); Serial.begin(115200); // Внимание !!!! при просмотре com порта выставьте скорость 115200 //svetdiap = 2; //минимальное значение световых диапазонов } void loop() { if (!client.connected()) { // переподключаемся к MQTT серверу reconnect(); } if (client.connected()) { client.loop(); //TempSend(); svetdiapf(); } } // Функция отправки показаний с термодатчика void TempSend() { if (tm == 0) { temp = 2; client.publish("/Home/temp", String(temp)); // отправляем в топик для термодатчика значение температуры //Serial.println(temp); tm = 300; // пауза между отправками значений температуры коло 3 секунд } tm--; delay(10); } void svetdiapf() { if (tm == 0) { putcomand = "AT"; putcomand += svetdiap; Serial.println (putcomand); tm = 300; } tm--; delay(10); } void callback(const MQTT::Publish & pub) { Serial.print(pub.topic()); // выводим в сериал порт название топика Serial.print(" => "); Serial.println(pub.payload_string()); // выводим в сериал порт значение полученных данных String payload = pub.payload_string(); if (String(pub.topic()) == "/Home/rgbr") // проверяем из нужного ли нам топика пришли данные { rgbr = payload.toInt(); // преобразуем полученные данные в тип integer if (rgbr != 0) { analogWrite(D1, rgbr); // включаем или выключаем светодиод в зависимоти от полученных значений данных Serial.println ("Вкл"); } else { analogWrite(D1, 0); // включаем или выключаем светодиод в зависимоти от полученных значений данных Serial.println ("Выкл"); } } if (String(pub.topic()) == "/Home/svetdiap") // проверяем из нужного ли нам топика пришли данные { svetdiap = payload.toInt(); // преобразуем полученные данные в тип integer } } void reconnect() { if (WiFi.status() != WL_CONNECTED) { // подключаемся к WIFI Serial.print("Подключение к WiFi SSID: "); Serial.print(ssid); Serial.println("..."); WiFi.begin(ssid, pass); if (WiFi.waitForConnectResult() != WL_CONNECTED) return; Serial.println("WiFi Подключен"); Serial.print ("IP: "); Serial.println(WiFi.localIP());//получаем IP WeMos, этот IP необходимо ввести в адресной строке браузера, чтобы получить доступ к WeMos Serial.print ("MAC: "); Serial.println(WiFi.macAddress()); //получаем MAC-адрес WeMos Serial.print ("Mask: "); Serial.println(WiFi.subnetMask()); //маску подсети Serial.print ("Gateway: "); Serial.println(WiFi.gatewayIP()); //IP- шлюза Serial.print ("SSID: "); Serial.println(WiFi.SSID());// имя сети, к которой подключен WeMos Serial.print ("уровень сигнала: "); Serial.println(WiFi.RSSI()); //и уровень сигнала } if (WiFi.status() == WL_CONNECTED) { // если вафля подключена if (!client.connected()) { // подключаемся к MQTT серверу Serial.println("Подключаемся к MQTT серверу"); if (client.connect(MQTT::Connect("arduinoClient2") .set_auth(mqtt_user, mqtt_pass))) { Serial.println("Подключение удалось"); client.set_callback(callback); client.subscribe("/Home/rgbr"); // подписывааемся по топик с данными яркости карсного client.subscribe("/Home/svetdiap"); // подписывааемся по топик с данными яркости карсного } else { Serial.println("Подключение не удалось"); } } } }на 3 форуме спрашиваю... и везде тишина... неужто никто не делал восстановление данных после перезагрузки вемоса/ардуины и тп )
Почему ж не делали, делали, я использую встроенный EEPROM ESP8266. Вот мой последний проект: https://youtu.be/YVLLmWthCts там очень много кода. :)
И кстати команду WIFI.begin() не нужно вызывать вновь при разрыве WiFI подключения (я тоже раньше так косячил) достаточно 1 раз при загрузке модуля вызвать команду wifi.begin() и при разрывах будет сам вновь подключаться.
И еще на будущее, у этой библиатеки pubsubclient есть косяк - нельзя однавременно в одном цикле loop отправлять с десяток исходящих сообщений, можно только по 1-му сообщению за один цикл loop, а иначе это приведет к подвисанию модуля т.к. на отправку одного сообщения уходит много времени (порядка 200 милисек).
Почему ж не делали, делали, я использую встроенный EEPROM ESP8266. Вот мой последний проект: https://youtu.be/YVLLmWthCts там очень много кода. :)
И кстати команду WIFI.begin() не нужно вызывать вновь при разрыве WiFI подключения (я тоже раньше так косячил) достаточно 1 раз при загрузке модуля вызвать команду wifi.begin() и при разрывах будет сам вновь подключаться.
И еще на будущее, у этой библиатеки pubsubclient есть косяк - нельзя однавременно в одном цикле loop отправлять с десяток исходящих сообщений, можно только по 1-му сообщению за один цикл loop, а иначе это приведет к подвисанию модуля т.к. на отправку одного сообщения уходит много времени (порядка 200 милисек).
Огромное спасибо за советы... 1 запись за loop.. ну введу флаг ) хотя...Может есть другие библиотеки?
Епромом пользоваться не хочу.... не ужели нельзя прогрпмно а не при изменении прочитать топик ? зачем использовать епром когда в облаке уже данные хранятся.... код гляну обяз ... хотчбы в целях обучения.. если не найду решения то конечно епром....
Ну некоторые данные можно хранить в облаке, если отправлять с пометкой "retained". Библиатека есть др. универсальная, ее все используют почему то. А эта спициальная для esp8266. У др. библиотеки тоже косяк, точно такой же, но с подписками, нельзя подписываться на кучу топиков за один цикл loop.
мои данные желательно хранить в облаке.... каму интересен цвет и время включения в акве... уж лучше постить за 1 луп...
НО КАК БЛИН принудительно прочитать тему???? уже мозг сломал
Ну за один цикл loop и не обязательно передовать все исходящие сообщения, я сделал лист для последовательной отправки 10 сообщений, в итоге все 10 исходящих сообщений отправятся за 10 циклов loop.
Да топики сами читаются (входящие сообщения обрабатывает callback). Запускается это все автоматически из цикла loop командой client.loop(), если подключен к серверу(облаку). Но в вашем скетче заметил не дописанный момент, во второй топих данные входящие прилетают, но с ними ничего не выполняется, они ни чем не управляют. Подключите же к ним уж наконц, света-диод какой нибудь. :) А все увидел топик "/Home/svetdiap" управляет каким то световым эфектом.
угу ....
мне важно прочитать топики при включении вемоса.... а не при изменении топика... при изменении читает все норм... при включении читает тока первый...
поэтому либо принудилово читать любой топик... либо при запуске читать все топики...
пока учусь ... топиков будет штук 40 ) ... обработчики смысла писать нет ... пока не научусь... ибо если не работает такая хрень уйду на каскаду...
Просто отправляйте данные в этот топик /Home/svetdiap с пометкой retained через приложение.
Подниму старую тему, вопрос по получению ответа от MQTT сервера.
на ESP8266 WeMos отправлю PUB пакеты, все отлично работает, тут вопросов нет.
на сервере в логах вижу такую запись:
т.е. если я правильно понял - мне сервер что то послал,
смотрю такой командой:
Должен ли я с помощью данного кода увидеть ответ сервера?
Нет, не правильно, там же входящие сообщения обробатываются в цикле void callback();
И есть 2 разных версии этой библиотеки от разных разработчиков, одна построеннана строках объекта класса String (рекомендованна для esp8266) , а др. на char.
Думаю, что служебные протокольные данные (такие, как CONNECT, ACK и т.д.) через обычный read() получить нельзя (да и смысла нет).
я без всяких библиотек работаю, иначе не интересно.
Думаю, что служебные протокольные данные (такие, как CONNECT, ACK и т.д.) через обычный read() получить нельзя (да и смысла нет).
ок, спасибо. А получить просто из любопытства хочеться. Во вскяом случае в оф документации данные пакеты описаны.
Update: судя по доке если я правильно понял, возвращается всего один байт - код ответа. Попробую вывести в консоль.
Update: судя по доке если я правильно понял, возвращается всего один байт - код ответа. Попробую вывести в консоль.
Тогда уточните - кто есть client - что за объект/класс?
Update: судя по доке если я правильно понял, возвращается всего один байт - код ответа. Попробую вывести в консоль.
Тогда уточните - кто есть client - что за объект/класс?
весь код если вдруг нужен:
#include <ESP8266WiFi.h> #include "OneWire.h" OneWire ds18b20(4); // DS18B20 on GPIO4=D2 WeMos #define errTemp 1111 byte dsData[9]; word currTemp = errTemp; #define period_get_temp 600000UL // 10 min unsigned long timer_get_temp = 590000; byte flag_get_temp = 0; byte modeLedWork = 0; // led mode // 0 - normal work 1 flash by 3 sec // 1 - error 1 - 1 flash by 1 sec - error get temp // 2 - error 2 - 2 flash by 1 sec - error connect wifi byte modeLedFlash = 0; #define period_led_flash 200UL #define period_normal_flash 5000UL #define period_err_flash 1000UL unsigned long timer_led_flash = 0; byte deviceMode = 0; // main mode work device // 0 connect wifi // 1 wait connect wifi // 2 repeat connect wifi // 3 connect to mqtt server char ssid[] = "TPmvil"; char password[] = "RZ5ahmtyKE"; #define period_test_wifi_connect 500UL unsigned long timer_test_wifi_connect = 0; #define period_timeout_wifi_connect 30000UL // 30sec unsigned long timer_timeout_wifi_connect = 0; #define period_repeat_wifi_connect 120000UL // 2min and MQTT repeat unsigned long timer_repeat_wifi_connect = 0; WiFiClient client; char mqtt_server[] = "m20.cloudmqtt.com"; // Имя сервера MQTT int mqtt_port = 19791; // Порт для подключения к серверу MQTT char mqtt_user[] = "****"; // Логи от сервер char mqtt_pass[] = "*****"; // Пароль от сервера char mqtt_device[] = "AndycatES39"; char mqtt_topic_temp[] = "/temp"; char mqtt_topic_led[] = "/led"; unsigned long currentMillis; #define LEDON digitalWrite(LED_BUILTIN,LOW) #define LEDOFF digitalWrite(LED_BUILTIN,HIGH) void setup() { // put your setup code here, to run once: pinMode(LED_BUILTIN, OUTPUT); LEDOFF; Serial.begin(115200); Serial.println("Reset Serial"); delay(500); Serial.println("Start"); } void loop() { // put your main code here, to run repeatedly: currentMillis = millis(); // get temp if ((currentMillis - timer_get_temp) >= period_get_temp) { if (flag_get_temp) { if ((currentMillis - timer_get_temp) >= (period_get_temp + 800UL)) { timer_get_temp = currentMillis; flag_get_temp = 0; currTemp = getTemp2(); if (currTemp == errTemp) { modeLedWork = 1; Serial.println("Error get temp"); } else { modeLedWork = 0; } } } else { flag_get_temp = 1; getTemp1(); } } // flash led switch (modeLedWork) { case 0: { if ((currentMillis - timer_led_flash) >= period_normal_flash) { if (modeLedFlash) { if ((currentMillis - timer_led_flash) >= (period_normal_flash + period_led_flash)) { modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } } else { modeLedFlash = 1; LEDON; } } break; } case 1: { if ((currentMillis - timer_led_flash) >= period_err_flash) { if (modeLedFlash) { if ((currentMillis - timer_led_flash) >= (period_err_flash + period_led_flash)) { modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } } else { modeLedFlash = 1; LEDON; } } break; } default: { if ((modeLedWork < 6) && (modeLedFlash <= (modeLedWork << 1))) { if ((currentMillis - timer_led_flash) >= (period_err_flash + (period_led_flash * modeLedFlash))) { if ((modeLedFlash + 1) >= (modeLedWork << 1)) { modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } else { if (bitRead(modeLedFlash, 0)) LEDOFF; else LEDON; ++modeLedFlash; } } } else { modeLedWork = 0; modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } } } // main work switch (deviceMode) { case 0: { // connect wifi WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); ++deviceMode; timer_timeout_wifi_connect = currentMillis; timer_test_wifi_connect = currentMillis; break; } case 1: { // wait connect wifi if ((currentMillis - timer_test_wifi_connect) >= period_test_wifi_connect) { timer_test_wifi_connect = currentMillis; if (WiFi.status() == WL_CONNECTED) { Serial.println("WiFi connected"); deviceMode = 3; modeLedWork = 0; // connect ok } else { Serial.print("."); if ((currentMillis - timer_timeout_wifi_connect) >= period_timeout_wifi_connect) { Serial.println("WiFi timeout connection"); timer_repeat_wifi_connect = currentMillis; deviceMode = 2; modeLedWork = 2; WiFi.disconnect(); // problem connect } } } break; } case 2: { // repeat connect wifi if ((currentMillis - timer_repeat_wifi_connect) >= period_repeat_wifi_connect) { deviceMode = 0; modeLedWork = 0; } break; } case 3: { // connect to mqtt server if (client.connect(mqtt_server, mqtt_port)) { Serial.println("MQTT connected"); deviceMode = 5; modeLedWork = 0; // connect ok } else { Serial.println("Error MQTT connect"); timer_repeat_wifi_connect = currentMillis; deviceMode = 4; modeLedWork = 3; // problem connect } break; } case 4: { // repeat connect mqtt if ((currentMillis - timer_repeat_wifi_connect) >= period_repeat_wifi_connect) { if (WiFi.status() == WL_CONNECTED) { deviceMode = 3; modeLedWork = 0; } else { deviceMode = 0; modeLedWork = 0; } } break; } case 5: { delay(5000); sendConnectPacket(); Serial.println(""); readResponseFromClient(); sendPubTemp(); Serial.println(""); readResponseFromClient(); sendDisConnectPacket(); Serial.println(""); readResponseFromClient(); client.stop(); deviceMode = 6; modeLedWork = 0; break; } default: { readResponseFromClient(); } } // end loop } void getTemp1() { ds18b20.reset(); ds18b20.write(0xCC); ds18b20.write(0x44); } word getTemp2() { ds18b20.reset(); ds18b20.write(0xCC); ds18b20.write(0xBE); for (byte i = 0; i < 9; i++) dsData[i] = ds18b20.read(); if (OneWire::crc8(dsData, 8) != dsData[8]) return errTemp; word outTemp = (word)(dsData[1] << 8) + dsData[0]; if ((word)(outTemp & 0x8000) == (word)(0x8000)) { outTemp = (~outTemp) + (word)1; outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10; } else { outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10; if (outTemp == 0) return errTemp; outTemp += (word)2000; } return outTemp; } void sendConnectPacket() { byte sizeDevice = sizeof(mqtt_device) - 1; byte sizeUser = sizeof(mqtt_user) - 1; byte sizePass = sizeof(mqtt_pass) - 1; // fixed header sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000 sendByteToMQTTclient((byte)(16 + sizeDevice + sizeUser + sizePass)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)0x04); // Length LSB (4) sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name sendByteToMQTTclient((byte)0x04); // Protocol Level byte sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0) sendByteToMQTTclient((byte)0x0A); // Keep Alive LSB (10) // payload sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i])); sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i])); sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i])); } void sendByteToMQTTclient(byte inByte) { client.write((byte)(inByte)); if ((inByte < 0x20) || (inByte >= 0x7F)) { Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" "); } else { Serial.write(inByte); } } void readResponseFromClient() { while (client.available()) { byte inByte = client.read(); if ((inByte < 0x20) || (inByte >= 0x7F)) { Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" "); } else { Serial.write(inByte); } } } void sendDisConnectPacket() { // fixed header sendByteToMQTTclient((byte)0xE0); // MQTT Control Packet type 1110 connect, reserved 0000 sendByteToMQTTclient((byte)0x00); // Remaining Length } void sendPubTemp() { if (currTemp = errTemp) return; char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currTemp; if (absTemp >= 2000) { textTemp[textPos] = '+'; absTemp -= 2000; } else { textTemp[textPos] = '-'; } ++textPos; if (absTemp >= 1000) { textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; } else { } byte sizeDevice = sizeof(mqtt_device) - 1; byte sizeTopic = sizeof(mqtt_topic_temp) - 1; byte sizeData = sizeof(textTemp) - 1;; // fixed header sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4) for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i])); for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_temp[i])); sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0) sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10) // payload for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i])); }Если сами пакет формируете, а не через PubsClient, то тогда должны получить. Я думал, что ваш клиент - библиотечный объект. C другой стороны в readResponseFromClient() должны уже получать что-то прилетающее от сервера после коннекта.
readResponseFromClient()
спасибо за подсказку/направление, дальше думаю разберусь.
А как для SIM800 примерно тоже сделать?
Проверенные примеры где то есть?
А в чем глобальная разница?
Есть примеры, поиском по mqtt посмотрите,
Irinka недавно делала
http://arduino.ru/forum/apparatnye-voprosy/arduino-uno-sim800lmqttblynk
закончил игрушку, отправка температуры, прием цвета и зажигание RGB светодиода:
#include <ESP8266WiFi.h> #include "OneWire.h" #define pin_red_led 2 // JPIO-2 = D4 WeMos #define pin_green_led 0 // JPIO-0 = D3 WeMos #define pin_blue_led 5 // JPIO-5 = D1 WeMos OneWire ds18b20(4); // DS18B20 on JPIO-4=D2 WeMos #define errTemp 1111 byte dsData[9]; word currTemp = errTemp; #define period_get_temp 600279UL // 10 min unsigned long timer_get_temp = 0; byte flag_get_temp = 0; byte modeLedWork = 0; // led mode // 0 - normal work 1 flash by 3 sec // 1 - error 1 - 1 flash by 1 sec - error get temp // 2 - error 2 - 2 flash by 1 sec - error connect wifi byte modeLedFlash = 0; #define period_led_flash 200UL #define period_normal_flash 5000UL #define period_err_flash 1000UL unsigned long timer_led_flash = 0; byte deviceMode = 0; // main mode work device // 0 connect wifi // 1 wait connect wifi // 2 repeat connect wifi // 3 connect to mqtt server char ssid[] = "Cat9"; char password[] = "71fa3c4b90"; //char ssid[] = "TPmvil"; //char password[] = "RZ5ahmtyKE"; #define period_test_wifi_connect 500UL unsigned long timer_test_wifi_connect = 0; #define period_timeout_wifi_connect 30000UL // 30sec unsigned long timer_timeout_wifi_connect = 0; #define period_repeat_wifi_connect 120000UL // 2min and MQTT repeat unsigned long timer_repeat_wifi_connect = 0; WiFiClient client; char mqtt_server[] = "m20.cloudmqtt.com"; // Имя сервера MQTT int mqtt_port = 19791; // Порт для подключения к серверу MQTT char mqtt_user[] = "***"; // Логи от сервер char mqtt_pass[] = "***"; // Пароль от сервера char mqtt_device[] = "AndycatES39"; char mqtt_topic_temp[] = "/temp"; char mqtt_topic_led[] = "/led"; #define period_mqtt_send_temp 900000UL // 15min unsigned long timer_mqtt_send_temp = 0; #define period_mqtt_ping 30000UL unsigned long timer_mqtt_ping = 0; byte fColor = 0; byte rColor = 0; byte gColor = 0; byte bColor = 0; byte pColor = 0; byte tColor = 0; byte sColor = 0; unsigned long currentMillis; #define LEDON digitalWrite(LED_BUILTIN,LOW) #define LEDOFF digitalWrite(LED_BUILTIN,HIGH) void setup() { // put your setup code here, to run once: pinMode(LED_BUILTIN, OUTPUT); pinMode(pin_red_led, OUTPUT); digitalWrite(pin_red_led, HIGH); pinMode(pin_green_led, OUTPUT); digitalWrite(pin_green_led, HIGH); pinMode(pin_blue_led, OUTPUT); digitalWrite(pin_blue_led, HIGH); LEDOFF; Serial.begin(115200); Serial.println("Reset Serial"); delay(500); Serial.println("Start"); } void loop() { // put your main code here, to run repeatedly: currentMillis = millis(); // get temp if ((currentMillis - timer_get_temp) >= period_get_temp) { if (flag_get_temp) { if ((currentMillis - timer_get_temp) >= (period_get_temp + 800UL)) { timer_get_temp = currentMillis; flag_get_temp = 0; currTemp = getTemp2(); if (currTemp == errTemp) { modeLedWork = 1; Serial.println("Error get temp"); } else { modeLedWork = 0; } } } else { flag_get_temp = 1; getTemp1(); } } // flash led switch (modeLedWork) { case 0: { if ((currentMillis - timer_led_flash) >= period_normal_flash) { if (modeLedFlash) { if ((currentMillis - timer_led_flash) >= (period_normal_flash + period_led_flash)) { modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } } else { modeLedFlash = 1; LEDON; } } break; } case 1: { if ((currentMillis - timer_led_flash) >= period_err_flash) { if (modeLedFlash) { if ((currentMillis - timer_led_flash) >= (period_err_flash + period_led_flash)) { modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } } else { modeLedFlash = 1; LEDON; } } break; } default: { if ((modeLedWork < 6) && (modeLedFlash <= (modeLedWork << 1))) { if ((currentMillis - timer_led_flash) >= (period_err_flash + (period_led_flash * modeLedFlash))) { if ((modeLedFlash + 1) >= (modeLedWork << 1)) { modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } else { if (bitRead(modeLedFlash, 0)) LEDOFF; else LEDON; ++modeLedFlash; } } } else { modeLedWork = 0; modeLedFlash = 0; LEDOFF; timer_led_flash = currentMillis; } } } // main work switch (deviceMode) { case 0: { // connect wifi WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); ++deviceMode; timer_timeout_wifi_connect = currentMillis; timer_test_wifi_connect = currentMillis; break; } case 1: { // wait connect wifi if ((currentMillis - timer_test_wifi_connect) >= period_test_wifi_connect) { timer_test_wifi_connect = currentMillis; if (WiFi.status() == WL_CONNECTED) { Serial.println("WiFi connected"); deviceMode = 3; modeLedWork = 0; // connect ok } else { Serial.print("."); if ((currentMillis - timer_timeout_wifi_connect) >= period_timeout_wifi_connect) { Serial.println("WiFi timeout connection"); timer_repeat_wifi_connect = currentMillis; deviceMode = 2; modeLedWork = 2; WiFi.disconnect(); // problem connect } } } break; } case 2: { // repeat connect wifi if ((currentMillis - timer_repeat_wifi_connect) >= period_repeat_wifi_connect) { deviceMode = 0; modeLedWork = 0; } break; } case 3: { // connect to mqtt server if (client.connect(mqtt_server, mqtt_port)) { Serial.println("MQTT connected"); deviceMode = 5; modeLedWork = 0; fColor = 0; sColor = 0; // connect ok } else { Serial.println("Error MQTT connect"); timer_repeat_wifi_connect = currentMillis; deviceMode = 4; modeLedWork = 3; // problem connect } break; } case 4: { // repeat connect mqtt if ((currentMillis - timer_repeat_wifi_connect) >= period_repeat_wifi_connect) { if (WiFi.status() == WL_CONNECTED) { deviceMode = 3; modeLedWork = 0; } else { deviceMode = 0; modeLedWork = 0; } } break; } case 5: { // send conneck packet and subscribe sendConnectPacket(); Serial.println(""); sendSubscribeLed(); Serial.println(""); deviceMode = 6; modeLedWork = 0; break; } case 6: { // send topic temp sendPubTemp(); Serial.println(""); deviceMode = 7; modeLedWork = 0; timer_mqtt_send_temp = currentMillis; timer_mqtt_ping = currentMillis; break; } default: { // wait next send temp and read data from mqtt server if ((currentMillis - timer_mqtt_send_temp) >= period_mqtt_send_temp) { timer_mqtt_send_temp = currentMillis; deviceMode = 3; modeLedWork = 0; // repeat connect mqtt server and send temp } else if ((currentMillis - timer_mqtt_ping) >= period_mqtt_ping) { timer_mqtt_ping = currentMillis; sendPingPacket(); Serial.println(""); } else { // read data readResponseFromClient(); } } } // show color led if (sColor) { sColor = 0; Serial.print(" Red=0x"); Serial.print(rColor, HEX); Serial.print(" "); Serial.print(" Green=0x"); Serial.print(gColor, HEX); Serial.print(" "); Serial.print(" Blue=0x"); Serial.print(bColor, HEX); Serial.print(" "); if (rColor >= 0x80) digitalWrite(pin_red_led, LOW); else digitalWrite(pin_red_led, HIGH); if (gColor >= 0x80) digitalWrite(pin_green_led, LOW); else digitalWrite(pin_green_led, HIGH); if (bColor >= 0x80) digitalWrite(pin_blue_led, LOW); else digitalWrite(pin_blue_led, HIGH); } // end loop } void getTemp1() { ds18b20.reset(); ds18b20.write(0xCC); ds18b20.write(0x44); } word getTemp2() { ds18b20.reset(); ds18b20.write(0xCC); ds18b20.write(0xBE); for (byte i = 0; i < 9; i++) dsData[i] = ds18b20.read(); if (OneWire::crc8(dsData, 8) != dsData[8]) return errTemp; word outTemp = (word)(dsData[1] << 8) + dsData[0]; if ((word)(outTemp & 0x8000) == (word)(0x8000)) { outTemp = (~outTemp) + (word)1; outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10; } else { outTemp = (((word)6 * outTemp) + outTemp / (word)4) / (word)10; if (outTemp == 0) return errTemp; outTemp += (word)2000; } return outTemp; } void sendConnectPacket() { byte sizeDevice = strlen(mqtt_device); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass); // fixed header sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000 sendByteToMQTTclient((byte)(16 + sizeDevice + sizeUser + sizePass)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)0x04); // Length LSB (4) sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name sendByteToMQTTclient((byte)0x04); // Protocol Level byte sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0) sendByteToMQTTclient((byte)0x28); // Keep Alive LSB (10) - 40 sec // payload sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i])); sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i])); sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i])); } void sendByteToMQTTclient(byte inByte) { client.write((byte)(inByte)); if ((inByte < 0x20) || (inByte >= 0x7F)) { Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" "); } else { Serial.write(inByte); } } void readResponseFromClient() { if (client.available()) { Serial.print(" Response = "); while (client.available()) { byte inByte = client.read(); if ((inByte < 0x20) || (inByte >= 0x7F)) { Serial.print(" 0x"); Serial.print(inByte, HEX); Serial.print(" "); } else { Serial.write(inByte); } // processing input byte if (fColor) { if ((pColor < 6) && (((inByte >= '0') && (inByte <= '9')) || ((inByte >= 'A') && (inByte <= 'F')))) { if (!(bitRead(pColor, 0))) { tColor = inByte; ++pColor; } else { switch (pColor) { case 1: { rColor = getByteFromTwoChar(tColor, inByte); ++pColor; break; } case 3: { gColor = getByteFromTwoChar(tColor, inByte); ++pColor; break; } default: { bColor = getByteFromTwoChar(tColor, inByte); fColor = 0; sColor = 1; } } } } } else { if (inByte == '#') { fColor = 1; pColor = 0; } } // end processing } Serial.println(""); } } void sendPingPacket() { // fixed header sendByteToMQTTclient((byte)0xC0); // MQTT Control Packet type (12) 1100 ping, reserved 0000 sendByteToMQTTclient((byte)0x00); // Remaining Length } void sendPubTemp() { if (currTemp == errTemp) return; char textTemp[] = "-100.0 °C"; byte textPos = 0; word absTemp = currTemp; if (absTemp >= 2000) { textTemp[textPos] = '+'; absTemp -= 2000; } else { textTemp[textPos] = '-'; } ++textPos; if (absTemp >= 1000) { textTemp[textPos] = (absTemp / 1000) + '0'; absTemp = absTemp % 1000; ++textPos; textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos; } else if (absTemp >= 100) { textTemp[textPos] = (absTemp / 100) + '0'; absTemp = absTemp % 100; ++textPos; textTemp[textPos] = (absTemp / 10) + '0'; ++textPos; } else if (absTemp >= 10) { textTemp[textPos] = (absTemp / 10) + '0'; ++textPos; } textTemp[textPos] = '.'; ++textPos; textTemp[textPos] = (absTemp % 10) + '0'; ++textPos; textTemp[textPos] = ' '; ++textPos; textTemp[textPos] = '`'; ++textPos; textTemp[textPos] = 'C'; ++textPos; textTemp[textPos] = 0; byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_temp); byte sizeData = strlen(textTemp); // fixed header sendByteToMQTTclient((byte)0x31); // MQTT Control Packet type 0011, DUP QoS Retain 0001 flags sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4) for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i])); for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_temp[i])); sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0) sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10) // payload for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i])); } void sendSubscribeLed() { byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_led); // fixed header sendByteToMQTTclient((byte)0x82); // MQTT Control Packet type (8) 0100, reserved 0010 sendByteToMQTTclient((byte)(5 + sizeDevice + sizeTopic)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0) sendByteToMQTTclient((byte)(0x0A)); // Packet Identifier LSB (10) // payload sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4) for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i])); for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_led[i])); sendByteToMQTTclient((byte)0x01); // Requested QoS(1) } byte getByteFromTwoChar(byte byte1, byte byte0) { byte resultB; if (byte1 >= 0x41) resultB = (byte1 - 0x37) * 16; else resultB = (byte1 - 0x30) * 16; if (byte0 >= 0x41) resultB = resultB + (byte0 - 0x37); else resultB = resultB + (byte0 - 0x30); return resultB; }Нашлись служебные данные?
Нашлись служебные данные?
Приходящие байты видны, но не на все команды есть ответы.
на CONNECT я так и не увидел, на SUBSCRIBE и PINGREQ ответы ожидаемо есть.
Т.е. читаем правильно - client.read()
Закончил мучать связку SIM800L + MQTT
Выкладываю рабочую последовательность команд работы с модемом:
Хоть хтото чето полезного запостил. Спасибо, интересно.
// Моносокет, т.е. как я понял - единомоментно работаем только с одним серверомЯ так понимаю, если не моносокет, то в
AT+CIPSTART,AT+CIPSEND,и еще коегде добавляется еще один параметр - номер соединения.RECV FROM:Хоть хтото чето полезного запостил.
Во блин, крутышка посчитал что червь хоть что то знает :)
ЗЫ. Я вас уже давно просил, пожалуйста не отвечайте на мои посты, у меня на вас аллергия.
Ваш монолог прерывать не буду, алергией червя удовлетворен ;)
НО КАК БЛИН принудительно прочитать тему???? уже мозг сломал
Например указать подписки на топики в функции reconnect()
Ну и в callback:
if(strcmp(topic, "topic") == 0) { //code }Подскажите. Есть локальный сервер, нужно управлять устройством по протоколу MQTT.
Вопрос? Для MQTT обязательно нужен Интернет, или можно сделать свой локальный. Устройство будет работать в чистом поле где нет интернета
Для MQTT, как протокола, Интернет не нужен.
Извените, а протокол и брокер MQTT это одно и тоже или разные вещи?
Извените, а протокол и брокер MQTT это одно и тоже или разные вещи?
Брокер это облоко (сервер) , через который все работает по протаколу MQTT. Это самое главное без брокера не могут устройства (клиенты mqtt) обмениватся сообщениям.
Н а моем новом телефоне не работает mqtt протокол похоже, предыдущий телефон с андроид норм работал, а новый- Honor 9 lyte не связывается-пишет постоянно-ошибка соединения, кто сталкивался может? Брокер зарегистрирован на cloudmqtt.com, на смартфоне пробовал и mqttdash и mqtt dashboard, везде ошибка выходит, видать в телефоне что то не пропускает.
Н а моем новом телефоне не работает mqtt протокол похоже, предыдущий телефон с андроид норм работал, а новый- Honor 9 lyte не связывается-пишет постоянно-ошибка соединения, кто сталкивался может? Брокер зарегистрирован на cloudmqtt.com, на смартфоне пробовал и mqttdash и mqtt dashboard, везде ошибка выходит, видать в телефоне что то не пропускает.
1. это сайт про Ардуино
2. думаю конкретно у вас и/или оператора проблемы + перепроверьте логин/пароль/сайт для подключения
3. у меня Honor 6A Андроид 7 работает отлично.
Upd: вокруг меня много любителей ставить антивирус на Андроид, возможно и у вас что то режет трафик.
1.Ну так-на той стороне стоит Ардуино с ESP8266. И тема называется Снова MQTT.
2.Ну то что у меня проблемы-об том и речь. Логин и пароль верные, сто раз всё перепроверял, их несколько на разные устройства, это отпадает.
3. У меня Honor 9 с восьмым андроидом и не работает.
Ставил на голый андроид, сам антивирус не ставил,но скрытый есть там вроде,при проверке системы на вирусы надпись Аваст виден, будем копать в сторону рута, но это тоже не очень гуд, с роутом на старом смартфоне переставал работать Сбербанк онлай, ругался на рут.
Ох сомневаюсь что дело в андроиде и рут вам не нужен.
Найду телефон с 9м андроидом - проверю из любопытства.
Upd так если рут стоит, особенно если совсем не РСТ то с большой вероятностью не заработает
Метод PubSubClient::publish() кушает только си-шные строки, но никак не стринги. Т.е. в 45й строке должно быть
client.publish("Home/temp", (char*)String(temp).c_str());Во, коструктивчик, спасибо! А я было уже собрался ленивого в себе бороть и закуривать протокол ))
Похоже не победить этот андроид 8, буду переходить на Blynk.
Нашлись служебные данные?
Приходящие байты видны, но не на все команды есть ответы.
на CONNECT я так и не увидел, на SUBSCRIBE и PINGREQ ответы ожидаемо есть.
Т.е. читаем правильно - client.read()
У меня на запрос пинга cloudmqtt.com почему то дисконнектит. может я его не правильно отсылаю?
gsm.println("AT+CIPSEND"); gsm.write(0xC0); gsm.write(byte(0)); gsm.write(0x1A);У меня на запрос пинга cloudmqtt.com почему то дисконнектит. может я его не правильно отсылаю?
gsm.println("AT+CIPSEND"); gsm.write(0xC0); gsm.write(byte(0)); gsm.write(0x1A);[/quote]
Конечно не правильно.
void sendPingPacket() { // fixed header sendByteToMQTTclient((byte)0xC0); // MQTT Control Packet type (12) 1100 ping, reserved 0000 sendByteToMQTTclient((byte)0x00); // Remaining Length }А дисконнектит вас сервер скорее всего из за того что заканчивается timeout время, отсылаемое сервером в CONNECT PACKET - выше опять же примеры - вставлете свое нужное время и сервер будет это время держать.
Так для этого пинги и посылаю чтоб не заканчивалось. Если пинги не кидаю дисконнектит по таймауту, как положено. Но если послать пинг, хоть сразу после подключения - дисконнектит сразу.
Так для этого пинги и посылаю чтоб не заканчивалось. Если пинги не кидаю дисконнектит по таймауту, как положено. Но если послать пинг, хоть сразу после подключения - дисконнектит сразу.
значит кривой пакет
Upd: в логах самого сервера что нибудь вразумительное есть?
Разобрался, просто видимо не дожидался приглащения и брокеру улетал только "конец пакета" 1A без заголовка )) Вот так работает:
bool mqttPing() { gsm.println("AT+CIPSEND"); if (gsm.find(">")) { gsm.write(0xC0); gsm.write(byte(0)); gsm.write(0x1A); } return gsm.find("SEND OK"); }видимо не дожидался приглащения
Мне конечно пофиг :)
но этим страдают множество проектов для Sim800, не дожидаются ответа модема и шлют уже что то другое.....о стабильности и корректности работы таких проектов можно только мечтать.
Фейл.. опять отлетает, бред какой то... Я правильно понял из спецификации, пакет PINGREQ это 0xC0 0x00 и всё?
пакет PINGREQ это 0xC0 0x00 и всё?
да.
советы стандартные: смотреть что пишет модем, смотреть что пишет брокер, разбираться.....