Начиная со стр #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() выводит по байту - сначала старший, потом младший.
Вместо тысячи слов
const char* proto = "MQIsdp"; const byte ver = 3; const char* cid = "devicename"; const char* willt = "online"; const char* user = "username"; const char* pass = "password"; void brokerconnect () { modem.write(0x10); modem.write( 4 + 2+strlen(proto) + 2+strlen(cid) + 2+strlen(willt) + 2+1 + 2+strlen(user) + 2+strlen(pass) ); modem.write((byte)0x00); modem.write(strlen(proto)); modem.write(proto); modem.write(ver); modem.write(0xE6); modem.write((byte)0x00); modem.write(0x3C); // flags, ka timout | E/C -retain/not modem.write((byte)0x00); modem.write(strlen(cid)); modem.write(cid); modem.write((byte)0x00); modem.write(strlen(willt)); modem.write(willt); // will topic modem.write((byte)0x00); modem.write(0x01); modem.write('0'); // will message modem.write((byte)0x00); modem.write(strlen(user)); modem.write(user); modem.write((byte)0x00); modem.write(strlen(pass)); modem.write(pass); }что за константа? версия протокола MQTT?
что за флаг? 00 и 3C это keep alive? а что E6 ? keepAliveInterval?
почему после названия устройства печатаются эти строки, а не сразу логин и пароль?
это же только пакет авторизации
modem.write((byte)0x00); modem.write(strlen(willt)); modem.write(willt); // will topic modem.write((byte)0x00); modem.write(0x01); modem.write('0'); // will messagehttp://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
byte sendConnectPacket(byte getSize) { byte sizeDevice = strlen(mqtt_device); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass); byte fullSize = 16 + sizeDevice + sizeUser + sizePass; if (getSize) return (fullSize + 2); // fixed header sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000 sendByteToMQTTclient((byte)(fullSize)); // 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)time_live_connect_packet); // Keep Alive LSB // 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])); }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. (или вы учебное пособие делаете?) Вам же дали функцию, она сама всё сделает.
мой вариант
const char ACCESSPOINT[]= "\"internet.mts.by\""; const char PROTOCOLIUS[] = "MQIsdp"; const char MQTTNAME[] = "Ma**V"; const char MQTTUSER[] = "i*****r"; const char MQTTPASSWORD[] = "1******g"; const char SERVERNAME_PORT[] = "\"m16.cloudmqtt.com\", \"14325\""; #define TIMEBROKER 20 // таймаут бездействия, превысив который с сервера выкинет , мин void AUTHsend () { 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); }а зачем переводить всё в байты? я про excel. (или вы учебное пособие делаете?) Вам же дали функцию, она сама всё сделает.
Для интереса.
//Параметры MQTT const char MQTT_Protocol_Name[] = "MQIsdp"; const char MQTT_Device_Name[] = "SIM800L"; const char MQTT_User_Name[] = "Irinka"; const char MQTT_Password[] = "qwerty"; const byte MQTT_ver= 3; const byte MQTT_Keep_Alive= 60; const byte MQTT_MSB=0x00; const String MQTT_Server = "m23.cloudmqtt.com"; const String MQTT_Port = "10077"; //Параметры MQTT void MQTT_CONNECT_Packet(){ byte Size_MQTT_Protocol_Name=strlen(MQTT_Protocol_Name); byte Size_MQTT_Device_Name=strlen(MQTT_Device_Name); byte Size_MQTT_User_Name=strlen(MQTT_User_Name); byte Size_MQTT_Password=strlen(MQTT_Password); byte Size_MQTT_CONNECT_Packet=12+Size_MQTT_Protocol_Name+Size_MQTT_Device_Name+Size_MQTT_User_Name+Size_MQTT_Password; DEBUG_PRINTLN(Size_MQTT_CONNECT_Packet); SIM800.write((byte)0x10);//Fixed header SIM800.write((byte)Size_MQTT_CONNECT_Packet);//Remaining Length SIM800.write((byte)MQTT_MSB);//Length MSB SIM800.write((byte)Size_MQTT_Protocol_Name);//Length LSB //Name protokol for (byte i = 0; i<Size_MQTT_Protocol_Name; i++){ SIM800.write((byte)MQTT_Protocol_Name[i]); } //Name protokol SIM800.write((byte)MQTT_ver);//Version SIM800.write((byte)0xC6);//Connect Flags SIM800.write((byte)MQTT_MSB);//Keep Alive MSB SIM800.write((byte)MQTT_Keep_Alive);//Keep Alive LSB SIM800.write((byte)MQTT_MSB);//Device MSB SIM800.write((byte)Size_MQTT_Device_Name);//Device LSB //Device_Name for (byte i = 0; i<Size_MQTT_Device_Name; i++){ SIM800.write((byte)MQTT_Device_Name[i]); } //Device_Name SIM800.write((byte)MQTT_MSB);//User MSB SIM800.write((byte)Size_MQTT_User_Name);//User LSB //User_Name for (byte i = 0; i<Size_MQTT_User_Name; i++){ SIM800.write((byte)MQTT_User_Name[i]); } //User_Name SIM800.write((byte)MQTT_MSB);//Password MSB SIM800.write((byte)Size_MQTT_Password);//Password LSB //Password for (byte i = 0; i<Size_MQTT_Password; i++){ SIM800.write((byte)MQTT_Password[i]); } //Password }//END void MQTT_CONNECT_Packet(){MaksVV
а разве не побайтно нужно отправлять текст?
const char PROTOCOLIUS[] = "MQIsdp";
SIM800.write (PROTOCOLIUS);
28//Name protokol29for(bytei = 0; i<Size_MQTT_Protocol_Name; i++){30SIM800.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 посту(е).
А попробуйте с реальным сервером ;) и там по логам будет видно корректно или нет.
Это конечно же, попробую, но для начала надо разобраться с протоколом отправки? точнее как отправлять
byte sendConnectPacket(byte getSize) {а не
void sendConnectPacket(byte getSize) {Я запуталась
//Параметры MQTT const char MQTT_Protocol_Name[] = "MQIsdp"; const char MQTT_Device_Name[] = "SIM800L"; const char MQTT_User_Name[] = "Irinka"; const char MQTT_Password[] = "qwerty"; const byte MQTT_ver= 3; const byte MQTT_Keep_Alive= 60; const byte MQTT_MSB=0x00; const String MQTT_Server = "m23.cloudmqtt.com"; const String MQTT_Port = "10077"; //Параметры MQTT void MQTT_Connect_Packet(){ byte Size_MQTT_Protocol_Name=strlen(MQTT_Protocol_Name); byte Size_MQTT_Device_Name=strlen(MQTT_Device_Name); byte Size_MQTT_User_Name=strlen(MQTT_User_Name); byte Size_MQTT_Password=strlen(MQTT_Password); byte Size_MQTT_CONNECT_Packet=12+Size_MQTT_Protocol_Name+Size_MQTT_Device_Name+Size_MQTT_User_Name+Size_MQTT_Password; DEBUG_PRINTLN(Size_MQTT_CONNECT_Packet); SIM800.write(0x10);//Fixed header SIM800.write(Size_MQTT_CONNECT_Packet);//Remaining Length SIM800.write(MQTT_MSB);//Length MSB SIM800.write(Size_MQTT_Protocol_Name);//Length LSB SIM800.write(MQTT_Protocol_Name);//Name protokol SIM800.write(MQTT_ver);//Version SIM800.write(0xC6);//Connect Flags SIM800.write(MQTT_MSB);//Keep Alive MSB SIM800.write(MQTT_Keep_Alive);//Keep Alive LSB SIM800.write(MQTT_MSB);//Device MSB SIM800.write(Size_MQTT_Device_Name);//Device LSB SIM800.write(MQTT_Device_Name);//Device_Name SIM800.write(MQTT_MSB);//User MSB SIM800.write(Size_MQTT_User_Name);//User LSB SIM800.write(MQTT_User_Name);//User_Name SIM800.write(MQTT_MSB);//Password MSB SIM800.write(Size_MQTT_Password);//Password LSB SIM800.write(MQTT_Password); //Password }//END void MQTT_Connect_Packet(){Скажите как сделать мой скетч правильно и я пошла соединяться с сервером XDDD (готовить купаты и макароны)
byte sendConnectPacket(byte getSize) {а не
void sendConnectPacket(byte getSize) {Я запуталась
Если getSize = high то функция только возвращает размер пакета, но не отправляет его, т к мне необходимо было знать размер заранее.
ЗЫ. А мне нравиться метод научного тыка - в экспериментах рождается истина.
//Параметры MQTT const char MQTT_Protocol_Name[] = "MQIsdp"; const char MQTT_Device_Name[] = "SIM800L"; const char MQTT_User_Name[] = "Irinka"; const char MQTT_Password[] = "qwerty"; const byte MQTT_ver= 3; const byte MQTT_Keep_Alive= 60; const byte MQTT_MSB=0x00; const String MQTT_Server = "m23.cloudmqtt.com"; const String MQTT_Port = "10077"; //Параметры MQTT void MQTT_Connect_Packet(){ byte Size_MQTT_Protocol_Name=strlen(MQTT_Protocol_Name); byte Size_MQTT_Device_Name=strlen(MQTT_Device_Name); byte Size_MQTT_User_Name=strlen(MQTT_User_Name); byte Size_MQTT_Password=strlen(MQTT_Password); byte Size_MQTT_CONNECT_Packet=12+Size_MQTT_Protocol_Name+Size_MQTT_Device_Name+Size_MQTT_User_Name+Size_MQTT_Password; DEBUG_PRINTLN(Size_MQTT_CONNECT_Packet); SIM800.write(0x10);//Fixed header SIM800.write(Size_MQTT_CONNECT_Packet);//Remaining Length SIM800.write(MQTT_MSB);//Length MSB SIM800.write(Size_MQTT_Protocol_Name);//Length LSB SIM800.write(MQTT_Protocol_Name);//Name protokol SIM800.write(MQTT_ver);//Version SIM800.write(0xC6);//Connect Flags SIM800.write(MQTT_MSB);//Keep Alive MSB SIM800.write(MQTT_Keep_Alive);//Keep Alive LSB SIM800.write(MQTT_MSB);//Device MSB SIM800.write(Size_MQTT_Device_Name);//Device LSB SIM800.write(MQTT_Device_Name);//Device_Name SIM800.write(MQTT_MSB);//User MSB SIM800.write(Size_MQTT_User_Name);//User LSB SIM800.write(MQTT_User_Name);//User_Name SIM800.write(MQTT_MSB);//Password MSB SIM800.write(Size_MQTT_Password);//Password LSB SIM800.write(MQTT_Password); //Password }//END void MQTT_Connect_Packet(){Скажите как сделать мой скетч правильно и я пошла соединяться с сервером XDDD (готовить купаты и макароны)
Строки 28 38 41 вы отправляете не строку, а только один байт, в цикле по строке пройдитесь и побайтно отправляйте.
54for(bytei = 0; i<Size_MQTT_Password; i++){55SIM800.write((byte)MQTT_Password[i]);56}Сделать как и было, спасибо, разберусь с подключением к интернету,отпишусь.
Забыла про байт окончания передачи
1A- байт окончания передачи пакетаЗабыла про байт окончания передачи
1A- байт окончания передачи пакетаэто где написано?
а....ну да, я немного по другому шлю
http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-411540
Для повышения образованности и дальнейших "экспериментов"
Вот так можно будет отправлять байт флага, вместо SIM800.write(0xC6);//Connect Flags
И уж сразу еще вопрос, я же могу хранить эти переменные во флеш памяти?
Можно все, вопрос зачем, памяти не хватает или что? 10 байт вас не спасут,а лишнее написание кода добавится.
const char MQTT_Protocol_Name[] = "MQIsdp"; void setup() { Serial.begin (19200); Serial.write(MQTT_Protocol_Name); } void loop() {}а зачем переводить всё в байты? я про excel. (или вы учебное пособие делаете?) Вам же дали функцию, она сама всё сделает.
Для интереса.
..."какая у людей интересная жизнь"... Полад Бюльбуль-Оглы
const char MQTT_Protocol_Name[] = "MQIsdp"; void setup() { Serial.begin (19200); Serial.write(MQTT_Protocol_Name); } void loop() {}в С слаб, может и не прав, спасибо, попробую.
Я в С ещё слабее вашего, однако действовал методом научного тыка. Действительно помогает! Так сказать стараюсь сразу проверять на практике.
Вот что ответил сервер
полный скетч покажите
Тестовый скетч
#include <SoftwareSerial.h> SoftwareSerial SIM800(6,7); //Пины Nano #define P0 (1 << 0) #define P1 (1 << 1) #define P2 (1 << 2) #define P3 (1 << 3) #define P4 (1 << 4) #define P5 (1 << 5) #define P6 (1 << 6) #define P7 (1 << 7) #define RESETSIM_OUTPUT (DDRB |= P0) #define RESETSIM_HIGH (PORTB |= P0) #define RESETSIM_LOW (PORTB &= ~P0) //Отладка #define DEBUG #ifdef DEBUG #define SERIAL_BEGIN Serial.begin(19200) #define DEBUG_PRINT(x) Serial.print (x) #define DEBUG_PRINTLN(x) Serial.println (x) #else #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) #define SERIAL_BEGIN #endif //Отладка //Параметры MQTT const char MQTT_Protocol_Name[] = "MQIsdp"; const char MQTT_Device_Name[] = "SIM800L"; const char MQTT_User_Name[] = "123456"; const char MQTT_Password[] = "1223456"; const byte MQTT_ver= 3; const byte MQTT_Keep_Alive= 60; const byte MQTT_MSB=0x00; const String MQTT_Server = "m10.cloudmqtt.com"; const String MQTT_Port = "10077"; 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 не используется //Параметры MQTT //Нужные АТ команды const String AT_komandu[] ={ "AT",//Проверка связи 0 "ATE1", "AT+CCALR?",//Проверка сети 1 "AT+CLIP=1",//"Ustanovlen AON 2 "AT+CMGF=1",//"Text mode 3 "AT+CMGDA=\"DEL ALL\"",//Sms udaleny 4 "ATH",//Sbros vhodiashchego 5 "AT+SAPBR=3,1, \"Contype\",\"GPRS\"",// 6 "AT+SAPBR=3,1, \"APN\",\"internet.tele2.ru\"",// 7 "AT+SAPBR=3,1,\"USER\",\"\"",// 8 "AT+SAPBR=3,1,\"PWD\",\"\"",// 9 "AT+SAPBR=1,1",//установка GPRS связи 10 "AT+CSTT=\"www\",\"\",\"\"",//11 "AT+CIICR",//12 "AT+CIFSR",//13 "AT+CIPSTART=\"TCP\",\"m10.cloudmqtt.com\",\"11481\"",//14 "AT+CIPSEND",//15 "AT+SAPBR=2,1",//полученный IP адрес 11 "AT+SAPBR=4,1", //текущие настройки соединения 12 "AT+SAPBR=0,1", //разорвать GPRS соединени 13 }; unsigned long TimePoiska; //AT+SAPBR=3,1, "Contype","GPRS" //AT+SAPBR=3,1, "APN","internet.tele2.ru" //GPRS AT command int i = 0; //Пакет соединения void MQTT_CONNECT_Packet(){ byte Size_MQTT_Protocol_Name=strlen(MQTT_Protocol_Name); byte Size_MQTT_Device_Name=strlen(MQTT_Device_Name); byte Size_MQTT_User_Name=strlen(MQTT_User_Name); byte Size_MQTT_Password=strlen(MQTT_Password); byte Size_MQTT_CONNECT_Packet=12+Size_MQTT_Protocol_Name+Size_MQTT_Device_Name+Size_MQTT_User_Name+Size_MQTT_Password; SIM800.write(0x10);//Fixed header SIM800.write(Size_MQTT_CONNECT_Packet);//Remaining Length SIM800.write(MQTT_MSB);//Length MSB SIM800.write(Size_MQTT_Protocol_Name);//Length LSB for (byte i = 0; i<Size_MQTT_Protocol_Name; i++){SIM800.write(MQTT_Protocol_Name[i]);}//Name protokol SIM800.write(MQTT_ver);//Version SIM800.write(0xC6);//Connect Flags SIM800.write(MQTT_MSB);//Keep Alive MSB SIM800.write(MQTT_Keep_Alive);//Keep Alive LSB SIM800.write(MQTT_MSB);//Device MSB SIM800.write(Size_MQTT_Device_Name);//Device LSB for (byte i = 0; i<Size_MQTT_Device_Name; i++){SIM800.write(MQTT_Device_Name[i]);}//Device_Name SIM800.write(MQTT_MSB);//User MSB SIM800.write(Size_MQTT_User_Name);//User LSB for (byte i = 0; i<Size_MQTT_User_Name; i++){SIM800.write(MQTT_User_Name[i]);}//User_Name SIM800.write(MQTT_MSB);//Password MSB SIM800.write(Size_MQTT_Password);//Password LSB for (byte i = 0; i<Size_MQTT_Password; i++){SIM800.write(MQTT_Password[i]);}//Password SIM800.write(0x1A);//End flag }//END void MQTT_CONNECT_Packet() void setup(){ SERIAL_BEGIN; SIM800.begin(38400); RESETSIM_OUTPUT; RESETSIM_LOW; delay(1000); RESETSIM_HIGH; delay(1000); DEBUG_PRINTLN("Onload MQTT"); delay(5000); TimePoiska=millis(); } void loop(){ if (SIM800.available()){ Serial.write(SIM800.read()); } /*if (Serial.available()) { SIM800.write(Serial.read()); }*/ if (millis()-TimePoiska>=2000){ TimePoiska=millis(); i++; if (i>16){ i=0; MQTT_CONNECT_Packet(); } DEBUG_PRINTLN("Komanda: "+AT_komandu[i]); SIM800.println(AT_komandu[i]); } }Мне кажется Вам реально заняться нечем в плохом смысле. Вам скинули несколько готовых функций, пользуйтесь, не нужно ничего придумывать. Так же ссылку на самый подробный солюшн по MQTT, даже с примерами, изучайте. Всё равно не понятно? - Сопоставьте первое со вторым.
Стоп, всё сконнектилось, ошибка была из-за повторной отправки
А чуть позже на сервере
А чуть позже на сервере
и чудненько!!!
А чуть позже на сервере
и чудненько!!!
В каком смысле?
Сервер пишет что подключение есть.
буду отправлять данные
на примерно таком же скетче я тоже познавал 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(); } } }А чуть позже на сервере
и чудненько!!!
В каком смысле?
В прямом, сервер подождал 30 секунд данные и отключился.
Я ж выше давал ссылку на описание и пример команд и там чёрным по русски было написано что в пакете connect указывать время соединения, будьте добры или данные отправлять каждые 20 секунд или переподключаться.