Движок правил 2.0

Просьба: в этом топике обсуждаются только нововведения и ошибки, обнаруженные при тестировании wb-rules 2.0. Для вопросов по программированию сценариев на стабильных версиях wb-rules существуют другие топики.


Доброго времени, форумчане!

К релизу готовится движок правил wb-rules версии 2.0, и нам нужны бета-тестеры. В обновлённой версии добавлен набор нововведений, а также исправлены некоторые обнаруженные ошибки.

Нововведения:

  • Система модулей (с использованием require(), похожая на оную в Node.js);
  • Полная изоляция правил;
  • Пользовательское постоянное хранилище (Persistent Storage);
  • Сохранение состояния виртуальных устройств в энергонезависимой памяти;
  • Анонимные правила (теперь не обязательно задавать имя в defineRule());
  • Управление правилами (можно разрешать/запрещать выполнение правил);

Исправления (основные):

  • Обнаружение ошибок в именах виртуальных устройств (недопустимые символы);
  • Обнаружение переопределений именованных правил и виртуальных устройств;
  • Удаление и пересоздание сценария (топик)
  • UPD: зависания на “тяжёлых” сценариях

Подробнее о нововведениях можно почитать здесь.

Скачать пакет для установки на контроллер можно с Github (ищите версию 2.0~betaN с максимальным N).

Вопросы, пожелания, предложения и баг-репорты приветствуются!

(UPD: На всякий случай напомню, что бета-версия не подходит для использования на критически важных объектах до выхода стабильной версии.)

Я вот аккуратненько спрошу тут — а почему собственно для правил используется не Node.js? Когда я занялся реализацией поддержки эппловского HomeKit (с помощью homebridge) в WB, было очень странно (и довольно мучительно, по правде сказать) ставить ноду в дополнение к вашему движку.

  1. Node.js - очень прожорливая штука.
  2. В Node.js используется V8, который (больше) не поддерживает архитектуру процессора, который стоит в текущем поколении Wiren Board.

Отчёт о тестировании “удаления и пересоздания сценариев”
Кратко: Проблема не решилась. Всё равно приходится перезапускать движок правил после каждого удаления.
Подробно:
Для добавления-удаления сценария использую следующую комбинацию виртуального устройства и правила:

defineVirtualDevice("switch_script_air_humidity", {
    title: "Switch script",
    cells: {
	enabled: {
	    type: "switch",
	    value: false
	},
    }
});

defineRule("control_script_air_humidity", {
  whenChanged: "switch_script_air_humidity/enabled",
  then: function (newValue, devName, cellName)  {
    log("Changed");
    if(newValue) {
            runShellCommand("cp /mnt/data/etc/rules-greenhouses/air_humidity.js /mnt/data/etc/wb-rules");
     	log("Правило air_humidity активировано");
    } else {
    	runShellCommand("rm -f /mnt/data/etc/wb-rules/air_humidity.js");
            log("Правило air_humidity деактивировано");
    }
  }
});

Циклы тестирования:

Без перезапуска после каждого удаления сценария:

  1. Корректно отработали два цикла добавления-удаления. Третье добавление не произошло.
    После первого теста движок перезапущен в ручную (service wb-rules restart).
  2. Корректно отработал один цикл добавления-удаления. Второе добавление не произошло.
    После второго теста движок перезапущен в ручную.
  3. Корректно отработал один цикл добавления-удаления. Второе добавление не произошло.

С перезапуском после каждого удаления ( добавил в код runShellCommand("service wb-rules restart"); ):

  1. Корректно отработали более четырёх циклов добавления-удаления.

Спасибо за репорт. Будем искать ошибку.

Помогите понять, как обращаться к переменным глобального хранилища из других сценариев?

пока получилось только так:
global.__proto__.ps = new PersistentStorage(“my-storage”, {global: true});

Так из других сценариев видна переменная ps с ссылкой на хранилище. Но так и параметр global не нужен. Значит точно есть другой, правильный способ.

Доброго времени.

Обращаться к одному и тому же хранилищу можно, создавая в разных сценариях объекты PersistentStorage с одним и тем же именем хранилища. Объекты вполне могут быть локальными для сценария.

Флаг global: true как раз нужен для того, чтобы хранилище было доступно под этим именем во всех файлах сценариев.

Таким образом, во всех сценариях такая конструкция обеспечит доступ к одному и тому же хранилищу:

var ps = new PersistentStorage("my-storage", {global: true});

ну, это, конечно первое что пришло на ум, но не получилось. может я не верно делаю?

var ps2 = PersistentStorage(“my-storage”);

не находит так переменные

Обязательно добавьте {global: true} в список аргументов.

Аргумент нужен не только при создании но и при доступе??

И подскажите, как теперь лучше делать глобальные функции? каждой свой модуль делать что-ли?

Создание и доступ здесь сильно не различаются; есть пространство имён глобальных хранилищ и для каждого сценария есть локальное. Если хранилище не существовало до вызова new PersistentStorage(), оно будет создано. Так что да, для глобального хранилища аргумент нужен при всех обращениях.

Глобальные фукнции можно сложить в один модуль, к примеру:

/etc/wb-rules-modules/myfunctions.js

exports.myfunc1 = function() {
    ...
};

exports.myfunc2 = function() {
   ...
};

и т.д.

Да, действительно так работает. Хотя, вроде, изначально так и пробовал…

А насколько критично, если я все-же сделаю ссылку на хранилище глобальной? Пока видится, что так удобнее будет.

Не могу вам запретить делать так :wink:

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

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

Спасибо, теперь прояснилось :slight_smile:

но теперь с функциями засада: когда пишу в скрипте: var fun = require(“my_function”);

пишет ошибку:Script error: SyntaxError: parse error (line 1)
duk_js_compiler.c:3391
require native strict preventsyield

модуль в папке wb-rules-modules с именем my_function.js что не так?

просто у вас расположение модулей по умолчанию указано:
/etc/wb-rules-modules

а в примере, указан путь: /etc/wb-rules/modules/myModule.js

С расположением всё в порядке, должна быть директория /etc/wb-rules-modules/.

Скорее всего, у вас есть ошибка в коде модуля или сценария, проверьте внимательно.

UPD: В документации действительно местами опечатки, сейчас исправлю.

понял в чем была проблема: при добавлении в модуле комментариев, начинаются проблемы. Проверьте у себя, плз.
подробнее о глюке:
есть скрип и модуль без комментов. Все работает нормально. Добавляю в модуль коммент (// или /* */ не важно), сохраняю. Потом пересохраняю скрипт и получаю ошибку синтаксиса. Удаляю коммент, перезапускаю wb-rules и все ок.

Это очень странно, комментарии работают.

глюк стабильный. Возможно из-за кодировки, так-как файл создаю в notepad++ и только сейчас заметил, когда зашёл в редактор через webui, что с русскими беда. Вроде исправил кодировки. Но глюк остался, даже без русских символов. Завтра попробую создать модуль через консоль и проверить.

Да, это вполне возможно. По идее, если всё делать в utf-8, должно работать без проблем.