Вопрос по правилам: как не запускать правила при первом запуске


#1

после перезагрузки контроллера часть правил запускается, потому что срабатывает onchange по сравнению с retained значениями. можно как-то отловить это и не пропускать отработку правил?


#2

Вопрос касается whenChanged?
Обработчик onchange не из wb-rules


#3

да, конечно, whenChanged


#4

whenChanged ничего не сравнивает, он просто выполняет заложенную функцию при изменении входного параметра или при перезапуске правила.
Можете на примере проиллюстрировать?


#5

да. есть радио кнопка 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 ) )
});

можно как-то отличить запуск правила при старте от запуска правила при событии?


#6

Ну на пример добавить проверку, что Current uptime больше минуты. Тогда в первую минуту после запуска правило работать не будет, за то и первое срабатывание будет проигнорировано.


#7

у меня стоит задержка 5 секунд после первого просмотра. минута много, но попробую, спасибо.


#8

Я обычно ставлю переменную-флаг при начальной инициализации программы, который при первом выполнении функции сбрасывается.

var initial = true;
.
.
.
if (initial) {  // если выполнение тела произошло по причине первоначальной загрузки сбрасываем флаг
initial = false;
} else {      // если выполнение кода произошло когда инициализация уже прошла, то выполняем действие
dev[devtarget] = ! dev[devtarget]; 
}
.
.

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


#9

у меня в любом случае whanChanged генерится в обертке, добавить туда проверку не сложно. но как-то хотелось бы документированно понимать, что это вызов не по событию, а по first run.


#10

Скажите пожалуйста что за обертку используете для генерации кода?
В чем ее преимущество?
Где про этот способ можно получить информацию?


#11

обертка - это генерация правил на основе массива данных с описанием кто на что и как реагирует. просто мне так было удобно.

почитать - это функции JavaScript + clusure.


#12

На странице описания движка правил есть немного про обертки:
https://wirenboard.com/wiki/index.php/Движок_правил_wb-rules
в разделе “Создание однотипных правил”.

Обертка (closure) в общем случае выглядит так:
(function() {
// код
})();

Ну, вот ссылка для почитать:
https://www.w3schools.com/js/js_function_closures.asp


#13

вот чуть более подробно с кусочками кода.

// 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 ) )
      });	
    }
  }
}