Правило не применяет изменения значений переменной

Здравствуйте. Есть правило:

//Pump_PO_1.js
//'use strict';
var grow_box = "_PO_1"; // CHANGE_ME! имя устройства. Выводится в заголовок окна и служит для разделения устройств
log.info("pump_"+grow_box+"START######################"); //Это лог.

var pump_relay = "wb-mr6cu_36/K3"; //CHANGE_ME! устройство-реле питания диммера (перемешивание)
var dimmer_relay = "wb-mr6cu_36/K2"; //CHANGE_ME! устройство-реле питания диммера (полив)
var aeration_relay = "wb-mr6cu_36/K7"; //CHANGE_ME! устройство-реле питания диммера (аэрация)
var stop_reley = "wb-mr6c_203/Input 1"; //CHANGE_ME! устройство-реле кнопки СТОП
var stop_lamp = "wb-mr6c_203/K1"; //CHANGE_ME! устройство- лампочка
var blizzer_reley_1 = "buzzer/enabled"; //CHANGE_ME! устройство- близзер
var blizzer_reley_2 = "wb-msw-v3_15/Buzzer"; //CHANGE_ME! устройство- близзер

var ps = new PersistentStorage("storage_"+grow_box, {global: true});// Определим объект-хранилище.

//Элементы виртуального устройства
//управления
var deviceCells = { 
  
  //Начало перемешивания hh:mm
  "Pump (start) time": {
    type: "text",
    readonly: false,
    value: ps["pump_start_time"],
  },
  
    "Pump (stop) time": {
    type: "text",
    readonly: false,
    value: ps["pump_stop_time"],
  },
  
  //Длительность перемешивания
  "Pump duration": {
    type: "text",
    readonly: false,
    value: ps["sun_start_duration"],
  },

    //Длительность полива
  "Watering duration": {
    type: "text",
    readonly: false,
    value: ps["watering_duration"],
  },
  
  //Длительность перерыва
    "Time-out duration": {
    type: "text",
    readonly: false,
    value: ps["time-out_duration"],
  },
  
    //Длительность СТОПа
    "STOP duration": {
    type: "text",
    readonly: false,
    value: ps["stop_duration"],
  },
  
  
   wateringON : {
          type : "switch",
          value : false,
  },
  
  pumpON : {
          type : "switch",
          value : false,
  },   
  
  aeration : {
          type : "switch",
          value : false,
  },
  
  day : {
          type : "switch",
          value : false,
  },
  
  timeout : {
          type : "switch",
          value : false,
  },
  
  work : {
          type : "switch",
          value : false,
  },
  
  STOP : {
          type : "switch",
          value : false,
  },
  
    blizzer : {
          type : "switch",
          value : false,
  },
  
};


//Создадим виртуальное устройство и добавим в него элементы 
  defineVirtualDevice("pump_"+grow_box, {
    title:"Pump "+grow_box,
    cells: deviceCells
  });

defineRule("Sunraise start time change", { //название правила 
whenChanged: "pump_"+grow_box+"/Pump (start) time", //при изменении поля времени начала рассвета запишем его в хранилище
  then: function (newValue, devName, cellName) { //выполняй следующие действия
    log.info("pump_"+grow_box+"/Pump start time", newValue); //Это лог. Он попадает в /var/log/messages
    ps["pump_start_time"] = newValue;
  }
});

defineRule("Pump stop time change", { //название правила 
whenChanged: "pump_"+grow_box+"/Pump (stop) time", //при изменении поля времени начала рассвета запишем его в хранилище
  then: function (newValue, devName, cellName) { //выполняй следующие действия
    log.info("pump_"+grow_box+"/Pump stop time", newValue); //Это лог. Он попадает в /var/log/messages
    ps["pump_stop_time"] = newValue;
  }
});

defineRule("Watering duration change", { //название правила 
whenChanged: "pump_"+grow_box+"/Watering duration", //при изменении поля времени начала рассвета запишем его в хранилище
  then: function (newValue, devName, cellName) { //выполняй следующие действия
    log.info("pump_"+grow_box+"/Watering duration", newValue); //Это лог. Он попадает в /var/log/messages
    ps["watering_duration"] = newValue;
  }
});

defineRule("Time-out duration change", { //название правила 
whenChanged: "pump_"+grow_box+"/Time-out duration", //при изменении поля времени начала рассвета запишем его в хранилище
  then: function (newValue, devName, cellName) { //выполняй следующие действия
    log.info("pump_"+grow_box+"/Time-out duration", newValue); //Это лог. Он попадает в /var/log/messages
    ps["time-out_duration"] = newValue;
  }
});


defineRule("STOP duration change", { //название правила 
whenChanged: "pump_"+grow_box+"/STOP duration", //при изменении поля времени начала рассвета запишем его в хранилище
  then: function (newValue, devName, cellName) { //выполняй следующие действия
    log.info("pump_"+grow_box+"/STOP duration", newValue); //Это лог. Он попадает в /var/log/messages
    ps["stop_duration"] = newValue;
  }
});


//*Дополнение для реле диммера

defineRule("day_start", { //название правила 
whenChanged: "pump_"+grow_box+"/day", 
  then: function (newValue, devName, cellName) { //выполняй следующие действия
  if ((dev["pump_"+grow_box]["day"] == true)){ 
    dev["pump_"+grow_box+"/pumpON"] = true;
    
  }
}
}); 


defineRule("dimmer_relay_on", { //название правила 
whenChanged: "pump_"+grow_box+"/pumpON", 
  then: function (newValue, devName, cellName) { //выполняй следующие действия
  if ((dev["pump_"+grow_box]["pumpON"] == true)){ 
    dev["pump_"+grow_box+"/aeration"] = true;
    
  }
}
});  


