Движок правил wb-rules: различия между версиями

Обновление до версии 1.7
(совместимость при обновлении до 2.2)
(Обновление до версии 1.7)
Строка 22: Строка 22:
использования для этой цели числовые значения (1, 0) в версии движка 2.2 операция присваивания не выполнится и завершится с ошибкой.
использования для этой цели числовые значения (1, 0) в версии движка 2.2 операция присваивания не выполнится и завершится с ошибкой.
Корректный способ — устанавливать булевы значений (true/false)
Корректный способ — устанавливать булевы значений (true/false)
При возникновении подобной проблемы в логах можно видеть подобные записи:
<pre>
ERROR: control wb-mr3_30/K1 SetValue() error: can't convert control value '1' (type float64) to datatype 'switch'
ERROR: control system/Reboot SetValue() error: can't convert control value '1' (type float64) to datatype 'pushbutton'
</pre>


Вместо:
Вместо:
Строка 33: Строка 39:
</syntaxhighlight>
</syntaxhighlight>


При возникновении подобной проблемы в логах можно видеть подобные записи:
=== Обновление до версии 1.7 ===
 
Начиная с версии wb-rules 1.7, локальные переменные и функции, объявленные в файле сценария не видны в других сценариях.
Таким образом, каждый сценарий может определять свои функции и переменные без риска изменить поведение других сценариев.
 
В качестве примера приведём два сценария, одновременно запускаемых в движке правил. Каждый сценарий определяет переменные и функции.
В предыдущих версиях wb-rules обращение к переменной, изменяемой в нескольких файлах сценариев, может привести к неопределённому поведению.
В версиях, начиная с 1.7, поведение строго определено и такое же, как будто сценарий единственный в системе.
 
Сценарий 1 (rules1.js):
<syntaxhighlight lang="ecmascript">
var test1 = 42;
 
setInterval(function myFuncOne() {
    log("myFuncOne called");
    log("test1: {}", test1);
    log("test2: {}", test2);
}, 5000);
</syntaxhighlight>
 
Сценарий 2 (rules2.js):
<syntaxhighlight lang="ecmascript">
var test1 = 84;
var test2 = "Hello";
 
setInterval(function myFuncTwo() {
    log("myFuncTwo called");
    log("test1: {}, test2: {}", test1, test2);
}, 5000);
</syntaxhighlight>
 
Было:
<pre>
2019-01-05 17:29:50 myFuncTwo called
2019-01-05 17:29:50 test1: 84, test2: Hello
2019-01-05 17:29:50 myFuncOne called
2019-01-05 17:29:50 test1: 84
2019-01-05 17:29:50 test2: Hello
</pre>
 
Стало:
<pre>
<pre>
ERROR: control wb-mr3_30/K1 SetValue() error: can't convert control value '1' (type float64) to datatype 'switch'
2019-01-05 17:28:42 myFuncTwo called
ERROR: control system/Reboot SetValue() error: can't convert control value '1' (type float64) to datatype 'pushbutton'
2019-01-05 17:28:42 test1: 84, test2: Hello
2019-01-05 17:28:42 myFuncOne called
2019-01-05 17:28:42 test1: 42
2019-01-05 17:28:42 ECMAScript error: ReferenceError: identifier 'test2' undefined
duk_js_var.c:1232
myFuncOne /etc/wb-rules/rules1.js:6 preventsyield
</pre>
</pre>
Возможные способы решения проблемы:
'''Способ 1'''
Самый простой способ: перенести всю логику, которая использует доступ к переменной в другм файле в тот же файл, где определена переменная. Т.е. на примере приведённых выше правил нужно перенести всё в один файл rules1.js
<syntaxhighlight lang="ecmascript">
var test1 = 42;
var test2 = "Hello";
setInterval(function myFuncTwo() {
    log("myFuncTwo called");
    log("test1: {}, test2: {}", test1, test2);
}, 5000);
setInterval(function myFuncOne() {
    log("myFuncOne called");
    log("test1: {}", test1);
    log("test2: {}", test2);
}, 5000);
</syntaxhighlight>
'''Способ 2'''
Следующий способ заключается в использовании глобального постоянного хранилища (PersistentStorage) ====
'''Внимание:''' при использовании глобальных постоянных хранилищ может произойти совпадение имён, в этом случае возможно труднообнаруживаемое нарушение поведения.
Вышеприведённый пример можно исправить следующим образом:
Сценарий 1 (rules1.js):
<syntaxhighlight lang="ecmascript">
var test1 = 42;
var ps = new PersistentStorage("my-global-storage", {global: true});
ps.test1 = test1;
setInterval(function myFuncOne() {
    log("myFuncOne called");
    log("test1: {}", test1);
    log("test2: {}", ps.test2);
}, 5000);
</syntaxhighlight>
Сценарий 2 (rules2.js):
<syntaxhighlight lang="ecmascript">
var test2 = "Hello";
var ps = new PersistentStorage("my-global-storage", {global: true});
ps.test2 = test2;
setInterval(function myFuncTwo() {
    log("myFuncTwo called");
    log("test1: {}, test2: {}", ps.test1, test2);
}, 5000);
</syntaxhighlight>
'''Способ 3'''
"Грязный" способ, который использует прототип глобального объекта - использовать этот способ не рекомендуется из-за возможного замусоривания глобального пространства пользовательскими данными.
Исправленная версия:
Сценарий 1 (rules1.js):
<syntaxhighlight lang="ecmascript">
global.__proto__.test1 = 42;
setInterval(function myFuncOne() {
    log("myFuncOne called");
    log("test1: {}", global.__proto__.test1);
    log("test2: {}", global.__proto__.test2);
}, 5000);
</syntaxhighlight>
Сценарий 2 (rules2.js):
<syntaxhighlight lang="ecmascript">
global.__proto__.test2 = "Hello";
setInterval(function myFuncTwo() {
    log("myFuncTwo called");
    log("test1: {}, test2: {}", global.__proto__.test1, global.__proto__.test2);
}, 5000);
</syntaxhighlight>


== Как создавать и редактировать правила == <!--T:3-->
== Как создавать и редактировать правила == <!--T:3-->
5

правок