diff --git a/README.md b/README.md index 6a8bd28..376a6bf 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ Automations require services to be able to send commande. Ex. light.turn_on. For - neviweb.set_aux_cycle_length, to set low voltage thermostat auxiliary cycle length and output. Values are: "15 sec", "5 min", "10 min", "15 min", "20 min", "25 min", "30 min". To trun on/off auxiliary heating just use the button at the bottom of the thermostat card. - neviweb.set_eco_status, to set eco status on/off of thermostats. - neviweb.set_switch_eco_status, to set switch eco status on/off. +- neviweb.set_em_heat, to turn on/off auxiliary/emergency heating. ## Catch Éco Sinopé signal for peak period diff --git a/custom_components.json b/custom_components.json index f55a9b9..03489c5 100644 --- a/custom_components.json +++ b/custom_components.json @@ -1,6 +1,6 @@ { "neviweb": { - "version": "2.1.7", + "version": "2.1.8", "local_location": "/custom_components/neviweb/__init__.py", "remote_location": "https://github.com/claudegel/sinope-1/tree/master/custom_components/neviweb/__init__.py", "visit_repo": "https://github.com/claudegel/sinope-1", diff --git a/custom_components/neviweb/__init__.py b/custom_components/neviweb/__init__.py index 99a4fb5..35f265a 100644 --- a/custom_components/neviweb/__init__.py +++ b/custom_components/neviweb/__init__.py @@ -46,7 +46,7 @@ ) #REQUIREMENTS = ['PY_Sinope==0.1.5'] -VERSION = '2.1.7' +VERSION = '2.1.8' _LOGGER = logging.getLogger(__name__) @@ -331,7 +331,7 @@ def get_device_daily_stats(self, device_id): if "values" in data: return data["values"] else: - _LOGGER.debug("Daily stat error: %s, %s", data, device_id) + _LOGGER.debug("Daily stat error: %s, device: %s", data, device_id) return None def get_device_hourly_stats(self, device_id): @@ -353,7 +353,7 @@ def get_device_hourly_stats(self, device_id): if "values" in data: return data["values"] else: - _LOGGER.debug("Hourly stat error: %s, %s", data, device_id) + _LOGGER.debug("Hourly stat error: %s, device: %s", data, device_id) return None def set_brightness(self, device_id, brightness): @@ -451,8 +451,8 @@ def set_setpoint_max(self, device_id, temp): _LOGGER.debug("setpointMax.data = %s", data) self.set_device_attributes(device_id, data) - def set_aux_heat(self, device_id, heat, cycle, floor): - """Set floor and low voltage thermostats auxiliary heating slave/off.""" + def set_em_heat(self, device_id, heat, cycle, floor): + """Set floor and low voltage thermostats emergency heating slave/off.""" if floor: data = {ATTR_AUX_CONFIG: heat} else: @@ -460,7 +460,7 @@ def set_aux_heat(self, device_id, heat, cycle, floor): data = {ATTR_AUX_CONFIG: heat} else: data = {ATTR_AUX_CONFIG: heat, ATTR_AUX_CYCLE_LENGTH: cycle} - _LOGGER.debug("aux_heat.data = %s", data) + _LOGGER.debug("em_heat.data = %s", data) self.set_device_attributes(device_id, data) def set_cycle_length(self, device_id, length): diff --git a/custom_components/neviweb/climate.py b/custom_components/neviweb/climate.py index ffbd566..240b1f7 100644 --- a/custom_components/neviweb/climate.py +++ b/custom_components/neviweb/climate.py @@ -89,11 +89,13 @@ ATTR_STATUS, ATTR_TEMP, ATTR_TIME, + ATTR_VALUE, ATTR_WATTAGE, ATTR_WATTAGE_OVERRIDE, MODE_AUTO, MODE_AUTO_BYPASS, MODE_AWAY, + MODE_EM_HEAT, MODE_FROST_PROTEC, MODE_MANUAL, MODE_OFF, @@ -103,6 +105,7 @@ SERVICE_SET_CLIMATE_KEYPAD_LOCK, SERVICE_SET_CYCLE_LENGTH, SERVICE_SET_EARLY_START, + SERVICE_SET_EM_HEAT, SERVICE_SET_SECOND_DISPLAY, SERVICE_SET_SETPOINT_MAX, SERVICE_SET_SETPOINT_MIN, @@ -114,7 +117,7 @@ _LOGGER = logging.getLogger(__name__) SUPPORT_FLAGS = (ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE) -SUPPORT_AUX_FLAGS = (ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.AUX_HEAT) +SUPPORT_AUX_FLAGS = (ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE) DEFAULT_NAME = "neviweb climate" @@ -264,6 +267,13 @@ } ) +SET_EM_HEAT_SCHEMA = vol.Schema( + { + vol.Required(ATTR_ENTITY_ID): cv.entity_id, + vol.Required(ATTR_VALUE): vol.In(["on", "off"]), + } +) + async def async_setup_platform( hass, config, @@ -423,6 +433,19 @@ def set_eco_status_service(service): thermostat.schedule_update_ha_state(True) break + def set_em_heat_service(service): + """Set emergency heat on/off for thermostats.""" + entity_id = service.data[ATTR_ENTITY_ID] + value = {} + for thermostat in entities: + if thermostat.entity_id == entity_id: + if service.data[ATTR_VALUE] == "on": + thermostat.turn_em_heat_on() + else: + thermostat.turn_em_heat_off() + thermostat.schedule_update_ha_state(True) + break + hass.services.async_register( DOMAIN, SERVICE_SET_SECOND_DISPLAY, @@ -507,6 +530,13 @@ def set_eco_status_service(service): schema=SET_ECO_STATUS_SCHEMA, ) + hass.services.async_register( + DOMAIN, + SERVICE_SET_EM_HEAT, + set_em_heat_service, + schema=SET_EM_HEAT_SCHEMA, + ) + def neviweb_to_ha(value): keys = [k for k, v in HA_TO_NEVIWEB_PERIOD.items() if v == value] if keys: @@ -540,7 +570,7 @@ def __init__(self, data, device_info, name, sku): self._operation_mode = None self._heat_level = 0 self._floor_mode = None - self._aux_heat = None + self._em_heat = None self._aux_wattage = None self._floor_air_limit = None self._floor_max = None @@ -648,7 +678,7 @@ def update(self): self._floor_temperature = device_data[ATTR_FLOOR_TEMP]["value"] self._floor_temp_error = device_data[ATTR_FLOOR_TEMP]["error"] if ATTR_AUX_CONFIG in device_data: - self._aux_heat = device_data[ATTR_AUX_CONFIG] + self._em_heat = device_data[ATTR_AUX_CONFIG] if ATTR_AUX_WATTAGE_OVERRIDE in device_data: self._aux_wattage = device_data[ATTR_AUX_WATTAGE_OVERRIDE] if ATTR_AUX_OUTPUT_STAGE in device_data: @@ -683,7 +713,7 @@ def update(self): self._floor_setpoint_max = device_data[ATTR_FLOOR_SETPOINT_MAX] self._floor_setpoint_min = device_data[ATTR_FLOOR_SETPOINT_MIN] self._cycle_length = device_data[ATTR_CYCLE_LENGTH] - self._aux_heat = device_data[ATTR_AUX_CONFIG] + self._em_heat = device_data[ATTR_AUX_CONFIG] self._aux_cycle_config = device_data[ATTR_AUX_CONFIG] self._aux_cycle_length = device_data[ATTR_AUX_CYCLE_LENGTH] self._aux_wattage = device_data[ATTR_AUX_WATTAGE_OVERRIDE] @@ -780,7 +810,7 @@ def extra_state_attributes(self): 'eco_power': self._shed_stat_power, 'eco_optout': self._shed_stat_optout}) if self._is_floor and not self._sku == "TH1500RF": - data.update({'auxiliary_status': self._aux_heat, + data.update({'auxiliary_status': self._em_heat, 'auxiliary_load': self._aux_wattage, 'aux_output_stage': self._aux_output_stage}) if self._is_floor: @@ -796,7 +826,7 @@ def extra_state_attributes(self): 'floor_setpoint_min': self._floor_setpoint_min}) if self._is_low_voltage: data.update({'sensor_mode': self._floor_mode, - 'auxiliary_status': self._aux_heat, + 'auxiliary_status': self._em_heat, 'auxiliary_load': self._aux_wattage, 'auxiliary_output_conf': self._aux_cycle_config, 'auxiliary_output_cycle': neviweb_to_ha(self._aux_cycle_length), @@ -813,6 +843,7 @@ def extra_state_attributes(self): 'pump_protection_freq': self._pump_protec_freq, 'pump_protection_duration': self._pump_protec_duration}) data.update ({'heat_level': self._heat_level, + 'pi_heating_demand': self._heat_level, 'wattage': self._wattage, 'hourly_kwh': self._hour_energy_kwh, 'daily_kwh': self._today_energy_kwh, @@ -846,9 +877,9 @@ def supported_features(self): return SUPPORT_FLAGS @property - def is_aux_heat(self): - """Return the min temperature.""" - return self._aux_heat in ["slave", "shortCycle", "longCycle"] + def is_em_heat(self): + """Return True if em_heat is active.""" + return self._em_heat in ["slave", "shortCycle", "longCycle"] @property def min_temp(self): @@ -1076,20 +1107,20 @@ def set_aux_cycle_length(self, value): self._aux_cycle_config = output self._aux_cycle_length = length - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" + def turn_em_heat_on(self): + """Turn emergency heater on.""" if self._is_floor: - self._aux_heat = "slave" + self._em_heat = "slave" else: if self._aux_cycle_length == "short": - self._aux_heat = "shortCycle" + self._em_heat = "shortCycle" else: - self._aux_heat = "longCycle" - self._client.set_aux_heat( - self._id, self._aux_heat, self._aux_cycle_length, self._is_floor) - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - self._aux_heat = "off" - self._client.set_aux_heat( + self._em_heat = "longCycle" + self._client.set_em_heat( + self._id, self._em_heat, self._aux_cycle_length, self._is_floor) + + def turn_em_heat_off(self): + """Turn emergency heater off.""" + self._em_heat = "off" + self._client.set_em_heat( self._id, "off", self._aux_cycle_length, self._is_floor) diff --git a/custom_components/neviweb/const.py b/custom_components/neviweb/const.py index 88c322c..5e7352c 100644 --- a/custom_components/neviweb/const.py +++ b/custom_components/neviweb/const.py @@ -58,6 +58,7 @@ ATTR_STATUS = "status" ATTR_SHED_PLANNING = "shedDayPlanningStatus" ATTR_LOCALSYNC = "localSync" +ATTR_VALUE = "value" MODE_AUTO = "auto" MODE_AUTO_BYPASS = "autoBypass" @@ -66,6 +67,7 @@ MODE_OFF = "off" MODE_HOME = "home" MODE_FROST_PROTEC = "frostProtection" +MODE_EM_HEAT = "emergencyHeat" SERVICE_SET_LED_INDICATOR = "set_led_indicator" SERVICE_SET_CLIMATE_KEYPAD_LOCK = "set_climate_keypad_lock" @@ -88,3 +90,4 @@ SERVICE_SET_CYCLE_LENGTH = "set_cycle_length" SERVICE_SET_ECO_STATUS = "set_eco_status" SERVICE_SET_SWITCH_ECO_STATUS = "set_switch_eco_status" +SERVICE_SET_EM_HEAT = "set_em_heat" diff --git a/custom_components/neviweb/manifest.json b/custom_components/neviweb/manifest.json index c88cc20..bf681de 100644 --- a/custom_components/neviweb/manifest.json +++ b/custom_components/neviweb/manifest.json @@ -5,5 +5,5 @@ "dependencies": [], "codeowners": ["@claudegel"], "requirements": [], - "version": "2.1.7" + "version": "2.1.8" } diff --git a/custom_components/neviweb/services.yaml b/custom_components/neviweb/services.yaml index 9d2fde6..2bdc4af 100644 --- a/custom_components/neviweb/services.yaml +++ b/custom_components/neviweb/services.yaml @@ -219,3 +219,12 @@ set_switch_eco_status: status: description: Set to «none» to turn off Eco-Sinope, to «planned» to turn on Eco-Sinope. example: "planned" + +set_em_heat: + description: Turn emergency heat on/off. + fields: + entity_id: + description: Name(s) of neviweb thermostat device. + example: "climate.neviweb_climate_office_floor" + value: + description: Set to «on» or «off» to turn_on or turn_off emergency heat.