Автоматическая система сброса теплой воды для фильтров обратного осмоса

Друзья, в одной из моих квартир недавно возникла проблема с температурой холодной воды, и с тех пор она не была решена. Возможно, в системе центрального водоснабжения моего дома горячая вода где-то подмешивается в трубу с холодной водой, и из-за этого из крана холодной воды поступает вода с температурой 36–39 градусов.

Такая повышенная температура из трубы холодной воды негативно сказывается на работе моей системы очистки воды методом обратного осмоса (ОС), а также на работу моего устройства ионизации воды, так как оно подключено после трех префильтров ОС. По паспорту, в систему ОС можно подавать воду до 38 градусов, а в устройство ионизации воды — до 30 градусов Цельсия. На практике рекомендуется использовать воду с температурой 4–30 °C для оптимальной работы системы ОС. Также температура воды в 25-35 °C может способствовать активному росту бактерий в накопительном баке системы обратного осмоса, но это решается установкой UV-фильтра.

После слива такой воды из крана в течение 5 минут вода становится около 27 градусов Цельсия. Было решено сделать автоматическую систему сброса теплой воды на базе ESP32 и Home Assistant.

Что вам понадобится

Шаг 1 : Изготавливаем температурный датчик

Температурный сенсор DS18B20

Возьмите температурный сенсор и припаяйте к нему трехжильный сигнальный провод. Не забудьте про маркировку контактов, чтобы знать, где Data, Ground и VDC. Закрепите сенсор на металлическом патрубке с помощью термоусадки. Сам патрубок соедините с двумя фитингами 1/4BSP – 1/4 Hose. Затем поместите патрубок в термоизоляцию.

Температурный сенсор прикрепленный к патрубку 1/4 BSP с помощью термоусадки

А вот и готовые термодатчики (дополнительный термодатчик я сделал для другого проекта):

Готовый термодатчик

Термодатчики

Шаг 2 : Собираем блок манифольда

Блок манифольда

Боксы для электрических шаровых кранов у всех будут свои, поэтому количество соединительных фитингов будет разным. В моем случае я купил контейнер для хранения с крышкой, просверлил в нем три отверстия под трубки 1/4”, а также четыре отверстия для вилки разъема GX12 на корпус. В этот бокс я поместил температурный датчик, два электрических шаровых крана, расходомер и соединил все фитингами для систем обратного осмоса. Провода электрических шаровых кранов, термодатчика и расходомера припаял к соответствующим выходам вилок разъемов GX12.

Шаг 3 : Пайка блока управления

Блок управления

Здесь также все предельно просто. В боксе просверлите соответствующие отверстия под GX12, светодиоды и кабель питания 220VAC. Соберите компоненты согласно схеме. Полноразмерную схему скачайте отсюда.

Задняя сторона блока управления

Задняя сторона блока управления

Шаг 4 : Заливаем программу в ESP32

Подсоедините ESP32 к ноутбуку, откройте Arduino IDE и загрузите следующий скетч:

#include <WiFi.h>
extern "C" {
  #include "freertos/FreeRTOS.h"
  #include "freertos/timers.h"
}
#include <AsyncMqttClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define WIFI_SSID "Your_WiFi_SSID"
#define WIFI_PASSWORD "Your_WiFi_Password"
IPAddress staticIP(192, 168, 0, XXX);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns(192, 168, 0, 1);

// Home Assistant Mosquitto MQTT Broker
#define MQTT_HOST IPAddress(192, 168, 0, XXX)
#define MQTT_PORT 1883
#define MQTT_USER "Your_MQTT_Username"
#define MQTT_PASSWORD "Your_MQTT_Password"

