Неожиданная особенность движка правил. Видимо, стоит добавить в вики.
Все глобальные переменные ОБЩИЕ между скриптами. Алиасы (defineAlias) также создают глобальные переменные. Т.е. два defineAlias или объявление глобальной переменной в разных скриптах могут конфликтовать. Нужно это учитывать при написании правил (например, делать префикс соответствующий скрипту). Долгое время думал, что это странные глюки движка, а все оказалось просто.
У меня в двух скриптах были конструкции типа defineAlias(“sensor”, “wb-mr11_1/Input 2”) (естественно входы были разные).
/Детектор присутстствия. В качестве детектора используется Bluetooth beacon с приёмником. Вкл. на D1_IN WB.
При приближении/удалении метки Bluetooth приёмник входит в неустойчивое состояние и появляется подобие дребезга контактов на его выходе.
И в зоне уверенного приёма наблюдаются кратковременные потери метки. (Логировать эти потери хочется, но как это сделать во время задерки не знаю,
полагаю надо использовать таймер с другой логикой, прерыванием, или сделать свой таймер.)
Следовательно надо организовать задерку включения/выключения. (В принципе достаточно и RC ценочки…)
Пример с задержкой http://contactless.ru/wiki/index.php/Движок_правил_wb-rules
см. “Детектор движения c таймаутом”. /
var DelayIn = 51000; //Задержка включения реле при появлении метки.
var DelayOut = 101000;//Задержка выключения реле при пропадании метки.
var timer_3_id = null;//Организация таймера.
var FirstRelayStatus = 0;//… для экспериментов.
var RelayStatus = FirstRelayStatus;//При старте делаю реле выключенным, для этого этот статус присваиваем самому реле см. строку 26,50
//ввёл статус для присвоения его нашему реле после перезагрузки WB, т.е. метка в зоне - реле включится, метка вне зоны - реле выключено.
defineRule(“I’m home IN”, {
when: function(){
return dev[“wb-gpio”][“D1_IN”] == 1// Когда появилась метка (начался дребезг)…
},
then: function(){
if (timer_3_id) {clearTimeout(timer_3_id);} //Организация таймера.
dev["wb-gpio"]["Relay_1"] = RelayStatus;//... статус RelayStatus = 0 присваиваем нашему реле...
timer_3_id = setTimeout(function() { //...запукаем таймер с задеркой DelayIn по истечение которой выполняем:
timer_3_id = null;// 1.Организация таймера.
if(dev["wb-gpio"]["D1_IN"] == 1){//2.Проверяем осталась ли метка в зоне приёма
if(RelayStatus == 0){//3. Лишний раз не хочу без толку включать уже включенное реле...
RelayStatus = !RelayStatus;//... но когда реле выключено меняем статус на будущее и
dev["wb-gpio"]["Relay_1"] = RelayStatus;//включаем реле.
}
}
},
DelayIn);// Вот само значение задержки.
}
});
defineRule(“I’m home OUT”, {
when: function(){
return dev[“wb-gpio”][“D1_IN”] == 0//Когда пропала метка (начался дребезг): ждём подольше, проверяем статус реле и выключаем реле.
},
then: function(){
if (timer_3_id) {clearTimeout(timer_3_id);}
ну там целая математика! может можно как-то привязать заход и восход к своему часовому поясу? и не в каждом правиле, а единоразова записать данные и по ним уже строить остальные сценарии!
При старте движка правил и раз в сутки (скажем, в полночь: when: cron("0 0 * * *")) определяем время восхода и заката на сегодня - как угодно, хоть стащив curl’ом страничку одного из многочисленных сайтов с этой информацией и выдрав из нее время sed’ом, хоть по предварительно забитой таблице.
Пересчитываем в миллисекунды, вычитаем текущее время, и соответственно выставляем два таймера через startTimer. В обработчиках таймеров делаем нужные действия.
Например так (координаты в запросе для Москвы, выдает время в миллисекундах с 00:00 GMT+3). Получаем данные curl’ом с http://sunrise-sunset.org/api, с помощью jq достаем из результата в формате json время восхода и заката и приводим в полезный для нас вид. $ curl -s 'http://api.sunrise-sunset.org/json?lat=37.61778&lng=55.75583&formatted=0' | jq -r '.results | (.sunrise, .sunset) | (.[11:13] | tonumber) as $h | (.[14:16] | tonumber) as $m | (($h+3)*60 + $m) * 60 * 1000' 16500000 65160000
(WB под рукой нет, там довольно старая версия jq и синтаксис может несколько отличаться).
Можно эту команду вызвать из движка правил с помощью spawn с опцией captureOutput и что-то с этими числами сделать полезное.
Помогите, пожалуйста, сделать правило для мигалки! Я написал, чтобы через 10 секунд включалась лампочка и мне нужно, чтобы она отключилась на 3 секунды, а затем снова включилась на 5 секунд. и так 15 раз. после чего обнулить таймер и
выключить лампочку.
Прочитайте пожалйуста первое сообщение темы и пропустите код через http://jsbeautifier.org/ , прежде чем постить, если он у вас отформатирован по левому краю.
Про двойные и долгие нажатия: можно поэкспериментировать с правилами. Сделайте правило с whenChanged на канал кнопки, добавьте отладочный вывод на срабатывание (log). Он должен выводиться на каждое нажатие кнопки, хоть и с небольшой (<~100ms) задержкой. Дальше можете в правиле завести глобальную переменную-счётчик и сбрасывать её значение по таймеру.
Как-то так (код не проверял):
(function() { //don't touch this line
var button_counter = 0;
var counter_clear_timer_id = null;
defineRule( "on_button_press", {
whenChanged: "wb-gpio/A1_IN",
then: function (newValue, devName, cellName) {
// если поймали нажатие, увеличиваем счётчик
if (newValue) {
button_counter += 1;
}
// счётчик равен двум, значит было двойное нажатие
if (button_counter == 2) {
log("double press!");
}
// после каждого нажатия сбрасываем таймер (удяляем старый)
if (counter_clear_timer_id) {
clearTimeout(counter_clear_timer_id);
}
// и взводим новый таймер, который сбросит счётчик через 2 секунды
counter_clear_timer_id = setTimeout(function() {
button_counter = 0;
}, 2000);
}
});
})();
Обращаюсь ко всем опытным и не очень пользователям контроллера! давайте здесь обменяемся архивом правил у кого что работает? от себя готов выложить свой архивчик с правилами и комментариями что за что отвечает.