Снова MQTT

flat
Offline
Зарегистрирован: 05.02.2015

Осваиваю wemos. Хочу порулить через cloudmqtt.com.
Что сделано
1. Заведен mqtt брокер с именем home.
2. в телефоне поставлено mqtt dashboard. Оформлена подписка на тему home/temp. Добавлен виджет паблишера svetik.
3. Скетч в порт выдает

Код (Text):
  1.  
  2. Connecting to xxxxx...
    WiFi connected
    IP: 192.168.4.105
    MAC: 60:01:94:14:E9:60
    Mask: 255.255.255.0
    Gateway: 192.168.4.1
    SSID: xxxxx
    Signal lvl: -84
    Connecting to MQTT server
    Connected to MQTT server
     
  3. 1
  4. 1
  5. 1
  6.  

НО в дашбоард эта единичка не прилетает. И светодиодом поморгать не могу... уже и видео посмотрел ... что то похоже не сделал .. а вот что хз...
Если при подключеном дашборде сменить состояние светодиода, отключится и снова сменить то при подключении оно восстанавливается.. так что связь телефон 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");
      }
    }

  }
}

 

flat
Offline
Зарегистрирован: 05.02.2015

Разобрался наконец то с подключением и тп...

При загрузке прочитывает только топик 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("Подключение не удалось");
      }
    }
 
  }
}
 

 

flat
Offline
Зарегистрирован: 05.02.2015

на 3 форуме спрашиваю... и везде тишина... неужто никто не делал восстановление данных после перезагрузки вемоса/ардуины и тп )

krepton85
Offline
Зарегистрирован: 02.02.2016

Почему ж не делали, делали, я использую встроенный EEPROM ESP8266. Вот мой последний проект: https://youtu.be/YVLLmWthCts там очень много кода. :) 

И кстати команду WIFI.begin() не нужно вызывать вновь при разрыве WiFI подключения (я тоже раньше так косячил) достаточно 1 раз при загрузке модуля вызвать команду wifi.begin() и при разрывах будет сам вновь подключаться. 

И еще на будущее, у этой библиатеки pubsubclient есть косяк - нельзя однавременно в одном цикле loop отправлять с десяток исходящих сообщений, можно только по 1-му сообщению за один цикл loop, а иначе это приведет к подвисанию модуля т.к. на отправку одного сообщения уходит много времени (порядка 200 милисек).

flat
Offline
Зарегистрирован: 05.02.2015

krepton85 пишет:

Почему ж не делали, делали, я использую встроенный EEPROM ESP8266. Вот мой последний проект: https://youtu.be/YVLLmWthCts там очень много кода. :) 

И кстати команду WIFI.begin() не нужно вызывать вновь при разрыве WiFI подключения (я тоже раньше так косячил) достаточно 1 раз при загрузке модуля вызвать команду wifi.begin() и при разрывах будет сам вновь подключаться. 

И еще на будущее, у этой библиатеки pubsubclient есть косяк - нельзя однавременно в одном цикле loop отправлять с десяток исходящих сообщений, можно только по 1-му сообщению за один цикл loop, а иначе это приведет к подвисанию модуля т.к. на отправку одного сообщения уходит много времени (порядка 200 милисек).

 

Огромное спасибо за советы... 1 запись за loop.. ну введу флаг ) хотя...Может есть другие библиотеки? 

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

krepton85
Offline
Зарегистрирован: 02.02.2016

Ну некоторые данные можно хранить в облаке, если отправлять с пометкой "retained". Библиатека есть др. универсальная, ее все используют почему то. А эта спициальная для esp8266. У др. библиотеки тоже косяк, точно такой же, но с подписками, нельзя подписываться на кучу топиков за один цикл loop.

flat
Offline
Зарегистрирован: 05.02.2015

мои данные желательно хранить в облаке.... каму интересен цвет и время включения в акве... уж лучше постить за 1 луп... 

