Assistants.dehumidifier

Ассистент контроля осушителя.

Включает осушитель при превышении влажности верхнего порога и выключает при снижении ниже нижнего порога (гистерезис). Датчик влажности встроен в само устройство.

  1"""Ассистент контроля осушителя.
  2
  3Включает осушитель при превышении влажности верхнего порога
  4и выключает при снижении ниже нижнего порога (гистерезис).
  5Датчик влажности встроен в само устройство.
  6"""
  7
  8from e_lib.assistants import Assistant
  9from langfuse import observe
 10from loguru import logger
 11
 12from Controllers import DehumidifierController
 13from Messengers.bot import Bot
 14
 15
 16class DehumidifierAssistant(Assistant):
 17    """Контролирует осушитель на основе встроенного датчика влажности.
 18
 19    Логика гистерезиса:
 20    - Включает осушитель, когда влажность превысила верхний порог.
 21    - Выключает осушитель, когда влажность снизилась ниже нижнего порога.
 22    - Уведомляет при потере онлайна устройства.
 23
 24    Attributes:
 25        dehumidifier: Контроллер осушителя (содержит и датчик, и управление).
 26        humidity_threshold_high: Верхний порог — включать осушитель.
 27        humidity_threshold_low: Нижний порог — выключать осушитель.
 28        bot: Бот для отправки уведомлений.
 29        last_online: Последнее известное состояние онлайн-статуса.
 30    """
 31
 32    def __init__(
 33        self,
 34        name: str,
 35        dehumidifier: DehumidifierController,
 36        humidity_threshold_high: float = 60,
 37        humidity_threshold_low: float = 50,
 38        bot: Bot | None = None,
 39    ):
 40        super().__init__(name)
 41        self.dehumidifier = dehumidifier
 42        self.humidity_threshold_high = humidity_threshold_high
 43        self.humidity_threshold_low = humidity_threshold_low
 44        self.bot = bot
 45        self.last_online: bool | None = None
 46
 47    @observe(name=f"Цикл контроля для {__qualname__}")
 48    def run(self) -> None:
 49        logger.debug(f'Запуск цикла контроля влажности для "{self.name}"...')
 50
 51        state = self.dehumidifier.get_state()
 52        if not state or state.get("humidity") is None:
 53            logger.error(
 54                f'Не удалось получить влажность, пропускаем цикл "{self.name}"'
 55            )
 56            return
 57
 58        online = state.get("online") == "online"
 59        if (
 60            self.last_online is not None
 61            and self.last_online
 62            and not online
 63            and self.bot
 64        ):
 65            self.bot.send_message(text=f'Осушитель "{self.name}" не в сети')
 66        self.last_online = online
 67
 68        if not online:
 69            logger.warning(f'Осушитель "{self.name}" не в сети, пропускаем контроль')
 70            return
 71
 72        humidity = state["humidity"]
 73        current_power = state.get("power", False)
 74        temperature = state.get("temperature")
 75
 76        if current_power:
 77            should_turn_on = humidity > self.humidity_threshold_low
 78        else:
 79            should_turn_on = humidity > self.humidity_threshold_high
 80
 81        if current_power != should_turn_on:
 82            success = self.dehumidifier.control_dehumidifier(should_turn_on)
 83            if not success:
 84                logger.error(
 85                    f'Цикл "{self.name}" завершен с ошибкой управления осушителем'
 86                )
 87                return
 88            action = "включен" if should_turn_on else "выключен"
 89            temp_text = (
 90                f", температура {temperature}°C" if temperature is not None else ""
 91            )
 92            message = (
 93                f"Влажность {humidity}%{temp_text}, пороги: {self.humidity_threshold_low}%–"
 94                f"{self.humidity_threshold_high}%. Осушитель {action}"
 95            )
 96            logger.info(message)
 97            if self.bot:
 98                self.bot.send_message(text=message)
 99        else:
