после перезагрузки контроллера часть правил запускается, потому что срабатывает onchange по сравнению с retained значениями. можно как-то отловить это и не пропускать отработку правил?
Вопрос касается whenChanged?
Обработчик onchange не из wb-rules
да, конечно, whenChanged
whenChanged ничего не сравнивает, он просто выполняет заложенную функцию при изменении входного параметра или при перезапуске правила.
Можете на примере проиллюстрировать?
да. есть радио кнопка vhome, у которой whenChanged выключает или выключает весь свет, например.
рестарт контроллера приводит к срабатыванию whenChanged, хотя нажатия не было.
рестарт движка правил к такому эффекту не приводит.
правило самое простое
defineRule( “targetrule” + rc, {
whenChanged: re.devname,
then:
(function( devname, target, devtarget ) {
return function( newValue, devName, cellName ) {
log( “on '” + devname + “’ change '” + target + “’ (” + devtarget + “)” + “nv={} dn={} cn={}”, newValue, devName, cellName );
dev[devtarget] = ! dev[devtarget];
};
})( re.devname, re.target, getTarget( re.target ) )
});
можно как-то отличить запуск правила при старте от запуска правила при событии?
Ну на пример добавить проверку, что Current uptime больше минуты. Тогда в первую минуту после запуска правило работать не будет, за то и первое срабатывание будет проигнорировано.
у меня стоит задержка 5 секунд после первого просмотра. минута много, но попробую, спасибо.
Я обычно ставлю переменную-флаг при начальной инициализации программы, который при первом выполнении функции сбрасывается.
var initial = true;
.
.
.
if (initial) { // если выполнение тела произошло по причине первоначальной загрузки сбрасываем флаг
initial = false;
} else { // если выполнение кода произошло когда инициализация уже прошла, то выполняем действие
dev[devtarget] = ! dev[devtarget];
}
.
.
Изящнее было бы такую проверку делать сразу в whenChanged, но похоже это не предусмотрено синтаксисом команды.
у меня в любом случае whanChanged генерится в обертке, добавить туда проверку не сложно. но как-то хотелось бы документированно понимать, что это вызов не по событию, а по first run.
Скажите пожалуйста что за обертку используете для генерации кода?
В чем ее преимущество?
Где про этот способ можно получить информацию?
обертка - это генерация правил на основе массива данных с описанием кто на что и как реагирует. просто мне так было удобно.
почитать - это функции JavaScript + clusure.
На странице описания движка правил есть немного про обертки:
https://wirenboard.com/wiki/index.php/Движок_правил_wb-rules
в разделе “Создание однотипных правил”.
Обертка (closure) в общем случае выглядит так:
(function() {
// код
})();
Ну, вот ссылка для почитать:
https://www.w3schools.com/js/js_function_closures.asp
вот чуть более подробно с кусочками кода.
// spalna
{ devname: "vhome_48932/1", name: null, target: "spalna svet" },
{ devname: "vhome_48932/2", name: "spalna mid", target: function() { TurnLight( false ); } },
{ devname: "vhome_48932/3", name: null, target: "balkon svet" },
// vhod
{ devname: "vhome_29476/1", name: "radio vhod 1", target: allOn },
{ devname: "vhome_29476/2", name: null, target: "koridor svet vhod" },
{ devname: "vhome_29476/3", name: "radio vhod 3", target: allOff },
for( var rc = 0; rc < mySources.length; rc++ )
{
var re = mySources[rc];
if( re.target )
{
if( typeof re.target == "function" )
{
defineRule( "targetrule" + rc, {
whenChanged: re.devname,
then:
(function( devname, target ) {
var first_run = true;
return function( newValue, devName, cellName ) {
if( first_run ) { first_run = false; return; }
log( "on " + devname + " call " + target + "nv={} dn={} cn={}", newValue, devName, cellName );
target( newValue, devName, cellName );
};
})( re.devname, re.target )
});
}
else
{
defineRule( "targetrule" + rc, {
whenChanged: re.devname,
then:
(function( devname, target, devtarget ) {
var first_run = true;
return function( newValue, devName, cellName ) {
if( first_run ) { first_run = false; return; }
log( "on '" + devname + "' change '" + target + "' (" + devtarget + ")" + "nv={} dn={} cn={}", newValue, devName, cellName );
dev[devtarget] = ! dev[devtarget];
};
})( re.devname, re.target, getTarget( re.target ) )
});
}
}
}
у меня, например, срабатывает whenChanged на вирт. устройстве, пока что одном. Никаких retained я не задавал. Срабатывает при рестарте правил. Почему оно вообще срабатывает? Можно, конечно, завалить таймаутом обработки, но это что, нормальная работа? У меня этот вирт. девайс срабатывает только по внешней команде, если ему 1 кинут, а после обработки это правило само сбрасывает значение 1 на 0. Это mosquitto глючит при вкл. правил? Проясните, пожалуйста. Конечно, грабли-костыли это хорошо, но еще лучше, когда понимаешь принцип работы.
Можно этот пример?
не знаю, даже, что это даст, но вот скрипт:
defineVirtualDevice(“GetCurrentStates”,
{
title: “GetCurrentStates”,
cells:
{
get:
{
type: “switch”,
value: false
},
data:
{
type: “text”,
value: “”
},
Current:
{
type: “text”,
value: “1”
}
}
});
defineRule(“send current states”,
{
whenChanged: “GetCurrentStates/get”,
then: function (newValue, devName, cellName)
{
if (newValue == 1)
{
log(“GetCurrentStates: правило отработало, сбрасываем значение в 0”);
dev["GetCurrentStates"]["Current"] = "12345qwert";
dev["GetCurrentStates"]["get"] = 0;
}
}
});
вот строка в бридж
topic /devices/GetCurrentStates/controls/get/on both 2 “” /client/AFDB3MCD
topic /devices/GetCurrentStates/controls/Current both 2 “” /client/AFDB3MCD
при рестарте правил москито вываливает состояние аналоговых выходов 0-10В и этот вирт девайс - 12345qwert
причем это делает москито. Я поменял в скрипте содержание, сохранил, правила рестартанул, а при рестарте все-равно шли старые значения. А когда я через морду принудительно дал команду, данные обновились и стали теперь при рестарте приходить новые. Как будто москито их запоминает, как-то выделяет и шлет при рестарте… Как это уже задолбало, то одно, то другое. День уходит на простую функцию…
Может, есть другой брокер, не знаете?
Так что, наверное, вопрос к whenChanged снимается, это не его рук дело… Ну а толку то, что снимается, система в итоге работает криво через одно место.
Действительно, непонятная логика брокера.
При перезагрузке правила повторять отправку retained-значений, а не того, что установлено в defineRules в качестве инициализирующего.
Не хватает функции обновления этих retained-значений из обновленного правила (например, если смысл перезагрузки его был как раз связан с установкой нового инициализирующего значения).
Добрый день! Есть такая проблема, предполагаем внести изменения в новом движке правил (по срокам сориентировать не могу). Вот цитата из https://wirenboard.com/wiki/index.php/Движок_правил_wb-rules_2.0:
В предыдущих версиях wb-rules значения контролов виртуальных устройств хранились только в MQTT retained, что не очень надёжно (в случае
потери питания данные могли быть легко утеряны). Начиная с версии 2.0, эти значения сохраняются также в специальное хранилище в постоянной
памяти и восстанавливаются при загрузке сценария.
Если необходимо каждый раз при перезагрузке скрипта восстанавливать строго определённое значение (т.е. не восстанавливать предыдущее сохранённое),
можно добавить в описание контрола поле forceDefault:
defineVirtualDevice("vdev", {
...
cells: {
...
mycell: {
type: "value",
value: "10",
forceDefault: true // при каждой загрузке сценария поле mycell будет получать значение 10
}
}
});
По умолчанию поле принимает значение false.
Разве этих изменений нет в текущей 1.7.* версии? По-моему уже есть…