From 2ab012de13fa2d8ac7b1c715935e9c05967c9edd Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 16:14:42 -0500 Subject: [PATCH 1/8] Add support for new HA climate horizontal swing --- custom_components/neviweb130/climate.py | 175 +++++++----------------- 1 file changed, 52 insertions(+), 123 deletions(-) diff --git a/custom_components/neviweb130/climate.py b/custom_components/neviweb130/climate.py index 9b81473..039298f 100644 --- a/custom_components/neviweb130/climate.py +++ b/custom_components/neviweb130/climate.py @@ -227,6 +227,8 @@ FAN_SPEED, FAN_CAPABILITY, FAN_SWING_CAPABILITY, + FULL_SWING, + FULL_SWING_OFF, PERIOD_VALUE, SET_ACTIVATION_SCHEMA, SET_AIR_FLOOR_MODE_SCHEMA, @@ -241,8 +243,6 @@ SET_DISPLAY_CONFIG_SCHEMA, SET_EARLY_START_SCHEMA, SET_EM_HEAT_SCHEMA, - SET_FAN_SWING_HORIZONTALL_SCHEMA, - SET_FAN_SWING_VERTICAL_SCHEMA, SET_FLOOR_AIR_LIMIT_SCHEMA, SET_FLOOR_LIMIT_HIGH_SCHEMA, SET_FLOOR_LIMIT_LOW_SCHEMA, @@ -280,6 +280,7 @@ ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.FAN_MODE + | ClimateEntityFeature.SWING_HORIZONTAL_MODE | ClimateEntityFeature.SWING_MODE | ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON @@ -355,11 +356,6 @@ ATTR_TIME, ] -FULL_SWING = ['swingFullRange'] -FULL_SWING_HORIZ = ['swingFullRangeHoriz'] -FULL_SWING_OFF = ['off'] -FULL_SWING_OFF_HORIZ = ['offHoriz'] - SUPPORTED_HVAC_WIFI_MODES = [ HVACMode.AUTO, HVACMode.HEAT, @@ -814,28 +810,6 @@ def set_sound_config_service(service): thermostat.schedule_update_ha_state(True) break - def set_fan_swing_horizontal_service(service): - """Set horizontal fan swing action for heat pump.""" - entity_id = service.data[ATTR_ENTITY_ID] - value = {} - for thermostat in entities: - if thermostat.entity_id == entity_id: - value = {"id": thermostat.unique_id, "swing": service.data[ATTR_FAN_SWING_HORIZ]} - thermostat.set_fan_swing_horizontal(value) - thermostat.schedule_update_ha_state(True) - break - - def set_fan_swing_vertical_service(service): - """Set vertical fan swing action for heat pump.""" - entity_id = service.data[ATTR_ENTITY_ID] - value = {} - for thermostat in entities: - if thermostat.entity_id == entity_id: - value = {"id": thermostat.unique_id, "swing": service.data[ATTR_FAN_SWING_VERT]} - thermostat.set_fan_swing_vertical(value) - thermostat.schedule_update_ha_state(True) - break - hass.services.async_register( DOMAIN, SERVICE_SET_SECOND_DISPLAY, @@ -1032,20 +1006,6 @@ def set_fan_swing_vertical_service(service): schema=SET_SOUND_CONFIG_SCHEMA, ) - hass.services.async_register( - DOMAIN, - SERVICE_SET_FAN_SWING_HORIZONTAL, - set_fan_swing_horizontal_service, - schema=SET_FAN_SWING_HORIZONTALL_SCHEMA, - ) - - hass.services.async_register( - DOMAIN, - SERVICE_SET_FAN_SWING_VERTICAL, - set_fan_swing_vertical_service, - schema=SET_FAN_SWING_VERTICAL_SCHEMA, - ) - def neviweb_to_ha(value): keys = [k for k, v in HA_TO_NEVIWEB_PERIOD.items() if v == value] if keys: @@ -1074,13 +1034,10 @@ def lock_to_ha(lock): case "partialLock": return "Tamper protection" -def extract_capability_full(sens, cap): - """Extract swing capability which are True for each HP device and add denegal capability.""" - if sens == "vert": - value = {i for i in cap if cap[i]==True} - return FULL_SWING_OFF + sorted(value) - value = {i+"Horiz" for i in cap if cap[i]==True} - return FULL_SWING_OFF_HORIZ + sorted(value) +def extract_capability_full(cap): + """Extract swing capability which are True for each HP device and add genegal capability.""" + value = {i for i in cap if cap[i]==True} + return FULL_SWING_OFF + sorted(value) def extract_capability(cap): """Extract capability which are True for each HP device.""" @@ -1409,6 +1366,16 @@ def target_cool_temperature(self) -> float: return self._cool_max return temp + @property + def preset_mode(self): + """Return current preset mode.""" + if self._occupancy == PRESET_HOME: + return PRESET_NONE + elif self._occupancy == PRESET_AWAY: + return PRESET_AWAY + else: + return PRESET_NONE + @property def preset_modes(self): """Return available preset modes.""" @@ -1421,16 +1388,6 @@ def preset_modes(self): else: return PRESET_MODES - @property - def preset_mode(self): - """Return current preset mode.""" - if self._occupancy == PRESET_HOME: - return PRESET_NONE - elif self._occupancy == PRESET_AWAY: - return PRESET_AWAY - else: - return PRESET_NONE - @property def hvac_action(self): """Return current HVAC action.""" @@ -1470,82 +1427,78 @@ def is_on(self): return True return False - @property - def fan_modes(self): - """Return available fan modes.""" - if self._is_HP or self._is_HC or self._is_hc: - return FAN_SPEED - else: - return None - @property def fan_mode(self) -> str | None: """Return the fan setting.""" return self._fan_speed - + @property - def swing_modes(self): - """Return available swing modes, vertical + horizontal.""" - if self._is_HP or self._is_hc: - return self.swing_modes_vertical + self.swing_modes_horizontal + def fan_modes(self) -> list[str] | None: + """Return available fan modes.""" + if self._is_HP or self._is_HC or self._is_hc: + return FAN_SPEED else: return None @property def swing_mode(self) -> str | None: - """Return the fan swing setting.""" - return self._fan_swing_vert + """Return the fan vertical swing setting.""" + if self._is_HP or self._is_hc: + return self._fan_swing_vert + return None @property - def swing_modes_vertical(self): - """Return available vertical swing modes""" + def swing_modes(self) -> list[str] | None: + """Return availables vertical swing modes.""" if self._is_HP or self._is_hc: if "fullVertical" in extract_capability(self._fan_swing_cap): - return FULL_SWING + extract_capability_full("vert", self._fan_swing_cap_vert) + return FULL_SWING + extract_capability_full(self._fan_swing_cap_vert) else: - return extract_capability_full("vert", self._fan_swing_cap_vert) + return extract_capability_full(self._fan_swing_cap_vert) else: return None @property - def swing_mode_vertical(self) -> str | None: + def swing_horizontal_mode(self) -> str | None: """Return the fan swing setting.""" - return self._fan_swing_vert + if self._is_HP or self._is_hc: + return self._fan_swing_horiz + return None @property - def swing_modes_horizontal(self): + def swing_horizontal_modes(self) -> list[str] | None: """Return available horizontal swing modes""" if self._is_HP or self._is_hc: if "fullHorizontal" in extract_capability(self._fan_swing_cap): - return FULL_SWING_HORIZ + extract_capability_full("horiz", self._fan_swing_cap_horiz) + return FULL_SWING + extract_capability_full(self._fan_swing_cap_horiz) else: - return extract_capability_full("horiz", self._fan_swing_cap_horiz) + return extract_capability_full(self._fan_swing_cap_horiz) else: return None - @property - def swing_mode_horizontal(self) -> str | None: - """Return the fan swing setting.""" - return self._fan_swing_horiz - - def set_fan_mode(self, speed): + def set_fan_mode(self, speed: str) -> None: """Set new fan mode.""" if speed is None: return self._client.set_fan_mode(self._id, speed) self._fan_speed = speed - def set_swing_mode(self, swing): - """Set new swing mode.""" + def set_swing_mode(self, swing: str) -> None: + """Set new vertical swing mode.""" if swing is None: return - elif swing[-5:] == "Horiz": - self._client.set_swing_horizontal(self._id, swing[:-5]) - self._fan_swing_horiz = swing[:-5] else: self._client.set_swing_vertical(self._id, swing) self._fan_swing_vert = swing + def set_swing_horizontal_mode(self, swing: str) -> None: + """Set new horizontal swing mode.""" + if swing is None: + return + else: + self._client.set_swing_horizontal(self._id, swing) + self._fan_swing_horiz = swing + def turn_on(self) -> None: """Turn the thermostat to HVACMode.heat on.""" self._client.set_setpoint_mode(self._id, HVACMode.HEAT, self._is_wifi) @@ -1900,30 +1853,6 @@ def set_sound_config(self, value): entity, sound) self._sound_conf = sound - def set_fan_swing_horizontal(self, value): - """Set horizontal fan swing action for heat pump.""" - swing = value["swing"] - entity = value["id"] - if swing[-5:] == "Horiz": - if swing not in FULL_SWING_HORIZ + extract_capability_full("horiz", self._fan_swing_cap_horiz): - self.notify_ha(f"Warning: Value " + swing + "selected for fan swing horizontal is not supported by " + self._name) - return - self._client.set_swing_horizontal(self._id, swing[:-5]) - self._fan_swing_horiz = swing[:-5] - else: - self._client.set_swing_horizontal(entity, swing) - self._fan_swing_horiz = swing - - def set_fan_swing_vertical(self, value): - """Set vertical fan swing action for heat pump.""" - swing = value["swing"] - entity = value["id"] - if swing not in FULL_SWING + extract_capability_full("vert", self._fan_swing_cap_vert): - self.notify_ha(f"Warning: Value selected for fan swing vertical is not supported by " + self._name) - return - self._client.set_swing_vertical(entity, swing) - self._fan_swing_vert = swing - def do_stat(self, start): """Get device energy statistic.""" if start - self._energy_stat_time > STAT_INTERVAL and self._energy_stat_time != 0: @@ -3570,8 +3499,8 @@ def extra_state_attributes(self): 'fan_swing_horizontal': self._fan_swing_horiz, 'fan_capability': extract_capability(self._fan_cap), 'fan_swing_capability': extract_capability(self._fan_swing_cap), - 'fan_swing_capability_vertical': extract_capability_full("vert", self._fan_swing_cap_vert), - 'fan_swing_capability_horizontal': extract_capability_full("horiz", self._fan_swing_cap_horiz), + 'fan_swing_capability_vertical': extract_capability_full(self._fan_swing_cap_vert), + 'fan_swing_capability_horizontal': extract_capability_full(self._fan_swing_cap_horiz), 'display_conf': self._display_conf, 'display_capability': extract_capability(self._display_cap), 'sound_conf': self._sound_conf, @@ -3776,8 +3705,8 @@ def extra_state_attributes(self): 'fan_swing_horizontal': self._fan_swing_horiz, 'fan_capability': self._fan_cap, 'fan_swing_capability': extract_capability(self._fan_swing_cap), - 'fan_swing_capability_vertical': extract_capability_full("vert", self._fan_swing_cap_vert), - 'fan_swing_capability_horizontal': extract_capability_full("horiz", self._fan_swing_cap_horiz), + 'fan_swing_capability_vertical': extract_capability_full(self._fan_swing_cap_vert), + 'fan_swing_capability_horizontal': extract_capability_full(self._fan_swing_cap_horiz), 'heat_pump_limit_temp': self._balance_pt, 'min_heat_pump_limit_temp': self._balance_pt_low, 'max_heat_pump_limit_temp': self._balance_pt_high, From ab1b2b873a3306b31e562f9decad982a6211a1fd Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 16:16:53 -0500 Subject: [PATCH 2/8] remove swing services --- custom_components/neviweb130/const.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/custom_components/neviweb130/const.py b/custom_components/neviweb130/const.py index 69ca067..e85298d 100644 --- a/custom_components/neviweb130/const.py +++ b/custom_components/neviweb130/const.py @@ -281,5 +281,3 @@ SERVICE_SET_HEAT_LOCKOUT_TEMPERATURE = "set_heat_lockout_temperature" SERVICE_SET_DISPLAY_CONFIG = "set_display_config" SERVICE_SET_SOUND_CONFIG = "set_sound_config" -SERVICE_SET_FAN_SWING_VERTICAL = "set_fan_swing_vertical" -SERVICE_SET_FAN_SWING_HORIZONTAL = "set_fan_swing_horizontal" From 5bcca8911680d2ed096a34d53f36f955c514a838 Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 16:25:29 -0500 Subject: [PATCH 3/8] Add new HA horizontal swing for climate --- custom_components/neviweb130/schema.py | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/custom_components/neviweb130/schema.py b/custom_components/neviweb130/schema.py index daf2f5e..3580bfb 100644 --- a/custom_components/neviweb130/schema.py +++ b/custom_components/neviweb130/schema.py @@ -90,7 +90,7 @@ """Default parameters values.""" -VERSION = '2.8.8' +VERSION = '2.8.9' SCAN_INTERVAL = timedelta(seconds=540) HOMEKIT_MODE = False STAT_INTERVAL = 1800 @@ -109,10 +109,12 @@ FAN_SWING_CAPABILITY = {"fullHorizontal", "autoHorizontal", "fullVertical", "autoVertical"} DISPLAY_CAPABILITY = {"enable", "disable"} SOUND_CAPABILITY = {"enable", "disable"} -SWING_CAPABILITY_VERTICAL = {'swingFullRange', 'off', 'fixedRegion1', 'fixedRegion2', 'fixedRegion3', 'fixedRegion4', 'fixedRegion5', 'fixedRegion6', 'fixedRegion7', 'fixedRegion8', +SWING_CAPABILITY_VERTICAL = {'swingFullRange', 'off', 'fixedRegion1', 'fixedRegion2', 'fixedRegion3', 'fixedRegion4', 'fixedRegion5', 'fixedRegion6', 'fixedRegion7', 'fixedRegion8', \ 'swingRegion1','swingRegion2','swingRegion3','swingRegion3','swingRegion5','swingRegion6','swingRegion7','swingRegion8'} -SWING_CAPABILITY_HORIZONTAL = {'swingFullRange', 'off', 'fixedRegion1', 'fixedRegion2', 'fixedRegion3', 'fixedRegion4', 'fixedRegion5', 'fixedRegion6', 'fixedRegion7', 'fixedRegion8', +SWING_CAPABILITY_HORIZONTAL = {'swingFullRange', 'off', 'fixedRegion1', 'fixedRegion2', 'fixedRegion3', 'fixedRegion4', 'fixedRegion5', 'fixedRegion6', 'fixedRegion7', 'fixedRegion8', \ 'swingRegion1','swingRegion2','swingRegion3','swingRegion3','swingRegion5','swingRegion6','swingRegion7','swingRegion8'} +FULL_SWING = ['swingFullRange'] +FULL_SWING_OFF = ['off'] """Config schema.""" @@ -373,24 +375,6 @@ } ) -SET_FAN_SWING_VERTICAL_SCHEMA = vol.Schema( - { - vol.Required(ATTR_ENTITY_ID): cv.entity_id, - vol.Required(ATTR_FAN_SWING_VERT): vol.All( - cv.ensure_list, [vol.In(SWING_CAPABILITY_VERTICAL)] - ), - } -) - -SET_FAN_SWING_HORIZONTALL_SCHEMA = vol.Schema( - { - vol.Required(ATTR_ENTITY_ID): cv.entity_id, - vol.Required(ATTR_FAN_SWING_HORIZ): vol.All( - cv.ensure_list, [vol.In(SWING_CAPABILITY_HORIZONTAL)] - ), - } -) - """light schema.""" SET_LIGHT_KEYPAD_LOCK_SCHEMA = vol.Schema( From 3209ff6724ac2f63e4a00deb5dae1f52d29182bd Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 16:29:02 -0500 Subject: [PATCH 4/8] Remove swing services --- custom_components/neviweb130/services.yaml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/custom_components/neviweb130/services.yaml b/custom_components/neviweb130/services.yaml index 3dfef7f..e1d5ec0 100644 --- a/custom_components/neviweb130/services.yaml +++ b/custom_components/neviweb130/services.yaml @@ -652,23 +652,3 @@ set_sound_config: soundConfig: description: possible values, enabled, disabled. example: "disabled" - -set_fan_swing_horizontal: - description: Set horizontal fan swing action for heat pump. - fields: - entity_id: - description: Name(s) of neviweb130 thermostat HP6000 device. - example: "climate.neviweb130_climate_HP6000ZB-GE" - fanSwingHorizontal: - description: For possible values, check fan_swing_capability_vertical attribute of your device. - example: "swingFullRange" - -set_fan_swing_vertical: - description: Set vertical fan swing action for heat pump. - fields: - entity_id: - description: Name(s) of neviweb130 thermostat HP6000 device. - example: "climate.neviweb130_climate_HP6000ZB-GE" - fanSwingVertical: - description: For possible values, check fan_swing_capability_horizontal attribute of your device. - example: "swingFullRange" From dddd2330d20ff8b6aa76cbc23940960b96faa5a7 Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 17:20:40 -0500 Subject: [PATCH 5/8] Remove service for swing mode --- custom_components/neviweb130/climate.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/custom_components/neviweb130/climate.py b/custom_components/neviweb130/climate.py index 039298f..e0d7a92 100644 --- a/custom_components/neviweb130/climate.py +++ b/custom_components/neviweb130/climate.py @@ -203,8 +203,6 @@ SERVICE_SET_DISPLAY_CONFIG, SERVICE_SET_EARLY_START, SERVICE_SET_EM_HEAT, - SERVICE_SET_FAN_SWING_HORIZONTAL, - SERVICE_SET_FAN_SWING_VERTICAL, SERVICE_SET_FLOOR_AIR_LIMIT, SERVICE_SET_FLOOR_LIMIT_HIGH, SERVICE_SET_FLOOR_LIMIT_LOW, From f8b7a1a9f9e24c425ef1744e7fe21e7f9202fd3f Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 19:03:13 -0500 Subject: [PATCH 6/8] remove swing services --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 69410da..33df00c 100644 --- a/README.md +++ b/README.md @@ -234,8 +234,6 @@ Automations require services to be able to send commande. Ex. light.turn_on. For - neviweb130.set_em_heat to turn on/off aux heat for floor and low voltage thermostats. This is a replacement of turn_aux_heat_on or off that was deprecated by HA. - neviweb130.set_display_config to set on/off display on heatpump. - neviweb130.set_sound_config to set on/off sound on heatpump. -- neviweb130.set_fan_swing_horizontal to set various vertical fan swing modes for heatpump. -- neviweb130.set_fan_swing_vertical to set various horizontal swing modes for heatpump. - neviweb130.set_heat_pump_operation_limit to set minimum operation temperature for heatpump. - neviweb130.set_heat_lockout_temperature to set maximum outside temperature limit to allow heating device operation. - neviweb130.set_cool_lockout_temperature to set minimum outside temperature limit to allow cooling device operation. From 867db82f3996e7d1842c0f439c4adb8fee931861 Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 20:14:18 -0500 Subject: [PATCH 7/8] Push version to 2.8.9 --- custom_components.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components.json b/custom_components.json index 0559eeb..3baac05 100644 --- a/custom_components.json +++ b/custom_components.json @@ -1,6 +1,6 @@ { "neviweb130": { - "version": "2.8.8", + "version": "2.8.9", "local_location": "/custom_components/neviweb130/__init__.py", "remote_location": "https://github.com/claudegel/sinope-130/tree/master/custom_components/__init__.py", "visit_repo": "https://github.com/claudegel/sinope-130", From 643c7f6871488684b16e3ab99676035d6cade09e Mon Sep 17 00:00:00 2001 From: Claude Gelinas Date: Sun, 8 Dec 2024 20:15:32 -0500 Subject: [PATCH 8/8] Push version to 2.8.9 --- custom_components/neviweb130/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/neviweb130/manifest.json b/custom_components/neviweb130/manifest.json index c2c3f27..0822458 100644 --- a/custom_components/neviweb130/manifest.json +++ b/custom_components/neviweb130/manifest.json @@ -5,6 +5,6 @@ "dependencies": [], "codeowners": ["@claudegel"], "requirements": [], - "version": "2.8.7", + "version": "2.8.9", "homeassistant": "2024.2.1" }