Files
Cyborg2017 b0e2681c4e feat: add vacuum platform support with vacuum.py implementation
- Add Platform.VACUUM to supported platforms list
- Implement vacuum.py with core functionality
- Update device registry to handle vacuum devices
2026-02-09 21:09:16 +08:00

196 lines
7.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from homeassistant.components.vacuum import (
StateVacuumEntity,
VacuumEntityFeature,
VacuumActivity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .core.logger import MideaLogger
from .midea_entity import MideaEntity
from . import load_device_config
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up vacuum entities for Midea devices."""
# 账号型 entry从 __init__ 写入的 accounts 桶加载设备和协调器
account_bucket = hass.data.get(DOMAIN, {}).get("accounts", {}).get(config_entry.entry_id)
if not account_bucket:
async_add_entities([])
return
device_list = account_bucket.get("device_list", {})
coordinator_map = account_bucket.get("coordinator_map", {})
devs = []
for device_id, info in device_list.items():
device_type = info.get("type")
sn8 = info.get("sn8")
config = await load_device_config(hass, device_type, sn8) or {}
entities_cfg = (config.get("entities") or {}).get(Platform.VACUUM, {})
manufacturer = config.get("manufacturer")
rationale = config.get("rationale")
coordinator = coordinator_map.get(device_id)
device = coordinator.device if coordinator else None
for entity_key, ecfg in entities_cfg.items():
devs.append(MideaVacuumEntity(
coordinator, device, manufacturer, rationale, entity_key, ecfg
))
async_add_entities(devs)
class MideaVacuumEntity(MideaEntity, StateVacuumEntity):
def __init__(self, coordinator, device, manufacturer, rationale, entity_key, config):
super().__init__(
coordinator,
device.device_id,
device.device_name,
f"T0x{device.device_type:02X}",
device.sn,
device.sn8,
device.model,
entity_key,
device=device,
manufacturer=manufacturer,
rationale=rationale,
config=config,
)
self._key_battery_level = self._config.get("battery_level")
self._key_status = self._config.get("status")
self._key_fan_speeds = self._config.get("fan_speeds")
#self._key_locate = self._config.get("locate")
#self._key_clean_spot = self._config.get("clean_spot")
#self._key_map = self._config.get("map")
@property
def supported_features(self):
features = VacuumEntityFeature(0)
features |= VacuumEntityFeature.STOP
features |= VacuumEntityFeature.PAUSE
features |= VacuumEntityFeature.START
features |= VacuumEntityFeature.RETURN_HOME
features |= VacuumEntityFeature.FAN_SPEED
features |= VacuumEntityFeature.STATUS
features |= VacuumEntityFeature.BATTERY
#features |= VacuumEntityFeature.LOCATE
#features |= VacuumEntityFeature.CLEAN_SPOT
#features |= VacuumEntityFeature.MAP
return features
@property
def battery_level(self):
"""Return the battery level of the vacuum cleaner."""
battery = self._get_nested_value(self._key_battery_level)
if battery is not None:
try:
return int(battery)
except (ValueError, TypeError):
return None
return None
@property
def status(self):
"""Return the status of the vacuum cleaner."""
status = self._get_nested_value(self._key_status)
if status is not None:
return status
return None
@property
def state(self):
"""Return the state of the vacuum cleaner."""
status = self.status
if not status:
return None
# Map Midea status to Home Assistant states
status_mapping = {
# === 清洁中状态 (CLEANING) ===
"work": VacuumActivity.CLEANING, # 清扫中
"auto_clean": VacuumActivity.CLEANING, # 自动清扫中
# === 已停靠状态 (DOCKED) ===
"charging_on_dock": VacuumActivity.DOCKED, # 座充中
"on_base": VacuumActivity.DOCKED, # 在基站上
"charge_finish": VacuumActivity.DOCKED, # 充电完成
# === 空闲状态 (IDLE) ===
"stop": VacuumActivity.IDLE, # 已停止
"sleep": VacuumActivity.IDLE, # 休眠中
# === 暂停状态 (PAUSED) ===
"clean_pause": VacuumActivity.PAUSED, # 清扫暂停
"charge_pause": VacuumActivity.PAUSED, # 充电暂停
# === 返回中状态 (RETURNING) ===
"charging": VacuumActivity.RETURNING, # 返回基站中
# === 错误状态 (ERROR) ===
"error": VacuumActivity.ERROR, # 错误
}
return status_mapping.get(status, status)
@property
def fan_speed(self):
"""Return the current fan speed."""
return self._dict_get_selected(self._key_fan_speeds)
@property
def fan_speed_list(self):
"""Return the list of available fan speeds."""
return list(self._key_fan_speeds.keys())
async def async_start(self):
"""Start or resume the cleaning task."""
# 设置为工作状态
if self._key_status:
await self.async_set_attribute(self._key_status, "work")
else:
await self._async_set_status_on_off(self._key_power, True)
async def async_stop(self):
"""Stop the vacuum cleaner."""
# 设置为停止状态
if self._key_status:
await self.async_set_attribute(self._key_status, "stop")
else:
await self._async_set_status_on_off(self._key_power, False)
async def async_pause(self):
"""Pause the cleaning task."""
# 设置为暂停状态
if self._key_status:
await self.async_set_attribute(self._key_status, "pause")
async def async_return_to_base(self):
"""Return the vacuum cleaner to its base."""
# 设置为回基站状态
if self._key_status:
await self.async_set_attribute(self._key_status, "charge")
async def async_set_fan_speed(self, fan_speed: str):
"""Set the fan speed."""
new_status = self._key_fan_speeds.get(fan_speed)
if new_status is not None:
await self.async_set_attributes(new_status)
#async def async_locate(self):
#"""Locate the vacuum cleaner."""
# 定位设备
# 具体实现取决于设备的控制方式
#if hasattr(self, "_key_locate"):
#await self.async_set_attribute(self._key_locate, True)
#async def async_clean_spot(self):
#"""Perform a clean spot."""
# 执行定点清扫
# 具体实现取决于设备的控制方式
#if hasattr(self, "_key_clean_spot"):
#await self.async_set_attribute(self._key_clean_spot, True)