"""Support for the SpaceAPI.""" import logging import voluptuous as vol from homeassistant.components.http import HomeAssistantView from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_ICON, ATTR_LATITUDE, ATTR_LOCATION, ATTR_LONGITUDE, ATTR_STATE, ATTR_UNIT_OF_MEASUREMENT, CONF_ADDRESS, CONF_EMAIL, CONF_ENTITY_ID, CONF_SENSORS, CONF_STATE, CONF_URL, ) import homeassistant.core as ha import homeassistant.helpers.config_validation as cv import homeassistant.util.dt as dt_util _LOGGER = logging.getLogger(__name__) ATTR_ADDRESS = "address" ATTR_API = "api" ATTR_CLOSE = "close" ATTR_CONTACT = "contact" ATTR_ISSUE_REPORT_CHANNELS = "issue_report_channels" ATTR_LASTCHANGE = "lastchange" ATTR_LOGO = "logo" ATTR_NAME = "name" ATTR_OPEN = "open" ATTR_SENSORS = "sensors" ATTR_SPACE = "space" ATTR_UNIT = "unit" ATTR_URL = "url" ATTR_VALUE = "value" ATTR_SENSOR_LOCATION = "location" CONF_CONTACT = "contact" CONF_HUMIDITY = "humidity" CONF_ICON_CLOSED = "icon_closed" CONF_ICON_OPEN = "icon_open" CONF_ICONS = "icons" CONF_IRC = "irc" CONF_ISSUE_REPORT_CHANNELS = "issue_report_channels" CONF_LOCATION = "location" CONF_LOGO = "logo" CONF_MAILING_LIST = "mailing_list" CONF_PHONE = "phone" CONF_SPACE = "space" CONF_TEMPERATURE = "temperature" CONF_TWITTER = "twitter" DATA_SPACEAPI = "data_spaceapi" DOMAIN = "spaceapi" ISSUE_REPORT_CHANNELS = [CONF_EMAIL, CONF_IRC, CONF_MAILING_LIST, CONF_TWITTER] SENSOR_TYPES = [CONF_HUMIDITY, CONF_TEMPERATURE] SPACEAPI_VERSION = 0.13 URL_API_SPACEAPI = "/api/spaceapi" LOCATION_SCHEMA = vol.Schema({vol.Optional(CONF_ADDRESS): cv.string}, required=True) CONTACT_SCHEMA = vol.Schema( { vol.Optional(CONF_EMAIL): cv.string, vol.Optional(CONF_IRC): cv.string, vol.Optional(CONF_MAILING_LIST): cv.string, vol.Optional(CONF_PHONE): cv.string, vol.Optional(CONF_TWITTER): cv.string, }, required=False, ) STATE_SCHEMA = vol.Schema( { vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Inclusive(CONF_ICON_CLOSED, CONF_ICONS): cv.url, vol.Inclusive(CONF_ICON_OPEN, CONF_ICONS): cv.url, }, required=False, ) SENSOR_SCHEMA = vol.Schema( {vol.In(SENSOR_TYPES): [cv.entity_id], cv.string: [cv.entity_id]} ) CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( { vol.Required(CONF_CONTACT): CONTACT_SCHEMA, vol.Required(CONF_ISSUE_REPORT_CHANNELS): vol.All( cv.ensure_list, [vol.In(ISSUE_REPORT_CHANNELS)] ), vol.Required(CONF_LOCATION): LOCATION_SCHEMA, vol.Required(CONF_LOGO): cv.url, vol.Required(CONF_SPACE): cv.string, vol.Required(CONF_STATE): STATE_SCHEMA, vol.Required(CONF_URL): cv.string, vol.Optional(CONF_SENSORS): SENSOR_SCHEMA, } ) }, extra=vol.ALLOW_EXTRA, ) def setup(hass, config): """Register the SpaceAPI with the HTTP interface.""" hass.data[DATA_SPACEAPI] = config[DOMAIN] hass.http.register_view(APISpaceApiView) return True class APISpaceApiView(HomeAssistantView): """View to provide details according to the SpaceAPI.""" url = URL_API_SPACEAPI name = "api:spaceapi" @staticmethod def get_sensor_data(hass, spaceapi, sensor): """Get data from a sensor.""" sensor_state = hass.states.get(sensor) if not sensor_state: return None sensor_data = {ATTR_NAME: sensor_state.name, ATTR_VALUE: sensor_state.state} if ATTR_SENSOR_LOCATION in sensor_state.attributes: sensor_data[ATTR_LOCATION] = sensor_state.attributes[ATTR_SENSOR_LOCATION] else: sensor_data[ATTR_LOCATION] = spaceapi[CONF_SPACE] # Some sensors don't have a unit of measurement if ATTR_UNIT_OF_MEASUREMENT in sensor_state.attributes: sensor_data[ATTR_UNIT] = sensor_state.attributes[ATTR_UNIT_OF_MEASUREMENT] return sensor_data @ha.callback def get(self, request): """Get SpaceAPI data.""" hass = request.app["hass"] spaceapi = dict(hass.data[DATA_SPACEAPI]) is_sensors = spaceapi.get("sensors") location = { ATTR_ADDRESS: spaceapi[ATTR_LOCATION][CONF_ADDRESS], ATTR_LATITUDE: hass.config.latitude, ATTR_LONGITUDE: hass.config.longitude, } state_entity = spaceapi["state"][ATTR_ENTITY_ID] space_state = hass.states.get(state_entity) if space_state is not None: state = { ATTR_OPEN: space_state.state != "off", ATTR_LASTCHANGE: dt_util.as_timestamp(space_state.last_updated), } else: state = {ATTR_OPEN: "null", ATTR_LASTCHANGE: 0} try: state[ATTR_ICON] = { ATTR_OPEN: spaceapi["state"][CONF_ICON_OPEN], ATTR_CLOSE: spaceapi["state"][CONF_ICON_CLOSED], } except KeyError: pass data = { ATTR_API: SPACEAPI_VERSION, ATTR_CONTACT: spaceapi[CONF_CONTACT], ATTR_ISSUE_REPORT_CHANNELS: spaceapi[CONF_ISSUE_REPORT_CHANNELS], ATTR_LOCATION: location, ATTR_LOGO: spaceapi[CONF_LOGO], ATTR_SPACE: spaceapi[CONF_SPACE], ATTR_STATE: state, ATTR_URL: spaceapi[CONF_URL], } if is_sensors is not None: sensors = {} for sensor_type in is_sensors: sensors[sensor_type] = [] for sensor in spaceapi["sensors"][sensor_type]: sensor_data = self.get_sensor_data(hass, spaceapi, sensor) sensors[sensor_type].append(sensor_data) data[ATTR_SENSORS] = sensors return self.json(data)