// MQTT Topics
#define MQTT_TOPIC_WATER_TEMPERATURE "homeassistant/ro_system/water_temperature"
#define MQTT_TOPIC_RO_SOLENOID "homeassistant/ro_system/ro_solenoid"
#define MQTT_TOPIC_DRAINAGE_SOLENOID "homeassistant/ro_system/drainage_solenoid"
#define MQTT_TOPIC_RO_PUMP "homeassistant/ro_system/ro_pump"
#define MQTT_TOPIC_DUMPED_WATER_INTERVAL_VOLUME "homeassistant/ro_system/dumped_water_interval_volume"
#define MQTT_TOPIC_SYSTEM_STATE "homeassistant/ro_system/system_state"
#define MQTT_TOPIC_DUMP_TIME "homeassistant/ro_system/dump_time"
#define MQTT_TOPIC_DUMP_TEMP_THRESHOLD "homeassistant/ro_system/dump_temp_threshold"

// GPIO pins for solenoids
#define RO_SOLENOID_PIN 26
#define DRAINAGE_SOLENOID_PIN 25

// GPIO where the DS18B20 is connected to
#define ONE_WIRE_BUS 27

// GPIO where Hall Sensor is connected to
#define FLOW_METER_PIN 33
volatile int pulseCount = 0; // Count of Hall Sensor pulses

// GPIO LEDS
#define RO_BLUE_LED 15
#define DRAINAGE_RED_LED 2
#define DUMP_TIMEOUT_RED_LED 4

// GPIO for RO PUMP
#define RO_PUMP_PIN 18

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);

// Temperature value
float water_temperature;

bool ro_solenoid_status = true; // true for opened, false for closed. RO solenoid is normally opened.
bool drainage_solenoid_status = false; // true for opened, false for closed. Drainage solenoid is normally closed.
bool ro_pump_status = true; // true for ON, false for OFF
bool ro_pump_delayed_start = false; // false for no delayed start initiated
bool system_error_state = false; // false for no errors

AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;

unsigned long previous_millis = 0;   // Stores last time temperature was published
unsigned long previous_millis_r = 0; // Stores last time RO solenoid was opened
unsigned long previous_millis_d = 0; // Stores last time Drainage solenoid was opened
const long interval = 10000;         // 10 seconds interval at which to publish sensor readings
long dump_time = 600000; // Initial dump time set for 10 minutes
float dump_temp_threshold = 29; // Initial dump temp threshold

String solenoid_open_name = "Открыто";
String solenoid_closed_name = "Закрыто";
String status_ro_water_supply_name = "Подача воды в обратный осмос";
String status_water_dump_timeout_name = "Превышение времени сброса";
String status_water_dump_in_progress_name = "Сброс тёплой воды";
int status_ro_pump_on = 1, status_ro_pump_off = 0, is_mqtt3 = 0;
String deviceName = "ESP32RO";

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.mode(WIFI_STA);
  WiFi.hostname(deviceName);
  WiFi.config(staticIP, gateway, subnet);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void connectToMqtt() {
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

void WiFiEvent(WiFiEvent_t event) {
  Serial.printf("[WiFi-event] event: %dn", event);
  switch(event) {
    case SYSTEM_EVENT_STA_GOT_IP:
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      connectToMqtt();
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      Serial.println("WiFi lost connection");
      xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
      xTimerStart(wifiReconnectTimer, 0);
      break;
  }
}

void onMqttConnect(bool sessionPresent) {
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);
  uint16_t packetIdSub = mqttClient.subscribe(MQTT_TOPIC_DUMP_TIME, 2);
  Serial.print("Subscribing at QoS 2, packetId: ");
  Serial.println(packetIdSub);
  uint16_t packetIdSub1 = mqttClient.subscribe(MQTT_TOPIC_DUMP_TEMP_THRESHOLD, 2);
  Serial.print("Subscribing at QoS 2, packetId: ");
  Serial.println(packetIdSub1);
  uint16_t packetIdSub2 = mqttClient.subscribe(MQTT_TOPIC_RO_PUMP, 2);
  Serial.print("Subscribing at QoS 2, packetId: ");
  Serial.println(packetIdSub2);
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");
  if (WiFi.isConnected()) {
    xTimerStart(mqttReconnectTimer, 0);
  }
}

