Arduino UNO +sim800l+mqtt(blynk)
- Войдите на сайт для отправки комментариев
Пнд, 10/07/2017 - 13:29
Здравствуйте! Помогите,пожалуйста! Пыталась сделать управление ардуиной через mqtt dashboard, брала готовый код, в итоге подключается к gprs, а к mqtt подключиться не может! Решила попробовать приложение blynk, взяла самый простой код из примеров,чтобы хотя бы просто подключиться! И опять....не может подключиться! Sim800l мигает редко,т.е.сеть поймал, через телефон в инет выходит! Помогите!
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space #define TINY_GSM_MODEM_SIM800 #include <TinyGsmClient.h> #include <BlynkSimpleSIM800.h> const char auth[] = ""; // Your GPRS credentials // Leave empty, if missing user or pass const char apn[] = "internet.mts.ru"; const char user[] = "mts"; const char pass[] = "mts"; #include <SoftwareSerial.h> SoftwareSerial SerialAT(2, 3); // RX, TX TinyGsm modem(SerialAT); void setup() { // Set console baud rate Serial.begin(115200); delay(10); // Set GSM module baud rate SerialAT.begin(115200); delay(3000); // Restart takes quite some time // To skip it, call init() instead of restart() Serial.println("Initializing modem..."); modem.restart(); Blynk.begin(auth, modem, apn, user, pass); } void loop() { Blynk.run(); } в сериал выходит только [13224] Modem init... [23440] Cannot initПытаюсь реализовать данный пример.
С передачей данных датчика. Выяснелось, что надо передовать пореже. Раз в 5 минут. Иначи теряется связь с Blynk.
Но всеравно через 4 часа теряет связь.
Здравствуйте. Начала изучать MQTT. Возникло много вопросов.
https://github.com/martinhol221/SIM800L_MQTT/wiki/Управление-реле-по-протоколу-MQTT-используя-Arduino-и-Sim800L.
Прочитала эту сатью.
Эти команды работают.
Далее не понимаю как осуществить авторизацию и передачу данных.
После команды AT+CIPSEND получаю приглашение ">"
далее нужно авторизоваться и ввести топик текст и т п
кусок кода из указанной мною статьи
Слово CITROEN в ASCII
67 73 84 82 79 69 78
Слово drive2ru в ASCII
100 114 105 118 101 50 114 117
Откуда чего берется, я не поняла
Слово CITROEN в ASCII
67 73 84 82 79 69 78
переведите в HEX и получите как в образце 43 49.....
Этот перевод в HEX обязателен? или можно передавать текст латиницей?
Откуда чего берется, я не поняла
Из описания протокола MQTT, вестимо. Вот, читайте первоисточник: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
Вот немного на русском: https://ipc2u.ru/articles/prostye-resheniya/chto-takoe-mqtt/ - но лучше читать первоисточник, конечно.
10 2D 00 06 4D 51 49 73 64 70 03 C2 00 3C 00 07 43 49 54 52 4F 45 4E 00 08 64 72 69 76 65 32 72 75 00 0C 6D 61 72 74 69 6E 68 6F 6C 32 32 31
Это пакет авторизации
Декодировала, получила следующее:
-MQIsdpВ<CITROENdrive2rumartinhol221
Т.е. чтобы авторизоваться мне нужно:
AT+CIPSEND
>
-MQIsdpВ<CITROENdrive2rumartinhol221 //как правильно записать эту строку и отправить?
Правильно - почитать спецификацию MQTT, формировать пакет байт и просто скармливать его по AT+CIPSEND. MQTT - не текстовый протокол, там пакеты байт.
Не получается отправить данные.
#include <SoftwareSerial.h> SoftwareSerial SIM800(7,6); String _response = ""; const char MQTT_user[10] = "ixboztkc"; //User // 69 78 62 6f 7a 74 6b 63 0a 0a const char MQTT_pass[15] = "kTBxIJNQLdvU"; //Password // 6b 54 42 78 49 4a 4e 51 4c 64 76 55 const char MQTT_CID[15] = "Irina"; // 49 72 69 6e 61 String MQTT_SERVER = "m10.cloudmqtt.com"; //Server String PORT = "11481"; void setup() { Serial.begin(9600); SIM800.begin(9600); Serial.println("Start!"); _response = sendATCommand("AT", true); _response = sendATCommand("AT+SAPBR=0,1", true); _response = sendATCommand("AT+SAPBR=3,1, \"Contype\",\"GPRS\"", true); _response = sendATCommand("AT+SAPBR=3,1, \"APN\",\"internet\"", true); _response = sendATCommand("AT+SAPBR=1,1", true); _response = sendATCommand("AT+SAPBR=2,1", true); _response = sendATCommand("AT+CIPSTART=\"TCP\",\"m10.cloudmqtt.com\",\"11481\"", true); delay(1000); _response = sendATCommand("AT+CIPSEND", true); delay(1000); _response = sendATCommand("10 2D 00 06 4D 51 49 73 64 70 03 C2 00 3C 00 05 49 72 69 6e 61 00 0A 69 78 62 6f 7a 74 6b 63 0a 0a 00 0C 6b 54 42 78 49 4a 4e 51 4c 64 76 55", true); _response = sendATCommand("30 0D 00 06 43 35 2F 64 73 30 31 32 2E 33 30" + (String)((char)26), true); } String sendATCommand(String cmd, bool waiting) { String _resp = ""; Serial.println(cmd); SIM800.println(cmd); if (waiting) { _resp = waitResponse(); if (_resp.startsWith(cmd)) { _resp = _resp.substring(_resp.indexOf("\r", cmd.length()) + 2); } Serial.println(_resp); } return _resp; } String waitResponse() { String _resp = ""; long _timeout = millis() + 5000; while (!SIM800.available() && millis() < _timeout) {}; if (SIM800.available()) { _resp = SIM800.readString(); } else { Serial.println("Timeout..."); } return _resp; } void loop() { if (SIM800.available()) { _response = waitResponse(); _response.trim(); Serial.println(_response); } }В мониторе порта получаю следующее:
Правильно отправлять наверное одной строкой:
_response = sendATCommand("10 2D 00 06 4D 51 49 73 64 70 03 C2 00 3C 00 05 49 72 69 6e 61 00 0A 69 78 62 6f 7a 74 6b 63 0a 0a 00 0C 6b 54 42 78 49 4a 4e 51 4c 64 76 55 30 0D 00 06 43 35 2F 64 73 30 31 32 2E 33 30" + (String)((char)26), true);Но все равно не работает
Авторизация и отправка в топик выглядит вот так:
mosquitto_pub -h m10.cloudmqtt.com -p 11481 -u ixboztkc -P kTBxIJNQLdvU -t C5 -m 300
_response = sendATCommand("6d 6f 73 71 75 69 74 74 6f 5f 70 75 62 20 2d 68 20 6d 31 30 2e 63 6c 6f 75 64 6d 71 74 74 2e 63 6f 6d 20 2d 70 20 31 31 34 38 31 20 2d 75 20 69 78 62 6f 7a 74 6b 63 20 2d 50 20 6b 54 42 78 49 4a 4e 51 4c 64 76 55 20 2d 74 20 43 35 20 2d 6d 20 33 30 30" + (String)((char)26), true);В ответ SEND OK
Но в топике запись не изменилась на "300"
Блин. MQTT - НЕ ТЕКСТОВЫЙ ПРОТОКОЛ, надо отправлять НЕ СТРОКУ, а НАБОР БАЙТ.
Так понятней?
Подскажите, как отправить этот набор байт, пожалуйста.
Irinka , сделайте массив байт с теми байтами какие вам нужны,
byte mss[] = {0x6D, 0x6f, 0x73 и т.д.
потом цикл по этому массиву отправляете все эти байты командой SIM800.write(x)
в конце массива можно сразу добавить байт 26 окончания отправки
и вы уже не первый проект я смотрю делаете на sim800, может быть уже набрались опыта - пора бы уходить от шаблонных копипастных функций sendATCommand и написать самим логику - гораздо проще все будет программировать.
Спасибо за помощь.
Где то я опять накосячила)))
Сделала массив
byte mss[] = {0x6d,0x6f,0x73,0x71,0x75,0x69,0x74,0x74,0x6f,0x5f,0x70,0x75,0x62, 0x20,0x2d,0x68,0x20,0x6d,0x31,0x30,0x2e,0x63,0x6c,0x6f,0x75, 0x64,0x6d,0x71,0x74,0x74,0x2e,0x63,0x6f,0x6d,0x20,0x2d,0x70,0x20,0x31,0x31,0x34 ,0x38,0x31,0x20,0x2d,0x75,0x20,0x69,0x78,0x62,0x6f,0x7a, 0x74,0x6b,0x63,0x20,0x2d,0x50,0x20,0x6b,0x54,0x42,0x78,0x49,0x4a,0x4e,0x51,0x4c, 0x64,0x76,0x55,0x20,0x2d,0x74,0x20,0x43,0x35,0x20,0x2d, 0x6d,0x20,0x33,0x30,0x30,0x1a};Отправляю
_response = sendATCommand("AT+CIPSEND", true); delay(1000); for (int i=0; i < sizeof(mss); i++){ SIM800.write(mss[i]); }В ответ:
и вы уже не первый проект я смотрю делаете на sim800, может быть уже набрались опыта - пора бы уходить от шаблонных копипастных функций sendATCommand и написать самим логику - гораздо проще все будет программировать.
Для моих столь маленьких проектов хватает, а так то да, буду совершенствоваться.
Так может беда в сервере MQTT? Отправка то произошла, нет возможности на стороне сервера посмотреть дошло или нет.
И кстати на sim800 вы закрываете сессию отправки? Может в этом причина....
Не нахожу информации по поводу закрытия сессии
"AT+CIPCLOSE" или AT+CIPSHUT ?
Не нахожу информации по поводу закрытия сессии
да, это к http сессии относиться, не ваш случай, команда HTTPTERM
вот из хорошей статьи вырезка (сам не пробовал) - судя по всему все у вас хорошо - разбирайтесь с сервером MQTT
Это я тоже читала. Вот и думаю, что отправка происходит, но почему то не доходит до топика
https://www.youtube.com/watch?v=dcpMa2UwEeA
Наверно я неправильно произвожу авторизацию
Иринка, добрый совет: решение проблем методом ненаучного тыка - путь в никуда. Вы так будете тыкаться до посинения. Единственно верный путь - это ПОНЯТЬ, как формируется пакет MQTT, и научиться формировать эти самые пакеты. Там несложно, в спецификации даже примеры алгоритмов есть. Можете также взять исходники PubSubClient и посмотреть - как формируется пакет MQTT там, но, если честно - там не совсем наглядно.
Короче, написать формирование пакета - не так сложно. Зато потом - вам будет пофиг, какой логин/пароль, какое имя топика, какой тип топика, какой payload - имея под рукой набор функций, вы всегда будете уверены, что пакет сформирован правильно. Иначе - так и будете не понимать, почему и что.
тут рядом недавно спорили спецы кто реально работал с MQTT, ждите их.
но вообще конечно надо смотреть логи сервера, но я так понимаю доступа у вас к нему нет.
Кстати, Энди прав. Нужно посмотреть, что прилетает на москита того же. tcpdump-ом или типа того. А если вы шлете на какой-нить чужой сервер, то там можно чего угодно кроме авторизации ожидать.
Исходя из этого сделала в экселе таблицу
Верно?
Ура ура, разобралась.
Неверно делала и авторизацию, и отправку данных.
Через эксель всё стало ясно.
Иринка, поставьте себе на локальную машину mosquitto - и шлите на него: там можно в консоли смотреть, что происходит. Это будет сильно лучше на первоначальном этапе.
Исходя из этого сделала в экселе таблицу
Верно?
Там, где вы пишете "константа" - это ошибка, почему - подробно описано в документации MQTT. Там не константа, там могут быть данные.
Спасибо.
Теперь еще вопрос, как мне число с запятой перевести в HEX?
Как вообще переводить текст в HEX и обратно.
вопрос не корректный, я конечно скину ссылку
https://ru.wikipedia.org/wiki/%D0%A8%D0%B5%D1%81%D1%82%D0%BD%D0%B0%D0%B4...
но я думаю вы и так знаете что такое шестнадцатиричная система счисления.
любой число в любом формате это тупо набор цифр.
понятие "перевод в HEX" актуально только отображения человеку,
а вопрос "как мне число с запятой перевести в HEX?" непонятен в принципе :(
в каком формате число? в каком формате оно нужно серверу? текст? float?
Как вообще переводить текст в HEX и обратно.
руками, например 2 HEX символа в байт:
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; }Имею:
float temp = 12,63;
С процедурой авторизации понятно, там ничего меняться не будет.
Нужно float temp gtthdtcnb в формат для отправки 31 32 2C 36 33
берете целую часть, разбиваете по разрядам (делением на 100, потом хвост на 10, потом хвост от 10 и т.д.), к каждому разряду прибавляете 0x30 и отправляете, потом отправляете точку 0x2C, потом аналогично дробную часть.
типа так:
byte addTextWord(char *text, byte firstpos, word inWord) { word cw = inWord % 10000; text[firstpos] = ((cw / 1000) + '0'); ++firstpos; cw = cw % 1000; text[firstpos] = ((cw / 100) + '0'); ++firstpos; cw = cw % 100; text[firstpos] = ((cw / 10) + '0'); ++firstpos; cw = cw % 10; text[firstpos] = (cw + '0'); ++firstpos; return firstpos; }С отправкой все более менее понятно.
А вот читать из топика не получается.
82 0E 00 01 00 09 43 35 2F 63 6F 6D 61 6E 64 0082маркер пакета подписки0E- общая длинна всего пакета авторизации 0E (HEX) = 14 (DEC) байт, от следующего байта и до конца00 01 00- постоянно09- длинна топика 09 (HEX) = 9 (DEC) байт43 35 2F 63 6F 6D 61 6E 64- имя топика на которое подписывается устройство, в ASCIIC5/comand00- постоянноСоздала топик C5/comand и записала в него значение 555
byte mss[] = { 0x10,0x2D,0x00,0x06,0x4D,0x51,0x49,0x73,0x64,0x70,0x03,0xC2,0x00,0x3C,0x00,0x07,0x49, 0x72,0x69,0x6E,0x6B,0x61,0x61,0x00,0x08,0x69,0x78,0x62,0x6F,0x7A,0x74,0x6B,0x63,0x00, 0x0C,0x6B,0x54,0x42,0x78,0x49,0x4A,0x4E,0x51,0x4C,0x64,0x76,0x55, 0x82,0x0E,0x00,0x01,0x00,0x09,0x43,0x35,0x2F,0x63,0x6F,0x6D,0x61,0x6E,0x64,0x00,0x1a};В итоге получаю:
Алгоритм получения данных из топика, подписка, мне не понятна(
Так есть же команда получения запроса есть ли у сервера ответ, размер ответа, ну и получения ответа - нет?
Опять же если хочется что бы модем сразу в консоль выдавал ответы от сервера - его надо перевести в этот режим.
Ну и главный вопрос :) - а сервер вообще что нибудь отвечает?
Когда отсылаю сообщения, в вебинтерфейсе эти сообщения появляются.
Как перевести можем в этот режим?
Как перевести можем в этот режим?
Не знаю, не помню, не использовал, просто читал что модем не все и не всегда в консоль выдаёт.
https://elementztechblog.wordpress.com/2016/07/18/arduino-mqtt-library-f...
Прошу прощения, изменила своё сообщение (немного накосячила)))
Што-то я не понимаю - чего делает mosquitto_sub в мониторе ардуино иде?
Вот что в мониторе.
Топик StatusRel содержит значение 10
Запрос на чтение из топика выглядит вот так
Изучая MQTT на NodeMCU подсмотрела следующее
-- publish a message with data = hello, QoS = 0, retain = 0 client:publish("/topic", "hello", 0, 0, function(client) print("sent") end)Если параметр retain = 0
то информация в топике не сохраняется, а если 1, то сохраняется и соответственно читается.
Получается, скорее всего, я публикую сообщения в топик без сохранения.
Как добавить маркер сохранения при публикации в топик?
Добрый вечер.
int led = 13; unsigned int Counter = 0; unsigned long datalength,CheckSum,RLength; unsigned short topiclength; unsigned char topic[30]; char str[250]; unsigned char encodedByte; int X; unsigned short MQTTProtocolNameLength; unsigned short MQTTClientIDLength; unsigned short MQTTUsernameLength; unsigned short MQTTPasswordLength; const char MQTTHost[30] = "m10.cloudmqtt.com"; const char MQTTPort[10] = "17434"; const char MQTTClientID[20] = "ABCDEF"; const char MQTTTopic[30] = "valetron"; const char MQTTProtocolName[10] = "MQIsdp"; const char MQTTLVL = 0x03; const char MQTTFlags = 0xC2; const unsigned int MQTTKeepAlive = 60; const char MQTTUsername[30] = "dxxkgkpp"; const char MQTTPassword[35] = "qAUZBdaSIULx"; const char MQTTQOS = 0x00; const char MQTTPacketID = 0x0001; void setup() {pinMode(led, OUTPUT); Serial.begin(9600); Serial.println("Arduino MQTT Tutorial, Valetron Systems @www.raviyp.com "); delay(3000); } void SendConnectPacket(void) {Serial.print("\r\nAT+CIPSEND\r\n"); delay(3000); Serial.write(0x10); MQTTProtocolNameLength = strlen(MQTTProtocolName); MQTTClientIDLength = strlen(MQTTClientID); MQTTUsernameLength = strlen(MQTTUsername); MQTTPasswordLength = strlen(MQTTPassword); datalength = MQTTProtocolNameLength+2+4+MQTTClientIDLength+2+MQTTUsernameLength+2+MQTTPasswordLength+2; X=datalength; do {encodedByte = X%128; X = X/128; if ( X > 0 ) { encodedByte |= 128; } Serial.write(encodedByte); } while ( X > 0 ); Serial.write(MQTTProtocolNameLength >> 8); Serial.write(MQTTProtocolNameLength & 0xFF); Serial.print(MQTTProtocolName); Serial.write(MQTTLVL); // LVL Serial.write(MQTTFlags); // Flags Serial.write(MQTTKeepAlive >> 8); Serial.write(MQTTKeepAlive & 0xFF); Serial.write(MQTTClientIDLength >> 8); Serial.write(MQTTClientIDLength & 0xFF); Serial.print(MQTTClientID); Serial.write(MQTTUsernameLength >> 8); Serial.write(MQTTUsernameLength & 0xFF); Serial.print(MQTTUsername); Serial.write(MQTTPasswordLength >> 8); Serial.write(MQTTPasswordLength & 0xFF); Serial.print(MQTTPassword); Serial.write(0x1A); } void SendPublishPacket(void) {Serial.print("\r\nAT+CIPSEND\r\n"); delay(3000); memset(str,0,250); topiclength = sprintf((char*)topic,MQTTTopic); datalength = sprintf((char*)str,"%s%u",topic,Counter); delay(1000); Serial.write(0x30); X=datalength+2; do {encodedByte = X%128; X = X/128; if ( X > 0 ) { encodedByte |= 128; } Serial.write(encodedByte); } while ( X > 0 ); Serial.write(topiclength >> 8); Serial.write(topiclength & 0xFF); Serial.print(str); Serial.write(0x1A); } void SendSubscribePacket(void) {Serial.print("\r\nAT+CIPSEND\r\n"); delay(3000); memset(str,0,250); topiclength = strlen(MQTTTopic); datalength = 2+2+topiclength+1; delay(1000); Serial.write(0x82); X=datalength; do {encodedByte = X%128; X = X/128; if ( X > 0 ) { encodedByte |= 128; } Serial.write(encodedByte); } while ( X > 0 ); Serial.write(MQTTPacketID >> 8); Serial.write(MQTTPacketID & 0xFF); Serial.write(topiclength >> 8); Serial.write(topiclength & 0xFF); Serial.print(MQTTTopic); Serial.write(MQTTQOS); Serial.write(0x1A); } void loop() {Serial.print("AT+CSTT=\"www\",\"\",\"\"\r\n"); delay(1000); Serial.print("AT+CIPMODE=0\r\n"); delay(1000); Serial.print("AT+CIICR\r\n"); delay(5000); Serial.print("AT+CIPSTART=\"TCP\",\"m10.cloudmqtt.com\",\"17434\"\r\n"); delay(4000); SendConnectPacket(); delay(5000); SendSubscribePacket(); while(1){ if(Serial.available()>0){ str[0] = Serial.read(); Serial.write(str[0]); if(str[0] == '1') digitalWrite(led, HIGH); if(str[0] == '0') digitalWrite(led, LOW); }}}do {encodedByte = X%128; X = X/128; if ( X > 0 ) { encodedByte |= 128; } Serial.write(encodedByte); } while ( X > 0 ); Serial.write(MQTTProtocolNameLength >> 8); Serial.write(MQTTProtocolNameLength & 0xFF); Serial.print(MQTTProtocolName); Serial.write(MQTTLVL); // LVL Serial.write(MQTTFlags); // Flags Serial.write(MQTTKeepAlive >> 8); Serial.write(MQTTKeepAlive & 0xFF); Serial.write(MQTTClientIDLength >> 8); Serial.write(MQTTClientIDLength & 0xFF); Serial.print(MQTTClientID); Serial.write(MQTTUsernameLength >> 8); Serial.write(MQTTUsernameLength & 0xFF); Serial.print(MQTTUsername); Serial.write(MQTTPasswordLength >> 8); Serial.write(MQTTPasswordLength & 0xFF); Serial.print(MQTTPassword); Serial.write(0x1A); }Объясните пожалуйста данный кусок кода