Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

Где найти подробное описания по работе с pubsubclient.h

Тема в разделе "IoT Manager – мобильное приложение", создана пользователем Bposter, 4 окт 2016.

  1. Bposter

    Bposter Новичок

    Сообщения:
    22
    Симпатии:
    0
    Где найти на русском подробное описание с библиотекой pubsubclient ? В яндексе не че не нахожу
     
  2. Victor

    Victor Administrator Команда форума

    Сообщения:
    2.209
    Симпатии:
    386
    Популярных библиотек pubsubclient на сегодняшний момент 2
    1. Устанавливается через стандартный менеджер библиотек GitHub - knolleary/pubsubclient: A client library for the Arduino Ethernet Shield that provides support for MQTT. (имеет ограничение на объем передаваемых данных)
    2. Форк от imroy GitHub - Imroy/pubsubclient: A client library for the ESP8266 that provides support for MQTT (не имеющий вышеуказанного ограничения)

    Русского описания я не встречал, но очень удобно смотреть доступные публичные функции в исходнике библиотеки pubsubclient/PubSubClient.h at master · Imroy/pubsubclient · GitHub
    там понятно какие параметры и каких типов можно передавать
     
  3. Bposter

    Bposter Новичок

    Сообщения:
    22
    Симпатии:
    0
    @Victor спасибо сейчас глянем
     
  4. Bposter

    Bposter Новичок

    Сообщения:
    22
    Симпатии:
    0
    Нашел вот такую функцию
    Код (Text):
    1. // Функция получения данных от сервера
    2.  
    3. void callback(const MQTT::Publish& pub)
    4. {
    5. Serial.print(pub.topic()); // выводим в сериал порт название топика
    6. Serial.print(" => ");
    7. Serial.print(pub.payload_string()); // выводим в сериал порт значение полученных данных
    8.  
    9. String payload = pub.payload_string();
    10.  
    11. if(String(pub.topic()) == "led/1") // проверяем из нужного ли нам топика пришли данные
    12. {
    13. int stled = payload.toInt(); // преобразуем полученные данные в тип integer
    14. }
    15. }
    Может подскажете как обратится к этой функции из loop чтоб вытащить значение передаваемые приложением на андроид?
     
  5. Victor

    Victor Administrator Команда форума

    Сообщения:
    2.209
    Симпатии:
    386
  6. Сергей_Ф

    Сергей_Ф Moderator Команда форума

    Сообщения:
    2.127
    Симпатии:
    226
    @Bposter обратите внимание, к этой функции не обращаются. Ее назначают в качестве обработчика сообщения. Почитайте про callback функции, что бы было понятнее.
     
  7. Bposter

    Bposter Новичок

    Сообщения:
    22
    Симпатии:
    0
    Спасибо с этим разобрался все ок работает, теперь встал вопрос запитки множества устройств таких как датчик движения, температуры, реле и тд.. Вопрос в том что есть хороший блок питания и я вот думаю запитывать каждое устройство от блока типа так
    [​IMG]
    При условии что допустим все устройства питаются от 9 вольт и мощность блока хватит на все так правильно будет?
     
  8. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    Подскажите, откуда вызывается назначаемая callback функция? Я посмотрел код клиента и похоже, что колбэк в итоге дергаем из основного цикла(client.loop(), который как раз сидит в основном цикле ), т.е. в данной реализации это не какой-то асинхронный процесс, который навесили на прерывание.
    Мне это почему интересно: я предполагаю, что могут быть ситуации, когда от брокера прилетит толпа сообщений и скорость их поступления окажется больше скорости их обработки на стороне esp и часть пакетов будет потеряна. При этом, если б колбек функция вызывалась асинхронно, то можно было б сначала все мессаджи складывать в программный FIFO, а в основном цикле (или в колбек функции + либа Ticker) с небольшой задержкой по времени их обрабатывать (каждые 0.5 с например).
    Ну а если колбек будет вызываться из основного цикла, то нет смысла тратить время на складывание данных в буфер - их нужно тут же обрабатывать.
     
  9. Victor

    Victor Administrator Команда форума

    Сообщения:
    2.209
    Симпатии:
    386
    как-бы ниоткуда, т.е. мы сами ее никогда не вызываем.
    ее вызывает библиотека, когда приходит сообщение (в loop не забываем добавитьclient.loop())
    применяйте к ней те же правила, что и к прерываниям (минимум операций, никакого вывода в консоль и т.п.)
    эту функцию желательно писать так, чтобы она была реентерабельна, т.е. один из вариантов так, как вы и описали, с FIFO.
    Но у брокера тоже все не мгновенно происходит, поэтому можно просто сложить сообщение во временную переменную (FIFO=одно сообщение) - для большинства применений этого достаточно.
    Есть еще AsyncMQTT (на AsyncIO) - можете посмотреть ее.
     
  10. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    Ну вот вы тоже говорите про client.loop(), а эта функция сидит в основном цикле. Т.е. как такового асинхронного вызова колбэк функции не происходит(может я не верно это понимаю).
    Я дальше pubSubClient не копал, есть надежда, что возможно в самой библиотеке MQTT есть асинхронные вызовы + некий буфер в который складываются сообщения.
    Спасибо за наводку, гляну что есть такое AsyncMQTT.
    А вот насчет организации работы с FIFO. Как обычно делают?
    Мне видится пара вариантов:
    • - в колбэк функции pubSubClient пришедшее сообщение сразу складываем в буфер. Из этого буфера добывает сообщения другая колбэк функция - использующаяся совместно с либой Ticker. Из плюсов мне видится простота решения, из минусов - некоторая задержка реакции на сообщение, максимум - на заданные период в тикере.
    • - в колбек функции pubSubClient пришедшее сообщение не сразу кладется в буфер, сначала смотрим флажок, который говорит, что прежний вызов колбек функции еще не завершился.
      В сообщении 12 написал почему не выйдет так сделать (раскрыть)
      Если флаг сброшен - выставляем его и начинаем обрабатывать сообщение. После обработки сообщения смотрим - нет ли чего в буфере. Если есть - обрабатываем, если нет - флаг сбрасываем и завершаем работу функции. Если на момент вызова функции флаг был установлен - просто добавляем очередное сообщение в буфер. Из плюсов этого решения - быстрая реакция на сообщение, из минусов - конкурентный доступ к флагу "занятости", который непонятно как организовать и допущение того, что для каждого вызова функции рождается новый процесс, т.е. одна и та же функция может работать в нескольких экземплярах в один и тот же момент времени - а это может быть не так. Т.е. вопрос - что произойдет, если вызвать функцию еще раз до того, как она завершит свою работу с прежнего вызова?
     
    Последнее редактирование: 28 окт 2016
  11. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    И еще пока не понятно как организовывать длительные процессы на которые пришел запрос. Я о публикации данных в топик. Т.е. вот допустим пришел запрос вида "дай мне последнее считанное значение с датчика Х". В ответ нужно будет начать что-то там отвечать, но если делать это тут же, в колбэк функции, есть шанс потерять часть следующих входных данных. Я думаю организовать пару FIFO - один для входных данных (наполняется в колбэк pubSubClient, это все, что там делается), второй - для данных, которые нужно будет опубликовать. А работать с ними так: создать пару колбэк функций для тикера - А и Б. колбэк А читает данные из буфера входных данных, как-то там их обрабатывает: это может быть прямое управление пинами или там изменение каких-то настроечных праметров, а может быть обработка запроса на передачу данных - состояния пинов, значений настроечных параметров, датчиков. В последнем случае запрашиваемые значения добавляются в буфер для публикации. колбэк Б занимается тем, что смотрит буфер выходных данных и если там что-то есть - извлекает данные и публикует. По одному элементу буфера за каждый вызов.
     
  12. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    Поигрался с колбэк функциями.
    О грустном: если одна и та же колбэк функция будет запущена до того, как успеет отработать ее предыдущая запущенная копия, то ловим рестарт системы по WDT. Т.е. нельзя давать функции "наступать самой себе на пятки". Для этого она должна вызываться с заведомо бОльшим интервалом времени, чем она сама отрабатывает.
    Что до совместной работы нескольких колбэк функций, то вроде б все норм.
    В аттаче я прикрепил наброски того как мне видится обработка входящих сообщений от брокера. Если увидите какие-либо недочеты или возможные узкие моменты - пожалуйста подскажите их.
    Издалека же) решение выглядит рабочим вариантом.
    В первом приближении:
    • - в колбэк функцию для pubSubClient будет добавлен парсер (наверное XML) выходные данные которого будут положены во входной буфер,
    • - в колбэк А -некоторые рулы, которые в зависимости от данных с датчиков и настроечных параметров меняют состояние пинов (либо значение некоторых настроечных параметров - так одни рулы смогут влиять на поведение других рулов).
    • - почти нетронутым останется колбэк Б - там просто вынимаем что есть в выходном буфере и публикуем.
    • - в качестве буферов будут кольцевые FIFO.
    • - чтение датчиков хочу делать в основном цикле.
    • - так же хочу завести еще одну колбэк функцию для запуска рулов - там период будет побольше, что-то вроде раз в 5 минут, т.к. предполгается рулить вялотекущими процессами.

    Т.е. запуск рулов и последующее обновление состояний выходных пинов будет осуществляться как "по требованию" со стороны брокера, так и штатно.
     

    Вложения:

  13. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    @nikolz, верно, наплодив колбэки я не получу несколько независимых тредов. В итоге они всё равно будут выстроены друг за другом. Пожалуй, я их использовал для упрощения разграничения зон ответственности. А вот интересно - если в данный момент времени будет работать колбэк А, который вызывается по тикеру и в это же время прилетит сообщение от брокера - колбек для pubSubClient вызовется, прервав работу колбэк А? Или мы просто ждем завершения работы очередной функции и только потом управление передается следующей? Хочется в колбэке для pubSubClient делать какое-то не длительно действия, типа перекидывания сообщения в буфер и быть при этом уверенным, что это произойдет в любом случае. Хотя.. колбэк - это обычная функция, и что б одна колбэк функция прервала выполнение другой колбэк функции, она должна быть запущена от функции, которая вызывается для обработки прерывания.
     
    Последнее редактирование: 28 окт 2016
  14. Сергей_Ф

    Сергей_Ф Moderator Команда форума

    Сообщения:
    2.127
    Симпатии:
    226
    @combasoft колбэк функция должна выполняться полностью, без прерываний. Вы сколько mqtt событий в секунду собрались обрабатывать, что такие вопросы Вас волнуют?
     
  15. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    Про приоритеты - этого я еще не знал. Можно пример?
    А вообще, похоже зря я всё так усложняю. Смотрите: в основном цикле дергаем client.loop(), внутри которого вызывается указанный юзером колбэк. В этой функции проверяем - не пришло ли нам сообщение. Если б все это выполнялось в один поток, то эта проверка сработала, если б мы стали проверять приход сообщения прям в момент его прихода. Что конечно крайне маловероятно. Зато если предположить(тут надо мануалы по esp смотреть), что процессом приема-передачи сообщений занимается отдельный wifi модуль, да еще с буфером в несколько сообщений, то самому МК остается только проверить не заполнен ли этот буфер и если он не пуст - прочитать из него очередное сообщение.
    Иначе говоря, можно особо не заморачиваться (если только случай не исключительный) с тем как много времени займет выполнение пользовательской колбэк функции, ну разве что датчики внутри этой функции не читать.
     
  16. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    Если не сложно, расскажите в кратце что происходит с пакетом данных, когда он долетает до ESP c MQTT клиентом на ней, в плоть до попадания в определенный пользователем колбэк.
    Почитать "про процессоры" это довольно абстрактно - могу копать много, но не в ту сторону, в итоге без результата. Да и как вникание в архитектуру МК поможет с колбеками, которые (если я правильно понимаю) специфичны именно для ЯП, а не архитектуры МК?
     
  17. Victor

    Victor Administrator Команда форума

    Сообщения:
    2.209
    Симпатии:
    386
    таких мануалов я не встречал, вам поможет изучение исходных кодов клиента (не важно - для микроконтроллеров или нет). Выберите язык в котором больше разбираетесь и найдите open source MQTT клиент, написанный на этом языке и изучайте.
    P.S. Я, вообще, поддерживаю дотошность, но в данном случае, по моему мнению, вы перебарщиваете. Не надо сильно в дебри залезать - по упрощенной схеме, как я вам уже сказал все работает - проверено. Решайте проблемы по мере поступления.
     
    Сергей_Ф нравится это.
  18. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    @nikolz, вы меня не поняли. Я примерно понимаю идею MQTT. Спрашивал я за то, что происходит на стороне ESP. Вот например: "прилетел пакет". Как ESP об этом узнает - что ей что-то пришло? Если знаете и не сложно написать - напишите, мне это сэкономит время. Может еще кому-нибудь кроме меня. Ярлыки про дилетантов оставье при себе.
    если ничего нового не придумали, то это прерывания. Т.е. с таблицей векторов прерываний, то, что среди прерываний есть приоритеты - я в курсе, но я не слышал, чтоб эти функции обзывали как колбэк функции. Я только недавно с этим видом функций ознакомился,
    могу конечно ошибаться, но в кратце такую функцию можно описать так: колбэк функция - это функция, которая передается в качестве аргумента для другой функции.
    @Victor, да, я усложнил без надобности. Попробую сделать по приведенному вами примеру, спасибо. Будут сложности - буду копать.
     
  19. Victor

    Victor Administrator Команда форума

    Сообщения:
    2.209
    Симпатии:
    386
    ок, только в нашем случае несколько "слоев реальности"
    • самый верхний, видимый слой - обмен по протоколу MQTT в вашем скетче
    • средний слой - обертка функций Espressif SDK - это Arduino IDE
    • следующий слой - стек TCP/IP в Espressif SDK (почти полностью разобран @pvvx)
    • далее WiFi стек, который, в принципе, известен, но реализация в ESP8266 практически закрыта для нас (она частично в SDK и частично в BIOS чипа)
    Все это как-то работает на одноядерном процессоре, Arduino волшебным образом переключает контексты между SDK и вашим скетчем в свободное время. Поэтому говорить об истиной асинхронности не очень верно, тут @nikolz прав.

    Я все это к тому, что полный ответ на ваш вопрос достаточно объемный и имеет смысл только при наличии определенных знаний (не малых) у того, кто спрашивает.
    Ответить со всеми деталями на него могут пара тысяч человек в мире, но я не из их числа. А понять ответ смогут лишь несколько сотен тысяч человек в мире. Я лишь отношу себя к тем, кто примерно понимает, что там происходит внутри.

    Разбирайтесь - я буду рад, если вы когда-нибудь войдете в число тех, кто не только понимает что внутри, но и сможет понять сложный развернутый ответ :)
     
    combasoft нравится это.
  20. combasoft

    combasoft Новичок

    Сообщения:
    35
    Симпатии:
    0
    Отлично! Спасибо)
     

Поделиться этой страницей