Добрый день!
Который день не могу побороть казалось бы простую задачку со скачущими переключателями в меню управления при наличии обратной связи от исполнительного устройства по MQTT (хотя думаю так же будет и по HTTP и т.п.).
Суть проблемы: по дому разбросано несколько модулей на ESP8266 управляющих через реле светом и т.д.
В меню управления для них накиданы переключатели.
Модули с реле раз в несколько секунд посылают свой статус на сервер. В результате даже если сам majordomo был перезагружен или еще что стряслось - после приема статуса сервером в меню управления все переключатели сами встают в соответствии с актуальными состояниями реле. Удобно.
Но есть проблема - при клике на переключатель в панели управления он дважды гуляет туда-сюда, т.е. делает выкл->вкл->выкл->вкл вместо просто выкл->вкл.
Как я понимаю происходит следующее:
1. Нажали на перключатель в меню управления. Он меняет свое состояние в интерфейсе (например был выключен - стал включен) и поле status.
2. На событие смены состояния переключателя генерируется посылка по MQTT на переключение нужного реле.
3. Начинается цикл обмена данными с брокером MQTT в majordomo. В этом цикле на реле посылается новый статус (включено), но до самого реле этот статус еще не дошел. В этом же цикле majordomo получает от брокера последнее состояние реле - а оно пока еще выключено. В результате у переключателя в меню управления меняется статус, и он снова получается выключен.
4. До реле дошел новый статус, оно включилось. Переключатель как был выключен, так и остался.
4. На следующем цикле обмена с брокером MQTT majordomo получает уже новый статус реле (только что включилось), и снова меняет значение переключателя в меню управления на правильное (включен).
Как это побороть?
Меню управления - переключатель с обратной связью по MQTT
Модератор: immortal
- sergejey
- Site Admin
- Сообщения: 4286
- Зарегистрирован: Пн сен 05, 2011 6:48 pm
- Откуда: Минск, Беларусь
- Благодарил (а): 76 раз
- Поблагодарили: 1559 раз
- Контактная информация:
Re: Меню управления - переключатель с обратной связью по MQT
Если статус не меняется, то реже посылайте его в брокер, чтобы минимизировать вероятность, когда новый статус отправился, а пришёл старый.
Сергей Джейгало, разработчик MajorDoMo
Идеи, ошибки -- за предложениями по исправлению и развитию слежу только здесь!
Профиль Connect -- информация, сотрудничество, услуги
-
- Сообщения: 38
- Зарегистрирован: Пт апр 22, 2016 6:15 pm
- Откуда: Уфа / Россия
- Благодарил (а): 5 раз
- Поблагодарили: 6 раз
- Контактная информация:
Re: Меню управления - переключатель с обратной связью по MQT
Для повторения сообщений с топиками после перезагрузки брокера можно отправлять топики с флагом retained. Это заставит брокер сохранять последнее состояние такого топика и после перезагрузки брокера разослать его всем подписчикам.
- foxvlad
- Сообщения: 287
- Зарегистрирован: Пн сен 22, 2014 3:18 pm
- Откуда: Сочи
- Благодарил (а): 78 раз
- Поблагодарили: 78 раз
- Контактная информация:
Re: Меню управления - переключатель с обратной связью по MQT
А вы случайно не знаете как потом после "retained" отчистить топик, а то если потом посылать без этого флага, при подключении клиента ему будет слаться значение запомненное с "retained" а не свежее без него.ElectronicsInFocus писал(а):Для повторения сообщений с топиками после перезагрузки брокера можно отправлять топики с флагом retained. Это заставит брокер сохранять последнее состояние такого топика и после перезагрузки брокера разослать его всем подписчикам.
Брокер Mosquitto.
Youtube канал - https://www.youtube.com/c/OkBitru
-
- Сообщения: 119
- Зарегистрирован: Пн авг 24, 2015 11:24 am
- Откуда: Сочи
- Благодарил (а): 4 раза
- Поблагодарили: 14 раз
Re: Меню управления - переключатель с обратной связью по MQT
буквально вчера закончил писать код для ESP с данным функционалом, но потом потестировал и понял что раз в секунду отправлять пакет в MQTT не очень правильно, особенно если модулей много
и пришел к такому варианту:
делаем две переменных для проверки, к примеру status и status_new и устанавливаем до цикла loop обоим false или 0
потом делаем проверку
при таком варианте, при каждом изменении состояния с датчика, отправляется пакет 1 или 0 в нужную структуру MQTT
все остальное время пакеты не отправляются
возможно еще пригодится мое решения отправки статуса связи от ESP до MJD
создал класс таймеров
создается объект таймера
Timer name_timer;
И потом вызывается таким образом
при проверке name_timer.set(30) он возвращает 1 каждые 30 секудн и происходит отправка пакета Status = 1
в итоге, свойства объектов у меня привязаны к MQTT, при изменении статуса любого свойства в MJD происходит изменение всех связанных объектов и вместе с этим отправляется пакет изменения статуса в ESP по MQTT
при изменении статуса любого управляющего устройства подключенного к ESP, ESP отправляет пакет изменения статуса по MQTT и MJD получая этот пакет, меняет свойства объекта при этом изменяя все привязанные к этому свойству элементы
обмен пакетами между MQTT брокером и ESP модулями сведен к минимуму, отправка пакетов происходит только в случае изменения свойства объекта в MJD или при изменении статуса пинов на ESP + отправка контрольного пакета status раз в 30 секунд ESP -> MJD для проверки статуса онлайн модуля ESP
все просто и надежно )
на этом же примере, можно реализовать обратную связь для выставления нужных пинов в нужное состояние к примеру так:
ESP при включении/появлении связи с MQTT брокером разово отправляет пакет online_mqtt в MJD
MJD при получении пакета обрабатывает метод в котором всем необходимым свойствам объекта, присваиваются их же значения, тем самым происходит отправка MQTT пакетов в ESP и тот получая их выставляет необходимые пины согласно полученным данным
в итоге, если связь с брокером была разорвана в случае ребута сервака или при пропадании WiFi сети или при перезагрузке модуля ESP, ESP модуль всегда будет иметь необходимые статусы пинов полученные из MJD
реализовать можно в функции setup
а в функции callback так
и пришел к такому варианту:
делаем две переменных для проверки, к примеру status и status_new и устанавливаем до цикла loop обоим false или 0
потом делаем проверку
Код: Выделить всё
if(если на пин пришло HIGH) {
//делаем проверку на предмет изменения состояния пина и устанавливаем status_new в 1
if(status = 0 && status_new = 0) status_new = 1;
status = 1;
} else {
//делаем проверку на предмет изменения состояния пина и устанавливаем status_new в 1
if(если status = 1 && status_new = 0) status_new = 1;
status = 0;
}
//тем самым, при проверке статуса пина, мы выставляем status_new в 1 только в случае изменения статуса пина
//дальше делаем проверку внутри цикла отправки пакетов MQTT брокеру
if (WiFi.status() == WL_CONNECTED) {
if (mqtt.connected()) {
if(status_new) {
//отправляем пакет со значением равному status
mqtt.publish("Public", String(status));
//сбрасываем status_new для дальнейших проверок
status_new = false;
}
}
}
все остальное время пакеты не отправляются
возможно еще пригодится мое решения отправки статуса связи от ESP до MJD
создал класс таймеров
Код: Выделить всё
class Timer {
private:
int timer_set = 0;
int timer_mode = 0;
unsigned long timer_time;
public:
int set(int t) {
if(timer_mode == 0) {
timer_mode = 1;
timer_set = t * 1000;
timer_time = millis();
return 1;
}
if(timer_mode == 1 && (timer_time + timer_set) < millis()) timer_mode = 0;
return 0;
}
};
Timer name_timer;
И потом вызывается таким образом
Код: Выделить всё
if (WiFi.status() == WL_CONNECTED) {
if (mqtt.connected()) {
if(name_timer.set(30)) {
mqtt.publish("Status", "1");
}
}
}
в итоге, свойства объектов у меня привязаны к MQTT, при изменении статуса любого свойства в MJD происходит изменение всех связанных объектов и вместе с этим отправляется пакет изменения статуса в ESP по MQTT
при изменении статуса любого управляющего устройства подключенного к ESP, ESP отправляет пакет изменения статуса по MQTT и MJD получая этот пакет, меняет свойства объекта при этом изменяя все привязанные к этому свойству элементы
обмен пакетами между MQTT брокером и ESP модулями сведен к минимуму, отправка пакетов происходит только в случае изменения свойства объекта в MJD или при изменении статуса пинов на ESP + отправка контрольного пакета status раз в 30 секунд ESP -> MJD для проверки статуса онлайн модуля ESP
все просто и надежно )
на этом же примере, можно реализовать обратную связь для выставления нужных пинов в нужное состояние к примеру так:
ESP при включении/появлении связи с MQTT брокером разово отправляет пакет online_mqtt в MJD
MJD при получении пакета обрабатывает метод в котором всем необходимым свойствам объекта, присваиваются их же значения, тем самым происходит отправка MQTT пакетов в ESP и тот получая их выставляет необходимые пины согласно полученным данным
в итоге, если связь с брокером была разорвана в случае ребута сервака или при пропадании WiFi сети или при перезагрузке модуля ESP, ESP модуль всегда будет иметь необходимые статусы пинов полученные из MJD
реализовать можно в функции setup
Код: Выделить всё
if(mqtt.connect(MQTT::Connect(esp_name).set_auth(mqtt_user, mqtt_pass))) {
mqtt.publish("Status_online");
mqtt.subscribe("#");
mqtt.set_callback(callback);
}
Код: Выделить всё
void callback(const MQTT::Publish& pub) {
String payload = pub.payload_string();
if(String(pub.topic()) == "Pin_rele") {
rele_status = payload.toInt();
}
}