mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 16:27:08 +00:00
Add option to specify Reolink Basic Service Port (#137603)
* Allow changing the baichuan port * styling * Add description * Add tests * Review feedback * capital letters Co-authored-by: Robert Resch <robert@resch.dev> --------- Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
parent
8a552aef9d
commit
b5fa3e74c0
@ -28,7 +28,7 @@ from homeassistant.helpers.event import async_call_later
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import CONF_SUPPORTS_PRIVACY_MODE, CONF_USE_HTTPS, DOMAIN
|
||||
from .const import CONF_BC_PORT, CONF_SUPPORTS_PRIVACY_MODE, CONF_USE_HTTPS, DOMAIN
|
||||
from .exceptions import PasswordIncompatible, ReolinkException, UserNotAdmin
|
||||
from .host import ReolinkHost
|
||||
from .services import async_setup_services
|
||||
@ -100,6 +100,7 @@ async def async_setup_entry(
|
||||
or host.api.use_https != config_entry.data[CONF_USE_HTTPS]
|
||||
or host.api.supported(None, "privacy_mode")
|
||||
!= config_entry.data.get(CONF_SUPPORTS_PRIVACY_MODE)
|
||||
or host.api.baichuan.port != config_entry.data.get(CONF_BC_PORT)
|
||||
):
|
||||
if host.api.port != config_entry.data[CONF_PORT]:
|
||||
_LOGGER.warning(
|
||||
@ -108,10 +109,21 @@ async def async_setup_entry(
|
||||
config_entry.data[CONF_PORT],
|
||||
host.api.port,
|
||||
)
|
||||
if (
|
||||
config_entry.data.get(CONF_BC_PORT, host.api.baichuan.port)
|
||||
!= host.api.baichuan.port
|
||||
):
|
||||
_LOGGER.warning(
|
||||
"Baichuan port of Reolink %s, changed from %s to %s",
|
||||
host.api.nvr_name,
|
||||
config_entry.data.get(CONF_BC_PORT),
|
||||
host.api.baichuan.port,
|
||||
)
|
||||
data = {
|
||||
**config_entry.data,
|
||||
CONF_PORT: host.api.port,
|
||||
CONF_USE_HTTPS: host.api.use_https,
|
||||
CONF_BC_PORT: host.api.baichuan.port,
|
||||
CONF_SUPPORTS_PRIVACY_MODE: host.api.supported(None, "privacy_mode"),
|
||||
}
|
||||
hass.config_entries.async_update_entry(config_entry, data=data)
|
||||
|
@ -8,6 +8,7 @@ import logging
|
||||
from typing import Any
|
||||
|
||||
from reolink_aio.api import ALLOWED_SPECIAL_CHARS
|
||||
from reolink_aio.baichuan import DEFAULT_BC_PORT
|
||||
from reolink_aio.exceptions import (
|
||||
ApiError,
|
||||
CredentialsInvalidError,
|
||||
@ -37,7 +38,7 @@ from homeassistant.helpers import config_validation as cv, selector
|
||||
from homeassistant.helpers.device_registry import format_mac
|
||||
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||
|
||||
from .const import CONF_SUPPORTS_PRIVACY_MODE, CONF_USE_HTTPS, DOMAIN
|
||||
from .const import CONF_BC_PORT, CONF_SUPPORTS_PRIVACY_MODE, CONF_USE_HTTPS, DOMAIN
|
||||
from .exceptions import (
|
||||
PasswordIncompatible,
|
||||
ReolinkException,
|
||||
@ -287,6 +288,7 @@ class ReolinkFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
if not errors:
|
||||
user_input[CONF_PORT] = host.api.port
|
||||
user_input[CONF_USE_HTTPS] = host.api.use_https
|
||||
user_input[CONF_BC_PORT] = host.api.baichuan.port
|
||||
user_input[CONF_SUPPORTS_PRIVACY_MODE] = host.api.supported(
|
||||
None, "privacy_mode"
|
||||
)
|
||||
@ -326,8 +328,9 @@ class ReolinkFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
if errors:
|
||||
data_schema = data_schema.extend(
|
||||
{
|
||||
vol.Optional(CONF_PORT): cv.positive_int,
|
||||
vol.Optional(CONF_PORT): cv.port,
|
||||
vol.Required(CONF_USE_HTTPS, default=False): bool,
|
||||
vol.Required(CONF_BC_PORT, default=DEFAULT_BC_PORT): cv.port,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -3,4 +3,5 @@
|
||||
DOMAIN = "reolink"
|
||||
|
||||
CONF_USE_HTTPS = "use_https"
|
||||
CONF_BC_PORT = "baichuan_port"
|
||||
CONF_SUPPORTS_PRIVACY_MODE = "privacy_mode_supported"
|
||||
|
@ -12,6 +12,7 @@ from typing import Any, Literal
|
||||
import aiohttp
|
||||
from aiohttp.web import Request
|
||||
from reolink_aio.api import ALLOWED_SPECIAL_CHARS, Host
|
||||
from reolink_aio.baichuan import DEFAULT_BC_PORT
|
||||
from reolink_aio.enums import SubType
|
||||
from reolink_aio.exceptions import NotSupportedError, ReolinkError, SubscriptionError
|
||||
|
||||
@ -33,7 +34,7 @@ from homeassistant.helpers.network import NoURLAvailableError, get_url
|
||||
from homeassistant.helpers.storage import Store
|
||||
from homeassistant.util.ssl import SSLCipherList
|
||||
|
||||
from .const import CONF_SUPPORTS_PRIVACY_MODE, CONF_USE_HTTPS, DOMAIN
|
||||
from .const import CONF_BC_PORT, CONF_SUPPORTS_PRIVACY_MODE, CONF_USE_HTTPS, DOMAIN
|
||||
from .exceptions import (
|
||||
PasswordIncompatible,
|
||||
ReolinkSetupException,
|
||||
@ -91,6 +92,7 @@ class ReolinkHost:
|
||||
protocol=options[CONF_PROTOCOL],
|
||||
timeout=DEFAULT_TIMEOUT,
|
||||
aiohttp_get_session_callback=get_aiohttp_session,
|
||||
bc_port=config.get(CONF_BC_PORT, DEFAULT_BC_PORT),
|
||||
)
|
||||
|
||||
self.last_wake: float = 0
|
||||
|
@ -8,13 +8,15 @@
|
||||
"host": "[%key:common::config_flow::data::host%]",
|
||||
"port": "[%key:common::config_flow::data::port%]",
|
||||
"use_https": "Enable HTTPS",
|
||||
"baichuan_port": "Basic service port",
|
||||
"username": "[%key:common::config_flow::data::username%]",
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
},
|
||||
"data_description": {
|
||||
"host": "The hostname or IP address of your Reolink device. For example: '192.168.1.25'.",
|
||||
"port": "The port to connect to the Reolink device. For HTTP normally: '80', for HTTPS normally '443'.",
|
||||
"port": "The HTTP(s) port to connect to the Reolink device API. For HTTP normally: '80', for HTTPS normally '443'.",
|
||||
"use_https": "Use a HTTPS (SSL) connection to the Reolink device.",
|
||||
"baichuan_port": "The 'Basic Service Port' to connect to the Reolink device over TCP. Normally '9000' unless manually changed in the Reolink desktop client.",
|
||||
"username": "Username to login to the Reolink device itself. Not the Reolink cloud account.",
|
||||
"password": "Password to login to the Reolink device itself. Not the Reolink cloud account."
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ from reolink_aio.exceptions import ReolinkError
|
||||
|
||||
from homeassistant.components.reolink.config_flow import DEFAULT_PROTOCOL
|
||||
from homeassistant.components.reolink.const import (
|
||||
CONF_BC_PORT,
|
||||
CONF_SUPPORTS_PRIVACY_MODE,
|
||||
CONF_USE_HTTPS,
|
||||
DOMAIN,
|
||||
@ -48,6 +49,7 @@ TEST_ITEM_NUMBER = "P000"
|
||||
TEST_CAM_MODEL = "RLC-123"
|
||||
TEST_DUO_MODEL = "Reolink Duo PoE"
|
||||
TEST_PRIVACY = True
|
||||
TEST_BC_PORT = 5678
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -136,6 +138,7 @@ def reolink_connect_class() -> Generator[MagicMock]:
|
||||
# Baichuan
|
||||
host_mock.baichuan = create_autospec(Baichuan)
|
||||
# Disable tcp push by default for tests
|
||||
host_mock.baichuan.port = TEST_BC_PORT
|
||||
host_mock.baichuan.events_active = False
|
||||
host_mock.baichuan.privacy_mode.return_value = False
|
||||
host_mock.baichuan.subscribe_events.side_effect = ReolinkError("Test error")
|
||||
@ -175,6 +178,7 @@ def config_entry(hass: HomeAssistant) -> MockConfigEntry:
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_SUPPORTS_PRIVACY_MODE: TEST_PRIVACY,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
|
@ -19,6 +19,7 @@ from homeassistant import config_entries
|
||||
from homeassistant.components.reolink import DEVICE_UPDATE_INTERVAL
|
||||
from homeassistant.components.reolink.config_flow import DEFAULT_PROTOCOL
|
||||
from homeassistant.components.reolink.const import (
|
||||
CONF_BC_PORT,
|
||||
CONF_SUPPORTS_PRIVACY_MODE,
|
||||
CONF_USE_HTTPS,
|
||||
DOMAIN,
|
||||
@ -40,6 +41,7 @@ from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo
|
||||
|
||||
from .conftest import (
|
||||
DHCP_FORMATTED_MAC,
|
||||
TEST_BC_PORT,
|
||||
TEST_HOST,
|
||||
TEST_HOST2,
|
||||
TEST_MAC,
|
||||
@ -88,6 +90,7 @@ async def test_config_flow_manual_success(
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_SUPPORTS_PRIVACY_MODE: TEST_PRIVACY,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
}
|
||||
assert result["options"] == {
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -140,6 +143,7 @@ async def test_config_flow_privacy_success(
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_SUPPORTS_PRIVACY_MODE: TEST_PRIVACY,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
}
|
||||
assert result["options"] == {
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -290,6 +294,7 @@ async def test_config_flow_errors(
|
||||
CONF_HOST: TEST_HOST,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
)
|
||||
|
||||
@ -302,6 +307,7 @@ async def test_config_flow_errors(
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_SUPPORTS_PRIVACY_MODE: TEST_PRIVACY,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
}
|
||||
assert result["options"] == {
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -322,6 +328,7 @@ async def test_options_flow(hass: HomeAssistant, mock_setup_entry: MagicMock) ->
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: "rtsp",
|
||||
@ -360,6 +367,7 @@ async def test_reauth(hass: HomeAssistant, mock_setup_entry: MagicMock) -> None:
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -405,6 +413,7 @@ async def test_reauth_abort_unique_id_mismatch(
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -474,6 +483,7 @@ async def test_dhcp_flow(hass: HomeAssistant, mock_setup_entry: MagicMock) -> No
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_SUPPORTS_PRIVACY_MODE: TEST_PRIVACY,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
}
|
||||
assert result["options"] == {
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -496,6 +506,7 @@ async def test_dhcp_ip_update_aborted_if_wrong_mac(
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -536,6 +547,7 @@ async def test_dhcp_ip_update_aborted_if_wrong_mac(
|
||||
protocol=DEFAULT_PROTOCOL,
|
||||
timeout=DEFAULT_TIMEOUT,
|
||||
aiohttp_get_session_callback=ANY,
|
||||
bc_port=TEST_BC_PORT,
|
||||
)
|
||||
assert expected_call in reolink_connect_class.call_args_list
|
||||
|
||||
@ -593,6 +605,7 @@ async def test_dhcp_ip_update(
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -635,6 +648,7 @@ async def test_dhcp_ip_update(
|
||||
protocol=DEFAULT_PROTOCOL,
|
||||
timeout=DEFAULT_TIMEOUT,
|
||||
aiohttp_get_session_callback=ANY,
|
||||
bc_port=TEST_BC_PORT,
|
||||
)
|
||||
assert expected_call in reolink_connect_class.call_args_list
|
||||
|
||||
@ -671,6 +685,7 @@ async def test_dhcp_ip_update_ingnored_if_still_connected(
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -702,6 +717,7 @@ async def test_dhcp_ip_update_ingnored_if_still_connected(
|
||||
protocol=DEFAULT_PROTOCOL,
|
||||
timeout=DEFAULT_TIMEOUT,
|
||||
aiohttp_get_session_callback=ANY,
|
||||
bc_port=TEST_BC_PORT,
|
||||
)
|
||||
assert expected_call in reolink_connect_class.call_args_list
|
||||
|
||||
@ -731,6 +747,7 @@ async def test_reconfig(hass: HomeAssistant, mock_setup_entry: MagicMock) -> Non
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
@ -777,6 +794,7 @@ async def test_reconfig_abort_unique_id_mismatch(
|
||||
CONF_PASSWORD: TEST_PASSWORD,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
|
@ -19,7 +19,7 @@ from homeassistant.components.reolink import (
|
||||
FIRMWARE_UPDATE_INTERVAL,
|
||||
NUM_CRED_ERRORS,
|
||||
)
|
||||
from homeassistant.components.reolink.const import DOMAIN
|
||||
from homeassistant.components.reolink.const import CONF_BC_PORT, DOMAIN
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from homeassistant.const import (
|
||||
CONF_PORT,
|
||||
@ -38,6 +38,7 @@ from homeassistant.helpers import (
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .conftest import (
|
||||
TEST_BC_PORT,
|
||||
TEST_CAM_MODEL,
|
||||
TEST_HOST_MODEL,
|
||||
TEST_MAC,
|
||||
@ -762,6 +763,21 @@ async def test_port_changed(
|
||||
assert config_entry.data[CONF_PORT] == 4567
|
||||
|
||||
|
||||
async def test_baichuan_port_changed(
|
||||
hass: HomeAssistant,
|
||||
reolink_connect: MagicMock,
|
||||
config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Test config_entry baichuan port update when it has changed during initial login."""
|
||||
assert config_entry.data[CONF_BC_PORT] == TEST_BC_PORT
|
||||
reolink_connect.baichuan.port = 8901
|
||||
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.data[CONF_BC_PORT] == 8901
|
||||
|
||||
|
||||
async def test_privacy_mode_on(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
|
@ -15,7 +15,7 @@ from homeassistant.components.media_source import (
|
||||
async_resolve_media,
|
||||
)
|
||||
from homeassistant.components.reolink.config_flow import DEFAULT_PROTOCOL
|
||||
from homeassistant.components.reolink.const import CONF_USE_HTTPS, DOMAIN
|
||||
from homeassistant.components.reolink.const import CONF_BC_PORT, CONF_USE_HTTPS, DOMAIN
|
||||
from homeassistant.components.stream import DOMAIN as MEDIA_STREAM_DOMAIN
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
@ -31,6 +31,7 @@ from homeassistant.helpers.device_registry import format_mac
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .conftest import (
|
||||
TEST_BC_PORT,
|
||||
TEST_HOST2,
|
||||
TEST_HOST_MODEL,
|
||||
TEST_MAC2,
|
||||
@ -348,6 +349,7 @@ async def test_browsing_not_loaded(
|
||||
CONF_PASSWORD: TEST_PASSWORD2,
|
||||
CONF_PORT: TEST_PORT,
|
||||
CONF_USE_HTTPS: TEST_USE_HTTPS,
|
||||
CONF_BC_PORT: TEST_BC_PORT,
|
||||
},
|
||||
options={
|
||||
CONF_PROTOCOL: DEFAULT_PROTOCOL,
|
||||
|
Loading…
x
Reference in New Issue
Block a user