Движок правил: примеры кода

Спасибо большое, разобрался!
Но возникает одна странная ошибкаЖ

Цитата
Script error: ReferenceError: identifier ‘ActionButtons’ undefined
duk_js_var.c:1232
anon /etc/wb-rules/light_switches.js:30 preventsyield

если перезагрузить WB или сервис движка правил.
Соответственно и правила не работают, пока не зайдешь в правило и не пересохранишь его.

С чем такое может быть связано и как это исправить?

Не хочется делать костылей по автоматическому пересохранению правила после перезагрузки…

А что у вас оказалось на 30-й строчке файла light_switches.js, и около него?
Можете просто весь итоговый файл выложить.

light_switches.js.txt (4.4 КБ)
Вот весь файл, там много всего лишнего…
ругается на строку:

Цитата
ActionButtons.onButtonPress(

при этом если пересохранить, то перестает ругаться

А ещё файл с описанием объекта ActionButtons сбросьте, пожалуйста

вот он onButtonPress.js.txt (5.2 КБ)

Здравствуйте! Помогите пожалуйста написать правильно скрипт. Вообщем ситуация такая,есть кнопка для управления вентилятором (вентилятор с регулировкой оборотов-работает через аналоговый выход 0-10v) она его включает при первом нажатии на 100% при втором на 50% и при третьем выключает это реализовать удалось. Также вентилятор должен работать от датчика влажности при превышении порога включается на 50% и по истечении какого то времени включается на 100% .Выключается при снижении порога и сбрасывает таймер .Если произошло включение по кнопке сценарий с датчиком работать не должен.Сейчас работает по другому(от датчика влажности вкл на 50% потом по времени на 100% сбрасывает сброс таймера и все по новой) помогите подкорректировать.

(function() { 
  var button_counter = 0;


  defineRule( "on_fan_button", {
    whenChanged: "wb-gpio/A1_IN",
    then: function (newValue, devName, cellName) {

      // если поймали нажатие, увеличиваем счётчик
      if (newValue) {
        button_counter += 1;
      }
       // счётчик равен одному, значит было одинарное нажатие
      if (button_counter == 1) {
        log("fan 100%");dev["wb-dac/EXT2_O1"] = 10000;
      }
      
      // счётчик равен двум, значит было двойное нажатие
      if (button_counter == 2) {
        log("fan 50%");dev["wb-dac/EXT2_O1"] = 5000;
      }
       if (button_counter == 3) {
        log("fan off");dev["wb-dac/EXT2_O1"] = 0;
      }
      // сброс счетчика
     if (button_counter == 3) {
        log("clear counter!",button_counter);button_counter = 0;
      }
    }
      });
  })();
          var Hum = 10;
       var motion_timer_1_timeout_ms = 10 * 1000;
        var motion_timer_1_id = null;
  
   defineRule("Hum_fan_on", { 
   whenChanged: "T2 Bathroom/Humidity", 

   then: function (newValue, devName, cellName) { 
 if ( newValue > Hum) {
  dev["wb-dac/EXT2_O1"] = 5000;  
  
if (motion_timer_1_id) {
      clearTimeout(motion_timer_1_id);
   }
  
    motion_timer_1_id = setTimeout(function () {
	   dev["wb-dac"]["EXT2_O1"] = 10000;         
               motion_timer_1_id = null;   
   	}, motion_timer_1_timeout_ms);           	
}
}
});

Судя по ошибке объект ActionButtons не существует на момент запуска скрипта light_switches. В качестве эксперимента: попробуйте переименовать onButtonPress.js в _onButtonPress.js или что-то подобное, чтобы по порядку он был выше light_switches.

2 лайка

Спасибо!
Это помогло!

2 сообщения было перемещено в эту тему: Новая версия движка правил

Всем здравствуйте!! Помогите пожалуйста написать правильно скрипт. Логика такая есть теплый пол он включается ы выключается по датчику температуры регулируется через виртуальный ползунок. Так же есть виртуальная кнопка когда на ней единица, все должно работать от датчика температуры, когда ноль все должно быть выключено и на датчик температуры реакции не должно быть. Вообщем кнопка должна разрешать работать ТП от датчика температуры или нет.

  defineVirtualDevice("Tp1", {
  title:"Регулятор температуры Пола в прихожей",
  cells: {
  "temperature": {
  type:"range",
  value: 25,
  max: 55
 },"Zima1": {
  type:"switch",
  value: 0,
 }
                }
                });
defineRule("Tpf1", {
whenChanged: "wb-w1/28-00000b785146",
then: function (newValue, devName, cellName) {
if (newValue>dev["Tp1/temperature"]) {
dev["wb-gpio/EXT1_HS5"] = 0;log("Выключение обогревателя 
 ТП1");
} else  
  dev["wb-gpio"]["EXT1_HS5"] = 1;log("Включение 
обогревателя ТП1");    
}
 });

Восход Заход
curl -sA Mozilla http://www.google.com/search?q=Восход+Заход+$1 | html2text -width 80 | grep "Заход\ "

Доброго дня!
Разбираюсь с движком правил, взял пример для кнопки (нажатие, долгое и двойное нажатие) отсюда выше. Сделал виртуальное устройство pushbutton, но с ним не получается оттестировать – всегда срабатывает долгое нажатие. Не получится на виртуальном девайсе без физической кнопки эмулировать даблклик и лонгпресс?

Давайте ваш скрипт целиком - посмотрю. Должно работать.

Кнопка в одном скрипте:

defineVirtualDevice("test_button1", {
  title: "Test dev 1",
  cells: {
    "switch_on": {
    type: "pushbutton",
    value: false,
    },
  }
});

Это скрипт в файле _OnButtonPress.js, его взял где-то здесь. Как бы я не нажимал, всегда срабатывает:

longPress: {
func: switchRelay,
prop: [“wb-mr6c_185”, “K2”]
}

Дабл клик просто выкл и вкл быстро реле.

(function () {
'use strict';

var ActionButtons = {};


/**
 * Function that identifies what kind of press was performed: single, double or long press;
 * and assigns an action for each type of press.
 *
 * @param  {string} trigger         -  Name of device and control in the following format: "<device>/<control>".
 * @param  {object} action          -  Defines actions to be taken for each type of button press.
 *                                  Key: "singlePress" or "doublePress" or "longPress" or "longRelease".
 *                                  Value: Object of the following structure {func: <function name>, prop: <array of parameters to be passed>}
 *                                  Example:
 *                                  {
 *                                      singlePress: {func: myFunc1, prop: ["wb-mr6c_1", "K1"]},
 *                                      doublePress: {func: myFunc2, prop: ["wb-mrgbw-d_2", "RGB", "255;177;85"]},
 *                                      longPress: {func: myFunc3, prop: []},
 *                                      longRelease: {func: myFunc4, prop: []}
 *                                  }
 * @param  {number} timeToNextPress -  Time (ms) after button up to wait for the next press before reseting the counter. Default is 300 ms.
 * @param  {number} timeOfLongPress -  Time (ms) after button down to be considered as as a long press. Default is 1000 ms (1 sec).
 */
ActionButtons.onButtonPress = function (trigger, action, timeToNextPress, timeOfLongPress) {
    var buttonPressedCounter = 0;
    var timerWaitNextShortPress = null;
    var timerLongPress = null;
    var isLongPress = false;

    var ruleName = "on_button_press_" + trigger.replace("/", "_");

    defineRule(ruleName, {
        whenChanged: trigger,
        then: function (newValue, devName, cellName) {

            // If button is pressed, wait for a long press
            if (newValue) {

                if (timerWaitNextShortPress) {
                    clearTimeout(timerWaitNextShortPress);
                }
                timerLongPress = setTimeout(function () {
                    if (typeof action.longPress === "object") {
                        if (typeof action.longPress.func === "function") {
                            action.longPress.func.apply(this, action.longPress.prop);
                        }
                    }
                    // log(">>>>>>> long press <<<<<<");
                    isLongPress = true;  // Long press identified, we will skip short press
                    buttonPressedCounter = 0;
                }, timeOfLongPress);

            }

            // If button is released, then it is not a "long press", start to count clicks
            else {
                if (!isLongPress) {
                    clearTimeout(timerLongPress);
                    buttonPressedCounter += 1;
                    timerWaitNextShortPress = setTimeout(function () {
                        switch (buttonPressedCounter) {
                        // Counter equals 1 - it's a single short press
                        case 1:
                            if (typeof action.singlePress === "object") {
                                if (typeof action.singlePress.func === "function") {
                                    action.singlePress.func.apply(this, action.singlePress.prop);
                                }
                            }
                            // log(">>>>>> short press - single <<<<<<");
                            break;
                        // Counter equals 2 - it's a double short press
                        case 2:
                            if (typeof action.doublePress === "object") {
                                if (typeof action.doublePress.func === "function") {
                                    action.doublePress.func.apply(this, action.doublePress.prop);
                                }
                            }
                            // log(">>>>>> short press - double <<<<<<");
                            break;
                        }
                        // Reset the counter
                        buttonPressedCounter = 0;
                    }, timeToNextPress);
                }

                // Catch button released after long press
                else {
                    if (typeof action.longRelease === "object") {
                        if (typeof action.longRelease.func === "function") {
                            if (typeof action.longRelease.prop === "array") {
                                action.longRelease.func.apply(this, action.longRelease.prop);
                            } else {
                                action.longRelease.func.apply(this, []);
                            }
                        }
                    }
                    isLongPress = false;
                }
            }

        }
    });
};



// export as Node module / AMD module / browser variable
if (typeof exports === 'object' && typeof module !== 'undefined') {
    module.exports = ActionButtons;
} else if (typeof define === 'function' && define.amd) {
    define(ActionButtons);
} else {
    global.ActionButtons = ActionButtons;
}

}());

ActionButtons.onButtonPress(
"test_button1/switch_on",
{
    singlePress: {
        func: switchRelay,
        prop: ["wb-mr6c_157", "K1"]
    },
    doublePress: {
        func: switchRelay,
        prop: ["wb-mr6c_185", "K1"]
    },
    longPress: {
        func: switchRelay,
        prop: ["wb-mr6c_185", "K2"]
    }
},
300, 1000
);

/**
* Helper Functions
*/
function switchRelay(device, control) {
  dev[device][control] = !dev[device + "/" + control];
}

“Софтовые” кнопки из Virtual Device не создают второе событие, при отпускании кнопки.
То есть если мы вставим log сюда:

then: function (newValue, devName, cellName) {
			log.info("trigger",newValue)
            // If button is pressed, wait for a long press

То увидим “нажатие”. Но не отпускаание. То есть независимо от того как долго кнопка нажата - событие при ее отпускании не возникнет.
Для теста можно использовать элемент управления “switch” (переключатель).

Как-то так я и предполагал. А свитч он будет и двойной клик отрабатывать, если его быстро туда-сюда дернуть?

В целом работает с переключателем, но неудобно там двойной клик делать. Параллельно срабатывает либо одинарный, либо долгое нажатие.

singlePress: {
        func: switchRelay,
        prop: ["wb-mr6c_157", "K1"]
    },
    doublePress: {
        func: switchRelay,
        prop: ["wb-mr6c_185", "K1"]

У вас в обоих случаях одно реле.

Не очень понял, но я для теста указал:

  1. одиночный клик wb-mr6c_157 контакт 1
  2. дабл клик wb-mr6c_185 контакт 1
  3. длинное нажатие wb-mr6c_185 контакт 2

Ну будет так работать разве? 2 и 3 реле одно, но выходы то разные.

Да, это я невнимательно посмотрел… Не увидел что сами устройства разные.
Попробуйте увеличить время на двойной клик.