5
правок
(совместимость при обновлении до 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> | ||
2019-01-05 17:28:42 myFuncTwo called | |||
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--> |
правок