commit
e29459a1ae
|
@ -12,7 +12,7 @@ import requests
|
|||
from homeassistant.components.camera import DOMAIN, Camera
|
||||
from homeassistant.helpers import validate_config
|
||||
|
||||
REQUIREMENTS = ['uvcclient==0.8']
|
||||
REQUIREMENTS = ['uvcclient==0.9.0']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -45,13 +45,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||
_LOGGER.error('Unable to connect to NVR: %s', str(ex))
|
||||
return False
|
||||
|
||||
identifier = nvrconn.server_version >= (3, 2, 0) and 'id' or 'uuid'
|
||||
# Filter out airCam models, which are not supported in the latest
|
||||
# version of UnifiVideo and which are EOL by Ubiquiti
|
||||
cameras = [camera for camera in cameras
|
||||
if 'airCam' not in nvrconn.get_camera(camera['uuid'])['model']]
|
||||
cameras = [
|
||||
camera for camera in cameras
|
||||
if 'airCam' not in nvrconn.get_camera(camera[identifier])['model']]
|
||||
|
||||
add_devices([UnifiVideoCamera(nvrconn,
|
||||
camera['uuid'],
|
||||
camera[identifier],
|
||||
camera['name'])
|
||||
for camera in cameras])
|
||||
return True
|
||||
|
@ -110,12 +112,17 @@ class UnifiVideoCamera(Camera):
|
|||
dict(name=self._name))
|
||||
password = 'ubnt'
|
||||
|
||||
if self._nvr.server_version >= (3, 2, 0):
|
||||
client_cls = uvc_camera.UVCCameraClientV320
|
||||
else:
|
||||
client_cls = uvc_camera.UVCCameraClient
|
||||
|
||||
camera = None
|
||||
for addr in addrs:
|
||||
try:
|
||||
camera = uvc_camera.UVCCameraClient(addr,
|
||||
caminfo['username'],
|
||||
password)
|
||||
camera = client_cls(addr,
|
||||
caminfo['username'],
|
||||
password)
|
||||
camera.login()
|
||||
_LOGGER.debug('Logged into UVC camera %(name)s via %(addr)s',
|
||||
dict(name=self._name, addr=addr))
|
||||
|
|
|
@ -375,7 +375,7 @@ unifi==1.2.5
|
|||
urllib3
|
||||
|
||||
# homeassistant.components.camera.uvc
|
||||
uvcclient==0.8
|
||||
uvcclient==0.9.0
|
||||
|
||||
# homeassistant.components.verisure
|
||||
vsure==0.8.1
|
||||
|
|
|
@ -23,14 +23,14 @@ class TestUVCSetup(unittest.TestCase):
|
|||
'key': 'secret',
|
||||
}
|
||||
fake_cameras = [
|
||||
{'uuid': 'one', 'name': 'Front'},
|
||||
{'uuid': 'two', 'name': 'Back'},
|
||||
{'uuid': 'three', 'name': 'Old AirCam'},
|
||||
{'uuid': 'one', 'name': 'Front', 'id': 'id1'},
|
||||
{'uuid': 'two', 'name': 'Back', 'id': 'id2'},
|
||||
{'uuid': 'three', 'name': 'Old AirCam', 'id': 'id3'},
|
||||
]
|
||||
|
||||
def fake_get_camera(uuid):
|
||||
""""Create a fake camera."""
|
||||
if uuid == 'three':
|
||||
if uuid == 'id3':
|
||||
return {'model': 'airCam'}
|
||||
else:
|
||||
return {'model': 'UVC'}
|
||||
|
@ -39,13 +39,14 @@ class TestUVCSetup(unittest.TestCase):
|
|||
add_devices = mock.MagicMock()
|
||||
mock_remote.return_value.index.return_value = fake_cameras
|
||||
mock_remote.return_value.get_camera.side_effect = fake_get_camera
|
||||
mock_remote.return_value.server_version = (3, 2, 0)
|
||||
self.assertTrue(uvc.setup_platform(hass, config, add_devices))
|
||||
mock_remote.assert_called_once_with('foo', 123, 'secret')
|
||||
add_devices.assert_called_once_with([
|
||||
mock_uvc.return_value, mock_uvc.return_value])
|
||||
mock_uvc.assert_has_calls([
|
||||
mock.call(mock_remote.return_value, 'one', 'Front'),
|
||||
mock.call(mock_remote.return_value, 'two', 'Back'),
|
||||
mock.call(mock_remote.return_value, 'id1', 'Front'),
|
||||
mock.call(mock_remote.return_value, 'id2', 'Back'),
|
||||
])
|
||||
|
||||
@mock.patch('uvcclient.nvr.UVCRemote')
|
||||
|
@ -57,13 +58,40 @@ class TestUVCSetup(unittest.TestCase):
|
|||
'key': 'secret',
|
||||
}
|
||||
fake_cameras = [
|
||||
{'uuid': 'one', 'name': 'Front'},
|
||||
{'uuid': 'two', 'name': 'Back'},
|
||||
{'uuid': 'one', 'name': 'Front', 'id': 'id1'},
|
||||
{'uuid': 'two', 'name': 'Back', 'id': 'id2'},
|
||||
]
|
||||
hass = mock.MagicMock()
|
||||
add_devices = mock.MagicMock()
|
||||
mock_remote.return_value.index.return_value = fake_cameras
|
||||
mock_remote.return_value.get_camera.return_value = {'model': 'UVC'}
|
||||
mock_remote.return_value.server_version = (3, 2, 0)
|
||||
self.assertTrue(uvc.setup_platform(hass, config, add_devices))
|
||||
mock_remote.assert_called_once_with('foo', 7080, 'secret')
|
||||
add_devices.assert_called_once_with([
|
||||
mock_uvc.return_value, mock_uvc.return_value])
|
||||
mock_uvc.assert_has_calls([
|
||||
mock.call(mock_remote.return_value, 'id1', 'Front'),
|
||||
mock.call(mock_remote.return_value, 'id2', 'Back'),
|
||||
])
|
||||
|
||||
@mock.patch('uvcclient.nvr.UVCRemote')
|
||||
@mock.patch.object(uvc, 'UnifiVideoCamera')
|
||||
def test_setup_partial_config_v31x(self, mock_uvc, mock_remote):
|
||||
"""Test the setup with a v3.1.x server."""
|
||||
config = {
|
||||
'nvr': 'foo',
|
||||
'key': 'secret',
|
||||
}
|
||||
fake_cameras = [
|
||||
{'uuid': 'one', 'name': 'Front', 'id': 'id1'},
|
||||
{'uuid': 'two', 'name': 'Back', 'id': 'id2'},
|
||||
]
|
||||
hass = mock.MagicMock()
|
||||
add_devices = mock.MagicMock()
|
||||
mock_remote.return_value.index.return_value = fake_cameras
|
||||
mock_remote.return_value.get_camera.return_value = {'model': 'UVC'}
|
||||
mock_remote.return_value.server_version = (3, 1, 3)
|
||||
self.assertTrue(uvc.setup_platform(hass, config, add_devices))
|
||||
mock_remote.assert_called_once_with('foo', 7080, 'secret')
|
||||
add_devices.assert_called_once_with([
|
||||
|
@ -114,6 +142,7 @@ class TestUVC(unittest.TestCase):
|
|||
'internalHost': 'host-b',
|
||||
'username': 'admin',
|
||||
}
|
||||
self.nvr.server_version = (3, 2, 0)
|
||||
|
||||
def test_properties(self):
|
||||
""""Test the properties."""
|
||||
|
@ -123,7 +152,7 @@ class TestUVC(unittest.TestCase):
|
|||
self.assertEqual('UVC Fake', self.uvc.model)
|
||||
|
||||
@mock.patch('uvcclient.store.get_info_store')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClient')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClientV320')
|
||||
def test_login(self, mock_camera, mock_store):
|
||||
""""Test the login."""
|
||||
mock_store.return_value.get_camera_password.return_value = 'seekret'
|
||||
|
@ -133,6 +162,16 @@ class TestUVC(unittest.TestCase):
|
|||
|
||||
@mock.patch('uvcclient.store.get_info_store')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClient')
|
||||
def test_login_v31x(self, mock_camera, mock_store):
|
||||
"""Test login with v3.1.x server."""
|
||||
mock_store.return_value.get_camera_password.return_value = 'seekret'
|
||||
self.nvr.server_version = (3, 1, 3)
|
||||
self.uvc._login()
|
||||
mock_camera.assert_called_once_with('host-a', 'admin', 'seekret')
|
||||
mock_camera.return_value.login.assert_called_once_with()
|
||||
|
||||
@mock.patch('uvcclient.store.get_info_store')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClientV320')
|
||||
def test_login_no_password(self, mock_camera, mock_store):
|
||||
""""Test the login with no password."""
|
||||
mock_store.return_value.get_camera_password.return_value = None
|
||||
|
@ -141,7 +180,7 @@ class TestUVC(unittest.TestCase):
|
|||
mock_camera.return_value.login.assert_called_once_with()
|
||||
|
||||
@mock.patch('uvcclient.store.get_info_store')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClient')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClientV320')
|
||||
def test_login_tries_both_addrs_and_caches(self, mock_camera, mock_store):
|
||||
""""Test the login tries."""
|
||||
responses = [0]
|
||||
|
@ -165,7 +204,7 @@ class TestUVC(unittest.TestCase):
|
|||
mock_camera.return_value.login.assert_called_once_with()
|
||||
|
||||
@mock.patch('uvcclient.store.get_info_store')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClient')
|
||||
@mock.patch('uvcclient.camera.UVCCameraClientV320')
|
||||
def test_login_fails_both_properly(self, mock_camera, mock_store):
|
||||
""""Test if login fails properly."""
|
||||
mock_camera.return_value.login.side_effect = socket.error
|
||||
|
|
Loading…
Reference in New Issue