mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 10:17:09 +00:00
Support configuring Axis to use HTTPS (#113271)
This commit is contained in:
parent
be7c4295dc
commit
5b5ff92a05
@ -25,6 +25,7 @@ from homeassistant.const import (
|
|||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
|
CONF_PROTOCOL,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
@ -42,7 +43,9 @@ from .errors import AuthenticationRequired, CannotConnect
|
|||||||
from .hub import AxisHub, get_axis_api
|
from .hub import AxisHub, get_axis_api
|
||||||
|
|
||||||
AXIS_OUI = {"00:40:8c", "ac:cc:8e", "b8:a4:4f"}
|
AXIS_OUI = {"00:40:8c", "ac:cc:8e", "b8:a4:4f"}
|
||||||
DEFAULT_PORT = 80
|
DEFAULT_PORT = 443
|
||||||
|
DEFAULT_PROTOCOL = "https"
|
||||||
|
PROTOCOL_CHOICES = ["https", "http"]
|
||||||
|
|
||||||
|
|
||||||
class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
||||||
@ -74,11 +77,19 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
|||||||
try:
|
try:
|
||||||
api = await get_axis_api(self.hass, MappingProxyType(user_input))
|
api = await get_axis_api(self.hass, MappingProxyType(user_input))
|
||||||
|
|
||||||
|
except AuthenticationRequired:
|
||||||
|
errors["base"] = "invalid_auth"
|
||||||
|
|
||||||
|
except CannotConnect:
|
||||||
|
errors["base"] = "cannot_connect"
|
||||||
|
|
||||||
|
else:
|
||||||
serial = api.vapix.serial_number
|
serial = api.vapix.serial_number
|
||||||
await self.async_set_unique_id(format_mac(serial))
|
await self.async_set_unique_id(format_mac(serial))
|
||||||
|
|
||||||
self._abort_if_unique_id_configured(
|
self._abort_if_unique_id_configured(
|
||||||
updates={
|
updates={
|
||||||
|
CONF_PROTOCOL: user_input[CONF_PROTOCOL],
|
||||||
CONF_HOST: user_input[CONF_HOST],
|
CONF_HOST: user_input[CONF_HOST],
|
||||||
CONF_PORT: user_input[CONF_PORT],
|
CONF_PORT: user_input[CONF_PORT],
|
||||||
CONF_USERNAME: user_input[CONF_USERNAME],
|
CONF_USERNAME: user_input[CONF_USERNAME],
|
||||||
@ -87,6 +98,7 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.config = {
|
self.config = {
|
||||||
|
CONF_PROTOCOL: user_input[CONF_PROTOCOL],
|
||||||
CONF_HOST: user_input[CONF_HOST],
|
CONF_HOST: user_input[CONF_HOST],
|
||||||
CONF_PORT: user_input[CONF_PORT],
|
CONF_PORT: user_input[CONF_PORT],
|
||||||
CONF_USERNAME: user_input[CONF_USERNAME],
|
CONF_USERNAME: user_input[CONF_USERNAME],
|
||||||
@ -96,13 +108,8 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
|||||||
|
|
||||||
return await self._create_entry(serial)
|
return await self._create_entry(serial)
|
||||||
|
|
||||||
except AuthenticationRequired:
|
|
||||||
errors["base"] = "invalid_auth"
|
|
||||||
|
|
||||||
except CannotConnect:
|
|
||||||
errors["base"] = "cannot_connect"
|
|
||||||
|
|
||||||
data = self.discovery_schema or {
|
data = self.discovery_schema or {
|
||||||
|
vol.Required(CONF_PROTOCOL): vol.In(PROTOCOL_CHOICES),
|
||||||
vol.Required(CONF_HOST): str,
|
vol.Required(CONF_HOST): str,
|
||||||
vol.Required(CONF_USERNAME): str,
|
vol.Required(CONF_USERNAME): str,
|
||||||
vol.Required(CONF_PASSWORD): str,
|
vol.Required(CONF_PASSWORD): str,
|
||||||
@ -149,6 +156,9 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.discovery_schema = {
|
self.discovery_schema = {
|
||||||
|
vol.Required(
|
||||||
|
CONF_PROTOCOL, default=entry_data.get(CONF_PROTOCOL, DEFAULT_PROTOCOL)
|
||||||
|
): str,
|
||||||
vol.Required(CONF_HOST, default=entry_data[CONF_HOST]): str,
|
vol.Required(CONF_HOST, default=entry_data[CONF_HOST]): str,
|
||||||
vol.Required(CONF_USERNAME, default=entry_data[CONF_USERNAME]): str,
|
vol.Required(CONF_USERNAME, default=entry_data[CONF_USERNAME]): str,
|
||||||
vol.Required(CONF_PASSWORD): str,
|
vol.Required(CONF_PASSWORD): str,
|
||||||
@ -166,7 +176,7 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
|||||||
CONF_HOST: discovery_info.ip,
|
CONF_HOST: discovery_info.ip,
|
||||||
CONF_MAC: format_mac(discovery_info.macaddress),
|
CONF_MAC: format_mac(discovery_info.macaddress),
|
||||||
CONF_NAME: discovery_info.hostname,
|
CONF_NAME: discovery_info.hostname,
|
||||||
CONF_PORT: DEFAULT_PORT,
|
CONF_PORT: 80,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -210,10 +220,7 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
|||||||
await self.async_set_unique_id(discovery_info[CONF_MAC])
|
await self.async_set_unique_id(discovery_info[CONF_MAC])
|
||||||
|
|
||||||
self._abort_if_unique_id_configured(
|
self._abort_if_unique_id_configured(
|
||||||
updates={
|
updates={CONF_HOST: discovery_info[CONF_HOST]}
|
||||||
CONF_HOST: discovery_info[CONF_HOST],
|
|
||||||
CONF_PORT: discovery_info[CONF_PORT],
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
self.context.update(
|
self.context.update(
|
||||||
@ -227,10 +234,11 @@ class AxisFlowHandler(ConfigFlow, domain=AXIS_DOMAIN):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.discovery_schema = {
|
self.discovery_schema = {
|
||||||
|
vol.Required(CONF_PROTOCOL): vol.In(PROTOCOL_CHOICES),
|
||||||
vol.Required(CONF_HOST, default=discovery_info[CONF_HOST]): str,
|
vol.Required(CONF_HOST, default=discovery_info[CONF_HOST]): str,
|
||||||
vol.Required(CONF_USERNAME): str,
|
vol.Required(CONF_USERNAME): str,
|
||||||
vol.Required(CONF_PASSWORD): str,
|
vol.Required(CONF_PASSWORD): str,
|
||||||
vol.Required(CONF_PORT, default=discovery_info[CONF_PORT]): int,
|
vol.Required(CONF_PORT, default=DEFAULT_PORT): int,
|
||||||
}
|
}
|
||||||
|
|
||||||
return await self.async_step_user()
|
return await self.async_step_user()
|
||||||
|
@ -7,7 +7,13 @@ from typing import Any
|
|||||||
import axis
|
import axis
|
||||||
from axis.configuration import Configuration
|
from axis.configuration import Configuration
|
||||||
|
|
||||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME
|
from homeassistant.const import (
|
||||||
|
CONF_HOST,
|
||||||
|
CONF_PASSWORD,
|
||||||
|
CONF_PORT,
|
||||||
|
CONF_PROTOCOL,
|
||||||
|
CONF_USERNAME,
|
||||||
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.httpx_client import get_async_client
|
from homeassistant.helpers.httpx_client import get_async_client
|
||||||
|
|
||||||
@ -29,6 +35,7 @@ async def get_axis_api(
|
|||||||
port=config[CONF_PORT],
|
port=config[CONF_PORT],
|
||||||
username=config[CONF_USERNAME],
|
username=config[CONF_USERNAME],
|
||||||
password=config[CONF_PASSWORD],
|
password=config[CONF_PASSWORD],
|
||||||
|
web_proto=config.get(CONF_PROTOCOL, "http"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from homeassistant.const import (
|
|||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
|
CONF_PROTOCOL,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -65,6 +66,7 @@ async def test_flow_manual_configuration(
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -75,6 +77,7 @@ async def test_flow_manual_configuration(
|
|||||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == f"M1065-LW - {MAC}"
|
assert result["title"] == f"M1065-LW - {MAC}"
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -101,6 +104,7 @@ async def test_manual_configuration_update_configuration(
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "2.3.4.5",
|
CONF_HOST: "2.3.4.5",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -130,6 +134,7 @@ async def test_flow_fails_faulty_credentials(hass: HomeAssistant) -> None:
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -156,6 +161,7 @@ async def test_flow_fails_cannot_connect(hass: HomeAssistant) -> None:
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -191,6 +197,7 @@ async def test_flow_create_entry_multiple_existing_entries_of_same_model(
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -201,6 +208,7 @@ async def test_flow_create_entry_multiple_existing_entries_of_same_model(
|
|||||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == f"M1065-LW - {MAC}"
|
assert result["title"] == f"M1065-LW - {MAC}"
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -233,17 +241,20 @@ async def test_reauth_flow_update_configuration(
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
CONF_PROTOCOL: "https",
|
||||||
CONF_HOST: "2.3.4.5",
|
CONF_HOST: "2.3.4.5",
|
||||||
CONF_USERNAME: "user2",
|
CONF_USERNAME: "user2",
|
||||||
CONF_PASSWORD: "pass2",
|
CONF_PASSWORD: "pass2",
|
||||||
CONF_PORT: 80,
|
CONF_PORT: 443,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result["type"] == FlowResultType.ABORT
|
assert result["type"] == FlowResultType.ABORT
|
||||||
assert result["reason"] == "already_configured"
|
assert result["reason"] == "already_configured"
|
||||||
|
assert mock_config_entry.data[CONF_PROTOCOL] == "https"
|
||||||
assert mock_config_entry.data[CONF_HOST] == "2.3.4.5"
|
assert mock_config_entry.data[CONF_HOST] == "2.3.4.5"
|
||||||
|
assert mock_config_entry.data[CONF_PORT] == 443
|
||||||
assert mock_config_entry.data[CONF_USERNAME] == "user2"
|
assert mock_config_entry.data[CONF_USERNAME] == "user2"
|
||||||
assert mock_config_entry.data[CONF_PASSWORD] == "pass2"
|
assert mock_config_entry.data[CONF_PASSWORD] == "pass2"
|
||||||
|
|
||||||
@ -334,6 +345,7 @@ async def test_discovery_flow(
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -344,6 +356,7 @@ async def test_discovery_flow(
|
|||||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
assert result["title"] == f"M1065-LW - {MAC}"
|
assert result["title"] == f"M1065-LW - {MAC}"
|
||||||
assert result["data"] == {
|
assert result["data"] == {
|
||||||
|
CONF_PROTOCOL: "http",
|
||||||
CONF_HOST: "1.2.3.4",
|
CONF_HOST: "1.2.3.4",
|
||||||
CONF_USERNAME: "user",
|
CONF_USERNAME: "user",
|
||||||
CONF_PASSWORD: "pass",
|
CONF_PASSWORD: "pass",
|
||||||
@ -430,7 +443,7 @@ async def test_discovered_device_already_configured(
|
|||||||
"presentationURL": "http://2.3.4.5:8080/",
|
"presentationURL": "http://2.3.4.5:8080/",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
8080,
|
80,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
SOURCE_ZEROCONF,
|
SOURCE_ZEROCONF,
|
||||||
@ -443,7 +456,7 @@ async def test_discovered_device_already_configured(
|
|||||||
properties={"macaddress": MAC},
|
properties={"macaddress": MAC},
|
||||||
type="mock_type",
|
type="mock_type",
|
||||||
),
|
),
|
||||||
8080,
|
80,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user