Неочевидное поведение asSoonAs правил при сохранении правила

Здравствуйте! Уже не первый раз сталкиваюсь с такой неочевидностью, наконец дошли руки ее описать.
Версии: WirenBoard 8.4.4, wb-rules 2.36.0
Представим такую ситуацию: есть виртуальное устройство с одной ячейкой типа switch, есть 2 asSoonAs правила, которые отслеживают значение этой ячейки и выполняют функцию, если условие выстреливает.
Код для примера:

defineVirtualDevice("dev", {
  title: "Test Device",
  cells: {
    foo: {
      type: "switch",
      value: false,
    },
  },
});

function handleFooUp() {
  log.debug("Function: Foo is up");
}

function handleFooDown() {
  log.debug("Function: Foo is down");
}

defineRule("fooUp", {
  asSoonAs: function () {
    return dev["dev/foo"];
  },
  then: function () {
    log.debug("Rule: Foo is up");
    
    handleFooUp();
  },
});

defineRule("fooDown", {
  asSoonAs: function () {
    return !dev["dev/foo"];
  },
  then: function () {
    log.debug("Rule: Foo is down");

    handleFooDown();
  },
});

Вопрос следующий: почему при сохранении правила, т.е при нажатии кнопки “Save” внутри редактора правил, у меня исполняется правило asSoonAs, хотя значение не менялось?

Объясняю вопрос,
Есть правило:

defineRule("fooDown", {
  asSoonAs: function () {
    return !dev["dev/foo"];
  },
  then: function () {
    log.debug("Rule: Foo is down");

    handleFooDown();
  },
});

Топик dev/foo равен 0, я сохраняю правило и получаю в консоли вывод:

2025-12-15 14:01:22 defineRule: fooUp
2025-12-15 14:01:22 defineRule: fooDown
2025-12-15 14:01:22 Rule: Foo is down
2025-12-15 14:01:22 Function: Foo is down

То есть правило сработало (then сработало → функция выполнилась), хотя переменная dev/foo не пришла из 1 в 0, а сохраняла свое значение.

Хотелось бы понять несколько вещей в такой ситуации:

  1. Правильно ли я понимаю, что asSoonAs так работать не должно, а так работать должно только when? (Поэтому я и использую asSoonAs, т.к такого вообще не ожидаю)
  2. Как можно обойти/поправить такие срабатывания? А то всю логику более сложных скриптов я строю на свойствах правил asSoonAs, а по итогу выходят ложные срабатывания (т.е срабатывания, когда переменная, на самом деле, не менялась)
  3. Может стоит обрабатывать смену значения у переменных по другому вообще, а не через 2 asSoonAs, как в моем приведенном примере кода?

Примечания:

  1. Если я сохраню правило еще раз, то все повторится
  2. Если я поменяю значение переменной на 1, то все так же повторится при нажатии на кнопку “Сохранить”
  3. Если я уберу defineVirtualDevice из этого файла в другой, все так же повторится

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

Спасибо! Хорошо, если данные проблемы имеют шанс на решение
И хоть ссылка, что вы прикрепили, насколько я вижу, не прям затрагивает срабатывание правил определенных типов, например asSoonAs, о чем я собственно и спрашивал, я могу понять, что проблема смежная и это хорошо, что ищутся какие-то решения касаемо самого движка wb-rules

Однако, хотелось вы уточнить у вас (или коллег), можно ли граммотно как-то обойти это до тех пор, пока проблема с концами не решилась?
То есть сделать так, чтобы подобных ложных срабатываний не было; если бы вы могли привести примеры кода, то был бы благодарен, так как много раз пытался уже обойти, но обычно от этого проблем появлялось еще больше

Да, есть общие смежные ошибки при сохранении.

К сожалению не силён в JS, попробуйте использовать правила с whenChanged

1 Like

Спасибо!
Вот уже стал сам экспериментировать с whenChanged и заметил, что такой проблемы нет, кажется. Значит, пока буду оперировать им в большей части.

Приведу конечный код и вывод для референса:

defineVirtualDevice("dev", {
  title: "Test Device",
  cells: {
    foo: {
      type: "switch",
      value: false,
    },
  },
});

function handleFooUp() {
  log.debug("Function: Foo is up");
}

function handleFooDown() {
  log.debug("Function: Foo is down");
}

defineRule("fooChange", {
  whenChanged: "dev/foo",
  then: function () {
    log.debug("Rule: Foo is changed: {}", dev["dev/foo"]);

    if (dev["dev/foo"]) {
      handleFooUp();
    } else {
      handleFooDown();
    }
  }
});

Вывод (при сохранении правила кнопкой):

2025-12-15 17:14:21 defineRule: fooChange
1 Like

Это ожидаемое поведение согласно документации GitHub - wirenboard/wb-rules: Rule engine for Wiren Board

asSoonAs (edge-triggered). Просмотр edge-triggered правил (asSoonAs) осуществляется следующим образом: вызывается функция, заданная в asSoonAs. Если функция обращается хотя бы к одному неполному параметру, правило не выполняется. Если функция не обращалась к неполным параметрам и вернула истинное значение, и при этом правило просматривается первый раз, либо при предыдущем просмотре значение функции было ложным, правило выполняется.