mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Refactor sun component for correctness (#7295)
* Refactor sun component for correctness * Convert datetimes to dates for astral * Fix tests for updated code * Fix times now that calcs are fixed * Move sun functions to helpers * Fix flake on new file * Additional tweaks from review * Update requirements
This commit is contained in:
parent
419d97fc06
commit
40d27cde0e
@ -16,8 +16,6 @@ from homeassistant.const import (
|
||||
from homeassistant.helpers.event import async_track_sunrise, async_track_sunset
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
DEPENDENCIES = ['sun']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
TRIGGER_SCHEMA = vol.Schema({
|
||||
|
@ -14,12 +14,13 @@ from homeassistant.core import callback
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.const import STATE_HOME, STATE_NOT_HOME
|
||||
from homeassistant.helpers.event import (
|
||||
async_track_point_in_time, async_track_state_change)
|
||||
async_track_point_in_utc_time, async_track_state_change)
|
||||
from homeassistant.helpers.sun import is_up, get_astral_event_next
|
||||
from homeassistant.loader import get_component
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
DOMAIN = 'device_sun_light_trigger'
|
||||
DEPENDENCIES = ['light', 'device_tracker', 'group', 'sun']
|
||||
DEPENDENCIES = ['light', 'device_tracker', 'group']
|
||||
|
||||
CONF_DEVICE_GROUP = 'device_group'
|
||||
CONF_DISABLE_TURN_OFF = 'disable_turn_off'
|
||||
@ -50,7 +51,6 @@ def async_setup(hass, config):
|
||||
device_tracker = get_component('device_tracker')
|
||||
group = get_component('group')
|
||||
light = get_component('light')
|
||||
sun = get_component('sun')
|
||||
conf = config[DOMAIN]
|
||||
disable_turn_off = conf.get(CONF_DISABLE_TURN_OFF)
|
||||
light_group = conf.get(CONF_LIGHT_GROUP, light.ENTITY_ID_ALL_LIGHTS)
|
||||
@ -78,7 +78,7 @@ def async_setup(hass, config):
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
next_setting = sun.next_setting(hass)
|
||||
next_setting = get_astral_event_next(hass, 'sunset')
|
||||
if not next_setting:
|
||||
return None
|
||||
return next_setting - LIGHT_TRANSITION_TIME * len(light_ids)
|
||||
@ -103,7 +103,7 @@ def async_setup(hass, config):
|
||||
# Track every time sun rises so we can schedule a time-based
|
||||
# pre-sun set event
|
||||
@callback
|
||||
def schedule_light_turn_on(entity, old_state, new_state):
|
||||
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
|
||||
@ -114,26 +114,26 @@ def async_setup(hass, config):
|
||||
return
|
||||
|
||||
for index, light_id in enumerate(light_ids):
|
||||
async_track_point_in_time(
|
||||
async_track_point_in_utc_time(
|
||||
hass, async_turn_on_factory(light_id),
|
||||
start_point + index * LIGHT_TRANSITION_TIME)
|
||||
|
||||
async_track_state_change(hass, sun.ENTITY_ID, schedule_light_turn_on,
|
||||
sun.STATE_BELOW_HORIZON, sun.STATE_ABOVE_HORIZON)
|
||||
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 sun.is_on(hass):
|
||||
schedule_light_turn_on(None, None, None)
|
||||
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 sun.is_on(hass))
|
||||
light_needed = not (lights_are_on or is_up(hass))
|
||||
|
||||
# These variables are needed for the elif check
|
||||
now = dt_util.now()
|
||||
now = dt_util.utcnow()
|
||||
start_point = calc_time_for_light_when_sunset()
|
||||
|
||||
# Do we need lights?
|
||||
@ -146,7 +146,7 @@ def async_setup(hass, config):
|
||||
# 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 < sun.next_setting(hass)):
|
||||
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
|
||||
|
@ -15,8 +15,6 @@ import homeassistant.util.dt as dt_util
|
||||
from homeassistant.helpers.entity import Entity
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
REQUIREMENTS = ['astral==1.4']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_NAME = 'Moon'
|
||||
|
@ -4,20 +4,18 @@ Support for functionality to keep track of the sun.
|
||||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/sun/
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_ELEVATION
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.event import (
|
||||
track_point_in_utc_time, track_utc_time_change)
|
||||
async_track_point_in_utc_time, async_track_utc_time_change)
|
||||
from homeassistant.helpers.sun import (
|
||||
get_astral_location, get_astral_event_next)
|
||||
from homeassistant.util import dt as dt_util
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import homeassistant.util as util
|
||||
|
||||
REQUIREMENTS = ['astral==1.4']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -37,223 +35,16 @@ STATE_ATTR_NEXT_NOON = 'next_noon'
|
||||
STATE_ATTR_NEXT_RISING = 'next_rising'
|
||||
STATE_ATTR_NEXT_SETTING = 'next_setting'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Optional(CONF_ELEVATION): cv.positive_int,
|
||||
}),
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
|
||||
def is_on(hass, entity_id=None):
|
||||
"""Test if the sun is currently up based on the statemachine."""
|
||||
entity_id = entity_id or ENTITY_ID
|
||||
|
||||
return hass.states.is_state(entity_id, STATE_ABOVE_HORIZON)
|
||||
|
||||
|
||||
def next_dawn(hass, entity_id=None):
|
||||
"""Local datetime object of the next dawn.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
utc_next = next_dawn_utc(hass, entity_id)
|
||||
|
||||
return dt_util.as_local(utc_next) if utc_next else None
|
||||
|
||||
|
||||
def next_dawn_utc(hass, entity_id=None):
|
||||
"""UTC datetime object of the next dawn.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
entity_id = entity_id or ENTITY_ID
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.parse_datetime(
|
||||
state.attributes[STATE_ATTR_NEXT_DAWN])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
# KeyError if STATE_ATTR_NEXT_DAWN does not exist
|
||||
return None
|
||||
|
||||
|
||||
def next_dusk(hass, entity_id=None):
|
||||
"""Local datetime object of the next dusk.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
utc_next = next_dusk_utc(hass, entity_id)
|
||||
|
||||
return dt_util.as_local(utc_next) if utc_next else None
|
||||
|
||||
|
||||
def next_dusk_utc(hass, entity_id=None):
|
||||
"""UTC datetime object of the next dusk.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
entity_id = entity_id or ENTITY_ID
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.parse_datetime(
|
||||
state.attributes[STATE_ATTR_NEXT_DUSK])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
# KeyError if STATE_ATTR_NEXT_DUSK does not exist
|
||||
return None
|
||||
|
||||
|
||||
def next_midnight(hass, entity_id=None):
|
||||
"""Local datetime object of the next midnight.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
utc_next = next_midnight_utc(hass, entity_id)
|
||||
|
||||
return dt_util.as_local(utc_next) if utc_next else None
|
||||
|
||||
|
||||
def next_midnight_utc(hass, entity_id=None):
|
||||
"""UTC datetime object of the next midnight.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
entity_id = entity_id or ENTITY_ID
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.parse_datetime(
|
||||
state.attributes[STATE_ATTR_NEXT_MIDNIGHT])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
# KeyError if STATE_ATTR_NEXT_MIDNIGHT does not exist
|
||||
return None
|
||||
|
||||
|
||||
def next_noon(hass, entity_id=None):
|
||||
"""Local datetime object of the next solar noon.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
utc_next = next_noon_utc(hass, entity_id)
|
||||
|
||||
return dt_util.as_local(utc_next) if utc_next else None
|
||||
|
||||
|
||||
def next_noon_utc(hass, entity_id=None):
|
||||
"""UTC datetime object of the next noon.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
entity_id = entity_id or ENTITY_ID
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.parse_datetime(
|
||||
state.attributes[STATE_ATTR_NEXT_NOON])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
# KeyError if STATE_ATTR_NEXT_NOON does not exist
|
||||
return None
|
||||
|
||||
|
||||
def next_setting(hass, entity_id=None):
|
||||
"""Local datetime object of the next sun setting.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
utc_next = next_setting_utc(hass, entity_id)
|
||||
|
||||
return dt_util.as_local(utc_next) if utc_next else None
|
||||
|
||||
|
||||
def next_setting_utc(hass, entity_id=None):
|
||||
"""UTC datetime object of the next sun setting.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
entity_id = entity_id or ENTITY_ID
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.parse_datetime(
|
||||
state.attributes[STATE_ATTR_NEXT_SETTING])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
# KeyError if STATE_ATTR_NEXT_SETTING does not exist
|
||||
return None
|
||||
|
||||
|
||||
def next_rising(hass, entity_id=None):
|
||||
"""Local datetime object of the next sun rising.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
utc_next = next_rising_utc(hass, entity_id)
|
||||
|
||||
return dt_util.as_local(utc_next) if utc_next else None
|
||||
|
||||
|
||||
def next_rising_utc(hass, entity_id=None):
|
||||
"""UTC datetime object of the next sun rising.
|
||||
|
||||
Async friendly.
|
||||
"""
|
||||
entity_id = entity_id or ENTITY_ID
|
||||
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
|
||||
try:
|
||||
return dt_util.parse_datetime(state.attributes[STATE_ATTR_NEXT_RISING])
|
||||
except (AttributeError, KeyError):
|
||||
# AttributeError if state is None
|
||||
# KeyError if STATE_ATTR_NEXT_RISING does not exist
|
||||
return None
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
@asyncio.coroutine
|
||||
def async_setup(hass, config):
|
||||
"""Track the state of the sun."""
|
||||
if None in (hass.config.latitude, hass.config.longitude):
|
||||
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
|
||||
return False
|
||||
if config.get(CONF_ELEVATION) is not None:
|
||||
_LOGGER.warning(
|
||||
"Elevation is now configured in home assistant core. "
|
||||
"See https://home-assistant.io/docs/configuration/basic/")
|
||||
|
||||
latitude = util.convert(hass.config.latitude, float)
|
||||
longitude = util.convert(hass.config.longitude, float)
|
||||
errors = []
|
||||
|
||||
if latitude is None:
|
||||
errors.append('Latitude needs to be a decimal value')
|
||||
elif -90 > latitude < 90:
|
||||
errors.append('Latitude needs to be -90 .. 90')
|
||||
|
||||
if longitude is None:
|
||||
errors.append('Longitude needs to be a decimal value')
|
||||
elif -180 > longitude < 180:
|
||||
errors.append('Longitude needs to be -180 .. 180')
|
||||
|
||||
if errors:
|
||||
_LOGGER.error('Invalid configuration received: %s', ", ".join(errors))
|
||||
return False
|
||||
|
||||
platform_config = config.get(DOMAIN, {})
|
||||
|
||||
elevation = platform_config.get(CONF_ELEVATION)
|
||||
if elevation is None:
|
||||
elevation = hass.config.elevation or 0
|
||||
|
||||
from astral import Location
|
||||
|
||||
location = Location(('', '', latitude, longitude,
|
||||
hass.config.time_zone.zone, elevation))
|
||||
|
||||
sun = Sun(hass, location)
|
||||
sun = Sun(hass, get_astral_location(hass))
|
||||
sun.point_in_time_listener(dt_util.utcnow())
|
||||
|
||||
return True
|
||||
@ -273,7 +64,7 @@ class Sun(Entity):
|
||||
self.next_midnight = self.next_noon = None
|
||||
self.solar_elevation = self.solar_azimuth = 0
|
||||
|
||||
track_utc_time_change(hass, self.timer_update, second=30)
|
||||
async_track_utc_time_change(hass, self.timer_update, second=30)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@ -308,64 +99,41 @@ class Sun(Entity):
|
||||
return min(self.next_dawn, self.next_dusk, self.next_midnight,
|
||||
self.next_noon, self.next_rising, self.next_setting)
|
||||
|
||||
@staticmethod
|
||||
def get_next_solar_event(callable_on_astral_location,
|
||||
utc_point_in_time, mod, increment):
|
||||
"""Calculate sun state at a point in UTC time."""
|
||||
import astral
|
||||
|
||||
while True:
|
||||
try:
|
||||
next_dt = callable_on_astral_location(
|
||||
utc_point_in_time + timedelta(days=mod), local=False)
|
||||
if next_dt > utc_point_in_time:
|
||||
break
|
||||
except astral.AstralError:
|
||||
pass
|
||||
mod += increment
|
||||
|
||||
return next_dt
|
||||
|
||||
@callback
|
||||
def update_as_of(self, utc_point_in_time):
|
||||
"""Update the attributes containing solar events."""
|
||||
self.next_dawn = Sun.get_next_solar_event(
|
||||
self.location.dawn, utc_point_in_time, -1, 1)
|
||||
self.next_dusk = Sun.get_next_solar_event(
|
||||
self.location.dusk, utc_point_in_time, -1, 1)
|
||||
self.next_midnight = Sun.get_next_solar_event(
|
||||
self.location.solar_midnight, utc_point_in_time, -1, 1)
|
||||
self.next_noon = Sun.get_next_solar_event(
|
||||
self.location.solar_noon, utc_point_in_time, -1, 1)
|
||||
self.next_rising = Sun.get_next_solar_event(
|
||||
self.location.sunrise, utc_point_in_time, -1, 1)
|
||||
self.next_setting = Sun.get_next_solar_event(
|
||||
self.location.sunset, utc_point_in_time, -1, 1)
|
||||
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)
|
||||
|
||||
@callback
|
||||
def update_sun_position(self, utc_point_in_time):
|
||||
"""Calculate the position of the sun."""
|
||||
from astral import Astral
|
||||
|
||||
self.solar_azimuth = Astral().solar_azimuth(
|
||||
utc_point_in_time,
|
||||
self.location.latitude,
|
||||
self.location.longitude)
|
||||
|
||||
self.solar_elevation = Astral().solar_elevation(
|
||||
utc_point_in_time,
|
||||
self.location.latitude,
|
||||
self.location.longitude)
|
||||
self.solar_azimuth = self.location.solar_azimuth(utc_point_in_time)
|
||||
self.solar_elevation = self.location.solar_elevation(utc_point_in_time)
|
||||
|
||||
@callback
|
||||
def point_in_time_listener(self, now):
|
||||
"""Run when the state of the sun has changed."""
|
||||
self.update_as_of(now)
|
||||
self.schedule_update_ha_state()
|
||||
self.hass.async_add_job(self.async_update_ha_state())
|
||||
|
||||
# Schedule next update at next_change+1 second so sun state has changed
|
||||
track_point_in_utc_time(
|
||||
async_track_point_in_utc_time(
|
||||
self.hass, self.point_in_time_listener,
|
||||
self.next_change + timedelta(seconds=1))
|
||||
|
||||
@callback
|
||||
def timer_update(self, time):
|
||||
"""Needed to update solar elevation and azimuth."""
|
||||
self.update_sun_position(time)
|
||||
self.schedule_update_ha_state()
|
||||
self.hass.async_add_job(self.async_update_ha_state())
|
||||
|
@ -11,18 +11,18 @@ import logging
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.light import is_on, turn_on
|
||||
from homeassistant.components.sun import next_setting, next_rising
|
||||
from homeassistant.components.switch import DOMAIN, SwitchDevice
|
||||
from homeassistant.const import CONF_NAME, CONF_PLATFORM
|
||||
from homeassistant.helpers.event import track_time_change
|
||||
from homeassistant.helpers.sun import get_astral_event_date
|
||||
from homeassistant.util.color import (
|
||||
color_temperature_to_rgb, color_RGB_to_xy,
|
||||
color_temperature_kelvin_to_mired)
|
||||
from homeassistant.util.dt import now as dt_now
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
DEPENDENCIES = ['sun', 'light']
|
||||
SUN = "sun.sun"
|
||||
DEPENDENCIES = ['light']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_LIGHTS = 'lights'
|
||||
@ -159,8 +159,7 @@ class FluxSwitch(SwitchDevice):
|
||||
"""Update all the lights using flux."""
|
||||
if now is None:
|
||||
now = dt_now()
|
||||
sunset = next_setting(self.hass, SUN).replace(
|
||||
day=now.day, month=now.month, year=now.year)
|
||||
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,
|
||||
@ -221,6 +220,5 @@ class FluxSwitch(SwitchDevice):
|
||||
hour=self._start_time.hour, minute=self._start_time.minute,
|
||||
second=0)
|
||||
else:
|
||||
sunrise = next_rising(self.hass, SUN).replace(
|
||||
day=now.day, month=now.month, year=now.year)
|
||||
sunrise = get_astral_event_date(self.hass, 'sunrise', now.date())
|
||||
return sunrise
|
||||
|
@ -7,8 +7,7 @@ import sys
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.components import (
|
||||
zone as zone_cmp, sun as sun_cmp)
|
||||
from homeassistant.components import zone as zone_cmp
|
||||
from homeassistant.const import (
|
||||
ATTR_GPS_ACCURACY, ATTR_LATITUDE, ATTR_LONGITUDE,
|
||||
CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, CONF_CONDITION,
|
||||
@ -17,6 +16,7 @@ from homeassistant.const import (
|
||||
CONF_BELOW, CONF_ABOVE)
|
||||
from homeassistant.exceptions import TemplateError, HomeAssistantError
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.sun import get_astral_event_date
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util.async import run_callback_threadsafe
|
||||
|
||||
@ -234,24 +234,34 @@ def state_from_config(config, config_validation=True):
|
||||
|
||||
def sun(hass, before=None, after=None, before_offset=None, after_offset=None):
|
||||
"""Test if current time matches sun requirements."""
|
||||
now = dt_util.now().time()
|
||||
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)
|
||||
|
||||
if before == SUN_EVENT_SUNRISE and now > (sun_cmp.next_rising(hass) +
|
||||
before_offset).time():
|
||||
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
|
||||
|
||||
elif before == SUN_EVENT_SUNSET and now > (sun_cmp.next_setting(hass) +
|
||||
before_offset).time():
|
||||
if sunset is None and (before == SUN_EVENT_SUNSET or
|
||||
after == SUN_EVENT_SUNSET):
|
||||
# There is no sunset today
|
||||
return False
|
||||
|
||||
if after == SUN_EVENT_SUNRISE and now < (sun_cmp.next_rising(hass) +
|
||||
after_offset).time():
|
||||
if before == SUN_EVENT_SUNRISE and utcnow > sunrise + before_offset:
|
||||
return False
|
||||
|
||||
elif after == SUN_EVENT_SUNSET and now < (sun_cmp.next_setting(hass) +
|
||||
after_offset).time():
|
||||
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
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""Helpers for listening to events."""
|
||||
import functools as ft
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.helpers.sun import get_astral_event_next
|
||||
from ..core import HomeAssistant, callback
|
||||
from ..const import (
|
||||
ATTR_NOW, EVENT_STATE_CHANGED, EVENT_TIME_CHANGED, MATCH_ALL)
|
||||
@ -197,29 +197,20 @@ track_time_interval = threaded_listener_factory(async_track_time_interval)
|
||||
@callback
|
||||
def async_track_sunrise(hass, action, offset=None):
|
||||
"""Add a listener that will fire a specified offset from sunrise daily."""
|
||||
from homeassistant.components import sun
|
||||
offset = offset or timedelta()
|
||||
remove = None
|
||||
|
||||
def next_rise():
|
||||
"""Return the next sunrise."""
|
||||
next_time = sun.next_rising_utc(hass) + offset
|
||||
|
||||
while next_time < dt_util.utcnow():
|
||||
next_time = next_time + timedelta(days=1)
|
||||
|
||||
return next_time
|
||||
|
||||
@callback
|
||||
def sunrise_automation_listener(now):
|
||||
"""Handle points in time to execute actions."""
|
||||
nonlocal remove
|
||||
remove = async_track_point_in_utc_time(
|
||||
hass, sunrise_automation_listener, next_rise())
|
||||
hass, sunrise_automation_listener, get_astral_event_next(
|
||||
hass, 'sunrise', offset=offset))
|
||||
hass.async_run_job(action)
|
||||
|
||||
remove = async_track_point_in_utc_time(
|
||||
hass, sunrise_automation_listener, next_rise())
|
||||
hass, sunrise_automation_listener, get_astral_event_next(
|
||||
hass, 'sunrise', offset=offset))
|
||||
|
||||
def remove_listener():
|
||||
"""Remove sunset listener."""
|
||||
@ -234,29 +225,20 @@ track_sunrise = threaded_listener_factory(async_track_sunrise)
|
||||
@callback
|
||||
def async_track_sunset(hass, action, offset=None):
|
||||
"""Add a listener that will fire a specified offset from sunset daily."""
|
||||
from homeassistant.components import sun
|
||||
offset = offset or timedelta()
|
||||
remove = None
|
||||
|
||||
def next_set():
|
||||
"""Return next sunrise."""
|
||||
next_time = sun.next_setting_utc(hass) + offset
|
||||
|
||||
while next_time < dt_util.utcnow():
|
||||
next_time = next_time + timedelta(days=1)
|
||||
|
||||
return next_time
|
||||
|
||||
@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, next_set())
|
||||
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, next_set())
|
||||
hass, sunset_automation_listener, get_astral_event_next(
|
||||
hass, 'sunset', offset=offset))
|
||||
|
||||
def remove_listener():
|
||||
"""Remove sunset listener."""
|
||||
|
87
homeassistant/helpers/sun.py
Normal file
87
homeassistant/helpers/sun.py
Normal file
@ -0,0 +1,87 @@
|
||||
"""Helpers for sun events."""
|
||||
import datetime
|
||||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
DATA_LOCATION_CACHE = 'astral_location_cache'
|
||||
|
||||
|
||||
@callback
|
||||
def get_astral_location(hass):
|
||||
"""Get an astral location for the current hass configuration."""
|
||||
from astral import Location
|
||||
|
||||
latitude = hass.config.latitude
|
||||
longitude = hass.config.longitude
|
||||
timezone = hass.config.time_zone.zone
|
||||
elevation = hass.config.elevation
|
||||
info = ('', '', latitude, longitude, timezone, elevation)
|
||||
|
||||
# Cache astral locations so they aren't recreated with the same args
|
||||
if DATA_LOCATION_CACHE not in hass.data:
|
||||
hass.data[DATA_LOCATION_CACHE] = {}
|
||||
|
||||
if info not in hass.data[DATA_LOCATION_CACHE]:
|
||||
hass.data[DATA_LOCATION_CACHE][info] = Location(info)
|
||||
|
||||
return hass.data[DATA_LOCATION_CACHE][info]
|
||||
|
||||
|
||||
@callback
|
||||
def get_astral_event_next(hass, event, utc_point_in_time=None, offset=None):
|
||||
"""Calculate the next specified solar event."""
|
||||
import astral
|
||||
|
||||
location = get_astral_location(hass)
|
||||
|
||||
if offset is None:
|
||||
offset = datetime.timedelta()
|
||||
|
||||
if utc_point_in_time is None:
|
||||
utc_point_in_time = dt_util.utcnow()
|
||||
|
||||
mod = -1
|
||||
while True:
|
||||
try:
|
||||
next_dt = getattr(location, event)(
|
||||
dt_util.as_local(utc_point_in_time).date() +
|
||||
datetime.timedelta(days=mod),
|
||||
local=False) + offset
|
||||
if next_dt > utc_point_in_time:
|
||||
return next_dt
|
||||
except astral.AstralError:
|
||||
pass
|
||||
mod += 1
|
||||
|
||||
|
||||
@callback
|
||||
def get_astral_event_date(hass, event, date=None):
|
||||
"""Calculate the astral event time for the specified date."""
|
||||
import astral
|
||||
|
||||
location = get_astral_location(hass)
|
||||
|
||||
if date is None:
|
||||
date = dt_util.now().date()
|
||||
|
||||
if isinstance(date, datetime.datetime):
|
||||
date = dt_util.as_local(date).date()
|
||||
|
||||
try:
|
||||
return getattr(location, event)(date, local=False)
|
||||
except astral.AstralError:
|
||||
# Event never occurs for specified date.
|
||||
return None
|
||||
|
||||
|
||||
@callback
|
||||
def is_up(hass, utc_point_in_time=None):
|
||||
"""Calculate if the sun is currently up."""
|
||||
if utc_point_in_time is None:
|
||||
utc_point_in_time = dt_util.utcnow()
|
||||
|
||||
next_sunrise = get_astral_event_next(hass, 'sunrise', utc_point_in_time)
|
||||
next_sunset = get_astral_event_next(hass, 'sunset', utc_point_in_time)
|
||||
|
||||
return next_sunrise > next_sunset
|
@ -8,3 +8,4 @@ typing>=3,<4
|
||||
aiohttp==2.0.7
|
||||
async_timeout==1.2.1
|
||||
chardet==3.0.2
|
||||
astral==1.4
|
||||
|
@ -9,6 +9,7 @@ typing>=3,<4
|
||||
aiohttp==2.0.7
|
||||
async_timeout==1.2.1
|
||||
chardet==3.0.2
|
||||
astral==1.4
|
||||
|
||||
# homeassistant.components.nuimo_controller
|
||||
--only-binary=all https://github.com/getSenic/nuimo-linux-python/archive/29fc42987f74d8090d0e2382e8f248ff5990b8c9.zip#nuimo==1.0.0
|
||||
@ -66,10 +67,6 @@ apcaccess==0.0.4
|
||||
# homeassistant.components.notify.apns
|
||||
apns2==0.1.1
|
||||
|
||||
# homeassistant.components.sun
|
||||
# homeassistant.components.sensor.moon
|
||||
astral==1.4
|
||||
|
||||
# homeassistant.components.light.avion
|
||||
# avion==0.6
|
||||
|
||||
|
@ -37,10 +37,6 @@ aiohttp_cors==0.5.3
|
||||
# homeassistant.components.notify.apns
|
||||
apns2==0.1.1
|
||||
|
||||
# homeassistant.components.sun
|
||||
# homeassistant.components.sensor.moon
|
||||
astral==1.4
|
||||
|
||||
# homeassistant.components.datadog
|
||||
datadog==0.15.0
|
||||
|
||||
|
3
setup.py
3
setup.py
@ -24,7 +24,8 @@ REQUIRES = [
|
||||
'typing>=3,<4',
|
||||
'aiohttp==2.0.7',
|
||||
'async_timeout==1.2.1',
|
||||
'chardet==3.0.2'
|
||||
'chardet==3.0.2',
|
||||
'astral==1.4',
|
||||
]
|
||||
|
||||
setup(
|
||||
|
@ -3,7 +3,6 @@ import asyncio
|
||||
import functools as ft
|
||||
import os
|
||||
import sys
|
||||
from datetime import timedelta
|
||||
from unittest.mock import patch, MagicMock, Mock
|
||||
from io import StringIO
|
||||
import logging
|
||||
@ -25,7 +24,7 @@ from homeassistant.const import (
|
||||
STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME, EVENT_TIME_CHANGED,
|
||||
EVENT_STATE_CHANGED, EVENT_PLATFORM_DISCOVERED, ATTR_SERVICE,
|
||||
ATTR_DISCOVERED, SERVER_PORT, EVENT_HOMEASSISTANT_CLOSE)
|
||||
from homeassistant.components import sun, mqtt, recorder
|
||||
from homeassistant.components import mqtt, recorder
|
||||
from homeassistant.components.http.auth import auth_middleware
|
||||
from homeassistant.components.http.const import (
|
||||
KEY_USE_X_FORWARDED_FOR, KEY_BANS_ENABLED, KEY_TRUSTED_NETWORKS)
|
||||
@ -213,20 +212,6 @@ def fire_service_discovered(hass, service, info):
|
||||
})
|
||||
|
||||
|
||||
def ensure_sun_risen(hass):
|
||||
"""Trigger sun to rise if below horizon."""
|
||||
if sun.is_on(hass):
|
||||
return
|
||||
fire_time_changed(hass, sun.next_rising_utc(hass) + timedelta(seconds=10))
|
||||
|
||||
|
||||
def ensure_sun_set(hass):
|
||||
"""Trigger sun to set if above horizon."""
|
||||
if not sun.is_on(hass):
|
||||
return
|
||||
fire_time_changed(hass, sun.next_setting_utc(hass) + timedelta(seconds=10))
|
||||
|
||||
|
||||
def load_fixture(filename):
|
||||
"""Load a fixture."""
|
||||
path = os.path.join(os.path.dirname(__file__), 'fixtures', filename)
|
||||
|
@ -22,7 +22,8 @@ class TestAutomationSun(unittest.TestCase):
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
mock_component(self.hass, 'group')
|
||||
mock_component(self.hass, 'sun')
|
||||
setup_component(self.hass, sun.DOMAIN, {
|
||||
sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
|
||||
|
||||
self.calls = []
|
||||
|
||||
@ -39,10 +40,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_sunset_trigger(self):
|
||||
"""Test the sunset trigger."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T02:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC)
|
||||
trigger_time = datetime(2015, 9, 16, 2, tzinfo=dt_util.UTC)
|
||||
|
||||
@ -78,10 +75,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_sunrise_trigger(self):
|
||||
"""Test the sunrise trigger."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 13, 23, tzinfo=dt_util.UTC)
|
||||
trigger_time = datetime(2015, 9, 16, 14, tzinfo=dt_util.UTC)
|
||||
|
||||
@ -105,10 +98,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_sunset_trigger_with_offset(self):
|
||||
"""Test the sunset trigger with offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T02:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 15, 23, tzinfo=dt_util.UTC)
|
||||
trigger_time = datetime(2015, 9, 16, 2, 30, tzinfo=dt_util.UTC)
|
||||
|
||||
@ -139,10 +128,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_sunrise_trigger_with_offset(self):
|
||||
"""Test the runrise trigger with offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 13, 23, tzinfo=dt_util.UTC)
|
||||
trigger_time = datetime(2015, 9, 16, 13, 30, tzinfo=dt_util.UTC)
|
||||
|
||||
@ -167,10 +152,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_if_action_before(self):
|
||||
"""Test if action was before."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
setup_component(self.hass, automation.DOMAIN, {
|
||||
automation.DOMAIN: {
|
||||
'trigger': {
|
||||
@ -188,14 +169,14 @@ class TestAutomationSun(unittest.TestCase):
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 16, 15, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(self.calls))
|
||||
|
||||
now = datetime(2015, 9, 16, 10, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
@ -203,10 +184,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_if_action_after(self):
|
||||
"""Test if action was after."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
setup_component(self.hass, automation.DOMAIN, {
|
||||
automation.DOMAIN: {
|
||||
'trigger': {
|
||||
@ -224,14 +201,14 @@ class TestAutomationSun(unittest.TestCase):
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 16, 13, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(self.calls))
|
||||
|
||||
now = datetime(2015, 9, 16, 15, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
@ -239,10 +216,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_if_action_before_with_offset(self):
|
||||
"""Test if action was before offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
setup_component(self.hass, automation.DOMAIN, {
|
||||
automation.DOMAIN: {
|
||||
'trigger': {
|
||||
@ -260,15 +233,15 @@ class TestAutomationSun(unittest.TestCase):
|
||||
}
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 16, 15, 1, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
now = datetime(2015, 9, 16, 14, 32, 44, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(self.calls))
|
||||
|
||||
now = datetime(2015, 9, 16, 15, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
now = datetime(2015, 9, 16, 14, 32, 43, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
@ -276,10 +249,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_if_action_after_with_offset(self):
|
||||
"""Test if action was after offset."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T14:00:00Z',
|
||||
})
|
||||
|
||||
setup_component(self.hass, automation.DOMAIN, {
|
||||
automation.DOMAIN: {
|
||||
'trigger': {
|
||||
@ -297,15 +266,15 @@ class TestAutomationSun(unittest.TestCase):
|
||||
}
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 16, 14, 59, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
now = datetime(2015, 9, 16, 14, 32, 42, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(self.calls))
|
||||
|
||||
now = datetime(2015, 9, 16, 15, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
now = datetime(2015, 9, 16, 14, 32, 43, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
@ -313,11 +282,6 @@ class TestAutomationSun(unittest.TestCase):
|
||||
|
||||
def test_if_action_before_and_after_during(self):
|
||||
"""Test if action was before and after during."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_RISING: '2015-09-16T10:00:00Z',
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T15:00:00Z',
|
||||
})
|
||||
|
||||
setup_component(self.hass, automation.DOMAIN, {
|
||||
automation.DOMAIN: {
|
||||
'trigger': {
|
||||
@ -335,62 +299,22 @@ class TestAutomationSun(unittest.TestCase):
|
||||
}
|
||||
})
|
||||
|
||||
now = datetime(2015, 9, 16, 9, 59, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
now = datetime(2015, 9, 16, 13, 8, 51, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(self.calls))
|
||||
|
||||
now = datetime(2015, 9, 16, 15, 1, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
now = datetime(2015, 9, 17, 2, 25, 18, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(self.calls))
|
||||
|
||||
now = datetime(2015, 9, 16, 12, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.now',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(1, len(self.calls))
|
||||
|
||||
def test_if_action_after_different_tz(self):
|
||||
"""Test if action was after in a different timezone."""
|
||||
import pytz
|
||||
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON, {
|
||||
sun.STATE_ATTR_NEXT_SETTING: '2015-09-16T17:30:00Z',
|
||||
})
|
||||
|
||||
setup_component(self.hass, automation.DOMAIN, {
|
||||
automation.DOMAIN: {
|
||||
'trigger': {
|
||||
'platform': 'event',
|
||||
'event_type': 'test_event',
|
||||
},
|
||||
'condition': {
|
||||
'condition': 'sun',
|
||||
'after': 'sunset',
|
||||
},
|
||||
'action': {
|
||||
'service': 'test.automation'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# Before
|
||||
now = datetime(2015, 9, 16, 17, tzinfo=pytz.timezone('US/Mountain'))
|
||||
with patch('homeassistant.util.dt.now',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(self.calls))
|
||||
|
||||
# After
|
||||
now = datetime(2015, 9, 16, 18, tzinfo=pytz.timezone('US/Mountain'))
|
||||
with patch('homeassistant.util.dt.now',
|
||||
now = datetime(2015, 9, 16, 16, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow',
|
||||
return_value=now):
|
||||
self.hass.bus.fire('test_event')
|
||||
self.hass.block_till_done()
|
||||
|
@ -1,5 +1,4 @@
|
||||
"""The tests for the Flux switch platform."""
|
||||
from datetime import timedelta
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
@ -86,28 +85,30 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
self.assertIsNone(state.attributes.get('xy_color'))
|
||||
self.assertIsNone(state.attributes.get('brightness'))
|
||||
|
||||
test_time = dt_util.now().replace(hour=10, minute=30,
|
||||
second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0,
|
||||
second=0)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
test_time = dt_util.now().replace(hour=10, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(0, len(turn_on_calls))
|
||||
|
||||
def test_flux_before_sunrise(self):
|
||||
@ -126,30 +127,32 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
self.assertIsNone(state.attributes.get('xy_color'))
|
||||
self.assertIsNone(state.attributes.get('brightness'))
|
||||
|
||||
test_time = dt_util.now().replace(hour=2, minute=30,
|
||||
second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0,
|
||||
second=0)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
test_time = dt_util.now().replace(hour=2, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 119)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.591, 0.395])
|
||||
@ -173,28 +176,30 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=8, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 180)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.431, 0.38])
|
||||
@ -218,28 +223,30 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=17, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 153)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.496, 0.397])
|
||||
@ -263,28 +270,30 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=23, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 119)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.591, 0.395])
|
||||
@ -308,30 +317,32 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=17, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'start_time': '6:00',
|
||||
'stop_time': '23:30'
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'start_time': '6:00',
|
||||
'stop_time': '23:30'
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 154)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.494, 0.397])
|
||||
@ -355,30 +366,32 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=17, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'start_colortemp': '1000',
|
||||
'stop_colortemp': '6000'
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'start_colortemp': '1000',
|
||||
'stop_colortemp': '6000'
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 167)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.461, 0.389])
|
||||
@ -402,29 +415,31 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=17, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'brightness': 255
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'brightness': 255
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 255)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.496, 0.397])
|
||||
@ -460,30 +475,34 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=12, minute=0, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
print('sunrise {}'.format(sunrise_time))
|
||||
return sunrise_time
|
||||
else:
|
||||
print('sunset {}'.format(sunset_time))
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id,
|
||||
dev2.entity_id,
|
||||
dev3.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id,
|
||||
dev2.entity_id,
|
||||
dev3.entity_id]
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_BRIGHTNESS], 171)
|
||||
self.assertEqual(call.data[light.ATTR_XY_COLOR], [0.452, 0.386])
|
||||
@ -511,28 +530,30 @@ class TestSwitchFlux(unittest.TestCase):
|
||||
|
||||
test_time = dt_util.now().replace(hour=8, minute=30, second=0)
|
||||
sunset_time = test_time.replace(hour=17, minute=0, second=0)
|
||||
sunrise_time = test_time.replace(hour=5,
|
||||
minute=0,
|
||||
second=0) + timedelta(days=1)
|
||||
sunrise_time = test_time.replace(hour=5, minute=0, second=0)
|
||||
|
||||
def event_date(hass, event, now=None):
|
||||
if event == 'sunrise':
|
||||
return sunrise_time
|
||||
else:
|
||||
return sunset_time
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=test_time):
|
||||
with patch('homeassistant.components.sun.next_rising',
|
||||
return_value=sunrise_time):
|
||||
with patch('homeassistant.components.sun.next_setting',
|
||||
return_value=sunset_time):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'mode': 'mired'
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
with patch('homeassistant.helpers.sun.get_astral_event_date',
|
||||
side_effect=event_date):
|
||||
assert setup_component(self.hass, switch.DOMAIN, {
|
||||
switch.DOMAIN: {
|
||||
'platform': 'flux',
|
||||
'name': 'flux',
|
||||
'lights': [dev1.entity_id],
|
||||
'mode': 'mired'
|
||||
}
|
||||
})
|
||||
turn_on_calls = mock_service(
|
||||
self.hass, light.DOMAIN, SERVICE_TURN_ON)
|
||||
switch.turn_on(self.hass, 'switch.flux')
|
||||
self.hass.block_till_done()
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
call = turn_on_calls[-1]
|
||||
self.assertEqual(call.data[light.ATTR_COLOR_TEMP], 269)
|
||||
|
@ -1,17 +1,19 @@
|
||||
"""The tests device sun light trigger component."""
|
||||
# pylint: disable=protected-access
|
||||
from datetime import datetime
|
||||
import os
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.setup import setup_component
|
||||
import homeassistant.loader as loader
|
||||
from homeassistant.const import CONF_PLATFORM, STATE_HOME, STATE_NOT_HOME
|
||||
from homeassistant.components import (
|
||||
device_tracker, light, sun, device_sun_light_trigger)
|
||||
device_tracker, light, device_sun_light_trigger)
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from tests.common import (
|
||||
get_test_config_dir, get_test_home_assistant, ensure_sun_risen,
|
||||
ensure_sun_set)
|
||||
get_test_config_dir, get_test_home_assistant, fire_time_changed)
|
||||
|
||||
|
||||
KNOWN_DEV_YAML_PATH = os.path.join(get_test_config_dir(),
|
||||
@ -61,26 +63,26 @@ class TestDeviceSunLightTrigger(unittest.TestCase):
|
||||
light.DOMAIN: {CONF_PLATFORM: 'test'}
|
||||
}))
|
||||
|
||||
self.assertTrue(setup_component(self.hass, sun.DOMAIN, {
|
||||
sun.DOMAIN: {sun.CONF_ELEVATION: 0}}))
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_lights_on_when_sun_sets(self):
|
||||
"""Test lights go on when there is someone home and the sun sets."""
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, device_sun_light_trigger.DOMAIN, {
|
||||
device_sun_light_trigger.DOMAIN: {}}))
|
||||
test_time = datetime(2017, 4, 5, 1, 2, 3, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow', return_value=test_time):
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, device_sun_light_trigger.DOMAIN, {
|
||||
device_sun_light_trigger.DOMAIN: {}}))
|
||||
|
||||
ensure_sun_risen(self.hass)
|
||||
light.turn_off(self.hass)
|
||||
|
||||
self.hass.block_till_done()
|
||||
|
||||
ensure_sun_set(self.hass)
|
||||
self.hass.block_till_done()
|
||||
test_time = test_time.replace(hour=3)
|
||||
with patch('homeassistant.util.dt.utcnow', return_value=test_time):
|
||||
fire_time_changed(self.hass, test_time)
|
||||
self.hass.block_till_done()
|
||||
|
||||
self.assertTrue(light.is_on(self.hass))
|
||||
|
||||
@ -105,17 +107,17 @@ class TestDeviceSunLightTrigger(unittest.TestCase):
|
||||
def test_lights_turn_on_when_coming_home_after_sun_set(self): \
|
||||
# pylint: disable=invalid-name
|
||||
"""Test lights turn on when coming home after sun set."""
|
||||
light.turn_off(self.hass)
|
||||
ensure_sun_set(self.hass)
|
||||
test_time = datetime(2017, 4, 5, 3, 2, 3, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.util.dt.utcnow', return_value=test_time):
|
||||
light.turn_off(self.hass)
|
||||
self.hass.block_till_done()
|
||||
|
||||
self.hass.block_till_done()
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, device_sun_light_trigger.DOMAIN, {
|
||||
device_sun_light_trigger.DOMAIN: {}}))
|
||||
|
||||
self.assertTrue(setup_component(
|
||||
self.hass, device_sun_light_trigger.DOMAIN, {
|
||||
device_sun_light_trigger.DOMAIN: {}}))
|
||||
self.hass.states.set(
|
||||
device_tracker.ENTITY_ID_FORMAT.format('device_2'), STATE_HOME)
|
||||
|
||||
self.hass.states.set(
|
||||
device_tracker.ENTITY_ID_FORMAT.format('device_2'), STATE_HOME)
|
||||
|
||||
self.hass.block_till_done()
|
||||
self.hass.block_till_done()
|
||||
self.assertTrue(light.is_on(self.hass))
|
||||
|
@ -24,118 +24,111 @@ class TestSun(unittest.TestCase):
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
def test_is_on(self):
|
||||
"""Test is_on method."""
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON)
|
||||
self.assertTrue(sun.is_on(self.hass))
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_BELOW_HORIZON)
|
||||
self.assertFalse(sun.is_on(self.hass))
|
||||
|
||||
def test_setting_rising(self):
|
||||
"""Test retrieving sun setting and rising."""
|
||||
setup_component(self.hass, sun.DOMAIN, {
|
||||
sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
|
||||
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.helpers.condition.dt_util.utcnow',
|
||||
return_value=utc_now):
|
||||
setup_component(self.hass, sun.DOMAIN, {
|
||||
sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
|
||||
|
||||
self.hass.block_till_done()
|
||||
state = self.hass.states.get(sun.ENTITY_ID)
|
||||
|
||||
from astral import Astral
|
||||
|
||||
astral = Astral()
|
||||
utc_now = dt_util.utcnow()
|
||||
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_now +
|
||||
timedelta(days=mod), latitude, longitude))
|
||||
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_now +
|
||||
timedelta(days=mod), latitude, longitude))
|
||||
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_now +
|
||||
timedelta(days=mod), longitude))
|
||||
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_now +
|
||||
timedelta(days=mod), longitude))
|
||||
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_now +
|
||||
timedelta(days=mod), latitude, longitude))
|
||||
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_now +
|
||||
timedelta(days=mod), latitude, longitude))
|
||||
next_setting = (astral.sunset_utc(
|
||||
utc_today + timedelta(days=mod), latitude, longitude))
|
||||
if next_setting > utc_now:
|
||||
break
|
||||
mod += 1
|
||||
|
||||
self.assertEqual(next_dawn, sun.next_dawn_utc(self.hass))
|
||||
self.assertEqual(next_dusk, sun.next_dusk_utc(self.hass))
|
||||
self.assertEqual(next_midnight, sun.next_midnight_utc(self.hass))
|
||||
self.assertEqual(next_noon, sun.next_noon_utc(self.hass))
|
||||
self.assertEqual(next_rising, sun.next_rising_utc(self.hass))
|
||||
self.assertEqual(next_setting, sun.next_setting_utc(self.hass))
|
||||
|
||||
# Point it at a state without the proper attributes
|
||||
self.hass.states.set(sun.ENTITY_ID, sun.STATE_ABOVE_HORIZON)
|
||||
self.assertIsNone(sun.next_dawn(self.hass))
|
||||
self.assertIsNone(sun.next_dusk(self.hass))
|
||||
self.assertIsNone(sun.next_midnight(self.hass))
|
||||
self.assertIsNone(sun.next_noon(self.hass))
|
||||
self.assertIsNone(sun.next_rising(self.hass))
|
||||
self.assertIsNone(sun.next_setting(self.hass))
|
||||
|
||||
# Point it at a non-existing state
|
||||
self.assertIsNone(sun.next_dawn(self.hass, 'non.existing'))
|
||||
self.assertIsNone(sun.next_dusk(self.hass, 'non.existing'))
|
||||
self.assertIsNone(sun.next_midnight(self.hass, 'non.existing'))
|
||||
self.assertIsNone(sun.next_noon(self.hass, 'non.existing'))
|
||||
self.assertIsNone(sun.next_rising(self.hass, 'non.existing'))
|
||||
self.assertIsNone(sun.next_setting(self.hass, 'non.existing'))
|
||||
self.assertEqual(next_dawn, dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_DAWN]))
|
||||
self.assertEqual(next_dusk, dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_DUSK]))
|
||||
self.assertEqual(next_midnight, dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_MIDNIGHT]))
|
||||
self.assertEqual(next_noon, dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_NOON]))
|
||||
self.assertEqual(next_rising, dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_RISING]))
|
||||
self.assertEqual(next_setting, dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_SETTING]))
|
||||
|
||||
def test_state_change(self):
|
||||
"""Test if the state changes at next setting/rising."""
|
||||
setup_component(self.hass, sun.DOMAIN, {
|
||||
sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
|
||||
now = datetime(2016, 6, 1, 8, 0, 0, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.helpers.condition.dt_util.utcnow',
|
||||
return_value=now):
|
||||
setup_component(self.hass, sun.DOMAIN, {
|
||||
sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
|
||||
|
||||
if sun.is_on(self.hass):
|
||||
test_state = sun.STATE_BELOW_HORIZON
|
||||
test_time = sun.next_setting(self.hass)
|
||||
else:
|
||||
test_state = sun.STATE_ABOVE_HORIZON
|
||||
test_time = sun.next_rising(self.hass)
|
||||
self.hass.block_till_done()
|
||||
|
||||
test_time = dt_util.parse_datetime(
|
||||
self.hass.states.get(sun.ENTITY_ID)
|
||||
.attributes[sun.STATE_ATTR_NEXT_RISING])
|
||||
self.assertIsNotNone(test_time)
|
||||
|
||||
self.assertEqual(sun.STATE_BELOW_HORIZON,
|
||||
self.hass.states.get(sun.ENTITY_ID).state)
|
||||
|
||||
self.hass.bus.fire(ha.EVENT_TIME_CHANGED,
|
||||
{ha.ATTR_NOW: test_time + timedelta(seconds=5)})
|
||||
|
||||
self.hass.block_till_done()
|
||||
|
||||
self.assertEqual(test_state, self.hass.states.get(sun.ENTITY_ID).state)
|
||||
self.assertEqual(sun.STATE_ABOVE_HORIZON,
|
||||
self.hass.states.get(sun.ENTITY_ID).state)
|
||||
|
||||
def test_norway_in_june(self):
|
||||
"""Test location in Norway where the sun doesn't set in summer."""
|
||||
@ -150,9 +143,11 @@ class TestSun(unittest.TestCase):
|
||||
sun.DOMAIN: {sun.CONF_ELEVATION: 0}})
|
||||
|
||||
state = self.hass.states.get(sun.ENTITY_ID)
|
||||
|
||||
assert state is not None
|
||||
assert sun.next_rising_utc(self.hass) == \
|
||||
|
||||
assert dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_RISING]) == \
|
||||
datetime(2016, 7, 25, 23, 23, 39, tzinfo=dt_util.UTC)
|
||||
assert sun.next_setting_utc(self.hass) == \
|
||||
assert dt_util.parse_datetime(
|
||||
state.attributes[sun.STATE_ATTR_NEXT_SETTING]) == \
|
||||
datetime(2016, 7, 26, 22, 19, 1, tzinfo=dt_util.UTC)
|
||||
|
@ -25,6 +25,7 @@ from homeassistant.components import sun
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
class TestEventHelpers(unittest.TestCase):
|
||||
@ -302,24 +303,27 @@ class TestEventHelpers(unittest.TestCase):
|
||||
|
||||
# Get next sunrise/sunset
|
||||
astral = Astral()
|
||||
utc_now = dt_util.utcnow()
|
||||
utc_now = datetime(2014, 5, 24, 12, 0, 0, tzinfo=dt_util.UTC)
|
||||
utc_today = utc_now.date()
|
||||
|
||||
mod = -1
|
||||
while True:
|
||||
next_rising = (astral.sunrise_utc(utc_now +
|
||||
timedelta(days=mod), latitude, longitude))
|
||||
next_rising = (astral.sunrise_utc(
|
||||
utc_today + timedelta(days=mod), latitude, longitude))
|
||||
if next_rising > utc_now:
|
||||
break
|
||||
mod += 1
|
||||
|
||||
# Track sunrise
|
||||
runs = []
|
||||
unsub = track_sunrise(self.hass, lambda: runs.append(1))
|
||||
with patch('homeassistant.util.dt.utcnow', return_value=utc_now):
|
||||
unsub = track_sunrise(self.hass, lambda: runs.append(1))
|
||||
|
||||
offset_runs = []
|
||||
offset = timedelta(minutes=30)
|
||||
unsub2 = track_sunrise(self.hass, lambda: offset_runs.append(1),
|
||||
offset)
|
||||
with patch('homeassistant.util.dt.utcnow', return_value=utc_now):
|
||||
unsub2 = track_sunrise(self.hass, lambda: offset_runs.append(1),
|
||||
offset)
|
||||
|
||||
# run tests
|
||||
self._send_time_changed(next_rising - offset)
|
||||
@ -334,7 +338,7 @@ class TestEventHelpers(unittest.TestCase):
|
||||
|
||||
self._send_time_changed(next_rising + offset)
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(2, len(runs))
|
||||
self.assertEqual(1, len(runs))
|
||||
self.assertEqual(1, len(offset_runs))
|
||||
|
||||
unsub()
|
||||
@ -342,7 +346,7 @@ class TestEventHelpers(unittest.TestCase):
|
||||
|
||||
self._send_time_changed(next_rising + offset)
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(2, len(runs))
|
||||
self.assertEqual(1, len(runs))
|
||||
self.assertEqual(1, len(offset_runs))
|
||||
|
||||
def test_track_sunset(self):
|
||||
@ -358,23 +362,27 @@ class TestEventHelpers(unittest.TestCase):
|
||||
|
||||
# Get next sunrise/sunset
|
||||
astral = Astral()
|
||||
utc_now = dt_util.utcnow()
|
||||
utc_now = datetime(2014, 5, 24, 12, 0, 0, tzinfo=dt_util.UTC)
|
||||
utc_today = utc_now.date()
|
||||
|
||||
mod = -1
|
||||
while True:
|
||||
next_setting = (astral.sunset_utc(utc_now +
|
||||
timedelta(days=mod), latitude, longitude))
|
||||
next_setting = (astral.sunset_utc(
|
||||
utc_today + timedelta(days=mod), latitude, longitude))
|
||||
if next_setting > utc_now:
|
||||
break
|
||||
mod += 1
|
||||
|
||||
# Track sunset
|
||||
runs = []
|
||||
unsub = track_sunset(self.hass, lambda: runs.append(1))
|
||||
with patch('homeassistant.util.dt.utcnow', return_value=utc_now):
|
||||
unsub = track_sunset(self.hass, lambda: runs.append(1))
|
||||
|
||||
offset_runs = []
|
||||
offset = timedelta(minutes=30)
|
||||
unsub2 = track_sunset(self.hass, lambda: offset_runs.append(1), offset)
|
||||
with patch('homeassistant.util.dt.utcnow', return_value=utc_now):
|
||||
unsub2 = track_sunset(
|
||||
self.hass, lambda: offset_runs.append(1), offset)
|
||||
|
||||
# Run tests
|
||||
self._send_time_changed(next_setting - offset)
|
||||
@ -389,7 +397,7 @@ class TestEventHelpers(unittest.TestCase):
|
||||
|
||||
self._send_time_changed(next_setting + offset)
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(2, len(runs))
|
||||
self.assertEqual(1, len(runs))
|
||||
self.assertEqual(1, len(offset_runs))
|
||||
|
||||
unsub()
|
||||
@ -397,7 +405,7 @@ class TestEventHelpers(unittest.TestCase):
|
||||
|
||||
self._send_time_changed(next_setting + offset)
|
||||
self.hass.block_till_done()
|
||||
self.assertEqual(2, len(runs))
|
||||
self.assertEqual(1, len(runs))
|
||||
self.assertEqual(1, len(offset_runs))
|
||||
|
||||
def _send_time_changed(self, now):
|
||||
|
227
tests/helpers/test_sun.py
Normal file
227
tests/helpers/test_sun.py
Normal file
@ -0,0 +1,227 @@
|
||||
"""The tests for the Sun helpers."""
|
||||
# pylint: disable=protected-access
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from datetime import timedelta, datetime
|
||||
|
||||
import homeassistant.util.dt as dt_util
|
||||
import homeassistant.helpers.sun as sun
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
class TestSun(unittest.TestCase):
|
||||
"""Test the sun helpers."""
|
||||
|
||||
def setUp(self):
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
|
||||
def tearDown(self):
|
||||
"""Stop everything that was started."""
|
||||
self.hass.stop()
|
||||
|
||||
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'))
|
||||
|
||||
def test_date_events(self):
|
||||
"""Test retrieving next sun events."""
|
||||
utc_now = datetime(2016, 11, 1, 8, 0, 0, tzinfo=dt_util.UTC)
|
||||
from astral import Astral
|
||||
|
||||
astral = Astral()
|
||||
utc_today = utc_now.date()
|
||||
|
||||
latitude = self.hass.config.latitude
|
||||
longitude = self.hass.config.longitude
|
||||
|
||||
dawn = astral.dawn_utc(utc_today, latitude, longitude)
|
||||
dusk = astral.dusk_utc(utc_today, latitude, longitude)
|
||||
midnight = astral.solar_midnight_utc(utc_today, longitude)
|
||||
noon = astral.solar_noon_utc(utc_today, longitude)
|
||||
sunrise = astral.sunrise_utc(utc_today, latitude, longitude)
|
||||
sunset = astral.sunset_utc(utc_today, latitude, longitude)
|
||||
|
||||
self.assertEqual(dawn, sun.get_astral_event_date(
|
||||
self.hass, 'dawn', utc_today))
|
||||
self.assertEqual(dusk, sun.get_astral_event_date(
|
||||
self.hass, 'dusk', utc_today))
|
||||
self.assertEqual(midnight, sun.get_astral_event_date(
|
||||
self.hass, 'solar_midnight', utc_today))
|
||||
self.assertEqual(noon, sun.get_astral_event_date(
|
||||
self.hass, 'solar_noon', utc_today))
|
||||
self.assertEqual(sunrise, sun.get_astral_event_date(
|
||||
self.hass, 'sunrise', utc_today))
|
||||
self.assertEqual(sunset, sun.get_astral_event_date(
|
||||
self.hass, 'sunset', utc_today))
|
||||
|
||||
def test_date_events_default_date(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)
|
||||
|
||||
with patch('homeassistant.util.dt.now', return_value=utc_now):
|
||||
self.assertEqual(dawn, sun.get_astral_event_date(
|
||||
self.hass, 'dawn', utc_today))
|
||||
self.assertEqual(dusk, sun.get_astral_event_date(
|
||||
self.hass, 'dusk', utc_today))
|
||||
self.assertEqual(midnight, sun.get_astral_event_date(
|
||||
self.hass, 'solar_midnight', utc_today))
|
||||
self.assertEqual(noon, sun.get_astral_event_date(
|
||||
self.hass, 'solar_noon', utc_today))
|
||||
self.assertEqual(sunrise, sun.get_astral_event_date(
|
||||
self.hass, 'sunrise', utc_today))
|
||||
self.assertEqual(sunset, sun.get_astral_event_date(
|
||||
self.hass, 'sunset', utc_today))
|
||||
|
||||
def test_date_events_accepts_datetime(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_now))
|
||||
self.assertEqual(dusk, sun.get_astral_event_date(
|
||||
self.hass, 'dusk', utc_now))
|
||||
self.assertEqual(midnight, sun.get_astral_event_date(
|
||||
self.hass, 'solar_midnight', utc_now))
|
||||
self.assertEqual(noon, sun.get_astral_event_date(
|
||||
self.hass, 'solar_noon', utc_now))
|
||||
self.assertEqual(sunrise, sun.get_astral_event_date(
|
||||
self.hass, 'sunrise', utc_now))
|
||||
self.assertEqual(sunset, sun.get_astral_event_date(
|
||||
self.hass, 'sunset', utc_now))
|
||||
|
||||
def test_is_up(self):
|
||||
"""Test retrieving next sun events."""
|
||||
utc_now = datetime(2016, 11, 1, 12, 0, 0, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.helpers.condition.dt_util.utcnow',
|
||||
return_value=utc_now):
|
||||
self.assertFalse(sun.is_up(self.hass))
|
||||
|
||||
utc_now = datetime(2016, 11, 1, 18, 0, 0, tzinfo=dt_util.UTC)
|
||||
with patch('homeassistant.helpers.condition.dt_util.utcnow',
|
||||
return_value=utc_now):
|
||||
self.assertTrue(sun.is_up(self.hass))
|
||||
|
||||
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
|
Loading…
x
Reference in New Issue
Block a user