mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
Axis - improved internal parameter handling (#23122)
Will result in faster startup per entry due to less network data
This commit is contained in:
parent
e7102eaf30
commit
a45df7aac9
@ -64,12 +64,9 @@ async def async_unload_entry(hass, config_entry):
|
|||||||
|
|
||||||
async def async_populate_options(hass, config_entry):
|
async def async_populate_options(hass, config_entry):
|
||||||
"""Populate default options for device."""
|
"""Populate default options for device."""
|
||||||
from axis.vapix import VAPIX_IMAGE_FORMAT
|
|
||||||
|
|
||||||
device = await get_device(hass, config_entry.data[CONF_DEVICE])
|
device = await get_device(hass, config_entry.data[CONF_DEVICE])
|
||||||
|
|
||||||
supported_formats = device.vapix.get_param(VAPIX_IMAGE_FORMAT)
|
supported_formats = device.vapix.params.image_format
|
||||||
|
|
||||||
camera = bool(supported_formats)
|
camera = bool(supported_formats)
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
|
@ -66,7 +66,6 @@ class AxisFlowHandler(config_entries.ConfigFlow):
|
|||||||
|
|
||||||
Manage device specific parameters.
|
Manage device specific parameters.
|
||||||
"""
|
"""
|
||||||
from axis.vapix import VAPIX_MODEL_ID, VAPIX_SERIAL_NUMBER
|
|
||||||
errors = {}
|
errors = {}
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
@ -79,13 +78,12 @@ class AxisFlowHandler(config_entries.ConfigFlow):
|
|||||||
}
|
}
|
||||||
device = await get_device(self.hass, self.device_config)
|
device = await get_device(self.hass, self.device_config)
|
||||||
|
|
||||||
self.serial_number = device.vapix.get_param(
|
self.serial_number = device.vapix.params.system_serialnumber
|
||||||
VAPIX_SERIAL_NUMBER)
|
|
||||||
|
|
||||||
if self.serial_number in configured_devices(self.hass):
|
if self.serial_number in configured_devices(self.hass):
|
||||||
raise AlreadyConfigured
|
raise AlreadyConfigured
|
||||||
|
|
||||||
self.model = device.vapix.get_param(VAPIX_MODEL_ID)
|
self.model = device.vapix.params.prodnbr
|
||||||
|
|
||||||
return await self._create_entry()
|
return await self._create_entry()
|
||||||
|
|
||||||
|
@ -67,13 +67,9 @@ class AxisNetworkDevice:
|
|||||||
|
|
||||||
async def async_setup(self):
|
async def async_setup(self):
|
||||||
"""Set up the device."""
|
"""Set up the device."""
|
||||||
from axis.vapix import VAPIX_FW_VERSION, VAPIX_PROD_TYPE
|
|
||||||
|
|
||||||
hass = self.hass
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.api = await get_device(
|
self.api = await get_device(
|
||||||
hass, self.config_entry.data[CONF_DEVICE])
|
self.hass, self.config_entry.data[CONF_DEVICE])
|
||||||
|
|
||||||
except CannotConnect:
|
except CannotConnect:
|
||||||
raise ConfigEntryNotReady
|
raise ConfigEntryNotReady
|
||||||
@ -83,8 +79,8 @@ class AxisNetworkDevice:
|
|||||||
'Unknown error connecting with Axis device on %s', self.host)
|
'Unknown error connecting with Axis device on %s', self.host)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.fw_version = self.api.vapix.get_param(VAPIX_FW_VERSION)
|
self.fw_version = self.api.vapix.params.firmware_version
|
||||||
self.product_type = self.api.vapix.get_param(VAPIX_PROD_TYPE)
|
self.product_type = self.api.vapix.params.prodtype
|
||||||
|
|
||||||
if self.config_entry.options[CONF_CAMERA]:
|
if self.config_entry.options[CONF_CAMERA]:
|
||||||
self.hass.async_create_task(
|
self.hass.async_create_task(
|
||||||
@ -188,9 +184,14 @@ async def get_device(hass, config):
|
|||||||
password=config[CONF_PASSWORD],
|
password=config[CONF_PASSWORD],
|
||||||
port=config[CONF_PORT], web_proto='http')
|
port=config[CONF_PORT], web_proto='http')
|
||||||
|
|
||||||
|
device.vapix.initialize_params(preload_data=False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with async_timeout.timeout(15):
|
with async_timeout.timeout(15):
|
||||||
await hass.async_add_executor_job(device.vapix.load_params)
|
await hass.async_add_executor_job(
|
||||||
|
device.vapix.params.update_brand)
|
||||||
|
await hass.async_add_executor_job(
|
||||||
|
device.vapix.params.update_properties)
|
||||||
return device
|
return device
|
||||||
|
|
||||||
except axis.Unauthorized:
|
except axis.Unauthorized:
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"domain": "axis",
|
"domain": "axis",
|
||||||
"name": "Axis",
|
"name": "Axis",
|
||||||
"documentation": "https://www.home-assistant.io/components/axis",
|
"documentation": "https://www.home-assistant.io/components/axis",
|
||||||
"requirements": [
|
"requirements": ["axis==21"],
|
||||||
"axis==20"
|
|
||||||
],
|
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": [
|
"codeowners": ["@kane610"]
|
||||||
"@kane610"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ av==6.1.2
|
|||||||
# avion==0.10
|
# avion==0.10
|
||||||
|
|
||||||
# homeassistant.components.axis
|
# homeassistant.components.axis
|
||||||
axis==20
|
axis==21
|
||||||
|
|
||||||
# homeassistant.components.baidu
|
# homeassistant.components.baidu
|
||||||
baidu-aip==1.6.6
|
baidu-aip==1.6.6
|
||||||
|
@ -61,7 +61,7 @@ apns2==0.3.0
|
|||||||
av==6.1.2
|
av==6.1.2
|
||||||
|
|
||||||
# homeassistant.components.axis
|
# homeassistant.components.axis
|
||||||
axis==20
|
axis==21
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
bellows-homeassistant==0.7.2
|
bellows-homeassistant==0.7.2
|
||||||
|
@ -6,8 +6,6 @@ from homeassistant.components.axis import config_flow
|
|||||||
|
|
||||||
from tests.common import mock_coro, MockConfigEntry
|
from tests.common import mock_coro, MockConfigEntry
|
||||||
|
|
||||||
import axis as axis_lib
|
|
||||||
|
|
||||||
|
|
||||||
async def test_configured_devices(hass):
|
async def test_configured_devices(hass):
|
||||||
"""Test that configured devices works as expected."""
|
"""Test that configured devices works as expected."""
|
||||||
@ -37,13 +35,9 @@ async def test_flow_works(hass):
|
|||||||
mock_device.port = port
|
mock_device.port = port
|
||||||
return mock_device
|
return mock_device
|
||||||
|
|
||||||
def mock_get_param(param):
|
|
||||||
"""Fake get param method."""
|
|
||||||
return param
|
|
||||||
|
|
||||||
mock_device.side_effect = mock_constructor
|
mock_device.side_effect = mock_constructor
|
||||||
mock_device.vapix.load_params.return_value = Mock()
|
mock_device.vapix.params.system_serialnumber = 'serialnumber'
|
||||||
mock_device.vapix.get_param.side_effect = mock_get_param
|
mock_device.vapix.params.prodnbr = 'prodnbr'
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
config_flow.DOMAIN,
|
config_flow.DOMAIN,
|
||||||
@ -59,23 +53,22 @@ async def test_flow_works(hass):
|
|||||||
config_flow.CONF_HOST: '1.2.3.4',
|
config_flow.CONF_HOST: '1.2.3.4',
|
||||||
config_flow.CONF_USERNAME: 'user',
|
config_flow.CONF_USERNAME: 'user',
|
||||||
config_flow.CONF_PASSWORD: 'pass',
|
config_flow.CONF_PASSWORD: 'pass',
|
||||||
config_flow.CONF_PORT: 81
|
config_flow.CONF_PORT: 80
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result['type'] == 'create_entry'
|
assert result['type'] == 'create_entry'
|
||||||
assert result['title'] == '{} - {}'.format(
|
assert result['title'] == '{} - {}'.format('prodnbr', 'serialnumber')
|
||||||
axis_lib.vapix.VAPIX_MODEL_ID, axis_lib.vapix.VAPIX_SERIAL_NUMBER)
|
|
||||||
assert result['data'] == {
|
assert result['data'] == {
|
||||||
axis.CONF_DEVICE: {
|
axis.CONF_DEVICE: {
|
||||||
config_flow.CONF_HOST: '1.2.3.4',
|
config_flow.CONF_HOST: '1.2.3.4',
|
||||||
config_flow.CONF_USERNAME: 'user',
|
config_flow.CONF_USERNAME: 'user',
|
||||||
config_flow.CONF_PASSWORD: 'pass',
|
config_flow.CONF_PASSWORD: 'pass',
|
||||||
config_flow.CONF_PORT: 81
|
config_flow.CONF_PORT: 80
|
||||||
},
|
},
|
||||||
config_flow.CONF_MAC: axis_lib.vapix.VAPIX_SERIAL_NUMBER,
|
config_flow.CONF_MAC: 'serialnumber',
|
||||||
config_flow.CONF_MODEL: axis_lib.vapix.VAPIX_MODEL_ID,
|
config_flow.CONF_MODEL: 'prodnbr',
|
||||||
config_flow.CONF_NAME: 'Brand.ProdNbr 0'
|
config_flow.CONF_NAME: 'prodnbr 0'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -89,7 +82,7 @@ async def test_flow_fails_already_configured(hass):
|
|||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
mock_device = Mock()
|
mock_device = Mock()
|
||||||
mock_device.vapix.get_param.return_value = '1234'
|
mock_device.vapix.params.system_serialnumber = '1234'
|
||||||
|
|
||||||
with patch('homeassistant.components.axis.config_flow.get_device',
|
with patch('homeassistant.components.axis.config_flow.get_device',
|
||||||
return_value=mock_coro(mock_device)):
|
return_value=mock_coro(mock_device)):
|
||||||
@ -97,7 +90,7 @@ async def test_flow_fails_already_configured(hass):
|
|||||||
config_flow.CONF_HOST: '1.2.3.4',
|
config_flow.CONF_HOST: '1.2.3.4',
|
||||||
config_flow.CONF_USERNAME: 'user',
|
config_flow.CONF_USERNAME: 'user',
|
||||||
config_flow.CONF_PASSWORD: 'pass',
|
config_flow.CONF_PASSWORD: 'pass',
|
||||||
config_flow.CONF_PORT: 81
|
config_flow.CONF_PORT: 80
|
||||||
})
|
})
|
||||||
|
|
||||||
assert result['errors'] == {'base': 'already_configured'}
|
assert result['errors'] == {'base': 'already_configured'}
|
||||||
@ -114,7 +107,7 @@ async def test_flow_fails_faulty_credentials(hass):
|
|||||||
config_flow.CONF_HOST: '1.2.3.4',
|
config_flow.CONF_HOST: '1.2.3.4',
|
||||||
config_flow.CONF_USERNAME: 'user',
|
config_flow.CONF_USERNAME: 'user',
|
||||||
config_flow.CONF_PASSWORD: 'pass',
|
config_flow.CONF_PASSWORD: 'pass',
|
||||||
config_flow.CONF_PORT: 81
|
config_flow.CONF_PORT: 80
|
||||||
})
|
})
|
||||||
|
|
||||||
assert result['errors'] == {'base': 'faulty_credentials'}
|
assert result['errors'] == {'base': 'faulty_credentials'}
|
||||||
@ -131,7 +124,7 @@ async def test_flow_fails_device_unavailable(hass):
|
|||||||
config_flow.CONF_HOST: '1.2.3.4',
|
config_flow.CONF_HOST: '1.2.3.4',
|
||||||
config_flow.CONF_USERNAME: 'user',
|
config_flow.CONF_USERNAME: 'user',
|
||||||
config_flow.CONF_PASSWORD: 'pass',
|
config_flow.CONF_PASSWORD: 'pass',
|
||||||
config_flow.CONF_PORT: 81
|
config_flow.CONF_PORT: 80
|
||||||
})
|
})
|
||||||
|
|
||||||
assert result['errors'] == {'base': 'device_unavailable'}
|
assert result['errors'] == {'base': 'device_unavailable'}
|
||||||
@ -207,13 +200,7 @@ async def test_discovery_flow_known_device(hass):
|
|||||||
mock_device.port = port
|
mock_device.port = port
|
||||||
return mock_device
|
return mock_device
|
||||||
|
|
||||||
def mock_get_param(param):
|
|
||||||
"""Fake get param method."""
|
|
||||||
return param
|
|
||||||
|
|
||||||
mock_device.side_effect = mock_constructor
|
mock_device.side_effect = mock_constructor
|
||||||
mock_device.vapix.load_params.return_value = Mock()
|
|
||||||
mock_device.vapix.get_param.side_effect = mock_get_param
|
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
config_flow.DOMAIN,
|
config_flow.DOMAIN,
|
||||||
@ -303,13 +290,9 @@ async def test_import_flow_works(hass):
|
|||||||
mock_device.port = port
|
mock_device.port = port
|
||||||
return mock_device
|
return mock_device
|
||||||
|
|
||||||
def mock_get_param(param):
|
|
||||||
"""Fake get param method."""
|
|
||||||
return param
|
|
||||||
|
|
||||||
mock_device.side_effect = mock_constructor
|
mock_device.side_effect = mock_constructor
|
||||||
mock_device.vapix.load_params.return_value = Mock()
|
mock_device.vapix.params.system_serialnumber = 'serialnumber'
|
||||||
mock_device.vapix.get_param.side_effect = mock_get_param
|
mock_device.vapix.params.prodnbr = 'prodnbr'
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
config_flow.DOMAIN,
|
config_flow.DOMAIN,
|
||||||
@ -324,8 +307,7 @@ async def test_import_flow_works(hass):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert result['type'] == 'create_entry'
|
assert result['type'] == 'create_entry'
|
||||||
assert result['title'] == '{} - {}'.format(
|
assert result['title'] == '{} - {}'.format('prodnbr', 'serialnumber')
|
||||||
axis_lib.vapix.VAPIX_MODEL_ID, axis_lib.vapix.VAPIX_SERIAL_NUMBER)
|
|
||||||
assert result['data'] == {
|
assert result['data'] == {
|
||||||
axis.CONF_DEVICE: {
|
axis.CONF_DEVICE: {
|
||||||
config_flow.CONF_HOST: '1.2.3.4',
|
config_flow.CONF_HOST: '1.2.3.4',
|
||||||
@ -333,7 +315,7 @@ async def test_import_flow_works(hass):
|
|||||||
config_flow.CONF_PASSWORD: 'pass',
|
config_flow.CONF_PASSWORD: 'pass',
|
||||||
config_flow.CONF_PORT: 80
|
config_flow.CONF_PORT: 80
|
||||||
},
|
},
|
||||||
config_flow.CONF_MAC: axis_lib.vapix.VAPIX_SERIAL_NUMBER,
|
config_flow.CONF_MAC: 'serialnumber',
|
||||||
config_flow.CONF_MODEL: axis_lib.vapix.VAPIX_MODEL_ID,
|
config_flow.CONF_MODEL: 'prodnbr',
|
||||||
config_flow.CONF_NAME: 'name'
|
config_flow.CONF_NAME: 'name'
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,9 @@ async def test_shutdown():
|
|||||||
|
|
||||||
async def test_get_device(hass):
|
async def test_get_device(hass):
|
||||||
"""Successful call."""
|
"""Successful call."""
|
||||||
with patch('axis.vapix.Vapix.load_params',
|
with patch('axis.param_cgi.Params.update_brand',
|
||||||
|
return_value=mock_coro()), \
|
||||||
|
patch('axis.param_cgi.Params.update_properties',
|
||||||
return_value=mock_coro()):
|
return_value=mock_coro()):
|
||||||
assert await device.get_device(hass, DEVICE_DATA)
|
assert await device.get_device(hass, DEVICE_DATA)
|
||||||
|
|
||||||
@ -199,7 +201,7 @@ async def test_get_device_fails(hass):
|
|||||||
"""Device unauthorized yields authentication required error."""
|
"""Device unauthorized yields authentication required error."""
|
||||||
import axis
|
import axis
|
||||||
|
|
||||||
with patch('axis.vapix.Vapix.load_params',
|
with patch('axis.param_cgi.Params.update_brand',
|
||||||
side_effect=axis.Unauthorized), \
|
side_effect=axis.Unauthorized), \
|
||||||
pytest.raises(errors.AuthenticationRequired):
|
pytest.raises(errors.AuthenticationRequired):
|
||||||
await device.get_device(hass, DEVICE_DATA)
|
await device.get_device(hass, DEVICE_DATA)
|
||||||
@ -209,7 +211,7 @@ async def test_get_device_device_unavailable(hass):
|
|||||||
"""Device unavailable yields cannot connect error."""
|
"""Device unavailable yields cannot connect error."""
|
||||||
import axis
|
import axis
|
||||||
|
|
||||||
with patch('axis.vapix.Vapix.load_params',
|
with patch('axis.param_cgi.Params.update_brand',
|
||||||
side_effect=axis.RequestError), \
|
side_effect=axis.RequestError), \
|
||||||
pytest.raises(errors.CannotConnect):
|
pytest.raises(errors.CannotConnect):
|
||||||
await device.get_device(hass, DEVICE_DATA)
|
await device.get_device(hass, DEVICE_DATA)
|
||||||
@ -219,7 +221,7 @@ async def test_get_device_unknown_error(hass):
|
|||||||
"""Device yield unknown error."""
|
"""Device yield unknown error."""
|
||||||
import axis
|
import axis
|
||||||
|
|
||||||
with patch('axis.vapix.Vapix.load_params',
|
with patch('axis.param_cgi.Params.update_brand',
|
||||||
side_effect=axis.AxisException), \
|
side_effect=axis.AxisException), \
|
||||||
pytest.raises(errors.AuthenticationRequired):
|
pytest.raises(errors.AuthenticationRequired):
|
||||||
await device.get_device(hass, DEVICE_DATA)
|
await device.get_device(hass, DEVICE_DATA)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user