"""Pushbullet platform for sensor component.""" import logging import threading from pushbullet import InvalidKeyError, Listener, PushBullet import voluptuous as vol from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.const import CONF_API_KEY, CONF_MONITORED_CONDITIONS import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) SENSOR_TYPES = { "application_name": ["Application name"], "body": ["Body"], "notification_id": ["Notification ID"], "notification_tag": ["Notification tag"], "package_name": ["Package name"], "receiver_email": ["Receiver email"], "sender_email": ["Sender email"], "source_device_iden": ["Sender device ID"], "title": ["Title"], "type": ["Type"], } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_API_KEY): cv.string, vol.Optional(CONF_MONITORED_CONDITIONS, default=["title", "body"]): vol.All( cv.ensure_list, vol.Length(min=1), [vol.In(SENSOR_TYPES)] ), } ) def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the Pushbullet Sensor platform.""" try: pushbullet = PushBullet(config.get(CONF_API_KEY)) except InvalidKeyError: _LOGGER.error("Wrong API key for Pushbullet supplied") return False pbprovider = PushBulletNotificationProvider(pushbullet) devices = [] for sensor_type in config[CONF_MONITORED_CONDITIONS]: devices.append(PushBulletNotificationSensor(pbprovider, sensor_type)) add_entities(devices) class PushBulletNotificationSensor(Entity): """Representation of a Pushbullet Sensor.""" def __init__(self, pb, element): """Initialize the Pushbullet sensor.""" self.pushbullet = pb self._element = element self._state = None self._state_attributes = None def update(self): """Fetch the latest data from the sensor. This will fetch the 'sensor reading' into self._state but also all attributes into self._state_attributes. """ try: self._state = self.pushbullet.data[self._element] self._state_attributes = self.pushbullet.data except (KeyError, TypeError): pass @property def name(self): """Return the name of the sensor.""" return f"Pushbullet {self._element}" @property def state(self): """Return the current state of the sensor.""" return self._state @property def device_state_attributes(self): """Return all known attributes of the sensor.""" return self._state_attributes class PushBulletNotificationProvider: """Provider for an account, leading to one or more sensors.""" def __init__(self, pb): """Start to retrieve pushes from the given Pushbullet instance.""" self.pushbullet = pb self._data = None self.listener = None self.thread = threading.Thread(target=self.retrieve_pushes) self.thread.daemon = True self.thread.start() def on_push(self, data): """Update the current data. Currently only monitors pushes but might be extended to monitor different kinds of Pushbullet events. """ if data["type"] == "push": self._data = data["push"] @property def data(self): """Return the current data stored in the provider.""" return self._data def retrieve_pushes(self): """Retrieve_pushes. Spawn a new Listener and links it to self.on_push. """ self.listener = Listener(account=self.pushbullet, on_push=self.on_push) _LOGGER.debug("Getting pushes") try: self.listener.run_forever() finally: self.listener.close()