НО КАК БЛИН принудительно прочитать тему???? уже мозг сломал 

krepton85
Offline
Зарегистрирован: 02.02.2016

Ну за один цикл loop и не обязательно передовать все исходящие сообщения, я сделал лист для последовательной отправки 10 сообщений, в итоге все 10 исходящих сообщений отправятся за 10 циклов loop.

Да топики сами читаются (входящие сообщения обрабатывает callback). Запускается это все автоматически из цикла loop командой client.loop(), если подключен к серверу(облаку). Но в вашем скетче заметил не дописанный момент, во второй топих данные входящие прилетают, но с ними ничего не выполняется, они ни чем не управляют. Подключите же к ним уж наконц, света-диод какой нибудь. :) А все увидел топик "/Home/svetdiap" управляет каким то световым эфектом.

flat
Offline
Зарегистрирован: 05.02.2015

угу .... 

 

мне важно прочитать топики при включении вемоса.... а не при изменении топика... при изменении читает все норм... при включении читает тока первый... 

поэтому либо принудилово читать любой топик... либо при запуске читать все топики... 

пока учусь ... топиков будет штук 40 ) ... обработчики смысла писать нет ... пока не научусь... ибо если не работает такая хрень уйду на каскаду... 

krepton85
Offline
Зарегистрирован: 02.02.2016

Просто отправляйте данные в этот топик /Home/svetdiap с пометкой retained через приложение.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Подниму старую тему, вопрос по получению ответа от MQTT сервера.

на ESP8266 WeMos отправлю PUB пакеты, все отлично работает, тут вопросов нет.

на сервере в логах вижу такую запись:

2018-11-09 12:20:31: Sending CONNACK to AndycatES39 (1, 0)

т.е. если я правильно понял - мне сервер что то послал,

смотрю такой командой:

while (client.available()) Serial.write(client.read());

Должен ли я с помощью данного кода увидеть ответ сервера?

krepton85
Offline
Зарегистрирован: 02.02.2016

Нет, не правильно, там же входящие сообщения обробатываются в цикле void callback();
И есть 2 разных версии этой библиотеки от разных разработчиков, одна построеннана строках объекта класса String (рекомендованна для esp8266) , а др. на char.

sadman41
Offline
Зарегистрирован: 19.10.2016

Думаю, что служебные протокольные данные (такие, как CONNECT, ACK и т.д.) через обычный read() получить нельзя (да и смысла нет).

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

krepton85 пишет:
Нет, не правильно, там же входящие сообщения обробатываются в цикле void callback(); И есть 2 разных версии этой библиотеки от разных разработчиков, одна построеннана строках объекта класса String (рекомендованна для esp8266) , а др. на char.

я без всяких библиотек работаю, иначе не интересно.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sadman41 пишет:

Думаю, что служебные протокольные данные (такие, как CONNECT, ACK и т.д.) через обычный read() получить нельзя (да и смысла нет).

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

Update: судя по доке если я правильно понял, возвращается всего один байт - код ответа. Попробую вывести в консоль.

sadman41
Offline
Зарегистрирован: 19.10.2016

andycat пишет:

Update: судя по доке если я правильно понял, возвращается всего один байт - код ответа. Попробую вывести в консоль.

Тогда уточните - кто есть client - что за объект/класс?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sadman41 пишет:

andycat пишет:

Update: судя по доке если я правильно понял, возвращается всего один байт - код ответа. Попробую вывести в консоль.

Тогда уточните - кто есть client - что за объект/класс?

WiFiClient client;

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

весь код если вдруг нужен:

#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]));
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Если сами пакет формируете, а не через PubsClient, то тогда должны получить. Я думал, что ваш клиент - библиотечный объект.  C другой стороны в readResponseFromClient() должны уже получать что-то прилетающее от сервера после коннекта.

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sadman41 пишет:

 readResponseFromClient() 

спасибо за подсказку/направление, дальше думаю разберусь.

 

