Arduino SIM800 MQTT Cloudmqtt.com выбрасывает с сервера

MaksVV
Offline
Зарегистрирован: 06.08.2015

Помогите разобраться кто в теме. Не могу разобраться нормально как правильно должен работать протокол. Плиз киньте ссылкой на нормальную статью.

Проблема у меня такая. Выбрасывает с брокера через примерно минуту бездействия (получаю от SIM800 CLOSED). 

Последовательность действий была такая. Зарегался на брокере cloudmqtt.com получил личные данные. Пока пробую коннектиться без ардуино - управляя СИМ800 через терминальную программу. Посылаю такие команды 

AT+SAPBR=3,1, "Contype","GPRS" - настройка параметров соединения, ответ OK

AT+SAPBR=3,1, "APN","internet.mts.by" - установка точки доступа, ответ OK

AT+SAPBR=1,1 - установка GPRS соединения, ответ OK

AT+CIPSTART="TCP","бла бла.cloudmqtt.com","бла бла" - установка связи с сервером, ответ CONNECT OK

далее сначала команду AT+CIPSEND

затем пакет авторизации. После чего пакет подписок. В принципе это всё работает т.к. подписавшись, получаю от брокера топики. И также публикации от сим800 тоже работают - брокер их видит. Но если ничего не делать, в течение одной минуты брокер? разрывает соединение - СИМ800 присылает CLOSED. Так и должно быть или я что то не так делаю? 

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

Сложно судить без скетча, скорее всего вы в пакете connect mqtt указываете минуту, сервер соответственно через минуту и отрубает соединение.

http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-411540

MaksVV
Offline
Зарегистрирован: 06.08.2015

я без ардуино пока пробую, т.е. взаимодействую с СИМ800 через терминал. А что за пакет connect mqtt? это пакет авторизации? 

У меня такой пакет авторизации : 

10 2A 00 06 4D 51 49 73 64 70 03 C2 00 3C 00 04 XX XX XX XX 00 08 XX XX XX XX XX XX XX XX 00 0C XX XX XX XX XX XX XX XX XX XX XX XX 1A

где

10 - маркер начала пакета авторизации

00  это разделитель 

4D 51 49 73 64 70  - это в ascii  протокол MQIsdp

XX это имя устройства, пользователя и пароль 

1А - маркер конца пакета 

где тут указывать время? 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Я так полагаю, почитать официальную документацию по протоколу MQTT - не предлагать, моветон?

MaksVV
Offline
Зарегистрирован: 06.08.2015

DIYMan, прелагать, киньте ссылкой, если на русском. По английски моя плохо понимать. 

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

Придётся учиться

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

Кстати непонятна логика общаться с модемом через терминал, проще написать примитивный скетч который будет тупо через секунду слать все команды.

Подсказка для начала - 229 строка время удержания коннекта

http://arduino.ru/forum/programmirovanie/snova-mqtt-1#comment-404716

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

MaksVV пишет:

DIYMan, прелагать, киньте ссылкой, если на русском. По английски моя плохо понимать. 

http://mqtt.org/ - далее с гуглопереводчиком ;)

MaksVV
Offline
Зарегистрирован: 06.08.2015

Пасиб, почитал. Все получилось. Споткнулся на том , что читал изначально описание mqtt не от первоисточника, а просто пользователя. Он там эти байты времени коннекта обозначил как константа. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

10 2A 00 06 4D 51 49 73 64 70 03 C2  00 3C  00 04 XX XX XX XX 00 08 XX XX XX XX XX XX XX XX 00 0C XX XX XX XX XX XX XX XX XX XX XX XX 1A

жирным байты времени коннекта. 0x3С  это как раз 60 сек. через столько времени и выкидывал брокер. 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

MaksVV пишет:

Пасиб, почитал. Все получилось. Споткнулся на том , что читал изначально описание mqtt не от первоисточника, а просто пользователя. Он там эти байты времени коннекта обозначил как константа. 

Ну вот видите, насколько бывает полезным чтение первоисточника ;) Рад, что всё получилось.

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

Нужно посылать что нибудь в брокер, иначе через полтора таймаута, заданного в фрейме подключения он считает что клиент "скорее мёртв чем жив" ©. Самый здравый вариант "пинговать" его с периодичностью в пределах таймаута (0xC0 0x00):

void ping() {
  gsm.println(F("AT+CIPSEND"));
  if (gsm.find("> ")) gsm.write(0xC0), gsm.write(byte(0x00)), gsm.write(0x1A), gsm.find("SEND OK\r\n");
}

 

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

