|
15 | 15 | from homeassistant.exceptions import NoEntitySpecifiedError
|
16 | 16 | from homeassistant.helpers.entity import Entity
|
17 | 17 | from homeassistant.util import dt
|
| 18 | +import pytz |
18 | 19 |
|
19 | 20 | from . import (
|
20 | 21 | CONF_EMAIL,
|
|
45 | 46 | "XXXX-WXX-7": "Every Sunday",
|
46 | 47 | }
|
47 | 48 |
|
| 49 | +RECURRING_PATTERN_ISO_SET = { |
| 50 | + None: (), |
| 51 | + "P1D": (1, 2, 3, 4, 5, 6, 7), |
| 52 | + "XXXX-WE": (6, 7), |
| 53 | + "XXXX-WD": (1, 2, 3, 4, 5), |
| 54 | + "XXXX-WXX-1": (1), |
| 55 | + "XXXX-WXX-2": (2), |
| 56 | + "XXXX-WXX-3": (3), |
| 57 | + "XXXX-WXX-4": (4), |
| 58 | + "XXXX-WXX-5": (5), |
| 59 | + "XXXX-WXX-6": (6), |
| 60 | + "XXXX-WXX-7": (7), |
| 61 | +} |
| 62 | + |
48 | 63 |
|
49 | 64 | @retry_async(limit=5, delay=5, catch_exceptions=False)
|
50 | 65 | async def async_setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
@@ -170,23 +185,28 @@ def __init__(
|
170 | 185 | self._unit = None
|
171 | 186 | self._device_class = DEVICE_CLASS_TIMESTAMP
|
172 | 187 | self._icon = icon
|
| 188 | + self._all = [] |
| 189 | + self._active = [] |
| 190 | + self._next = None |
| 191 | + self._timestamp: datetime.datetime = None |
| 192 | + self._process_raw_notifications() |
| 193 | + |
| 194 | + def _process_raw_notifications(self): |
173 | 195 | self._all = (
|
174 |
| - sorted(self._n_dict.items(), key=lambda x: x[1][self._sensor_property]) |
| 196 | + list(map(self._fix_alarm_date_time, self._n_dict.items())) |
175 | 197 | if self._n_dict
|
176 | 198 | else []
|
177 | 199 | )
|
178 |
| - self._all = list(map(self._fix_alarm_date_time, self._all)) |
179 |
| - self._sorted = ( |
| 200 | + self._all = list(map(self._update_recurring_alarm, self._all)) |
| 201 | + self._all = sorted(self._all, key=lambda x: x[1][self._sensor_property]) |
| 202 | + self._active = ( |
180 | 203 | list(filter(lambda x: x[1]["status"] == "ON", self._all))
|
181 | 204 | if self._all
|
182 | 205 | else []
|
183 | 206 | )
|
184 |
| - self._next = self._sorted[0][1] if self._sorted else None |
185 |
| - self._timestamp: datetime.datetime = None |
| 207 | + self._next = self._active[0][1] if self._active else None |
186 | 208 |
|
187 | 209 | def _fix_alarm_date_time(self, value):
|
188 |
| - import pytz |
189 |
| - |
190 | 210 | if (
|
191 | 211 | self._sensor_property != "date_time"
|
192 | 212 | or not value
|
@@ -222,6 +242,25 @@ def _fix_alarm_date_time(self, value):
|
222 | 242 | )
|
223 | 243 | return value
|
224 | 244 |
|
| 245 | + def _update_recurring_alarm(self, value): |
| 246 | + _LOGGER.debug("value %s", value) |
| 247 | + alarm = value[1][self._sensor_property] |
| 248 | + recurring_pattern = value[1]["recurringPattern"] |
| 249 | + while ( |
| 250 | + recurring_pattern |
| 251 | + and alarm < dt.now() |
| 252 | + and alarm.isoweekday not in RECURRING_PATTERN_ISO_SET[recurring_pattern] |
| 253 | + ): |
| 254 | + alarm += datetime.timedelta(days=1) |
| 255 | + if alarm != value[1][self._sensor_property]: |
| 256 | + _LOGGER.debug( |
| 257 | + "Alarm with recurrence %s set to %s", |
| 258 | + RECURRING_PATTERN[recurring_pattern], |
| 259 | + alarm, |
| 260 | + ) |
| 261 | + value[1][self._sensor_property] = alarm |
| 262 | + return value |
| 263 | + |
225 | 264 | @staticmethod
|
226 | 265 | def _round_time(value: datetime.datetime) -> datetime.datetime:
|
227 | 266 | precision = datetime.timedelta(seconds=1).total_seconds()
|
@@ -325,18 +364,7 @@ async def async_update(self):
|
325 | 364 | self._n_dict = account_dict["notifications"][self._dev_id][self._type]
|
326 | 365 | except KeyError:
|
327 | 366 | self._n_dict = None
|
328 |
| - self._all = ( |
329 |
| - sorted(self._n_dict.items(), key=lambda x: x[1][self._sensor_property]) |
330 |
| - if self._n_dict |
331 |
| - else [] |
332 |
| - ) |
333 |
| - self._all = list(map(self._fix_alarm_date_time, self._all)) |
334 |
| - self._sorted = ( |
335 |
| - list(filter(lambda x: x[1]["status"] == "ON", self._all)) |
336 |
| - if self._all |
337 |
| - else [] |
338 |
| - ) |
339 |
| - self._next = self._sorted[0][1] if self._sorted else None |
| 367 | + self._process_raw_notifications() |
340 | 368 | try:
|
341 | 369 | self.async_schedule_update_ha_state()
|
342 | 370 | except NoEntitySpecifiedError:
|
@@ -367,9 +395,9 @@ def device_state_attributes(self):
|
367 | 395 |
|
368 | 396 | attr = {
|
369 | 397 | "recurrence": self.recurrence,
|
370 |
| - "total_active": len(self._sorted), |
| 398 | + "total_active": len(self._active), |
371 | 399 | "total_all": len(self._all),
|
372 |
| - "sorted_active": json.dumps(self._sorted, default=str), |
| 400 | + "sorted_active": json.dumps(self._active, default=str), |
373 | 401 | "sorted_all": json.dumps(self._all, default=str),
|
374 | 402 | }
|
375 | 403 | return attr
|
|
0 commit comments