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 )
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: Последнее известное состояние онлайн-статуса.
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.
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.