100            temp_text = (
101                f", температура {temperature}°C" if temperature is not None else ""
102            )
103            logger.debug(
104                f'Цикл "{self.name}" завершен: влажность {humidity}%{temp_text}, '
105                f"осушитель {'включен' if current_power else 'выключен'}"
106            )
class DehumidifierAssistant(e_lib.assistants.base.Assistant):
 17class DehumidifierAssistant(Assistant):
 18    """Контролирует осушитель на основе встроенного датчика влажности.
 19
 20    Логика гистерезиса:
 21    - Включает осушитель, когда влажность превысила верхний порог.
 22    - Выключает осушитель, когда влажность снизилась ниже нижнего порога.
 23    - Уведомляет при потере онлайна устройства.
 24
 25    Attributes:
 26        dehumidifier: Контроллер осушителя (содержит и датчик, и управление).
 27        humidity_threshold_high: Верхний порог — включать осушитель.
 28        humidity_threshold_low: Нижний порог — выключать осушитель.
 29        bot: Бот для отправки уведомлений.
 30        last_online: Последнее известное состояние онлайн-статуса.
 31    """
 32
 33    def __init__(
 34        self,
 35        name: str,
 36        dehumidifier: DehumidifierController,
 37        humidity_threshold_high: float = 60,
 38        humidity_threshold_low: float = 50,
 39        bot: Bot | None = None,
 40    ):
 41        super().__init__(name)
 42        self.dehumidifier = dehumidifier
 43        self.humidity_threshold_high = humidity_threshold_high
 44        self.humidity_threshold_low = humidity_threshold_low
 45        self.bot = bot
 46        self.last_online: bool | None = None
 47
 48    @observe(name=f"Цикл контроля для {__qualname__}")
 49    def run(self) -> None:
 50        logger.debug(f'Запуск цикла контроля влажности для "{self.name}"...')
 51
 52        state = self.dehumidifier.get_state()
 53        if not state or state.get("humidity") is None:
 54            logger.error(
 55                f'Не удалось получить влажность, пропускаем цикл "{self.name}"'
 56            )
 57            return
 58
 59        online = state.get("online") == "online"
 60        if (
 61            self.last_online is not None
 62            and self.last_online
 63            and not online
 64            and self.bot
 65        ):
 66            self.bot.send_message(text=f'Осушитель "{self.name}" не в сети')
 67        self.last_online = online
 68
 69        if not online:
 70            logger.warning(f'Осушитель "{self.name}" не в сети, пропускаем контроль')
 71            return
 72
 73        humidity = state["humidity"]
 74        current_power = state.get("power", False)
 75        temperature = state.get("temperature")
 76
 77        if current_power:
 78            should_turn_on = humidity > self.humidity_threshold_low
 79        else:
 80            should_turn_on = humidity > self.humidity_threshold_high
 81
 82        if current_power != should_turn_on:
 83            success = self.dehumidifier.control_dehumidifier(should_turn_on)
 84            if not success:
 85                logger.error(
 86                    f'Цикл "{self.name}" завершен с ошибкой управления осушителем'
 87                )
 88                return
 89            action = "включен" if should_turn_on else "выключен"
 90            temp_text = (
 91                f", температура {temperature}°C" if temperature is not None else ""
 92            )
 93            message = (
 94                f"Влажность {humidity}%{temp_text}, пороги: {self.humidity_threshold_low}%–"
 95                f"{self.humidity_threshold_high}%. Осушитель {action}"
 96            )
 97            logger.info(message)
 98            if self.bot:
 99                self.bot.send_message(text=message)
100        else:
101            temp_text = (
102                f", температура {temperature}°C" if temperature is not None else ""
103            )
104            logger.debug(
105                f'Цикл "{self.name}" завершен: влажность {humidity}%{temp_text}, '
106                f"осушитель {'включен' if current_power else 'выключен'}"
107            )

Контролирует осушитель на основе встроенного датчика влажности.

