• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Очередной MQTT-клиент для android в виде приборной панели списком

max506

New member
Здесь решалась проблема с тем, что оборудование отсылая свой статус серверу, само же его и получало
Ну да, я как раз об этой проблеме и говорю. Только не понимаю, как эту проблему решает различие темы всего лишь одним знаком $ в конце. Автор запроса сам писал, что если будет два топика в одном виджете, то на один можно отправлять сообщения, и не подписываться на него, а с другого получать, подписавшись. Но при этом топики должны различаться так, чтобы при подписке можно было задать маску (о чем я написал в предыдущем своем сообщении).
 

max506

New member
Мне самому не нравится этот костыль, достаточно было бы оборудованию проверить, что команду выполнять не нужно, т.к. уже выполнена ранее и цикла бы не возникло, но, на сколько я понял, у автора запроса не было возможности влиять на логику обработки команд/отсылки статуса оборудованием, отсюда пришлось организовывать костыль.
У меня похожая проблема. И она не в зацикливании, а в лишней трате времени контроллера на обработку.
Мой пример:
В связке живут Ардуино и ESP. На Ардуино крутится вся логика, а ESP отвечает за отправку/получение данных. Связаны контроллеры по UART.
Теперь представьте, что Ардуино передала ESP 20 топиков со значениями, которые также могут быть изменены из Lenear MQTT. ESP, отправив эти 20 значений, тут же получит их назад, поскольку подписана на эти темы. Теперь надо потратить время, чтобы их распарсить, и снова отдать по UART в Ардуино. А зачем? Если бы была возможность отправить эти значения в топики, на которые ESP не подписана, это бы решило проблему. А подписываться только на темы, которые можно изменять в вашей программе. Но для этого в интерфейсе надо иметь возможность формировать значения обоих топиков.
 
Последнее редактирование:

ravend

Member
Пример, допустим радио-выключатель света: на нём есть физические кнопки "вкл" и "выкл".
1.Пользователь нажимает физическую кнопку и на сервер, в топик light1 идет команда on.
2.Оборудование само получает, свою же собственную команду light1 - on (так как подписано на light1/#), и сообщает свое состояние в топик light1 - on, переходим к пункту №2.
 

max506

New member
Пример, допустим радио-выключатель света: на нём есть физические кнопки "вкл" и "выкл".
1.Пользователь нажимает физическую кнопку и на сервер, в топик light1 идет команда on.
2.Оборудование само получает, свою же собственную команду light1 - on (так как подписано на light1/#), и сообщает свое состояние в топик light1 - on, переходим к пункту №2.
Для решения этой ситуации надо иметь на виджете два топика:
/inf/light1 - на эту тему слать сообщение при нажатии физической кнопки и не подписываться на нее;
/mod/light1 - подписываться по маске /mod/# и получать сообщения, только когда изменения произведены в вашем интерфейсе.
Таким образом все сообщения делятся на информационные (read only) и модифицируемые.
 

max506

New member
достаточно было бы оборудованию проверить, что команду выполнять не нужно,
В том-то и дело, что моя ESP не может (и не должна) ничего проверять, поскольку ее задача заключается только в отправке/получении сообщений от/для Ардуино. А какие сообщения принимать, должно решаться на уровне масок подписки.
Но для этого в интерфейсе надо иметь возможность формировать значения обоих топиков ))
 
Последнее редактирование:

ravend

Member
Для решения этой ситуации
Не обязательно, я считаю что проблема в подходе при реализации устройств, не нужно думать, что ваша железка (тот же выключатель) является местом сосредоточения актуальной информации, при работе с MQTT, центром является сам сервер MQTT, а все устройства должны читать текущее состояние и воспроизводить его своей логикой и помещать _новое_ состояние на сервер.
Пример: не сервер, в топик light1 положили значение on, как оно там оказалось (и когда) - совсем не важно, оборудование должно прочитать это значение и включить свет, _при_этом_ не отчитываться на сервер, что свет включен (или отчитываться в ДРУГОЙ топик! если уж требуется признак, что команда отработана).
 

max506

New member
На мой взгляд, назначение подписки в протоколе MQTT именно и служит для решения задачи не получения (обратно от брокера) информации, которая не нужна/не интересна (в данном случае отправленная самим же устройством).
Сейчас для реализации такой возможности для одного объекта в вашем интерфейсе надо завести два виджета:
на один из них, не редактируемый, слать информацию для отображения, а с другого, редактируемого, принимать. Но ведь удобнее было поддержать две темы в одном виджете, раз уж все равно это реализовали. Но в текущей реализации это, к сожалению, не имеет практического применения :(
 

max506

New member
В общем очевидно, что протоколу MQTT при публикации сообщения не хватает признака отправлять/не отправлять сообщение обратно источнику. Брокер же знает, от кого оно пришло. Это бы разом решило многие проблемы )))
 

