mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 08:17:08 +00:00
Avoid services unload for Homematicip Cloud (#146050)
* Avoid services unload * fix tests * apply review comments * cleanup * apply review comment
This commit is contained in:
parent
d448ef9f16
commit
7b699f7733
@ -21,7 +21,7 @@ from .const import (
|
|||||||
HMIPC_NAME,
|
HMIPC_NAME,
|
||||||
)
|
)
|
||||||
from .hap import HomematicIPConfigEntry, HomematicipHAP
|
from .hap import HomematicIPConfigEntry, HomematicipHAP
|
||||||
from .services import async_setup_services, async_unload_services
|
from .services import async_setup_services
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
@ -116,8 +116,6 @@ async def async_unload_entry(
|
|||||||
assert hap.reset_connection_listener is not None
|
assert hap.reset_connection_listener is not None
|
||||||
hap.reset_connection_listener()
|
hap.reset_connection_listener()
|
||||||
|
|
||||||
await async_unload_services(hass)
|
|
||||||
|
|
||||||
return await hap.async_reset()
|
return await hap.async_reset()
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,32 +123,29 @@ SCHEMA_SET_HOME_COOLING_MODE = vol.Schema(
|
|||||||
async def async_setup_services(hass: HomeAssistant) -> None:
|
async def async_setup_services(hass: HomeAssistant) -> None:
|
||||||
"""Set up the HomematicIP Cloud services."""
|
"""Set up the HomematicIP Cloud services."""
|
||||||
|
|
||||||
if hass.services.async_services_for_domain(DOMAIN):
|
|
||||||
return
|
|
||||||
|
|
||||||
@verify_domain_control(hass, DOMAIN)
|
@verify_domain_control(hass, DOMAIN)
|
||||||
async def async_call_hmipc_service(service: ServiceCall) -> None:
|
async def async_call_hmipc_service(service: ServiceCall) -> None:
|
||||||
"""Call correct HomematicIP Cloud service."""
|
"""Call correct HomematicIP Cloud service."""
|
||||||
service_name = service.service
|
service_name = service.service
|
||||||
|
|
||||||
if service_name == SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION:
|
if service_name == SERVICE_ACTIVATE_ECO_MODE_WITH_DURATION:
|
||||||
await _async_activate_eco_mode_with_duration(hass, service)
|
await _async_activate_eco_mode_with_duration(service)
|
||||||
elif service_name == SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD:
|
elif service_name == SERVICE_ACTIVATE_ECO_MODE_WITH_PERIOD:
|
||||||
await _async_activate_eco_mode_with_period(hass, service)
|
await _async_activate_eco_mode_with_period(service)
|
||||||
elif service_name == SERVICE_ACTIVATE_VACATION:
|
elif service_name == SERVICE_ACTIVATE_VACATION:
|
||||||
await _async_activate_vacation(hass, service)
|
await _async_activate_vacation(service)
|
||||||
elif service_name == SERVICE_DEACTIVATE_ECO_MODE:
|
elif service_name == SERVICE_DEACTIVATE_ECO_MODE:
|
||||||
await _async_deactivate_eco_mode(hass, service)
|
await _async_deactivate_eco_mode(service)
|
||||||
elif service_name == SERVICE_DEACTIVATE_VACATION:
|
elif service_name == SERVICE_DEACTIVATE_VACATION:
|
||||||
await _async_deactivate_vacation(hass, service)
|
await _async_deactivate_vacation(service)
|
||||||
elif service_name == SERVICE_DUMP_HAP_CONFIG:
|
elif service_name == SERVICE_DUMP_HAP_CONFIG:
|
||||||
await _async_dump_hap_config(hass, service)
|
await _async_dump_hap_config(service)
|
||||||
elif service_name == SERVICE_RESET_ENERGY_COUNTER:
|
elif service_name == SERVICE_RESET_ENERGY_COUNTER:
|
||||||
await _async_reset_energy_counter(hass, service)
|
await _async_reset_energy_counter(service)
|
||||||
elif service_name == SERVICE_SET_ACTIVE_CLIMATE_PROFILE:
|
elif service_name == SERVICE_SET_ACTIVE_CLIMATE_PROFILE:
|
||||||
await _set_active_climate_profile(hass, service)
|
await _set_active_climate_profile(service)
|
||||||
elif service_name == SERVICE_SET_HOME_COOLING_MODE:
|
elif service_name == SERVICE_SET_HOME_COOLING_MODE:
|
||||||
await _async_set_home_cooling_mode(hass, service)
|
await _async_set_home_cooling_mode(service)
|
||||||
|
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
domain=DOMAIN,
|
domain=DOMAIN,
|
||||||
@ -217,90 +214,75 @@ async def async_setup_services(hass: HomeAssistant) -> None:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_services(hass: HomeAssistant):
|
async def _async_activate_eco_mode_with_duration(service: ServiceCall) -> None:
|
||||||
"""Unload HomematicIP Cloud services."""
|
|
||||||
if hass.config_entries.async_loaded_entries(DOMAIN):
|
|
||||||
return
|
|
||||||
|
|
||||||
for hmipc_service in HMIPC_SERVICES:
|
|
||||||
hass.services.async_remove(domain=DOMAIN, service=hmipc_service)
|
|
||||||
|
|
||||||
|
|
||||||
async def _async_activate_eco_mode_with_duration(
|
|
||||||
hass: HomeAssistant, service: ServiceCall
|
|
||||||
) -> None:
|
|
||||||
"""Service to activate eco mode with duration."""
|
"""Service to activate eco mode with duration."""
|
||||||
duration = service.data[ATTR_DURATION]
|
duration = service.data[ATTR_DURATION]
|
||||||
|
|
||||||
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
||||||
if home := _get_home(hass, hapid):
|
if home := _get_home(service.hass, hapid):
|
||||||
await home.activate_absence_with_duration_async(duration)
|
await home.activate_absence_with_duration_async(duration)
|
||||||
else:
|
else:
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
await entry.runtime_data.home.activate_absence_with_duration_async(duration)
|
await entry.runtime_data.home.activate_absence_with_duration_async(duration)
|
||||||
|
|
||||||
|
|
||||||
async def _async_activate_eco_mode_with_period(
|
async def _async_activate_eco_mode_with_period(service: ServiceCall) -> None:
|
||||||
hass: HomeAssistant, service: ServiceCall
|
|
||||||
) -> None:
|
|
||||||
"""Service to activate eco mode with period."""
|
"""Service to activate eco mode with period."""
|
||||||
endtime = service.data[ATTR_ENDTIME]
|
endtime = service.data[ATTR_ENDTIME]
|
||||||
|
|
||||||
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
||||||
if home := _get_home(hass, hapid):
|
if home := _get_home(service.hass, hapid):
|
||||||
await home.activate_absence_with_period_async(endtime)
|
await home.activate_absence_with_period_async(endtime)
|
||||||
else:
|
else:
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
await entry.runtime_data.home.activate_absence_with_period_async(endtime)
|
await entry.runtime_data.home.activate_absence_with_period_async(endtime)
|
||||||
|
|
||||||
|
|
||||||
async def _async_activate_vacation(hass: HomeAssistant, service: ServiceCall) -> None:
|
async def _async_activate_vacation(service: ServiceCall) -> None:
|
||||||
"""Service to activate vacation."""
|
"""Service to activate vacation."""
|
||||||
endtime = service.data[ATTR_ENDTIME]
|
endtime = service.data[ATTR_ENDTIME]
|
||||||
temperature = service.data[ATTR_TEMPERATURE]
|
temperature = service.data[ATTR_TEMPERATURE]
|
||||||
|
|
||||||
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
||||||
if home := _get_home(hass, hapid):
|
if home := _get_home(service.hass, hapid):
|
||||||
await home.activate_vacation_async(endtime, temperature)
|
await home.activate_vacation_async(endtime, temperature)
|
||||||
else:
|
else:
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
await entry.runtime_data.home.activate_vacation_async(endtime, temperature)
|
await entry.runtime_data.home.activate_vacation_async(endtime, temperature)
|
||||||
|
|
||||||
|
|
||||||
async def _async_deactivate_eco_mode(hass: HomeAssistant, service: ServiceCall) -> None:
|
async def _async_deactivate_eco_mode(service: ServiceCall) -> None:
|
||||||
"""Service to deactivate eco mode."""
|
"""Service to deactivate eco mode."""
|
||||||
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
||||||
if home := _get_home(hass, hapid):
|
if home := _get_home(service.hass, hapid):
|
||||||
await home.deactivate_absence_async()
|
await home.deactivate_absence_async()
|
||||||
else:
|
else:
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
await entry.runtime_data.home.deactivate_absence_async()
|
await entry.runtime_data.home.deactivate_absence_async()
|
||||||
|
|
||||||
|
|
||||||
async def _async_deactivate_vacation(hass: HomeAssistant, service: ServiceCall) -> None:
|
async def _async_deactivate_vacation(service: ServiceCall) -> None:
|
||||||
"""Service to deactivate vacation."""
|
"""Service to deactivate vacation."""
|
||||||
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
||||||
if home := _get_home(hass, hapid):
|
if home := _get_home(service.hass, hapid):
|
||||||
await home.deactivate_vacation_async()
|
await home.deactivate_vacation_async()
|
||||||
else:
|
else:
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
await entry.runtime_data.home.deactivate_vacation_async()
|
await entry.runtime_data.home.deactivate_vacation_async()
|
||||||
|
|
||||||
|
|
||||||
async def _set_active_climate_profile(
|
async def _set_active_climate_profile(service: ServiceCall) -> None:
|
||||||
hass: HomeAssistant, service: ServiceCall
|
|
||||||
) -> None:
|
|
||||||
"""Service to set the active climate profile."""
|
"""Service to set the active climate profile."""
|
||||||
entity_id_list = service.data[ATTR_ENTITY_ID]
|
entity_id_list = service.data[ATTR_ENTITY_ID]
|
||||||
climate_profile_index = service.data[ATTR_CLIMATE_PROFILE_INDEX] - 1
|
climate_profile_index = service.data[ATTR_CLIMATE_PROFILE_INDEX] - 1
|
||||||
|
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
if entity_id_list != "all":
|
if entity_id_list != "all":
|
||||||
for entity_id in entity_id_list:
|
for entity_id in entity_id_list:
|
||||||
group = entry.runtime_data.hmip_device_by_entity_id.get(entity_id)
|
group = entry.runtime_data.hmip_device_by_entity_id.get(entity_id)
|
||||||
@ -312,16 +294,16 @@ async def _set_active_climate_profile(
|
|||||||
await group.set_active_profile_async(climate_profile_index)
|
await group.set_active_profile_async(climate_profile_index)
|
||||||
|
|
||||||
|
|
||||||
async def _async_dump_hap_config(hass: HomeAssistant, service: ServiceCall) -> None:
|
async def _async_dump_hap_config(service: ServiceCall) -> None:
|
||||||
"""Service to dump the configuration of a Homematic IP Access Point."""
|
"""Service to dump the configuration of a Homematic IP Access Point."""
|
||||||
config_path: str = (
|
config_path: str = (
|
||||||
service.data.get(ATTR_CONFIG_OUTPUT_PATH) or hass.config.config_dir
|
service.data.get(ATTR_CONFIG_OUTPUT_PATH) or service.hass.config.config_dir
|
||||||
)
|
)
|
||||||
config_file_prefix = service.data[ATTR_CONFIG_OUTPUT_FILE_PREFIX]
|
config_file_prefix = service.data[ATTR_CONFIG_OUTPUT_FILE_PREFIX]
|
||||||
anonymize = service.data[ATTR_ANONYMIZE]
|
anonymize = service.data[ATTR_ANONYMIZE]
|
||||||
|
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
hap_sgtin = entry.unique_id
|
hap_sgtin = entry.unique_id
|
||||||
assert hap_sgtin is not None
|
assert hap_sgtin is not None
|
||||||
|
|
||||||
@ -338,12 +320,12 @@ async def _async_dump_hap_config(hass: HomeAssistant, service: ServiceCall) -> N
|
|||||||
config_file.write_text(json_state, encoding="utf8")
|
config_file.write_text(json_state, encoding="utf8")
|
||||||
|
|
||||||
|
|
||||||
async def _async_reset_energy_counter(hass: HomeAssistant, service: ServiceCall):
|
async def _async_reset_energy_counter(service: ServiceCall):
|
||||||
"""Service to reset the energy counter."""
|
"""Service to reset the energy counter."""
|
||||||
entity_id_list = service.data[ATTR_ENTITY_ID]
|
entity_id_list = service.data[ATTR_ENTITY_ID]
|
||||||
|
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
if entity_id_list != "all":
|
if entity_id_list != "all":
|
||||||
for entity_id in entity_id_list:
|
for entity_id in entity_id_list:
|
||||||
device = entry.runtime_data.hmip_device_by_entity_id.get(entity_id)
|
device = entry.runtime_data.hmip_device_by_entity_id.get(entity_id)
|
||||||
@ -355,16 +337,16 @@ async def _async_reset_energy_counter(hass: HomeAssistant, service: ServiceCall)
|
|||||||
await device.reset_energy_counter_async()
|
await device.reset_energy_counter_async()
|
||||||
|
|
||||||
|
|
||||||
async def _async_set_home_cooling_mode(hass: HomeAssistant, service: ServiceCall):
|
async def _async_set_home_cooling_mode(service: ServiceCall):
|
||||||
"""Service to set the cooling mode."""
|
"""Service to set the cooling mode."""
|
||||||
cooling = service.data[ATTR_COOLING]
|
cooling = service.data[ATTR_COOLING]
|
||||||
|
|
||||||
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
if hapid := service.data.get(ATTR_ACCESSPOINT_ID):
|
||||||
if home := _get_home(hass, hapid):
|
if home := _get_home(service.hass, hapid):
|
||||||
await home.set_cooling_async(cooling)
|
await home.set_cooling_async(cooling)
|
||||||
else:
|
else:
|
||||||
entry: HomematicIPConfigEntry
|
entry: HomematicIPConfigEntry
|
||||||
for entry in hass.config_entries.async_loaded_entries(DOMAIN):
|
for entry in service.hass.config_entries.async_loaded_entries(DOMAIN):
|
||||||
await entry.runtime_data.home.set_cooling_async(cooling)
|
await entry.runtime_data.home.set_cooling_async(cooling)
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,8 +176,8 @@ async def test_hmip_dump_hap_config_services(
|
|||||||
assert write_mock.mock_calls
|
assert write_mock.mock_calls
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_services_and_unload_services(hass: HomeAssistant) -> None:
|
async def test_setup_services(hass: HomeAssistant) -> None:
|
||||||
"""Test setup services and unload services."""
|
"""Test setup services."""
|
||||||
mock_config = {HMIPC_AUTHTOKEN: "123", HMIPC_HAPID: "ABC123", HMIPC_NAME: "name"}
|
mock_config = {HMIPC_AUTHTOKEN: "123", HMIPC_HAPID: "ABC123", HMIPC_NAME: "name"}
|
||||||
MockConfigEntry(domain=DOMAIN, data=mock_config).add_to_hass(hass)
|
MockConfigEntry(domain=DOMAIN, data=mock_config).add_to_hass(hass)
|
||||||
|
|
||||||
@ -201,46 +201,3 @@ async def test_setup_services_and_unload_services(hass: HomeAssistant) -> None:
|
|||||||
assert len(config_entries) == 1
|
assert len(config_entries) == 1
|
||||||
|
|
||||||
await hass.config_entries.async_unload(config_entries[0].entry_id)
|
await hass.config_entries.async_unload(config_entries[0].entry_id)
|
||||||
# Check services are removed
|
|
||||||
assert not hass.services.async_services().get(DOMAIN)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_setup_two_haps_unload_one_by_one(hass: HomeAssistant) -> None:
|
|
||||||
"""Test setup two access points and unload one by one and check services."""
|
|
||||||
|
|
||||||
# Setup AP1
|
|
||||||
mock_config = {HMIPC_AUTHTOKEN: "123", HMIPC_HAPID: "ABC123", HMIPC_NAME: "name"}
|
|
||||||
MockConfigEntry(domain=DOMAIN, data=mock_config).add_to_hass(hass)
|
|
||||||
# Setup AP2
|
|
||||||
mock_config2 = {HMIPC_AUTHTOKEN: "123", HMIPC_HAPID: "ABC1234", HMIPC_NAME: "name2"}
|
|
||||||
MockConfigEntry(domain=DOMAIN, data=mock_config2).add_to_hass(hass)
|
|
||||||
|
|
||||||
with patch("homeassistant.components.homematicip_cloud.HomematicipHAP") as mock_hap:
|
|
||||||
instance = mock_hap.return_value
|
|
||||||
instance.async_setup = AsyncMock(return_value=True)
|
|
||||||
instance.home.id = "1"
|
|
||||||
instance.home.modelType = "mock-type"
|
|
||||||
instance.home.name = "mock-name"
|
|
||||||
instance.home.label = "mock-label"
|
|
||||||
instance.home.currentAPVersion = "mock-ap-version"
|
|
||||||
instance.async_reset = AsyncMock(return_value=True)
|
|
||||||
|
|
||||||
assert await async_setup_component(hass, DOMAIN, {})
|
|
||||||
|
|
||||||
hmipc_services = hass.services.async_services()[DOMAIN]
|
|
||||||
assert len(hmipc_services) == 9
|
|
||||||
|
|
||||||
config_entries = hass.config_entries.async_entries(DOMAIN)
|
|
||||||
assert len(config_entries) == 2
|
|
||||||
# unload the first AP
|
|
||||||
await hass.config_entries.async_unload(config_entries[0].entry_id)
|
|
||||||
|
|
||||||
# services still exists
|
|
||||||
hmipc_services = hass.services.async_services()[DOMAIN]
|
|
||||||
assert len(hmipc_services) == 9
|
|
||||||
|
|
||||||
# unload the second AP
|
|
||||||
await hass.config_entries.async_unload(config_entries[1].entry_id)
|
|
||||||
|
|
||||||
# Check services are removed
|
|
||||||
assert not hass.services.async_services().get(DOMAIN)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user