defineRule("dimmer_relay_on_1", { //название правила 
whenChanged: "pump_"+grow_box+"/pumpON", 
  then: function (newValue, devName, cellName) { //выполняй следующие действия
  if ((dev["pump_"+grow_box]["pumpON"] == true) && (dev["pump_"+grow_box]["STOP"] == false)){ 
    dev[pump_relay] = true; //включаем реле
    dev[aeration_relay] = true;
    
  }
}
});


defineRule("dimmer_relay_off", { //название правила 
whenChanged:"pump_"+grow_box+"/pumpON", 
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["pumpON"] == false)){
    dev["pump_"+grow_box+"/wateringON"] = true;
  }
}
});


defineRule("dimmer_relay_off_1", { //название правила 
whenChanged:"pump_"+grow_box+"/pumpON", 
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["pumpON"] == false) && (dev["pump_"+grow_box]["STOP"] == false)){
    dev["pump_"+grow_box+"/wateringON"] = true;
    dev[dimmer_relay] = true;
     dev[pump_relay] = false;
  }
}
});
 
defineRule("watering_relay_off", { //название правила 
whenChanged:"pump_"+grow_box+"/wateringON", //При изменении флага "закат" - проверим и выключим реле
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["wateringON"] == false)){ //Если диммер на минимуме а реле включено
     dev[dimmer_relay] = false;
     dev[aeration_relay] = false;
     dev["pump_"+grow_box+"/aeration"] = false;
     dev["pump_"+grow_box]["timeout"] = true;
  }
}
});

defineRule("watering_relay_off_1", { //название правила 
whenChanged:"pump_"+grow_box+"/wateringON", //При изменении флага "закат" - проверим и выключим реле
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["wateringON"] == false) && (dev["pump_"+grow_box]["STOP"] == false)){ //Если диммер на минимуме а реле включено
     dev[dimmer_relay] = false;
     dev[aeration_relay] = false;
  }
}
});


defineRule("time-out_off", { //название правила 
whenChanged:"pump_"+grow_box+"/timeout", //При изменении флага "закат" - проверим и выключим реле
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["timeout"] == false) && (dev["pump_"+grow_box]["day"] == true)){ //Если диммер на минимуме а реле включено
     dev["pump_"+grow_box+"/pumpON"] = true;
  }
}
});

defineRule("stop_reley ON", { //название правила 
whenChanged:stop_reley, //При изменении флага "закат" - проверим и выключим реле
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev[stop_reley] == true)){ //Если диммер на минимуме а реле включено
     dev[stop_lamp] = true;
     dev["pump_" + grow_box]["STOP"] = true;
  }
}
});

defineRule("STOP ON", { //название правила 
whenChanged:"pump_"+grow_box+"/STOP", //При изменении флага "закат" - проверим и выключим реле
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["STOP"] == true)){ //Если диммер на минимуме а реле включено
     dev[stop_lamp] = true;
     dev[pump_relay] = false;
     dev[aeration_relay] = false;
     dev[dimmer_relay] = false;
     dev[blizzer_reley_1] = false;
     dev[blizzer_reley_2] = false;
     dev["pump_" + grow_box]["blizzer"] = true;
  }
}
});



defineRule("STOP Off", { //название правила 
whenChanged:"pump_"+grow_box+"/STOP", //При изменении флага "закат" - проверим и выключим реле
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["STOP"] == false)){ //Если диммер на минимуме а реле включено
     dev[stop_lamp] = false;
     dev[blizzer_reley_1] = false;
     dev[blizzer_reley_2] = false;
  }
}
});

defineRule("blizzer on", { //название правила 
whenChanged:"pump_"+grow_box+"/blizzer", //При изменении флага "закат" - проверим и выключим реле
  then: function (newValue, devName, cellName) { //выполняй следующие действия
   if ((dev["pump_"+grow_box]["blizzer"] == false)){ //Если диммер на минимуме а реле включено
     dev[blizzer_reley_1] = true;
     dev[blizzer_reley_2] = true;
  }
}
});



//*Конец дополнения

//'таймер для старта перемешивания';
var motion_timer_1_timeout_ms = (((ps["sun_start_duration"]) * 60)*1000);
var motion_timer_1_id = null;
defineRule("motion_detector_1", {
    whenChanged: "pump_" + grow_box + "/pumpON",
    then: function (newValue, devName, cellName) {
        if ((dev["pump_" + grow_box]["pumpON"] == true)) {
            if (motion_timer_1_id) {
                clearTimeout(motion_timer_1_id);
            }
            motion_timer_1_id = setTimeout(function () {
                dev["pump_" + grow_box]["pumpON"] = false;
                motion_timer_1_id = null;
            }, motion_timer_1_timeout_ms);
        }
    },
});

//'Конец таймера';

//'таймер для старта полива';
var motion_timer_2_timeout_ms = (((dev["pump_"+grow_box+"/Watering duration"]) * 60)*1000);
var motion_timer_2_id = null;
defineRule("motion_detector_2", {
    whenChanged: "pump_" + grow_box + "/wateringON",
    then: function (newValue, devName, cellName) {
        if ((dev["pump_" + grow_box]["wateringON"] == true)) {
            if (motion_timer_2_id) {
                clearTimeout(motion_timer_2_id);
            }
            motion_timer_2_id = setTimeout(function () {
                dev["pump_" + grow_box]["wateringON"] = false;
                motion_timer_2_id = null;
            }, motion_timer_2_timeout_ms);
        }
    },
});

//'Конец таймера';


//'таймер для старта тайм-аут';
var motion_timer_3_timeout_ms = (((dev["pump_"+grow_box+"/Time-out duration"]) * 60)*1000);
var motion_timer_3_id = null;
defineRule("motion_detector_3", {
    whenChanged: "pump_" + grow_box + "/timeout",
    then: function (newValue, devName, cellName) {
        if ((dev["pump_" + grow_box]["timeout"] == true)) {
            if (motion_timer_3_id) {
                clearTimeout(motion_timer_3_id);
            }
            motion_timer_3_id = setTimeout(function () {
                dev["pump_" + grow_box]["timeout"] = false;
                motion_timer_3_id = null;
            }, motion_timer_3_timeout_ms);
        }
    },
});

