mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 03:37:07 +00:00
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:
parent
c01b7bbf28
commit
7cbd55a817
@ -1,7 +1,9 @@
|
|||||||
"""Support for HomematicIP Cloud devices."""
|
"""Support for HomematicIP Cloud devices."""
|
||||||
import logging
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from homematicip.aio.group import AsyncHeatingGroup
|
from homematicip.aio.group import AsyncHeatingGroup
|
||||||
|
from homematicip.base.helpers import handle_config
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
@ -26,17 +28,23 @@ from .hap import HomematicipAuth, HomematicipHAP # noqa: F401
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ATTR_ACCESSPOINT_ID = "accesspoint_id"
|
||||||
|
ATTR_ANONYMIZE = "anonymize"
|
||||||
ATTR_CLIMATE_PROFILE_INDEX = "climate_profile_index"
|
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_DURATION = "duration"
|
||||||
ATTR_ENDTIME = "endtime"
|
ATTR_ENDTIME = "endtime"
|
||||||
ATTR_TEMPERATURE = "temperature"
|
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_DURATION = "activate_eco_mode_with_duration"
|
||||||
SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD = "activate_eco_mode_with_period"
|
SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD = "activate_eco_mode_with_period"
|
||||||
SERVICE_ACTIVATE_VACATION = "activate_vacation"
|
SERVICE_ACTIVATE_VACATION = "activate_vacation"
|
||||||
SERVICE_DEACTIVATE_ECO_MODE = "deactivate_eco_mode"
|
SERVICE_DEACTIVATE_ECO_MODE = "deactivate_eco_mode"
|
||||||
SERVICE_DEACTIVATE_VACATION = "deactivate_vacation"
|
SERVICE_DEACTIVATE_VACATION = "deactivate_vacation"
|
||||||
|
SERVICE_DUMP_HAP_CONFIG = "dump_hap_config"
|
||||||
SERVICE_SET_ACTIVE_CLIMATE_PROFILE = "set_active_climate_profile"
|
SERVICE_SET_ACTIVE_CLIMATE_PROFILE = "set_active_climate_profile"
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
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:
|
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
||||||
"""Set up the HomematicIP Cloud component."""
|
"""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,
|
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):
|
def _get_home(hapid: str):
|
||||||
"""Return a HmIP home."""
|
"""Return a HmIP home."""
|
||||||
hap = hass.data[DOMAIN].get(hapid)
|
hap = hass.data[DOMAIN].get(hapid)
|
||||||
|
@ -57,4 +57,15 @@ set_active_climate_profile:
|
|||||||
description: The index of the climate profile (1 based)
|
description: The index of the climate profile (1 based)
|
||||||
example: 1
|
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
|
||||||
|
@ -5,7 +5,7 @@ from unittest.mock import patch
|
|||||||
from homeassistant.components import homematicip_cloud as hmipc
|
from homeassistant.components import homematicip_cloud as hmipc
|
||||||
from homeassistant.setup import async_setup_component
|
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):
|
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 await hmipc.async_unload_entry(hass, entry)
|
||||||
assert len(mock_hap.return_value.async_reset.mock_calls) == 1
|
assert len(mock_hap.return_value.async_reset.mock_calls) == 1
|
||||||
assert hass.data[hmipc.DOMAIN] == {}
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user