""" Support for information from HP ILO sensors. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.sensor.hp_ilo/ """ import logging from datetime import timedelta import voluptuous as vol from homeassistant.const import ( CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD, CONF_NAME, CONF_MONITORED_VARIABLES, CONF_VALUE_TEMPLATE, CONF_SENSOR_TYPE, CONF_UNIT_OF_MEASUREMENT) from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.helpers.entity import Entity from homeassistant.util import Throttle import homeassistant.helpers.config_validation as cv REQUIREMENTS = ['python-hpilo==3.9'] _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = 'HP ILO' DEFAULT_PORT = 443 MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300) SENSOR_TYPES = { 'server_name': ['Server Name', 'get_server_name'], 'server_fqdn': ['Server FQDN', 'get_server_fqdn'], 'server_host_data': ['Server Host Data', 'get_host_data'], 'server_oa_info': ['Server Onboard Administrator Info', 'get_oa_info'], 'server_power_status': ['Server Power state', 'get_host_power_status'], 'server_power_readings': ['Server Power readings', 'get_power_readings'], 'server_power_on_time': ['Server Power On time', 'get_server_power_on_time'], 'server_asset_tag': ['Server Asset Tag', 'get_asset_tag'], 'server_uid_status': ['Server UID light', 'get_uid_status'], 'server_health': ['Server Health', 'get_embedded_health'], 'network_settings': ['Network Settings', 'get_network_settings'] } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional(CONF_MONITORED_VARIABLES, default=[]): vol.All(cv.ensure_list, [vol.Schema({ vol.Required(CONF_NAME): cv.string, vol.Required(CONF_SENSOR_TYPE): vol.All(cv.string, vol.In(SENSOR_TYPES)), vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string, vol.Optional(CONF_VALUE_TEMPLATE): cv.template })]), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, }) # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the HP ILO sensor.""" hostname = config.get(CONF_HOST) port = config.get(CONF_PORT) login = config.get(CONF_USERNAME) password = config.get(CONF_PASSWORD) monitored_variables = config.get(CONF_MONITORED_VARIABLES) # Create a data fetcher to support all of the configured sensors. Then make # the first call to init the data and confirm we can connect. try: hp_ilo_data = HpIloData(hostname, port, login, password) except ValueError as error: _LOGGER.error(error) return False # Initialize and add all of the sensors. devices = [] for monitored_variable in monitored_variables: new_device = HpIloSensor( hass=hass, hp_ilo_data=hp_ilo_data, sensor_name='{} {}'.format( config.get(CONF_NAME), monitored_variable[CONF_NAME]), sensor_type=monitored_variable[CONF_SENSOR_TYPE], sensor_value_template=monitored_variable.get(CONF_VALUE_TEMPLATE), unit_of_measurement=monitored_variable.get( CONF_UNIT_OF_MEASUREMENT)) devices.append(new_device) add_devices(devices, True) class HpIloSensor(Entity): """Representation of a HP ILO sensor.""" def __init__(self, hass, hp_ilo_data, sensor_type, sensor_name, sensor_value_template, unit_of_measurement): """Initialize the sensor.""" self._hass = hass self._name = sensor_name self._unit_of_measurement = unit_of_measurement self._ilo_function = SENSOR_TYPES[sensor_type][1] self.hp_ilo_data = hp_ilo_data if sensor_value_template is not None: sensor_value_template.hass = hass self._sensor_value_template = sensor_value_template self._state = None self._state_attributes = None _LOGGER.debug("Created HP ILO sensor %r", self) @property def name(self): """Return the name of the sensor.""" return self._name @property def unit_of_measurement(self): """Return the unit of measurement of the sensor.""" return self._unit_of_measurement @property def state(self): """Return the state of the sensor.""" return self._state @property def device_state_attributes(self): """Return the state attributes.""" return self._state_attributes def update(self): """Get the latest data from HP ILO and updates the states.""" # Call the API for new data. Each sensor will re-trigger this # same exact call, but that's fine. Results should be cached for # a short period of time to prevent hitting API limits. self.hp_ilo_data.update() ilo_data = getattr(self.hp_ilo_data.data, self._ilo_function)() if self._sensor_value_template is not None: ilo_data = self._sensor_value_template.render(ilo_data=ilo_data) self._state = ilo_data class HpIloData(object): """Gets the latest data from HP ILO.""" def __init__(self, host, port, login, password): """Initialize the data object.""" self._host = host self._port = port self._login = login self._password = password self.data = None self.update() @Throttle(MIN_TIME_BETWEEN_UPDATES) def update(self): """Get the latest data from HP ILO.""" import hpilo try: self.data = hpilo.Ilo( hostname=self._host, login=self._login, password=self._password, port=self._port) except (hpilo.IloError, hpilo.IloCommunicationError, hpilo.IloLoginFailed) as error: raise ValueError("Unable to init HP ILO, {}".format(error))