예제 #1
0
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
예제 #2
0
 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())
예제 #3
0
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
예제 #4
0
    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
예제 #5
0
 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()
예제 #6
0
    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)
예제 #7
0
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
예제 #8
0
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
예제 #9
0
    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
예제 #10
0
 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")
예제 #11
0
    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)
예제 #12
0
    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)
예제 #13
0
    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)
예제 #14
0
    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)
예제 #15
0
    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)
예제 #16
0
 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
예제 #17
0
 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
예제 #18
0
 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
예제 #19
0
 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
예제 #20
0
 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
예제 #21
0
 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)
예제 #22
0
    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
예제 #23
0
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)
예제 #24
0
    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))
예제 #25
0
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
예제 #26
0
    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)
예제 #27
0
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)
예제 #28
0
    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
예제 #29
0
    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))
예제 #30
0
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)
예제 #31
0
    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)
예제 #32
0
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
예제 #34
0
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
예제 #35
0
    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)
예제 #36
0
    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
예제 #37
0
    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
예제 #38
0
 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
예제 #39
0
 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
예제 #40
0
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
예제 #41
0
    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)
예제 #42
0
    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,
            )
예제 #43
0
    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)
예제 #44
0
    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
예제 #45
0
    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)