Циклическое срабатывание правил

Вопрос по правилам.
Есть термостат с параметром “ТемператураРеал”. Я создал виртуальное устройство с параметром “ТемператураВирт”.
Есть Правило1 на изменение ТемпературыВирт - в результате ТемператураРеал должна стать равной ТемпературыВирт.
И есть Правило2 на изменение ТемпературыРеал - в результате ТемператураВитр должна стать равной ТемпературеРеал.
Изменение температуры должно быть доступно как с физического термостата, так и с виртуального.
Сейчас изменение ТемпературыРеал вызывает сработку Правила1 и сработку Правила2 и так по циклу.
Как сделать так чтобы при изменении ТемпературыВирт срабатывало только Правило1, а при изменении ТемпературыРеал только Правило2?

Добрый день.
Рекомендую использовать какое-либо флаг для исключения “нежелательного” срабатывания, например. А вообще - считаю выбранную архитектуру с разными правилами неподходящей.

У меня два термостата на 1м и 2м этаже. У термостатов есть параметр Статус (вкл/выкл), нужно сделать так чтобы в один момент времени вкл только один термостат, а второй был выкл.
С включенного термостата нужно будет брать уставку температуры и температуру с датчика для котла.
Если оба термостата выключены - то и котел выключен.
При этом хотелось бы иметь возможность выбрать источник температуры и указывать уставку в вебинтерфейсе, чтобы оно отображалось на выбранном термостате.
Как-то так… посоветуйте в какую строну смотреть.

Вы сейчас описываете задачу.
У нее много способов решения, тот же флаг например.
Если что-то в ПО работает не так как описано в документации - то дайте воспроизводящий пример пожалуйста.

Я новичок в wb, извините, если что-то я не понимаю. Как я понял из документации (GitHub - wirenboard/wb-rules: Rule engine for Wiren Board), что получать изменившиеся значения я могу через правила (defineRule), и если необходимо в правилах менять значения у других устройств. Как в первом сообщении я написал, при попытке таким образом реализовать мою задачу (которую я тоже уже описал) я получаю ненужные мне, “паразитные” так сказать, срабатывания правил у изменяемых свойств. И я понимаю, что это поведение системы штатное. Я и хотел узнать, может быть есть способ “красивый” и правильный, реализовать подобную задачу, помимо флагов.
Вы сказали, то считаете такую архитектуру неподходящей, раскройте ответ, если можно - какую архитектуру вы считаете более подходящей в данном случае или на какие моменты обратить внимание в документации или может есть еще документация по правилам?

Вот тут именно этот вопрос обсуждался.
И, кстати, есть еще один подход: в каждом правиле перед записью нового значения проверять - а не равно ли оно уже записываемому. И если равно - то ничего не делать. Таким образом - второе правило будет вызвано - но один раз.

Да, именно это и нужно. Спасибо.

1 лайк

Все таки на работает.

По ссылке выше предлагалось два варианта:

  1. getDevice(‘led’).getControl(‘range_dali’).setValue({value: 50, notify: false}); Этот вариант может раньше работал, сейчас не работает, все равно запускается событие на изменяемом устройстве.
  2. Отключить правило (disableRule) выполнить изменение параметра и затем включить правило (enableRule). Там же говорилось, что штатное поведение системы когда “обычный JS, функции работают асинхронно”, но по факту так не работает. Если правило отключить при инициализации в теле модуля - да работает, а если выключить в одном правиле другое правило - выполнить его и включить - не работает.

Получается остаются только флаги, но это усложняет очень код, особенно когда устройств несколько.
Хотелось бы иметь документированную работающую возможность аналогичную getDevice(‘led’).getControl(‘range_dali’).setValue({value: 50, notify: false}); т.к. она решает все вопросы.
Либо хотя бы работающую как заявлено disableRule/enableRule.

Я как автор той темы, так и не решил проблему. :frowning: Очень хочет иметь какой-то метод просто синхронизации нескольких значений. Или хотя бы, иметь возможность понимать в обработчике, вызвано ли изменение значения изменением внутри прибора, или внешним воздействием.

1 лайк

Получается только на флагах.
Если сделать flag1 = true и в правиле1 поставить условие if (!flag1) { return }, а в другом правиле:

flag1 = false;
dev["......"] = "test"; //изменяем свойство, которое связано с правилом1
flag1 = true;

то когда, в результате изменения свойства, будет вызвано правило1 значение flag1 будет true, т.е. ничего не работает…
Этого можно избежать, если поставить ожидание:

flag1 = false;
dev["......"] = "test"; //изменяем свойство, которое связано с правилом1
msec = Date.now(); 
do {
  r=0;
} while (Date.now()-msec <= 5);
flag1 = true;

тогда все отрабатывает как надо.

Таймаут в данном случае ставить нельзя, он асинхронный и не ждет окончания выполнения. Таймаут у меня сработал только если между установками большие паузы (секунды), если изменить таким образом сразу 5 параметров по одному-двум флаг обратно в true не устанавливается.

Все равно это “костыли”, действительно, нормального решения нет, поэтому:

Хотелось бы иметь документированную работающую возможность аналогичную getDevice(‘led’).getControl(‘range_dali’).setValue({value: 50, notify: false}); т.к. она исключает проблему полностью и решает все вопросы.

Не очень все же хорошая идея - какие-то дополнительные блокировки, как внешние (флаги) так и выключение срабатывания.
Решается как правило обработкой необходимости менять значение.
Например:
Есть контролы A,B,C
Соответственно правила для A, меняющее B, правило для B, меняющее С и правило для C, меняющее А.
При изменении любого контрола - возникает цикл. Но если добавить в каждое правило условие, проверяющее значение в изменяемом контроле и публикующее только при отличающемся - они отработают только один раз.

К сожалению, не все устройства дают быструю обратную связь. Например, у меня, когда кондиционерам сказать “включи режи ауто”, команда в него уходит быстро. А вот изменение регистра происходит с задержкой, по ощущениям 300-1500 мс. В итоге, это выглядит так: я в виртуальном устройстве меняю режим. Это вызывает правило реального. Но там еще старое значение. В общем, я пока для себя принял решение, что в таких случаях просто делаю задержку около 1-2 секунд, в течение которой игнорирую старое значение.

Но все это криво, ад в отладке и в целом, боль. А еще - такой способ не подходит для света, если потом прокидывать это все в HomeBridge. Потому что в Apple нет явного события “начал менять яркость, отпустил, и ПО установило яркость”. Там, если я веду пальцем по слайдеру яркости - должна в реалтайме меняться яркость. И в случае с WB это в приницпе невозможно, как мне показалось, поэтому слайдер под пальцем постоянно прыгает.

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

Тут дело в том (еще) что топики меняют не только правила. Но и драйвера. То есть при (почти) одновременной записи из драйвера и из правила можно пропустить срабатывание.