void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
  Serial.println("Subscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  Serial.print("  qos: ");
  Serial.println(qos);
}
void onMqttUnsubscribe(uint16_t packetId) {
  Serial.println("Unsubscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
  if (String(topic) == "homeassistant/ro_system/dump_time") {
  String message1 = "";
  for (size_t i = 0; i < len; i++) {
    message1 += (char)payload[i];
  }
   dump_time = message1.toInt()*60000;
  }

  if (String(topic) == "homeassistant/ro_system/dump_temp_threshold") {
  String message2 = "";
  for (size_t i = 0; i < len; i++) {
    message2 += (char)payload[i];
  }
   dump_temp_threshold = message2.toFloat();
  }

 if (String(topic) == MQTT_TOPIC_RO_PUMP) {
  String message3 = "";
  for (size_t i = 0; i < len; i++) {
    message3 += (char)payload[i];
  }
   if (message3.toInt() == 0) ro_pump_status = false; else ro_pump_status = true;
   is_mqtt3 = 1;
  }
}

void onMqttPublish(uint16_t packetId) {
  Serial.println("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup() {

  pinMode(FLOW_METER_PIN, INPUT_PULLUP); // Enable pull-up resistor
  attachInterrupt(digitalPinToInterrupt(FLOW_METER_PIN), pulseCounter, FALLING); // Assign pulseCounter to interrupt

  pinMode(RO_SOLENOID_PIN, OUTPUT);
  pinMode(DRAINAGE_SOLENOID_PIN, OUTPUT);
  pinMode(RO_BLUE_LED, OUTPUT);
  pinMode(DRAINAGE_RED_LED, OUTPUT);
  pinMode(DUMP_TIMEOUT_RED_LED, OUTPUT);
  pinMode(RO_PUMP_PIN, OUTPUT);

  digitalWrite(RO_SOLENOID_PIN, LOW);
  digitalWrite(DRAINAGE_SOLENOID_PIN, LOW);
  digitalWrite(RO_BLUE_LED, HIGH);
  digitalWrite(DRAINAGE_RED_LED, HIGH);
  digitalWrite(DUMP_TIMEOUT_RED_LED, LOW);
  digitalWrite(RO_PUMP_PIN, LOW);

  // Start the DS18B20 sensor
  sensors.begin();

  Serial.begin(115200);
  Serial.println();
  Serial.println();

  mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt));
  wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi));

  WiFi.onEvent(WiFiEvent);

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  mqttClient.onSubscribe(onMqttSubscribe);
  mqttClient.onUnsubscribe(onMqttUnsubscribe);
  mqttClient.onMessage(onMqttMessage);
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  mqttClient.setCredentials(MQTT_USER, MQTT_PASSWORD);
  connectToWifi();
}

