Jewish calendar sensor (#16393)

* Initial commit for  jewish calendar sensor

* Make check for logging errors into it's own function

* Can't use f-strings as we need to support python3.5

* Implement basic functionality: printing of date

* Update requirements_all.txt

* Allow user to specify date for sensor

* Add hdate to test requirements

* Update to match pull request

* Support date output in hebrew

* Limit languages to english and hebrew

* Add name back to sensor

* Change icon to be calendar-today

* Add multiple sensors

* Fix tests

* Make Hound happy, remove unused imported class

* hdate expects datetime.date not datetime.datetime

* Return sensor name

* Times should be returned as time object, not datetime

* Add myself to codeowners for jewish calendar component

* Return actual reading, not index

* Add more tests. Currently failing.

Will need to update hdate API and version before continuing.

* Fix weekly portion test

* Make all tests pass

* Make travis happy and add a test so it doesnt happen again

* Remove defaults in __init__ method

* Change sensor state variable to local variable in update() method

* Minor changes
This commit is contained in:
Tsvi Mostovicz 2018-09-17 23:43:31 +03:00 committed by Fabian Affolter
parent 4b30cbbf3b
commit 25712f16b3
6 changed files with 276 additions and 0 deletions

View File

@ -72,6 +72,7 @@ homeassistant/components/sensor/airvisual.py @bachya
homeassistant/components/sensor/filter.py @dgomes
homeassistant/components/sensor/gearbest.py @HerrHofrat
homeassistant/components/sensor/irish_rail_transport.py @ttroy50
homeassistant/components/sensor/jewish_calendar.py @tsvi
homeassistant/components/sensor/miflora.py @danielhiversen @ChristianKuehnel
homeassistant/components/sensor/nsw_fuel_station.py @nickw444
homeassistant/components/sensor/pollen.py @bachya

View File

@ -0,0 +1,134 @@
"""
Platform to retrieve Jewish calendar information for Home Assistant.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.jewish_calendar/
"""
import logging
import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
import homeassistant.util.dt as dt_util
REQUIREMENTS = ['hdate==0.6.3']
_LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = {
'date': ['Date', 'mdi:judaism'],
'weekly_portion': ['Parshat Hashavua', 'mdi:book-open-variant'],
'holiday_name': ['Holiday', 'mdi:calendar-star'],
'holyness': ['Holyness', 'mdi:counter'],
'first_light': ['Alot Hashachar', 'mdi:weather-sunset-up'],
'gra_end_shma': ['Latest time for Shm"a GR"A', 'mdi:calendar-clock'],
'mga_end_shma': ['Latest time for Shm"a MG"A', 'mdi:calendar-clock'],
'plag_mincha': ['Plag Hamincha', 'mdi:weather-sunset-down'],
'first_stars': ['T\'set Hakochavim', 'mdi:weather-night'],
}
CONF_DIASPORA = 'diaspora'
CONF_LANGUAGE = 'language'
CONF_SENSORS = 'sensors'
DEFAULT_NAME = 'Jewish Calendar'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_DIASPORA, default=False): cv.boolean,
vol.Optional(CONF_LATITUDE): cv.latitude,
vol.Optional(CONF_LONGITUDE): cv.longitude,
vol.Optional(CONF_LANGUAGE, default='english'):
vol.In(['hebrew', 'english']),
vol.Optional(CONF_SENSORS, default=['date']):
vol.All(cv.ensure_list, vol.Length(min=1), [vol.In(SENSOR_TYPES)]),
})
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):
"""Set up the Jewish calendar sensor platform."""
language = config.get(CONF_LANGUAGE)
name = config.get(CONF_NAME)
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
diaspora = config.get(CONF_DIASPORA)
if None in (latitude, longitude):
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
return
dev = []
for sensor_type in config[CONF_SENSORS]:
dev.append(JewishCalSensor(
name, language, sensor_type, latitude, longitude, diaspora))
async_add_entities(dev, True)
class JewishCalSensor(Entity):
"""Representation of an Jewish calendar sensor."""
def __init__(
self, name, language, sensor_type, latitude, longitude, diaspora):
"""Initialize the Jewish calendar sensor."""
self.client_name = name
self._name = SENSOR_TYPES[sensor_type][0]
self.type = sensor_type
self._hebrew = (language == 'hebrew')
self._state = None
self.latitude = latitude
self.longitude = longitude
self.diaspora = diaspora
_LOGGER.debug("Sensor %s initialized", self.type)
@property
def name(self):
"""Return the name of the sensor."""
return '{} {}'.format(self.client_name, self._name)
@property
def icon(self):
"""Icon to display in the front end."""
return SENSOR_TYPES[self.type][1]
@property
def state(self):
"""Return the state of the sensor."""
return self._state
async def async_update(self):
"""Update the state of the sensor."""
import hdate
today = dt_util.now().date()
date = hdate.HDate(
today, diaspora=self.diaspora, hebrew=self._hebrew)
if self.type == 'date':
self._state = hdate.date.get_hebrew_date(
date.h_day, date.h_month, date.h_year, hebrew=self._hebrew)
elif self.type == 'weekly_portion':
self._state = hdate.date.get_parashe(
date.get_reading(self.diaspora), hebrew=self._hebrew)
elif self.type == 'holiday_name':
try:
self._state = next(
x.description[self._hebrew].long
for x in hdate.htables.HOLIDAYS
if x.index == date.get_holyday())
except StopIteration:
self._state = None
elif self.type == 'holyness':
self._state = hdate.date.get_holyday_type(date.get_holyday())
else:
times = hdate.Zmanim(
date=today,
latitude=self.latitude, longitude=self.longitude,
hebrew=self._hebrew).zmanim
self._state = times[self.type].time()
_LOGGER.debug("New value: %s", self._state)