MaksVV пишет:

 0x3С  это как раз 60 сек. через столько времени и выкидывал брокер. 

Поправочка, если задано 60 сек, выкинет через 90 сек. Брокер даёт ещё половину времени таймаута как бонус на медленное соединение.

MaksVV
Offline
Зарегистрирован: 06.08.2015

пасиб, буду знать. Позвольте спросить ещё один момент.  Сильно ещё не разбирался с этим, но может вы знаете. 

Когда подписался на топик и он приходит из брокера,  СИМ800 не вставляет в конце строки \n\r. Мне бы так проще было парсить строку. Это как то можно настроить на сим800? В самом топике это добавить не могу у отправителя топика (программа MQTT dash)

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

MaksVV пишет:

 СИМ800 не вставляет в конце строки \n\r. 

модем сам по себе ничего не вставляет и это не настраивается.

то что вы видите - это ответ от брокера - с ним и договаривайтесь.

как вариант для облегчения - добавить в отправляемые данные некие спец символы для разграничения данных.

MaksVV
Offline
Зарегистрирован: 06.08.2015

andycat пишет:
то что вы видите - это ответ от брокера - с ним и договаривайтесь.

ну в общем это тоже подразумевалось в вопросе. Можно ли либо на брокере либо в программе MQTT dash добавить эти символы? я к сожалению не нашёл. 

andycat пишет:
как вариант для облегчения - добавить в отправляемые данные некие спец символы для разграничения данных.
Про спец символы так и сделал. добавил $&. 

Но,  например, в MQTT dash в  пиктограмме "диапазон/прогресс" нельзя добавить спец символы, только выбранное число отправляет. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

andycat пишет:
модем сам по себе ничего не вставляет и это не настраивается.

ну это не совсем так. Как раз вы описали АТ команды там в теме "снова MQTT"и я узнал, что можно сделать, чтобы СИМ800  добавлял заголовок +IPD (команда AT+CIPHEAD=1) в принятых строках от сервера. Спасиб за это. 

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

MaksVV пишет:

andycat пишет:
то что вы видите - это ответ от брокера - с ним и договаривайтесь.

ну в общем это тоже подразумевалось в вопросе. Можно ли либо на брокере либо в программе MQTT dash добавить эти символы? я к сожалению не нашёл. 

andycat пишет:
как вариант для облегчения - добавить в отправляемые данные некие спец символы для разграничения данных.
Про спец символы так и сделал. добавил $&. 

Но,  например, в MQTT dash в  пиктограмме "диапазон/прогресс" нельзя добавить спец символы, только выбранное число отправляет. 

написать свою MQTT dash или отправлять все данные в виде текстовой строки

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

MaksVV пишет:

andycat пишет:
модем сам по себе ничего не вставляет и это не настраивается.

ну это не совсем так. Как раз вы описали АТ команды там в теме "снова MQTT"и я узнал, что можно сделать, чтобы СИМ800  добавлял заголовок +IPD (команда AT+CIPHEAD=1) в принятых строках от сервера. Спасиб за это. 

ну можно конечно, только от сервера кроме нужных вам данных топика еще что нибудь может прилететь и если оно прилетит между топиками - сильно собьет ваш разбор ответов.

357 // ответы на подписанные топики MQTT
358 +IPD,13:0AT41/key7Key OFF
359  
360 +IPD,13:0AT41/key5Key ON

 

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

MaksVV пишет:

приходит из брокера,  СИМ800 не вставляет в конце строки \n\r. 

SIM800 вставляет перенос строки только в ответах на АТ - команды. При получении фрейма из брокера он его отдаёт как есть, ибо это никакой не АТ - обмен, а IP - протокольная информация. Поскольку в фрейме вполне может быть и 0x0D и 0x0A и что угодно ещё, то это просто недопустимо. Кстати при передаче фрейма в брокер есть такой нюанс, что байт 0x1A модемом однозначно воспринимается как конец фрейма, и если такой байт встрачается в самой передавайемой информации то всё что дальше просто обрежится и воспримется им как неверная АТ - команда, а уж тем более прийдя до ответа "SEND OK" этот "хвост" может напрочь проглючить и без того глючный SIM800. Сталкивался с таким, как побороть не придумал..

Да и вообще инфу из брокера надо парсить как положено а не по каким то "концам строки", "переносам строки" и т.п. Я например написал функцию для этого, расдупляет в том числе "мультифреймы". Если модем в течении короткого времени получет от брокера несколько фреймов он их запихивает в один и отдаёт "на выход" одной большой кучей.

