Движок правил wb-rules: различия между версиями
Строка 87: | Строка 87: | ||
==== Правило для статуса питания ==== | |||
[https://github.com/contactless/wirenboard/blob/master/system_rules/rules/power_status.js Правило] создаёт виртуальное устройство, которое сообщает текущий статус питания. В качестве входных данных используется два канала АЦП: измерение напряжения на аккумуляторе и измерение входного напряжения. | |||
Реализована следующая логика: | |||
1) Если входное напряжение меньше напряжение на аккмуляторе, то значит плата питается от аккумулятора. В этом случае, также отображается 0V в качестве входного напряжения. | |||
2) Если входное напряжение больше напряжения на аккумуляторе, то плата работает от внешнего источника питания. В качестве входонго напряжения отображается измерение с канала Vin. | |||
Для иллюстрации правила используют два разных способа срабатывания: по изменению значения контрола (правило _system_track_vin) и по изменению значения выражения (два других). | |||
<pre> | |||
defineVirtualDevice("power_status", { | |||
title: "Power status", // | |||
cells: { | |||
'working on battery' : { | |||
type : "switch", | |||
value : false, | |||
readonly : true | |||
}, | |||
'Vin' : { | |||
type : "voltage", | |||
value : 0 | |||
} | |||
} | |||
}); | |||
defineRule("_system_track_vin", { | |||
whenChanged: "wb-adc/Vin", | |||
then: function() { | |||
if (dev["wb-adc"]["Vin"] < dev["wb-adc"]["BAT"] ) { | |||
dev["power_status"]["Vin"] = 0; | |||
} else { | |||
dev["power_status"]["Vin"] = dev["wb-adc"]["Vin"] ; | |||
} | |||
} | |||
}); | |||
defineRule("_system_dc_on", { | |||
asSoonAs: function () { | |||
return dev["wb-adc"]["Vin"] > dev["wb-adc"]["BAT"]; | |||
}, | |||
then: function () { | |||
dev["power_status"]["working on battery"] = false; | |||
} | |||
}); | |||
defineRule("_system_dc_off", { | |||
asSoonAs: function () { | |||
return dev["wb-adc"]["Vin"] <= dev["wb-adc"]["BAT"]; | |||
}, | |||
then: function () { | |||
dev["power_status"]["working on battery"] = true; | |||
} | |||
}); | |||
</pre> | |||
=== Отправка команд по RS-485 === | === Отправка команд по RS-485 === |
Версия 19:59, 5 мая 2015
Статья в процессе наполнения, полная документация доступна здесь.
Примеры
Системные правила
Некторые правила поставляются с системой правил по-умолчанию в пакете wb-rules-system.
Полный список правил в репозитории.
Некоторые примеры:
Правило для пищалки
Правило создаёт виртуальное устройство buzzer с ползунками для регулировки громкости и частоты, а также кнопкой включения звука.
defineVirtualDevice("buzzer", { title: "Buzzer", // cells: { frequency : { type : "range", value : 3000, max : 7000, }, volume : { type : "range", value : 10, max : 100, }, enabled : { type : "switch", value : false, }, } }); // setup pwm2 runShellCommand("echo 2 > /sys/class/pwm/pwmchip0/export"); function _buzzer_set_params() { var period = parseInt(1.0 / dev.buzzer.frequency * 1E9); var duty_cycle = parseInt(dev.buzzer.volume * 1.0 / 100 * period * 0.5); runShellCommand("echo " + period + " > /sys/class/pwm/pwmchip0/pwm2/period"); runShellCommand("echo " + duty_cycle + " > /sys/class/pwm/pwmchip0/pwm2/duty_cycle"); }; defineRule("_system_buzzer_params", { whenChanged: [ "buzzer/frequency", "buzzer/volume", ], then: function (newValue, devName, cellName) { if ( dev.buzzer.enabled) { _buzzer_set_params(); } } }); defineRule("_system_buzzer_onof", { whenChanged: "buzzer/enabled", then: function (newValue, devName, cellName) { if ( dev.buzzer.enabled) { _buzzer_set_params(); runShellCommand("echo 1 > /sys/class/pwm/pwmchip0/pwm2/enable"); } else { runShellCommand("echo 0 > /sys/class/pwm/pwmchip0/pwm2/enable"); } } });
Правило для статуса питания
Правило создаёт виртуальное устройство, которое сообщает текущий статус питания. В качестве входных данных используется два канала АЦП: измерение напряжения на аккумуляторе и измерение входного напряжения.
Реализована следующая логика:
1) Если входное напряжение меньше напряжение на аккмуляторе, то значит плата питается от аккумулятора. В этом случае, также отображается 0V в качестве входного напряжения. 2) Если входное напряжение больше напряжения на аккумуляторе, то плата работает от внешнего источника питания. В качестве входонго напряжения отображается измерение с канала Vin.
Для иллюстрации правила используют два разных способа срабатывания: по изменению значения контрола (правило _system_track_vin) и по изменению значения выражения (два других).
defineVirtualDevice("power_status", { title: "Power status", // cells: { 'working on battery' : { type : "switch", value : false, readonly : true }, 'Vin' : { type : "voltage", value : 0 } } }); defineRule("_system_track_vin", { whenChanged: "wb-adc/Vin", then: function() { if (dev["wb-adc"]["Vin"] < dev["wb-adc"]["BAT"] ) { dev["power_status"]["Vin"] = 0; } else { dev["power_status"]["Vin"] = dev["wb-adc"]["Vin"] ; } } }); defineRule("_system_dc_on", { asSoonAs: function () { return dev["wb-adc"]["Vin"] > dev["wb-adc"]["BAT"]; }, then: function () { dev["power_status"]["working on battery"] = false; } }); defineRule("_system_dc_off", { asSoonAs: function () { return dev["wb-adc"]["Vin"] <= dev["wb-adc"]["BAT"]; }, then: function () { dev["power_status"]["working on battery"] = true; } });
Отправка команд по RS-485
Для примера отправим команду устройству на порт /dev/ttyNSC0 (неоптоизолированный RS-485 на Wiren Board 4). Для этого будем использовать движок правил и возможность выполнения произвольных шелл-команд. Подробнее см. в документации.
С помощью движка правил создадим виртуальное устройство с контролом типа switch (переключатель).
При включении переключателя будем отправлять команду (уст. Яркость кан. 00=0xff) для Uniel UCH-M141:
FF FF 0A 01 FF 00 00 0A
При выключении переключателя будем отправлять команду (уст. Яркость кан. 00=0x00) для Uniel UCH-M141:
FF FF 0A 01 00 00 00 0B
1. Настройка порта
Для настройки порта /dev/ttyNSC0 на скорость 9600 надо выполнить следующую команду
stty -F /dev/ttyNSC0 ospeed 9600 ispeed 9600 raw clocal -crtscts -parenb -echo cs8
2. Отправка команды
Отправка данных делается следующей шелл-командой:
/usr/bin/printf '\xFF\xFF\x0A\x01\xD1\x06\x00\xE2' >/dev/ttyNSC0
где "\xFF\xFF\x0A\x01\xD1\x06\x00\xE2" - это запись команды "FF FF 0A 01 D1 06 00 E2".
3. Создадим в движке правил новый файл с правилами
/etc/wb-rules/rs485_cmd.js
Файл можно редактировать с помощью vim, nano или mcedit в сеансе ssh на устройстве, либо залить его с помощью SCP.
root@wirenboard:~# mcedit /etc/wb-rules/rs485_cmd.js
4. Описываем в файле виртуальный девайс
defineVirtualDevice("rs485_cmd", { title: "Send custom command to RS-485 port", cells: { enabled: { type: "switch", value: false }, } });
5. Перезапускаем wb-rules и проверяем работу
root@wirenboard:~# /etc/init.d/wb-rules restart root@wirenboard:~# tail -f /var/log/messages
В логе не должно быть сообщений об ошибке (выход через control-c)
В веб-интерфейсе в разделе Devices должно появиться новое устройство "Send custom command to RS-485 port".
6. Добавим функцию для конфигурирования порта.
function setup_port() { runShellCommand("stty -F /dev/ttyNSC0 ospeed 9600 ispeed 9600 raw clocal -crtscts -parenb -echo cs8"); }
7. Опишем правила на вклчение и выключение переключателя
defineRule("_rs485_switch_on", { asSoonAs: function () { return dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\xff\\x00\\x00\\x0a' > /dev/ttyNSC0"); } }); defineRule("_rs485_switch_off", { asSoonAs: function () { return !dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\x00\\x00\\x00\\x0b' >/dev/ttyNSC0"); } });
Обратите внимание на двойное экранирование.
7. Собираем всё вместе
Полное содержимое файла с правилами:
root@wirenboard:~# cat /etc/wb-rules/rs485_cmd.js defineVirtualDevice("rs485_cmd", { title: "Send custom command to RS-485 port", cells: { enabled: { type: "switch", value: false }, } }); function setup_port() { runShellCommand("stty -F /dev/ttyNSC0 ospeed 9600 ispeed 9600 raw clocal -crtscts -parenb -echo cs8"); } defineRule("_rs485_switch_on", { asSoonAs: function () { return dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\xff\\x00\\x00\\x0a' > /dev/ttyNSC0"); } }); defineRule("_rs485_switch_off", { asSoonAs: function () { return !dev.rs485_cmd.enabled; }, then: function() { runShellCommand("/usr/bin/printf '\\xff\\xff\\x0a\\x01\\x00\\x00\\x00\\x0b' >/dev/ttyNSC0"); } });