def sun(hass, before=None, after=None, before_offset=None, after_offset=None): """Test if current time matches sun requirements.""" utcnow = dt_util.utcnow() today = dt_util.as_local(utcnow).date() before_offset = before_offset or timedelta(0) after_offset = after_offset or timedelta(0) sunrise = get_astral_event_date(hass, 'sunrise', today) sunset = get_astral_event_date(hass, 'sunset', today) if sunrise is None and SUN_EVENT_SUNRISE in (before, after): # There is no sunrise today return False if sunset is None and SUN_EVENT_SUNSET in (before, after): # There is no sunset today return False if before == SUN_EVENT_SUNRISE and utcnow > sunrise + before_offset: return False if before == SUN_EVENT_SUNSET and utcnow > sunset + before_offset: return False if after == SUN_EVENT_SUNRISE and utcnow < sunrise + after_offset: return False if after == SUN_EVENT_SUNSET and utcnow < sunset + after_offset: return False return True
def update_as_of(self, utc_time): """Update the attributes containing solar events.""" # Always need to update next_rising and next_setting so state can be # determined. for a, e in [(STATE_ATTR_NEXT_RISING, 'sunrise'), (STATE_ATTR_NEXT_SETTING, 'sunset')]: setattr(self, a, get_astral_event_next(self.hass, e, utc_time)) # Only need to update remaining properties if they will be reported # in attributes. for a, e in [(STATE_ATTR_NEXT_DAWN, 'dawn'), (STATE_ATTR_NEXT_DUSK, 'dusk'), (STATE_ATTR_NEXT_MIDNIGHT, 'solar_midnight'), (STATE_ATTR_NEXT_NOON, 'solar_noon')]: if a in self._monitored_condtions: setattr(self, a, get_astral_event_next(self.hass, e, utc_time)) for a, e in [(STATE_ATTR_SUNRISE, 'sunrise'), (STATE_ATTR_SUNSET, 'sunset')]: if a in self._monitored_condtions: setattr(self, a, get_astral_event_date(self.hass, e, utc_time)) for a, d in [(STATE_ATTR_DAYLIGHT, 0), (STATE_ATTR_PREV_DAYLIGHT, -1), (STATE_ATTR_NEXT_DAYLIGHT, 1)]: if a in self._monitored_condtions: dl = get_astral_event_date(self.hass, 'daylight', utc_time + timedelta(days=d)) setattr(self, a, (dl[1] - dl[0]).total_seconds())
def sun(hass, before=None, after=None, before_offset=None, after_offset=None): """Test if current time matches sun requirements.""" utcnow = dt_util.utcnow() today = dt_util.as_local(utcnow).date() before_offset = before_offset or timedelta(0) after_offset = after_offset or timedelta(0) sunrise = get_astral_event_date(hass, 'sunrise', today) sunset = get_astral_event_date(hass, 'sunset', today) if sunrise is None and (before == SUN_EVENT_SUNRISE or after == SUN_EVENT_SUNRISE): # There is no sunrise today return False if sunset is None and (before == SUN_EVENT_SUNSET or after == SUN_EVENT_SUNSET): # There is no sunset today return False if before == SUN_EVENT_SUNRISE and utcnow > sunrise + before_offset: return False elif before == SUN_EVENT_SUNSET and utcnow > sunset + before_offset: return False if after == SUN_EVENT_SUNRISE and utcnow < sunrise + after_offset: return False elif after == SUN_EVENT_SUNSET and utcnow < sunset + after_offset: return False return True
def _calculate_boudary_time(self): """Calculate internal absolute time boundaries.""" nowutc = dt_util.utcnow() # If after value is a sun event instead of absolute time if is_sun_event(self._after): # Calculate the today's event utc time or # if not available take next after_event_date = get_astral_event_date( self.hass, self._after, nowutc ) or get_astral_event_next(self.hass, self._after, nowutc) else: # Convert local time provided to UTC today # datetime.combine(date, time, tzinfo) is not supported # in python 3.5. The self._after is provided # with hass configured TZ not system wide after_event_date = self._naive_time_to_utc_datetime(self._after) self._time_after = after_event_date # If before value is a sun event instead of absolute time if is_sun_event(self._before): # Calculate the today's event utc time or if not available take # next before_event_date = get_astral_event_date( self.hass, self._before, nowutc ) or get_astral_event_next(self.hass, self._before, nowutc) # Before is earlier than after if before_event_date < after_event_date: # Take next day for before before_event_date = get_astral_event_next( self.hass, self._before, after_event_date ) else: # Convert local time provided to UTC today, see above before_event_date = self._naive_time_to_utc_datetime(self._before) # It is safe to add timedelta days=1 to UTC as there is no DST if before_event_date < after_event_date + self._after_offset: before_event_date += timedelta(days=1) self._time_before = before_event_date # We are calculating the _time_after value assuming that it will happen today # But that is not always true, e.g. after 23:00, before 12:00 and now is 10:00 # If _time_before and _time_after are ahead of nowutc: # _time_before is set to 12:00 next day # _time_after is set to 23:00 today # nowutc is set to 10:00 today if ( not is_sun_event(self._after) and self._time_after > nowutc and self._time_before > nowutc + timedelta(days=1) ): # remove one day from _time_before and _time_after self._time_after -= timedelta(days=1) self._time_before -= timedelta(days=1) # Add offset to utc boundaries according to the configuration self._time_after += self._after_offset self._time_before += self._before_offset
def update_as_of(self, utc_point_in_time): """Update the attributes containing solar events.""" # Always need to update next_rising and next_setting so state can be # determined. self.next_rising = get_astral_event_next(self.hass, 'sunrise', utc_point_in_time) self.next_setting = get_astral_event_next(self.hass, 'sunset', utc_point_in_time) # Only need to update remaining properties if they will be reported # in attributes. if STATE_ATTR_MAX_ELEVATION in self._attrs: self._attrs[STATE_ATTR_MAX_ELEVATION] = ( self.location.solar_elevation( get_astral_event_date(self.hass, 'solar_noon', utc_point_in_time))) for attr, event, func in [ (STATE_ATTR_NEXT_DAWN, 'dawn', get_astral_event_next), (STATE_ATTR_NEXT_DUSK, 'dusk', get_astral_event_next), (STATE_ATTR_NEXT_MIDNIGHT, 'solar_midnight', get_astral_event_next), (STATE_ATTR_NEXT_NOON, 'solar_noon', get_astral_event_next), (STATE_ATTR_SUNRISE, 'sunrise', get_astral_event_date), (STATE_ATTR_SUNSET, 'sunset', get_astral_event_date) ]: if attr in self._attrs: self._attrs[attr] = func(self.hass, event, utc_point_in_time) for attr, delta in [(STATE_ATTR_DAYLIGHT, 0), (STATE_ATTR_PREV_DAYLIGHT, -1), (STATE_ATTR_NEXT_DAYLIGHT, 1)]: if attr in self._attrs: daylight = get_astral_event_date( self.hass, 'daylight', utc_point_in_time + timedelta(days=delta)) self._attrs[attr] = (daylight[1] - daylight[0]).total_seconds()
def sun_factor(self, now): now_date = now.date() if self._sun_data and self._sun_data[0] == now_date: (sunrise_begin, sunrise_end, sunset_begin, sunset_end) = self._sun_data[1] else: sunrise = get_astral_event_date(self.hass, 'sunrise', now_date) sunset = get_astral_event_date(self.hass, 'sunset', now_date) sunrise_begin = sunrise - _20_MIN sunrise_end = sunrise + _40_MIN sunset_begin = sunset - _40_MIN sunset_end = sunset + _20_MIN self._sun_data = (now_date, (sunrise_begin, sunrise_end, sunset_begin, sunset_end)) if sunrise_end < now < sunset_begin: # Daytime return 1 if now < sunrise_begin or sunset_end < now: # Nighttime return 0 if now <= sunrise_end: # Sunrise return (now - sunrise_begin).total_seconds() / (60 * 60) else: # Sunset return (sunset_end - now).total_seconds() / (60 * 60)
def sun( hass: HomeAssistant, before: Optional[str] = None, after: Optional[str] = None, before_offset: Optional[timedelta] = None, after_offset: Optional[timedelta] = None, ) -> bool: """Test if current time matches sun requirements.""" utcnow = dt_util.utcnow() today = dt_util.as_local(utcnow).date() before_offset = before_offset or timedelta(0) after_offset = after_offset or timedelta(0) sunrise_today = get_astral_event_date(hass, SUN_EVENT_SUNRISE, today) sunset_today = get_astral_event_date(hass, SUN_EVENT_SUNSET, today) sunrise = sunrise_today sunset = sunset_today if today > dt_util.as_local(cast( datetime, sunrise_today)).date() and SUN_EVENT_SUNRISE in (before, after): tomorrow = dt_util.as_local(utcnow + timedelta(days=1)).date() sunrise_tomorrow = get_astral_event_date(hass, SUN_EVENT_SUNRISE, tomorrow) sunrise = sunrise_tomorrow if today > dt_util.as_local(cast( datetime, sunset_today)).date() and SUN_EVENT_SUNSET in (before, after): tomorrow = dt_util.as_local(utcnow + timedelta(days=1)).date() sunset_tomorrow = get_astral_event_date(hass, SUN_EVENT_SUNSET, tomorrow) sunset = sunset_tomorrow if sunrise is None and SUN_EVENT_SUNRISE in (before, after): # There is no sunrise today return False if sunset is None and SUN_EVENT_SUNSET in (before, after): # There is no sunset today return False if before == SUN_EVENT_SUNRISE and utcnow > cast(datetime, sunrise) + before_offset: return False if before == SUN_EVENT_SUNSET and utcnow > cast(datetime, sunset) + before_offset: return False if after == SUN_EVENT_SUNRISE and utcnow < cast(datetime, sunrise) + after_offset: return False if after == SUN_EVENT_SUNSET and utcnow < cast(datetime, sunset) + after_offset: return False return True
async def test_from_sunrise_to_sunset(hass, freezer, hass_tz_info): """Test period from sunrise to sunset.""" test_time = datetime(2019, 1, 12, tzinfo=hass_tz_info) sunrise = dt_util.as_local( get_astral_event_date(hass, "sunrise", dt_util.as_utc(test_time)) ) sunset = dt_util.as_local( get_astral_event_date(hass, "sunset", dt_util.as_utc(test_time)) ) config = { "binary_sensor": [ { "platform": "tod", "name": "Day", "after": "sunrise", "before": "sunset", } ] } entity_id = "binary_sensor.day" freezer.move_to(sunrise + timedelta(seconds=-1)) await async_setup_component(hass, "binary_sensor", config) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_OFF freezer.move_to(sunrise) async_fire_time_changed(hass, dt_util.utcnow()) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_ON freezer.move_to(sunrise + timedelta(seconds=1)) async_fire_time_changed(hass, dt_util.utcnow()) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_ON freezer.move_to(sunset + timedelta(seconds=-1)) async_fire_time_changed(hass, dt_util.utcnow()) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_ON freezer.move_to(sunset) async_fire_time_changed(hass, dt_util.utcnow()) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_OFF freezer.move_to(sunset + timedelta(seconds=1)) async_fire_time_changed(hass, dt_util.utcnow()) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_OFF
def _calculate_initial_boudary_time(self): """Calculate internal absolute time boudaries.""" nowutc = self.current_datetime # If after value is a sun event instead of absolute time if is_sun_event(self._after): # Calculate the today's event utc time or # if not available take next after_event_date = \ get_astral_event_date(self.hass, self._after, nowutc) or \ get_astral_event_next(self.hass, self._after, nowutc) else: # Convert local time provided to UTC today # datetime.combine(date, time, tzinfo) is not supported # in python 3.5. The self._after is provided # with hass configured TZ not system wide after_event_date = datetime.combine( nowutc, self._after.replace( tzinfo=self.hass.config.time_zone)).astimezone(tz=pytz.UTC) self._time_after = after_event_date # If before value is a sun event instead of absolute time if is_sun_event(self._before): # Calculate the today's event utc time or if not available take # next before_event_date = \ get_astral_event_date(self.hass, self._before, nowutc) or \ get_astral_event_next(self.hass, self._before, nowutc) # Before is earlier than after if before_event_date < after_event_date: # Take next day for before before_event_date = get_astral_event_next( self.hass, self._before, after_event_date) else: # Convert local time provided to UTC today, see above before_event_date = datetime.combine( nowutc, self._before.replace( tzinfo=self.hass.config.time_zone)).astimezone(tz=pytz.UTC) # It is safe to add timedelta days=1 to UTC as there is no DST if before_event_date < after_event_date + self._after_offset: before_event_date += timedelta(days=1) self._time_before = before_event_date # Add offset to utc boundaries according to the configuration self._time_after += self._after_offset self._time_before += self._before_offset
def sunset_time(self, date, day): date = datetime.datetime.strptime( date[:10], '%Y-%m-%d').date() + datetime.timedelta(days=day) data = get_astral_event_date(self.hass, event="sunset", date=date) sunset = self.utc_to_local(data, str(self._timezone)) # _LOGGER.error(sunset) return str(sunset)[:19].replace(" ", "T")
async def async_update(self): """Update the state of the sensor.""" import hdate now = dt_util.as_local(dt_util.now()) _LOGGER.debug("Now: %s Timezone = %s", now, now.tzinfo) today = now.date() sunset = dt_util.as_local(get_astral_event_date( self.hass, SUN_EVENT_SUNSET, today)) _LOGGER.debug("Now: %s Sunset: %s", now, sunset) if now > sunset: today += timedelta(1) date = hdate.HDate( today, diaspora=self.diaspora, hebrew=self._hebrew) if self.type == 'date': self._state = date.hebrew_date elif self.type == 'weekly_portion': self._state = date.parasha elif self.type == 'holiday_name': self._state = date.holiday_description elif self.type == 'holyness': self._state = date.holiday_type else: times = hdate.Zmanim( date=today, latitude=self.latitude, longitude=self.longitude, timezone=self.timezone, hebrew=self._hebrew).zmanim self._state = times[self.type].time() _LOGGER.debug("New value: %s", self._state)
async def async_update(self): """Update the state of the sensor.""" now = dt_util.now() _LOGGER.debug("Now: %s Location: %r", now, self._location) today = now.date() sunset = dt_util.as_local( get_astral_event_date(self.hass, SUN_EVENT_SUNSET, today) ) _LOGGER.debug("Now: %s Sunset: %s", now, sunset) daytime_date = hdate.HDate(today, diaspora=self._diaspora, hebrew=self._hebrew) # The Jewish day starts after darkness (called "tzais") and finishes at # sunset ("shkia"). The time in between is a gray area (aka "Bein # Hashmashot" - literally: "in between the sun and the moon"). # For some sensors, it is more interesting to consider the date to be # tomorrow based on sunset ("shkia"), for others based on "tzais". # Hence the following variables. after_tzais_date = after_shkia_date = daytime_date today_times = self.make_zmanim(today) if now > sunset: after_shkia_date = daytime_date.next_day if today_times.havdalah and now > today_times.havdalah: after_tzais_date = daytime_date.next_day self._state = self.get_state(daytime_date, after_shkia_date, after_tzais_date) _LOGGER.debug("New value for %s: %s", self._type, self._state)
async def async_update(self): """Update the state of the sensor.""" import hdate now = dt_util.as_local(dt_util.now()) _LOGGER.debug("Now: %s Timezone = %s", now, now.tzinfo) today = now.date() sunset = dt_util.as_local( get_astral_event_date(self.hass, SUN_EVENT_SUNSET, today)) _LOGGER.debug("Now: %s Sunset: %s", now, sunset) if now > sunset: today += timedelta(1) date = hdate.HDate(today, diaspora=self.diaspora, hebrew=self._hebrew) if self.type == 'date': self._state = date.hebrew_date elif self.type == 'weekly_portion': self._state = date.parasha elif self.type == 'holiday_name': self._state = date.holiday_description elif self.type == 'holyness': self._state = date.holiday_type else: times = hdate.Zmanim(date=today, latitude=self.latitude, longitude=self.longitude, timezone=self.timezone, hebrew=self._hebrew).zmanim self._state = times[self.type].time() _LOGGER.debug("New value: %s", self._state)
def flux_update(self, now=None): """Update all the lights using flux.""" if now is None: now = dt_now() sunset = get_astral_event_date(self.hass, 'sunset', now.date()) start_time = self.find_start_time(now) stop_time = now.replace( hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) if start_time < now < sunset: # Daytime time_state = 'day' temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Nightime time_state = 'night' if now < stop_time and now > start_time: now_time = now else: now_time = stop_time temp_range = abs(self._sunset_colortemp - self._stop_colortemp) night_length = int(stop_time.timestamp() - sunset.timestamp()) seconds_from_sunset = int(now_time.timestamp() - sunset.timestamp()) percentage_complete = seconds_from_sunset / night_length temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset x_val, y_val, b_val = color_RGB_to_xy(*color_temperature_to_rgb(temp)) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None if self._mode == MODE_XY: set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info("Lights updated to x:%s y:%s brightness:%s, %s%% " "of %s cycle complete at %s", x_val, y_val, brightness, round( percentage_complete * 100), time_state, now) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) set_lights_temp(self.hass, self._lights, mired, brightness) _LOGGER.info("Lights updated to mired:%s brightness:%s, %s%% " "of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, now)
def flux_update(self, now=None): """Update all the lights using flux.""" if now is None: now = dt_now() sunset = get_astral_event_date(self.hass, 'sunset', now.date()) start_time = self.find_start_time(now) stop_time = now.replace(hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) if start_time < now < sunset: # Daytime time_state = 'day' temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Nightime time_state = 'night' if now < stop_time and now > start_time: now_time = now else: now_time = stop_time temp_range = abs(self._sunset_colortemp - self._stop_colortemp) night_length = int(stop_time.timestamp() - sunset.timestamp()) seconds_from_sunset = int(now_time.timestamp() - sunset.timestamp()) percentage_complete = seconds_from_sunset / night_length temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset x_val, y_val, b_val = color_RGB_to_xy(*color_temperature_to_rgb(temp)) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None if self._mode == MODE_XY: set_lights_xy(self.hass, self._lights, x_val, y_val, brightness) _LOGGER.info( "Lights updated to x:%s y:%s brightness:%s, %s%% " "of %s cycle complete at %s", x_val, y_val, brightness, round(percentage_complete * 100), time_state, now) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) set_lights_temp(self.hass, self._lights, mired, brightness) _LOGGER.info( "Lights updated to mired:%s brightness:%s, %s%% " "of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, now)
def find_start_time(self, now): """Return sunrise or start_time if given.""" if self._start_time: sunrise = now.replace(hour=self._start_time.hour, minute=self._start_time.minute, second=0) else: sunrise = get_astral_event_date(self.hass, 'sunrise', now.date()) return sunrise
def find_stop_time(self, now): """Return dusk or stop_time if given.""" if self._stop_time: dusk = now.replace(hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) else: dusk = get_astral_event_date(self.hass, "dusk", now.date()) return dusk
def find_stop_time(self, now): """Return dusk or stop_time if given.""" if self._stop_time: dusk = now.replace( hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) else: dusk = get_astral_event_date(self.hass, 'dusk', now.date()) return dusk
def find_start_time(self, now): """Return sunrise or start_time if given.""" if self._start_time: sunrise = now.replace( hour=self._start_time.hour, minute=self._start_time.minute, second=0) else: sunrise = get_astral_event_date(self.hass, 'sunrise', now.date()) return sunrise
def find_stop_time(self, now): """Return sunset or stop_time if given.""" if self._stop_time: sunset = now.replace(hour=self._stop_time.hour, minute=self._stop_time.minute, second=0) else: sunset = get_astral_event_date(self.hass, SUN_EVENT_SUNSET, now.date()) return sunset
def __init__(self, hass, now): """Initialise pool pump manager.""" self._hass = hass self._now = now self._sun = self._hass.states.get('sun.sun') sunrise = get_astral_event_date(self._hass, SUN_EVENT_SUNRISE, self._now.date()) self._first_run_offset_after_sunrise, self._durations \ = self._build_parameters() run_start_time = self._round_to_next_five_minutes(sunrise + timedelta( minutes=self._first_run_offset_after_sunrise)) self._runs = self.build_runs(run_start_time, self._durations)
def test_norway_in_june(self): """Test location in Norway where the sun doesn't set in summer.""" self.hass.config.latitude = 69.6 self.hass.config.longitude = 18.8 june = datetime(2016, 6, 1, tzinfo=dt_util.UTC) print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNRISE, datetime(2017, 7, 25))) print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNSET, datetime(2017, 7, 25))) print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNRISE, datetime(2017, 7, 26))) print(sun.get_astral_event_date(self.hass, SUN_EVENT_SUNSET, datetime(2017, 7, 26))) assert sun.get_astral_event_next(self.hass, SUN_EVENT_SUNRISE, june) \ == datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC) assert sun.get_astral_event_next(self.hass, SUN_EVENT_SUNSET, june) \ == datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC) assert sun.get_astral_event_date(self.hass, SUN_EVENT_SUNRISE, june) \ is None assert sun.get_astral_event_date(self.hass, SUN_EVENT_SUNSET, june) \ is None
def test_date_events_default_date(hass): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) from astral import Astral astral = Astral() utc_today = utc_now.date() latitude = hass.config.latitude longitude = hass.config.longitude dawn = astral.dawn_utc(utc_today, latitude, longitude) dusk = astral.dusk_utc(utc_today, latitude, longitude) midnight = astral.solar_midnight_utc(utc_today, longitude) noon = astral.solar_noon_utc(utc_today, longitude) sunrise = astral.sunrise_utc(utc_today, latitude, longitude) sunset = astral.sunset_utc(utc_today, latitude, longitude) with patch('homeassistant.util.dt.now', return_value=utc_now): assert dawn == sun.get_astral_event_date(hass, 'dawn', utc_today) assert dusk == sun.get_astral_event_date(hass, 'dusk', utc_today) assert midnight == sun.get_astral_event_date(hass, 'solar_midnight', utc_today) assert noon == sun.get_astral_event_date(hass, 'solar_noon', utc_today) assert sunrise == sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, utc_today) assert sunset == sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, utc_today)
def test_date_events(self): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) from astral import Astral astral = Astral() utc_today = utc_now.date() latitude = self.hass.config.latitude longitude = self.hass.config.longitude dawn = astral.dawn_utc(utc_today, latitude, longitude) dusk = astral.dusk_utc(utc_today, latitude, longitude) midnight = astral.solar_midnight_utc(utc_today, longitude) noon = astral.solar_noon_utc(utc_today, longitude) sunrise = astral.sunrise_utc(utc_today, latitude, longitude) sunset = astral.sunset_utc(utc_today, latitude, longitude) self.assertEqual(dawn, sun.get_astral_event_date( self.hass, 'dawn', utc_today)) self.assertEqual(dusk, sun.get_astral_event_date( self.hass, 'dusk', utc_today)) self.assertEqual(midnight, sun.get_astral_event_date( self.hass, 'solar_midnight', utc_today)) self.assertEqual(noon, sun.get_astral_event_date( self.hass, 'solar_noon', utc_today)) self.assertEqual(sunrise, sun.get_astral_event_date( self.hass, 'sunrise', utc_today)) self.assertEqual(sunset, sun.get_astral_event_date( self.hass, 'sunset', utc_today))
def test_norway_in_june(hass): """Test location in Norway where the sun doesn't set in summer.""" hass.config.latitude = 69.6 hass.config.longitude = 18.8 june = datetime(2016, 6, 1, tzinfo=dt_util.UTC) print( sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, datetime(2017, 7, 25))) print( sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, datetime(2017, 7, 25))) print( sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, datetime(2017, 7, 26))) print( sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, datetime(2017, 7, 26))) assert sun.get_astral_event_next(hass, SUN_EVENT_SUNRISE, june) \ == datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC) assert sun.get_astral_event_next(hass, SUN_EVENT_SUNSET, june) \ == datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC) assert sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, june) \ is None assert sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, june) \ is None
def test_date_events(self): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) from astral import Astral astral = Astral() utc_today = utc_now.date() latitude = self.hass.config.latitude longitude = self.hass.config.longitude dawn = astral.dawn_utc(utc_today, latitude, longitude) dusk = astral.dusk_utc(utc_today, latitude, longitude) midnight = astral.solar_midnight_utc(utc_today, longitude) noon = astral.solar_noon_utc(utc_today, longitude) sunrise = astral.sunrise_utc(utc_today, latitude, longitude) sunset = astral.sunset_utc(utc_today, latitude, longitude) assert dawn == sun.get_astral_event_date( self.hass, 'dawn', utc_today) assert dusk == sun.get_astral_event_date( self.hass, 'dusk', utc_today) assert midnight == sun.get_astral_event_date( self.hass, 'solar_midnight', utc_today) assert noon == sun.get_astral_event_date( self.hass, 'solar_noon', utc_today) assert sunrise == sun.get_astral_event_date( self.hass, SUN_EVENT_SUNRISE, utc_today) assert sunset == sun.get_astral_event_date( self.hass, SUN_EVENT_SUNSET, utc_today)
def test_date_events(hass): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) from astral import Astral astral = Astral() utc_today = utc_now.date() latitude = hass.config.latitude longitude = hass.config.longitude dawn = astral.dawn_utc(utc_today, latitude, longitude) dusk = astral.dusk_utc(utc_today, latitude, longitude) midnight = astral.solar_midnight_utc(utc_today, longitude) noon = astral.solar_noon_utc(utc_today, longitude) sunrise = astral.sunrise_utc(utc_today, latitude, longitude) sunset = astral.sunset_utc(utc_today, latitude, longitude) assert dawn == sun.get_astral_event_date(hass, "dawn", utc_today) assert dusk == sun.get_astral_event_date(hass, "dusk", utc_today) assert midnight == sun.get_astral_event_date(hass, "solar_midnight", utc_today) assert noon == sun.get_astral_event_date(hass, "solar_noon", utc_today) assert sunrise == sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, utc_today) assert sunset == sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, utc_today)
def test_norway_in_june(self): """Test location in Norway where the sun doesn't set in summer.""" self.hass.config.latitude = 69.6 self.hass.config.longitude = 18.8 june = datetime(2016, 6, 1, tzinfo=dt_util.UTC) print( sun.get_astral_event_date(self.hass, 'sunrise', datetime(2017, 7, 25))) print( sun.get_astral_event_date(self.hass, 'sunset', datetime(2017, 7, 25))) print( sun.get_astral_event_date(self.hass, 'sunrise', datetime(2017, 7, 26))) print( sun.get_astral_event_date(self.hass, 'sunset', datetime(2017, 7, 26))) assert sun.get_astral_event_next(self.hass, 'sunrise', june) == \ datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC) assert sun.get_astral_event_next(self.hass, 'sunset', june) == \ datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC) assert sun.get_astral_event_date(self.hass, 'sunrise', june) is None assert sun.get_astral_event_date(self.hass, 'sunset', june) is None
def test_date_events(self): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) from astral import Astral astral = Astral() utc_today = utc_now.date() latitude = self.hass.config.latitude longitude = self.hass.config.longitude dawn = astral.dawn_utc(utc_today, latitude, longitude) dusk = astral.dusk_utc(utc_today, latitude, longitude) midnight = astral.solar_midnight_utc(utc_today, longitude) noon = astral.solar_noon_utc(utc_today, longitude) sunrise = astral.sunrise_utc(utc_today, latitude, longitude) sunset = astral.sunset_utc(utc_today, latitude, longitude) self.assertEqual( dawn, sun.get_astral_event_date(self.hass, 'dawn', utc_today)) self.assertEqual( dusk, sun.get_astral_event_date(self.hass, 'dusk', utc_today)) self.assertEqual( midnight, sun.get_astral_event_date(self.hass, 'solar_midnight', utc_today)) self.assertEqual( noon, sun.get_astral_event_date(self.hass, 'solar_noon', utc_today)) self.assertEqual( sunrise, sun.get_astral_event_date(self.hass, 'sunrise', utc_today)) self.assertEqual( sunset, sun.get_astral_event_date(self.hass, 'sunset', utc_today))
def test_date_events(hass): """Test retrieving next sun events.""" utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC) from astral import LocationInfo import astral.sun utc_today = utc_now.date() location = LocationInfo( latitude=hass.config.latitude, longitude=hass.config.longitude ) dawn = astral.sun.dawn(location.observer, utc_today) dusk = astral.sun.dusk(location.observer, utc_today) midnight = astral.sun.midnight(location.observer, utc_today) noon = astral.sun.noon(location.observer, utc_today) sunrise = astral.sun.sunrise(location.observer, utc_today) sunset = astral.sun.sunset(location.observer, utc_today) assert dawn == sun.get_astral_event_date(hass, "dawn", utc_today) assert dusk == sun.get_astral_event_date(hass, "dusk", utc_today) assert midnight == sun.get_astral_event_date(hass, "midnight", utc_today) assert noon == sun.get_astral_event_date(hass, "noon", utc_today) assert sunrise == sun.get_astral_event_date(hass, SUN_EVENT_SUNRISE, utc_today) assert sunset == sun.get_astral_event_date(hass, SUN_EVENT_SUNSET, utc_today)
async def async_update(self): """Update the state of the sensor.""" import hdate now = dt_util.as_local(dt_util.now()) _LOGGER.debug("Now: %s Timezone = %s", now, now.tzinfo) today = now.date() upcoming_saturday = today + timedelta((12 - today.weekday()) % 7) sunset = dt_util.as_local(get_astral_event_date( self.hass, SUN_EVENT_SUNSET, today)) _LOGGER.debug("Now: %s Sunset: %s", now, sunset) if now > sunset: today += timedelta(1) date = hdate.HDate( today, diaspora=self.diaspora, hebrew=self._hebrew) upcoming_shabbat = hdate.HDate( upcoming_saturday, diaspora=self.diaspora, hebrew=self._hebrew) if self.type == 'date': self._state = hdate.date.get_hebrew_date( date.h_day, date.h_month, date.h_year, hebrew=self._hebrew) elif self.type == 'weekly_portion': self._state = hdate.date.get_parashe( upcoming_shabbat.get_reading(self.diaspora), hebrew=self._hebrew) elif self.type == 'holiday_name': try: description = next( x.description[self._hebrew] for x in hdate.htables.HOLIDAYS if x.index == date.get_holyday()) if not self._hebrew: self._state = description else: self._state = description.long except StopIteration: self._state = None elif self.type == 'holyness': self._state = hdate.date.get_holyday_type(date.get_holyday()) else: times = hdate.Zmanim( date=today, latitude=self.latitude, longitude=self.longitude, timezone=self.timezone, hebrew=self._hebrew).zmanim self._state = times[self.type].time() _LOGGER.debug("New value: %s", self._state)
def get_weather_symbol(symbol, hass=None): """Get a weather symbol for the symbol value.""" ret_val = "" if symbol in FMI_WEATHER_SYMBOL_MAP.keys(): ret_val = FMI_WEATHER_SYMBOL_MAP[symbol] if hass is not None and ret_val == 1: # Clear as per FMI today = date.today() sunset = get_astral_event_date(hass, SUN_EVENT_SUNSET, today) sunset = sunset.astimezone(tz.tzlocal()) if datetime.now().astimezone(tz.tzlocal()) >= sunset: # Clear night ret_val = FMI_WEATHER_SYMBOL_MAP[0] return ret_val
async def test_from_sunset_to_sunrise(hass, freezer, hass_tz_info): """Test period from sunset to sunrise.""" test_time = datetime(2019, 1, 12, tzinfo=hass_tz_info) sunset = dt_util.as_local(get_astral_event_date(hass, "sunset", test_time)) sunrise = dt_util.as_local(get_astral_event_next(hass, "sunrise", sunset)) # assert sunset == sunrise config = { "binary_sensor": [{ "platform": "tod", "name": "Night", "after": "sunset", "before": "sunrise", }] } entity_id = "binary_sensor.night" freezer.move_to(sunset + timedelta(seconds=-1)) await async_setup_component(hass, "binary_sensor", config) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_OFF freezer.move_to(sunset) hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: dt_util.utcnow()}) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_ON freezer.move_to(sunset + timedelta(minutes=1)) hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: dt_util.utcnow()}) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_ON freezer.move_to(sunrise + timedelta(minutes=-1)) hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: dt_util.utcnow()}) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_ON freezer.move_to(sunrise) hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: dt_util.utcnow()}) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_OFF freezer.move_to(sunrise + timedelta(minutes=1)) hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: dt_util.utcnow()}) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == STATE_OFF
def sun(hass: HomeAssistant, before: Optional[str] = None, after: Optional[str] = None, before_offset: Optional[timedelta] = None, after_offset: Optional[timedelta] = None) -> bool: """Test if current time matches sun requirements.""" utcnow = dt_util.utcnow() today = dt_util.as_local(utcnow).date() before_offset = before_offset or timedelta(0) after_offset = after_offset or timedelta(0) sunrise = get_astral_event_date(hass, SUN_EVENT_SUNRISE, today) sunset = get_astral_event_date(hass, SUN_EVENT_SUNSET, today) if sunrise is None and SUN_EVENT_SUNRISE in (before, after): # There is no sunrise today return False if sunset is None and SUN_EVENT_SUNSET in (before, after): # There is no sunset today return False if before == SUN_EVENT_SUNRISE and \ utcnow > cast(datetime, sunrise) + before_offset: return False if before == SUN_EVENT_SUNSET and \ utcnow > cast(datetime, sunset) + before_offset: return False if after == SUN_EVENT_SUNRISE and \ utcnow < cast(datetime, sunrise) + after_offset: return False if after == SUN_EVENT_SUNSET and \ utcnow < cast(datetime, sunset) + after_offset: return False return True
def __init__(self, hass, now): """Initialise pool pump manager.""" self._hass = hass self._now = now self._sun = self._hass.states.get("sun.sun") schedule_config = { "break_duration": hass.data[DOMAIN][ATTR_SCHEDULE_BREAK_DURATION_IN_HOURS] } self._pool_controler = AbacusFilteringDuration(schedule_config=schedule_config) # TODO: check when the schedule for next day is computed noon = dt_util.as_local( get_astral_event_date(self._hass, "solar_noon", self._now.date()) ) _LOGGER.debug("Solar noon is at: {}".format(noon)) self._total_duration_in_hours = self._build_parameters() # Create runs with a pivot on solar noon self._runs = self._pool_controler.update_schedule(noon)
def test_sun_offset(self): """Test sun event with offset.""" test_time = self.hass.config.time_zone.localize( datetime(2019, 1, 12)).astimezone(pytz.UTC) sunrise = dt_util.as_local(get_astral_event_date( self.hass, 'sunrise', dt_util.as_utc(test_time)) + timedelta(hours=-1, minutes=-30)) sunset = dt_util.as_local(get_astral_event_date( self.hass, 'sunset', dt_util.as_utc(test_time)) + timedelta(hours=1, minutes=30)) config = { 'binary_sensor': [ { 'platform': 'tod', 'name': 'Day', 'after': 'sunrise', 'after_offset': '-1:30', 'before': 'sunset', 'before_offset': '1:30' } ] } entity_id = 'binary_sensor.day' testtime = sunrise + timedelta(seconds=-1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): setup_component(self.hass, 'binary_sensor', config) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF testtime = sunrise with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON testtime = sunrise + timedelta(seconds=1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON self.hass.block_till_done() testtime = sunset + timedelta(seconds=-1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON self.hass.block_till_done() testtime = sunset with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF self.hass.block_till_done() testtime = sunset + timedelta(seconds=1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF test_time = test_time + timedelta(days=1) sunrise = dt_util.as_local(get_astral_event_date( self.hass, 'sunrise', dt_util.as_utc(test_time)) + timedelta(hours=-1, minutes=-30)) testtime = sunrise with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON
def test_from_sunset_to_sunrise(self): """Test period from sunset to sunrise.""" test_time = self.hass.config.time_zone.localize( datetime(2019, 1, 12)).astimezone(pytz.UTC) sunset = dt_util.as_local(get_astral_event_date( self.hass, 'sunset', test_time)) sunrise = dt_util.as_local(get_astral_event_next( self.hass, 'sunrise', sunset)) # assert sunset == sunrise config = { 'binary_sensor': [ { 'platform': 'tod', 'name': 'Night', 'after': 'sunset', 'before': 'sunrise' } ] } entity_id = 'binary_sensor.night' testtime = sunset + timedelta(minutes=-1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): setup_component(self.hass, 'binary_sensor', config) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF testtime = sunset with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON testtime = sunset + timedelta(minutes=1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON testtime = sunrise + timedelta(minutes=-1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON testtime = sunrise with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) self.hass.block_till_done() # assert state == "dupa" assert state.state == STATE_OFF testtime = sunrise + timedelta(minutes=1) with patch('homeassistant.components.tod.binary_sensor.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF
def find_stop_time(self, now): """Return sunset or stop_time if given.""" sunset = get_astral_event_date(self.hass, SUN_EVENT_SUNSET, now.date()) return sunset
def find_start_time(self, now): """Return sunrise or start_time if given.""" sunrise = get_astral_event_date(self.hass, SUN_EVENT_SUNRISE, now.date()) return sunrise
def sun( hass: HomeAssistant, before: str | None = None, after: str | None = None, before_offset: timedelta | None = None, after_offset: timedelta | None = None, ) -> bool: """Test if current time matches sun requirements.""" utcnow = dt_util.utcnow() today = dt_util.as_local(utcnow).date() before_offset = before_offset or timedelta(0) after_offset = after_offset or timedelta(0) sunrise_today = get_astral_event_date(hass, SUN_EVENT_SUNRISE, today) sunset_today = get_astral_event_date(hass, SUN_EVENT_SUNSET, today) sunrise = sunrise_today sunset = sunset_today if today > dt_util.as_local( cast(datetime, sunrise_today) ).date() and SUN_EVENT_SUNRISE in (before, after): tomorrow = dt_util.as_local(utcnow + timedelta(days=1)).date() sunrise_tomorrow = get_astral_event_date(hass, SUN_EVENT_SUNRISE, tomorrow) sunrise = sunrise_tomorrow if today > dt_util.as_local( cast(datetime, sunset_today) ).date() and SUN_EVENT_SUNSET in (before, after): tomorrow = dt_util.as_local(utcnow + timedelta(days=1)).date() sunset_tomorrow = get_astral_event_date(hass, SUN_EVENT_SUNSET, tomorrow) sunset = sunset_tomorrow if sunrise is None and SUN_EVENT_SUNRISE in (before, after): # There is no sunrise today condition_trace_set_result(False, message="no sunrise today") return False if sunset is None and SUN_EVENT_SUNSET in (before, after): # There is no sunset today condition_trace_set_result(False, message="no sunset today") return False if before == SUN_EVENT_SUNRISE: wanted_time_before = cast(datetime, sunrise) + before_offset condition_trace_update_result(wanted_time_before=wanted_time_before) if utcnow > wanted_time_before: return False if before == SUN_EVENT_SUNSET: wanted_time_before = cast(datetime, sunset) + before_offset condition_trace_update_result(wanted_time_before=wanted_time_before) if utcnow > wanted_time_before: return False if after == SUN_EVENT_SUNRISE: wanted_time_after = cast(datetime, sunrise) + after_offset condition_trace_update_result(wanted_time_after=wanted_time_after) if utcnow < wanted_time_after: return False if after == SUN_EVENT_SUNSET: wanted_time_after = cast(datetime, sunset) + after_offset condition_trace_update_result(wanted_time_after=wanted_time_after) if utcnow < wanted_time_after: return False return True
async def async_update(self): """Update the state of the sensor.""" import hdate now = dt_util.as_local(dt_util.now()) _LOGGER.debug("Now: %s Timezone = %s", now, now.tzinfo) today = now.date() sunset = dt_util.as_local(get_astral_event_date( self.hass, SUN_EVENT_SUNSET, today)) _LOGGER.debug("Now: %s Sunset: %s", now, sunset) if now > sunset: today += timedelta(1) date = hdate.HDate( today, diaspora=self.diaspora, hebrew=self._hebrew) location = hdate.Location(latitude=self.latitude, longitude=self.longitude, timezone=self.timezone, diaspora=self.diaspora) def make_zmanim(date): """Create a Zmanim object.""" return hdate.Zmanim( date=date, location=location, candle_lighting_offset=self.candle_lighting_offset, havdalah_offset=self.havdalah_offset, hebrew=self._hebrew) if self.type == 'date': self._state = date.hebrew_date elif self.type == 'weekly_portion': # Compute the weekly portion based on the upcoming shabbat. self._state = date.upcoming_shabbat.parasha elif self.type == 'holiday_name': self._state = date.holiday_description elif self.type == 'holyness': self._state = date.holiday_type elif self.type == 'upcoming_shabbat_candle_lighting': times = make_zmanim(date.upcoming_shabbat.previous_day.gdate) self._state = times.candle_lighting elif self.type == 'upcoming_candle_lighting': times = make_zmanim(date.upcoming_shabbat_or_yom_tov.first_day .previous_day.gdate) self._state = times.candle_lighting elif self.type == 'upcoming_shabbat_havdalah': times = make_zmanim(date.upcoming_shabbat.gdate) self._state = times.havdalah elif self.type == 'upcoming_havdalah': times = make_zmanim(date.upcoming_shabbat_or_yom_tov .last_day.gdate) self._state = times.havdalah elif self.type == 'issur_melacha_in_effect': self._state = make_zmanim(now).issur_melacha_in_effect else: times = make_zmanim(today).zmanim self._state = times[self.type].time() _LOGGER.debug("New value: %s", self._state)
async def async_flux_update(self, utcnow=None): """Update all the lights using flux.""" if utcnow is None: utcnow = dt_utcnow() now = as_local(utcnow) sunset = get_astral_event_date(self.hass, SUN_EVENT_SUNSET, now.date()) start_time = self.find_start_time(now) stop_time = self.find_stop_time(now) if stop_time <= start_time: # stop_time does not happen in the same day as start_time if start_time < now: # stop time is tomorrow stop_time += datetime.timedelta(days=1) elif now < start_time: # stop_time was yesterday since the new start_time is not reached stop_time -= datetime.timedelta(days=1) if start_time < now < sunset: # Daytime time_state = "day" temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Night time time_state = "night" if now < stop_time: if stop_time < start_time and stop_time.day == sunset.day: # we need to use yesterday's sunset time sunset_time = sunset - datetime.timedelta(days=1) else: sunset_time = sunset night_length = int(stop_time.timestamp() - sunset_time.timestamp()) seconds_from_sunset = int(now.timestamp() - sunset_time.timestamp()) percentage_complete = seconds_from_sunset / night_length else: percentage_complete = 1 temp_range = abs(self._sunset_colortemp - self._stop_colortemp) temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset rgb = color_temperature_to_rgb(temp) x_val, y_val, b_val = color_RGB_to_xy_brightness(*rgb) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None if self._mode == MODE_XY: await async_set_lights_xy(self.hass, self._lights, x_val, y_val, brightness, self._transition) _LOGGER.debug( "Lights updated to x:%s y:%s brightness:%s, %s%% " "of %s cycle complete at %s", x_val, y_val, brightness, round(percentage_complete * 100), time_state, now, ) elif self._mode == MODE_RGB: await async_set_lights_rgb(self.hass, self._lights, rgb, self._transition) _LOGGER.debug( "Lights updated to rgb:%s, %s%% of %s cycle complete at %s", rgb, round(percentage_complete * 100), time_state, now, ) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) await async_set_lights_temp(self.hass, self._lights, mired, brightness, self._transition) _LOGGER.debug( "Lights updated to mired:%s brightness:%s, %s%% " "of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, now, )
async def async_update(self): """Update the state of the sensor.""" import hdate now = dt_util.as_local(dt_util.now()) _LOGGER.debug("Now: %s Timezone = %s", now, now.tzinfo) today = now.date() sunset = dt_util.as_local(get_astral_event_date( self.hass, SUN_EVENT_SUNSET, today)) _LOGGER.debug("Now: %s Sunset: %s", now, sunset) location = hdate.Location(latitude=self.latitude, longitude=self.longitude, timezone=self.timezone, diaspora=self.diaspora) def make_zmanim(date): """Create a Zmanim object.""" return hdate.Zmanim( date=date, location=location, candle_lighting_offset=self.candle_lighting_offset, havdalah_offset=self.havdalah_offset, hebrew=self._hebrew) date = hdate.HDate( today, diaspora=self.diaspora, hebrew=self._hebrew) lagging_date = date # Advance Hebrew date if sunset has passed. # Not all sensors should advance immediately when the Hebrew date # officially changes (i.e. after sunset), hence lagging_date. if now > sunset: date = date.next_day today_times = make_zmanim(today) if today_times.havdalah and now > today_times.havdalah: lagging_date = lagging_date.next_day # Terminology note: by convention in py-libhdate library, "upcoming" # refers to "current" or "upcoming" dates. if self.type == 'date': self._state = date.hebrew_date elif self.type == 'weekly_portion': # Compute the weekly portion based on the upcoming shabbat. self._state = lagging_date.upcoming_shabbat.parasha elif self.type == 'holiday_name': self._state = date.holiday_description elif self.type == 'holyness': self._state = date.holiday_type elif self.type == 'upcoming_shabbat_candle_lighting': times = make_zmanim(lagging_date.upcoming_shabbat .previous_day.gdate) self._state = times.candle_lighting elif self.type == 'upcoming_candle_lighting': times = make_zmanim(lagging_date.upcoming_shabbat_or_yom_tov .first_day.previous_day.gdate) self._state = times.candle_lighting elif self.type == 'upcoming_shabbat_havdalah': times = make_zmanim(lagging_date.upcoming_shabbat.gdate) self._state = times.havdalah elif self.type == 'upcoming_havdalah': times = make_zmanim(lagging_date.upcoming_shabbat_or_yom_tov .last_day.gdate) self._state = times.havdalah elif self.type == 'issur_melacha_in_effect': self._state = make_zmanim(now).issur_melacha_in_effect else: times = make_zmanim(today).zmanim self._state = times[self.type].time() _LOGGER.debug("New value: %s", self._state)
def test_from_sunrise_to_sunset(self): """Test period from sunrise to sunset.""" test_time = datetime( 2019, 1, 12, tzinfo=self.hass.config.time_zone) sunrise = dt_util.as_local(get_astral_event_date( self.hass, 'sunrise', dt_util.as_utc(test_time))) sunset = dt_util.as_local(get_astral_event_date( self.hass, 'sunset', dt_util.as_utc(test_time))) config = { 'binary_sensor': [ { 'platform': 'tod', 'name': 'Day', 'after': 'sunrise', 'before': 'sunset' } ] } entity_id = 'binary_sensor.day' testtime = sunrise + timedelta(seconds=-1) with patch('homeassistant.components.binary_sensor.tod.dt_util.utcnow', return_value=testtime): setup_component(self.hass, 'binary_sensor', config) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF testtime = sunrise with patch('homeassistant.components.binary_sensor.tod.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON testtime = sunrise + timedelta(seconds=1) with patch('homeassistant.components.binary_sensor.tod.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON self.hass.block_till_done() testtime = sunset + timedelta(seconds=-1) with patch('homeassistant.components.binary_sensor.tod.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_ON self.hass.block_till_done() testtime = sunset with patch('homeassistant.components.binary_sensor.tod.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF self.hass.block_till_done() testtime = sunset + timedelta(seconds=1) with patch('homeassistant.components.binary_sensor.tod.dt_util.utcnow', return_value=testtime): self.hass.bus.fire(ha.EVENT_TIME_CHANGED, { ha.ATTR_NOW: testtime}) self.hass.block_till_done() state = self.hass.states.get(entity_id) assert state.state == STATE_OFF
def flux_update(self, now=None): """Update all the lights using flux.""" if now is None: now = dt_now() sunset = get_astral_event_date(self.hass, 'sunset', now.date()) start_time = self.find_start_time(now) stop_time = self.find_stop_time(now) if stop_time <= start_time: # stop_time does not happen in the same day as start_time if start_time < now: # stop time is tomorrow stop_time += datetime.timedelta(days=1) elif now < start_time: # stop_time was yesterday since the new start_time is not reached stop_time -= datetime.timedelta(days=1) if start_time < now < sunset: # Daytime time_state = 'day' temp_range = abs(self._start_colortemp - self._sunset_colortemp) day_length = int(sunset.timestamp() - start_time.timestamp()) seconds_from_start = int(now.timestamp() - start_time.timestamp()) percentage_complete = seconds_from_start / day_length temp_offset = temp_range * percentage_complete if self._start_colortemp > self._sunset_colortemp: temp = self._start_colortemp - temp_offset else: temp = self._start_colortemp + temp_offset else: # Night time time_state = 'night' if now < stop_time: if stop_time < start_time and stop_time.day == sunset.day: # we need to use yesterday's sunset time sunset_time = sunset - datetime.timedelta(days=1) else: sunset_time = sunset # pylint: disable=no-member night_length = int(stop_time.timestamp() - sunset_time.timestamp()) seconds_from_sunset = int(now.timestamp() - sunset_time.timestamp()) percentage_complete = seconds_from_sunset / night_length else: percentage_complete = 1 temp_range = abs(self._sunset_colortemp - self._stop_colortemp) temp_offset = temp_range * percentage_complete if self._sunset_colortemp > self._stop_colortemp: temp = self._sunset_colortemp - temp_offset else: temp = self._sunset_colortemp + temp_offset rgb = color_temperature_to_rgb(temp) x_val, y_val, b_val = color_RGB_to_xy_brightness(*rgb) brightness = self._brightness if self._brightness else b_val if self._disable_brightness_adjust: brightness = None if self._mode == MODE_XY: set_lights_xy(self.hass, self._lights, x_val, y_val, brightness, self._transition) _LOGGER.info("Lights updated to x:%s y:%s brightness:%s, %s%% " "of %s cycle complete at %s", x_val, y_val, brightness, round( percentage_complete * 100), time_state, now) elif self._mode == MODE_RGB: set_lights_rgb(self.hass, self._lights, rgb, self._transition) _LOGGER.info("Lights updated to rgb:%s, %s%% " "of %s cycle complete at %s", rgb, round(percentage_complete * 100), time_state, now) else: # Convert to mired and clamp to allowed values mired = color_temperature_kelvin_to_mired(temp) set_lights_temp(self.hass, self._lights, mired, brightness, self._transition) _LOGGER.info("Lights updated to mired:%s brightness:%s, %s%% " "of %s cycle complete at %s", mired, brightness, round(percentage_complete * 100), time_state, now)