Remove deprecated YAML import from traccar (#125763)

This commit is contained in:
Jan-Philipp Benecke 2024-09-23 19:14:55 +02:00 committed by GitHub
parent 4a424a6603
commit 28c2df37ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 4 additions and 296 deletions

View File

@ -4,50 +4,15 @@ from __future__ import annotations
from datetime import timedelta from datetime import timedelta
import logging import logging
from typing import Any
from pytraccar import ApiClient, TraccarException from homeassistant.components.device_tracker import SourceType, TrackerEntity
import voluptuous as vol from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.components.device_tracker import ( from homeassistant.helpers import device_registry as dr
PLATFORM_SCHEMA as DEVICE_TRACKER_PLATFORM_SCHEMA,
AsyncSeeCallback,
SourceType,
TrackerEntity,
)
from homeassistant.components.device_tracker.legacy import (
YAML_DEVICES,
remove_device_from_config,
)
from homeassistant.config import load_yaml_config_file
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import (
CONF_EVENT,
CONF_HOST,
CONF_MONITORED_CONDITIONS,
CONF_PASSWORD,
CONF_PORT,
CONF_SSL,
CONF_USERNAME,
CONF_VERIFY_SSL,
EVENT_HOMEASSISTANT_STARTED,
)
from homeassistant.core import (
DOMAIN as HOMEASSISTANT_DOMAIN,
Event,
HomeAssistant,
callback,
)
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import slugify
from . import DOMAIN, TRACKER_UPDATE from . import DOMAIN, TRACKER_UPDATE
from .const import ( from .const import (
@ -58,8 +23,6 @@ from .const import (
ATTR_LATITUDE, ATTR_LATITUDE,
ATTR_LONGITUDE, ATTR_LONGITUDE,
ATTR_SPEED, ATTR_SPEED,
CONF_MAX_ACCURACY,
CONF_SKIP_ACCURACY_ON,
EVENT_ALARM, EVENT_ALARM,
EVENT_ALL_EVENTS, EVENT_ALL_EVENTS,
EVENT_COMMAND_RESULT, EVENT_COMMAND_RESULT,
@ -104,28 +67,6 @@ EVENTS = [
EVENT_ALL_EVENTS, EVENT_ALL_EVENTS,
] ]
PLATFORM_SCHEMA = DEVICE_TRACKER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_PORT, default=8082): cv.port,
vol.Optional(CONF_SSL, default=False): cv.boolean,
vol.Optional(CONF_VERIFY_SSL, default=True): cv.boolean,
vol.Required(CONF_MAX_ACCURACY, default=0): cv.positive_int,
vol.Optional(CONF_SKIP_ACCURACY_ON, default=[]): vol.All(
cv.ensure_list, [cv.string]
),
vol.Optional(CONF_MONITORED_CONDITIONS, default=[]): vol.All(
cv.ensure_list, [cv.string]
),
vol.Optional(CONF_EVENT, default=[]): vol.All(
cv.ensure_list,
[vol.In(EVENTS)],
),
}
)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
@ -167,80 +108,6 @@ async def async_setup_entry(
async_add_entities(entities) async_add_entities(entities)
async def async_setup_scanner(
hass: HomeAssistant,
config: ConfigType,
async_see: AsyncSeeCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> bool:
"""Import configuration to the new integration."""
api = ApiClient(
host=config[CONF_HOST],
port=config[CONF_PORT],
ssl=config[CONF_SSL],
username=config[CONF_USERNAME],
password=config[CONF_PASSWORD],
client_session=async_get_clientsession(hass, config[CONF_VERIFY_SSL]),
)
async def _run_import(_: Event):
known_devices: dict[str, dict[str, Any]] = {}
try:
known_devices = await hass.async_add_executor_job(
load_yaml_config_file, hass.config.path(YAML_DEVICES)
)
except (FileNotFoundError, HomeAssistantError):
_LOGGER.debug(
"No valid known_devices.yaml found, "
"skip removal of devices from known_devices.yaml"
)
if known_devices:
traccar_devices: list[str] = []
try:
resp = await api.get_devices()
traccar_devices = [slugify(device["name"]) for device in resp]
except TraccarException as exception:
_LOGGER.error("Error while getting device data: %s", exception)
return
for dev_name in traccar_devices:
if dev_name in known_devices:
await hass.async_add_executor_job(
remove_device_from_config, hass, dev_name
)
_LOGGER.debug("Removed device %s from known_devices.yaml", dev_name)
if not hass.states.async_available(f"device_tracker.{dev_name}"):
hass.states.async_remove(f"device_tracker.{dev_name}")
hass.async_create_task(
hass.config_entries.flow.async_init(
"traccar_server",
context={"source": SOURCE_IMPORT},
data=config,
)
)
async_create_issue(
hass,
HOMEASSISTANT_DOMAIN,
f"deprecated_yaml_{DOMAIN}",
breaks_in_ha_version="2024.8.0",
is_fixable=False,
issue_domain=DOMAIN,
severity=IssueSeverity.WARNING,
translation_key="deprecated_yaml",
translation_placeholders={
"domain": DOMAIN,
"integration_title": "Traccar",
},
)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, _run_import)
return True
class TraccarEntity(TrackerEntity, RestoreEntity): class TraccarEntity(TrackerEntity, RestoreEntity):
"""Represent a tracked device.""" """Represent a tracked device."""

View File

@ -160,39 +160,6 @@ class TraccarServerConfigFlow(ConfigFlow, domain=DOMAIN):
errors=errors, errors=errors,
) )
async def async_step_import(self, import_data: dict[str, Any]) -> ConfigFlowResult:
"""Import an entry."""
configured_port = str(import_data[CONF_PORT])
self._async_abort_entries_match(
{
CONF_HOST: import_data[CONF_HOST],
CONF_PORT: configured_port,
}
)
if "all_events" in (imported_events := import_data.get("event", [])):
events = list(EVENTS.values())
else:
events = imported_events
return self.async_create_entry(
title=f"{import_data[CONF_HOST]}:{configured_port}",
data={
CONF_HOST: import_data[CONF_HOST],
CONF_PORT: configured_port,
CONF_SSL: import_data.get(CONF_SSL, False),
CONF_VERIFY_SSL: import_data.get(CONF_VERIFY_SSL, True),
CONF_USERNAME: import_data[CONF_USERNAME],
CONF_PASSWORD: import_data[CONF_PASSWORD],
},
options={
CONF_MAX_ACCURACY: import_data[CONF_MAX_ACCURACY],
CONF_EVENTS: events,
CONF_CUSTOM_ATTRIBUTES: import_data.get("monitored_conditions", []),
CONF_SKIP_ACCURACY_FILTER_FOR: import_data.get(
"skip_accuracy_filter_on", []
),
},
)
@staticmethod @staticmethod
@callback @callback
def async_get_options_flow( def async_get_options_flow(

View File

@ -1,23 +1,18 @@
"""Test the Traccar Server config flow.""" """Test the Traccar Server config flow."""
from collections.abc import Generator from collections.abc import Generator
from typing import Any
from unittest.mock import AsyncMock from unittest.mock import AsyncMock
import pytest import pytest
from pytraccar import TraccarException from pytraccar import TraccarException
from homeassistant import config_entries from homeassistant import config_entries
# pylint: disable-next=hass-component-root-import
from homeassistant.components.traccar.device_tracker import PLATFORM_SCHEMA
from homeassistant.components.traccar_server.const import ( from homeassistant.components.traccar_server.const import (
CONF_CUSTOM_ATTRIBUTES, CONF_CUSTOM_ATTRIBUTES,
CONF_EVENTS, CONF_EVENTS,
CONF_MAX_ACCURACY, CONF_MAX_ACCURACY,
CONF_SKIP_ACCURACY_FILTER_FOR, CONF_SKIP_ACCURACY_FILTER_FOR,
DOMAIN, DOMAIN,
EVENTS,
) )
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import ( from homeassistant.const import (
@ -155,127 +150,6 @@ async def test_options(
} }
@pytest.mark.parametrize(
("imported", "data", "options"),
[
(
{
CONF_HOST: "1.1.1.1",
CONF_PORT: 443,
CONF_USERNAME: "test-username",
CONF_PASSWORD: "test-password",
},
{
CONF_HOST: "1.1.1.1",
CONF_PORT: "443",
CONF_VERIFY_SSL: True,
CONF_SSL: False,
CONF_USERNAME: "test-username",
CONF_PASSWORD: "test-password",
},
{
CONF_EVENTS: [],
CONF_CUSTOM_ATTRIBUTES: [],
CONF_SKIP_ACCURACY_FILTER_FOR: [],
CONF_MAX_ACCURACY: 0,
},
),
(
{
CONF_HOST: "1.1.1.1",
CONF_USERNAME: "test-username",
CONF_PASSWORD: "test-password",
CONF_SSL: True,
"event": ["device_online", "device_offline"],
},
{
CONF_HOST: "1.1.1.1",
CONF_PORT: "8082",
CONF_VERIFY_SSL: True,
CONF_SSL: True,
CONF_USERNAME: "test-username",
CONF_PASSWORD: "test-password",
},
{
CONF_EVENTS: ["device_online", "device_offline"],
CONF_CUSTOM_ATTRIBUTES: [],
CONF_SKIP_ACCURACY_FILTER_FOR: [],
CONF_MAX_ACCURACY: 0,
},
),
(
{
CONF_HOST: "1.1.1.1",
CONF_USERNAME: "test-username",
CONF_PASSWORD: "test-password",
CONF_SSL: True,
"event": ["device_online", "device_offline", "all_events"],
},
{
CONF_HOST: "1.1.1.1",
CONF_PORT: "8082",
CONF_VERIFY_SSL: True,
CONF_SSL: True,
CONF_USERNAME: "test-username",
CONF_PASSWORD: "test-password",
},
{
CONF_EVENTS: list(EVENTS.values()),
CONF_CUSTOM_ATTRIBUTES: [],
CONF_SKIP_ACCURACY_FILTER_FOR: [],
CONF_MAX_ACCURACY: 0,
},
),
],
)
async def test_import_from_yaml(
hass: HomeAssistant,
imported: dict[str, Any],
data: dict[str, Any],
options: dict[str, Any],
mock_traccar_api_client: Generator[AsyncMock],
) -> None:
"""Test importing configuration from YAML."""
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data=PLATFORM_SCHEMA({"platform": "traccar", **imported}),
)
assert result["type"] is FlowResultType.CREATE_ENTRY
assert result["title"] == f"{data[CONF_HOST]}:{data[CONF_PORT]}"
assert result["data"] == data
assert result["options"] == options
assert result["result"].state is ConfigEntryState.LOADED
async def test_abort_import_already_configured(hass: HomeAssistant) -> None:
"""Test abort for existing server while importing."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_HOST: "1.1.1.1", CONF_PORT: "8082"},
)
config_entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data=PLATFORM_SCHEMA(
{
"platform": "traccar",
CONF_USERNAME: "test-username",
CONF_PASSWORD: "test-password",
CONF_HOST: "1.1.1.1",
CONF_PORT: "8082",
}
),
)
assert result["type"] is FlowResultType.ABORT
assert result["reason"] == "already_configured"
async def test_abort_already_configured( async def test_abort_already_configured(
hass: HomeAssistant, hass: HomeAssistant,
mock_config_entry: MockConfigEntry, mock_config_entry: MockConfigEntry,