"""Константы и словари значений интеграции fglair (PROTOCOL §8).""" from __future__ import annotations from homeassistant.components.climate import HVACMode from pyfglair import Prop, State, Template from pyfglair.provision import REGIONS as _PROVISION_REGIONS DOMAIN = "fglair" CONF_HOST = "host" CONF_DEVICE_PORT = "device_port" CONF_DSN = "dsn" CONF_LANIP_KEY = "lanip_key" CONF_LANIP_KEY_ID = "lanip_key_id" CONF_MODEL = "model" CONF_TEMPLATE = "template" CONF_NAME = "name" CONF_LISTEN_PORT = "listen_port" CONF_KEEPALIVE_MS = "keepalive_ms" CONF_REGION = "region" CONF_EMAIL = "email" CONF_PASSWORD = "password" CONF_CONFIG_JSON = "config_json" CONF_OVERRIDES = "overrides" CONF_TEMP_STEP = "temp_step" CONF_FEATURES = "features" CONF_TEMP_MIN = "temp_min" CONF_TEMP_MAX = "temp_max" CONF_TEMP_NUM = "temp_num" CONF_TEMP_DEN = "temp_den" CONF_TEMP_OFFSET = "temp_offset" DEFAULT_DEVICE_PORT = 80 # 0 => свободный эфемерный порт: несколько ConfigEntry (несколько # кондиционеров) не конфликтуют; модулю фактический порт сообщается в # local_reg (PROTOCOL §1). DEFAULT_LISTEN_PORT = 0 DEFAULT_KEEPALIVE_MS = 15000 TRIAL_TIMEOUT = 10.0 REGIONS = sorted(_PROVISION_REGIONS) TRIAL_ERRORS = { "no_slots": "no_slots", "key_mismatch": "key_mismatch", "unreachable": "cannot_connect", "timeout": "timeout", "start_failed": "cannot_connect", "properties_missing": "properties_missing", } # --------------------------------------------------------------------------- # operation_mode (PROTOCOL §8.3): 0=OFF, 1=ON, 2=AUTO, 3=COOL, 4=DRY, # 5=FAN, 6=HEAT # --------------------------------------------------------------------------- OPERATION_MODE_OFF = 0 OPERATION_MODE_ON = 1 HVAC_MODE_TO_VALUE = { HVACMode.AUTO: 2, HVACMode.COOL: 3, HVACMode.DRY: 4, HVACMode.FAN_ONLY: 5, HVACMode.HEAT: 6, } HVAC_VALUE_TO_MODE = {value: mode for mode, value in HVAC_MODE_TO_VALUE.items()} # device_capabilities, биты (PROTOCOL §8.5) CAP_HVAC = { HVACMode.AUTO: 4, HVACMode.COOL: 0, HVACMode.DRY: 1, HVACMode.FAN_ONLY: 2, HVACMode.HEAT: 3, } CAP_FAN = {"auto": 5, "high": 6, "medium": 7, "low": 8, "quiet": 9} CAP_SWING_VERTICAL = 10 CAP_SWING_HORIZONTAL = 11 CAP_ECONOMY = 12 CAP_MIN_HEAT = 13 CAP_INDOOR_FAN_CONTROL = 14 CAP_POWERFUL = 16 CAP_OUTDOOR_LOW_NOISE = 17 CAP_COIL_DRY = 18 # fan_speed (PROTOCOL §8.3) FAN_VALUE_TO_MODE = {0: "quiet", 1: "low", 2: "medium", 3: "high", 4: "auto"} FAN_MODE_TO_VALUE = {mode: value for value, mode in FAN_VALUE_TO_MODE.items()} # preset: ECO = economy_mode, BOOST = powerful_mode PRESET_ECO = "eco" PRESET_BOOST = "boost" PRESET_PROP = { PRESET_ECO: Prop.ECONOMY_MODE, PRESET_BOOST: Prop.POWERFUL_MODE, } SWING_MODES = ["off", "on"] # switch-свойства: prop -> (translation_key, capability bit | None) SWITCH_PROPS: dict[Prop, tuple[str, int | None]] = { Prop.ECONOMY_MODE: ("economy_mode", CAP_ECONOMY), Prop.POWERFUL_MODE: ("powerful_mode", CAP_POWERFUL), Prop.COIL_DRY_MODE: ("coil_dry_mode", CAP_COIL_DRY), Prop.MIN_HEAT: ("min_heat", CAP_MIN_HEAT), Prop.OUTDOOR_LOW_NOISE: ("outdoor_low_noise", CAP_OUTDOOR_LOW_NOISE), Prop.HUMAN_DET_AUTO_SAVE: ("human_det_auto_save", None), Prop.WIFI_LED_ENABLE: ("wifi_led_enable", None), Prop.INDOOR_FAN_CONTROL: ("indoor_fan_control", CAP_INDOOR_FAN_CONTROL), } # --------------------------------------------------------------------------- # Feature-модель (план: страница capabilities в мастере + фильтрация сущностей). # key -> (capability bit | None, свойство-источник | None). # Для битовых фич дефолт = бит в device_capabilities; для небитовых — # наличие свойства в ответах устройства; для заслонок — num_dir > 1. # --------------------------------------------------------------------------- FEATURES: dict[str, tuple[int | None, Prop | None]] = { "mode_cool": (CAP_HVAC[HVACMode.COOL], Prop.OPERATION_MODE), "mode_dry": (CAP_HVAC[HVACMode.DRY], Prop.OPERATION_MODE), "mode_fan": (CAP_HVAC[HVACMode.FAN_ONLY], Prop.OPERATION_MODE), "mode_heat": (CAP_HVAC[HVACMode.HEAT], Prop.OPERATION_MODE), "mode_auto": (CAP_HVAC[HVACMode.AUTO], Prop.OPERATION_MODE), "fan_quiet": (CAP_FAN["quiet"], Prop.FAN_SPEED), "fan_low": (CAP_FAN["low"], Prop.FAN_SPEED), "fan_medium": (CAP_FAN["medium"], Prop.FAN_SPEED), "fan_high": (CAP_FAN["high"], Prop.FAN_SPEED), "fan_auto": (CAP_FAN["auto"], Prop.FAN_SPEED), "swing_vertical": (CAP_SWING_VERTICAL, Prop.AF_VERTICAL_SWING), "swing_horizontal": (CAP_SWING_HORIZONTAL, Prop.AF_HORIZONTAL_SWING), "economy_mode": (CAP_ECONOMY, Prop.ECONOMY_MODE), "min_heat": (CAP_MIN_HEAT, Prop.MIN_HEAT), "indoor_fan_control": (CAP_INDOOR_FAN_CONTROL, Prop.INDOOR_FAN_CONTROL), "powerful_mode": (CAP_POWERFUL, Prop.POWERFUL_MODE), "outdoor_low_noise": (CAP_OUTDOOR_LOW_NOISE, Prop.OUTDOOR_LOW_NOISE), "coil_dry_mode": (CAP_COIL_DRY, Prop.COIL_DRY_MODE), "display_temperature": (None, Prop.DISPLAY_TEMPERATURE), "human_det_auto_save": (None, Prop.HUMAN_DET_AUTO_SAVE), "wifi_led_enable": (None, Prop.WIFI_LED_ENABLE), "af_vertical_direction": (None, Prop.AF_VERTICAL_DIRECTION), "af_horizontal_direction": (None, Prop.AF_HORIZONTAL_DIRECTION), } # Описания для мастера и для атрибута description сущностей. FEATURE_DESCRIPTIONS = { "ru": { "mode_cool": "Охлаждение", "mode_dry": "Осушение", "mode_fan": "Вентиляция (без нагрева/охлаждения)", "mode_heat": "Обогрев", "mode_auto": "Автоматический режим", "fan_auto": "Автоскорость вентилятора", "fan_quiet": "Тихая скорость", "fan_low": "Низкая скорость", "fan_medium": "Средняя скорость", "fan_high": "Высокая скорость", "swing_vertical": "Качание заслонки по вертикали", "swing_horizontal": "Качание заслонки по горизонтали", "economy_mode": "Экономичный режим", "min_heat": "Минимальный обогрев (поддержание +10 °C)", "indoor_fan_control": "Управление вентилятором при работе наружного блока", "powerful_mode": "Мощный режим (ускоренный выход на режим)", "outdoor_low_noise": "Тихий наружный блок", "coil_dry_mode": "Сушка испарителя", "display_temperature": "Датчик температуры помещения", "human_det_auto_save": "Автосохранение при отсутствии людей (датчик присутствия)", "wifi_led_enable": "Индикатор Wi-Fi на модуле", "af_vertical_direction": "Выбор положения вертикальной заслонки", "af_horizontal_direction": "Выбор положения горизонтальной заслонки", }, "en": { "mode_cool": "Cooling", "mode_dry": "Dry", "mode_fan": "Fan only", "mode_heat": "Heating", "mode_auto": "Automatic mode", "fan_auto": "Auto fan speed", "fan_quiet": "Quiet fan speed", "fan_low": "Low fan speed", "fan_medium": "Medium fan speed", "fan_high": "High fan speed", "swing_vertical": "Vertical louver swing", "swing_horizontal": "Horizontal louver swing", "economy_mode": "Economy mode", "min_heat": "Minimum heat (keep +10 °C)", "indoor_fan_control": "Indoor fan control while outdoor unit runs", "powerful_mode": "Powerful mode", "outdoor_low_noise": "Outdoor unit low noise", "coil_dry_mode": "Coil dry", "display_temperature": "Room temperature sensor", "human_det_auto_save": "Human detection auto save", "wifi_led_enable": "Wi-Fi LED indicator", "af_vertical_direction": "Vertical louver position", "af_horizontal_direction": "Horizontal louver position", }, } ENTITY_DESCRIPTIONS = { "ru": { "climate": "Управление кондиционером: режим, скорость, уставка, " "заслонки, пресеты", "room_temperature": "Температура воздуха в помещении", "error_code": "Код ошибки кондиционера (0 — ошибок нет)", "connection_state": "Состояние связи с модулем кондиционера", "connectivity": "Есть ли связь с модулем", "defrost": "Идёт разморозка наружного блока", "maintenance": "Требуется обслуживание", "oil_recovery": "Возврат масла в компрессор", "pump_down": "Откачка хладагента (pump down)", "check_operation": "Проверочный прогон", "simultaneous": "Одновременные операции", "different_modes": "Разморозка/масло/прочие режимы (шаблон B)", }, "en": { "climate": "Air conditioner control: mode, fan, setpoint, louvers, presets", "room_temperature": "Room air temperature", "error_code": "Air conditioner error code (0 = no errors)", "connection_state": "Connection state with the AC module", "connectivity": "Whether the module is reachable", "defrost": "Outdoor unit defrost in progress", "maintenance": "Maintenance required", "oil_recovery": "Compressor oil recovery", "pump_down": "Refrigerant pump down", "check_operation": "Check operation", "simultaneous": "Simultaneous operations", "different_modes": "Defrost/oil/other modes (template B)", }, } def entity_description(language: str, key: str) -> str | None: lang = "ru" if str(language).lower().startswith("ru") else "en" return ENTITY_DESCRIPTIONS[lang].get(key) or FEATURE_DESCRIPTIONS[lang].get( key ) # op_status, биты (PROTOCOL §8.4): translation_key -> bit OP_STATUS_BITS: dict[str, int] = { "defrost": 24, "maintenance": 22, "oil_recovery": 28, "pump_down": 29, "check_operation": 30, "simultaneous": 25, "different_modes": 21, } # Уставка: фактические ограничения бытового прибора (PROTOCOL §8.3 [LEGACY]); # единицы API = 0.1 °C. TEMP_MIN_TENTHS = 160 TEMP_MAX_TENTHS = 300 TEMP_STEP_TENTHS = { Template.A: 5, Template.B: 10, Template.F: 5, } # Состояния, в которых сущности доступны (PROTOCOL/план §5). AVAILABLE_STATES = (State.ONLINE, State.RECOVERING)