diff --git a/custom_components/waste_collection_schedule/__init__.py b/custom_components/waste_collection_schedule/__init__.py index 91af47789..49c7a3893 100644 --- a/custom_components/waste_collection_schedule/__init__.py +++ b/custom_components/waste_collection_schedule/__init__.py @@ -40,6 +40,8 @@ CONF_PICTURE = "picture" CONF_USE_DEDICATED_CALENDAR = "use_dedicated_calendar" CONF_DEDICATED_CALENDAR_TITLE = "dedicated_calendar_title" +CONF_START_HOUR = "start_hour" +CONF_END_HOUR = "end_hour" CUSTOMIZE_CONFIG = vol.Schema( { @@ -50,6 +52,8 @@ vol.Optional(CONF_PICTURE): cv.string, vol.Optional(CONF_USE_DEDICATED_CALENDAR): cv.boolean, vol.Optional(CONF_DEDICATED_CALENDAR_TITLE): cv.string, + vol.Optional(CONF_START_HOUR): cv.string, + vol.Optional(CONF_END_HOUR): cv.string, } ) @@ -106,6 +110,8 @@ async def async_setup(hass: HomeAssistant, config: dict): picture=c.get(CONF_PICTURE), use_dedicated_calendar=c.get(CONF_USE_DEDICATED_CALENDAR, False), dedicated_calendar_title=c.get(CONF_DEDICATED_CALENDAR_TITLE, False), + start_hour=c.get(CONF_START_HOUR, None), + end_hour=c.get(CONF_END_HOUR, None), ) await hass.async_add_executor_job( api.add_source_shell, diff --git a/custom_components/waste_collection_schedule/calendar.py b/custom_components/waste_collection_schedule/calendar.py index f76abaa79..8fc8d999c 100644 --- a/custom_components/waste_collection_schedule/calendar.py +++ b/custom_components/waste_collection_schedule/calendar.py @@ -1,10 +1,11 @@ """Calendar platform support for Waste Collection Schedule.""" import logging -from datetime import datetime, timedelta +from datetime import datetime, timedelta, time, tzinfo from homeassistant.components.calendar import CalendarEntity, CalendarEvent from homeassistant.core import HomeAssistant +from homeassistant.util import dt as dt_util # fmt: off from custom_components.waste_collection_schedule.waste_collection_schedule.collection_aggregator import \ @@ -27,6 +28,8 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= api = discovery_info["api"] + tz = dt_util.get_time_zone(hass.config.time_zone) if hass.config.time_zone is not None else None + for shell in api.shells: dedicated_calendar_types = shell.get_dedicated_calendar_types() for type in dedicated_calendar_types: @@ -37,6 +40,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= name=shell.get_calendar_title_for_type(type), include_types={shell.get_collection_type_name(type)}, unique_id=calc_unique_calendar_id(shell, type), + timezone=tz ) ) @@ -50,6 +54,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= for type in dedicated_calendar_types }, unique_id=calc_unique_calendar_id(shell), + timezone=tz ) ) @@ -65,6 +70,7 @@ def __init__( aggregator, name, unique_id: str, + timezone: tzinfo, include_types=None, exclude_types=None, ): @@ -75,6 +81,7 @@ def __init__( self._exclude_types = exclude_types self._unique_id = unique_id self._attr_unique_id = unique_id + self._timezone = timezone if timezone is not None else dt_util.DEFAULT_TIME_ZONE @property def name(self): @@ -116,6 +123,18 @@ async def async_get_events( def _convert(self, collection) -> CalendarEvent: """Convert an collection into a Home Assistant calendar event.""" + if collection.start_hour is not None and collection.end_hour is not None: + event_date_time = datetime.combine( + collection.date, + time(hour=0, minute=0, second=0), + self._timezone + ) + return CalendarEvent( + summary=collection.type, + start=event_date_time + timedelta(hours=collection.start_hour), + end=event_date_time + timedelta(hours=collection.end_hour), + ) + return CalendarEvent( summary=collection.type, start=collection.date, diff --git a/custom_components/waste_collection_schedule/manifest.json b/custom_components/waste_collection_schedule/manifest.json index 2574940ef..4332fb88f 100644 --- a/custom_components/waste_collection_schedule/manifest.json +++ b/custom_components/waste_collection_schedule/manifest.json @@ -1,11 +1,12 @@ { "domain": "waste_collection_schedule", "name": "waste_collection_schedule", - "codeowners": ["@mampfes"], - "dependencies": [], "documentation": "https://github.com/mampfes/hacs_waste_collection_schedule#readme", - "integration_type": "hub", + "requirements": ["icalendar", "recurring_ical_events", "icalevents", "bs4"], + "dependencies": [], + "codeowners": ["@mampfes"], "iot_class": "cloud_polling", - "requirements": ["icalendar", "recurring_ical_events", "icalevents", "beautifulsoup4", "lxml"], - "version": "1.49.0" + "version": "1.34.1", + "integration_type": "hub", + "loggers": ["custom_components.waste_collection_schedule"] } diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/collection.py b/custom_components/waste_collection_schedule/waste_collection_schedule/collection.py index 16f2b9105..f5f9c00b9 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/collection.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/collection.py @@ -9,7 +9,7 @@ def __init__( icon: Optional[str] = None, picture: Optional[str] = None, ): - dict.__init__(self, date=date.isoformat(), icon=icon, picture=picture) + dict.__init__(self, date=date.isoformat(), icon=icon, picture=picture, start_hour=None, end_hour=None) self._date = date # store date also as python date object @property @@ -34,6 +34,20 @@ def picture(self): def set_picture(self, picture: str): self["picture"] = picture + @property + def start_hour(self): + return self["start_hour"] + + def set_start_hour(self, hours: int): + self["start_hour"] = int(hours) + + @property + def end_hour(self): + return self["end_hour"] + + def set_end_hour(self, hours: int): + self["end_hour"] = int(hours) + class Collection(CollectionBase): def __init__( diff --git a/custom_components/waste_collection_schedule/waste_collection_schedule/source_shell.py b/custom_components/waste_collection_schedule/waste_collection_schedule/source_shell.py index 6f53c5d1a..a4660bf33 100644 --- a/custom_components/waste_collection_schedule/waste_collection_schedule/source_shell.py +++ b/custom_components/waste_collection_schedule/waste_collection_schedule/source_shell.py @@ -21,6 +21,8 @@ def __init__( picture=None, use_dedicated_calendar=False, dedicated_calendar_title=None, + start_hour=None, + end_hour=None, ): self._waste_type = waste_type self._alias = alias @@ -29,6 +31,8 @@ def __init__( self._picture = picture self._use_dedicated_calendar = use_dedicated_calendar self._dedicated_calendar_title = dedicated_calendar_title + self._start_hour = start_hour + self._end_hour = end_hour @property def waste_type(self): @@ -58,8 +62,16 @@ def use_dedicated_calendar(self): def dedicated_calendar_title(self): return self._dedicated_calendar_title + @property + def start_hour(self): + return self._start_hour + + @property + def end_hour(self): + return self._end_hour + def __repr__(self): - return f"Customize{{waste_type={self._waste_type}, alias={self._alias}, show={self._show}, icon={self._icon}, picture={self._picture}}}" + return f"Customize{{waste_type={self._waste_type}, alias={self._alias}, show={self._show}, icon={self._icon}, picture={self._picture}, start_hour={self._start_hour}, end_hour={self._end_hour}}}" def filter_function(entry: Collection, customize: Dict[str, Customize]): @@ -82,6 +94,16 @@ def customize_function(entry: Collection, customize: Dict[str, Customize]): return entry +def start_end_time_function(entry: Collection, customize: Dict[str, Customize]): + c = customize.get(entry.type) + if c is not None: + if c.start_hour is not None: + entry.set_start_hour(c.start_hour) + if c.end_hour is not None: + entry.set_end_hour(c.end_hour) + return entry + + class SourceShell: def __init__( self, @@ -146,6 +168,9 @@ def fetch(self): # filter hidden entries entries = filter(lambda x: filter_function(x, self._customize), entries) + # add optional start and end time to a waste event + entries = map(lambda x: start_end_time_function(x, self._customize), entries) + # customize fetched entries entries = map(lambda x: customize_function(x, self._customize), entries)