Short Circuit
Short Circuit аватар
Offline
Зарегистрирован: 17.05.2015

А как для SIM800 примерно тоже сделать?

Проверенные примеры где то есть?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

А в чем глобальная разница?
Есть примеры, поиском по mqtt посмотрите,
Irinka недавно делала

http://arduino.ru/forum/apparatnye-voprosy/arduino-uno-sim800lmqttblynk

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

закончил игрушку, отправка температуры, прием цвета и зажигание 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;
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Нашлись служебные данные?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sadman41 пишет:

Нашлись служебные данные?

Приходящие байты видны, но не на все команды есть ответы.

на CONNECT я так и не увидел, на SUBSCRIBE и PINGREQ ответы ожидаемо есть.

Т.е. читаем правильно - client.read()

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Закончил мучать связку SIM800L + MQTT

Выкладываю рабочую последовательность команд работы с модемом:

Power ON or WDT reset

// проверка связи

AT
AKey ON 
T

OK

// включаем режим распознования DTMF

AT+DDET=1
AT+DDET=1

OK

// отключаем возврат команд от модема

ATE0
ATE0

OK

// включаем АОН

AT+CLIP=1

OK

// вручную поднимать трубку при входящем звонке

ATS0=0

OK

// развернутый символьный ответ от модема

ATV1

OK

// подробный вывод ошибок

AT+CMEE=2

OK

// PDU режим приема и отправки SMS

AT+CMGF=0

OK

// проверяем что зарегестрировались в домашней сети

AT+CREG?

+CREG: 0,1

OK

// настройки нужны если отправлять http запросы и получать ответы самим модемом

AT+SAPBR=3,1,"CONTYPE","GPRS"

OK

AT+SAPBR=3,1,"APN","internet"

OK

AT+SAPBR=3,1,"USER",""

OK

AT+SAPBR=3,1,"PWD",""

OK

// включаем режим ухода в сон с помощью пина DTR на модеме

AT+CSCLK=1

OK

// смотрим кто оператор

AT+COPS?

+COPS: 0,0,"MOTIV"

OK

// Проверка доступа к услугам пакетной передачи данных

AT+CGATT?

+CGATT: 1

OK

// Командный режим передачи данных

AT+CIPMODE=0

OK

// Моносокет, т.е. как я понял - единомоментно работаем только с одним сервером

AT+CIPMUX=0

OK

// Перед блоком данных, принятых от сервера добавлять заголовок формата +IPD,<длина блока данных>

AT+CIPHEAD=1

OK

// При приеме данных не показывать уведомление в виде RECV FROM:<IP адрес отправителя>,<порт>

AT+CIPSRIP=0

OK

Ready

// закончили стартовую инициализацию, начинаем основной цикл
// у меня например отправка на MQTT сервер идет каждые 30 секунд
// соотвественно от модема ждем корректный ответ 40 секунд (больше 
// периода цикла, в случае не корректного ответа и/или его 
// отсутствии - перезагрузка модема


// смотрим статус

AT+CIPSTATUS

OK

STATE: IP INITIAL

// точка APN

AT+CSTT="internet"

OK

// смотрим статус

AT+CIPSTATUS

OK

STATE: IP START

// Активация контекста

AT+CIICR

OK

// смотрим статус

AT+CIPSTATUS

OK

STATE: IP GPRSACT

// как я понял вывод клиентского IP адреса, но выводится какая то хрень

AT+CIFSR

// смотрим статус

AT+CIPSTATUS
1\???rj?
OK

STATE: IP STATUS

// подключаемся к серверу

AT+CIPSTART="TCP","m23.cloudmqtt.com",15069

OK

CONNECT OK

// смотрим статус

AT+CIPSTATUS

OK

STATE: CONNECT OK

// Нормальный режим передачи данных.При этом режиме каждая порция высланных данных подтверждается сообщением “SEND OK”, что означает, что сервер данные принял и подтвердил их получение

