Нужна помощь с настройкой выключателей.
В чем суть: есть модули аналогового вывода (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; //ставим на заданное значение
}
Вызывать, передавая имяДиммера, ИмяКанала, ИзменениеЗначения(положительное или отрицательное), максимальноеЗначение
К сожалению не работает. Краткое нажатие отрабатывает исправно, а вот длительное не работает(
Выдает вот это:
А какое значение передется диммеру?
В каком смысле какие?
Вот, если нужно код целиком:
(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]
А как должно быть? Что бы периодически значение увеличивалось пока нажата кнопка, до указанного диапазона?
Попробуйте данное правило, не забудьте только указать свои устройства.
Я не много переделал логику. На одно быстрое нажатие выключаем свет, по двойному включаем свет. А если кнопка зажата уставка на диммере будет постепенно увеличивать или уменьшатся.
(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/EXT1_IN2", //Вход, за которым следим.
{
singlePress: { // Когда нажали быстро выключаем свет
func: OnOff,
prop: ["wb-dac_test", "EXT1_O1_test",0]
},
doublePress: { // Когда нажали быстро 2 раза включаем свет
func: On,
prop: ["wb-dac_test", "EXT1_O1_test",10000]
},
longPress: { // Когда зажали добовляем или уменьшаем яркость, в зависимости в каком был включен или выключен свет.
func: dimmerChange,
prop: ["wb-dac_test", "EXT1_O1_test",10,10000]
}
},
300, 1000
);
/**
* Helper Functions
*/
var Destinations; // Флаг направления изменения яркости, для опредееняи увиличивать или уменьшать
function OnOff(dimmerName, outputName, dimmerValue){
dev[dimmerName][outputName] = 0; //Выключаем
Destinations = true; // Выстовялем флаг на увиличение
}
function On(dimmerName, outputName, maxValue){
dev[dimmerName][outputName] = maxValue; //ставим на максимальное значение
Destinations= false; // Выстовялем флаг на уменьшения
}
function dimmerChange(dimmerName, outputName, shiftValue, maxValue){
while (dev["wb-gpio"]["EXT1_IN2"]) {
var currentValue = dev[dimmerName][outputName] //получим текущее значение
if (Destinations)
{
var newValue = currentValue+shiftValue; //Определяем предполоджительно новое значение
if (newValue>maxValue) {
newValue=maxValue;
dev[dimmerName][outputName] = newValue; //ставим на заданное значение
Destinations = false;
return;
};
dev[dimmerName][outputName] = newValue; //ставим на заданное значение
}
else
{
var newValue = currentValue-shiftValue; //Определяем предположительно новое значение
if (newValue<0){
newValue=0;
dev[dimmerName][outputName] = newValue; //ставим на заданное значение
Destinations=true;
return;
};
dev[dimmerName][outputName] = newValue; //ставим на заданное значение
}
}
}
Да, именно так. Чтобы была та же логика работы, что и у WB-MDM3 в однокнопочном режиме:
-
короткое нажатие переключает состояние канала (выключает или включает с установленной яркостью).
-
долгое нажатие меняет яркость, вверх до 100 % или вниз до 1 %. Направление меняется при каждом долгом нажатии.
К сожалению, присланный вами код вообще не заработал(