Логика гистерезиса:

  • Включает осушитель, когда влажность превысила верхний порог.
  • Выключает осушитель, когда влажность снизилась ниже нижнего порога.
  • Уведомляет при потере онлайна устройства.

Attributes: dehumidifier: Контроллер осушителя (содержит и датчик, и управление). humidity_threshold_high: Верхний порог — включать осушитель. humidity_threshold_low: Нижний порог — выключать осушитель. bot: Бот для отправки уведомлений. last_online: Последнее известное состояние онлайн-статуса.

DehumidifierAssistant( name: str, dehumidifier: Controllers.dehumidifier.DehumidifierController, humidity_threshold_high: float = 60, humidity_threshold_low: float = 50, bot: Messengers.bot.Bot | None = None)
33    def __init__(
34        self,
35        name: str,
36        dehumidifier: DehumidifierController,
37        humidity_threshold_high: float = 60,
38        humidity_threshold_low: float = 50,
39        bot: Bot | None = None,
40    ):
41        super().__init__(name)
42        self.dehumidifier = dehumidifier
43        self.humidity_threshold_high = humidity_threshold_high
44        self.humidity_threshold_low = humidity_threshold_low
45        self.bot = bot
46        self.last_online: bool | None = None

Initialize the assistant.

Args: name: Assistant name (defaults to "Ассистент без имени"). logger: Logger for messages; defaults to a standard-library logger for this module. Projects may pass their own logger (e.g. a loguru logger) to keep messages in the project's log sinks.

dehumidifier
humidity_threshold_high
humidity_threshold_low
bot
last_online: bool | None
@observe(name=f'Цикл контроля для {__qualname__}')
def run(self) -> None:
 48    @observe(name=f"Цикл контроля для {__qualname__}")
 49    def run(self) -> None:
 50        logger.debug(f'Запуск цикла контроля влажности для "{self.name}"...')
 51
 52        state = self.dehumidifier.get_state()
 53        if not state or state.get("humidity") is None:
 54            logger.error(
 55                f'Не удалось получить влажность, пропускаем цикл "{self.name}"'
 56            )
 57            return
 58
 59        online = state.get("online") == "online"
 60        if (
 61            self.last_online is not None
 62            and self.last_online
 63            and not online
 64            and self.bot
 65        ):
 66            self.bot.send_message(text=f'Осушитель "{self.name}" не в сети')
 67        self.last_online = online
 68
 69        if not online:
 70            logger.warning(f'Осушитель "{self.name}" не в сети, пропускаем контроль')
 71            return
 72
 73        humidity = state["humidity"]
 74        current_power = state.get("power", False)
 75        temperature = state.get("temperature")
 76
 77        if current_power:
 78            should_turn_on = humidity > self.humidity_threshold_low
 79        else:
 80            should_turn_on = humidity > self.humidity_threshold_high
 81
 82        if current_power != should_turn_on:
 83            success = self.dehumidifier.control_dehumidifier(should_turn_on)
 84            if not success:
 85                logger.error(
 86                    f'Цикл "{self.name}" завершен с ошибкой управления осушителем'
 87                )
 88                return
 89            action = "включен" if should_turn_on else "выключен"
 90            temp_text = (
 91                f", температура {temperature}°C" if temperature is not None else ""
 92            )
 93            message = (
 94                f"Влажность {humidity}%{temp_text}, пороги: {self.humidity_threshold_low}%–"
 95                f"{self.humidity_threshold_high}%. Осушитель {action}"
 96            )
 97            logger.info(message)
 98            if self.bot:
 99                self.bot.send_message(text=message)
100        else:
101            temp_text = (
102                f", температура {temperature}°C" if temperature is not None else ""
103            )
104            logger.debug(
105                f'Цикл "{self.name}" завершен: влажность {humidity}%{temp_text}, '
106                f"осушитель {'включен' if current_power else 'выключен'}"
107            )

Perform one processing cycle.

Must be overridden in a subclass.