//'Конец таймера';


//'таймер для СТОПа';
var motion_timer_4_timeout_ms = (((ps["stop_duration"]) * 60)*1000);
var motion_timer_4_id = null;
defineRule("motion_detector_4", {
    whenChanged: "pump_" + grow_box + "/STOP",
    then: function (newValue, devName, cellName) {
        if (dev["pump_" + grow_box]["STOP"] == true) {
            if (motion_timer_4_id) {
                clearTimeout(motion_timer_4_id);
            }
            motion_timer_4_id = setTimeout(function () {
                dev["pump_" + grow_box]["STOP"] = false;
                motion_timer_4_id = null;
            }, motion_timer_4_timeout_ms);
        }
    },
});

//'Конец таймера';


//'таймер для близзера';
var motion_timer_5_timeout_ms = (((ps["stop_duration"]-1) * 60)*1000);
var motion_timer_5_id = null;
defineRule("motion_detector_5", {
    whenChanged: "pump_" + grow_box + "/blizzer",
    then: function (newValue, devName, cellName) {
        if (dev["pump_" + grow_box]["blizzer"] == true) {
            if (motion_timer_5_id) {
                clearTimeout(motion_timer_5_id);
            }
            motion_timer_5_id = setTimeout(function () {
                dev["pump_" + grow_box]["blizzer"] = false;
                motion_timer_5_id = null;
            }, motion_timer_5_timeout_ms);
        }
    },
});

//'Конец таймера';


//'Отслеживание времени старта и стопа';
defineRule("time_on_off", {
         when: cron('*/30 * * * *'),                             // каждые 30 секунд..
         then: function () {                                     // ..вызываем функцию  
           var currentTime = new Date();                         // получить и сохранить в переменную currentTime текущее системное время контроллера
           var currentHours = currentTime.getUTCHours()+3;     // сохранить в переменную currentHours значение часа из currentTime + 3 часа (корректировка часового пояса на +3 часа для MSK. PS Если это нужно)  
           var currentMinutes = currentTime.getUTCMinutes();     // сохранить в переменную currentMinutes значение минут из currentTime (если нужно будет оперировать не только "часами", но и "минутами")

           if ( (currentHours >= dev["pump_"+grow_box+"/Pump (start) time"]) && (currentHours <= (dev["pump_"+grow_box+"/Pump (stop) time"]-1) && (dev["pump_"+grow_box]["work"] == true)) )        // если число "часов" больше или равно 6 и меньше или равно 18, т.е. текущее время от 6:00 до 18:59
           {
             log("Сейчас День = ", currentHours);                // Вывести в лог текст "Сейчас День =" и число "часов"
             dev["pump_"+grow_box+"/day"] = true;                       // включить (true)
           
           } else{                                               // иначе (т.е. вне диапазона 6..18 часов, от 19:00 до 5:59 )
     
              log ("Сейчас Ночь = ", currentHours)               // Вывести в лог текст "Сейчас Ночь ="  и число "часов"
              dev["pump_"+grow_box+"/day"] = false;                     // выключить (false)
           }
         }  
});
// после отладки правила и проверки его работоспособности строчки с log() можно отключить (удалить или поставить перед ними // ) чтобы не забивать лог файл контроллера ненужной информацией
//'Окончание отслеживания времени старта и стопа';

Возможно где-то кривое и собрано из нескольких других, но всё-таки…
Смысл в том, чтобы последовательно включать перемешивание раствора, полив и перерыв.
Продолжительность этого всего задаётся с помощью переменных
Проблема в том, что при изменении переменных не меняется продолжительность работы таймеров. Она меняется только в том случае, если перезапустить правило. При этом время начала и время окончания считывается корректно.
Контроллер WB-6.
Может я что-то упустил или неправильно написал?
Помогите пожалуйста. Спасибо!

Вы хотите чтобы за вас написали код который вы задумали?
wb-rules как работало так и работает …

Вот исправленная версия по быстрому вашего кода с некоторыми с пояснениями:

// Pump_PO_1.js
'use strict';
var grow_box = "_PO_1"; // Имя устройства

var pump_relay = "wb-mr6cu_36/K3"; // Реле перемешивания
var dimmer_relay = "wb-mr6cu_36/K2"; // Реле полива
var aeration_relay = "wb-mr6cu_36/K7"; // Реле аэрации
var stop_relay = "wb-mr6c_203/Input 1"; // Кнопка СТОП (Исправлено: было stop_reley)
var stop_lamp = "wb-mr6c_203/K1"; // Лампочка СТОП
var blizzer_relay_1 = "buzzer/enabled"; // Зуммер 1 (Исправлено: было blizzer_reley_1)
var blizzer_relay_2 = "wb-msw-v3_15/Buzzer"; // Зуммер 2 (Исправлено: было blizzer_reley_2)

var ps = new PersistentStorage("storage_" + grow_box, {global: true});

// Инициализация значений по умолчанию
if (ps["pump_start_time"] === undefined) ps["pump_start_time"] = "08:00";
if (ps["pump_stop_time"] === undefined) ps["pump_stop_time"] = "20:00";
if (ps["pump_duration"] === undefined) ps["pump_duration"] = 10; // минут (Исправлено: было sun_start_duration)
if (ps["watering_duration"] === undefined) ps["watering_duration"] = 5; // минут
if (ps["timeout_duration"] === undefined) ps["timeout_duration"] = 15; // минут (Исправлено: было time-out_duration)
if (ps["stop_duration"] === undefined) ps["stop_duration"] = 30; // минут
if (ps["work_enabled"] === undefined) ps["work_enabled"] = true; // Добавлено: общий флаг работы