dao89

New member
max506. где ж вы раньше были, когда я просил автора реализовать два разных топика для виджетов (я ведь изначально это и просил) :) На тот момент некому было меня поддержать и это не было полноценно реализовано...
Раз уж тут опять пошла дискуссия, приведу ещё пример. Постараюсь коротко, не вдаваясь в подробности.
Яркостью светодиодных лент у меня дома (в коридоре и ванной они - основной свет) можно управлять вручную (для этого создан виджет Slider, топик, к примеру, /set/kom/le), но обычно они загораются автоматически на основе датчиков движения. В режиме ручного управления, при получении сообщения с яркостью, контроллер плавно приводит яркость ленты к полученному значению.
В авто-режиме, когда свет загорается и тухнет сам, значения, пришедшие в этот топик игнорируются, при этом контроллер отправляет в этот же топик фактическое текущее значение, чтобы в приложении не отображалось неправильное. Включение света происходит хоть и плавно, но быстро (секунда-две), поэтому видеть на слайдере промежуточные значения яркости не обязательно, хватит и одного - конечного.
А вот когда движение кончилось, время ожидания вышло и свет начинает медленно (в течении минуты) плавно тухнуть, то тут уже хотелось бы видеть на виджете промежуточные значения фактической яркости. Свет гаснет, контроллер шлет десятки (а то и сотни) сообщений о текущей яркости. Вот только зачем ему их принимать?
Когда включено управление лентой по датчику движения, можно, конечно, отписаться от топика, на который приходит яркость ленты, но тогда если случайно ткнуть на виджет пальцем, то там будет красоваться значение, не соответствующее реальности и контроллер это не сможет исправить, т.к. отписан от топика. Можно отписываться только в момент когда контроллер меняет яркость ленты и подписываться обратно по окончанию процесса. Но уж очень много всяких костылей только от того, что в приложении нет возможности задать два топика для виджета... Я бы мог привести ещё разных примеров, но на описание даже одного уходит много времени, к сожалению.
P.S. Признаюсь, функционал с дополнительным топиком с $ в конце я до сих пор не использовал в своем умном доме, помятуя слова автора о том, что можно обойтись без этого. Да, можно. Особенно в простых ситуациях. А когда система становится сложной, с множеством вариантов управления одним и тем же объектом - вот тут то возникают различные неудобства.
P.P.S. Насчет того, что может решить топик с $ на конце. На тот момент, когда я на это согласился, стояла задача разграничивать сообщения пришедшие от пользователя и те, что были отправлены самим контроллером. Если бы контроллер слал сообщения с состоянием датчика (к примеру) в топик с $, он бы их получал, но знал бы, что они пришли от него самого и их не нужно обрабатывать. В итоге проблему я решил по-другому, но от этого ситуации, когда два разных топика были бы кстати, не исчезли.
 

dao89

New member
Может кому-то пригодится.
1. У вас есть дата\время (Unix-time) какого-то события, например последнего движения. В удобном виде её можно отобразить так:
Код:
var dt=new Date(value*1000);
var time=dt.getHours() + (dt.getMinutes() < 10 ? ':0' : ':')+ dt.getMinutes()+(dt.getSeconds() < 10 ? ':0' : ':')+ dt.getSeconds();
dt.setHours(0,0,0,0);
now = new Date();
now.setHours(0,0,0,0);
var diff=(now-dt)/1000/86400;
switch (diff){
case 0: value='сегодня || ' + time;
break;
case 1: value='вчера || ' + time;
break;
case 2: value='позавчера || ' + time;
break;
default:
var dt=new Date(value*1000);
value=dt.toLocaleString();
};
2. Контроллеры посылают сообщения с текущим датой\временем (Unix-time), подавая таким образом сигнал, что они "живы". Красиво вывести в онлайне ли устройство, можно так:
Код:
value=(Date.now() / 1000 - value) < 70 ? 'online' : '!!! offline !!!';
P.S. Как это выглядит можно посмотреть на скриншотах. Если кто подскажет как можно укоротить первый скрипт - буду рад увидеть. В JS не силен...
 

Вложения

telobezumnoe

New member
доброго времени суток. понравилось приложение, не понимаю всех этих заморочек с двумя топиками. можно же в скетче сделать проверку совпадают ли принятые данные с отправленными, если устройство подписано на тот же топик что и публикует. и при отправке переменных которые быстро меняются (димированние ламп) отправлять их после того как они перестали изменяться в цикле, или достижению какого то значения. По поводу приложения, почему то при подключении другого клиента (mqtt dashbord) он обновляет данные с сервера если приложение было офлайн, в то время когда данные изменились, в текущем приложении данные так и остаются теми же, какие были на момент выключения приложения. что бы они обновились, надо чтоб новые данные пришли в момент работы приложения..
любопытно, сервер отправляет данные по изменению единожды всем кто на него подписан?.. или в скетче можно как то опросить сервер на наличие текущих данных?
 

