Начиная со стр #9 идёт выплёскивание пакета MQTT: два байта (MQTTProtocolNameLength), которые на картинке "Protocol name (length)", потом четыре байта (MQTTProtocolName) "Protocol name" - "MQTT". Байт (MQTTLVL) "Protocol level"... и т.д.
Не переживайте, я тоже не понял пока её функционал.
Irinka пишет:
Serial.write(MQTTProtocolNameLength >> 8);// Здесь, как Вы сказали, два байта длина Protocol name?
Serial.write(MQTTProtocolNameLength & 0xFF);//? Serial.write(MQTTProtocolName);//MQIsdp
unsigned short MQTTProtocolNameLength; <= два байта.
Каждый write() выводит по байту - сначала старший, потом младший.
тут с комментариями пакет подключения, каждая строчка прокомментирована текстом из официальной документации, там на официальной странице MQTT все описания есть.
Integer data values are 16 bits in big-endian order: the high order byte precedes the lower order byte. This means that a 16-bit word is presented on the network as Most Significant Byte (MSB), followed by Least Significant Byte (LSB).
Целочисленные значения данных составляют 16 бит в порядке Биг-эндиана: старший байт предшествует младшему байту. Это означает, что 16-разрядное слово представлено в сети как наиболее значимый байт (MSB), за которым следует наименее значимый байт (LSB).
т е старший и младший байт числа
3.1.2.7 Will Retain
Position: bit 5 of the Connect Flags.
This bit specifies if the Will Message is to be Retained when it is published.
If the Will Flag is set to 0, then the Will Retain Flag MUST be set to 0 [MQTT-3.1.2-15].
If the Will Flag is set to 1:
If Will Retain is set to 0, the Server MUST publish the Will Message as a non-retained message [MQTT-3.1.2-16].
If Will Retain is set to 1, the Server MUST publish the Will Message as a retained message [MQTT-3.1.2-17]..
по русски - если нужно чтобы подписанные на топик клиенты видели ранее сохраненное значение то этот флаг должен быть включен
Will QoS - подтверждение получение - есть два варианта, я например только 0 использую, т е без подтверждения, т.к. смысла нет - послал запрос на железку - железка приняла данные - пришел ответ, если ответа нет - проблема. Впрочем дело вкуса.
3.1.3.2 Will Topic
If the Will Flag is set to 1, the Will Topic is the next field in the payload
я так понимаю что установка флага подразумевает отправку длинного сообщения состоящего из нескольких
3.1.2.4 Clean Session
Position: bit 1 of the Connect Flags byte.
This bit specifies the handling of the Session state.
The Client and Server can store Session state to enable reliable messaging to continue across a sequence of Network Connections. This bit is used to control the lifetime of the Session state
думаю используется для удержания сессии при QoS 1 2, при 0 флаге по окончании таймаута требуется переподключение к серверу или слать ping пакеты через определенные периоды
Will QoS - подтверждение получение - есть два варианта, я например только 0 использую, т е без подтверждения, т.к. смысла нет - послал запрос на железку - железка приняла данные - пришел ответ, если ответа нет - проблема. Впрочем дело вкуса.
Установка соединения с MQTT брокером
AT+SAPBR=3,1, "Contype","GPRS" - настройка параметров соединения, ответ OK
AT+SAPBR=3,1, "APN","internet.mts.by" - установка точки доступа, ответ OK
AT+SAPBR=1,1 - установка GPRS соединения, ответ OK
AT+SAPBR=2,1 - проверка соединения, ответ +SAPBR: 1,1,"100.78.6.XXX"
AT+CIPSTART="TCP","m23.cloudmqtt.com","10077" - установка связи с сервером, ответ CONNECT OK
AT+CIPSEND - команда на отпраку пакета
пакет авторизации MQTT_CON()
пакет публикации MQTT_PUB()
пакет подписки MQTT_SUB()
1A - байт окончания передачи пакета
Установка соединения с MQTT брокером
AT+SAPBR=3,1, "Contype","GPRS" - настройка параметров соединения, ответ OK
AT+SAPBR=3,1, "APN","internet.mts.by" - установка точки доступа, ответ OK
AT+SAPBR=1,1 - установка GPRS соединения, ответ OK
AT+SAPBR=2,1 - проверка соединения, ответ +SAPBR: 1,1,"100.78.6.XXX"
AT+CIPSTART="TCP","m23.cloudmqtt.com","10077" - установка связи с сервером, ответ CONNECT OK
AT+CIPSEND - команда на отпраку пакета
пакет авторизации MQTT_CON()
пакет публикации MQTT_PUB()
пакет подписки MQTT_SUB()
1A - байт окончания передачи пакета
Для повышения образованности и дальнейших "экспериментов"
const byte MQTT_Connect_Flags=B11000110;
//7 bit User name flag (1)
//6 bit Password flag (1)
//5 bit Will RETAIN (0)
//4 bit Will QoS (0)
//3 bit Will QoS (0)
//2 bit Will flag (1)
//1 bit Clean Session (1)
//0 bit не используется
SIM800.write(MQTT_Connect_Flags);//Connect Flags
Вот так можно будет отправлять байт флага, вместо SIM800.write(0xC6);//Connect Flags
И уж сразу еще вопрос, я же могу хранить эти переменные во флеш памяти?
Мне кажется Вам реально заняться нечем в плохом смысле. Вам скинули несколько готовых функций, пользуйтесь, не нужно ничего придумывать. Так же ссылку на самый подробный солюшн по MQTT, даже с примерами, изучайте. Всё равно не понятно? - Сопоставьте первое со вторым.
2019-12-05 18:16:58: Log cleared by user
2019-12-05 18:17:08: New connection from 176.59.100.9 on port 11481.
2019-12-05 18:18:38: Client <unknown> has exceeded timeout, disconnecting.
2019-12-05 18:16:58: Log cleared by user
2019-12-05 18:17:08: New connection from 176.59.100.9 on port 11481.
2019-12-05 18:18:38: Client <unknown> has exceeded timeout, disconnecting.
2019-12-05 18:16:58: Log cleared by user
2019-12-05 18:17:08: New connection from 176.59.100.9 on port 11481.
2019-12-05 18:18:38: Client <unknown> has exceeded timeout, disconnecting.
на примерно таком же скетче я тоже познавал MQTT. Но сразу скажу, что нужно работать с модемом в режиме диалога. Т.е. если с сервера выкидывает происходило переподключение и т.д. А этот скетч чисто для проверки подключения к брокеру.
#include <SoftwareSerial.h>
SoftwareSerial SIM800 (6, 7);//Rx, Tx //UART для соединения с GSM модулем
//---------------------------Настройки MQTT-----------------------------------------------------------------------------
const char ACCESSPOINT[]= "\"internet.mts.by\""; // точка доступа оператора связи симкарты
const char PROTOCOLIUS[] = "MQIsdp"; // это и оставляем
const char MQTTNAME[] = "Ma V"; // это смотрим на сервере MQTT
const char MQTTUSER[] = "i r"; // это смотрим на сервере MQTT
const char MQTTPASSWORD[] = "1 g"; // это смотрим на сервере MQTT
const char SERVERNAME_PORT[] = "\"m16.cloudmqtt.com\", \"14325\""; // это смотрим на сервере MQTT
#define TIMEBROKER 20 // таймаут бездействия с брокером, мин (при превышении его с сервера выкидывает)
//----------------------------------------------------------------------------------------------------------------------
byte Init = 1; // переменная автомат инита
int temper = 25; // так просто переменная, например температуры
void setup()
{
delay (5000); // ждём пока модем одуплится
Serial.begin(19200); // отладка
SIM800.begin(38400); // сериал соединение для gsm модуля
}
void loop()
{
SIM800setting (); // настройка модема
if (SIM800.available()>0) Serial.write(SIM800.read()); // отладка модема
sendDataMQTT(); // периодическая отправка данных на брокер
}
void SIM800setting ()
{
static uint32_t previnit = 0;
if (Init<=11 && millis() - previnit>3000)
{
if (Init == 1) SIM800.println (F("AT+CIPHEAD=1"));
else if (Init == 2) SIM800.println (F("AT+CMGF=1"));
else if (Init == 3) SIM800.println (F("AT+IFC=0, 0"));
else if (Init == 4) SIM800.println (F("AT+GSMBUSY=1"));
else if (Init == 5) SIM800.println (F("AT+CNMI=1,2,2,1,0"));
else if (Init == 6) SIM800.println (F("AT+SAPBR=3,1, \"Contype\",\"GPRS\""));
else if (Init == 7) SIM800.print (F("AT+SAPBR=3,1, \"APN\",")), SIM800.println (ACCESSPOINT);
else if (Init == 8) SIM800.println (F("AT+SAPBR=1,1"));
else if (Init == 9) SIM800.print (F("AT+CIPSTART=\"TCP\",")), SIM800.println (SERVERNAME_PORT);
else if (Init == 10) AUTHsend (); // отправка брокеру пакета авторизации
else if (Init == 11) SUBsend("top/#"); // подписка на топики
previnit = millis();
Init++;
}
}
void AUTHsend ()
{
SIM800.println (F("AT+CIPSEND"));
delay (250);
uint16_t timeBroker = TIMEBROKER;
SIM800.write (0x10);
SIM800.write (strlen(PROTOCOLIUS) + strlen(MQTTNAME) + strlen(MQTTUSER) + strlen(MQTTPASSWORD) + 12);
SIM800.write ((byte)0);
SIM800.write (strlen(PROTOCOLIUS));
SIM800.write (PROTOCOLIUS);
SIM800.write (0x03);
SIM800.write (0xC2);
timeBroker *=60;
byte * timeBr = (byte*)&timeBroker;
SIM800.write(*(timeBr+=1)); // время сеанса связи с брокером, сек (ст. байт)
SIM800.write(*(--timeBr)); // время сеанса связи с брокером, сек (мл. байт)
SIM800.write ((byte)0);
SIM800.write (strlen(MQTTNAME));
SIM800.write (MQTTNAME);
SIM800.write ((byte)0);
SIM800.write (strlen(MQTTUSER));
SIM800.write (MQTTUSER);
SIM800.write ((byte)0);
SIM800.write (strlen(MQTTPASSWORD));
SIM800.write (MQTTPASSWORD);
SIM800.write (0x1A);
}
void SUBsend (char topSub[20]) {
SIM800.println (F("AT+CIPSEND"));
delay (250);
SIM800.write (0x82);
SIM800.write (strlen(topSub) + 5);
SIM800.write ((byte)0);
SIM800.write (0x01);
SIM800.write ((byte)0);
SIM800.write (strlen(topSub));
SIM800.write (topSub);
SIM800.write ((byte)0x00);
SIM800.write (0x1A);
}
void PUBsend (char topPub[30], String Command)
{
SIM800.println (F("AT+CIPSEND"));
delay (250);
SIM800.write (0x30);
SIM800.write (strlen (topPub) + Command.length() + 2);
SIM800.write ((byte)0x00);
SIM800.write (strlen (topPub));
SIM800.write (topPub);
for (byte i = 0; i < Command.length(); i++) SIM800.write (Command[i]);
SIM800.write(0x1A);
}
void sendDataMQTT()
{
if (Init>=12) // если инит модема завершен
{
static uint32_t prev = 0;
if (millis() - prev>5000) //периодически отправляем топик с температурой на брокер
{
PUBsend ("top/temp", String(temper));
prev = millis();
}
}
}
2019-12-05 18:16:58: Log cleared by user
2019-12-05 18:17:08: New connection from 176.59.100.9 on port 11481.
2019-12-05 18:18:38: Client <unknown> has exceeded timeout, disconnecting.
и чудненько!!!
В каком смысле?
В прямом, сервер подождал 30 секунд данные и отключился.
Я ж выше давал ссылку на описание и пример команд и там чёрным по русски было написано что в пакете connect указывать время соединения, будьте добры или данные отправлять каждые 20 секунд или переподключаться.
https://openlabpro.com/guide/mqtt-packet-format/
Тяжело для понимая в таком виде..
Начиная со стр #9 идёт выплёскивание пакета MQTT: два байта (MQTTProtocolNameLength), которые на картинке "Protocol name (length)", потом четыре байта (MQTTProtocolName) "Protocol name" - "MQTT". Байт (MQTTLVL) "Protocol level"... и т.д.
Получается, это тоже самое что я делала раньше в ручную...
Serial.write(0x10); //Печатаю маркер авторизации
Serial.write(encodedByte);//Это общая длина пакета подписки
Serial.write(MQTTProtocolNameLength >> 8);// Здесь, как Вы сказали, два байта длина Protocol name?
Serial.write(MQTTProtocolNameLength & 0xFF);//? Serial.write(MQTTProtocolName);//MQIsdp
unsigned short MQTTProtocolNameLength; <= два байта.
Каждый write() выводит по байту - сначала старший, потом младший.
Вместо тысячи слов
что за константа? версия протокола MQTT?
что за флаг? 00 и 3C это keep alive? а что E6 ? keepAliveInterval?
почему после названия устройства печатаются эти строки, а не сразу логин и пароль?
это же только пакет авторизации
http://arduino.ru/forum/programmirovanie/snova-mqtt-1?page=1#comment-460595
тут с комментариями пакет подключения, каждая строчка прокомментирована текстом из официальной документации, там на официальной странице MQTT все описания есть.
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718028
1. Да, версия протокола.
2. 0х3С = 60(dec) да, keep alive таймаут. 0xE6 - флаги
MQTT в главе 3 все сообщения доступно разжёваны, рекомендую.
Integer data values are 16 bits in big-endian order: the high order byte precedes the lower order byte. This means that a 16-bit word is presented on the network as Most Significant Byte (MSB), followed by Least Significant Byte (LSB).
Целочисленные значения данных составляют 16 бит в порядке Биг-эндиана: старший байт предшествует младшему байту. Это означает, что 16-разрядное слово представлено в сети как наиболее значимый байт (MSB), за которым следует наименее значимый байт (LSB).
т е старший и младший байт числа
3.1.2.4 Clean Session
Position: bit 1 of the Connect Flags byte.
This bit specifies the handling of the Session state.
The Client and Server can store Session state to enable reliable messaging to continue across a sequence of Network Connections. This bit is used to control the lifetime of the Session state
думаю используется для удержания сессии при QoS 1 2, при 0 флаге по окончании таймаута требуется переподключение к серверу или слать ping пакеты через определенные периоды
Вот что у меня получилось, прошу проверить.
Ссылка на файл эксель https://dropmefiles.com/TpR0W
Will QoS - подтверждение получение - есть два варианта, я например только 0 использую, т е без подтверждения, т.к. смысла нет - послал запрос на железку - железка приняла данные - пришел ответ, если ответа нет - проблема. Впрочем дело вкуса.
00 - без подтверждения (4 бит -0 3 бит - 0)
01 - с подтверждением (4 бит - 0 3 бит - 1)
Так?
QoS в картинках: https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels/
а зачем переводить всё в байты? я про excel. (или вы учебное пособие делаете?) Вам же дали функцию, она сама всё сделает.
мой вариант
а зачем переводить всё в байты? я про excel. (или вы учебное пособие делаете?) Вам же дали функцию, она сама всё сделает.
Для интереса.
MaksVV
а разве не побайтно нужно отправлять текст?
const char PROTOCOLIUS[] = "MQIsdp";
SIM800.write (PROTOCOLIUS);
28
//Name protokol
29
for
(
byte
i = 0; i<Size_MQTT_Protocol_Name; i++){
30
SIM800.write((
byte
)MQTT_Protocol_Name[i]);
31
}
32
//Name protokol
а зачем переводить всё в байты? я про excel. (или вы учебное пособие делаете?) Вам же дали функцию, она сама всё сделает.
Для интереса.
Лишние телодвижения как я думаю.
Сделайте один раз функцию (или готовую возьмите - выше были) и используйте.
Кстати (любопытно) зачем вам QoS 1?
Кстати (любопытно) зачем вам QoS 1?
Вы про то, что у меня там 1 установлена?
Connect Flags = 0xC6
А так всё верно у меня в коде?
ну дак напишите минискетч и проверьте свой и мой вариант. Или вот
Кстати (любопытно) зачем вам QoS 1?
Вы про то, что у меня там 1 установлена?
Connect Flags = 0xC6
А так всё верно у меня в коде?
А попробуйте с реальным сервером ;) и там по логам будет видно корректно или нет.
ну дак напишите минискетч и проверьте свой и мой вариант. Или вот
Метод тыка я люблю, это да.
НО...
Опять я путаюсь с write
Я делала как в 59 посту(е).
А попробуйте с реальным сервером ;) и там по логам будет видно корректно или нет.
Это конечно же, попробую, но для начала надо разобраться с протоколом отправки? точнее как отправлять
а не
Я запуталась
Скажите как сделать мой скетч правильно и я пошла соединяться с сервером XDDD (готовить купаты и макароны)
а не
Я запуталась
Если getSize = high то функция только возвращает размер пакета, но не отправляет его, т к мне необходимо было знать размер заранее.
ЗЫ. А мне нравиться метод научного тыка - в экспериментах рождается истина.
Скажите как сделать мой скетч правильно и я пошла соединяться с сервером XDDD (готовить купаты и макароны)
Строки 28 38 41 вы отправляете не строку, а только один байт, в цикле по строке пройдитесь и побайтно отправляйте.
54
for
(
byte
i = 0; i<Size_MQTT_Password; i++){
55
SIM800.write((
byte
)MQTT_Password[i]);
56
}
Сделать как и было, спасибо, разберусь с подключением к интернету,отпишусь.
Забыла про байт окончания передачи
1A
- байт окончания передачи пакетаЗабыла про байт окончания передачи
1A
- байт окончания передачи пакетаэто где написано?
а....ну да, я немного по другому шлю
http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-411540
Для повышения образованности и дальнейших "экспериментов"
Вот так можно будет отправлять байт флага, вместо SIM800.write(0xC6);//Connect Flags
И уж сразу еще вопрос, я же могу хранить эти переменные во флеш памяти?
Можно все, вопрос зачем, памяти не хватает или что? 10 байт вас не спасут,а лишнее написание кода добавится.
а зачем переводить всё в байты? я про excel. (или вы учебное пособие делаете?) Вам же дали функцию, она сама всё сделает.
Для интереса.
..."какая у людей интересная жизнь"... Полад Бюльбуль-Оглы
в С слаб, может и не прав, спасибо, попробую.
Я в С ещё слабее вашего, однако действовал методом научного тыка. Действительно помогает! Так сказать стараюсь сразу проверять на практике.
Вот что ответил сервер
полный скетч покажите
Тестовый скетч
Мне кажется Вам реально заняться нечем в плохом смысле. Вам скинули несколько готовых функций, пользуйтесь, не нужно ничего придумывать. Так же ссылку на самый подробный солюшн по MQTT, даже с примерами, изучайте. Всё равно не понятно? - Сопоставьте первое со вторым.
Стоп, всё сконнектилось, ошибка была из-за повторной отправки
А чуть позже на сервере
А чуть позже на сервере
и чудненько!!!
А чуть позже на сервере
и чудненько!!!
В каком смысле?
Сервер пишет что подключение есть.
буду отправлять данные
на примерно таком же скетче я тоже познавал MQTT. Но сразу скажу, что нужно работать с модемом в режиме диалога. Т.е. если с сервера выкидывает происходило переподключение и т.д. А этот скетч чисто для проверки подключения к брокеру.
А чуть позже на сервере
и чудненько!!!
В каком смысле?
В прямом, сервер подождал 30 секунд данные и отключился.
Я ж выше давал ссылку на описание и пример команд и там чёрным по русски было написано что в пакете connect указывать время соединения, будьте добры или данные отправлять каждые 20 секунд или переподключаться.