// Элементы виртуального устройства
var deviceCells = {
    "Pump (start) time": {
        type: "text",
        readonly: false,
        value: ps["pump_start_time"],
    },
    "Pump (stop) time": {
        type: "text",
        readonly: false,
        value: ps["pump_stop_time"],
    },
    "Pump duration (min)": { // Исправлено название
        type: "range",
        min: 1,
        max: 120,
        readonly: false,
        value: parseInt(ps["pump_duration"]) || 10,
    },
    "Watering duration (min)": {
        type: "range",
        min: 1,
        max: 60,
        readonly: false,
        value: parseInt(ps["watering_duration"]) || 5,
    },
    "Timeout duration (min)": { // Исправлено название
        type: "range",
        min: 1,
        max: 120,
        readonly: false,
        value: parseInt(ps["timeout_duration"]) || 15,
    },
    "STOP duration (min)": {
        type: "range",
        min: 1,
        max: 240,
        readonly: false,
        value: parseInt(ps["stop_duration"]) || 30,
    },
    "Work enabled": { // Добавлено: общий переключатель работы
        type: "switch",
        value: ps["work_enabled"],
    },
    wateringON: {
        type: "switch",
        value: false,
        readonly: true,
    },
    pumpON: {
        type: "switch",
        value: false,
        readonly: true,
    },
    aeration: {
        type: "switch",
        value: false,
        readonly: true,
    },
    day: {
        type: "switch",
        value: false,
        readonly: true,
    },
    timeout: {
        type: "switch",
        value: false,
        readonly: true,
    },
    STOP: {
        type: "switch",
        value: false,
        readonly: true,
    },
    blizzer: {
        type: "switch",
        value: false,
        readonly: true,
    },
};

// Создаем виртуальное устройство
defineVirtualDevice("pump_" + grow_box, {
    title: "Pump " + grow_box,
    cells: deviceCells
});

// Правила для сохранения настроек
defineRule("Pump start time change", {
    whenChanged: "pump_" + grow_box + "/Pump (start) time",
    then: function(newValue) {
        ps["pump_start_time"] = newValue;
        log.info("Pump start time changed to:", newValue);
    }
});

defineRule("Pump stop time change", {
    whenChanged: "pump_" + grow_box + "/Pump (stop) time",
    then: function(newValue) {
        ps["pump_stop_time"] = newValue;
        log.info("Pump stop time changed to:", newValue);
    }
});

defineRule("Pump duration change", {
    whenChanged: "pump_" + grow_box + "/Pump duration (min)",
    then: function(newValue) {
        ps["pump_duration"] = parseInt(newValue);
        log.info("Pump duration changed to:", newValue);
    }
});

defineRule("Watering duration change", {
    whenChanged: "pump_" + grow_box + "/Watering duration (min)",
    then: function(newValue) {
        ps["watering_duration"] = parseInt(newValue);
        log.info("Watering duration changed to:", newValue);
    }
});

defineRule("Timeout duration change", {
    whenChanged: "pump_" + grow_box + "/Timeout duration (min)",
    then: function(newValue) {
        ps["timeout_duration"] = parseInt(newValue);
        log.info("Timeout duration changed to:", newValue);
    }
});

defineRule("STOP duration change", {
    whenChanged: "pump_" + grow_box + "/STOP duration (min)",
    then: function(newValue) {
        ps["stop_duration"] = parseInt(newValue);
        log.info("STOP duration changed to:", newValue);
    }
});

defineRule("Work enabled change", {
    whenChanged: "pump_" + grow_box + "/Work enabled",
    then: function(newValue) {
        ps["work_enabled"] = newValue;
        log.info("Work enabled changed to:", newValue);
        if (!newValue) {
            // При выключении останавливаем все процессы
            dev["pump_" + grow_box + "/pumpON"] = false;
            dev["pump_" + grow_box + "/wateringON"] = false;
            dev["pump_" + grow_box + "/timeout"] = false;
            dev["pump_" + grow_box + "/STOP"] = false;
        }
    }
});

// Основная логика работы
defineRule("day_start", {
    whenChanged: "pump_" + grow_box + "/day",
    then: function() {
        var device = "pump_" + grow_box;
        if (dev[device]["day"] && dev[device]["Work enabled"] && !dev[device]["STOP"]) {
            dev[device + "/pumpON"] = true;
        }
    }
});

defineRule("pumpON_change", {
    whenChanged: "pump_" + grow_box + "/pumpON",
    then: function() {
        var device = "pump_" + grow_box;
        if (dev[device]["pumpON"] && dev[device]["Work enabled"] && !dev[device]["STOP"]) {
            // Включаем перемешивание и аэрацию
            dev[pump_relay] = true;
            dev[aeration_relay] = true;
            dev[device + "/aeration"] = true;
            
            // Запускаем таймер перемешивания
            var duration = parseInt(dev[device + "/Pump duration (min)"]) * 60 * 1000;
            setTimeout(function() {
                if (dev[device]["pumpON"] && !dev[device]["STOP"]) {
                    dev[device + "/pumpON"] = false;
                }
            }, duration);
        } else {
            dev[pump_relay] = false;
        }
    }
});

defineRule("pumpON_to_watering", {
    whenChanged: "pump_" + grow_box + "/pumpON",
    then: function() {
        var device = "pump_" + grow_box;
        if (!dev[device]["pumpON"] && dev[device]["Work enabled"] && !dev[device]["STOP"]) {
            // Запускаем полив после перемешивания
            dev[device + "/wateringON"] = true;
        }
    }
});

