Wb-jscript
Введение
Задача автоматизации - это упростить человеку жизнь. “Умный дом” - это, конечно, частный случай. Но полезный. Попытаемся применить скрипты контроллера WB (Wiren Board 6) для управления. Текст ниже предназначен тем, кто не имеет опыта программирования, но хочет научиться.
Используемое оборудование
В названиях “DI” - Digital Input “DO” - Output соответственно.
Программирование
Скрипт
Скриптом называется обыкновенный текстовый файл. Для того чтобы он выполнялся движком wb-rules нужно выполнить два условия:
- Имя файла должно заканчиваться на .js
- Файл должен располагаться в каталоге /etc/wb-rules
Веб-интерфейс контроллера имеет встроенный редактор скриптов, доступный из его главного меню по ссылке "Rules"
Выполнение скриптов
Только что созданный скрипт после нажатия кнопки "Save" (и при запуске wb-rules) сразу же выполнится. То есть, будут созданы все переменные, правила, таймеры. И дальнейшее поведение скрипта будет определяться только событиями, как внешними (изменения состояния устройств, на которые "подписаны" правила) так и таймерами.
Переменные
Где хранить значения, а также строки и все остальное, включая ссылки на объекты? Именно в переменных. Можно представить каждую переменную как коробку. Подписанную коробку. Подпись - это имя переменной, а содержимое коробки - это ее значение.
Кроме "простых" переменных еще используются массивы. Массив - это "стопка" значений, которые определяются одним именем переменной и "номером" в стопке. Еще есть структуры (объекты), но о них - позже.
Важно: JS, по умолчанию, при присвоении переменной одного типа значения другого типа - меняет тип переменной. Иногда это вызывает неожиданное поведение.
Типы переменных в JS:
- String: представляет строку
- Number: представляет числовое значение
- Boolean: представляет логическое значение true или false.
- undefined: указывает, что значение не установлено
- null: указывает на неопределенное значение
Ниже попробуем создать первый скрипт и поймем значение типов.
Логи
Использование логов для отладки - бесценно. Иметь возможность в любом месте скрипта записать текущее значение переменной, состояние устройства очень помогает. Логи в WB двух типов - с записью в файл (/var/log/mesages) и в mqtt топик. Лог вызывается такой командой:
log.{debug,info,warning,error}(fmt, [arg1 [, ...]])
Научимся ими пользоваться, а заодно, и напишем первый скрипт. В меню “Rules” нажимаем “New” и в поле для имени, вверху пишем “logs_and_vars_test.js” И в поле скрипта вставляем:
//logs_and_vars_test.js
//Просто комментарий. Начинается с двойного слеша "//"
var testvar1; //Переменная "testvar1" Ничего не присваиваем при объявлении(создании), "пустая"
log.info("Тип и значение переменной testvar1", typeof(testvar1), testvar1); // Тип (и значение) undefined
testvar1 = "yellow submarine"; // Присвоим строку
log.info("Тип и значение переменной testvar1", typeof(testvar1), testvar1);
testvar1 = 42; //Присвоим число
log.info("Тип и значение переменной testvar1", typeof(testvar1), testvar1);
testvar1 = false; //Булево (true/false)
log.info("Тип и значение переменной testvar1", typeof(testvar1), testvar1);
testvar2 = "red submarine"; //Сразу при объявлении присваиваем значение
log.info("Тип и значение переменной testvar2", typeof(testvar2), testvar2);
testvar1 = testvar2; //Тип testvar1 - булево. testvar2 - строка
log.info("Тип и значение переменной testvar1", typeof(testvar1), testvar1); // при присвоении тип поменялся.
Не забывайте пустую строку в конце скрипта.
Прежде чем сохранять, давайте зададимся вопросом “как же логи читать?”
Два (даже три) способа.
- Самый простой: нажимаем на кнопку с символом гаечного ключа. Она находится в нижнем правом углу окна редактора скриптов.
Нажимаем - выдвигается консоль. Пока пустая, но после нажатия кнопки "Save" сюда выводятся сообщения.
- Чуть сложнее: открываем ssh сессию на контроллере и вводим
tail -f /var/log/messages |grep wb-rules
Команда просматривает файл и при появлении в нем строчек с "wb-rules" Нажмем опять кнопку "Save" - выводит их в stdout (на экран)
Чтобы кнопка "Save" стала вновь активной, надо что-нибудь изменить в окне редактора. Например, добавить пробел.
Можно убедиться, что скрипт выполняется и даже совершает полезное действие - выводит сообщения.
Как определить тип
Функция
typeof
принимает в качестве аргумента (то, что в скобках) переменную и возвращает нам ее тип
Если выполнить код:
variable1 = "yellow submarine";
variable2 = typeof(variable1);
То
variable2
будет иметь тип "string" и значение "yellow submarine"
2do: Дописать про форматирование вывода логов вида log("Инфо текст {} {} {}".format(var1, var2, var3));
Условия
Очень часто нужно что-нибудь с чем-то сравнить. Например, температуру с желаемой (с уставкой на тайном языке наладчиков-проектировщиков). Напишем простой пример, в котором сравним два значения.
//if_then.js
//Просто комментарий. Начинается с двойного слеша "//"
var t_real =20; //Переменная в которой будет хранитьтся измеренная (реальная) температура
var t_ust = 22; //Переменная в которой хранится уставка (желаемая) температура
if (t_real > t_ust) { //В "()"скобках - условие.
log.info("Температура", t_real, "БОЛЬШЕ уставки", t_ust);
}
Не забывайте пустую строку в конце скрипта.
Использование
Сама конструкция условий основана на простой вещи: Если то, что в круглых скобках после оператора "if" верно - код в "{}" выполнитя Надо отвлечься на понятие - "верно" то есть истина, true Если мы говорим о условиях - сразу перечислим самые распростарненные:
- > - больше true когда ( 5 > 3 )
- < - меньше true когда ( 1 < 3 )
- >= - больше или равно true когда ( 5 >= 3) и когда ( 5 >= 5 )
- == - равно true когда ( 5 == 5) Внимание! про == ниже
- || - ИЛИ true когда ( true || true ), кода ( true || false ), хоть одно из условий true
- && - И true когда ( true && true ), кода оба true
И про "равно":
//if_then_eq.js
var test1 = 2;
var test2 = 3;
if (test1 = test2) {
log.info("Выполняется! А почему?!");
}
log.info("test1", test1);
log.info("test2", test2);
Все просто. Для того чтобы определить истинность условия компилятор выполняет выражение в скобках. Первой переменной можно присвоить вторую? Можно! Все, условие выполнено. Поэтому не надо использовать "=" в условиях. Только "==".
Что делать, когда надо выполнять разные действия в зависимости от условия? Оператор elseсинтаксис ниже:
//if_then_else.js
var t_real = 18; //Переменная в которой будет хранитьтся измеренная (реальная) температура
var t_ust = 22; //Переменная в которой хранится уставка (желаемая) температура
if (t_real > t_ust) { //В "()"скобках - условие.
log.info("Температура", t_real, "БОЛЬШЕ уставки", t_ust);
}
else { //Если условие НЕ выполняется
log.info("Температура", t_real, "МЕНЬШЕ уставки", t_ust);
}
Отладка
Если условие не работает так как нам надо - то:
- Проверяем тип переменных перед условием
//if_then_types.js
var test1 = 4;
var test2 = "aaa"; //Переменная тип string
log.info("перед условием");
if (test1 > test2) { //В "()"скобках - условие.
log.info("Больше");
}
Сравнивать переменные разных типов - некорректно. Выведем типы чтобы оценить возможность сравения:
//if_then_types_1.js
var test1 = 4;
var test2 = "aaa"; //Переменная тип string
log.info("перед условием. Тип test1", typeof(test1), "Тип test2", typeof(test2));
if (typeof(test1) !== typeof(test2)) { //А вот типы сравнивать - можно.
log.info("Типы разные");
}
else {
log.info("Типы одинаковые");
}
if (test1 && test2) { //В "()"скобках - условие.
log.info("Больше");
}
"!" - это модификатор "НЕ" для логических условий. !true==false