"""
homeassistant.components.camera.uvc
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for Ubiquiti's UVC cameras.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.uvc/
"""
import logging
import socket

import requests

from homeassistant.helpers import validate_config
from homeassistant.components.camera import DOMAIN, Camera

REQUIREMENTS = ['uvcclient==0.6']

_LOGGER = logging.getLogger(__name__)


def setup_platform(hass, config, add_devices, discovery_info=None):
    """ Discover cameras on a Unifi NVR. """
    if not validate_config({DOMAIN: config}, {DOMAIN: ['nvr', 'key']},
                           _LOGGER):
        return None

    addr = config.get('nvr')
    port = int(config.get('port', 7080))
    key = config.get('key')

    from uvcclient import nvr
    nvrconn = nvr.UVCRemote(addr, port, key)
    try:
        cameras = nvrconn.index()
    except nvr.NotAuthorized:
        _LOGGER.error('Authorization failure while connecting to NVR')
        return False
    except nvr.NvrError:
        _LOGGER.error('NVR refuses to talk to me')
        return False
    except requests.exceptions.ConnectionError as ex:
        _LOGGER.error('Unable to connect to NVR: %s', str(ex))
        return False

    for camera in cameras:
        add_devices([UnifiVideoCamera(nvrconn,
                                      camera['uuid'],
                                      camera['name'])])


class UnifiVideoCamera(Camera):
    """ A Ubiquiti Unifi Video Camera. """

    def __init__(self, nvr, uuid, name):
        super(UnifiVideoCamera, self).__init__()
        self._nvr = nvr
        self._uuid = uuid
        self._name = name
        self.is_streaming = False

    @property
    def name(self):
        return self._name

    @property
    def is_recording(self):
        caminfo = self._nvr.get_camera(self._uuid)
        return caminfo['recordingSettings']['fullTimeRecordEnabled']

    def camera_image(self):
        from uvcclient import camera as uvc_camera

        caminfo = self._nvr.get_camera(self._uuid)
        camera = None
        for addr in [caminfo['host'], caminfo['internalHost']]:
            try:
                camera = uvc_camera.UVCCameraClient(addr,
                                                    caminfo['username'],
                                                    'ubnt')
                _LOGGER.debug('Logged into UVC camera %(name)s via %(addr)s',
                              dict(name=self._name, addr=addr))
            except socket.error:
                pass
            except uvc_camera.CameraConnectError:
                pass
            except uvc_camera.CameraAuthError:
                pass

        if not camera:
            _LOGGER.error('Unable to login to camera')
            return None

        try:
            camera.login()
            return camera.get_snapshot()
        except uvc_camera.CameraConnectError:
            _LOGGER.error('Failed to connect to camera %s', self._name)

@@ -1740,24 +1740,86 @@
 ming = False
+%0A        self._connect_addr = None%0A        self._camera = None
 %0A%0A    @prope
@@ -2044,20 +2044,14 @@
 def 
-camera_image
+_login
 (sel
@@ -2105,17 +2105,16 @@
 _camera%0A
-%0A
         
@@ -2168,41 +2168,105 @@
     
-camera = None%0A        for
+if self._connect_addr:%0A            addrs = %5Bself._connect_addr%5D%0A        else:%0A           
  addr
- in
+s =
  %5Bca
@@ -2304,16 +2304,65 @@
 lHost'%5D%5D
+%0A%0A        camera = None%0A        for addr in addrs
 :%0A      
@@ -2563,16 +2563,47 @@
 'ubnt')%0A
+                camera.login()%0A
         
@@ -2736,16 +2736,58 @@
 =addr))%0A
+                self._connect_addr = addr%0A
         
@@ -2971,17 +2971,16 @@
    pass%0A
-%0A
         
@@ -3086,40 +3086,197 @@
     
-try:%0A            camera.
+self._camera = camera%0A        return True%0A%0A    def camera_image(self):%0A        from uvcclient import camera as uvc_camera%0A        if not self._camera:%0A            if not self._
 login()
-%0A
+:%0A    
     
@@ -3289,17 +3289,100 @@
   return
- 
+%0A%0A        def _get_image(retry=True):%0A            try:%0A                return self._
 camera.g
@@ -3395,16 +3395,20 @@
 pshot()%0A
+    
         
@@ -3449,32 +3449,36 @@
 or:%0A            
+    
 _LOGGER.error('F
@@ -3480,49 +3480,390 @@
 or('
-Fai
+Unab
 le
-d
  to con
-nect to camera %25s', self._name
+tact camera')%0A            except uvc_camera.CameraAuthError:%0A                if retry:%0A                    self._login()%0A                    return _get_image(retry=False)%0A                else:%0A                    _LOGGER.error('Unable to log into camera, unable '%0A                                  'to get snapshot')%0A                    raise%0A%0A        return _get_image(
 )%0A

Improve UVC performance by not logging in on each image fetch