defineRule("wateringON_change", {
    whenChanged: "pump_" + grow_box + "/wateringON",
    then: function() {
        var device = "pump_" + grow_box;
        if (dev[device]["wateringON"] && dev[device]["Work enabled"] && !dev[device]["STOP"]) {
            // Включаем полив
            dev[dimmer_relay] = true;
            
            // Запускаем таймер полива
            var duration = parseInt(dev[device + "/Watering duration (min)"]) * 60 * 1000;
            setTimeout(function() {
                if (dev[device]["wateringON"] && !dev[device]["STOP"]) {
                    dev[device + "/wateringON"] = false;
                }
            }, duration);
        } else {
            dev[dimmer_relay] = false;
        }
    }
});

defineRule("watering_to_timeout", {
    whenChanged: "pump_" + grow_box + "/wateringON",
    then: function() {
        var device = "pump_" + grow_box;
        if (!dev[device]["wateringON"] && dev[device]["Work enabled"] && !dev[device]["STOP"]) {
            // Выключаем аэрацию
            dev[aeration_relay] = false;
            dev[device + "/aeration"] = false;
            
            // Запускаем тайм-аут
            dev[device + "/timeout"] = true;
        }
    }
});

defineRule("timeout_change", {
    whenChanged: "pump_" + grow_box + "/timeout",
    then: function() {
        var device = "pump_" + grow_box;
        if (dev[device]["timeout"] && dev[device]["Work enabled"] && !dev[device]["STOP"]) {
            // Запускаем таймер тайм-аута
            var duration = parseInt(dev[device + "/Timeout duration (min)"]) * 60 * 1000;
            setTimeout(function() {
                if (dev[device]["timeout"] && !dev[device]["STOP"]) {
                    dev[device + "/timeout"] = false;
                }
            }, duration);
        }
    }
});

defineRule("timeout_to_pump", {
    whenChanged: "pump_" + grow_box + "/timeout",
    then: function() {
        var device = "pump_" + grow_box;
        if (!dev[device]["timeout"] && dev[device]["day"] && dev[device]["Work enabled"] && !dev[device]["STOP"]) {
            // Запускаем следующий цикл
            dev[device + "/pumpON"] = true;
        }
    }
});

// Логика кнопки STOP
defineRule("stop_button_pressed", {
    whenChanged: stop_relay,
    then: function() {
        if (dev[stop_relay]) {
            var device = "pump_" + grow_box;
            dev[device + "/STOP"] = true;
            dev[stop_lamp] = true;
        }
    }
});

defineRule("STOP_change", {
    whenChanged: "pump_" + grow_box + "/STOP",
    then: function() {
        var device = "pump_" + grow_box;
        if (dev[device]["STOP"]) {
            // Выключаем все реле
            dev[pump_relay] = false;
            dev[dimmer_relay] = false;
            dev[aeration_relay] = false;
            
            // Выключаем флаги процессов
            dev[device + "/pumpON"] = false;
            dev[device + "/wateringON"] = false;
            dev[device + "/timeout"] = false;
            dev[device + "/aeration"] = false;
            
            // Включаем зуммер на 1 секунду
            dev[blizzer_relay_1] = true;
            dev[blizzer_relay_2] = true;
            setTimeout(function() {
                dev[blizzer_relay_1] = false;
                dev[blizzer_relay_2] = false;
            }, 1000);
            
            // Запускаем таймер остановки
            var duration = parseInt(dev[device + "/STOP duration (min)"]) * 60 * 1000;
            setTimeout(function() {
                dev[device + "/STOP"] = false;
            }, duration);
            
            // Запускаем зуммер за 1 минуту до окончания STOP
            var buzzerDuration = (parseInt(dev[device + "/STOP duration (min)"]) - 1) * 60 * 1000;
            setTimeout(function() {
                if (dev[device]["STOP"]) {
                    dev[device + "/blizzer"] = true;
                }
            }, buzzerDuration);
        } else {
            dev[stop_lamp] = false;
            dev[device + "/blizzer"] = false;
        }
    }
});

defineRule("blizzer_change", {
    whenChanged: "pump_" + grow_box + "/blizzer",
    then: function() {
        var device = "pump_" + grow_box;
        if (dev[device]["blizzer"]) {
            dev[blizzer_relay_1] = true;
            dev[blizzer_relay_2] = true;
            
            // Выключаем зуммер через 30 секунд
            setTimeout(function() {
                dev[blizzer_relay_1] = false;
                dev[blizzer_relay_2] = false;
                dev[device + "/blizzer"] = false;
            }, 30000);
        } else {
            dev[blizzer_relay_1] = false;
            dev[blizzer_relay_2] = false;
        }
    }
});

// Контроль времени суток
defineRule("time_check", {
    when: cron('* * * * *'), // Проверяем каждую минуту
    then: function() {
        var device = "pump_" + grow_box;
        if (!dev[device]["Work enabled"] || dev[device]["STOP"]) {
            return;
        }
        
        var now = new Date();
        var currentHours = now.getHours();
        var currentMinutes = now.getMinutes();
        var currentTime = currentHours * 60 + currentMinutes;
        
        // Парсим время начала и окончания
        var startTime = dev[device + "/Pump (start) time"];
        var stopTime = dev[device + "/Pump (stop) time"];
        
        var startParts = startTime.split(':');
        var stopParts = stopTime.split(':');
        
        var startHour = parseInt(startParts[0]);
        var startMinute = parseInt(startParts[1]);
        var stopHour = parseInt(stopParts[0]);
        var stopMinute = parseInt(stopParts[1]);
        
        var startTotal = startHour * 60 + startMinute;
        var stopTotal = stopHour * 60 + stopMinute;
        
        // Определяем, день или ночь
        if (currentTime >= startTotal && currentTime < stopTotal) {
            if (!dev[device]["day"]) {
                dev[device + "/day"] = true;
                log.info("Day started");
            }
        } else {
            if (dev[device]["day"]) {
                dev[device + "/day"] = false;
                // Выключаем все процессы на ночь
                dev[device + "/pumpON"] = false;
                dev[device + "/wateringON"] = false;
                dev[device + "/timeout"] = false;
                dev[device + "/aeration"] = false;
                log.info("Night started");
            }
        }
    }
});

