From d9deee9e52eaa342a152de2fe3a6376402bb23bc Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Mon, 31 Aug 2020 08:37:04 +0200 Subject: [PATCH] simplify calc_percent --- .../circadian_lighting/__init__.py | 104 +++++++++--------- .../circadian_lighting/sensor.py | 0 .../circadian_lighting/switch.py | 23 ++-- 3 files changed, 59 insertions(+), 68 deletions(-) mode change 100644 => 100755 custom_components/circadian_lighting/__init__.py mode change 100644 => 100755 custom_components/circadian_lighting/sensor.py mode change 100644 => 100755 custom_components/circadian_lighting/switch.py diff --git a/custom_components/circadian_lighting/__init__.py b/custom_components/circadian_lighting/__init__.py old mode 100644 new mode 100755 index 5492511e..5d12a934 --- a/custom_components/circadian_lighting/__init__.py +++ b/custom_components/circadian_lighting/__init__.py @@ -58,6 +58,8 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = "circadian_lighting" CIRCADIAN_LIGHTING_UPDATE_TOPIC = f"{DOMAIN}_update" +SUN_EVENT_NOON = "solar_noon" +SUN_EVENT_MIDNIGHT = "solar_midnight" CONF_MIN_CT = "min_colortemp" DEFAULT_MIN_CT = 2500 @@ -195,7 +197,7 @@ class CircadianLighting: microsecond=int(self._time[key].strftime("%f")), ) - def get_sunrise_sunset(self, date=None): + def get_sunrise_sunset(self, date=None, as_timestamps=False): if self._time["sunrise"] is not None and self._time["sunset"] is not None: if date is None: date = dt_now(self._timezone) @@ -231,65 +233,57 @@ class CircadianLighting: sunrise = sunrise + self._sunrise_offset if self._sunset_offset is not None: sunset = sunset + self._sunset_offset - return { + datetimes = { SUN_EVENT_SUNRISE: sunrise.astimezone(self._timezone), SUN_EVENT_SUNSET: sunset.astimezone(self._timezone), - "solar_noon": solar_noon.astimezone(self._timezone), - "solar_midnight": solar_midnight.astimezone(self._timezone), + SUN_EVENT_NOON: solar_noon.astimezone(self._timezone), + SUN_EVENT_MIDNIGHT: solar_midnight.astimezone(self._timezone), } + if as_timestamps: + return {k: dt.timestamp() for k, dt in datetimes.items()} + else: + return datetimes def calc_percent(self): now = dt_now(self._timezone) _LOGGER.debug("now: " + str(now)) - today_sun_times = self.get_sunrise_sunset(now) - _LOGGER.debug("today_sun_times: " + str(today_sun_times)) + today = self.get_sunrise_sunset(now, as_timestamps=True) + _LOGGER.debug("today: " + str(today)) # Convert everything to epoch timestamps for easy calculation - now_seconds = now.timestamp() - sunrise_seconds = today_sun_times[SUN_EVENT_SUNRISE].timestamp() - sunset_seconds = today_sun_times[SUN_EVENT_SUNSET].timestamp() - solar_noon_seconds = today_sun_times["solar_noon"].timestamp() - solar_midnight_seconds = today_sun_times["solar_midnight"].timestamp() + now_ts = now.timestamp() - if now < today_sun_times[SUN_EVENT_SUNRISE]: + if now_ts < today[SUN_EVENT_SUNRISE]: # It's before sunrise (after midnight) # Because it's before sunrise (and after midnight) sunset must have happend yesterday - yesterday_sun_times = self.get_sunrise_sunset(now - timedelta(days=1)) - _LOGGER.debug("yesterday_sun_times: " + str(yesterday_sun_times)) - sunset_seconds = yesterday_sun_times[SUN_EVENT_SUNSET].timestamp() + yesterday = self.get_sunrise_sunset( + now - timedelta(days=1), as_timestamps=True + ) + _LOGGER.debug("yesterday: " + str(yesterday)) + today[SUN_EVENT_SUNSET] = yesterday[SUN_EVENT_SUNSET] if ( - today_sun_times["solar_midnight"] > today_sun_times[SUN_EVENT_SUNSET] - and yesterday_sun_times["solar_midnight"] - > yesterday_sun_times[SUN_EVENT_SUNSET] + today[SUN_EVENT_MIDNIGHT] > today[SUN_EVENT_SUNSET] + and yesterday[SUN_EVENT_MIDNIGHT] > yesterday[SUN_EVENT_SUNSET] ): # Solar midnight is after sunset so use yesterdays's time - solar_midnight_seconds = yesterday_sun_times[ - "solar_midnight" - ].timestamp() - elif now > today_sun_times[SUN_EVENT_SUNSET]: + today[SUN_EVENT_MIDNIGHT] = yesterday[SUN_EVENT_MIDNIGHT] + elif now_ts > today[SUN_EVENT_SUNSET]: # It's after sunset (before midnight) # Because it's after sunset (and before midnight) sunrise should happen tomorrow - tomorrow_sun_times = self.get_sunrise_sunset(now + timedelta(days=1)) - _LOGGER.debug("tomorrow_sun_times: " + str(tomorrow_sun_times)) - sunrise_seconds = tomorrow_sun_times[SUN_EVENT_SUNRISE].timestamp() + tomorrow = self.get_sunrise_sunset( + now + timedelta(days=1), as_timestamps=True + ) + _LOGGER.debug("tomorrow: " + str(tomorrow)) + today[SUN_EVENT_SUNRISE] = tomorrow[SUN_EVENT_SUNRISE] if ( - today_sun_times["solar_midnight"] < today_sun_times[SUN_EVENT_SUNRISE] - and tomorrow_sun_times["solar_midnight"] - < tomorrow_sun_times[SUN_EVENT_SUNRISE] + today[SUN_EVENT_MIDNIGHT] < today[SUN_EVENT_SUNRISE] + and tomorrow[SUN_EVENT_MIDNIGHT] < tomorrow[SUN_EVENT_SUNRISE] ): # Solar midnight is before sunrise so use tomorrow's time - solar_midnight_seconds = tomorrow_sun_times[ - "solar_midnight" - ].timestamp() + today[SUN_EVENT_MIDNIGHT] = tomorrow[SUN_EVENT_MIDNIGHT] - _LOGGER.debug( - f"now_seconds: {now_seconds}, " - f"sunrise_seconds: {sunrise_seconds}, " - f"sunset_seconds: {sunset_seconds}, " - f"solar_midnight_seconds: {solar_midnight_seconds}, " - f"solar_noon_seconds: {solar_noon_seconds}" - ) + _LOGGER.debug(f"now_ts: {now_ts}, {today}") # Figure out where we are in time so we know which half of the parabola to calculate # We're generating a different sunset-sunrise parabola for before and after solar midnight @@ -297,31 +291,31 @@ class CircadianLighting: # We're also (obviously) generating a different parabola for sunrise-sunset # sunrise-sunset parabola - if now_seconds > sunrise_seconds and now_seconds < sunset_seconds: - h = solar_noon_seconds + if now_ts > today[SUN_EVENT_SUNRISE] and now_ts < today[SUN_EVENT_SUNSET]: + h = today[SUN_EVENT_NOON] k = 100 - # parabola before solar_noon - if now_seconds < solar_noon_seconds: - x = sunrise_seconds - # parabola after solar_noon - else: - x = sunset_seconds + # parabola before solar_noon else after solar_noon + x = ( + today[SUN_EVENT_SUNRISE] + if now_ts < today[SUN_EVENT_NOON] + else today[SUN_EVENT_SUNSET] + ) y = 0 # sunset_sunrise parabola - elif now_seconds > sunset_seconds and now_seconds < sunrise_seconds: - h = solar_midnight_seconds + elif now_ts > today[SUN_EVENT_SUNSET] and now_ts < today[SUN_EVENT_SUNRISE]: + h = today[SUN_EVENT_MIDNIGHT] k = -100 - # parabola before solar_midnight - if now_seconds < solar_midnight_seconds: - x = sunset_seconds - # parabola after solar_midnight - else: - x = sunrise_seconds + # parabola before solar_midnight else after solar_midnight + x = ( + today[SUN_EVENT_SUNSET] + if now_ts < today[SUN_EVENT_MIDNIGHT] + else today[SUN_EVENT_SUNRISE] + ) y = 0 a = (y - k) / (h - x) ** 2 - percentage = a * (now_seconds - h) ** 2 + k + percentage = a * (now_ts - h) ** 2 + k _LOGGER.debug( f"h: {h}, k: {k}, x: {x}, y: {y}, a: {a}, percentage: {percentage}" diff --git a/custom_components/circadian_lighting/sensor.py b/custom_components/circadian_lighting/sensor.py old mode 100644 new mode 100755 diff --git a/custom_components/circadian_lighting/switch.py b/custom_components/circadian_lighting/switch.py old mode 100644 new mode 100755 index bb90bce8..d0a781aa --- a/custom_components/circadian_lighting/switch.py +++ b/custom_components/circadian_lighting/switch.py @@ -99,7 +99,7 @@ PLATFORM_SCHEMA = vol.Schema( vol.Optional( CONF_INITIAL_TRANSITION, default=DEFAULT_INITIAL_TRANSITION ): VALID_TRANSITION, - vol.Optional(CONF_ONCE_ONLY): cv.boolean, + vol.Optional(CONF_ONCE_ONLY, default=False): cv.boolean, } ) @@ -359,22 +359,19 @@ class CircadianSwitch(SwitchEntity, RestoreEntity): _LOGGER.debug(f"{light} {which} Adjusted - {msg}") def light_state_changed(self, entity_id, from_state, to_state): - with suppress(Exception): - _LOGGER.debug(f"{entity_id} change from {from_state} to {to_state}") - if to_state.state == "on" and from_state.state != "on": - self.adjust_lights([entity_id], self._initial_transition) + _LOGGER.debug(f"{entity_id} change from {from_state} to {to_state}") + if to_state.state == "on" and from_state.state != "on": + self.adjust_lights([entity_id], self._initial_transition) def sleep_state_changed(self, entity_id, from_state, to_state): - with suppress(Exception): - _LOGGER.debug(f"{entity_id} change from {from_state} to {to_state}") - if ( - to_state.state == self._sleep_state + _LOGGER.debug(f"{entity_id} change from {from_state} to {to_state}") + if ( + to_state.state == self._sleep_state or from_state.state == self._sleep_state ): self._update_switch(self._initial_transition, force=True) def disable_state_changed(self, entity_id, from_state, to_state): - with suppress(Exception): - _LOGGER.debug("{entity_id} change from {from_state} to {to_state}") - if from_state.state == self._disable_state: - self._update_switch(self._initial_transition, force=True) + _LOGGER.debug("{entity_id} change from {from_state} to {to_state}") + if from_state.state == self._disable_state: + self._update_switch(self._initial_transition, force=True)