AT+CIPQSEND=0

OK

// отправка данных после приглашения >
// пишем количество отправляемых байт

AT+CIPSEND=149

// пакет CONNECT, обязательно в пакете указать "время жизни" т.е. время до разрыва связи
// у меня 40 секунд - больше времени цикла, что бы получить команды от сервера
> 0x10 ( 0x0  0x4 MQTT 0x4  0xC0  0x0 ( 0x0  0x4 AT41 0x0  0x8 MQTTLOGIN 0x0  0xC MQTTPASS
// пакет SUBSCRIBE
 0x82  0xD  0x0  0xA  0x0  0x8 AT41/key 0x0 
// пакеты PUBLISH
1 0xF  0x0  0xA AT41/gps_l 0x0  0x0 5
1 0x10  0x0  0xA AT41/gps_b 0x0  0x0 93
0 0x11  0x0  0x9 AT41/temp 0x0  0x0 18.8
0 0x10  0x0  0x8 AT41/vin 0x0  0x0 3.96
0 0x12  0x0  0xB AT41/uptime 0x0  0x0 003
 
// это косяк - данные не отправились
CLOSED
// единственное место где идет игнорирование ответа от модема
// соотвественно мы ждем 40 секунд и вместо перезагрузки модема идем дальше
No response!

// ЖДЕМ КОНЦА ЦИКЛА

// закрываем сессию

AT+CIPSHUT

SHUT OK


// Начали новый цикл

AT+CIPSTATUS

OK

STATE: IP INITIAL
AT+CSTT="internet"

OK
AT+CIPSTATUS

OK

STATE: IP START
AT+CIICR

OK
AT+CIPSTATUS

OK

STATE: IP GPRSACT
AT+CIFSR

AT+CIPSTATUS
1\????
OK

STATE: IP STATUS
AT+CIPSTART="TCP","m23.cloudmqtt.com",15069

OK

CONNECT OK
AT+CIPSTATUS

OK

STATE: CONNECT OK
AT+CIPQSEND=0

OK
AT+CIPSEND=149

> 0x10 ( 0x0  0x4 MQTT 0x4  0xC0  0x0 ( 0x0  0x4 AT41 0x0  0x8 ****** 0x0  0xC *******
 0x82  0xD  0x0  0xA  0x0  0x8 AT41/key 0x0 
1 0xF  0x0  0xA AT41/gps_l 0x0  0x0 6
1 0x10  0x0  0xA AT41/gps_b 0x0  0x0 95
0 0x11  0x0  0x9 AT41/temp 0x0  0x0 18.8
0 0x10  0x0  0x8 AT41/vin 0x0  0x0 3.96
0 0x12  0x0  0xB AT41/uptime 0x0  0x0 004


// а вот это уже корректный ответ - данные успешно отправлены на сервер 
SEND OK
403

+IPD,4: 
+IPD,5:?
2192
AT+CIPSHUT

SHUT OK
AT+CIPSTATUS

OK

STATE: IP INITIAL
AT+CSTT="internet"

OK
AT+CIPSTATUS

OK

STATE: IP START
AT+CIICR

OK
AT+CIPSTATUS

OK

STATE: IP GPRSACT
AT+CIFSR

AT+CIPSTATUS
1\???4??
OK

STATE: IP STATUS
AT+CIPSTART="TCP","m23.cloudmqtt.com",15069

OK

CONNECT OK
AT+CIPSTATUS

OK

STATE: CONNECT OK
AT+CIPQSEND=0

OK
AT+CIPSEND=149

> 0x10 ( 0x0  0x4 MQTT 0x4  0xC0  0x0 ( 0x0  0x4 AT41 0x0  0x8 ****** 0x0  0xC ******
 0x82  0xD  0x0  0xA  0x0  0x8 AT41/key 0x0 
1 0xF  0x0  0xA AT41/gps_l 0x0  0x0 4
1 0x10  0x0  0xA AT41/gps_b 0x0  0x0 91
0 0x11  0x0  0x9 AT41/temp 0x0  0x0 19.2
0 0x10  0x0  0x8 AT41/vin 0x0  0x0 4.03
0 0x12  0x0  0xB AT41/uptime 0x0  0x0 004
 
SEND OK

+IPD,4: 
+IPD,5:?
// ответы на подписанные топики MQTT
+IPD,13:0AT41/key7Key OFF

+IPD,13:0AT41/key5Key ON


AT+CIPSHUT

SHUT OK

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Logik
Offline
Зарегистрирован: 05.08.2014

Хоть хтото чето  полезного запостил. Спасибо, интересно.

// Моносокет, т.е. как я понял - единомоментно работаем только с одним сервером

Я так понимаю, если  не моносокет, то в AT+CIPSTART, AT+CIPSEND, RECV FROM: и еще коегде добавляется еще один параметр - номер соединения.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Logik пишет:

Хоть хтото чето  полезного запостил. 

Во блин, крутышка посчитал что червь хоть что то знает :)

ЗЫ. Я вас уже давно просил, пожалуйста не отвечайте на мои посты, у меня на вас аллергия.

Logik
Offline
Зарегистрирован: 05.08.2014

Ваш монолог прерывать не буду, алергией червя удовлетворен ;)

VaDoSiQ
VaDoSiQ аватар
Offline
Зарегистрирован: 19.01.2017

flat пишет:

НО КАК БЛИН принудительно прочитать тему???? уже мозг сломал 

Например указать подписки на топики в функции reconnect()

Ну и в callback:


if(strcmp(topic, "topic") == 0) {
  //code
}

 

OOM
Offline
Зарегистрирован: 07.01.2017

Подскажите. Есть локальный сервер, нужно управлять устройством по протоколу MQTT.

Вопрос? Для MQTT обязательно нужен Интернет, или можно сделать свой локальный. Устройство будет работать в чистом поле где нет интернета

sadman41
Offline
Зарегистрирован: 19.10.2016

Для MQTT, как протокола, Интернет не нужен.

OOM
Offline
Зарегистрирован: 07.01.2017

Извените, а протокол и брокер MQTT это одно и тоже или разные вещи?

krepton85
Offline
Зарегистрирован: 02.02.2016

OOM пишет:

Извените, а протокол и брокер MQTT это одно и тоже или разные вещи?


Брокер это облоко (сервер) , через который все работает по протаколу MQTT. Это самое главное без брокера не могут устройства (клиенты mqtt) обмениватся сообщениям.

dm211
Offline
Зарегистрирован: 30.01.2019

Н а моем новом телефоне не работает mqtt протокол похоже, предыдущий телефон с андроид норм работал, а новый- Honor 9 lyte не связывается-пишет постоянно-ошибка соединения, кто сталкивался может? Брокер зарегистрирован на cloudmqtt.com, на смартфоне пробовал и mqttdash и mqtt dashboard, везде ошибка выходит, видать в телефоне что то не пропускает.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

dm211 пишет:

Н а моем новом телефоне не работает mqtt протокол похоже, предыдущий телефон с андроид норм работал, а новый- Honor 9 lyte не связывается-пишет постоянно-ошибка соединения, кто сталкивался может? Брокер зарегистрирован на cloudmqtt.com, на смартфоне пробовал и mqttdash и mqtt dashboard, везде ошибка выходит, видать в телефоне что то не пропускает.

1. это сайт про Ардуино

2. думаю конкретно у вас и/или оператора проблемы + перепроверьте логин/пароль/сайт для подключения

3. у меня Honor 6A Андроид 7 работает отлично.

Upd: вокруг меня много любителей ставить антивирус на Андроид, возможно и у вас что то режет трафик.

dm211
Offline
Зарегистрирован: 30.01.2019

1.Ну так-на той стороне стоит Ардуино с ESP8266. И тема называется Снова MQTT.

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

3. У меня Honor 9 с восьмым андроидом и не работает.

Ставил на голый андроид, сам антивирус не ставил,но скрытый есть там вроде,при проверке системы на вирусы надпись Аваст виден, будем копать в сторону рута, но это тоже не очень гуд, с роутом на старом смартфоне переставал работать Сбербанк онлай, ругался на рут.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Ох сомневаюсь что дело в андроиде и рут вам не нужен.
Найду телефон с 9м андроидом - проверю из любопытства.

Upd так если рут стоит, особенно если совсем не РСТ то с большой вероятностью не заработает

vlad072
Offline
Зарегистрирован: 01.08.2017

Метод PubSubClient::publish() кушает только си-шные строки, но никак не стринги. Т.е. в 45й строке должно быть

  client.publish("Home/temp", (char*)String(temp).c_str());

 

vlad072
Offline
Зарегистрирован: 01.08.2017

Во, коструктивчик, спасибо! А я было уже собрался ленивого в себе бороть и закуривать протокол ))

dm211
Offline
Зарегистрирован: 30.01.2019

Похоже не победить этот андроид 8, буду переходить на Blynk.

vlad072
Offline
Зарегистрирован: 01.08.2017

andycat пишет:

sadman41 пишет:

Нашлись служебные данные?

Приходящие байты видны, но не на все команды есть ответы.

на CONNECT я так и не увидел, на SUBSCRIBE и PINGREQ ответы ожидаемо есть.

Т.е. читаем правильно - client.read()

У меня на запрос пинга cloudmqtt.com почему то дисконнектит. может я его не правильно отсылаю?

gsm.println("AT+CIPSEND");
gsm.write(0xC0); gsm.write(byte(0)); gsm.write(0x1A);

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

vlad072 пишет:

У меня на запрос пинга cloudmqtt.com почему то дисконнектит. может я его не правильно отсылаю?

gsm.println("AT+CIPSEND");
gsm.write(0xC0); gsm.write(byte(0)); gsm.write(0x1A);

 

[/quote]

Конечно не правильно.

Примеры процедур отправки
 
 
Список команд для модема
 
 
Отправка Ping пакета
 
void sendPingPacket() {
  // fixed header
  sendByteToMQTTclient((byte)0xC0); // MQTT Control Packet type (12) 1100 ping, reserved 0000
  sendByteToMQTTclient((byte)0x00); // Remaining Length
}

 

ЗЫ. Причем я уже давал ссылки эти в другой ветке, вашего сарказма/вопроса про моргание лампочек не понял. Делаю вывод что вы даже не попытались вникнуть в пример и вытащить оттуда готовые фнкции по отправке MQTT пакетов.

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

А дисконнектит вас сервер скорее всего из за того что заканчивается timeout время, отсылаемое сервером в CONNECT PACKET - выше опять же примеры - вставлете свое нужное время и сервер будет это время держать.

vlad072
Offline
Зарегистрирован: 01.08.2017

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

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

vlad072 пишет:

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

значит кривой пакет

Upd: в логах самого сервера что нибудь вразумительное есть?

 

vlad072
Offline
Зарегистрирован: 01.08.2017

Разобрался, просто видимо не дожидался приглащения и брокеру улетал только "конец пакета" 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");
}

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

vlad072 пишет:

видимо не дожидался приглащения 

Мне конечно пофиг :)

но этим страдают множество проектов для Sim800, не дожидаются ответа модема и шлют уже что то другое.....о стабильности и корректности работы таких проектов можно только мечтать.

vlad072
Offline
Зарегистрирован: 01.08.2017

Фейл.. опять отлетает, бред какой то... Я правильно понял из спецификации, пакет PINGREQ это 0xC0 0x00 и всё?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

vlad072 пишет:

 пакет PINGREQ это 0xC0 0x00 и всё?

да.

советы стандартные: смотреть что пишет модем, смотреть что пишет брокер, разбираться.....