Весь скрипт выглядит так:
defineVirtualDevice("dimmer2", { //Создаём виртуальнное устройство Диммер3
title: "dimmer control2",
cells: { //с параметрами
change: {
type: "switch", // тип, публикуемый в MQTT-топике /devices/.../controls/.../meta/type для данного параметра.
value: false // значение по умолчанию
},
click: {
type: "switch", // одиночный клик
value: false // значение по умолчанию
},
doubleClick: {
type: "switch", // двойной клик
value: false // значение по умолчанию
},
value: {
type: "value", // тип (.../meta/type)
value: 0 // значение по умолчанию
},
saved: {
type: "value", // тип (.../meta/type)
value: 100 // значение по умолчанию
},
}
});
var dirct3 = false;
var lastdirct3 = false;
var timerLast3;
var timerTime3;
var countClick3 = 0; // кол-во сделанных кликов (счетчик, начальное значение всегда = 0)
// для тонкой настройки
var timeClick3 = 900; // время одного клика/длинного клика
var timeout23 = 1500; // максимальное время ожидания двойного клика
var timeout3 = 400; // интервал изменения яркости димера в мс
var delta3 = 6; // шаг приращения яркости диммера
var startBright3 = 1; // начальная яркость при розжиге
var hkmin = 0;
var hkmax = 100;
var dalimin = 86;
var dalimax = 254;
var p;
trackMqtt("/devices/dimmer2/controls/value", function(message){
log.info("name: {}, value: {}".format(message.topic, message.value));
log.info(p);
if(message.value > hkmin && message.value <= hkmax){
p = parseInt(((message.value-hkmin) / (hkmax-hkmin)) * (dalimax-dalimin) + dalimin, 10);
dev["dali_gw2_21"]["Channel 0"] = p;
} else {
dev["dali_gw2_21"]["Channel 0"] = 0;
}
});
defineRule("simple_folow", {
whenChanged: "dimmer2/value",
then: function (newValue, devName, cellName) {
log.info("Вход в функцию");
log.info(p);
if(newValue > hkmin && newValue <= hkmax){
p = parseInt(((newValue-hkmin) / (hkmax-hkmin)) * (dalimax-dalimin) + dalimin, 10);
dev["dali_gw2_21"]["Channel 0"] = p;
}
}
});
defineRule("oneClick3", {
asSoonAs: function() {
// было одно нажатие, восстанавливаем запомненое значение или полностью выключаем
return dev["dimmer2/click"];
},
then: function() { // выполняется при срабатывании правила
if (dev["dimmer2/value"] > 0) { // если свет включен, сохраняем текущее значение и выключаем
dev["dimmer2/saved"] = dev["dimmer2/value"];
dev["dimmer2/value"] = 0;
dev["dali_gw2_21"]["Channel 0"] = 0;
log.info("Выключить свет");
} else { // если свет выключен, выставляем значение взяв из сохраненного
dev["dimmer2/value"] = dev["dimmer2/saved"];
log.info("Включить свет");
}
dev["dimmer2/click"] = false; // сброс состояния
log.info("oneClick");
}
});
defineRule("wtoClick3", {
asSoonAs: function() {
// было двойное нажатие, свет на максимум
return dev["dimmer2/doubleClick"];
},
then: function() { // выполняется при срабатывании правила
dev["dimmer2/value"] = 100; // максимальная яркость
dev["dimmer2/doubleClick"] = false; // сброс состояния
log.info("doubleClick");
}
});
// правило с именем startClicking
defineRule("startClicking3", {
asSoonAs: function() {
// edge-triggered-правило - выполняется, только когда значение
// данной функции меняется и при этом становится истинным
// т.е. когда dimmer2/change стало = true, а до этого было fasle
// запускаем работу диммера по нажатию клавиши
return dev["dimmer2/change"];
},
then: function() { // выполняется при срабатывании правила
//log.info("1 - dirct3:", dirct3, "lastdirct3:", lastdirct3);
if (dev["dimmer2/value"] == 100) {
dirct3 = false;
} else if (dev["dimmer2/value"] == 0) {
dirct3 = true;
} else {
dirct3 = !lastdirct3;
}
//log.info("2 - dirct3:", dirct3, "lastdirct3:", lastdirct3);
startTicker("clickTimer3", timeout3); // запустить таймер clickTimer со срабатыванием каждые N мс
log.info("startClicking3");
}
});
defineRule("stopClicking3", {
asSoonAs: function() {
// т.е. когда dimmer2/change стало = false, а до этого было true
// по простому кнопку димера отпустили, прекращаем димировать (тормозим тикающий таймер)
return !dev["dimmer2/change"];
},
then: function() {
timers.clickTimer3.stop(); // остановить таймер clickTimer
lastdirct3 = dirct3;
log.info("stopClicking3");
}
});
defineRule("doClick3", {
when: function() {
// т.е. пока таймер clickTimer3 работает, вызываем функцию при каждом срабатывании таймера
// тут работает диммер
return timers.clickTimer3.firing;
},
then: function() {
log.info("doClick3");
if (dirct3) { // розжиг
log.info("розжиг");
if (dev["dimmer2/value"] >= 93) {
dev["dimmer2/value"] = 100;
} else {
// при начале розжига проверяем на минимальный порог
// если меньше, то сразу устанавливаем значение яркости = startBright3
// иначе наращиваем с заданным шагом
log.info("Start. value =", dev["dimmer2/value"], "startBright3 = ", startBright3)
if (dev["dimmer2/value"] >= startBright3){
dev["dimmer2/value"] = ((dev["dimmer2/value"] * 1) + delta3); //.toFixed(0);
} else {
dev["dimmer2/value"] = startBright3; //.toFixed(0);
}
log.info("Finish. value =", dev["dimmer2/value"])
}
}
if (!dirct3) { // затухание
log.info("затухание");
if (dev["dimmer2/value"] <= 6) {
dev["dimmer2/value"] = 0;
} else {
dev["dimmer2/value"] = ((dev["dimmer2/value"] * 1) - delta3);//.toFixed(0);
}
}
}
});
defineRule("timeout23", {
when: function() {
//вызываем функцию при срабатывании таймера
return timers.doubleClickTimeout3.firing;
},
then: function() {
log.info("Прошло много времени, сбрасываем счетчик");
countClick3 = 0;
}
});
defineRule("long_press3", {
// Срабатывание при изменении значения параметра.
whenChanged: "wb-gpio/A2_IN", //при изменении состояния A2_IN у устройства wb-gpio
then: function(newValue, devName, cellName) { //выполняй следующие действия
log.info("newValue = ", newValue);
if (newValue) {
timerLast3 = Date.now();
log.info("timerLast3 = ", timerLast3);
startTimer("doubleClickTimeout3", timeout23); // старт таймера ожидания двух кликов
dev["dimmer2/change"] = true;
} else {
dev["dimmer2/change"] = false;
timerTime3 = Date.now();
log.info("timerTime3 = " + timerTime3);
if ((timerTime3 - timerLast3) <= timeClick3) {
log.info("countClick3 = ", countClick3);
if (countClick3 >= 1){
log.info("Было второе короткое нажатие");
dev["dimmer2/doubleClick"] = true;
countClick3 = 0; //сброс счетчика
}
else if (countClick3 <= 0){
log.info("Было короткое нажатие");
dev["dimmer2/click"] = true;
countClick3 = countClick3 + 1;
}
} else if ((timerTime3 - timerLast3) >= timeClick3) {
countClick3 = 0; //сброс счетчика
lastdirct3 = dirct3;
timers.doubleClickTimeout3.stop(); // остановить таймер, т.к. было длинное нажатие
log.info("было длинное нажатие");
}
}
}
});
Если управлять через WEB работает нормально, но если управлять через A2_IN - работает не стабильно. Завтра продолжу эксперименты, Если подскажите способ оптимизировать правило, или всю задачу - буду признателен.