Понятно. Спасибо огромное. Потихоньку начинают “осмысляться” непонятные “кракозяблы” на импортном языке… Интересно., захватывает … Но меня прямо " с корнем выдирают" из-за компа. (Занимаюсь на работе…) Придётся пока на этом остановиться. Продолжу попозже. Ещё раз огромное спаибо за ликбез…
До встречи !
Спасибо всем за помощь и понимание. Сегодня таки заработал виртуальный выключатель правила. Код примерно такой:
// Включение / выключение правила выключателем на панели Devices
// Создаём виртуальное устройство - выключатель.
defineVirtualDevice("simple_test", {
title: "Simple test",
cells: {
enabled: {
type: "switch",
value: false
},
}
});
defineRule("heater_control", { //название правила - "контроль обогревателя"
whenChanged: "wb-adc/R1", //при изменении состояния датчика света
then: function(newValue, devName, cellName) { //выполняй следующие действия
if (dev.simple_test.enabled) { // если вируальн. устр-во simple_test в положении enabled
if (dev["wb-adc"]["R1"] > 800) { //если сопротивление датчика больше 800,
dev["wb-gpio"]["EXT1_R3A6"] = 0; //установи на выходе wb-gpio устройство EXT1_R3A5
//в состояние "выключено"
} else { // иначе
if (dev["wb-adc"]["R1"] < 1000) { //если сопротивление датчика больше 1550,
//(обеспечиваем гистерезис)
dev["wb-gpio"]["EXT1_R3A6"] = 1; //установи EXT1_R3A1 в состояние "включено"
}
}
}
}
});
Наверное криво, что-то может не правильно., но работает. Ещё раз спасибо за помощь!
Неожиданная особенность движка правил. Видимо, стоит добавить в вики.
Все глобальные переменные ОБЩИЕ между скриптами. Алиасы (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);}
dev["wb-gpio"]["Relay_1"] = RelayStatus;
timer_3_id = setTimeout(function() {
timer_3_id = null;
if(dev["wb-gpio"]["D1_IN"] == 0){
if(RelayStatus == 1){
RelayStatus = !RelayStatus;
dev["wb-gpio"]["Relay_1"] = RelayStatus;
}
}
},
DelayOut);
}
});
Добрый день! может кто знает? как привязать включение и выключение света к восходу и заходу солнца?
А у вас есть идеи, откуда получать время восхода и заката?
ну там целая математика! может можно как-то привязать заход и восход к своему часовому поясу? и не в каждом правиле, а единоразова записать данные и по ним уже строить остальные сценарии!
При старте движка правил и раз в сутки (скажем, в полночь: when: cron("0 0 * * *")
) определяем время восхода и заката на сегодня - как угодно, хоть стащив curl’ом страничку одного из многочисленных сайтов с этой информацией и выдрав из нее время sed’ом, хоть по предварительно забитой таблице.
Пересчитываем в миллисекунды, вычитаем текущее время, и соответственно выставляем два таймера через startTimer
. В обработчиках таймеров делаем нужные действия.
Спасибо за информацию, но я не совсем понимаю, что значит curl’ом и sed’ом. можно по подробнее как это и что это такое?
Например так (координаты в запросе для Москвы, выдает время в миллисекундах с 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 раз. после чего обнулить таймер и
выключить лампочку.
var motion_timer_5_timeout_ms = 10 * 1000;
var motion_timer_5_id = null;
defineRule("svet_miganie_1",
{
when: function ()
{
return dev["wb-gpio/EXT6_DR1"] ==1;
},
then: function()
{
if (motion_timer_5_id)
{
clearTimeout(motion_timer_5_id);
}
motion_timer_5_id = setTimeout(function ()
{
dev["wb-gpio"]["EXT1_R3A2"] = 1;
motion_timer_5_id = null;
},
motion_timer_5_timeout_ms);
}
});
Прочитайте пожалйуста первое сообщение темы и пропустите код через http://jsbeautifier.org/ , прежде чем постить, если он у вас отформатирован по левому краю.
Подскажите пожалуйста,
есть ли какой-то способ ловить двойные или тройные нажатия на нефиксирующуюся кнопку?
И зафиксировать “долгое” нажатие?
Спасибо
А кнопка куда подключена?
Пока на сухой контакт wb5, но это временное решение - кнопок планируется штук 20 и я пока не понимаю куда их все подключить
Можно расширять, через WBIO-DI-DR-16 например.
Про двойные и долгие нажатия: можно поэкспериментировать с правилами. Сделайте правило с 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);
}
});
})();