log.info("pump_" + grow_box + " STARTED ######################");

Основные исправления:

  1. Опечатки в именах переменных: stop_releystop_relay, blizzer_releyblizzer_relay
  2. Инициализация значений по умолчанию: Добавлены проверки на undefined
  3. Исправлены имена настроек: sun_start_durationpump_duration, time-out_durationtimeout_duration
  4. Использование правильных типов: Для длительностей теперь используется range с min/max
  5. Преобразование типов: Добавлены parseInt() для числовых значений
  6. Упрощена логика таймеров: Используется setTimeout вместо сложных правил с whenChanged
  7. Добавлен общий переключатель “Work enabled”: Для полного контроля работы системы
  8. Исправлена проверка времени: Правильно парсится время из формата “hh:mm”
  9. Убраны избыточные правила: Объединены дублирующиеся правила
  10. Добавлено логирование: Для отслеживания работы системы

Рекомендации по документации wb-rules:

  • Ознакомьтесь с официальной документацией
  • Особое внимание уделите разделам:
    • defineRule() и триггеры (when, whenChanged)
    • Работа с виртуальными устройствами (defineVirtualDevice())
    • Сохранение состояния (PersistentStorage)
    • Функция cron() для планирования

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

Здравствуйте. Спасибо за Ваш ответ и Ваш код. Смотрится и работает очень хорошо.
Нет, мне не надо было, чтобы за меня писали код. Я хотел, чтобы проверили и указали на ошибки.
Ошибки нашёл и исправил. Вам ещё раз спасибо за код. Некоторые “фишки“ позаимствую для будущего

Это функция “поддержки”?
Я бы на месте WB просто отправлял бы к интеграторам …

P.S. просто несколько раз (и вообще когда столкнетесь с проблемой) перечитайте документацию (там не много) с начала и до конца. Плюс в вики есть примеры использования …
И по максимуму “упрощайте”. Саму логику.

P.S. Если на улице идет или планируется дождь поливать надо?
А если почва уже влажная?
А температура и влажность воздуха имеет значение для полива?

Ну, когда есть время - можно и написать что-нибудь. Просто для поддержания компетенций, оговорив что “это пример, может быть непригоден для продуктового применения”.

Судя по логике - это для гидропоники, не думаю что дождь возможен.

Ну я и “исправил” код … Но не факт что понял что именно нужно и из изначального кода (там слишком все не очень понятно …).

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

Спасибо за такое внимание к теме)
Действительно, возможно, это и не напрямую вопрос в поддержку тк сам продукт WB работает исправно, а правило, как таковое, не является продуктом WB, а является продуктом того, кто его создаёт и разбираться в таких проблемах, поддержка WB, не обязана. Вопросов нет)
Но когда мы только начинали нашу деятельность и выбирали автоматику, то помощь тех.поддержки в написании первых правил (довольно сложных, если честно) была очень кстати.
То правило, с которым я обратился - это правило для поливов на сити-ферме. Чтобы вместо того, чтобы добавлять кучу отдельных правил для полива и не забивать каждый полив отдельно, была идея такого цикла. То есть цикл работает в течении дня и в нём есть перемешивание раствора в баке, полив на линии и перерыв.
Отдельно установлены кнопки с лампочками. Нажимая на кнопку, выключаются все реле и не запускаются в течении определённого времени, загорается лапочка “стоп“.
Близзер - для сигнала об скором включении и продолжении цикла работы. Важно при нажатии на кнопку не останавливать таймеры, а исключительно отключить и не включать реле.
Может в скором времени я сделаю какое видео на эту тему и выложу сюда, но, вероятнее всего, это появится в какой-то из статей WB на Хабр).
Ниже выложу код, на котором сейчас остановился, прогоняю и отслеживаю.

