コード例 #1
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())
コード例 #2
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
コード例 #3
0
async def test_norwegian_case_winter(hass, freezer, hass_tz_info):
    """Test location in Norway where the sun doesn't set in summer."""
    hass.config.latitude = 69.6
    hass.config.longitude = 18.8

    test_time = datetime(2010, 1, 1, tzinfo=hass_tz_info)
    sunrise = dt_util.as_local(
        get_astral_event_next(hass, "sunrise", dt_util.as_utc(test_time)))
    sunset = dt_util.as_local(
        get_astral_event_next(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(test_time)
    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 + timedelta(seconds=-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

    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_ON

    freezer.move_to(sunrise + timedelta(seconds=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(sunset + timedelta(seconds=-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(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_OFF

    freezer.move_to(sunset + timedelta(seconds=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
コード例 #4
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
コード例 #5
0
ファイル: test_sun.py プロジェクト: ManHammer/home-assistant
    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
コード例 #6
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()
コード例 #7
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
コード例 #8
0
 def _daylight_today(self) -> float:
     """Calculate duration in hours between sunrise and sunset today."""
     today = dt_util.now()
     today = today.replace(hour=1)
     _LOGGER.debug("Calculating daylight for today: %s", today)
     sunrise = get_astral_event_next(self._hass, SUN_EVENT_SUNRISE,
                                     dt_util.as_utc(today))
     sunset = get_astral_event_next(self._hass, SUN_EVENT_SUNSET,
                                    dt_util.as_utc(today))
     daylight = sunset - sunrise
     daylight_in_hours = daylight.total_seconds() / 3600
     _LOGGER.debug("Total daylight today: %.1f hours", daylight_in_hours)
     return daylight_in_hours
コード例 #9
0
ファイル: tod.py プロジェクト: pp81381/home-assistant
    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
ファイル: event.py プロジェクト: boced66/home-assistant
 def sunset_automation_listener(now):
     """Handle points in time to execute actions."""
     nonlocal remove
     remove = async_track_point_in_utc_time(
         hass, sunset_automation_listener, get_astral_event_next(
             hass, SUN_EVENT_SUNSET, offset=offset))
     hass.async_run_job(action)
コード例 #11
0
 def sunset_automation_listener(now):
     """Handle points in time to execute actions."""
     nonlocal remove
     remove = async_track_point_in_utc_time(
         hass, sunset_automation_listener,
         get_astral_event_next(hass, 'sunset', offset=offset))
     hass.async_run_job(action)
コード例 #12
0
    def _listen_next_sun_event(self):
        """Set up the sun event listener."""
        assert self._unsub_sun is None

        self._unsub_sun = async_track_point_in_utc_time(
            self.hass, self._handle_sun_event,
            get_astral_event_next(self.hass, self.event, offset=self.offset))
コード例 #13
0
    def check_light_on_dev_state_change(entity, old_state, new_state):
        """Handle tracked device state changes."""
        lights_are_on = group.is_on(hass, light_group)
        light_needed = not (lights_are_on or is_up(hass))

        # These variables are needed for the elif check
        now = dt_util.utcnow()
        start_point = calc_time_for_light_when_sunset()

        # Do we need lights?
        if light_needed:
            logger.info("Home coming event for %s. Turning lights on", entity)
            light.async_turn_on(hass, light_ids, profile=light_profile)

        # Are we in the time span were we would turn on the lights
        # if someone would be home?
        # Check this by seeing if current time is later then the point
        # in time when we would start putting the lights on.
        elif (start_point and
              start_point < now < get_astral_event_next(hass, 'sunset')):

            # Check for every light if it would be on if someone was home
            # when the fading in started and turn it on if so
            for index, light_id in enumerate(light_ids):
                if now > start_point + index * LIGHT_TRANSITION_TIME:
                    light.async_turn_on(hass, light_id)

                else:
                    # If this light didn't happen to be turned on yet so
                    # will all the following then, break.
                    break
コード例 #14
0
    def check_light_on_dev_state_change(entity, old_state, new_state):
        """Handle tracked device state changes."""
        lights_are_on = group.is_on(light_group)
        light_needed = not (lights_are_on or is_up(hass))

        # These variables are needed for the elif check
        now = dt_util.utcnow()
        start_point = calc_time_for_light_when_sunset()

        # Do we need lights?
        if light_needed:
            logger.info("Home coming event for %s. Turning lights on", entity)
            light.async_turn_on(light_ids, profile=light_profile)

        # Are we in the time span were we would turn on the lights
        # if someone would be home?
        # Check this by seeing if current time is later then the point
        # in time when we would start putting the lights on.
        elif (start_point
              and start_point < now < get_astral_event_next(hass, 'sunset')):

            # Check for every light if it would be on if someone was home
            # when the fading in started and turn it on if so
            for index, light_id in enumerate(light_ids):
                if now > start_point + index * LIGHT_TRANSITION_TIME:
                    light.async_turn_on(light_id)

                else:
                    # If this light didn't happen to be turned on yet so
                    # will all the following then, break.
                    break
コード例 #15
0
ファイル: binary_sensor.py プロジェクト: Twtcer/core-1
    def _turn_to_next_day(self):
        """Turn to to the next day."""
        if is_sun_event(self._after):
            self._time_after = get_astral_event_next(
                self.hass, self._after, self._time_after - self._after_offset)
            self._time_after += self._after_offset
        else:
            # Offset is already there
            self._time_after += timedelta(days=1)

        if is_sun_event(self._before):
            self._time_before = get_astral_event_next(
                self.hass, self._before,
                self._time_before - self._before_offset)
            self._time_before += self._before_offset
        else:
            # Offset is already there
            self._time_before += timedelta(days=1)
コード例 #16
0
ファイル: tod.py プロジェクト: chilicheech/home-assistant
    def _turn_to_next_day(self):
        """Turn to to the next day."""
        if is_sun_event(self._after):
            self._time_after = get_astral_event_next(
                self.hass, self._after,
                self._time_after - self._after_offset)
            self._time_after += self._after_offset
        else:
            # Offset is already there
            self._time_after += timedelta(days=1)

        if is_sun_event(self._before):
            self._time_before = get_astral_event_next(
                self.hass, self._before,
                self._time_before - self._before_offset)
            self._time_before += self._before_offset
        else:
            # Offset is already there
            self._time_before += timedelta(days=1)
コード例 #17
0
def get_solar_event(solar_event, local_now, hass):
    """Returns the next occurring solar event. Local time."""
    start_of_day_utc = dt_util.as_utc(
        datetime.combine(local_now.date(), time(hour=0, minute=0)))

    next_dawn = dt_util.as_local(
        get_astral_event_next(hass,
                              solar_event,
                              utc_point_in_time=start_of_day_utc))
    return next_dawn
コード例 #18
0
    def calc_time_for_light_when_sunset():
        """Calculate the time when to start fading lights in when sun sets.

        Returns None if no next_setting data available.

        Async friendly.
        """
        next_setting = get_astral_event_next(hass, 'sunset')
        if not next_setting:
            return None
        return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)
コード例 #19
0
ファイル: __init__.py プロジェクト: dcnielsen90/core
    def calc_time_for_light_when_sunset():
        """Calculate the time when to start fading lights in when sun sets.

        Returns None if no next_setting data available.

        Async friendly.
        """
        next_setting = get_astral_event_next(hass, SUN_EVENT_SUNSET)
        if not next_setting:
            return None
        return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)
コード例 #20
0
ファイル: test_binary_sensor.py プロジェクト: jcgoette/core
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)
    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(minutes=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(sunrise + timedelta(minutes=-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(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_OFF

    freezer.move_to(sunrise + timedelta(minutes=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
コード例 #21
0
ファイル: __init__.py プロジェクト: zezo010/home-assistant
 def update_as_of(self, utc_point_in_time):
     """Update the attributes containing solar events."""
     self.next_dawn = get_astral_event_next(
         self.hass, 'dawn', utc_point_in_time)
     self.next_dusk = get_astral_event_next(
         self.hass, 'dusk', utc_point_in_time)
     self.next_midnight = get_astral_event_next(
         self.hass, 'solar_midnight', utc_point_in_time)
     self.next_noon = get_astral_event_next(
         self.hass, 'solar_noon', utc_point_in_time)
     self.next_rising = get_astral_event_next(
         self.hass, SUN_EVENT_SUNRISE, utc_point_in_time)
     self.next_setting = get_astral_event_next(
         self.hass, SUN_EVENT_SUNSET, utc_point_in_time)
コード例 #22
0
ファイル: sun.py プロジェクト: tmcarr/home-assistant
 def update_as_of(self, utc_point_in_time):
     """Update the attributes containing solar events."""
     self.next_dawn = get_astral_event_next(
         self.hass, 'dawn', utc_point_in_time)
     self.next_dusk = get_astral_event_next(
         self.hass, 'dusk', utc_point_in_time)
     self.next_midnight = get_astral_event_next(
         self.hass, 'solar_midnight', utc_point_in_time)
     self.next_noon = get_astral_event_next(
         self.hass, 'solar_noon', utc_point_in_time)
     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)
コード例 #23
0
    def check_light_on_dev_state_change(entity, old_state, new_state):
        """Handle tracked device state changes."""
        lights_are_on = any_light_on()
        light_needed = not (lights_are_on or is_up(hass))

        # These variables are needed for the elif check
        now = dt_util.utcnow()
        start_point = calc_time_for_light_when_sunset()

        # Do we need lights?
        if light_needed:
            logger.info("Home coming event for %s. Turning lights on", entity)
            hass.async_create_task(
                hass.services.async_call(
                    DOMAIN_LIGHT,
                    SERVICE_TURN_ON,
                    {ATTR_ENTITY_ID: light_ids, ATTR_PROFILE: light_profile},
                )
            )

        # Are we in the time span were we would turn on the lights
        # if someone would be home?
        # Check this by seeing if current time is later then the point
        # in time when we would start putting the lights on.
        elif start_point and start_point < now < get_astral_event_next(
            hass, SUN_EVENT_SUNSET
        ):

            # Check for every light if it would be on if someone was home
            # when the fading in started and turn it on if so
            for index, light_id in enumerate(light_ids):
                if now > start_point + index * LIGHT_TRANSITION_TIME:
                    hass.async_create_task(
                        hass.services.async_call(
                            DOMAIN_LIGHT, SERVICE_TURN_ON, {ATTR_ENTITY_ID: light_id}
                        )
                    )

                else:
                    # If this light didn't happen to be turned on yet so
                    # will all the following then, break.
                    break
コード例 #24
0
def async_track_sunset(hass, action, offset=None):
    """Add a listener that will fire a specified offset from sunset daily."""
    remove = None

    @callback
    def sunset_automation_listener(now):
        """Handle points in time to execute actions."""
        nonlocal remove
        remove = async_track_point_in_utc_time(
            hass, sunset_automation_listener,
            get_astral_event_next(hass, 'sunset', offset=offset))
        hass.async_run_job(action)

    remove = async_track_point_in_utc_time(
        hass, sunset_automation_listener,
        get_astral_event_next(hass, 'sunset', offset=offset))

    def remove_listener():
        """Remove sunset listener."""
        remove()

    return remove_listener
コード例 #25
0
ファイル: event.py プロジェクト: boced66/home-assistant
def async_track_sunset(hass, action, offset=None):
    """Add a listener that will fire a specified offset from sunset daily."""
    remove = None

    @callback
    def sunset_automation_listener(now):
        """Handle points in time to execute actions."""
        nonlocal remove
        remove = async_track_point_in_utc_time(
            hass, sunset_automation_listener, get_astral_event_next(
                hass, SUN_EVENT_SUNSET, offset=offset))
        hass.async_run_job(action)

    remove = async_track_point_in_utc_time(
        hass, sunset_automation_listener, get_astral_event_next(
            hass, SUN_EVENT_SUNSET, offset=offset))

    def remove_listener():
        """Remove sunset listener."""
        remove()

    return remove_listener
コード例 #26
0
ファイル: test_sun.py プロジェクト: ManHammer/home-assistant
    def test_next_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

        mod = -1
        while True:
            next_dawn = (astral.dawn_utc(
                utc_today + timedelta(days=mod), latitude, longitude))
            if next_dawn > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_dusk = (astral.dusk_utc(
                utc_today + timedelta(days=mod), latitude, longitude))
            if next_dusk > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_midnight = (astral.solar_midnight_utc(
                utc_today + timedelta(days=mod), longitude))
            if next_midnight > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_noon = (astral.solar_noon_utc(
                utc_today + timedelta(days=mod), longitude))
            if next_noon > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_rising = (astral.sunrise_utc(
                utc_today + timedelta(days=mod), latitude, longitude))
            if next_rising > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_setting = (astral.sunset_utc(
                utc_today + timedelta(days=mod), latitude, longitude))
            if next_setting > utc_now:
                break
            mod += 1

        with patch('homeassistant.helpers.condition.dt_util.utcnow',
                   return_value=utc_now):
            assert next_dawn == sun.get_astral_event_next(
                self.hass, 'dawn')
            assert next_dusk == sun.get_astral_event_next(
                self.hass, 'dusk')
            assert next_midnight == sun.get_astral_event_next(
                self.hass, 'solar_midnight')
            assert next_noon == sun.get_astral_event_next(
                self.hass, 'solar_noon')
            assert next_rising == sun.get_astral_event_next(
                self.hass, SUN_EVENT_SUNRISE)
            assert next_setting == sun.get_astral_event_next(
                self.hass, SUN_EVENT_SUNSET)
コード例 #27
0
    def test_norwegian_case_summer(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

        test_time = self.hass.config.time_zone.localize(datetime(
            2010, 6, 1)).astimezone(pytz.UTC)

        sunrise = dt_util.as_local(
            get_astral_event_next(self.hass, "sunrise",
                                  dt_util.as_utc(test_time)))
        sunset = dt_util.as_local(
            get_astral_event_next(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 = test_time
        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 + 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

        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
コード例 #28
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
コード例 #29
0
def test_next_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

    mod = -1
    while True:
        next_dawn = astral.dawn_utc(utc_today + timedelta(days=mod), latitude,
                                    longitude)
        if next_dawn > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_dusk = astral.dusk_utc(utc_today + timedelta(days=mod), latitude,
                                    longitude)
        if next_dusk > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_midnight = astral.solar_midnight_utc(
            utc_today + timedelta(days=mod), longitude)
        if next_midnight > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_noon = astral.solar_noon_utc(utc_today + timedelta(days=mod),
                                          longitude)
        if next_noon > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_rising = astral.sunrise_utc(utc_today + timedelta(days=mod),
                                         latitude, longitude)
        if next_rising > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_setting = astral.sunset_utc(utc_today + timedelta(days=mod),
                                         latitude, longitude)
        if next_setting > utc_now:
            break
        mod += 1

    with patch("homeassistant.helpers.condition.dt_util.utcnow",
               return_value=utc_now):
        assert next_dawn == sun.get_astral_event_next(hass, "dawn")
        assert next_dusk == sun.get_astral_event_next(hass, "dusk")
        assert next_midnight == sun.get_astral_event_next(
            hass, "solar_midnight")
        assert next_noon == sun.get_astral_event_next(hass, "solar_noon")
        assert next_rising == sun.get_astral_event_next(
            hass, SUN_EVENT_SUNRISE)
        assert next_setting == sun.get_astral_event_next(
            hass, SUN_EVENT_SUNSET)
コード例 #30
0
    def test_next_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

        mod = -1
        while True:
            next_dawn = (astral.dawn_utc(utc_today + timedelta(days=mod),
                                         latitude, longitude))
            if next_dawn > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_dusk = (astral.dusk_utc(utc_today + timedelta(days=mod),
                                         latitude, longitude))
            if next_dusk > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_midnight = (astral.solar_midnight_utc(
                utc_today + timedelta(days=mod), longitude))
            if next_midnight > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_noon = (astral.solar_noon_utc(utc_today + timedelta(days=mod),
                                               longitude))
            if next_noon > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_rising = (astral.sunrise_utc(utc_today + timedelta(days=mod),
                                              latitude, longitude))
            if next_rising > utc_now:
                break
            mod += 1

        mod = -1
        while True:
            next_setting = (astral.sunset_utc(utc_today + timedelta(days=mod),
                                              latitude, longitude))
            if next_setting > utc_now:
                break
            mod += 1

        with patch('homeassistant.helpers.condition.dt_util.utcnow',
                   return_value=utc_now):
            self.assertEqual(next_dawn,
                             sun.get_astral_event_next(self.hass, 'dawn'))
            self.assertEqual(next_dusk,
                             sun.get_astral_event_next(self.hass, 'dusk'))
            self.assertEqual(
                next_midnight,
                sun.get_astral_event_next(self.hass, 'solar_midnight'))
            self.assertEqual(
                next_noon, sun.get_astral_event_next(self.hass, 'solar_noon'))
            self.assertEqual(next_rising,
                             sun.get_astral_event_next(self.hass, 'sunrise'))
            self.assertEqual(next_setting,
                             sun.get_astral_event_next(self.hass, 'sunset'))
コード例 #31
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
コード例 #32
0
    def test_norwegian_case_winter(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

        test_time = self.hass.config.time_zone.localize(datetime(
            2010, 1, 1)).astimezone(pytz.UTC)
        sunrise = dt_util.as_local(
            get_astral_event_next(self.hass, 'sunrise',
                                  dt_util.as_utc(test_time)))
        sunset = dt_util.as_local(
            get_astral_event_next(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 = test_time
        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 + 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

        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
コード例 #33
0
def async_setup(hass, config):
    """Set up the triggers to control lights based on device presence."""
    logger = logging.getLogger(__name__)
    device_tracker = get_component('device_tracker')
    group = get_component('group')
    light = get_component('light')
    conf = config[DOMAIN]
    disable_turn_off = conf.get(CONF_DISABLE_TURN_OFF)
    light_group = conf.get(CONF_LIGHT_GROUP, light.ENTITY_ID_ALL_LIGHTS)
    light_profile = conf.get(CONF_LIGHT_PROFILE)
    device_group = conf.get(
        CONF_DEVICE_GROUP, device_tracker.ENTITY_ID_ALL_DEVICES)
    device_entity_ids = group.get_entity_ids(
        hass, device_group, device_tracker.DOMAIN)

    if not device_entity_ids:
        logger.error("No devices found to track")
        return False

    # Get the light IDs from the specified group
    light_ids = group.get_entity_ids(hass, light_group, light.DOMAIN)

    if not light_ids:
        logger.error("No lights found to turn on")
        return False

    def calc_time_for_light_when_sunset():
        """Calculate the time when to start fading lights in when sun sets.

        Returns None if no next_setting data available.

        Async friendly.
        """
        next_setting = get_astral_event_next(hass, 'sunset')
        if not next_setting:
            return None
        return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)

    def async_turn_on_before_sunset(light_id):
        """Turn on lights."""
        if not device_tracker.is_on(hass) or light.is_on(hass, light_id):
            return
        light.async_turn_on(hass, light_id,
                            transition=LIGHT_TRANSITION_TIME.seconds,
                            profile=light_profile)

    def async_turn_on_factory(light_id):
        """Generate turn on callbacks as factory."""
        @callback
        def async_turn_on_light(now):
            """Turn on specific light."""
            async_turn_on_before_sunset(light_id)

        return async_turn_on_light

    # Track every time sun rises so we can schedule a time-based
    # pre-sun set event
    @callback
    def schedule_light_turn_on(now):
        """Turn on all the lights at the moment sun sets.

        We will schedule to have each light start after one another
        and slowly transition in.
        """
        start_point = calc_time_for_light_when_sunset()
        if not start_point:
            return

        for index, light_id in enumerate(light_ids):
            async_track_point_in_utc_time(
                hass, async_turn_on_factory(light_id),
                start_point + index * LIGHT_TRANSITION_TIME)

    async_track_point_in_utc_time(hass, schedule_light_turn_on,
                                  get_astral_event_next(hass, 'sunrise'))

    # If the sun is already above horizon schedule the time-based pre-sun set
    # event.
    if is_up(hass):
        schedule_light_turn_on(None)

    @callback
    def check_light_on_dev_state_change(entity, old_state, new_state):
        """Handle tracked device state changes."""
        lights_are_on = group.is_on(hass, light_group)
        light_needed = not (lights_are_on or is_up(hass))

        # These variables are needed for the elif check
        now = dt_util.utcnow()
        start_point = calc_time_for_light_when_sunset()

        # Do we need lights?
        if light_needed:
            logger.info("Home coming event for %s. Turning lights on", entity)
            light.async_turn_on(hass, light_ids, profile=light_profile)

        # Are we in the time span were we would turn on the lights
        # if someone would be home?
        # Check this by seeing if current time is later then the point
        # in time when we would start putting the lights on.
        elif (start_point and
              start_point < now < get_astral_event_next(hass, 'sunset')):

            # Check for every light if it would be on if someone was home
            # when the fading in started and turn it on if so
            for index, light_id in enumerate(light_ids):
                if now > start_point + index * LIGHT_TRANSITION_TIME:
                    light.async_turn_on(hass, light_id)

                else:
                    # If this light didn't happen to be turned on yet so
                    # will all the following then, break.
                    break

    async_track_state_change(
        hass, device_entity_ids, check_light_on_dev_state_change,
        STATE_NOT_HOME, STATE_HOME)

    if disable_turn_off:
        return True

    @callback
    def turn_off_lights_when_all_leave(entity, old_state, new_state):
        """Handle device group state change."""
        if not group.is_on(hass, light_group):
            return

        logger.info(
            "Everyone has left but there are lights on. Turning them off")
        light.async_turn_off(hass, light_ids)

    async_track_state_change(
        hass, device_group, turn_off_lights_when_all_leave,
        STATE_HOME, STATE_NOT_HOME)

    return True
コード例 #34
0
def async_setup(hass, config):
    """Set up the triggers to control lights based on device presence."""
    logger = logging.getLogger(__name__)
    device_tracker = get_component('device_tracker')
    group = get_component('group')
    light = get_component('light')
    conf = config[DOMAIN]
    disable_turn_off = conf.get(CONF_DISABLE_TURN_OFF)
    light_group = conf.get(CONF_LIGHT_GROUP, light.ENTITY_ID_ALL_LIGHTS)
    light_profile = conf.get(CONF_LIGHT_PROFILE)
    device_group = conf.get(CONF_DEVICE_GROUP,
                            device_tracker.ENTITY_ID_ALL_DEVICES)
    device_entity_ids = group.get_entity_ids(hass, device_group,
                                             device_tracker.DOMAIN)

    if not device_entity_ids:
        logger.error("No devices found to track")
        return False

    # Get the light IDs from the specified group
    light_ids = group.get_entity_ids(hass, light_group, light.DOMAIN)

    if not light_ids:
        logger.error("No lights found to turn on")
        return False

    def calc_time_for_light_when_sunset():
        """Calculate the time when to start fading lights in when sun sets.

        Returns None if no next_setting data available.

        Async friendly.
        """
        next_setting = get_astral_event_next(hass, 'sunset')
        if not next_setting:
            return None
        return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)

    def async_turn_on_before_sunset(light_id):
        """Turn on lights."""
        if not device_tracker.is_on(hass) or light.is_on(hass, light_id):
            return
        light.async_turn_on(hass,
                            light_id,
                            transition=LIGHT_TRANSITION_TIME.seconds,
                            profile=light_profile)

    def async_turn_on_factory(light_id):
        """Generate turn on callbacks as factory."""
        @callback
        def async_turn_on_light(now):
            """Turn on specific light."""
            async_turn_on_before_sunset(light_id)

        return async_turn_on_light

    # Track every time sun rises so we can schedule a time-based
    # pre-sun set event
    @callback
    def schedule_light_turn_on(now):
        """Turn on all the lights at the moment sun sets.

        We will schedule to have each light start after one another
        and slowly transition in.
        """
        start_point = calc_time_for_light_when_sunset()
        if not start_point:
            return

        for index, light_id in enumerate(light_ids):
            async_track_point_in_utc_time(
                hass, async_turn_on_factory(light_id),
                start_point + index * LIGHT_TRANSITION_TIME)

    async_track_point_in_utc_time(hass, schedule_light_turn_on,
                                  get_astral_event_next(hass, 'sunrise'))

    # If the sun is already above horizon schedule the time-based pre-sun set
    # event.
    if is_up(hass):
        schedule_light_turn_on(None)

    @callback
    def check_light_on_dev_state_change(entity, old_state, new_state):
        """Handle tracked device state changes."""
        lights_are_on = group.is_on(hass, light_group)
        light_needed = not (lights_are_on or is_up(hass))

        # These variables are needed for the elif check
        now = dt_util.utcnow()
        start_point = calc_time_for_light_when_sunset()

        # Do we need lights?
        if light_needed:
            logger.info("Home coming event for %s. Turning lights on", entity)
            light.async_turn_on(hass, light_ids, profile=light_profile)

        # Are we in the time span were we would turn on the lights
        # if someone would be home?
        # Check this by seeing if current time is later then the point
        # in time when we would start putting the lights on.
        elif (start_point
              and start_point < now < get_astral_event_next(hass, 'sunset')):

            # Check for every light if it would be on if someone was home
            # when the fading in started and turn it on if so
            for index, light_id in enumerate(light_ids):
                if now > start_point + index * LIGHT_TRANSITION_TIME:
                    light.async_turn_on(hass, light_id)

                else:
                    # If this light didn't happen to be turned on yet so
                    # will all the following then, break.
                    break

    async_track_state_change(hass, device_entity_ids,
                             check_light_on_dev_state_change, STATE_NOT_HOME,
                             STATE_HOME)

    if disable_turn_off:
        return True

    @callback
    def turn_off_lights_when_all_leave(entity, old_state, new_state):
        """Handle device group state change."""
        if not group.is_on(hass, light_group):
            return

        logger.info(
            "Everyone has left but there are lights on. Turning them off")
        light.async_turn_off(hass, light_ids)

    async_track_state_change(hass, device_group,
                             turn_off_lights_when_all_leave, STATE_HOME,
                             STATE_NOT_HOME)

    return True
コード例 #35
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
コード例 #36
0
ファイル: __init__.py プロジェクト: dcnielsen90/core
async def async_setup(hass, config):
    """Set up the triggers to control lights based on device presence."""
    logger = logging.getLogger(__name__)
    device_tracker = hass.components.device_tracker
    group = hass.components.group
    light = hass.components.light
    person = hass.components.person
    conf = config[DOMAIN]
    disable_turn_off = conf.get(CONF_DISABLE_TURN_OFF)
    light_group = conf.get(CONF_LIGHT_GROUP)
    light_profile = conf.get(CONF_LIGHT_PROFILE)

    device_group = conf.get(CONF_DEVICE_GROUP)

    if device_group is None:
        device_entity_ids = hass.states.async_entity_ids(device_tracker.DOMAIN)
    else:
        device_entity_ids = group.get_entity_ids(device_group,
                                                 device_tracker.DOMAIN)
        device_entity_ids.extend(
            group.get_entity_ids(device_group, person.DOMAIN))

    if not device_entity_ids:
        logger.error("No devices found to track")
        return False

    # Get the light IDs from the specified group
    if light_group is None:
        light_ids = hass.states.async_entity_ids(light.DOMAIN)
    else:
        light_ids = group.get_entity_ids(light_group, light.DOMAIN)

    if not light_ids:
        logger.error("No lights found to turn on")
        return False

    @callback
    def anyone_home():
        """Test if anyone is home."""
        return any(device_tracker.is_on(dt_id) for dt_id in device_entity_ids)

    @callback
    def any_light_on():
        """Test if any light on."""
        return any(light.is_on(light_id) for light_id in light_ids)

    def calc_time_for_light_when_sunset():
        """Calculate the time when to start fading lights in when sun sets.

        Returns None if no next_setting data available.

        Async friendly.
        """
        next_setting = get_astral_event_next(hass, SUN_EVENT_SUNSET)
        if not next_setting:
            return None
        return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)

    def async_turn_on_before_sunset(light_id):
        """Turn on lights."""
        if not anyone_home() or light.is_on(light_id):
            return
        hass.async_create_task(
            hass.services.async_call(
                DOMAIN_LIGHT,
                SERVICE_TURN_ON,
                {
                    ATTR_ENTITY_ID: light_id,
                    ATTR_TRANSITION: LIGHT_TRANSITION_TIME.seconds,
                    ATTR_PROFILE: light_profile,
                },
            ))

    def async_turn_on_factory(light_id):
        """Generate turn on callbacks as factory."""
        @callback
        def async_turn_on_light(now):
            """Turn on specific light."""
            async_turn_on_before_sunset(light_id)

        return async_turn_on_light

    # Track every time sun rises so we can schedule a time-based
    # pre-sun set event
    @callback
    def schedule_light_turn_on(now):
        """Turn on all the lights at the moment sun sets.

        We will schedule to have each light start after one another
        and slowly transition in.
        """
        start_point = calc_time_for_light_when_sunset()
        if not start_point:
            return

        for index, light_id in enumerate(light_ids):
            async_track_point_in_utc_time(
                hass,
                async_turn_on_factory(light_id),
                start_point + index * LIGHT_TRANSITION_TIME,
            )

    async_track_point_in_utc_time(
        hass, schedule_light_turn_on,
        get_astral_event_next(hass, SUN_EVENT_SUNRISE))

    # If the sun is already above horizon schedule the time-based pre-sun set
    # event.
    if is_up(hass):
        schedule_light_turn_on(None)

    @callback
    def check_light_on_dev_state_change(entity, old_state, new_state):
        """Handle tracked device state changes."""
        lights_are_on = any_light_on()
        light_needed = not (lights_are_on or is_up(hass))

        # These variables are needed for the elif check
        now = dt_util.utcnow()
        start_point = calc_time_for_light_when_sunset()

        # Do we need lights?
        if light_needed:
            logger.info("Home coming event for %s. Turning lights on", entity)
            hass.async_create_task(
                hass.services.async_call(
                    DOMAIN_LIGHT,
                    SERVICE_TURN_ON,
                    {
                        ATTR_ENTITY_ID: light_ids,
                        ATTR_PROFILE: light_profile
                    },
                ))

        # Are we in the time span were we would turn on the lights
        # if someone would be home?
        # Check this by seeing if current time is later then the point
        # in time when we would start putting the lights on.
        elif start_point and start_point < now < get_astral_event_next(
                hass, SUN_EVENT_SUNSET):

            # Check for every light if it would be on if someone was home
            # when the fading in started and turn it on if so
            for index, light_id in enumerate(light_ids):
                if now > start_point + index * LIGHT_TRANSITION_TIME:
                    hass.async_create_task(
                        hass.services.async_call(DOMAIN_LIGHT, SERVICE_TURN_ON,
                                                 {ATTR_ENTITY_ID: light_id}))

                else:
                    # If this light didn't happen to be turned on yet so
                    # will all the following then, break.
                    break

    async_track_state_change(
        hass,
        device_entity_ids,
        check_light_on_dev_state_change,
        STATE_NOT_HOME,
        STATE_HOME,
    )

    if disable_turn_off:
        return True

    @callback
    def turn_off_lights_when_all_leave(entity, old_state, new_state):
        """Handle device group state change."""
        # Make sure there is not someone home
        if anyone_home():
            return

        # Check if any light is on
        if not any_light_on():
            return

        logger.info(
            "Everyone has left but there are lights on. Turning them off")
        hass.async_create_task(
            hass.services.async_call(DOMAIN_LIGHT, SERVICE_TURN_OFF,
                                     {ATTR_ENTITY_ID: light_ids}))

    async_track_state_change(
        hass,
        device_entity_ids,
        turn_off_lights_when_all_leave,
        STATE_HOME,
        STATE_NOT_HOME,
    )

    return True
コード例 #37
0
async def test_norwegian_case_summer(hass):
    """Test location in Norway where the sun doesn't set in summer."""
    hass.config.latitude = 69.6
    hass.config.longitude = 18.8
    hass.config.elevation = 10.0

    test_time = datetime(2010, 6, 1, tzinfo=dt_util.UTC)

    sunrise = dt_util.as_local(
        get_astral_event_next(hass, "sunrise", dt_util.as_utc(test_time)))
    sunset = dt_util.as_local(
        get_astral_event_next(hass, "sunset", dt_util.as_utc(sunrise)))
    config = {
        "binary_sensor": [{
            "platform": "tod",
            "name": "Day",
            "after": "sunrise",
            "before": "sunset",
        }]
    }
    entity_id = "binary_sensor.day"
    testtime = test_time
    with patch(
            "homeassistant.components.tod.binary_sensor.dt_util.utcnow",
            return_value=testtime,
    ):
        await async_setup_component(hass, "binary_sensor", config)
        await hass.async_block_till_done()

        await hass.async_block_till_done()
        state = hass.states.get(entity_id)
        assert state.state == STATE_OFF

    testtime = sunrise + timedelta(seconds=-1)
    with patch(
            "homeassistant.components.tod.binary_sensor.dt_util.utcnow",
            return_value=testtime,
    ):

        hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: testtime})
        await hass.async_block_till_done()

        state = 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,
    ):

        hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: testtime})
        await hass.async_block_till_done()

        state = 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,
    ):

        hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: testtime})
        await hass.async_block_till_done()

        state = hass.states.get(entity_id)
        assert state.state == STATE_ON

    await hass.async_block_till_done()

    testtime = sunset + timedelta(seconds=-1)
    with patch(
            "homeassistant.components.tod.binary_sensor.dt_util.utcnow",
            return_value=testtime,
    ):

        hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: testtime})
        await hass.async_block_till_done()

        state = hass.states.get(entity_id)
        assert state.state == STATE_ON

    await hass.async_block_till_done()

    testtime = sunset
    with patch(
            "homeassistant.components.tod.binary_sensor.dt_util.utcnow",
            return_value=testtime,
    ):

        hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: testtime})
        await hass.async_block_till_done()

        state = hass.states.get(entity_id)
        assert state.state == STATE_OFF

    await hass.async_block_till_done()

    testtime = sunset + timedelta(seconds=1)
    with patch(
            "homeassistant.components.tod.binary_sensor.dt_util.utcnow",
            return_value=testtime,
    ):

        hass.bus.async_fire(ha.EVENT_TIME_CHANGED, {ha.ATTR_NOW: testtime})
        await hass.async_block_till_done()

        state = hass.states.get(entity_id)
        assert state.state == STATE_OFF
コード例 #38
0
    def test_norwegian_case_summer(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

        test_time = self.hass.config.time_zone.localize(
            datetime(2010, 6, 1)).astimezone(pytz.UTC)

        sunrise = dt_util.as_local(get_astral_event_next(
            self.hass, 'sunrise', dt_util.as_utc(test_time)))
        sunset = dt_util.as_local(get_astral_event_next(
            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 = test_time
        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 + 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

        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
コード例 #39
0
def test_next_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
    )

    mod = -1
    while True:
        next_dawn = astral.sun.dawn(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_dawn > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_dusk = astral.sun.dusk(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_dusk > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_midnight = astral.sun.midnight(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_midnight > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_noon = astral.sun.noon(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_noon > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_rising = astral.sun.sunrise(
            location.observer, date=utc_today + timedelta(days=mod)
        )
        if next_rising > utc_now:
            break
        mod += 1

    mod = -1
    while True:
        next_setting = astral.sun.sunset(
            location.observer, utc_today + timedelta(days=mod)
        )
        if next_setting > utc_now:
            break
        mod += 1

    with patch("homeassistant.helpers.condition.dt_util.utcnow", return_value=utc_now):
        assert next_dawn == sun.get_astral_event_next(hass, "dawn")
        assert next_dusk == sun.get_astral_event_next(hass, "dusk")
        assert next_midnight == sun.get_astral_event_next(hass, "midnight")
        assert next_noon == sun.get_astral_event_next(hass, "noon")
        assert next_rising == sun.get_astral_event_next(hass, SUN_EVENT_SUNRISE)
        assert next_setting == sun.get_astral_event_next(hass, SUN_EVENT_SUNSET)