""" Support for UpCloud. For more details about this component, please refer to the documentation at https://home-assistant.io/components/upcloud/ """ import asyncio import logging from datetime import timedelta import voluptuous as vol from homeassistant.const import ( CONF_USERNAME, CONF_PASSWORD, CONF_SCAN_INTERVAL, STATE_ON, STATE_OFF, STATE_PROBLEM) from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.dispatcher import ( async_dispatcher_connect, dispatcher_send) from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import track_time_interval REQUIREMENTS = ['upcloud-api==0.4.2'] _LOGGER = logging.getLogger(__name__) ATTR_CORE_NUMBER = 'core_number' ATTR_HOSTNAME = 'hostname' ATTR_MEMORY_AMOUNT = 'memory_amount' ATTR_STATE = 'state' ATTR_TITLE = 'title' ATTR_UUID = 'uuid' ATTR_ZONE = 'zone' CONF_SERVERS = 'servers' DATA_UPCLOUD = 'data_upcloud' DOMAIN = 'upcloud' DEFAULT_COMPONENT_NAME = 'UpCloud {}' DEFAULT_COMPONENT_DEVICE_CLASS = 'power' UPCLOUD_PLATFORMS = ['binary_sensor', 'switch'] SCAN_INTERVAL = timedelta(seconds=60) SIGNAL_UPDATE_UPCLOUD = "upcloud_update" STATE_MAP = { "started": STATE_ON, "stopped": STATE_OFF, "error": STATE_PROBLEM, } CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_SCAN_INTERVAL, default=SCAN_INTERVAL): cv.time_period, }), }, extra=vol.ALLOW_EXTRA) def setup(hass, config): """Set up the UpCloud component.""" import upcloud_api conf = config[DOMAIN] username = conf.get(CONF_USERNAME) password = conf.get(CONF_PASSWORD) scan_interval = conf.get(CONF_SCAN_INTERVAL) manager = upcloud_api.CloudManager(username, password) try: manager.authenticate() hass.data[DATA_UPCLOUD] = UpCloud(manager) except upcloud_api.UpCloudAPIError: _LOGGER.error("Authentication failed.") return False def upcloud_update(event_time): """Call UpCloud to update information.""" _LOGGER.debug("Updating UpCloud component") hass.data[DATA_UPCLOUD].update() dispatcher_send(hass, SIGNAL_UPDATE_UPCLOUD) # Call the UpCloud API to refresh data track_time_interval(hass, upcloud_update, scan_interval) return True class UpCloud(object): """Handle all communication with the UpCloud API.""" def __init__(self, manager): """Initialize the UpCloud connection.""" self.data = {} self.manager = manager def update(self): """Update data from UpCloud API.""" self.data = { server.uuid: server for server in self.manager.get_servers() } class UpCloudServerEntity(Entity): """Entity class for UpCloud servers.""" def __init__(self, upcloud, uuid): """Initialize the UpCloud server entity.""" self._upcloud = upcloud self.uuid = uuid self.data = None @property def unique_id(self) -> str: """Return unique ID for the entity.""" return self.uuid @property def name(self): """Return the name of the component.""" try: return DEFAULT_COMPONENT_NAME.format(self.data.title) except (AttributeError, KeyError, TypeError): return DEFAULT_COMPONENT_NAME.format(self.uuid) @asyncio.coroutine def async_added_to_hass(self): """Register callbacks.""" async_dispatcher_connect( self.hass, SIGNAL_UPDATE_UPCLOUD, self._update_callback) @callback def _update_callback(self): """Call update method.""" self.async_schedule_update_ha_state(True) @property def icon(self): """Return the icon of this server.""" return 'mdi:server' if self.is_on else 'mdi:server-off' @property def state(self): """Return state of the server.""" try: return STATE_MAP.get(self.data.state) except AttributeError: return None @property def is_on(self): """Return true if the server is on.""" return self.state == STATE_ON @property def device_class(self): """Return the class of this server.""" return DEFAULT_COMPONENT_DEVICE_CLASS @property def device_state_attributes(self): """Return the state attributes of the UpCloud server.""" return { x: getattr(self.data, x, None) for x in (ATTR_UUID, ATTR_TITLE, ATTR_HOSTNAME, ATTR_ZONE, ATTR_STATE, ATTR_CORE_NUMBER, ATTR_MEMORY_AMOUNT) } def update(self): """Update data of the UpCloud server.""" self.data = self._upcloud.data.get(self.uuid)