//Pump_PO_1.js
//‘use strict’;
var grow_box = “PO_1"; // CHANGE_ME! имя устройства. Выводится в заголовок окна и служит для разделения устройств
log.info("pump”+grow_box+" START ######################"); //Это лог.

var pump_relay = “wb-mr6cu_36/K3”; //CHANGE_ME! устройство-реле питания диммера (перемешивание)
var dimmer_relay = “wb-mr6cu_36/K2”; //CHANGE_ME! устройство-реле питания диммера (полив)
var aeration_relay = “wb-mr6cu_36/K7”; //CHANGE_ME! устройство-реле питания диммера (аэрация)
var stop_reley = “wb-mr6c_203/Input 1”; //CHANGE_ME! устройство-реле кнопки СТОП
var stop_lamp = “wb-mr6c_203/K1”; //CHANGE_ME! устройство-лампочка
var blizzer_reley_1 = “buzzer/enabled”; //CHANGE_ME! устройство-близзер
var blizzer_reley_2 = “wb-msw-v3_15/Buzzer”; //CHANGE_ME! устройство-близзер

var ps = new PersistentStorage(“storage_”+grow_box, {global: true});// Определим объект-хранилище.

// Инициализация значений в хранилище, если они не существуют
if (ps[“pump_start_time”] === undefined) ps[“pump_start_time”] = “06:00”;
if (ps[“pump_stop_time”] === undefined) ps[“pump_stop_time”] = “22:00”;
if (ps[“pump_duration”] === undefined) ps[“pump_duration”] = “5”;
if (ps[“watering_duration”] === undefined) ps[“watering_duration”] = “10”;
if (ps[“timeout_duration”] === undefined) ps[“timeout_duration”] = “30”;
if (ps[“stop_duration”] === undefined) ps[“stop_duration”] = “2”;

//Элементы виртуального устройства управления
var deviceCells = {

//Начало перемешивания hh:mm
“Pump (start) time”: {
type: “text”,
readonly: false,
value: ps[“pump_start_time”],
},

“Pump (stop) time”: {
type: “text”,
readonly: false,
value: ps[“pump_stop_time”],
},

//Длительность перемешивания
“Pump duration”: {
type: “text”,
readonly: false,
value: ps[“pump_duration”],
},

//Длительность полива
“Watering duration”: {
type: “text”,
readonly: false,
value: ps[“watering_duration”],
},

//Длительность перерыва
“Time-out duration”: {
type: “text”,
readonly: false,
value: ps[“timeout_duration”], // Исправлено: дефис в имени переменной
},

//Длительность СТОПа
“STOP duration”: {
type: “text”,
readonly: false,
value: ps[“stop_duration”],
},

wateringON: {
type: “switch”,
value: false,
},

pumpON: {
type: “switch”,
value: false,
},

aeration: {
type: “switch”,
value: false,
},

day: {
type: “switch”,
value: false,
},

timeout: {
type: “switch”,
value: false,
},

work: {
type: “switch”,
value: false,
},

STOP: {
type: “switch”,
value: false,
},

blizzer: {
type: “switch”,
value: false,
},
};

//Создадим виртуальное устройство и добавим в него элементы
defineVirtualDevice(“pump_”+grow_box, {
title: "Pump "+grow_box,
cells: deviceCells
});

// Правила для сохранения значений в хранилище
defineRule(“Pump start time change”, {
whenChanged: “pump_”+grow_box+“/Pump (start) time”,
then: function (newValue, devName, cellName) {
log.info(“pump_”+grow_box+“/Pump start time”, newValue);
ps[“pump_start_time”] = newValue;
}
});

defineRule(“Pump stop time change”, {
whenChanged: “pump_”+grow_box+“/Pump (stop) time”,
then: function (newValue, devName, cellName) {
log.info(“pump_”+grow_box+“/Pump stop time”, newValue);
ps[“pump_stop_time”] = newValue;
}
});

defineRule(“Pump duration change”, { // Добавлено: отсутствовало правило
whenChanged: “pump_”+grow_box+“/Pump duration”,
then: function (newValue, devName, cellName) {
log.info(“pump_”+grow_box+“/Pump duration”, newValue);
ps[“pump_duration”] = newValue;
}
});

defineRule(“Watering duration change”, {
whenChanged: “pump_”+grow_box+“/Watering duration”,
then: function (newValue, devName, cellName) {
log.info(“pump_”+grow_box+“/Watering duration”, newValue);
ps[“watering_duration”] = newValue;
}
});

defineRule(“Time-out duration change”, {
whenChanged: “pump_”+grow_box+“/Time-out duration”,
then: function (newValue, devName, cellName) {
log.info(“pump_”+grow_box+“/Time-out duration”, newValue);
ps[“timeout_duration”] = newValue; // Исправлено
}
});

defineRule(“STOP duration change”, {
whenChanged: “pump_”+grow_box+“/STOP duration”,
then: function (newValue, devName, cellName) {
log.info(“pump_”+grow_box+“/STOP duration”, newValue);
ps[“stop_duration”] = newValue;
}
});

// Правила управления реле
defineRule(“day_start”, {
whenChanged: “pump_”+grow_box+“/day”,
then: function (newValue, devName, cellName) {
if (newValue == true) {
dev[“pump_”+grow_box+“/pumpON”] = true;
}
}
});

defineRule(“pumpON_changed”, {
whenChanged: “pump_”+grow_box+“/pumpON”,
then: function (newValue, devName, cellName) {
if (newValue == true && dev[“pump_”+grow_box][“STOP”] == false) {
dev[pump_relay] = true;
dev[aeration_relay] = true;
dev[“pump_”+grow_box+“/aeration”] = true;
} else if (newValue == false) {
dev[pump_relay] = false;
dev[“pump_”+grow_box+“/wateringON”] = true;
}
}
});

defineRule(“pumpON_changed_1”, {
whenChanged: “pump_”+grow_box+“/pumpON”,
then: function (newValue, devName, cellName) {
if (newValue == true && dev[“pump_”+grow_box][“STOP”] == true) {
dev[“pump_”+grow_box+“/aeration”] = true;
} else if (newValue == false && dev[“pump_”+grow_box][“STOP”] == true) {
dev[“pump_”+grow_box+“/wateringON”] = true;
}
}
});

defineRule(“wateringON_changed”, {
whenChanged: “pump_”+grow_box+“/wateringON”,
then: function (newValue, devName, cellName) {
if (newValue == true && dev[“pump_”+grow_box][“STOP”] == false) {
dev[dimmer_relay] = true;
} else if (newValue == false) {
dev[dimmer_relay] = false;
dev[aeration_relay] = false;
dev[“pump_”+grow_box+“/aeration”] = false;
dev[“pump_”+grow_box+“/timeout”] = true;
}
}
});

defineRule(“wateringON_changed_1”, {
whenChanged: “pump_”+grow_box+“/wateringON”,
then: function (newValue, devName, cellName) {
if (newValue == true && dev[“pump_”+grow_box][“STOP”] == true) {
dev[dimmer_relay] = false;
} else if (newValue == false && dev[“pump_”+grow_box][“STOP”] == true) {
dev[dimmer_relay] = false;
dev[aeration_relay] = false;
dev[“pump_”+grow_box+“/aeration”] = false;
dev[“pump_”+grow_box+“/timeout”] = true;
}
}
});

defineRule(“timeout_changed”, {
whenChanged: “pump_”+grow_box+“/timeout”,
then: function (newValue, devName, cellName) {
if (newValue == false && dev[“pump_”+grow_box][“day”] == true) {
dev[“pump_”+grow_box+“/pumpON”] = true;
}
}
});

defineRule(“stop_button_pressed”, {
whenChanged: stop_reley,
then: function (newValue, devName, cellName) {
if (newValue == true) {
dev[stop_lamp] = true;
dev[“pump_” + grow_box+“/STOP”] = true;
}
}
});

defineRule(“STOP_changed”, {
whenChanged: “pump_”+grow_box+“/STOP”,
then: function (newValue, devName, cellName) {
if (newValue == true) {
dev[stop_lamp] = true;
dev[pump_relay] = false;
dev[aeration_relay] = false;
dev[dimmer_relay] = false;
dev[“pump_” + grow_box + “/blizzer”] = true;
} else {
dev[stop_lamp] = false;
dev[blizzer_reley_1] = false;
dev[blizzer_reley_2] = false;
}
}
});

defineRule(“blizzer_changed”, {
whenChanged: “pump_”+grow_box+“/blizzer”,
then: function (newValue, devName, cellName) {
if (newValue == false) {
dev[blizzer_reley_1] = true;
dev[blizzer_reley_2] = true;
}
}
});

// Таймеры
// Таймер для перемешивания
var motion_timer_1_id = null;
defineRule(“motion_detector_1”, {
whenChanged: “pump_” + grow_box + “/pumpON”,
then: function (newValue, devName, cellName) {
if (newValue == true) {
if (motion_timer_1_id) {
clearTimeout(motion_timer_1_id);
}
var duration = parseInt(dev[“pump_”+grow_box+“/Pump duration”]) || 5;
var timeout_ms = duration * 60 * 1000;
motion_timer_1_id = setTimeout(function () {
dev[“pump_” + grow_box+“/pumpON”] = false;
motion_timer_1_id = null;
}, timeout_ms);
}
}
});

// Таймер для полива
var motion_timer_2_id = null;
defineRule(“motion_detector_2”, {
whenChanged: “pump_” + grow_box + “/wateringON”,
then: function (newValue, devName, cellName) {
if (newValue == true) {
if (motion_timer_2_id) {
clearTimeout(motion_timer_2_id);
}
var duration = parseInt(dev[“pump_”+grow_box+“/Watering duration”]) || 5;
var timeout_ms = duration * 60 * 1000;
motion_timer_2_id = setTimeout(function () {
dev[“pump_” + grow_box+“/wateringON”] = false;
motion_timer_2_id = null;
}, timeout_ms);
}
}
});

// Таймер для тайм-аута
var motion_timer_3_id = null;
defineRule(“motion_detector_3”, {
whenChanged: “pump_” + grow_box + “/timeout”,
then: function (newValue, devName, cellName) {
if (newValue == true) {
if (motion_timer_3_id) {
clearTimeout(motion_timer_3_id);
}
var duration = parseInt(dev[“pump_”+grow_box+“/Time-out duration”]) || 30;
var timeout_ms = duration * 60 * 1000;
motion_timer_3_id = setTimeout(function () {
dev[“pump_” + grow_box+“/timeout”] = false;
motion_timer_3_id = null;
}, timeout_ms);
}
}
});

// Таймер для СТОПа
var motion_timer_4_id = null;
defineRule(“motion_detector_4”, {
whenChanged: “pump_” + grow_box + “/STOP”,
then: function (newValue, devName, cellName) {
if (newValue == true) {
if (motion_timer_4_id) {
clearTimeout(motion_timer_4_id);
}
var duration = parseInt(dev[“pump_”+grow_box+“/STOP duration”]) || 2;
var timeout_ms = duration * 60 * 1000;
motion_timer_4_id = setTimeout(function () {
dev[“pump_” + grow_box+“/STOP”] = false;
motion_timer_4_id = null;
}, timeout_ms);
}
}
});

// Таймер для близзера (за 1 минуту до конца STOP)
var motion_timer_5_id = null;
defineRule(“motion_detector_5”, {
whenChanged: “pump_” + grow_box + “/blizzer”,
then: function (newValue, devName, cellName) {
if (newValue == true) {
if (motion_timer_5_id) {
clearTimeout(motion_timer_5_id);
}
var stop_duration = parseInt(dev[“pump_”+grow_box+“/STOP duration”]) || 2;
var timeout_ms = (stop_duration * 60 - 60) * 1000; // За 1 минуту до конца
if (timeout_ms < 0) timeout_ms = 0;

  motion_timer_5_id = setTimeout(function () {
    dev["pump_" + grow_box+"/blizzer"] = false;
    motion_timer_5_id = null;
  }, timeout_ms);
}

}
});

// Отслеживание времени старта и стопа
defineRule(“time_on_off”, {
when: cron('*/30 * * * *'),                             // каждые 30 секунд..
then: function () {                                     // ..вызываем функцию
var currentTime = new Date();                         // получить и сохранить в переменную currentTime текущее системное время контроллера
var currentHours = currentTime.getUTCHours()+3;     // сохранить в переменную currentHours значение часа из currentTime + 3 часа (корректировка часового пояса на +3 часа для MSK. PS Если это нужно)
var currentMinutes = currentTime.getUTCMinutes();     // сохранить в переменную currentMinutes значение минут из currentTime (если нужно будет оперировать не только “часами”, но и “минутами”)

       if ( (currentHours >= dev["pump_"+grow_box+"/Pump (start) time"]) && (currentHours <= (dev["pump_"+grow_box+"/Pump (stop) time"]-1) && (dev["pump_"+grow_box]["work"] == true)) )        // если число "часов" больше или равно 6 и меньше или равно 18, т.е. текущее время от 6:00 до 18:59
       {
         log("Сейчас День = ", currentHours);                // Вывести в лог текст "Сейчас День =" и число "часов"
         dev["pump_"+grow_box+"/day"] = true;                       // включить (true)
       
       } else{                                               // иначе (т.е. вне диапазона 6..18 часов, от 19:00 до 5:59 )
 
          log ("Сейчас Ночь = ", currentHours)               // Вывести в лог текст "Сейчас Ночь ="  и число "часов"
          dev["pump_"+grow_box+"/day"] = false;                     // выключить (false)
       }
     }  

});

log.info(“pump_”+grow_box+" script loaded successfully");