Add dump config service to HomematicIP Cloud (#28231)

* Add dump config service to HomematicIP Cloud

* Mock builin.open

* Fix test

* reduce SGTIN if anonymize

* apply review feedback
This commit is contained in:
SukramJ 2019-11-04 09:55:12 +01:00 committed by Fabian Affolter
parent c01b7bbf28
commit 7cbd55a817
3 changed files with 75 additions and 3 deletions

View File

@ -1,7 +1,9 @@
"""Support for HomematicIP Cloud devices."""
import logging
from pathlib import Path
from homematicip.aio.group import AsyncHeatingGroup
from homematicip.base.helpers import handle_config
import voluptuous as vol
from homeassistant import config_entries
@ -26,17 +28,23 @@ from .hap import HomematicipAuth, HomematicipHAP # noqa: F401
_LOGGER = logging.getLogger(__name__)
ATTR_ACCESSPOINT_ID = "accesspoint_id"
ATTR_ANONYMIZE = "anonymize"
ATTR_CLIMATE_PROFILE_INDEX = "climate_profile_index"
ATTR_CONFIG_OUTPUT_FILE_PREFIX = "config_output_file_prefix"
ATTR_CONFIG_OUTPUT_PATH = "config_output_path"
ATTR_DURATION = "duration"
ATTR_ENDTIME = "endtime"
ATTR_TEMPERATURE = "temperature"
ATTR_ACCESSPOINT_ID = "accesspoint_id"
DEFAULT_CONFIG_FILE_PREFIX = "hmip-config"
SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION = "activate_eco_mode_with_duration"
SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD = "activate_eco_mode_with_period"
SERVICE_ACTIVATE_VACATION = "activate_vacation"
SERVICE_DEACTIVATE_ECO_MODE = "deactivate_eco_mode"
SERVICE_DEACTIVATE_VACATION = "deactivate_vacation"
SERVICE_DUMP_HAP_CONFIG = "dump_hap_config"
SERVICE_SET_ACTIVE_CLIMATE_PROFILE = "set_active_climate_profile"
CONFIG_SCHEMA = vol.Schema(
@ -96,6 +104,16 @@ SCHEMA_SET_ACTIVE_CLIMATE_PROFILE = vol.Schema(
}
)
SCHEMA_DUMP_HAP_CONFIG = vol.Schema(
{
vol.Optional(ATTR_CONFIG_OUTPUT_PATH): cv.string,
vol.Optional(
ATTR_CONFIG_OUTPUT_FILE_PREFIX, default=DEFAULT_CONFIG_FILE_PREFIX
): cv.string,
vol.Optional(ATTR_ANONYMIZE, default=True): cv.boolean,
}
)
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
"""Set up the HomematicIP Cloud component."""
@ -239,6 +257,36 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
schema=SCHEMA_SET_ACTIVE_CLIMATE_PROFILE,
)
async def _async_dump_hap_config(service):
"""Service to dump the configuration of a Homematic IP Access Point."""
config_path = (
service.data.get(ATTR_CONFIG_OUTPUT_PATH) or hass.config.config_dir
)
config_file_prefix = service.data[ATTR_CONFIG_OUTPUT_FILE_PREFIX]
anonymize = service.data[ATTR_ANONYMIZE]
for hap in hass.data[DOMAIN].values():
hap_sgtin = hap.config_entry.title
if anonymize:
hap_sgtin = hap_sgtin[-4:]
file_name = f"{config_file_prefix}_{hap_sgtin}.json"
path = Path(config_path)
config_file = path / file_name
json_state = await hap.home.download_configuration()
json_state = handle_config(json_state, anonymize)
config_file.write_text(json_state, encoding="utf8")
hass.services.async_register(
DOMAIN,
SERVICE_DUMP_HAP_CONFIG,
_async_dump_hap_config,
schema=SCHEMA_DUMP_HAP_CONFIG,
)
def _get_home(hapid: str):
"""Return a HmIP home."""
hap = hass.data[DOMAIN].get(hapid)

View File

@ -57,4 +57,15 @@ set_active_climate_profile:
description: The index of the climate profile (1 based)
example: 1
dump_hap_config:
description: Dump the configuration of the Homematic IP Access Point(s).
fields:
config_output_path:
description: (Default is 'Your home-assistant config directory') Path where to store the config.
example: '/config'
config_output_file_prefix:
description: (Default is 'hmip-config') Name of the config file. The SGTIN of the AP will always be appended.
example: 'hmip-config'
anonymize:
description: (Default is True) Should the Configuration be anonymized?
example: True

View File

@ -5,7 +5,7 @@ from unittest.mock import patch
from homeassistant.components import homematicip_cloud as hmipc
from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry, mock_coro
from tests.common import Mock, MockConfigEntry, mock_coro
async def test_config_with_accesspoint_passed_to_config_entry(hass):
@ -150,3 +150,16 @@ async def test_unload_entry(hass):
assert await hmipc.async_unload_entry(hass, entry)
assert len(mock_hap.return_value.async_reset.mock_calls) == 1
assert hass.data[hmipc.DOMAIN] == {}
async def test_hmip_dump_hap_config_services(hass, mock_hap_with_service):
"""Test dump configuration services."""
with patch("pathlib.Path.write_text", return_value=Mock()) as write_mock:
await hass.services.async_call(
"homematicip_cloud", "dump_hap_config", {"anonymize": True}, blocking=True
)
home = mock_hap_with_service.home
assert home.mock_calls[-1][0] == "download_configuration"
assert len(home.mock_calls) == 8 # pylint: disable=W0212
assert len(write_mock.mock_calls) > 0