From cb59b3fee17634e75b8cb1552ee8a7f01b1d0528 Mon Sep 17 00:00:00 2001 From: aetolus Date: Wed, 23 Aug 2017 08:40:16 +1000 Subject: [PATCH] Add worldtidesinfo sensor component (#8860) * Style fixes for worldtidesinfo sensor component * Fix D202 for worldtidesinfo sensor component * Multiple fixes * Multiple fixes * Fixes * more * working with changes * changes * changes * fix style errors * fix style errors * Complete rewrite * worldtidesinfo Fix D202 for worldtidesinfo sensor component Multiple fixes Multiple fixes Fixes more working with changes changes changes fix style errors fix style errors Complete rewrite PR Changes * Fix * fix scan interval & lint --- .coveragerc | 1 + .../components/sensor/worldtidesinfo.py | 113 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 homeassistant/components/sensor/worldtidesinfo.py diff --git a/.coveragerc b/.coveragerc index c1356abe8b4..d8041b9fe6c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -528,6 +528,7 @@ omit = homeassistant/components/sensor/ups.py homeassistant/components/sensor/vasttrafik.py homeassistant/components/sensor/waqi.py + homeassistant/components/sensor/worldtidesinfo.py homeassistant/components/sensor/xbox_live.py homeassistant/components/sensor/yweather.py homeassistant/components/sensor/zamg.py diff --git a/homeassistant/components/sensor/worldtidesinfo.py b/homeassistant/components/sensor/worldtidesinfo.py new file mode 100644 index 00000000000..c9a42f3cb11 --- /dev/null +++ b/homeassistant/components/sensor/worldtidesinfo.py @@ -0,0 +1,113 @@ +""" +This component provides HA sensor support for the worldtides.info API. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/sensor.worldtidesinfo/ +""" +import logging +import time +from datetime import timedelta + +import requests +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components.sensor import PLATFORM_SCHEMA +from homeassistant.const import (CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, + CONF_NAME, STATE_UNKNOWN) +from homeassistant.helpers.entity import Entity + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_NAME = 'WorldTidesInfo' + +SCAN_INTERVAL = timedelta(seconds=3600) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Required(CONF_API_KEY): cv.string, + vol.Optional(CONF_LATITUDE): cv.latitude, + vol.Optional(CONF_LONGITUDE): cv.longitude, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, +}) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """Set up the WorldTidesInfo sensor.""" + name = config.get(CONF_NAME) + + lat = config.get(CONF_LATITUDE, hass.config.latitude) + lon = config.get(CONF_LONGITUDE, hass.config.longitude) + key = config.get(CONF_API_KEY) + + if None in (lat, lon): + _LOGGER.error("Latitude or longitude not set in Home Assistant config") + + add_devices([WorldTidesInfoSensor(name, lat, lon, key)], True) + + +class WorldTidesInfoSensor(Entity): + """Representation of a WorldTidesInfo sensor.""" + + def __init__(self, name, lat, lon, key): + """Initialize the sensor.""" + self._name = name + self._lat = lat + self._lon = lon + self._key = key + self.data = None + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def device_state_attributes(self): + """Return the state attributes of this device.""" + attr = {} + if "High" in str(self.data['extremes'][0]['type']): + attr['high_tide_time_utc'] = self.data['extremes'][0]['date'] + attr['high_tide_height'] = self.data['extremes'][0]['height'] + attr['low_tide_time_utc'] = self.data['extremes'][1]['date'] + attr['low_tide_height'] = self.data['extremes'][1]['height'] + elif "Low" in str(self.data['extremes'][0]['type']): + attr['high_tide_time_utc'] = self.data['extremes'][1]['date'] + attr['high_tide_height'] = self.data['extremes'][1]['height'] + attr['low_tide_time_utc'] = self.data['extremes'][0]['date'] + attr['low_tide_height'] = self.data['extremes'][0]['height'] + return attr + + @property + def state(self): + """Return the state of the device.""" + if self.data: + if "High" in str(self.data['extremes'][0]['type']): + tidetime = time.strftime('%I:%M %p', time.localtime( + self.data['extremes'][0]['dt'])) + return "High tide at %s" % (tidetime) + elif "Low" in str(self.data['extremes'][0]['type']): + tidetime = time.strftime('%I:%M %p', time.localtime( + self.data['extremes'][1]['dt'])) + return "Low tide at %s" % (tidetime) + else: + return STATE_UNKNOWN + else: + return STATE_UNKNOWN + + def update(self): + """Get the latest data from WorldTidesInfo API.""" + start = int(time.time()) + resource = 'https://www.worldtides.info/api?extremes&length=86400' \ + '&key=%s&lat=%s&lon=%s&start=%s' % (self._key, self._lat, + self._lon, start) + + try: + self.data = requests.get(resource, timeout=10).json() + _LOGGER.debug("Data = %s", self.data) + _LOGGER.info("Tide data queried with start time set to: %s", + (start)) + except ValueError as err: + _LOGGER.error("Check WorldTidesInfo %s", err.args) + self.data = None + raise