void loop() {

if (ro_pump_status == false && is_mqtt3 == 1) {
  digitalWrite(RO_PUMP_PIN, HIGH);
  is_mqtt3 = 0;
}

if (ro_pump_status == true && is_mqtt3 == 1) {
  digitalWrite(RO_PUMP_PIN, LOW);
  is_mqtt3 = 0;
}

  // Get current millis()
  unsigned long current_millis = millis();

  // Check if it's time to take a new data readings
  if (current_millis - previous_millis >= interval) {

    // Record the time of the reading
    previous_millis = current_millis;

    float intervalVolume = pulseCount * 0.1622168797; // Convert pulse count to millilitres
    pulseCount = 0; // Reset pulse count

    // Take a temperature reading
    sensors.requestTemperatures();
    water_temperature = sensors.getTempCByIndex(0);
    Serial.print("Water temp: ");
    Serial.println(water_temperature);
    Serial.print("Interval volume: ");
    Serial.println(intervalVolume);

    // Publish volume of dumped water for the last 10 seconds to MQTT
    mqttClient.publish(MQTT_TOPIC_DUMPED_WATER_INTERVAL_VOLUME, 2, false, String(intervalVolume).c_str());
    // Publish the temperature reading to MQTT
    mqttClient.publish(MQTT_TOPIC_WATER_TEMPERATURE, 2, false, String(water_temperature).c_str());
    // Publish RO pump state to MQTT
    if (ro_pump_status == true) {
      mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_on).c_str()); } else {
      mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_off).c_str());
    }

    // Publish system state to MQTT
    if (ro_solenoid_status == false && drainage_solenoid_status == true && system_error_state == false) {
      // Publish system state to MQTT. Water dump in progress
      mqttClient.publish(MQTT_TOPIC_SYSTEM_STATE, 2, false, status_water_dump_in_progress_name.c_str());
    } else if (ro_solenoid_status == true && drainage_solenoid_status == false && system_error_state == false) {
      // Publish system state to MQTT. RO water supply
      mqttClient.publish(MQTT_TOPIC_SYSTEM_STATE, 2, false, status_ro_water_supply_name.c_str());
    } else {
      // Publish system error state to MQTT
      mqttClient.publish(MQTT_TOPIC_SYSTEM_STATE, 2, false, status_water_dump_timeout_name.c_str());
    }

    // Check if the temperature is above 29 degrees
    if (water_temperature > dump_temp_threshold && system_error_state == false) {

      // Close RO solenoid
      if (digitalRead(RO_SOLENOID_PIN) != HIGH) {
        // Switch off Blue RO LED
        digitalWrite(RO_BLUE_LED, LOW);
        // Close RO solenoid
        digitalWrite(RO_SOLENOID_PIN, HIGH);
        // Update the RO solenoid status
        ro_solenoid_status = false;
        // Publish RO solenoid status to MQTT
        mqttClient.publish(MQTT_TOPIC_RO_SOLENOID, 2, false, solenoid_closed_name.c_str());
      }

      // Open Drainage solenoid
      if (digitalRead(DRAINAGE_SOLENOID_PIN) != HIGH) {
        previous_millis_d = current_millis;
        // Switch off Red Drainage LED
        digitalWrite(DRAINAGE_RED_LED, LOW);
        // Open Drainage solenoid
        digitalWrite(DRAINAGE_SOLENOID_PIN, HIGH);
        // Update the Drainage solenoid status
        drainage_solenoid_status = true;
        // Publish Drainage solenoid status to MQTT
        mqttClient.publish(MQTT_TOPIC_DRAINAGE_SOLENOID, 2, false, solenoid_open_name.c_str());
      }

      // Switch OFF RO pump
      if (digitalRead(RO_PUMP_PIN) != HIGH) {
        // Switch OFF RO pump
        digitalWrite(RO_PUMP_PIN, HIGH);
        // Update the RO Pump status
        ro_pump_status = false;
        // Publish RO pump state to MQTT
        mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_off).c_str());
      }

    } else if (water_temperature < (dump_temp_threshold - 2) && system_error_state == false) {

      // Open RO solenoid
      if (digitalRead(RO_SOLENOID_PIN) != LOW) {
        previous_millis_r = current_millis;
        // Open RO solenoid
        digitalWrite(RO_SOLENOID_PIN, LOW);
        // Switch on Blue RO LED
        digitalWrite(RO_BLUE_LED, HIGH);
        // Update the RO solenoid status
        ro_solenoid_status = true;
        // Update the RO Pump delayed start status
        ro_pump_delayed_start = true;
        // Publish RO solenoid status to MQTT
        mqttClient.publish(MQTT_TOPIC_RO_SOLENOID, 2, false, solenoid_open_name.c_str());
      }

      // Close Drainage solenoid
      if (digitalRead(DRAINAGE_SOLENOID_PIN) != LOW) {
        // Close Drainage solenoid
        digitalWrite(DRAINAGE_SOLENOID_PIN, LOW);
        // Switch on Red Drainage LED
        digitalWrite(DRAINAGE_RED_LED, HIGH);
        // Update the Drainage solenoid status
        drainage_solenoid_status = false;
        // Publish Drainage solenoid status to MQTT
        mqttClient.publish(MQTT_TOPIC_DRAINAGE_SOLENOID, 2, false, solenoid_closed_name.c_str());
      }
    } // End of ELSE IF

    // Delayed start of RO pump after 15 seconds
    if (ro_pump_delayed_start == true && system_error_state == false && current_millis - previous_millis_r >= 15000 ) {
      // Switch ON RO pump
      digitalWrite(RO_PUMP_PIN, LOW);
      // Update the RO Pump delayed start status
      ro_pump_delayed_start = false;
      // Update the RO Pump status
      ro_pump_status = true;
      // Publish RO pump state to MQTT
      mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_on).c_str());
    }

    // Check if dump continues for more than XX minutes set in HA
    if (drainage_solenoid_status == true && system_error_state == false && current_millis - previous_millis_d >= dump_time) {
      // Close Drainage solenoid if it has been open for more than XX minutes set in HA
      digitalWrite(DRAINAGE_SOLENOID_PIN, LOW);
      // Switch on Red Drainage LED
      digitalWrite(DRAINAGE_RED_LED, HIGH);
      // Switch on Red Timeout LED
      digitalWrite(DUMP_TIMEOUT_RED_LED, HIGH);

      // Update the solenoid status variable
      drainage_solenoid_status = false;
      system_error_state = true;

      //Publish Drainage solenoid status to MQTT
      mqttClient.publish(MQTT_TOPIC_DRAINAGE_SOLENOID, 2, false, solenoid_closed_name.c_str());
    }

  }
}