void ipdhandling(const byte* frame, byte len = 1 ) { //++++++++++++++  PROCESSING DATA FROM BROKER  ++++++++++++++++++
  if (frame == NULL) return;
  for (byte _idx = 0; _idx < len;) {
    if ( (frame[_idx] == 0xD0) && (frame[_idx+1] == 0x00) ) {            // pingresp d0 00
      dbg("ping responce!");
      _idx += 2;
    } else  if ( (frame[_idx] == 0x20) && (frame[_idx+1] == 0x02) ) {    // connak 20 02 00 00
      if (frame[_idx+3] == 0x00) flash.run(700ul), dbg("conn accepted");
      else { dbg("conn refused"); gsm.println(F("AT+CIPSHUT")); return; }
      _idx += 4;
    } else if ((frame[_idx] & ~0x01) == 0x30) {                          // pub recv !!sometime 31 10 00 0c
      char* _tptr = (char*)(frame + _idx + 4);
      byte  _tlen = frame[_idx+3]; 
      char* _pptr = (char*)(frame + _idx + frame[_idx+3] + 4) ;
      byte  _plen = frame[_idx+1] - frame[_idx+3] - 2;
      char  _topic[_tlen+1]; strncpy(_topic, _tptr, _tlen); _topic[_tlen] = '\0';
      char  _payl [_plen+1]; strncpy(_payl,  _pptr, _plen); _payl[_plen] = '\0';
      _idx += frame[_idx+1] + 2;
    } else break; //unexpected header
    //++++++ здесь обрабатываем _topic и _payl как нам вздумается
  } // cycle
}  // ipd func

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

vlad072 пишет:

Кстати при передаче фрейма в брокер есть такой нюанс, что байт 0x1A модемом однозначно воспринимается как конец фрейма, и если такой байт встрачается в самой передавайемой информации то всё что дальше просто обрежится и воспримется им как неверная АТ - команда, а уж тем более прийдя до ответа "SEND OK" этот "хвост" может напрочь проглючить и без того глючный SIM800. Сталкивался с таким, как побороть не придумал..

Читаем раздел 8.2.3 официальной документации по AT-командам, секция Write command, и видим, что там можно указывать длину данных к отсылу. То, что вы описали, справедливо для секции Execution command. Т.е. проблемы - просто нет, есть невнимательное чтение документации.

В зависимости от настройки CIPMUX после установления соединения посылаем либо AT+CIPSEND=ДЛИНА_ДАННЫХ_К_ОТСЫЛУ, либо AT+CIPSEND=НОМЕР_СОЕДИНЕНИЯ,ДЛИНА ДАННЫХ

Потом ждём приглашения (не забывая анализировать возможные ошибки) - и посылаем данные указанной длины. И никакой проблемы с байтом 0x1A - просто нет.

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

DIYMan]</p> <p>[quote=vlad072 пишет:

можно указывать длину данных к отсылу. 

Можно, но не всегда удобно, да иногда и невозможно её рассчитать. Слишком большой огород городить придётся, код вырастит в разы и в моём случае уж точно не влезет в 368 мегу.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

vlad072]</p> <p>[quote=DIYMan пишет:

vlad072 пишет:

можно указывать длину данных к отсылу. 

Можно, но не всегда удобно, да иногда и невозможно её рассчитать. Слишком большой огород городить придётся, код вырастит в разы и в моём случае уж точно не влезет в 368 мегу.

1. Код "в разы" не вырастет, будет только ещё одна промежуточная команда, всё;

2. Ну это же вы писали

vlad072 пишет:

Сталкивался с таким, как побороть не придумал..

Вотя и ответил - не надо там ничего бороть, т.к. проблемы - не существует, всё описано в документации.

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

Если большой фрейм, как например подключение, где и собственно пакет подключения, и подписки, и паблиши - всё просчитить, перевести в текст.. и так делать повсеместно - гемер тот ещё.В общем и целом да, вы правы, проблема решаема, но не всегда малой кровью.

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

vlad072 , такое ощущение что у вас любая задача это гемор, то модем глючит, то памяти мало, может оно вообще не ваше - писать софт на МК - идите в PC, там всего много и ничего не глючит.

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

У вас что ни пост то сплошной "конструктив" формата: лишбы не пройти мимо, хоть что нибудь да ляпнуть, раздражется уже, вот честно. Те, у кого всё гладко и беспроблемно сюда с вопросами не обращаются, на то и форум.