ravend

Member
любопытно, сервер отправляет данные по изменению единожды всем кто на него подписан?.. или в скетче можно как то опросить сервер на наличие текущих данных?
Чтобы приложение (или Ваше оборудование) получило актуальное состояние топика (даже если было отключено от сервера/сети, в то время когда значение в топике было опубликовано), нужно отправлять данные с признаком "Retained", это стандартная возможность указать MQTT серверу, что содержимое сообщения должно быть доставлено, как только клиент будет подключен (и, естественно подписан на соответствующий топик) к серверу MQTT.

В Linear MQTT в некоторых виджетах можно указать retained, в некоторых этот признак назначен по умолчанию и "снять" его нельзя (это виджеты: slieder и switch).
 

ravend

Member
Чтобы легче было понять назначение признака retained, можно/нужно думать про него следующим образом:
- с признаком retained нужно отправлять сообщения, чтобы опубликовать _состояние_
- без признака retained оправляются _команды_.

Пример:
"Состояние", это к примеру сообщение со значением, отражающее интенсивность света светодиодной ленты, или должен ли быть кран открытым, или должен ли работать вентилятор.
"Команда", - это к примеру, сообщение содержащее признак, что свет нужно включить сейчас, или вентилятор нужно выключить сейчас и т.д.
 

dao89

New member
не понимаю всех этих заморочек с двумя топиками. можно же в скетче сделать проверку совпадают ли принятые данные с отправленными, если устройство подписано на тот же топик что и публикует. и при отправке переменных которые быстро меняются (димированние ламп) отправлять их после того как они перестали изменяться в цикле, или достижению какого то значения.
То что вы пишите - это очевидные вещи. А если требуется не в конце процесса один раз отправить конечное состояние, а отправлять все промежуточные значения?
В любом случае, если стоит задача не засорять сеть ненужным трафиком, не тратить ресурсы контроллеров на обработку ненужных им сообщений, то без обсуждаемой тут пары топиков для виджета не обойтись. Это факт, если речь идёт об MQTT.

@ravend стоит ли ожидать обновления программы с возможностью сохранения и загрузки конфига через диалог выбора файла, вместо текущей реализации (при которой программа предлагается для открытия любых файлов)?
 

max506

New member
где ж вы раньше были, когда я просил автора реализовать два разных топика для виджетов (я ведь изначально это и просил) :) На тот момент некому было меня поддержать и это не было полноценно реализовано...
На тот момент я еще не знал, что такое MQTT )))
контроллер шлет десятки (а то и сотни) сообщений о текущей яркости. Вот только зачем ему их принимать?
Вот я именно об этом и говорю. Контроллер должен иметь возможность подписаться только на те сообщения, которые инициированы из виджета пользователем, но не на те, которые контроллер отправляет в виджет. Надо экономить трафик, и особенно это критично, когда работа идет по сотовой сети через облачный MQTT-брокер.
можно же в скетче сделать проверку совпадают ли принятые данные с отправленными
Может и можно, но в некоторых случаях совсем не оптимально (почитайте мои предыдущие сообщения о связке Ардуино +ESP). Мне приходится перекачивать в Ардуино через UART огромный объем совершенно ненужных данных. Ну не дублировать же мне все переменные на ESP, чтобы проверять изменение их значений. В моем случае ESP - это всего лишь транспортный уровень, и ни о какой логике знать этот модуль не должен.

P.S. Кстати, в похожем приложении MQTT Dash реализовано два топика для виджета. Но я еще не обсудил с автором его видение концепции, как предполагалось их использовать при реализации приложения.
 

dao89

New member
Вот подарочек с утра от автора - приложение обновилось! Из нового, как я понял, как раз таки раздельные sub и pub топики. Спасибо! Осталось подумать как теперь это лучше всего применить. Еще бы экспорт\импорт настроек сделать через файл, или, что еще лучше, через mqtt топик специальный, это было вообще отлично (идею подсмотрел у автора mqtt dash).
 

mvn77

New member
Подскажите пожалуйста - возможно реализовать подачу звукового сигнала или воспроизведение звукового файла в случае выхода температуры за пределы определенных границ и в случае не обновления данных в течении N-ного времени?
 

klbsss

New member
Подскажите пожалуйста - возможно реализовать подачу звукового сигнала или воспроизведение звукового файла в случае выхода температуры за пределы определенных границ и в случае не обновления данных в течении N-ного времени?
Реализовал с помощью thingspeak и виджета на андроид iot thingspeak
 
Сверху Снизу