parent
0687a457b1
commit
3e0eb8763f
homeassistant/components/sensor
script
tests/components/sensor
|
@ -0,0 +1,122 @@
|
|||
"""
|
||||
Support for tracking which astronomical or meteorological season it is.
|
||||
|
||||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/components/sensor/season/
|
||||
"""
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||
from homeassistant.const import CONF_TYPE
|
||||
from homeassistant.helpers.entity import Entity
|
||||
import homeassistant.util as util
|
||||
|
||||
REQUIREMENTS = ['ephem==3.7.6.0']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
NORTHERN = 'northern'
|
||||
SOUTHERN = 'southern'
|
||||
EQUATOR = 'equator'
|
||||
STATE_SPRING = 'Spring'
|
||||
STATE_SUMMER = 'Summer'
|
||||
STATE_AUTUMN = 'Autumn'
|
||||
STATE_WINTER = 'Winter'
|
||||
TYPE_ASTRONOMICAL = 'astronomical'
|
||||
TYPE_METEOROLOGICAL = 'meteorological'
|
||||
VALID_TYPES = [TYPE_ASTRONOMICAL, TYPE_METEOROLOGICAL]
|
||||
|
||||
HEMISPHERE_SEASON_SWAP = {STATE_WINTER: STATE_SUMMER,
|
||||
STATE_SPRING: STATE_AUTUMN,
|
||||
STATE_AUTUMN: STATE_SPRING,
|
||||
STATE_SUMMER: STATE_WINTER}
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Optional(CONF_TYPE, default=TYPE_ASTRONOMICAL): vol.In(VALID_TYPES)
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Display the current season."""
|
||||
if None in (hass.config.latitude, hass.config.longitude):
|
||||
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
|
||||
return False
|
||||
|
||||
latitude = util.convert(hass.config.latitude, float)
|
||||
_type = config.get(CONF_TYPE)
|
||||
|
||||
if latitude < 0:
|
||||
hemisphere = SOUTHERN
|
||||
elif latitude > 0:
|
||||
hemisphere = NORTHERN
|
||||
else:
|
||||
hemisphere = EQUATOR
|
||||
|
||||
_LOGGER.debug(_type)
|
||||
add_devices([Season(hass, hemisphere, _type)])
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_season(date, hemisphere, season_tracking_type):
|
||||
"""Calculate the current season."""
|
||||
import ephem
|
||||
|
||||
if hemisphere == 'equator':
|
||||
return None
|
||||
|
||||
if season_tracking_type == TYPE_ASTRONOMICAL:
|
||||
spring_start = ephem.next_equinox(str(date.year)).datetime()
|
||||
summer_start = ephem.next_solstice(str(date.year)).datetime()
|
||||
autumn_start = ephem.next_equinox(spring_start).datetime()
|
||||
winter_start = ephem.next_solstice(summer_start).datetime()
|
||||
else:
|
||||
spring_start = datetime(2017, 3, 1).replace(year=date.year)
|
||||
summer_start = spring_start.replace(month=6)
|
||||
autumn_start = spring_start.replace(month=9)
|
||||
winter_start = spring_start.replace(month=12)
|
||||
|
||||
if spring_start <= date < summer_start:
|
||||
season = STATE_SPRING
|
||||
elif summer_start <= date < autumn_start:
|
||||
season = STATE_SUMMER
|
||||
elif autumn_start <= date < winter_start:
|
||||
season = STATE_AUTUMN
|
||||
elif winter_start <= date or spring_start > date:
|
||||
season = STATE_WINTER
|
||||
|
||||
# If user is located in the southern hemisphere swap the season
|
||||
if hemisphere == NORTHERN:
|
||||
return season
|
||||
return HEMISPHERE_SEASON_SWAP.get(season)
|
||||
|
||||
|
||||
class Season(Entity):
|
||||
"""Representation of the current season."""
|
||||
|
||||
def __init__(self, hass, hemisphere, season_tracking_type):
|
||||
"""Initialize the season."""
|
||||
self.hass = hass
|
||||
self.hemisphere = hemisphere
|
||||
self.datetime = datetime.now()
|
||||
self.type = season_tracking_type
|
||||
self.season = get_season(self.datetime, self.hemisphere, self.type)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
return "Season"
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the current season."""
|
||||
return self.season
|
||||
|
||||
def update(self):
|
||||
"""Update season."""
|
||||
self.datetime = datetime.now()
|
||||
self.season = get_season(self.datetime, self.hemisphere, self.type)
|
|
@ -202,6 +202,9 @@ enocean==0.31
|
|||
# homeassistant.components.sensor.envirophat
|
||||
# envirophat==0.0.6
|
||||
|
||||
# homeassistant.components.sensor.season
|
||||
ephem==3.7.6.0
|
||||
|
||||
# homeassistant.components.keyboard_remote
|
||||
# evdev==0.6.1
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ apns2==0.1.1
|
|||
# homeassistant.components.sensor.dsmr
|
||||
dsmr_parser==0.8
|
||||
|
||||
# homeassistant.components.sensor.season
|
||||
ephem==3.7.6.0
|
||||
|
||||
# homeassistant.components.climate.honeywell
|
||||
evohomeclient==0.2.5
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ TEST_REQUIREMENTS = (
|
|||
'restrictedpython',
|
||||
'pyunifi',
|
||||
'prometheus_client',
|
||||
'ephem'
|
||||
)
|
||||
|
||||
IGNORE_PACKAGES = (
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
"""The tests for the Season sensor platform."""
|
||||
# pylint: disable=protected-access
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
|
||||
import homeassistant.components.sensor.season as season
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
class TestSeason(unittest.TestCase):
|
||||
"""Test the season platform."""
|
||||
|
||||
DEVICE = None
|
||||
CONFIG_ASTRONOMICAL = {'type': 'astronomical'}
|
||||
CONFIG_METEOROLOGICAL = {'type': 'meteorological'}
|
||||
|
||||
def add_devices(self, devices):
|
||||
"""Mock add devices."""
|
||||
for device in devices:
|
||||
self.DEVICE = device
|
||||
|
||||
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_season_should_be_summer_northern_astonomical(self):
|
||||
"""Test that season should be summer."""
|
||||
# A known day in summer
|
||||
summer_day = datetime(2017, 9, 3, 0, 0)
|
||||
current_season = season.get_season(summer_day, season.NORTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_SUMMER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_summer_northern_meteorological(self):
|
||||
"""Test that season should be summer."""
|
||||
# A known day in summer
|
||||
summer_day = datetime(2017, 8, 13, 0, 0)
|
||||
current_season = season.get_season(summer_day, season.NORTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_SUMMER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_autumn_northern_astonomical(self):
|
||||
"""Test that season should be autumn."""
|
||||
# A known day in autumn
|
||||
autumn_day = datetime(2017, 9, 23, 0, 0)
|
||||
current_season = season.get_season(autumn_day, season.NORTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_AUTUMN,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_autumn_northern_meteorological(self):
|
||||
"""Test that season should be autumn."""
|
||||
# A known day in autumn
|
||||
autumn_day = datetime(2017, 9, 3, 0, 0)
|
||||
current_season = season.get_season(autumn_day, season.NORTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_AUTUMN,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_winter_northern_astonomical(self):
|
||||
"""Test that season should be winter."""
|
||||
# A known day in winter
|
||||
winter_day = datetime(2017, 12, 25, 0, 0)
|
||||
current_season = season.get_season(winter_day, season.NORTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_WINTER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_winter_northern_meteorological(self):
|
||||
"""Test that season should be winter."""
|
||||
# A known day in winter
|
||||
winter_day = datetime(2017, 12, 3, 0, 0)
|
||||
current_season = season.get_season(winter_day, season.NORTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_WINTER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_spring_northern_astonomical(self):
|
||||
"""Test that season should be spring."""
|
||||
# A known day in spring
|
||||
spring_day = datetime(2017, 4, 1, 0, 0)
|
||||
current_season = season.get_season(spring_day, season.NORTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_SPRING,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_spring_northern_meteorological(self):
|
||||
"""Test that season should be spring."""
|
||||
# A known day in spring
|
||||
spring_day = datetime(2017, 3, 3, 0, 0)
|
||||
current_season = season.get_season(spring_day, season.NORTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_SPRING,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_winter_southern_astonomical(self):
|
||||
"""Test that season should be winter."""
|
||||
# A known day in winter
|
||||
winter_day = datetime(2017, 9, 3, 0, 0)
|
||||
current_season = season.get_season(winter_day, season.SOUTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_WINTER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_winter_southern_meteorological(self):
|
||||
"""Test that season should be winter."""
|
||||
# A known day in winter
|
||||
winter_day = datetime(2017, 8, 13, 0, 0)
|
||||
current_season = season.get_season(winter_day, season.SOUTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_WINTER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_spring_southern_astonomical(self):
|
||||
"""Test that season should be spring."""
|
||||
# A known day in spring
|
||||
spring_day = datetime(2017, 9, 23, 0, 0)
|
||||
current_season = season.get_season(spring_day, season.SOUTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_SPRING,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_spring_southern_meteorological(self):
|
||||
"""Test that season should be spring."""
|
||||
# A known day in spring
|
||||
spring_day = datetime(2017, 9, 3, 0, 0)
|
||||
current_season = season.get_season(spring_day, season.SOUTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_SPRING,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_summer_southern_astonomical(self):
|
||||
"""Test that season should be summer."""
|
||||
# A known day in summer
|
||||
summer_day = datetime(2017, 12, 25, 0, 0)
|
||||
current_season = season.get_season(summer_day, season.SOUTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_SUMMER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_summer_southern_meteorological(self):
|
||||
"""Test that season should be summer."""
|
||||
# A known day in summer
|
||||
summer_day = datetime(2017, 12, 3, 0, 0)
|
||||
current_season = season.get_season(summer_day, season.SOUTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_SUMMER,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_autumn_southern_astonomical(self):
|
||||
"""Test that season should be spring."""
|
||||
# A known day in spring
|
||||
autumn_day = datetime(2017, 4, 1, 0, 0)
|
||||
current_season = season.get_season(autumn_day, season.SOUTHERN,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(season.STATE_AUTUMN,
|
||||
current_season)
|
||||
|
||||
def test_season_should_be_autumn_southern_meteorological(self):
|
||||
"""Test that season should be autumn."""
|
||||
# A known day in autumn
|
||||
autumn_day = datetime(2017, 3, 3, 0, 0)
|
||||
current_season = season.get_season(autumn_day, season.SOUTHERN,
|
||||
season.TYPE_METEOROLOGICAL)
|
||||
self.assertEqual(season.STATE_AUTUMN,
|
||||
current_season)
|
||||
|
||||
def test_on_equator_results_in_none(self):
|
||||
"""Test that season should be unknown."""
|
||||
# A known day in summer if astronomical and northern
|
||||
summer_day = datetime(2017, 9, 3, 0, 0)
|
||||
current_season = season.get_season(summer_day,
|
||||
season.EQUATOR,
|
||||
season.TYPE_ASTRONOMICAL)
|
||||
self.assertEqual(None, current_season)
|
Loading…
Reference in New Issue