diff --git a/homeassistant/components/android_ip_webcam.py b/homeassistant/components/android_ip_webcam.py index 3b6de5c4892..e236a04a40a 100644 --- a/homeassistant/components/android_ip_webcam.py +++ b/homeassistant/components/android_ip_webcam.py @@ -12,7 +12,8 @@ import voluptuous as vol from homeassistant.core import callback from homeassistant.const import ( CONF_NAME, CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD, - CONF_SENSORS, CONF_SWITCHES, CONF_TIMEOUT, CONF_SCAN_INTERVAL) + CONF_SENSORS, CONF_SWITCHES, CONF_TIMEOUT, CONF_SCAN_INTERVAL, + CONF_PLATFORM) from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers import discovery import homeassistant.helpers.config_validation as cv @@ -21,14 +22,17 @@ from homeassistant.helpers.dispatcher import ( from homeassistant.helpers.entity import Entity from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.util.dt import utcnow +from homeassistant.components.camera.mjpeg import ( + CONF_MJPEG_URL, CONF_STILL_IMAGE_URL, DOMAIN as MJPEG_DOMAIN) DOMAIN = 'android_ip_webcam' -REQUIREMENTS = ["pydroid-ipcam==0.2"] +REQUIREMENTS = ["pydroid-ipcam==0.3"] SCAN_INTERVAL = timedelta(seconds=10) DATA_IP_WEBCAM = 'android_ip_webcam' +ATTR_HOST = 'host' ATTR_VID_CONNS = 'Video Connections' ATTR_AUD_CONNS = 'Audio Connections' @@ -119,9 +123,11 @@ SENSORS = ['audio_connections', 'battery_level', 'battery_temp', SIGNAL_UPDATE_DATA = 'android_ip_webcam_update' +CONF_AUTO_DISCOVERY = 'auto_discovery' CONF_MOTION_SENSOR = 'motion_sensor' -DEFAULT_MOTION_SENSOR = True +DEFAULT_AUTO_DISCOVERY = True +DEFAULT_MOTION_SENSOR = False DEFAULT_NAME = 'IP Webcam' DEFAULT_PORT = 8080 DEFAULT_TIMEOUT = 10 @@ -137,11 +143,14 @@ CONFIG_SCHEMA = vol.Schema({ cv.time_period, vol.Inclusive(CONF_USERNAME, 'authentication'): cv.string, vol.Inclusive(CONF_PASSWORD, 'authentication'): cv.string, - vol.Optional(CONF_SWITCHES, default=SWITCHES): + vol.Optional(CONF_AUTO_DISCOVERY, default=DEFAULT_AUTO_DISCOVERY): + cv.boolean, + vol.Optional(CONF_SWITCHES, default=[]): vol.All(cv.ensure_list, [vol.In(SWITCHES)]), - vol.Optional(CONF_SENSORS, default=SENSORS): + vol.Optional(CONF_SENSORS, default=[]): vol.All(cv.ensure_list, [vol.In(SENSORS)]), - vol.Optional(CONF_MOTION_SENSOR, default=DEFAULT_MOTION_SENSOR): bool + vol.Optional(CONF_MOTION_SENSOR, default=DEFAULT_MOTION_SENSOR): + cv.boolean, })]) }, extra=vol.ALLOW_EXTRA) @@ -162,7 +171,11 @@ def async_setup(hass, config): password = cam_config.get(CONF_PASSWORD) name = cam_config[CONF_NAME] interval = cam_config[CONF_SCAN_INTERVAL] + switches = cam_config[CONF_SWITCHES] + sensors = cam_config[CONF_SENSORS] + motion = cam_config[CONF_MOTION_SENSOR] + # init ip webcam cam = PyDroidIPCam( hass.loop, websession, host, cam_config[CONF_PORT], username=username, password=password, @@ -179,12 +192,27 @@ def async_setup(hass, config): hass, async_update_data, utcnow() + interval) yield from async_update_data(None) + + # use autodiscovery to detect sensors/configs + if cam_config[CONF_AUTO_DISCOVERY]: + if not cam.available: + _LOGGER.error( + "Android webcam %s not found for discovery!", host) + return + + sensors = cam.enabled_sensors + switches = cam.enabled_settings + if 'motion_active' in sensors: + sensors.pop('motion_active') + motion = True + + # load platforms webcams[host] = cam mjpeg_camera = { - 'platform': 'mjpeg', - 'mjpeg_url': cam.mjpeg_url, - 'still_image_url': cam.image_url, + CONF_PLATFORM: MJPEG_DOMAIN, + CONF_MJPEG_URL: cam.mjpeg_url, + CONF_STILL_IMAGE_URL: cam.image_url, CONF_NAME: name, } if username and password: @@ -193,13 +221,6 @@ def async_setup(hass, config): CONF_PASSWORD: password }) - if cam_config[CONF_MOTION_SENSOR]: - hass.async_add_job(discovery.async_load_platform( - hass, 'binary_sensor', DOMAIN, { - CONF_HOST: host, - CONF_NAME: name, - }, config)) - hass.async_add_job(discovery.async_load_platform( hass, 'camera', 'mjpeg', mjpeg_camera, config)) @@ -207,16 +228,24 @@ def async_setup(hass, config): hass, 'sensor', DOMAIN, { CONF_NAME: name, CONF_HOST: host, - CONF_SENSORS: cam_config[CONF_SENSORS], + CONF_SENSORS: sensors, }, config)) hass.async_add_job(discovery.async_load_platform( hass, 'switch', DOMAIN, { CONF_NAME: name, CONF_HOST: host, - CONF_SWITCHES: cam_config[CONF_SWITCHES], + CONF_SWITCHES: switches, }, config)) + if motion: + hass.async_add_job(discovery.async_load_platform( + hass, 'binary_sensor', DOMAIN, { + CONF_HOST: host, + CONF_NAME: name, + }, config)) + + tasks = [async_setup_ipcamera(conf) for conf in config[DOMAIN]] if tasks: yield from asyncio.wait(tasks, loop=hass.loop) @@ -258,7 +287,7 @@ class AndroidIPCamEntity(Entity): @property def device_state_attributes(self): """Return the state attributes.""" - state_attr = {} + state_attr = {ATTTR_HOST: self._host} if self._ipcam.status_data is None: return state_attr @@ -266,6 +295,5 @@ class AndroidIPCamEntity(Entity): self._ipcam.status_data.get('video_connections') state_attr[ATTR_AUD_CONNS] = \ self._ipcam.status_data.get('audio_connections') - state_attr.update(self._ipcam.current_settings) return state_attr diff --git a/homeassistant/components/binary_sensor/android_ip_webcam.py b/homeassistant/components/binary_sensor/android_ip_webcam.py index 8c0699040ed..4b9b4af24af 100644 --- a/homeassistant/components/binary_sensor/android_ip_webcam.py +++ b/homeassistant/components/binary_sensor/android_ip_webcam.py @@ -6,7 +6,6 @@ https://home-assistant.io/components/binary_sensor.android_ip_webcam/ """ import asyncio -from homeassistant.const import STATE_UNKNOWN from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.components.android_ip_webcam import ( KEY_MAP, DATA_IP_WEBCAM, AndroidIPCamEntity, CONF_HOST, CONF_NAME) @@ -54,17 +53,8 @@ class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice): @asyncio.coroutine def async_update(self): """Retrieve latest state.""" - if self._ipcam.status_data is None: - self._state = STATE_UNKNOWN - return - - if self._sensor not in self._ipcam.enabled_sensors: - self._state = STATE_UNKNOWN - return - - container = self._ipcam.sensor_data.get(self._sensor) - data_point = container.get('data', [[0, [0.0]]]) - self._state = data_point[0][-1][0] == 1.0 + state, _ = self._ipcam.export_sensor(self._sensor) + self._state = state == 1.0 @property def device_class(self): diff --git a/homeassistant/components/sensor/android_ip_webcam.py b/homeassistant/components/sensor/android_ip_webcam.py index 14a77da632e..5b7099d1c96 100644 --- a/homeassistant/components/sensor/android_ip_webcam.py +++ b/homeassistant/components/sensor/android_ip_webcam.py @@ -6,7 +6,6 @@ https://home-assistant.io/components/sensor.android_ip_webcam/ """ import asyncio -from homeassistant.const import STATE_UNKNOWN from homeassistant.components.android_ip_webcam import ( KEY_MAP, ICON_MAP, DATA_IP_WEBCAM, AndroidIPCamEntity, CONF_HOST, CONF_NAME, CONF_SENSORS) @@ -64,23 +63,11 @@ class IPWebcamSensor(AndroidIPCamEntity): @asyncio.coroutine def async_update(self): """Retrieve latest state.""" - if self._ipcam.status_data is None or self._ipcam.sensor_data is None: - self._state = STATE_UNKNOWN - return - - if self._sensor not in self._ipcam.enabled_sensors: - self._state = STATE_UNKNOWN - return - if self._sensor in ('audio_connections', 'video_connections'): self._state = self._ipcam.status_data.get(self._sensor) self._unit = 'Connections' else: - container = self._ipcam.sensor_data.get(self._sensor) - self._unit = container.get('unit', self._unit) - data_point = container.get('data', [[0, [0.0]]]) - if data_point and data_point[0]: - self._state = data_point[0][-1][0] + self._state, self._unit = self._ipcam.export_sensor(self._sensor) @property def icon(self): diff --git a/homeassistant/components/switch/android_ip_webcam.py b/homeassistant/components/switch/android_ip_webcam.py index 6362e0c5261..6e3b9ed77f1 100644 --- a/homeassistant/components/switch/android_ip_webcam.py +++ b/homeassistant/components/switch/android_ip_webcam.py @@ -6,7 +6,6 @@ https://home-assistant.io/components/switch.android_ip_webcam/ """ import asyncio -from homeassistant.const import STATE_UNKNOWN from homeassistant.components.switch import SwitchDevice from homeassistant.components.android_ip_webcam import ( KEY_MAP, ICON_MAP, DATA_IP_WEBCAM, AndroidIPCamEntity, CONF_HOST, @@ -54,10 +53,7 @@ class IPWebcamSettingsSwitch(AndroidIPCamEntity, SwitchDevice): @asyncio.coroutine def async_update(self): """Get the updated status of the switch.""" - if self._ipcam.status_data is not None: - self._state = self._ipcam.current_settings.get(self._setting) - else: - self._state = STATE_UNKNOWN + self._state = bool(self._ipcam.current_settings.get(self._setting)) @property def is_on(self): diff --git a/requirements_all.txt b/requirements_all.txt index cba53d3a13d..afa3c2d7126 100755 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -482,7 +482,7 @@ pycmus==0.1.0 pydispatcher==2.0.5 # homeassistant.components.android_ip_webcam -pydroid-ipcam==0.2 +pydroid-ipcam==0.3 # homeassistant.components.sensor.ebox pyebox==0.1.0