Управление теплым полом и отоплением на кухне

Добрый день!
Написал скрипт управления теплым полом и отоплением кухни, но он не работает, скрипт во вложении. Не могу понять где ошибка, может кто-то подскажет.
Задача: есть кухня, где есть водяное отопление со своим контуром (датчик WB-MSW v3) и теплый электрический пол (датчик 1-Wire).
Хотелось бы включать электрический пол с 23.00-7.00 ежедневно,
а отопление в будни с 18.00-23.30 и в выходные с 9.00-23.30.
Конечно есть два гистерезиса по температурам, то есть когда реле М6С отключает теплый пол и когда поступает 24В от wb-gpio/EXT1_K1 на нормально-открытые сервопривода контура отопления.
Также есть:

  • три ползунка: первый активирует правило теплого пола, второй: активирует правило отопления, третий активирует режим отопления: выходной и будни;
  • два выключателя: один повешен на реле М6С (канал 5), второй повешен на клему контроллера А1_IN, на которую подано 5В.
    В приоритете над правилом являются выключатели и если они нажаты, то пол или отопление работают.
    Кухня-теплый пол и отопление.txt (16,5 КБ)

image

Доброго дня.
В первую очередь, я рекомендую все значения дат обновлять внутри whenChanged, в данном виде у вас значения фиксируются при сохранении скрипта и больше не меняются.

Во-вторых, пользуйтесь промежуточным выводом значений в консоль при помощи функции log(), проблему с датами вы бы давно таким образом заметили.

В коде есть небольшая ошибка в определении выходных дней. Дни недели в JavaScript начинаются с воскресенья (0), поэтому суббота будет 6, а воскресенье - 0.
Исправление: var isWeekend = (day == 6) || (day == 0);

Сравнение с true и false : В JavaScript прямое сравнение с true или false часто является излишним. Например, if (dev["wb-mr6c_149/Input 5"] == true) можно заменить на if (dev["wb-mr6c_149/Input 5"]). Это не ошибка, просто рекомендация для упрощения кода.

Повторяющиеся действия: В вашем коде есть множество условий, которые устанавливают одно и то же значение для dev["wb-gpio/EXT1_K1"] или dev["wb-mr6c_149/K5"]. Это может быть упрощено путем группировки условий.

Проверка условий времени: Вы используете date > date_start_floor и date < date_end_floor для проверки времени. Убедитесь, что это корректно отражает вашу логику, так как это будет сравнивать даты, включая день, месяц и год. Уточнение: Если вам нужно сравнивать только время, а не даты, вам придется преобразовать эти значения в формат, который сравнивает только часы и минуты.

Добрый день!
А что значит обнулять значения дат внутри whenchanged?

Для примера, оборачиваем запрос актуальных дат в отдельную функцию (привожу только часть кода):

function updateDateVariables() {
    var now = new Date();
    var date_start_floor = new Date(now);
    var date_end_floor = new Date(now);
    date_start_floor.setHours(23, 2, 0, 0); // Устанавливаем время начала работы теплого пола
    date_end_floor.setHours(6, 58, 0, 0); // Устанавливаем время окончания работы теплого пола
    
    // Возвращаем объект с обновленными временными переменными
    return {
        startFloor: date_start_floor,
        endFloor: date_end_floor
    };
}

и далее уже при каждом изменении значения температуры, запрашиваем актуальные даты.

defineRule("Heat_Floor_Kitchen", {
  whenChanged: "wb-w1/28-00000c19588c",
  then: function (newValue, devName, cellName) {
    
    // Код пропущен
    // Получаем обновленные временные переменные
    var dates = updateDateVariables();
    var now = new Date();
    if ((dev["wb-mr6c_149/Input 5"] == false) && (dev["Kitchen/RuleTempFloor"] == true)) {
      if (now > dates.startFloor && now < dates.endFloor && newValue < (dev["Kitchen/temp2"] - hysteresis_floor)) {
        dev["wb-mr6c_149/K5"] = true; // теплый пол работает
      } else {
        dev["wb-mr6c_149/K5"] = false; // теплый пол не работает
      }
    }
    
    // ... продолжение вашего кода
  }
});

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

Добрый день!
“Повторяющиеся действия: В вашем коде есть множество условий, которые устанавливают одно и то же значение…”

Напишите пожалуйста пример группировки условий.

Спасибо.

Добрый день! С ветвлениями и виртуальными устройствами разобрался, спасибо, но с датами и временем Ваш алгоритм мне не подошел.
Ваш пример работает для интервалов в рамках одних суток (например с 7.00 до 23.00), а если интервал в котором нужно работать устройству начинается в одних сутках и заканчивается в других, то получается в текущих сутках в логах такой результат:
INFO: [rule info] 2024-02-05 23:01:00.000+03:00 2024-02-06 06:58:00.000+03:00.
А как начнутся следующие сутки (после 00.00):
INFO: [rule info] 2024-02-06 23:01:00.000+03:00 2024-02-07 06:58:00.000+03:00.
То есть задача, чтобы теплый пол работал с 23.01 до 6.58. А по факту пол по примеру выше работает у меня с 23.01 до 00.00 и как начинаются новые сутки, даты в коде меняются (см. значение выше в логах).
Вместо 6.58 ставил 30.58, то есть 24+6, но это ничего не меняет.
Не подскажите как решить эту проблему?

Добрый день.
Мы не занимаемся написанием кода, к сожалению.
Но давайте натолкну на верный путь.
Надеюсь что у вас получится разобраться и адаптировать под свои задачи.

function isTimeBetween(startTime, endTime, now) {
    if (endTime < startTime) {
        // Переход через полночь
        return now >= startTime || now <= endTime;
    }
    return now >= startTime && now <= endTime;
}

defineRule("Heat_Floor_Kitchen", {
    whenChanged: "wb-w1/28-00000c19588c",
    then: function (newValue, devName, cellName) {
        var now = new Date();
        var todayStart = new Date(now);
        var todayEnd = new Date(now);
        var tomorrowStart = new Date(now);
        var tomorrowEnd = new Date(now);

        todayStart.setHours(23, 0, 0, 0); // Время начала работы теплого пола сегодня
        todayEnd.setHours(23, 59, 59, 999); // Конец сегодняшнего дня
        tomorrowStart.setHours(0, 0, 0, 0); // Начало следующего дня
        tomorrowEnd.setHours(7, 0, 0, 0); // Время окончания работы теплого пола завтра

        var isWorkingTimeToday = isTimeBetween(todayStart, todayEnd, now);
        var isWorkingTimeTomorrow = isTimeBetween(tomorrowStart, tomorrowEnd, now);

        var shouldHeat = (isWorkingTimeToday || isWorkingTimeTomorrow) && newValue < (dev["Kitchen/temp2"] - hysteresis_floor);

        dev["wb-mr6c_149/K5"] = shouldHeat;
    }
});

Для удобства обновление дат можно вынести в отдельную функцию, как мы делали ранее.
Я, к сожалению, не тестировал этот код в реальных условиях, но должно работать.