Remove deprecated YAML in `android_ip_webcam` (#80875)
parent
1b3c383558
commit
a205ba7656
|
@ -2,37 +2,20 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from pydroid_ipcam import PyDroidIPCam
|
from pydroid_ipcam import PyDroidIPCam
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
CONF_NAME,
|
|
||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_PORT,
|
CONF_PORT,
|
||||||
CONF_SCAN_INTERVAL,
|
|
||||||
CONF_SENSORS,
|
|
||||||
CONF_SWITCHES,
|
|
||||||
CONF_TIMEOUT,
|
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
Platform,
|
Platform,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
|
||||||
from homeassistant.helpers.typing import ConfigType
|
|
||||||
|
|
||||||
from .const import (
|
from .const import DOMAIN
|
||||||
CONF_MOTION_SENSOR,
|
|
||||||
DEFAULT_NAME,
|
|
||||||
DEFAULT_PORT,
|
|
||||||
DEFAULT_TIMEOUT,
|
|
||||||
DOMAIN,
|
|
||||||
SCAN_INTERVAL,
|
|
||||||
SENSORS,
|
|
||||||
SWITCHES,
|
|
||||||
)
|
|
||||||
from .coordinator import AndroidIPCamDataUpdateCoordinator
|
from .coordinator import AndroidIPCamDataUpdateCoordinator
|
||||||
|
|
||||||
PLATFORMS: list[Platform] = [
|
PLATFORMS: list[Platform] = [
|
||||||
|
@ -43,66 +26,7 @@ PLATFORMS: list[Platform] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
|
||||||
vol.All(
|
|
||||||
cv.deprecated(DOMAIN),
|
|
||||||
{
|
|
||||||
DOMAIN: vol.All(
|
|
||||||
cv.ensure_list,
|
|
||||||
[
|
|
||||||
vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
||||||
vol.Required(CONF_HOST): cv.string,
|
|
||||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
|
||||||
vol.Optional(
|
|
||||||
CONF_TIMEOUT, default=DEFAULT_TIMEOUT
|
|
||||||
): cv.positive_int,
|
|
||||||
vol.Optional(
|
|
||||||
CONF_SCAN_INTERVAL, default=SCAN_INTERVAL
|
|
||||||
): cv.time_period,
|
|
||||||
vol.Inclusive(CONF_USERNAME, "authentication"): cv.string,
|
|
||||||
vol.Inclusive(CONF_PASSWORD, "authentication"): cv.string,
|
|
||||||
vol.Optional(CONF_SWITCHES): vol.All(
|
|
||||||
cv.ensure_list, [vol.In(SWITCHES)]
|
|
||||||
),
|
|
||||||
vol.Optional(CONF_SENSORS): vol.All(
|
|
||||||
cv.ensure_list, [vol.In(SENSORS)]
|
|
||||||
),
|
|
||||||
vol.Optional(CONF_MOTION_SENSOR): cv.boolean,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
extra=vol.ALLOW_EXTRA,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|
||||||
"""Set up the IP Webcam component."""
|
|
||||||
|
|
||||||
if DOMAIN not in config:
|
|
||||||
return True
|
|
||||||
|
|
||||||
async_create_issue(
|
|
||||||
hass,
|
|
||||||
DOMAIN,
|
|
||||||
"deprecated_yaml",
|
|
||||||
breaks_in_ha_version="2022.11.0",
|
|
||||||
is_fixable=False,
|
|
||||||
severity=IssueSeverity.WARNING,
|
|
||||||
translation_key="deprecated_yaml",
|
|
||||||
)
|
|
||||||
for entry in config[DOMAIN]:
|
|
||||||
hass.async_create_task(
|
|
||||||
hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN, context={"source": SOURCE_IMPORT}, data=entry
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
|
|
@ -8,15 +8,7 @@ from pydroid_ipcam.exceptions import PyDroidIPCamException, Unauthorized
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.const import (
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME
|
||||||
CONF_HOST,
|
|
||||||
CONF_NAME,
|
|
||||||
CONF_PASSWORD,
|
|
||||||
CONF_PORT,
|
|
||||||
CONF_SCAN_INTERVAL,
|
|
||||||
CONF_TIMEOUT,
|
|
||||||
CONF_USERNAME,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.data_entry_flow import FlowResult
|
from homeassistant.data_entry_flow import FlowResult
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
@ -75,19 +67,11 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
self._async_abort_entries_match(
|
self._async_abort_entries_match(
|
||||||
{CONF_HOST: user_input[CONF_HOST], CONF_PORT: user_input[CONF_PORT]}
|
{CONF_HOST: user_input[CONF_HOST], CONF_PORT: user_input[CONF_PORT]}
|
||||||
)
|
)
|
||||||
# to be removed when YAML import is removed
|
|
||||||
title = user_input.get(CONF_NAME) or user_input[CONF_HOST]
|
|
||||||
if not (errors := await validate_input(self.hass, user_input)):
|
if not (errors := await validate_input(self.hass, user_input)):
|
||||||
return self.async_create_entry(title=title, data=user_input)
|
return self.async_create_entry(title=user_input[CONF_HOST], data=user_input)
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
step_id="user",
|
step_id="user",
|
||||||
data_schema=STEP_USER_DATA_SCHEMA,
|
data_schema=STEP_USER_DATA_SCHEMA,
|
||||||
errors=errors,
|
errors=errors,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_import(self, import_config: dict[str, Any]) -> FlowResult:
|
|
||||||
"""Import a config entry from configuration.yaml."""
|
|
||||||
import_config.pop(CONF_SCAN_INTERVAL)
|
|
||||||
import_config.pop(CONF_TIMEOUT)
|
|
||||||
return await self.async_step_user(import_config)
|
|
||||||
|
|
|
@ -4,38 +4,6 @@ from datetime import timedelta
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
DOMAIN: Final = "android_ip_webcam"
|
DOMAIN: Final = "android_ip_webcam"
|
||||||
DEFAULT_NAME: Final = "IP Webcam"
|
|
||||||
DEFAULT_PORT: Final = 8080
|
DEFAULT_PORT: Final = 8080
|
||||||
DEFAULT_TIMEOUT: Final = 10
|
|
||||||
|
|
||||||
CONF_MOTION_SENSOR: Final = "motion_sensor"
|
|
||||||
|
|
||||||
MOTION_ACTIVE: Final = "motion_active"
|
MOTION_ACTIVE: Final = "motion_active"
|
||||||
SCAN_INTERVAL: Final = timedelta(seconds=10)
|
SCAN_INTERVAL: Final = timedelta(seconds=10)
|
||||||
|
|
||||||
|
|
||||||
SWITCHES = [
|
|
||||||
"exposure_lock",
|
|
||||||
"ffc",
|
|
||||||
"focus",
|
|
||||||
"gps_active",
|
|
||||||
"motion_detect",
|
|
||||||
"night_vision",
|
|
||||||
"overlay",
|
|
||||||
"torch",
|
|
||||||
"whitebalance_lock",
|
|
||||||
"video_recording",
|
|
||||||
]
|
|
||||||
|
|
||||||
SENSORS = [
|
|
||||||
"audio_connections",
|
|
||||||
"battery_level",
|
|
||||||
"battery_temp",
|
|
||||||
"battery_voltage",
|
|
||||||
"light",
|
|
||||||
"motion",
|
|
||||||
"pressure",
|
|
||||||
"proximity",
|
|
||||||
"sound",
|
|
||||||
"video_connections",
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
"""Test the Android IP Webcam config flow."""
|
"""Test the Android IP Webcam config flow."""
|
||||||
from datetime import timedelta
|
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
@ -45,35 +44,6 @@ async def test_form(hass: HomeAssistant, aioclient_mock_fixture) -> None:
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
|
||||||
async def test_import_flow_success(hass: HomeAssistant, aioclient_mock_fixture) -> None:
|
|
||||||
"""Test a successful import of yaml."""
|
|
||||||
with patch(
|
|
||||||
"homeassistant.components.android_ip_webcam.async_setup_entry",
|
|
||||||
return_value=True,
|
|
||||||
) as mock_setup_entry:
|
|
||||||
result2 = await hass.config_entries.flow.async_init(
|
|
||||||
DOMAIN,
|
|
||||||
context={"source": config_entries.SOURCE_IMPORT},
|
|
||||||
data={
|
|
||||||
"name": "IP Webcam",
|
|
||||||
"host": "1.1.1.1",
|
|
||||||
"port": 8080,
|
|
||||||
"timeout": 10,
|
|
||||||
"scan_interval": timedelta(seconds=30),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert result2["type"] == FlowResultType.CREATE_ENTRY
|
|
||||||
assert result2["title"] == "IP Webcam"
|
|
||||||
assert result2["data"] == {
|
|
||||||
"name": "IP Webcam",
|
|
||||||
"host": "1.1.1.1",
|
|
||||||
"port": 8080,
|
|
||||||
}
|
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
|
||||||
|
|
||||||
|
|
||||||
async def test_device_already_configured(
|
async def test_device_already_configured(
|
||||||
hass: HomeAssistant, aioclient_mock_fixture
|
hass: HomeAssistant, aioclient_mock_fixture
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
"""Tests for the Android IP Webcam integration."""
|
"""Tests for the Android IP Webcam integration."""
|
||||||
|
|
||||||
|
|
||||||
from collections.abc import Awaitable
|
|
||||||
from typing import Callable
|
|
||||||
from unittest.mock import Mock
|
from unittest.mock import Mock
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
|
@ -10,10 +8,8 @@ import aiohttp
|
||||||
from homeassistant.components.android_ip_webcam.const import DOMAIN
|
from homeassistant.components.android_ip_webcam.const import DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntryState
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.setup import async_setup_component
|
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
from tests.components.repairs import get_repairs
|
|
||||||
from tests.test_util.aiohttp import AiohttpClientMocker
|
from tests.test_util.aiohttp import AiohttpClientMocker
|
||||||
|
|
||||||
MOCK_CONFIG_DATA = {
|
MOCK_CONFIG_DATA = {
|
||||||
|
@ -25,21 +21,6 @@ MOCK_CONFIG_DATA = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def test_setup(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
aioclient_mock_fixture,
|
|
||||||
hass_ws_client: Callable[
|
|
||||||
[HomeAssistant], Awaitable[aiohttp.ClientWebSocketResponse]
|
|
||||||
],
|
|
||||||
) -> None:
|
|
||||||
"""Test integration failed due to an error."""
|
|
||||||
assert await async_setup_component(hass, DOMAIN, {DOMAIN: [MOCK_CONFIG_DATA]})
|
|
||||||
assert hass.config_entries.async_entries(DOMAIN)
|
|
||||||
issues = await get_repairs(hass, hass_ws_client)
|
|
||||||
assert len(issues) == 1
|
|
||||||
assert issues[0]["issue_id"] == "deprecated_yaml"
|
|
||||||
|
|
||||||
|
|
||||||
async def test_successful_config_entry(
|
async def test_successful_config_entry(
|
||||||
hass: HomeAssistant, aioclient_mock_fixture
|
hass: HomeAssistant, aioclient_mock_fixture
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Reference in New Issue