From 853420d97259e07278a54439d9cec7c305becb7b Mon Sep 17 00:00:00 2001 From: Hans Oischinger Date: Tue, 5 Jan 2021 12:12:31 +0100 Subject: [PATCH] Add Vicare set mode service (#44563) * vicare: add set_vicare_mode service The set_vicare_mode service allows the user to set any of the possible heating modes of their heating device. Not just the ones that were mapped to home assistant climate modes. * vicare: Undo async changes and add heating mode Useless async changes were undone. To be able to set the most relevant modes the set_vicare_mode shall be able to also set the heating mode (without domestic hot water) * Extract kwarg and undo some more async changes Currectly extract the service argument Adapt according to review * Lint fixes * Replace kwargs with single arg Co-authored-by: Martin Hjelmare Co-authored-by: Martin Hjelmare --- homeassistant/components/vicare/climate.py | 47 ++++++++++++++----- homeassistant/components/vicare/services.yaml | 9 ++++ 2 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 homeassistant/components/vicare/services.yaml diff --git a/homeassistant/components/vicare/climate.py b/homeassistant/components/vicare/climate.py index ddfb28478df..d1accd8ea0a 100644 --- a/homeassistant/components/vicare/climate.py +++ b/homeassistant/components/vicare/climate.py @@ -2,6 +2,7 @@ import logging import requests +import voluptuous as vol from homeassistant.components.climate import ClimateEntity from homeassistant.components.climate.const import ( @@ -16,6 +17,7 @@ from homeassistant.components.climate.const import ( SUPPORT_TARGET_TEMPERATURE, ) from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, TEMP_CELSIUS +from homeassistant.helpers import entity_platform from . import ( DOMAIN as VICARE_DOMAIN, @@ -28,7 +30,11 @@ from . import ( _LOGGER = logging.getLogger(__name__) +SERVICE_SET_VICARE_MODE = "set_vicare_mode" +SERVICE_SET_VICARE_MODE_ATTR_MODE = "vicare_mode" + VICARE_MODE_DHW = "dhw" +VICARE_MODE_HEATING = "heating" VICARE_MODE_DHWANDHEATING = "dhwAndHeating" VICARE_MODE_DHWANDHEATINGCOOLING = "dhwAndHeatingCooling" VICARE_MODE_FORCEDREDUCED = "forcedReduced" @@ -55,6 +61,7 @@ SUPPORT_FLAGS_HEATING = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE VICARE_TO_HA_HVAC_HEATING = { VICARE_MODE_DHW: HVAC_MODE_OFF, + VICARE_MODE_HEATING: HVAC_MODE_HEAT, VICARE_MODE_DHWANDHEATING: HVAC_MODE_AUTO, VICARE_MODE_DHWANDHEATINGCOOLING: HVAC_MODE_AUTO, VICARE_MODE_FORCEDREDUCED: HVAC_MODE_OFF, @@ -79,22 +86,36 @@ HA_TO_VICARE_PRESET_HEATING = { } -def setup_platform(hass, config, add_entities, discovery_info=None): +async def async_setup_platform( + hass, hass_config, async_add_entities, discovery_info=None +): """Create the ViCare climate devices.""" if discovery_info is None: return vicare_api = hass.data[VICARE_DOMAIN][VICARE_API] heating_type = hass.data[VICARE_DOMAIN][VICARE_HEATING_TYPE] - add_entities( + async_add_entities( [ ViCareClimate( - f"{hass.data[VICARE_DOMAIN][VICARE_NAME]} Heating", + f"{hass.data[VICARE_DOMAIN][VICARE_NAME]} Heating", vicare_api, heating_type, ) ] ) + platform = entity_platform.current_platform.get() + + platform.async_register_entity_service( + SERVICE_SET_VICARE_MODE, + { + vol.Required(SERVICE_SET_VICARE_MODE_ATTR_MODE): vol.In( + VICARE_TO_HA_HVAC_HEATING + ), + }, + "set_vicare_mode", + ) + class ViCareClimate(ClimateEntity): """Representation of the ViCare heating climate device.""" @@ -154,7 +175,6 @@ class ViCareClimate(ClimateEntity): elif self._heating_type == HeatingType.heatpump: self._current_action = self._api.getCompressorActive() - except requests.exceptions.ConnectionError: _LOGGER.error("Unable to retrieve data from ViCare server") except ValueError: @@ -194,10 +214,9 @@ class ViCareClimate(ClimateEntity): """Set a new hvac mode on the ViCare API.""" vicare_mode = HA_TO_VICARE_HVAC_HEATING.get(hvac_mode) if vicare_mode is None: - _LOGGER.error( - "Cannot set invalid vicare mode: %s / %s", hvac_mode, vicare_mode + raise ValueError( + f"Cannot set invalid vicare mode: {hvac_mode} / {vicare_mode}" ) - return _LOGGER.debug("Setting hvac mode to %s / %s", hvac_mode, vicare_mode) self._api.setMode(vicare_mode) @@ -250,12 +269,9 @@ class ViCareClimate(ClimateEntity): """Set new preset mode and deactivate any existing programs.""" vicare_program = HA_TO_VICARE_PRESET_HEATING.get(preset_mode) if vicare_program is None: - _LOGGER.error( - "Cannot set invalid vicare program: %s / %s", - preset_mode, - vicare_program, + raise ValueError( + f"Cannot set invalid vicare program: {preset_mode}/{vicare_program}" ) - return _LOGGER.debug("Setting preset to %s / %s", preset_mode, vicare_program) self._api.deactivateProgram(self._current_program) @@ -265,3 +281,10 @@ class ViCareClimate(ClimateEntity): def device_state_attributes(self): """Show Device Attributes.""" return self._attributes + + def set_vicare_mode(self, vicare_mode): + """Service function to set vicare modes directly.""" + if vicare_mode not in VICARE_TO_HA_HVAC_HEATING: + raise ValueError(f"Cannot set invalid vicare mode: {vicare_mode}") + + self._api.setMode(vicare_mode) diff --git a/homeassistant/components/vicare/services.yaml b/homeassistant/components/vicare/services.yaml new file mode 100644 index 00000000000..2efaf530a9c --- /dev/null +++ b/homeassistant/components/vicare/services.yaml @@ -0,0 +1,9 @@ +set_vicare_mode: + description: Set a ViCare mode. + fields: + entity_id: + description: Name(s) of vicare climate entities. + example: "climate.vicare_heating" + vicare_mode: + description: ViCare mode. One of "dhw", "dhwAndHeating", "heating", "dhwAndHeatingCooling", "forcedReduced", "forcedNormal" or "standby" + example: "dhw"