Однократное и длительное нажатие кнопки для управления светом

Нужна помощь с настройкой выключателей.
В чем суть: есть модули аналогового вывода (WBIO-AO-10V-8 - подключается напрямую к вайрену, WB-MAO4 - подключается через мод бус и WB-MRGBW-D - тоже через мод бус), которые управляют диммерами светодиодных лент, и два модуля дискретных входов (WBIO-DI-WD-14, один из который напрямую к вайрену, а другой через WB-MGE и WB-MIO, т.е из интернета в мод бус, а из мод буса в I2C), к которым подключаются выключатели без фиксации (звонковые кнопки).
В чем задача: нужно настроить управление диммерами по нажатию на кнопки. Однократное краткое нажатие – включить на 100 процентов, еще одно однократное – выключить, длительное – изменение яркости по кругу (от 0 дошло до 100, потом в обратную сторону).
Как такое можно реализовать?
Если можно, прошу максимально подробный ответ, тк работаю с этим в первый раз)

Добрый день.
Вот то, что для обработки WD-14 нужно:

Нужно только переписать функции под задачу.

WB-MRGBW-D - умеет с помощью своих входов управляться, или обязательно внешнее управление?

Да, т.к WB-MRGBW-D используется нескольких одноцветных лент, а встроенная регулировка только общая

А можно чуть конкретнее? Что именно в данном коде нужно поменять именно под мою задачу?

Например, кнопка у нас подключена к модулю WBIO-DI-WD-14, в вайрене вход GPIO 268 (EXT1_IN13). Диммер подключен к WBIO-AO-10V-8, в вайрене выход 3 (DACchannel 1, MQTT id EXT4_O1, IIO channel number 3. Как правильно написать это все?

Понятно. Поэтому - можно переработать функцию из

function changeSetting(){
  log.info("Enter function");
  stringRGB = dev[dimmNumber +"mrgbw-d/RLine"].toString() +";"+ dev[dimmNumber +"mrgbw-d/GLine"].toString() +";"+ dev[dimmNumber +"mrgbw-d/BLine"].toString();
  //log.info("stringRGB=",stringRGB);
  dev[devDimmer +"/RGB"] = stringRGB;
  dev[devDimmer +"/White"] = dev[dimmNumber +"mrgbw-d/WLine"];
}

так:

//01_29_test_04.js
var devDimmer = "wb-mrgbw-d_189" // For name REAL MRGBW-D device #ChangeMe!#

function changeSettingRGB(num, newSetiing){
  //log.info("Enter function");
  //log.info("dev[devDimmer +/RGB]=",dev[devDimmer +"/RGB"]);
  //Получим строку с текущими значениями цвета.
  //ну и надо ее разобрать
  arrayOfRGB = dev[devDimmer +"/RGB"].split(";");
  //Тут - присваиваем ЭЛЕМНТУ массива НОВОЕ значение
  arrayOfRGB[num] = newSetiing;
  //log.info("arrayOfRGB=",arrayOfRGB[0],arrayOfRGB[1],arrayOfRGB[2]);
  stringRGB = arrayOfRGB[0].toString() +";"+ arrayOfRGB[1].toString() +";"+ arrayOfRGB[2].toString();
  //log.info("stringRGB=",stringRGB);
  dev[devDimmer +"/RGB"] = stringRGB;
}

//использование:
changeSettingRGB(0,25);  //для канала R -25
changeSettingRGB(1,42); //для канала G -42
changeSettingRGB(2,200); //для канала B -200

белый канал обработки не требует.

В коде реализована готовая функция, которая создает правила под обработку разных “нажатий”.
Туда (в функцию), как видно, передается кроме утроройства, за которысм “следим” еще и вызовы (имена) функций, которые вызываются при событиях. События - короткое нажатие, длинное, …
Менять надо именно эти функции. То есть скелет - готов, надо только реализовать алгоритм.
Для включения по короткому нажатию, например:

...
singlePress: {
       func: OnOff,
       prop: ["SomeDimmer", "SomeOutput", 100]
    },
...


и описать саму функцию-хелпер:

function OnOff(dimmerName, outputName, dimmerValue){
  if (dev[dimmerName][outputName]) { //Если не ноль
    dev[dimmerName][outputName] = 0; //Выключаем
  }
  else {
    dev[dimmerName][outputName] = dimmerValue; //Включаем на заданное значение
  }
}

Хинт:
Открываем в веб-интерфейсе “Settings” - “MQTT Channels”


Ну и тот же “EXT1_IN13”
записываем как

dev["wb-gpio"][EXT1_IN13]

используем строки из первого и второго столбца.
Тут же можно следить за значениями, если не хочется подписываться на топики в консоли.

Ура! Вкл, выкл заработало отлично, но не как не могу додуматься как реализовать функцию диммирования на WBIO-AO-10V-8. Можете, пожалуйста помочь и с этой функцией?

Подскажите пожалуйста)

Ну, достаточно, думаю, описать функцию-хелпер для изменения уровня диммирования так:

function dimmerChange(dimmerName, outputName, shiftValue, maxValue){
 var currentValue = dev[dimmerName][outputName]  //получим текущее значение
var newValue = currentValue+shiftValue; //Определяем предполоджительно новое значение
  if (newValue>maxValue) {newValue=0}
  if (newValue<0) {newValue=maxValue}
  dev[dimmerName][outputName] = newValue; //ставим на заданное значение

}

Вызывать, передавая имяДиммера, ИмяКанала, ИзменениеЗначения(положительное или отрицательное), максимальноеЗначение

Есть новая версия функции, в которой добавлена обработка долгого нажатия и периодического (пока не отпустил) вызова функции:

1 симпатия

К сожалению не работает. Краткое нажатие отрабатывает исправно, а вот длительное не работает(
Выдает вот это:

А какое значение передется диммеру?

В каком смысле какие?
Вот, если нужно код целиком:

(function () {
'use strict';
var ActionButtons = {};
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-gpio/EXT2_IN2",          //Вход, за которым следим.
{
    singlePress: {
       func: OnOff,
       prop: ["wb-dac", "EXT1_O1", 10000]
    },
    longPress: {
       func: dimmerChange, 
       prop: ["wb-dac", "EXT1_O1"]
    }
},
300, 1000
);
/**
* Helper Functions
*/
function OnOff(dimmerName, outputName, dimmerValue){
  if (dev[dimmerName][outputName]) { //Если не ноль
    dev[dimmerName][outputName] = 0; //Выключаем
  }
  else {
    dev[dimmerName][outputName] = dimmerValue; //Включаем на заданное значение
  }
}

function dimmerChange(dimmerName, outputName, shiftValue, maxValue){
 var currentValue = dev[dimmerName][outputName]  //получим текущее значение
var newValue = currentValue+shiftValue; //Определяем предполоджительно новое значение
  if (newValue>maxValue) {newValue=0}
  if (newValue<0) {newValue=maxValue}
  dev[dimmerName][outputName] = newValue; //ставим на заданное значение

}

А значения-то почему в функцию не передаете? Ни shiftValue ни maxValue
Надо как-то так:

 prop: ["wb-dac", "EXT1_O1", 10, 1000]

Не выходит, при длительном нажатии однократно прибавляет яркость на 10 пунктов и все.