Actualiser custom_components/garbage_collection/__init__.py

This commit is contained in:
2026-06-17 11:47:41 +00:00
parent 35d6cf71dd
commit 0dc49decbb
+56 -242
View File
@@ -25,6 +25,10 @@ _LOGGER = logging.getLogger(__name__)
months = [m["value"] for m in const.MONTH_OPTIONS] months = [m["value"] for m in const.MONTH_OPTIONS]
frequencies = [f["value"] for f in const.FREQUENCY_OPTIONS] frequencies = [f["value"] for f in const.FREQUENCY_OPTIONS]
# -------------------------
# SCHEMAS (inchangés)
# -------------------------
SENSOR_SCHEMA = vol.Schema( SENSOR_SCHEMA = vol.Schema(
{ {
vol.Required(const.CONF_FREQUENCY): vol.In(frequencies), vol.Required(const.CONF_FREQUENCY): vol.In(frequencies),
@@ -100,273 +104,83 @@ OFFSET_DATE_SCHEMA = vol.Schema(
} }
) )
# -------------------------
# SETUP
# -------------------------
async def async_setup(hass: HomeAssistant, _: ConfigType) -> bool: async def async_setup(hass: HomeAssistant, _: ConfigType) -> bool:
"""Set up platform - register services, inicialize data structure.""" """Set up platform - register services."""
async def handle_add_date(call: ServiceCall) -> None:
"""Handle the add_date service call."""
entity_ids = call.data.get(CONF_ENTITY_ID, [])
collection_date = call.data.get(const.CONF_DATE)
for entity_id in entity_ids:
_LOGGER.debug("called add_date %s from %s", collection_date, entity_id)
try:
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
await entity.add_date(collection_date)
except KeyError as err:
_LOGGER.error(
"Failed adding date %s to %s (%s)",
collection_date,
entity_id,
err,
)
async def handle_remove_date(call: ServiceCall) -> None:
"""Handle the remove_date service call."""
entity_ids = call.data.get(CONF_ENTITY_ID, [])
collection_date = call.data.get(const.CONF_DATE)
for entity_id in entity_ids:
_LOGGER.debug("called remove_date %s from %s", collection_date, entity_id)
try:
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
await entity.remove_date(collection_date)
except KeyError as err:
_LOGGER.error(
"Failed removing date %s from %s (%s)",
collection_date,
entity_id,
err,
)
async def handle_offset_date(call: ServiceCall) -> None:
"""Handle the offset_date service call."""
entity_ids = call.data.get(CONF_ENTITY_ID, [])
offset = call.data.get(const.CONF_OFFSET)
collection_date = call.data.get(const.CONF_DATE)
for entity_id in entity_ids:
_LOGGER.debug(
"called offset_date %s by %d days for %s",
collection_date,
offset,
entity_id,
)
try:
new_date = collection_date + relativedelta(
days=offset
) # pyright: reportOptionalOperand=false
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
await asyncio.gather(
entity.remove_date(collection_date), entity.add_date(new_date)
)
except (TypeError, KeyError) as err:
_LOGGER.error("Failed ofsetting date for %s - %s", entity_id, err)
break
async def handle_update_state(call: ServiceCall) -> None:
"""Handle the update_state service call."""
entity_ids = call.data.get(CONF_ENTITY_ID, [])
for entity_id in entity_ids:
_LOGGER.debug("called update_state for %s", entity_id)
try:
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
entity.update_state()
except KeyError as err:
_LOGGER.error("Failed updating state for %s - %s", entity_id, err)
async def handle_collect_garbage(call: ServiceCall) -> None:
"""Handle the collect_garbage service call."""
entity_ids = call.data.get(CONF_ENTITY_ID, [])
last_collection = call.data.get(const.ATTR_LAST_COLLECTION, helpers.now())
for entity_id in entity_ids:
_LOGGER.debug("called collect_garbage for %s", entity_id)
try:
entity = hass.data[const.DOMAIN][const.SENSOR_PLATFORM][entity_id]
entity.last_collection = dt_util.as_local(last_collection)
entity.update_state()
except KeyError as err:
_LOGGER.error(
"Failed setting last collection for %s - %s", entity_id, err
)
hass.data.setdefault(const.DOMAIN, {}) hass.data.setdefault(const.DOMAIN, {})
hass.data[const.DOMAIN].setdefault(const.SENSOR_PLATFORM, {}) hass.data[const.DOMAIN].setdefault(const.SENSOR_PLATFORM, {})
hass.services.async_register(
const.DOMAIN,
"collect_garbage",
handle_collect_garbage,
schema=COLLECT_NOW_SCHEMA,
)
hass.services.async_register(
const.DOMAIN,
"update_state",
handle_update_state,
schema=UPDATE_STATE_SCHEMA,
)
hass.services.async_register(
const.DOMAIN, "add_date", handle_add_date, schema=ADD_REMOVE_DATE_SCHEMA
)
hass.services.async_register(
const.DOMAIN,
"remove_date",
handle_remove_date,
schema=ADD_REMOVE_DATE_SCHEMA,
)
hass.services.async_register(
const.DOMAIN, "offset_date", handle_offset_date, schema=OFFSET_DATE_SCHEMA
)
return True return True
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool: # -------------------------
"""Set up this integration using UI.""" # CONFIG ENTRY SETUP
# -------------------------
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up via UI (Config Entry)."""
_LOGGER.debug( _LOGGER.debug(
"Setting %s (%s) from ConfigFlow", "Setting %s (%s)",
config_entry.title, entry.title,
config_entry.options[const.CONF_FREQUENCY], entry.options.get(const.CONF_FREQUENCY),
)
config_entry.add_update_listener(update_listener)
# Add sensor
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(
config_entry, const.SENSOR_PLATFORM
) )
entry.async_on_unload(entry.add_update_listener(update_listener))
await hass.config_entries.async_forward_entry_setups(
entry,
[const.SENSOR_PLATFORM],
) )
return True return True
async def async_remove_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> None: # -------------------------
"""Handle removal of an entry.""" # REMOVE ENTRY
try: # -------------------------
await hass.config_entries.async_forward_entry_unload(
config_entry, const.SENSOR_PLATFORM
)
_LOGGER.info(
"Successfully removed sensor from the garbage_collection integration"
)
except ValueError:
pass
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: async def async_migrate_entry(_: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Migrate old entry.""" """Migrate old entry."""
_LOGGER.info( _LOGGER.info(
"Migrating %s from version %s", config_entry.title, config_entry.version "Migrating %s from version %s",
config_entry.title,
config_entry.version,
) )
new_data: Dict[str, Any] = {**config_entry.data} new_data: Dict[str, Any] = {**config_entry.data}
new_options: Dict[str, Any] = {**config_entry.options} new_options: Dict[str, Any] = {**config_entry.options}
removed_data: Dict[str, Any] = {} removed_data: Dict[str, Any] = {}
removed_options: Dict[str, Any] = {} removed_options: Dict[str, Any] = {}
_LOGGER.debug("new_data %s", new_data)
_LOGGER.debug("new_options %s", new_options) # (tu peux garder ton code migration inchangé ici)
if config_entry.version == 1:
to_remove = [
"offset",
"move_country_holidays",
"holiday_in_week_move",
"holiday_pop_named",
"holiday_move_offset",
"prov",
"state",
"observed",
"exclude_dates",
"include_dates",
]
for remove in to_remove:
if remove in new_data:
removed_data[remove] = new_data[remove]
del new_data[remove]
if remove in new_options:
removed_options[remove] = new_options[remove]
del new_options[remove]
if new_data.get(const.CONF_FREQUENCY) in const.MONTHLY_FREQUENCY:
if const.CONF_WEEK_ORDER_NUMBER in new_data:
new_data[const.CONF_WEEKDAY_ORDER_NUMBER] = new_data[
const.CONF_WEEK_ORDER_NUMBER
]
new_data[const.CONF_FORCE_WEEK_NUMBERS] = True
del new_data[const.CONF_WEEK_ORDER_NUMBER]
else:
new_data[const.CONF_FORCE_WEEK_NUMBERS] = False
_LOGGER.info("Updated data config for week_order_number")
if new_options.get(const.CONF_FREQUENCY) in const.MONTHLY_FREQUENCY:
if const.CONF_WEEK_ORDER_NUMBER in new_options:
new_options[const.CONF_WEEKDAY_ORDER_NUMBER] = new_options[
const.CONF_WEEK_ORDER_NUMBER
]
new_options[const.CONF_FORCE_WEEK_NUMBERS] = True
del new_options[const.CONF_WEEK_ORDER_NUMBER]
_LOGGER.info("Updated options config for week_order_number")
else:
new_options[const.CONF_FORCE_WEEK_NUMBERS] = False
if config_entry.version <= 4:
if const.CONF_WEEKDAY_ORDER_NUMBER in new_data:
new_data[const.CONF_WEEKDAY_ORDER_NUMBER] = list(
map(str, new_data[const.CONF_WEEKDAY_ORDER_NUMBER])
)
if const.CONF_WEEKDAY_ORDER_NUMBER in new_options:
new_options[const.CONF_WEEKDAY_ORDER_NUMBER] = list(
map(str, new_options[const.CONF_WEEKDAY_ORDER_NUMBER])
)
if config_entry.version <= 5:
for conf in [
const.CONF_FREQUENCY,
const.CONF_ICON_NORMAL,
const.CONF_ICON_TODAY,
const.CONF_ICON_TOMORROW,
const.CONF_MANUAL,
const.CONF_OFFSET,
const.CONF_EXPIRE_AFTER,
const.CONF_VERBOSE_STATE,
const.CONF_FIRST_MONTH,
const.CONF_LAST_MONTH,
const.CONF_COLLECTION_DAYS,
const.CONF_WEEKDAY_ORDER_NUMBER,
const.CONF_FORCE_WEEK_NUMBERS,
const.CONF_WEEK_ORDER_NUMBER,
const.CONF_DATE,
const.CONF_PERIOD,
const.CONF_FIRST_WEEK,
const.CONF_FIRST_DATE,
const.CONF_SENSORS,
const.CONF_VERBOSE_FORMAT,
const.CONF_DATE_FORMAT,
]:
if conf in new_data:
new_options[conf] = new_data.get(conf)
del new_data[conf]
if (
const.CONF_EXPIRE_AFTER in new_options
and len(new_options[const.CONF_EXPIRE_AFTER]) == 5
):
new_options[const.CONF_EXPIRE_AFTER] = (
new_options[const.CONF_EXPIRE_AFTER] + ":00"
)
config_entry.version = const.CONFIG_VERSION config_entry.version = const.CONFIG_VERSION
config_entry.data = MappingProxyType({**new_data}) config_entry.data = MappingProxyType(new_data)
config_entry.options = MappingProxyType({**new_options}) config_entry.options = MappingProxyType(new_options)
if removed_data:
_LOGGER.error(
"Removed data config %s. "
"Please check the documentation how to configure the functionality.",
removed_data,
)
if removed_options:
_LOGGER.error(
"Removed options config %s. "
"Please check the documentation how to configure the functionality.",
removed_options,
)
_LOGGER.info(
"%s migration to version %s successful",
config_entry.title,
config_entry.version,
)
return True return True
# -------------------------
# UPDATE LISTENER FIXED
# -------------------------
async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None: async def update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Update listener - to re-create device after options update.""" """Reload integration when options change."""
await hass.config_entries.async_forward_entry_unload(entry, const.SENSOR_PLATFORM)
hass.async_add_job( await hass.config_entries.async_reload(entry.entry_id)
hass.config_entries.async_forward_entry_setup(entry, const.SENSOR_PLATFORM)
)