Нестандартные функции выключателей

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

  1. Короткое нажатие - вкл/выкл свет на заданном уровне яркости (WB-MDM3)
  2. Двойное короткое нажатие - вкл/выкл подсветка (WB-MRGBW-D)
  3. Длительное нажатие - уменьшение/увеличение яркости света (WB-MDM3)
    Может кто-то сталкивался с такой задачей?
1 лайк

Для решения такой задачи нужно обрабатывать нажатия не на реле/диммере, с момощью маппинг-таблицы а в самом контроллере правилами.
Например в теме https://support.wirenboard.com/t/kak-napisat-sczenarij-dlinnogo-nazhatiya/2342/3
и https://support.wirenboard.com/t/wb-mr6-i-prodolzhitelnost-nazhatiya/2528/2
Ну и основное: https://support.wirenboard.com/t/dvizhok-pravil-primery-koda/483/78

Вот я свое оборудование туда прописываю, и не работает.
onButtonPress(
“on_button_press”,
“wb-gpio/EXT1_DR14”,
{
singlePress: [“R1”, “K1”],
doublePress: [“R1”, “K2”],
longPress: [“R1”, “K3”]


},
200, 2000
);

то ли лыжи не едут, то ли я, в прошлом программист c++/html/php ни чего не понимаю.
почему команда dev[“R1”][“K1”] = 1; не включает реле, а dev[“R1”][“K1”] = true включает…

Напишу код и прокомментирую подробно. Сейчас займусь.
PS: Вывод а лог - крайне полезен.

log.info("TestLog Info 1")//Это лог. Он попадает в /var/log/messages

Можно и переменные включать:

log.info("TestLog Info 3", dev["R1"]["K1"])
1 лайк
(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) {
    log.info("LongPress ActionButtons.onButtonPress")//Это лог. Он попадает в /var/log/messages
    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) {
          log.info("LongPress defineRule")//Это лог. Он попадает в /var/log/messages

            // 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(
"wb-mio-gpio_157:1/IN14",          //Вход, за которым следим.
{
    singlePress: {
       func: switchRelay,
       prop: ["wb-mio-gpio_157:2", "K1"]
    },
    doublePress: {
       func: switchRelay, prop: ["wb-mio-gpio_157:2", "K2"]
        //func: switchDimmerRGB,
        //prop: ["wb-mr6c_10", "K2", "wb-mrgbw-d_24"]
    },
    longPress: {
       func: switchRelay, prop: ["wb-mio-gpio_157:2", "K3"]
        //func: setRandomRGB,
        //prop: ["wb-mr6c_10", "K2", "wb-mrgbw-d_24"]
    }
},
300, 1000
);


/**
* Helper Functions
*/
function switchRelay(device, control) { //Принимает в параметрах устройство и выход. Переключает состояние выхода на противоположное.
  log.info("LongPress switchRelay" ,device, control)//Это лог. Он попадает в /var/log/messages
  dev[device][control] = !dev[device + "/" + control];
}

function switchDimmerRGB(relayDevice, relayControl, dimmerDevice) {
   dev[relayDevice][relayControl] = true;
   if (dev[dimmerDevice + "/RGB"] !== "0;0;0") {
     dev[dimmerDevice]["RGB"] = "0;0;0";
   }
   else {
     dev[dimmerDevice]["RGB"] = dev[relayDevice + "/RGB"];
   }
}

function setRandomRGB(relayDevice, relayControl, dimmerDevice) {
  dev[relayDevice][relayControl] = true;
  dev[relayDevice + "/RGB"] = "" + Math.floor(Math.random() * 255) + ";" + Math.floor(Math.random() * 255) + ";" + Math.floor(Math.random() * 255);
  dev[dimmerDevice]["RGB"] = dev[relayDevice + "/RGB"];
}

Все вставляем в один скрипт.
singlePress
doublePress
longPress
вызывают хелпер-функции соответственно. В них можно уже то что нужно прописать.

7 лайков

Я заменил имена устройств на свои и всё работает! УРА!!! Спасибо, очень помогло, я бы не додумался сейчас.

1 лайк

Отлично! Рад что получилось.

из хелперов не работает switchDimmerRGB. пока не понимаю почему. разбираюсь. Не могу понять на каких командах общаться с устройствами, где это посмотреть. 3 дня сижу на сайте, читаю-вникаю. Надо вникать тк еще есть задача, чтобы RGBW при включении возвращался в те установки, которые были при выключении. И при длительном нажатии чтобы диммер ламп плавно уменьшал яркость, а при повторном длительном нажатии, чтобы увеличивал яркость.

Диммера RGB у меня сейчас нет, про общение с устройствами “вручную” - https://wirenboard.com/wiki/index.php/Modbus-client

Надо хранить его значения в переменных, при включении - восстанавливать.

Тоже переменная, в которую записывать в хелпере “longPress” что делали в этот раз. “1” - увеличивали, “0” - уменьшали например.
Благодарю за вопросы, как раз занят документацией - включу туда примеры.

Как это теоретически сделать, используя переменные - я понимаю. Я не понимаю какими “словами” и “выражениями” это прописывать. Вот нужно мне установить Диммер “White” в положение “200”. Где мне брать информацию о том, как правильно это прописать? Вроде всё просто как 2сосны, а сижу 3 дня без толку. Кого-то напрягать глупыми вопросами тоже не очень хочется)

Вопросы не глупые совсем. А очень полезные.

mosquitto_sub -v -t /# 

вернет все топики.
В том числе и все топики диммера, если нужно что-то “фильтровать” - тогда

mosquitto_sub -v -t /# | grep  ХХХ

То есть mqqt “дерево” - оно как файловая система. Можем прочитать “файл”, можем его записать.

для установки -
dev[НАЗВАНИЕДИММЕРА + “/RGB”] = “x;y;z” - это “цвет”
dev[НАЗВАНИЕДИММЕРА + “/White”] = x; - это “Белый”

Я понял аналитически, что команду диммеру нужно давать в таком виде:
dev[НАЗВАНИЕДИММЕРА + “/RGB”] = “x;y;z” - это “цвет”
dev[НАЗВАНИЕДИММЕРА + “/White”] = x; - это “Белый”
это работает, спасибо!
Но главный вопрос… где написано это правило? Почему не:
dev[НАЗВАНИЕДИММЕРА][“White”] = x;
где таким недалёким как я, набраться информации, чтобы не задавать вопросов, а просто сделать исходя из определенной методики?

Можно и так.
Все - в вики https://wirenboard.com/wiki/index.php/%D0%94%D0%B2%D0%B8%D0%B6%D0%BE%D0%BA_%D0%BF%D1%80%D0%B0%D0%B2%D0%B8%D0%BB_wb-rules
откуда ссылка на Гитхаб

ActionButtons.onButtonPress(
“wb-mio-gpio_157:1/IN14”, //Вход, за которым следим.

вопрос, что такое «:1»? далее по тексту есть еще и «:2» =)

верно ли я понимаю, что если мне надо сделать обработку всех 14 входов wbio-di-wd-14, то я в этом же файле правил пишу 14 раз конструкцию вида:

ActionButtons.onButtonPress(
"ТУТ ВХОДЫ С 1 ПО 14 типа 'wb-gpio/EXT1_IN1'",          //Вход, за которым следим.
{
    singlePress: {},
    doublePress: {},
    longPress: {}
},
300, 1000
);

Имхо проще установить какой нибудь HMI - типа этого
https://aliexpress.ru/item/1005002381803936.html
на место выключателя