diff --git a/homeassistant/components/camera/doorbird.py b/homeassistant/components/camera/doorbird.py index 034ddc2fabbe0af831bf5b1092670d86a5ee45e4..6680258d95d2530a3cf55564994510f8536d2fff 100644 --- a/homeassistant/components/camera/doorbird.py +++ b/homeassistant/components/camera/doorbird.py @@ -17,9 +17,9 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession DEPENDENCIES = ['doorbird'] -_CAMERA_LAST_VISITOR = "DoorBird Last Ring" -_CAMERA_LAST_MOTION = "DoorBird Last Motion" -_CAMERA_LIVE = "DoorBird Live" +_CAMERA_LAST_VISITOR = "{} Last Ring" +_CAMERA_LAST_MOTION = "{} Last Motion" +_CAMERA_LIVE = "{} Live" _LAST_VISITOR_INTERVAL = datetime.timedelta(minutes=1) _LAST_MOTION_INTERVAL = datetime.timedelta(minutes=1) _LIVE_INTERVAL = datetime.timedelta(seconds=1) @@ -30,16 +30,22 @@ _TIMEOUT = 10 # seconds @asyncio.coroutine def async_setup_platform(hass, config, async_add_devices, discovery_info=None): """Set up the DoorBird camera platform.""" - device = hass.data.get(DOORBIRD_DOMAIN) - async_add_devices([ - DoorBirdCamera(device.live_image_url, _CAMERA_LIVE, _LIVE_INTERVAL), - DoorBirdCamera( - device.history_image_url(1, 'doorbell'), _CAMERA_LAST_VISITOR, - _LAST_VISITOR_INTERVAL), - DoorBirdCamera( - device.history_image_url(1, 'motionsensor'), _CAMERA_LAST_MOTION, - _LAST_MOTION_INTERVAL), - ]) + for doorstation in hass.data[DOORBIRD_DOMAIN]: + device = doorstation.device + async_add_devices([ + DoorBirdCamera( + device.live_image_url, + _CAMERA_LIVE.format(doorstation.name), + _LIVE_INTERVAL), + DoorBirdCamera( + device.history_image_url(1, 'doorbell'), + _CAMERA_LAST_VISITOR.format(doorstation.name), + _LAST_VISITOR_INTERVAL), + DoorBirdCamera( + device.history_image_url(1, 'motionsensor'), + _CAMERA_LAST_MOTION.format(doorstation.name), + _LAST_MOTION_INTERVAL), + ]) class DoorBirdCamera(Camera): diff --git a/homeassistant/components/doorbird.py b/homeassistant/components/doorbird.py index 48f229b49cad8c44eee2495c742e172216121776..6cd820816e2fef2d94529ae6d66d2b95559405c2 100644 --- a/homeassistant/components/doorbird.py +++ b/homeassistant/components/doorbird.py @@ -4,14 +4,16 @@ Support for DoorBird device. For more details about this component, please refer to the documentation at https://home-assistant.io/components/doorbird/ """ -import asyncio import logging +import asyncio import voluptuous as vol -from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD from homeassistant.components.http import HomeAssistantView +from homeassistant.const import CONF_HOST, CONF_USERNAME, \ + CONF_PASSWORD, CONF_NAME, CONF_DEVICES, CONF_MONITORED_CONDITIONS import homeassistant.helpers.config_validation as cv +from homeassistant.util import slugify REQUIREMENTS = ['DoorBirdPy==0.1.3'] @@ -24,60 +26,139 @@ API_URL = '/api/{}'.format(DOMAIN) CONF_DOORBELL_EVENTS = 'doorbell_events' CONF_CUSTOM_URL = 'hass_url_override' +DOORBELL_EVENT = 'doorbell' +MOTION_EVENT = 'motionsensor' + +# Sensor types: Name, device_class, event +SENSOR_TYPES = { + 'doorbell': ['Button', 'occupancy', DOORBELL_EVENT], + 'motion': ['Motion', 'motion', MOTION_EVENT], +} + +DEVICE_SCHEMA = vol.Schema({ + vol.Required(CONF_HOST): cv.string, + vol.Required(CONF_USERNAME): cv.string, + vol.Required(CONF_PASSWORD): cv.string, + vol.Optional(CONF_CUSTOM_URL): cv.string, + vol.Optional(CONF_NAME): cv.string, + vol.Optional(CONF_MONITORED_CONDITIONS, default=[]): + vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), +}) + CONFIG_SCHEMA = vol.Schema({ DOMAIN: vol.Schema({ - vol.Required(CONF_HOST): cv.string, - vol.Required(CONF_USERNAME): cv.string, - vol.Required(CONF_PASSWORD): cv.string, - vol.Optional(CONF_DOORBELL_EVENTS): cv.boolean, - vol.Optional(CONF_CUSTOM_URL): cv.string, - }) + vol.Required(CONF_DEVICES): vol.All(cv.ensure_list, [DEVICE_SCHEMA]) + }), }, extra=vol.ALLOW_EXTRA) -SENSOR_DOORBELL = 'doorbell' - def setup(hass, config): """Set up the DoorBird component.""" from doorbirdpy import DoorBird - device_ip = config[DOMAIN].get(CONF_HOST) - username = config[DOMAIN].get(CONF_USERNAME) - password = config[DOMAIN].get(CONF_PASSWORD) + # Provide an endpoint for the doorstations to call to trigger events + hass.http.register_view(DoorbirdRequestView()) + + doorstations = [] + + for index, doorstation_config in enumerate(config[DOMAIN][CONF_DEVICES]): + device_ip = doorstation_config.get(CONF_HOST) + username = doorstation_config.get(CONF_USERNAME) + password = doorstation_config.get(CONF_PASSWORD) + custom_url = doorstation_config.get(CONF_CUSTOM_URL) + events = doorstation_config.get(CONF_MONITORED_CONDITIONS) + name = (doorstation_config.get(CONF_NAME) + or 'DoorBird {}'.format(index + 1)) + + device = DoorBird(device_ip, username, password) + status = device.ready() + + if status[0]: + _LOGGER.info("Connected to DoorBird at %s as %s", device_ip, + username) + doorstation = ConfiguredDoorbird(device, name, events, custom_url) + doorstations.append(doorstation) + elif status[1] == 401: + _LOGGER.error("Authorization rejected by DoorBird at %s", + device_ip) + return False + else: + _LOGGER.error("Could not connect to DoorBird at %s: Error %s", + device_ip, str(status[1])) + return False + + # SETUP EVENT SUBSCRIBERS + if events is not None: + # This will make HA the only service that receives events. + doorstation.device.reset_notifications() + + # Subscribe to doorbell or motion events + subscribe_events(hass, doorstation) + + hass.data[DOMAIN] = doorstations - device = DoorBird(device_ip, username, password) - status = device.ready() + return True - if status[0]: - _LOGGER.info("Connected to DoorBird at %s as %s", device_ip, username) - hass.data[DOMAIN] = device - elif status[1] == 401: - _LOGGER.error("Authorization rejected by DoorBird at %s", device_ip) - return False - else: - _LOGGER.error("Could not connect to DoorBird at %s: Error %s", - device_ip, str(status[1])) - return False - if config[DOMAIN].get(CONF_DOORBELL_EVENTS): - # Provide an endpoint for the device to call to trigger events - hass.http.register_view(DoorbirdRequestView()) +def subscribe_events(hass, doorstation): + """Initialize the subscriber.""" + for sensor_type in doorstation.monitored_events: + name = '{} {}'.format(doorstation.name, + SENSOR_TYPES[sensor_type][0]) + event_type = SENSOR_TYPES[sensor_type][2] # Get the URL of this server hass_url = hass.config.api.base_url - # Override it if another is specified in the component configuration - if config[DOMAIN].get(CONF_CUSTOM_URL): - hass_url = config[DOMAIN].get(CONF_CUSTOM_URL) - _LOGGER.info("DoorBird will connect to this instance via %s", - hass_url) + # Override url if another is specified onth configuration + if doorstation.custom_url is not None: + hass_url = doorstation.custom_url - # This will make HA the only service that gets doorbell events - url = '{}{}/{}'.format(hass_url, API_URL, SENSOR_DOORBELL) - device.reset_notifications() - device.subscribe_notification(SENSOR_DOORBELL, url) + slug = slugify(name) + + url = '{}{}/{}'.format(hass_url, API_URL, slug) + + _LOGGER.info("DoorBird will connect to this instance via %s", + url) + + _LOGGER.info("You may use the following event name for automations" + ": %s_%s", DOMAIN, slug) + + doorstation.device.subscribe_notification(event_type, url) - return True + +class ConfiguredDoorbird(): + """Attach additional information to pass along with configured device.""" + + def __init__(self, device, name, events=None, custom_url=None): + """Initialize configured device.""" + self._name = name + self._device = device + self._custom_url = custom_url + self._monitored_events = events + + @property + def name(self): + """Custom device name.""" + return self._name + + @property + def device(self): + """The configured device.""" + return self._device + + @property + def custom_url(self): + """Custom url for device.""" + return self._custom_url + + @property + def monitored_events(self): + """Get monitored events.""" + if self._monitored_events is None: + return [] + + return self._monitored_events class DoorbirdRequestView(HomeAssistantView): @@ -93,5 +174,7 @@ class DoorbirdRequestView(HomeAssistantView): def get(self, request, sensor): """Respond to requests from the device.""" hass = request.app['hass'] + hass.bus.async_fire('{}_{}'.format(DOMAIN, sensor)) + return 'OK' diff --git a/homeassistant/components/switch/doorbird.py b/homeassistant/components/switch/doorbird.py index 9886b3a586d04a8c17d717970beb8bb919906a80..92ba3640237edbc196ecdda946ca4409ce54086f 100644 --- a/homeassistant/components/switch/doorbird.py +++ b/homeassistant/components/switch/doorbird.py @@ -4,10 +4,10 @@ import logging import voluptuous as vol +import homeassistant.helpers.config_validation as cv from homeassistant.components.doorbird import DOMAIN as DOORBIRD_DOMAIN from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice from homeassistant.const import CONF_SWITCHES -import homeassistant.helpers.config_validation as cv DEPENDENCIES = ['doorbird'] @@ -15,7 +15,7 @@ _LOGGER = logging.getLogger(__name__) SWITCHES = { "open_door": { - "name": "Open Door", + "name": "{} Open Door", "icon": { True: "lock-open", False: "lock" @@ -23,7 +23,7 @@ SWITCHES = { "time": datetime.timedelta(seconds=3) }, "open_door_2": { - "name": "Open Door 2", + "name": "{} Open Door 2", "icon": { True: "lock-open", False: "lock" @@ -31,7 +31,7 @@ SWITCHES = { "time": datetime.timedelta(seconds=3) }, "light_on": { - "name": "Light On", + "name": "{} Light On", "icon": { True: "lightbulb-on", False: "lightbulb" @@ -48,31 +48,36 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the DoorBird switch platform.""" - device = hass.data.get(DOORBIRD_DOMAIN) - switches = [] - for switch in SWITCHES: - _LOGGER.debug("Adding DoorBird switch %s", SWITCHES[switch]["name"]) - switches.append(DoorBirdSwitch(device, switch)) + + for doorstation in hass.data[DOORBIRD_DOMAIN]: + + device = doorstation.device + + for switch in SWITCHES: + + _LOGGER.debug("Adding DoorBird switch %s", + SWITCHES[switch]["name"].format(doorstation.name)) + switches.append(DoorBirdSwitch(device, switch, doorstation.name)) add_devices(switches) - _LOGGER.info("Added DoorBird switches") class DoorBirdSwitch(SwitchDevice): """A relay in a DoorBird device.""" - def __init__(self, device, switch): + def __init__(self, device, switch, name): """Initialize a relay in a DoorBird device.""" self._device = device self._switch = switch + self._name = name self._state = False self._assume_off = datetime.datetime.min @property def name(self): """Return the name of the switch.""" - return SWITCHES[self._switch]["name"] + return SWITCHES[self._switch]["name"].format(self._name) @property def icon(self):