Show default profiles in homematic cloud climate entity (#107348)

* Default names for visible profiles

* Increase number of devices in test

* remove unnecessary check

* Add testcase and split another into two

* Add type annotations and docstring

* Remove code which not belongs to the PR

* Add myself to codeowners
This commit is contained in:
hahn-th 2024-04-19 08:09:48 +02:00 committed by GitHub
parent 4cce75177a
commit ed4f00279e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 462 additions and 16 deletions

View File

@ -599,6 +599,8 @@ build.json @home-assistant/supervisor
/tests/components/homekit_controller/ @Jc2k @bdraco
/homeassistant/components/homematic/ @pvizeli
/tests/components/homematic/ @pvizeli
/homeassistant/components/homematicip_cloud/ @hahn-th
/tests/components/homematicip_cloud/ @hahn-th
/homeassistant/components/homewizard/ @DCSBL
/tests/components/homewizard/ @DCSBL
/homeassistant/components/honeywell/ @rdfurman @mkmer

View File

@ -13,6 +13,7 @@ from homematicip.aio.group import AsyncHeatingGroup
from homematicip.base.enums import AbsenceType
from homematicip.device import Switch
from homematicip.functionalHomes import IndoorClimateHome
from homematicip.group import HeatingCoolingProfile
from homeassistant.components.climate import (
PRESET_AWAY,
@ -35,6 +36,14 @@ from .hap import HomematicipHAP
HEATING_PROFILES = {"PROFILE_1": 0, "PROFILE_2": 1, "PROFILE_3": 2}
COOLING_PROFILES = {"PROFILE_4": 3, "PROFILE_5": 4, "PROFILE_6": 5}
NICE_PROFILE_NAMES = {
"PROFILE_1": "Default",
"PROFILE_2": "Alternative 1",
"PROFILE_3": "Alternative 2",
"PROFILE_4": "Cooling 1",
"PROFILE_5": "Cooling 2",
"PROFILE_6": "Cooling 3",
}
ATTR_PRESET_END_TIME = "preset_end_time"
PERMANENT_END_TIME = "permanent"
@ -164,8 +173,9 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
return PRESET_ECO
return (
self._device.activeProfile.name
if self._device.activeProfile.name in self._device_profile_names
self._get_qualified_profile_name(self._device.activeProfile)
if self._get_qualified_profile_name(self._device.activeProfile)
in self._device_profile_names
else None
)
@ -218,9 +228,6 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set new preset mode."""
if preset_mode not in self.preset_modes:
return
if self._device.boostMode and preset_mode != PRESET_BOOST:
await self._device.set_boost(False)
if preset_mode == PRESET_BOOST:
@ -256,20 +263,30 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
return self._home.get_functionalHome(IndoorClimateHome)
@property
def _device_profiles(self) -> list[Any]:
def _device_profiles(self) -> list[HeatingCoolingProfile]:
"""Return the relevant profiles."""
return [
profile
for profile in self._device.profiles
if profile.visible
and profile.name != ""
and profile.index in self._relevant_profile_group
if profile.visible and profile.index in self._relevant_profile_group
]
@property
def _device_profile_names(self) -> list[str]:
"""Return a collection of profile names."""
return [profile.name for profile in self._device_profiles]
return [
self._get_qualified_profile_name(profile)
for profile in self._device_profiles
]
def _get_qualified_profile_name(self, profile: HeatingCoolingProfile) -> str:
"""Get a name for the given profile. If exists, this is the name of the profile."""
if profile.name != "":
return profile.name
if profile.index in NICE_PROFILE_NAMES:
return NICE_PROFILE_NAMES[profile.index]
return profile.index
def _get_profile_idx_by_name(self, profile_name: str) -> int:
"""Return a profile index by name."""
@ -277,7 +294,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
index_name = [
profile.index
for profile in self._device_profiles
if profile.name == profile_name
if self._get_qualified_profile_name(profile) == profile_name
]
return relevant_index[index_name[0]]

View File

@ -1,7 +1,7 @@
{
"domain": "homematicip_cloud",
"name": "HomematicIP Cloud",
"codeowners": [],
"codeowners": ["@hahn-th"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/homematicip_cloud",
"iot_class": "cloud_push",

View File

@ -4791,6 +4791,59 @@
"type": "HEATING_THERMOSTAT",
"updateState": "UP_TO_DATE"
},
"3014F71100000000ETRV0013": {
"automaticValveAdaptionNeeded": false,
"availableFirmwareVersion": "2.0.2",
"connectionType": "HMIP_RF",
"firmwareVersion": "2.0.2",
"firmwareVersionInteger": 131074,
"functionalChannels": {
"0": {
"configPending": false,
"deviceId": "3014F71100000000ETRV0013",
"dutyCycle": false,
"functionalChannelType": "DEVICE_OPERATIONLOCK",
"groupIndex": 0,
"groups": ["00000000-0000-0000-0000-000000000014"],
"index": 0,
"label": "",
"lowBat": false,
"operationLockActive": false,
"routerModuleEnabled": false,
"routerModuleSupported": false,
"rssiDeviceValue": -58,
"rssiPeerValue": -58,
"unreach": false,
"supportedOptionalFeatures": {}
},
"1": {
"deviceId": "3014F71100000000ETRV0013",
"functionalChannelType": "HEATING_THERMOSTAT_CHANNEL",
"groupIndex": 1,
"groups": ["00000000-0000-0000-0005-000000000019"],
"index": 1,
"label": "",
"valveActualTemperature": 20.0,
"setPointTemperature": 5.0,
"temperatureOffset": 0.0,
"valvePosition": 0.0,
"valveState": "ADAPTION_DONE"
}
},
"homeId": "00000000-0000-0000-0000-000000000001",
"id": "3014F71100000000ETRV0013",
"label": "Heizkörperthermostat4",
"lastStatusUpdate": 1524514007132,
"liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED",
"manufacturerCode": 1,
"modelId": 269,
"modelType": "HMIP-eTRV",
"oem": "eQ-3",
"permanentlyReachable": true,
"serializedGlobalTradeItemNumber": "3014F71100000000ETRV0013",
"type": "HEATING_THERMOSTAT",
"updateState": "UP_TO_DATE"
},
"3014F7110000000000000014": {
"automaticValveAdaptionNeeded": false,
"availableFirmwareVersion": "2.0.2",
@ -8535,6 +8588,297 @@
"windowOpenTemperature": 5.0,
"windowState": null
},
"00000000-0000-0000-0005-000000000019": {
"activeProfile": "PROFILE_1",
"actualTemperature": null,
"boostDuration": 15,
"boostMode": false,
"channels": [
{
"channelIndex": 1,
"deviceId": "3014F71100000000ETRV0013"
}
],
"controlMode": "AUTOMATIC",
"controllable": true,
"cooling": null,
"coolingAllowed": false,
"coolingIgnored": false,
"dutyCycle": false,
"ecoAllowed": true,
"ecoIgnored": false,
"externalClockCoolingTemperature": 23.0,
"externalClockEnabled": false,
"externalClockHeatingTemperature": 19.0,
"floorHeatingMode": "FLOOR_HEATING_STANDARD",
"homeId": "00000000-0000-0000-0000-000000000001",
"humidity": null,
"humidityLimitEnabled": true,
"humidityLimitValue": 60,
"id": "00000000-0000-0000-0005-000000000019",
"label": "Vorzimmer3",
"lastSetPointReachedTimestamp": 1557767559939,
"lastSetPointUpdatedTimestamp": 1557767559939,
"lastStatusUpdate": 1524514007132,
"lowBat": false,
"maxTemperature": 30.0,
"metaGroupId": "00000000-0000-0000-0000-000000000014",
"minTemperature": 5.0,
"partyMode": false,
"profiles": {
"PROFILE_1": {
"enabled": true,
"groupId": "00000000-0000-0000-0005-000000000019",
"index": "PROFILE_1",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000058",
"visible": true
},
"PROFILE_2": {
"enabled": true,
"groupId": "00000000-0000-0000-0005-000000000019",
"index": "PROFILE_2",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000059",
"visible": true
},
"PROFILE_3": {
"enabled": true,
"groupId": "00000000-0000-0000-0005-000000000019",
"index": "PROFILE_3",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000060",
"visible": false
},
"PROFILE_4": {
"enabled": false,
"groupId": "00000000-0000-0000-0005-000000000019",
"index": "PROFILE_4",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000061",
"visible": true
},
"PROFILE_5": {
"enabled": false,
"groupId": "00000000-0000-0000-0005-000000000019",
"index": "PROFILE_5",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000062",
"visible": false
},
"PROFILE_6": {
"enabled": false,
"groupId": "00000000-0000-0000-0005-000000000019",
"index": "PROFILE_6",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000063",
"visible": false
}
},
"setPointTemperature": 5.0,
"type": "HEATING",
"unreach": false,
"valvePosition": 0.0,
"valveSilentModeEnabled": false,
"valveSilentModeSupported": false,
"heatingFailureSupported": true,
"windowOpenTemperature": 5.0,
"windowState": null
},
"00000000-0000-0000-0001-000000000019": {
"activeProfile": "PROFILE_1",
"actualTemperature": null,
"boostDuration": 15,
"boostMode": false,
"channels": [
{
"channelIndex": 1,
"deviceId": "3014F7110000000000000013"
}
],
"controlMode": "AUTOMATIC",
"controllable": true,
"cooling": null,
"coolingAllowed": false,
"coolingIgnored": false,
"dutyCycle": false,
"ecoAllowed": true,
"ecoIgnored": false,
"externalClockCoolingTemperature": 23.0,
"externalClockEnabled": false,
"externalClockHeatingTemperature": 19.0,
"floorHeatingMode": "FLOOR_HEATING_STANDARD",
"homeId": "00000000-0000-0000-0000-000000000001",
"humidity": null,
"humidityLimitEnabled": true,
"humidityLimitValue": 60,
"id": "00000000-0000-0000-0001-000000000019",
"label": "Vorzimmer",
"lastSetPointReachedTimestamp": 1557767559939,
"lastSetPointUpdatedTimestamp": 1557767559939,
"lastStatusUpdate": 1524514007132,
"lowBat": false,
"maxTemperature": 30.0,
"metaGroupId": "00000000-0000-0000-0000-000000000014",
"minTemperature": 5.0,
"partyMode": false,
"profiles": {
"PROFILE_1": {
"enabled": true,
"groupId": "00000000-0000-0000-0001-000000000019",
"index": "PROFILE_1",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000058",
"visible": true
},
"PROFILE_2": {
"enabled": true,
"groupId": "00000000-0000-0000-0001-000000000019",
"index": "PROFILE_2",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000059",
"visible": false
},
"PROFILE_3": {
"enabled": true,
"groupId": "00000000-0000-0000-0001-000000000019",
"index": "PROFILE_3",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000060",
"visible": false
},
"PROFILE_4": {
"enabled": false,
"groupId": "00000000-0000-0000-0001-000000000019",
"index": "PROFILE_4",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000061",
"visible": true
},
"PROFILE_5": {
"enabled": false,
"groupId": "00000000-0000-0000-0001-000000000019",
"index": "PROFILE_5",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000062",
"visible": false
},
"PROFILE_6": {
"enabled": false,
"groupId": "00000000-0000-0000-0001-000000000019",
"index": "PROFILE_6",
"name": "",
"profileId": "00000000-0000-0000-0000-000000000063",
"visible": false
}
},
"setPointTemperature": 5.0,
"type": "HEATING",
"unreach": false,
"valvePosition": 0.0,
"valveSilentModeEnabled": false,
"valveSilentModeSupported": false,
"heatingFailureSupported": true,
"windowOpenTemperature": 5.0,
"windowState": null
},
"00000000-0000-0001-0001-000000000019": {
"activeProfile": "PROFILE_1",
"actualTemperature": null,
"boostDuration": 15,
"boostMode": false,
"channels": [
{
"channelIndex": 1,
"deviceId": "3014F7110000000000000013"
}
],
"controlMode": "AUTOMATIC",
"controllable": true,
"cooling": null,
"coolingAllowed": false,
"coolingIgnored": false,
"dutyCycle": false,
"ecoAllowed": true,
"ecoIgnored": false,
"externalClockCoolingTemperature": 23.0,
"externalClockEnabled": false,
"externalClockHeatingTemperature": 19.0,
"floorHeatingMode": "FLOOR_HEATING_STANDARD",
"homeId": "00000000-0000-0000-0000-000000000001",
"humidity": null,
"humidityLimitEnabled": true,
"humidityLimitValue": 60,
"id": "00000000-0000-0001-0001-000000000019",
"label": "Vorzimmer2",
"lastSetPointReachedTimestamp": 1557767559939,
"lastSetPointUpdatedTimestamp": 1557767559939,
"lastStatusUpdate": 1524514007132,
"lowBat": false,
"maxTemperature": 30.0,
"metaGroupId": "00000000-0000-0000-0000-000000000014",
"minTemperature": 5.0,
"partyMode": false,
"profiles": {
"PROFILE_1": {
"enabled": true,
"groupId": "00000000-0000-0001-0001-000000000019",
"index": "PROFILE_1",
"name": "Testprofile",
"profileId": "00000000-0000-0000-0001-000000000058",
"visible": true
},
"PROFILE_2": {
"enabled": true,
"groupId": "00000000-0000-0001-0001-000000000019",
"index": "PROFILE_2",
"name": "",
"profileId": "00000000-0000-0000-0001-000000000059",
"visible": true
},
"PROFILE_3": {
"enabled": true,
"groupId": "00000000-0000-0001-0001-000000000019",
"index": "PROFILE_3",
"name": "",
"profileId": "00000000-0000-0000-0001-000000000060",
"visible": false
},
"PROFILE_4": {
"enabled": false,
"groupId": "00000000-0000-0001-0001-000000000019",
"index": "PROFILE_4",
"name": "",
"profileId": "00000000-0000-0000-0001-000000000061",
"visible": true
},
"PROFILE_5": {
"enabled": false,
"groupId": "00000000-0000-0001-0001-000000000019",
"index": "PROFILE_5",
"name": "",
"profileId": "00000000-0000-0000-0001-000000000062",
"visible": false
},
"PROFILE_6": {
"enabled": false,
"groupId": "00000000-0000-0001-0001-000000000019",
"index": "PROFILE_6",
"name": "",
"profileId": "00000000-0000-0000-0001-000000000063",
"visible": false
}
},
"setPointTemperature": 5.0,
"type": "HEATING",
"unreach": false,
"valvePosition": 0.0,
"valveSilentModeEnabled": false,
"valveSilentModeSupported": false,
"heatingFailureSupported": true,
"windowOpenTemperature": 5.0,
"windowState": null
},
"00000000-AAAA-0000-0000-000000000001": {
"actualTemperature": 15.4,
"channels": [

View File

@ -1,6 +1,7 @@
"""Tests for HomematicIP Cloud climate."""
import datetime
from unittest.mock import patch
from homematicip.base.enums import AbsenceType
from homematicip.functionalHomes import IndoorClimateHome
@ -15,7 +16,6 @@ from homeassistant.components.climate import (
PRESET_AWAY,
PRESET_BOOST,
PRESET_ECO,
PRESET_NONE,
HVACAction,
HVACMode,
)
@ -217,12 +217,14 @@ async def test_hmip_heating_group_heat(
ha_state = hass.states.get(entity_id)
assert ha_state.state == HVACMode.AUTO
# hvac mode "dry" is not available. expect a valueerror.
await hass.services.async_call(
"climate",
"set_hvac_mode",
{"entity_id": entity_id, "hvac_mode": "dry"},
blocking=True,
)
assert len(hmip_device.mock_calls) == service_call_counter + 24
# Only fire event from last async_manipulate_test_data available.
assert hmip_device.mock_calls[-1][0] == "fire_update_event"
@ -429,14 +431,95 @@ async def test_hmip_heating_group_heat_with_radiator(
assert ha_state.attributes["min_temp"] == 5.0
assert ha_state.attributes["max_temp"] == 30.0
assert ha_state.attributes["temperature"] == 5.0
assert ha_state.attributes[ATTR_PRESET_MODE] is None
assert ha_state.attributes[ATTR_PRESET_MODE] == "Default"
assert ha_state.attributes[ATTR_PRESET_MODES] == [
PRESET_NONE,
PRESET_BOOST,
PRESET_ECO,
"Default",
]
async def test_hmip_heating_profile_default_name(
hass: HomeAssistant, default_mock_hap_factory
) -> None:
"""Test visible profile 1 without a name should be displayed as 'Default'."""
entity_id = "climate.vorzimmer3"
entity_name = "Vorzimmer3"
device_model = None
mock_hap = await default_mock_hap_factory.async_get_mock_hap(
test_devices=["Heizkörperthermostat4"],
test_groups=[entity_name],
)
ha_state, hmip_device = get_and_check_entity_basics(
hass, mock_hap, entity_id, entity_name, device_model
)
assert hmip_device
assert ha_state.state == HVACMode.AUTO
assert ha_state.attributes[ATTR_PRESET_MODES] == [
PRESET_BOOST,
PRESET_ECO,
"Default",
"Alternative 1",
]
async def test_hmip_heating_profile_naming(
hass: HomeAssistant, default_mock_hap_factory
) -> None:
"""Test Heating Profile Naming."""
entity_id = "climate.vorzimmer2"
entity_name = "Vorzimmer2"
device_model = None
mock_hap = await default_mock_hap_factory.async_get_mock_hap(
test_devices=["Heizkörperthermostat2"],
test_groups=[entity_name],
)
ha_state, hmip_device = get_and_check_entity_basics(
hass, mock_hap, entity_id, entity_name, device_model
)
assert hmip_device
assert ha_state.state == HVACMode.AUTO
assert ha_state.attributes[ATTR_PRESET_MODES] == [
PRESET_BOOST,
PRESET_ECO,
"Testprofile",
"Alternative 1",
]
async def test_hmip_heating_profile_name_not_in_list(
hass: HomeAssistant, default_mock_hap_factory
) -> None:
"""Test set profile when profile is not in available profiles."""
expected_profile = "Testprofile"
entity_id = "climate.vorzimmer2"
entity_name = "Vorzimmer2"
device_model = None
mock_hap = await default_mock_hap_factory.async_get_mock_hap(
test_devices=["Heizkörperthermostat2"],
test_groups=[entity_name],
)
ha_state, hmip_device = get_and_check_entity_basics(
hass, mock_hap, entity_id, entity_name, device_model
)
with patch(
"homeassistant.components.homematicip_cloud.climate.NICE_PROFILE_NAMES",
return_value={},
):
await hass.services.async_call(
"climate",
"set_preset_mode",
{"entity_id": entity_id, "preset_mode": expected_profile},
blocking=True,
)
ha_state = hass.states.get(entity_id)
assert ha_state.attributes[ATTR_PRESET_MODE] == expected_profile
async def test_hmip_climate_services(
hass: HomeAssistant, mock_hap_with_service
) -> None:

View File

@ -26,7 +26,7 @@ async def test_hmip_load_all_supported_devices(
test_devices=None, test_groups=None
)
assert len(mock_hap.hmip_device_by_entity_id) == 272
assert len(mock_hap.hmip_device_by_entity_id) == 278
async def test_hmip_remove_device(