ha(ux): мастер из трёх страниц, feature-модель и capabilities-фильтрация
- config flow: template (A/B/F с пояснениями, значения с устройства, определение по oem_model; для неизвестных моделей — пробинг A/B/F тремя короткими сессиями) -> capabilities (23 тумблера с описаниями, дефолты из device_capabilities/num_dir/ответов) -> limits (диапазон/шаг, ручная конверсия); каждая страница с пометкой «значения определены автоматически, можно пропустить» - features.py: FeatureSet/LiveValues/device_default/resolve_features; entry.data["features"] хранит выбор пользователя; reconfigure предзаполняет; YAML-import получает дефолты - сущности создаются только для включённых фич: climate (режимы/скорости/ swing/пресеты), switch, select заслонок (caps+num_dir), датчик комнаты; исправлено появление select без ламелей - trial: caps/num_dir и presence-зонды (необязательные свойства), answered; координатор ждёт первые свойства перед созданием сущностей (feature- дефолты без гонки) - атрибут description у сущностей (HA не поддерживает тултипы) + описания фич в мастере (en/ru) - тесты: features, probing, обновлённые flow/entities/repairs; 57 components
This commit is contained in:
@@ -24,6 +24,7 @@ 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"
|
||||
@@ -112,6 +113,131 @@ SWITCH_PROPS: dict[Prop, tuple[str, int | 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,
|
||||
|
||||
Reference in New Issue
Block a user