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:
@@ -16,10 +16,6 @@ from pyfglair import Prop
|
||||
from pyfglair.templates import prop_info
|
||||
|
||||
from .const import (
|
||||
CAP_FAN,
|
||||
CAP_HVAC,
|
||||
CAP_SWING_HORIZONTAL,
|
||||
CAP_SWING_VERTICAL,
|
||||
FAN_MODE_TO_VALUE,
|
||||
FAN_VALUE_TO_MODE,
|
||||
HVAC_MODE_TO_VALUE,
|
||||
@@ -27,7 +23,6 @@ from .const import (
|
||||
OPERATION_MODE_OFF,
|
||||
OPERATION_MODE_ON,
|
||||
PRESET_BOOST,
|
||||
PRESET_CAP,
|
||||
PRESET_ECO,
|
||||
PRESET_PROP,
|
||||
SWING_MODES,
|
||||
@@ -41,13 +36,24 @@ async def async_setup_entry(hass, entry, async_add_entities) -> None:
|
||||
async_add_entities([FglairClimate(runtime.coordinator)])
|
||||
|
||||
|
||||
MODE_FEATURE = {
|
||||
HVACMode.AUTO: "mode_auto",
|
||||
HVACMode.COOL: "mode_cool",
|
||||
HVACMode.DRY: "mode_dry",
|
||||
HVACMode.FAN_ONLY: "mode_fan",
|
||||
HVACMode.HEAT: "mode_heat",
|
||||
}
|
||||
FAN_FEATURE = {mode: f"fan_{mode}" for mode in FAN_VALUE_TO_MODE.values()}
|
||||
PRESET_FEATURE = {PRESET_ECO: "economy_mode", PRESET_BOOST: "powerful_mode"}
|
||||
|
||||
|
||||
class FglairClimate(FglairEntity, ClimateEntity):
|
||||
_attr_name = None
|
||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
|
||||
def __init__(self, coordinator: FglairCoordinator) -> None:
|
||||
# translation_key не нужен: имя = имя устройства (has_entity_name).
|
||||
super().__init__(coordinator, "climate", None)
|
||||
super().__init__(coordinator, "climate", None, description_key="climate")
|
||||
self._last_hvac_mode: Optional[HVACMode] = None
|
||||
|
||||
# -- свойства шаблона --------------------------------------------------
|
||||
@@ -56,37 +62,37 @@ class FglairClimate(FglairEntity, ClimateEntity):
|
||||
|
||||
def _hvac_modes(self) -> list[HVACMode]:
|
||||
modes: list[HVACMode] = [HVACMode.OFF]
|
||||
for mode, bit in CAP_HVAC.items():
|
||||
if self.supports_capability(bit):
|
||||
for mode, key in MODE_FEATURE.items():
|
||||
if self.feature_enabled(key):
|
||||
modes.append(mode)
|
||||
return modes
|
||||
|
||||
def _fan_modes(self) -> Optional[list[str]]:
|
||||
if not self._in_template(Prop.FAN_SPEED):
|
||||
return None
|
||||
return [
|
||||
mode
|
||||
for mode, bit in CAP_FAN.items()
|
||||
if self.supports_capability(bit)
|
||||
modes = [
|
||||
mode for mode, key in FAN_FEATURE.items()
|
||||
if self.feature_enabled(key)
|
||||
]
|
||||
return modes or None
|
||||
|
||||
def _preset_modes(self) -> Optional[list[str]]:
|
||||
presets = [
|
||||
preset
|
||||
for preset, bit in PRESET_CAP.items()
|
||||
for preset, key in PRESET_FEATURE.items()
|
||||
if self._in_template(PRESET_PROP[preset])
|
||||
and self.supports_capability(bit)
|
||||
and self.feature_enabled(key)
|
||||
]
|
||||
return presets or None
|
||||
|
||||
def _vertical_swing_supported(self) -> bool:
|
||||
return self._in_template(Prop.AF_VERTICAL_SWING) and (
|
||||
self.supports_capability(CAP_SWING_VERTICAL)
|
||||
self.feature_enabled("swing_vertical")
|
||||
)
|
||||
|
||||
def _horizontal_swing_supported(self) -> bool:
|
||||
return self._in_template(Prop.AF_HORIZONTAL_SWING) and (
|
||||
self.supports_capability(CAP_SWING_HORIZONTAL)
|
||||
self.feature_enabled("swing_horizontal")
|
||||
)
|
||||
|
||||
# -- ClimateEntity ----------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user