void pulseCounter() {
  pulseCount++; // Increment pulse count
}

Все указанные библиотеки в скетче должны быть установлены заранее. Обратите внимание, что в формуле intervalVolume = pulseCount * 0.1622168797, коэффициент 0.1622168797 означает количество миллилитров за каждый оборот турбинки расходомера.

Шаг 5 : Настраиваем Home Assistant

 

Связь между ESP32 и Home Assistant (HA) осуществляется через MQTT-брокер. В HA создайте следующую карточку:

type: entities
entities:
  - entity: sensor.water_temperature
    secondary_info: last-changed
    name: Температура воды
    icon: mdi:water
  - entity: sensor.ro_system_state
    secondary_info: last-changed
    name: Статус системы
    icon: mdi:water-alert
  - entity: sensor.ro_solenoid_status
    secondary_info: last-changed
    name: Соленоид осмоса
    icon: mdi:pipe-valve
  - entity: sensor.drainage_solenoid_status
    secondary_info: last-changed
    name: Соленоид сброса
    icon: mdi:pipe-valve
  - entity: switch.ro_pump
    secondary_info: last-changed
    name: Насос
    icon: mdi:pump
  - entity: input_number.dump_temp_threshold
    secondary_info: last-changed
    name: Порог температуры
  - entity: input_number.dump_time
    name: Макс. время сброса
    secondary_info: last-changed
  - entity: sensor.water_dump_counts_for_today
    secondary_info: last-changed
    name: Количество сбросов за сегодня
  - entity: sensor.average_dump_time_today
    secondary_info: last-changed
    name: Среднее время сброса
    icon: mdi:timer
show_header_toggle: false
title: Обратный осмос
state_color: true

В configuration.yaml добавьте следующие строки:

sensor:
  - platform: template
    sensors:
      average_dump_time_today:
        unit_of_measurement: 'мин.'
        friendly_name: "Average dump time today"
        value_template: "{{ ((states('sensor.water_dumps_total_time_for_today')|float / states('sensor.water_dump_counts_for_today')|float) * 60)|round(1) }}"
  - platform: history_stats      
    name: Water dump counts for today
    entity_id: sensor.ro_system_state
    state: "Сброс тёплой воды"
    type: count
    start: "{{ now().replace(hour=0, minute=0, second=0) }}"
    end: "{{ now() }}"
  - platform: history_stats
    name: Water dumps total time for today
    entity_id: sensor.ro_system_state
    state: "Сброс тёплой воды"
    type: time
    start: "{{ now().replace(hour=0, minute=0, second=0) }}"
    end: "{{ now() }}"
input_number:
  dump_time:
    name: Dump time
    mode: slider
    unit_of_measurement: "мин."
    icon: mdi:timer
    min: 10
    max: 20
    step: 1
  dump_temp_threshold:
    name: Dump temp threshold
    mode: slider
    unit_of_measurement: "°C"
    icon: mdi:thermometer
    min: 22
    max: 31
    step: 0.1

В automations.yaml добавьте следующее:

- id: 'XXXXXXXXXXXX1'
  alias: Отправить значение максимального времени сброса воды через MQTT
  description: ''
  trigger:
  - platform: state
    entity_id: input_number.dump_time
  condition: []
  action:
  - data:
      topic: homeassistant/ro_system/dump_time
      payload: '{{ states(''input_number.dump_time'') }}'
      retain: true
    action: mqtt.publish
  mode: single
- id: 'XXXXXXXXXXXX2'
  alias: Отправить значение порога температуры воды через MQTT
  description: ''
  trigger:
  - platform: state
    entity_id: input_number.dump_temp_threshold
  condition: []
  action:
  - data:
      topic: homeassistant/ro_system/dump_temp_threshold
      payload: '{{ states(''input_number.dump_temp_threshold'') }}'
      retain: true
    action: mqtt.publish
  mode: single
- id: 'XXXXXXXXXXXX3'
  alias: Установить значение максимального времени сброса воды из MQTT на слайдере
  description: ''
  trigger:
  - platform: mqtt
    topic: homeassistant/ro_system/dump_time
  condition: []
  action:
    service: input_number.set_value
    data_template:
      entity_id: input_number.dump_time
      value: '{{ trigger.payload }}'
  mode: single
- id: 'XXXXXXXXXXXX4'
  alias: Установить значение порога температуры воды из MQTT на слайдере
  description: ''
  trigger:
  - platform: mqtt
    topic: homeassistant/ro_system/dump_temp_threshold
  condition: []
  action:
  - service: input_number.set_value
    data_template:
      entity_id: input_number.dump_temp_threshold
      value: '{{ trigger.payload }}'
  mode: single

Шаг 6 : Подключаем систему обратного осмоса

Подключите трубку подачи воды от холодной воды к входу блока манифольда. Выход от электрического шарового крана (НО) подключите к входу обратного осмоса, а выход от электрического шарового крана (НЗ) подключите к трубке дренажа через Т-фиттинг. Затем соедините блок манифольда с блоком управления и протестируйте систему. В моем случае в системе обратного осмоса присутствует насос подкачки, и он также подключен к блоку управления. Если термодатчик зафиксирует превышение температуры поступающей воды, то подача воды на обратный осмос закроется, и параллельно начнется сброс воды в дренаж. Также блок управления отключит насос подкачки обратного осмоса. После падения температуры воды произойдет обратный процесс, и насос подкачки включится через 15 секунд после начала закрытия электрических шаровых кранов. Если по какой-то причине температура не снизится ниже 2 градусов от заданной пороговой температуры на слайдере и в течение заданного времени сброса в Home Assistant, то сброс автоматически закроется, и на корпусе блока управления загорится красный светодиод ошибки.

P/S

Profit :)

Понравилась инструкция? Тогда поделитесь ей со своими друзьями или попробуйте написать свою собственную!

Регистрация на сайте

Оставьте свой отзыв

Вы должны Войти, чтобы оставлять отзывы.