Files
Garbage-Collection-fr/custom_components/garbage_collection/__init__.py
T

186 lines
5.5 KiB
Python

"""Component to integrate with garbage_colection."""
from __future__ import annotations
import asyncio
import logging
from datetime import timedelta
from types import MappingProxyType
from typing import Any, Dict
import homeassistant.helpers.config_validation as cv
import homeassistant.util.dt as dt_util
import voluptuous as vol
from dateutil.relativedelta import relativedelta
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_HIDDEN, CONF_ENTITIES, CONF_ENTITY_ID, WEEKDAYS
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers.typing import ConfigType
from . import const, helpers
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
months = [m["value"] for m in const.MONTH_OPTIONS]
frequencies = [f["value"] for f in const.FREQUENCY_OPTIONS]
# -------------------------
# SCHEMAS (inchangés)
# -------------------------
SENSOR_SCHEMA = vol.Schema(
{
vol.Required(const.CONF_FREQUENCY): vol.In(frequencies),
vol.Optional(const.CONF_ICON_NORMAL): cv.icon,
vol.Optional(const.CONF_ICON_TODAY): cv.icon,
vol.Optional(const.CONF_ICON_TOMORROW): cv.icon,
vol.Optional(const.CONF_EXPIRE_AFTER): helpers.time_text,
vol.Optional(const.CONF_VERBOSE_STATE): cv.boolean,
vol.Optional(ATTR_HIDDEN): cv.boolean,
vol.Optional(const.CONF_MANUAL): cv.boolean,
vol.Optional(const.CONF_DATE): helpers.month_day_text,
vol.Optional(CONF_ENTITIES): cv.entity_ids,
vol.Optional(const.CONF_COLLECTION_DAYS): vol.All(
cv.ensure_list, [vol.In(WEEKDAYS)]
),
vol.Optional(const.CONF_FIRST_MONTH): vol.In(months),
vol.Optional(const.CONF_LAST_MONTH): vol.In(months),
vol.Optional(const.CONF_WEEKDAY_ORDER_NUMBER): vol.All(
cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(min=1, max=5))]
),
vol.Optional(const.CONF_WEEK_ORDER_NUMBER): vol.All(
cv.ensure_list, [vol.All(vol.Coerce(int), vol.Range(min=1, max=5))]
),
vol.Optional(const.CONF_PERIOD): vol.All(
vol.Coerce(int), vol.Range(min=1, max=1000)
),
vol.Optional(const.CONF_FIRST_WEEK): vol.All(
vol.Coerce(int), vol.Range(min=1, max=52)
),
vol.Optional(const.CONF_FIRST_DATE): cv.date,
vol.Optional(const.CONF_VERBOSE_FORMAT): cv.string,
vol.Optional(const.CONF_DATE_FORMAT): cv.string,
},
extra=vol.ALLOW_EXTRA,
)
CONFIG_SCHEMA = vol.Schema(
{
const.DOMAIN: vol.Schema(
{vol.Optional(const.CONF_SENSORS): vol.All(cv.ensure_list, [SENSOR_SCHEMA])}
)
},
extra=vol.ALLOW_EXTRA,
)
COLLECT_NOW_SCHEMA = vol.Schema(
{
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
vol.Optional(const.ATTR_LAST_COLLECTION): cv.datetime,
}
)
UPDATE_STATE_SCHEMA = vol.Schema(
{
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
}
)
ADD_REMOVE_DATE_SCHEMA = vol.Schema(
{
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
vol.Required(const.CONF_DATE): cv.date,
}
)
OFFSET_DATE_SCHEMA = vol.Schema(
{
vol.Required(CONF_ENTITY_ID): vol.All(cv.ensure_list, [cv.string]),
vol.Required(const.CONF_DATE): cv.date,
vol.Required(const.CONF_OFFSET): vol.All(
vol.Coerce(int), vol.Range(min=-31, max=31)
),
}
)
# -------------------------
# SETUP
# -------------------------
async def async_setup(hass: HomeAssistant, _: ConfigType) -> bool:
"""Set up platform - register services."""
hass.data.setdefault(const.DOMAIN, {})
hass.data[const.DOMAIN].setdefault(const.SENSOR_PLATFORM, {})
return True
# -------------------------
# CONFIG ENTRY SETUP
# -------------------------
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up via UI (Config Entry)."""
_LOGGER.debug(
"Setting %s (%s)",
entry.title,
entry.options.get(const.CONF_FREQUENCY),
)
entry.async_on_unload(entry.add_update_listener(update_listener))
await hass.config_entries.async_forward_entry_setups(
entry,
[const.SENSOR_PLATFORM],
)
return True
# -------------------------
# REMOVE ENTRY
# -------------------------
async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Handle removal."""
await hass.config_entries.async_unload_platforms(
entry,
[const.SENSOR_PLATFORM],
)
# -------------------------
# MIGRATION (inchangé)
# -------------------------
async def async_migrate_entry(_: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Migrate old entry."""
_LOGGER.info(
"Migrating %s from version %s",
config_entry.title,
config_entry.version,
)
new_data: Dict[str, Any] = {**config_entry.data}
new_options: Dict[str, Any] = {**config_entry.options}
removed_data: Dict[str, Any] = {}
removed_options: Dict[str, Any] = {}
# (tu peux garder ton code migration inchangé ici)
config_entry.version = const.CONFIG_VERSION
config_entry.data = MappingProxyType(new_data)
config_entry.options = MappingProxyType(new_options)
return True
# -------------------------
# UPDATE LISTENER FIXED
# -------------------------
async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Reload integration when options change."""
await hass.config_entries.async_reload(entry.entry_id)