View File

@ -435,6 +435,9 @@ haversine==0.4.5
# homeassistant.components.mqtt.server
hbmqtt==0.9.4
# homeassistant.components.sensor.jewish_calendar
hdate==0.6.3
# homeassistant.components.climate.heatmiser
heatmiserV3==0.9.1

View File

@ -80,6 +80,9 @@ haversine==0.4.5
# homeassistant.components.mqtt.server
hbmqtt==0.9.4
# homeassistant.components.sensor.jewish_calendar
hdate==0.6.3
# homeassistant.components.binary_sensor.workday
holidays==0.9.7

View File

@ -55,6 +55,7 @@ TEST_REQUIREMENTS = (
'ha-ffmpeg',
'haversine',
'hbmqtt',
'hdate',
'holidays',
'home-assistant-frontend',
'homematicip',

View File

@ -0,0 +1,134 @@
"""The tests for the Jewish calendar sensor platform."""
import unittest
from datetime import datetime as dt
from unittest.mock import patch
from homeassistant.util.async_ import run_coroutine_threadsafe
from homeassistant.setup import setup_component
from homeassistant.components.sensor.jewish_calendar import JewishCalSensor
from tests.common import get_test_home_assistant
class TestJewishCalenderSensor(unittest.TestCase):
"""Test the Jewish Calendar sensor."""
TEST_LATITUDE = 31.778
TEST_LONGITUDE = 35.235
def setUp(self):
"""Set up things to run when tests begin."""
self.hass = get_test_home_assistant()
def tearDown(self):
"""Stop everything that was started."""
self.hass.stop()
def checkForLoggingErrors(self):
"""Check whether logger spitted out errors."""
errors = [rec for rec in self.cm.records if rec.levelname == "ERROR"]
self.assertFalse(errors, ("Logger reported error(s): ",
[err.getMessage() for err in errors]))
def test_jewish_calendar_min_config(self):
"""Test minimum jewish calendar configuration."""
config = {
'sensor': {
'platform': 'jewish_calendar'
}
}
with self.assertLogs() as self.cm:
assert setup_component(self.hass, 'sensor', config)
self.checkForLoggingErrors()
def test_jewish_calendar_hebrew(self):
"""Test jewish calendar sensor with language set to hebrew."""
config = {
'sensor': {
'platform': 'jewish_calendar',
'language': 'hebrew',
}
}
with self.assertLogs() as self.cm:
assert setup_component(self.hass, 'sensor', config)
self.checkForLoggingErrors()
def test_jewish_calendar_multiple_sensors(self):
"""Test jewish calendar sensor with multiple sensors setup."""
config = {
'sensor': {
'platform': 'jewish_calendar',
'sensors': [
'date', 'weekly_portion', 'holiday_name',
'holyness', 'first_light', 'gra_end_shma',
'mga_end_shma', 'plag_mincha', 'first_stars'
]
}
}
with self.assertLogs() as self.cm:
assert setup_component(self.hass, 'sensor', config)
self.checkForLoggingErrors()
def test_jewish_calendar_sensor_date_output(self):
"""Test Jewish calendar sensor date output."""
test_time = dt(2018, 9, 3)
sensor = JewishCalSensor(
name='test', language='english', sensor_type='date',
latitude=self.TEST_LATITUDE, longitude=self.TEST_LONGITUDE,
diaspora=False)
with patch('homeassistant.util.dt.now', return_value=test_time):
run_coroutine_threadsafe(
sensor.async_update(),
self.hass.loop).result()
self.assertEqual(sensor.state, '23 Elul 5778')
def test_jewish_calendar_sensor_date_output_hebrew(self):
"""Test Jewish calendar sensor date output in hebrew."""
test_time = dt(2018, 9, 3)
sensor = JewishCalSensor(
name='test', language='hebrew', sensor_type='date',
latitude=self.TEST_LATITUDE, longitude=self.TEST_LONGITUDE,
diaspora=False)
with patch('homeassistant.util.dt.now', return_value=test_time):
run_coroutine_threadsafe(
sensor.async_update(),
self.hass.loop).result()
self.assertEqual(sensor.state, "כ\"ג באלול ה\' תשע\"ח")
def test_jewish_calendar_sensor_holiday_name(self):
"""Test Jewish calendar sensor date output in hebrew."""
test_time = dt(2018, 9, 10)
sensor = JewishCalSensor(
name='test', language='hebrew', sensor_type='holiday_name',
latitude=self.TEST_LATITUDE, longitude=self.TEST_LONGITUDE,
diaspora=False)
with patch('homeassistant.util.dt.now', return_value=test_time):
run_coroutine_threadsafe(
sensor.async_update(),
self.hass.loop).result()
self.assertEqual(sensor.state, "א\' ראש השנה")
def test_jewish_calendar_sensor_holyness(self):
"""Test Jewish calendar sensor date output in hebrew."""
test_time = dt(2018, 9, 10)
sensor = JewishCalSensor(
name='test', language='hebrew', sensor_type='holyness',
latitude=self.TEST_LATITUDE, longitude=self.TEST_LONGITUDE,
diaspora=False)
with patch('homeassistant.util.dt.now', return_value=test_time):
run_coroutine_threadsafe(
sensor.async_update(),
self.hass.loop).result()
self.assertEqual(sensor.state, 1)
def test_jewish_calendar_sensor_torah_reading(self):
"""Test Jewish calendar sensor date output in hebrew."""
test_time = dt(2018, 9, 8)
sensor = JewishCalSensor(
name='test', language='hebrew', sensor_type='weekly_portion',
latitude=self.TEST_LATITUDE, longitude=self.TEST_LONGITUDE,
diaspora=False)
with patch('homeassistant.util.dt.now', return_value=test_time):
run_coroutine_threadsafe(
sensor.async_update(),
self.hass.loop).result()
self.assertEqual(sensor.state, "פרשת נצבים")