Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Ongoing

- A zone shows the cooling setpoint of each preset only when the gateway has cooling and cooling is allowed for that zone. A zone that may not cool shows the heating setpoint alone, and, when no schedule is selected, reports heating as its climate mode.
- Setting the heating setpoint of a preset no longer fails in a zone that may not cool when the value is above the cooling setpoint stored for that zone.

## v1.15.0

- Contribution PR's [#936](https://github.com/plugwise/python-plugwise/pull/936) and [#938](https://github.com/plugwise/python-plugwise/pull/938) by @MartvanMale:
Expand Down
98 changes: 34 additions & 64 deletions fixtures/adam_heatpump_cooling/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,7 @@
"asleep_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 18.0,
"setpoint": 18.0,
"upper_bound": 30.0
},
"available_schedules": [
Expand All @@ -191,27 +190,24 @@
"away_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 25.0,
"setpoint_low": 18.5,
"setpoint": 18.5,
"upper_bound": 30.0
},
"climate_mode": "cool",
"climate_mode": "heat",
"control_state": "idle",
"dev_class": "climate",
"home_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 18.0,
"setpoint": 18.0,
"upper_bound": 30.0
},
"model": "ThermoZone",
"name": "Slaapkamer DB",
"no_frost_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 30.0,
"setpoint_low": 10.0,
"setpoint": 10.0,
"upper_bound": 30.0
},
"preset_modes": [
Expand Down Expand Up @@ -243,8 +239,7 @@
"vacation_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 28.0,
"setpoint_low": 16.0,
"setpoint": 16.0,
"upper_bound": 30.0
},
"vendor": "Plugwise",
Expand Down Expand Up @@ -341,8 +336,7 @@
"asleep_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 23.0,
"setpoint_low": 20.5,
"setpoint": 20.5,
"upper_bound": 30.0
},
"available_schedules": [
Expand All @@ -354,8 +348,7 @@
"away_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 25.0,
"setpoint_low": 20.5,
"setpoint": 20.5,
"upper_bound": 30.0
},
"climate_mode": "auto",
Expand All @@ -364,17 +357,15 @@
"home_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 20.5,
"setpoint": 20.5,
"upper_bound": 30.0
},
"model": "ThermoZone",
"name": "Badkamer 2",
"no_frost_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 30.0,
"setpoint_low": 10.0,
"setpoint": 10.0,
"upper_bound": 30.0
},
"preset_modes": [
Expand Down Expand Up @@ -405,8 +396,7 @@
"vacation_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 28.0,
"setpoint_low": 16.0,
"setpoint": 16.0,
"upper_bound": 30.0
},
"vendor": "Plugwise",
Expand Down Expand Up @@ -536,8 +526,7 @@
"asleep_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 23.0,
"setpoint_low": 20.5,
"setpoint": 20.5,
"upper_bound": 30.0
},
"available_schedules": [
Expand All @@ -549,8 +538,7 @@
"away_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 25.0,
"setpoint_low": 20.5,
"setpoint": 20.5,
"upper_bound": 30.0
},
"climate_mode": "auto",
Expand All @@ -559,17 +547,15 @@
"home_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 20.5,
"setpoint": 20.5,
"upper_bound": 30.0
},
"model": "ThermoZone",
"name": "Badkamer 1",
"no_frost_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 30.0,
"setpoint_low": 10.0,
"setpoint": 10.0,
"upper_bound": 30.0
},
"preset_modes": [
Expand Down Expand Up @@ -601,8 +587,7 @@
"vacation_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 28.0,
"setpoint_low": 16.0,
"setpoint": 16.0,
"upper_bound": 30.0
},
"vendor": "Plugwise",
Expand All @@ -617,8 +602,7 @@
"asleep_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 18.0,
"setpoint": 18.0,
"upper_bound": 30.0
},
"available_schedules": [
Expand All @@ -630,27 +614,24 @@
"away_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 25.0,
"setpoint_low": 18.5,
"setpoint": 18.5,
"upper_bound": 30.0
},
"climate_mode": "cool",
"climate_mode": "heat",
"control_state": "idle",
"dev_class": "climate",
"home_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 20.0,
"setpoint": 20.0,
"upper_bound": 30.0
},
"model": "ThermoZone",
"name": "Slaapkamer RB",
"no_frost_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 30.0,
"setpoint_low": 10.0,
"setpoint": 10.0,
"upper_bound": 30.0
},
"preset_modes": [
Expand Down Expand Up @@ -681,8 +662,7 @@
"vacation_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 28.0,
"setpoint_low": 16.0,
"setpoint": 16.0,
"upper_bound": 30.0
},
"vendor": "Plugwise",
Expand Down Expand Up @@ -899,8 +879,7 @@
"asleep_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 17.5,
"setpoint": 17.5,
"upper_bound": 30.0
},
"available_schedules": [
Expand All @@ -912,27 +891,24 @@
"away_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 25.0,
"setpoint_low": 18.0,
"setpoint": 18.0,
"upper_bound": 30.0
},
"climate_mode": "cool",
"climate_mode": "heat",
"control_state": "idle",
"dev_class": "climate",
"home_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 18.0,
"setpoint": 18.0,
"upper_bound": 30.0
},
"model": "ThermoZone",
"name": "Bijkeuken",
"no_frost_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 30.0,
"setpoint_low": 10.0,
"setpoint": 10.0,
"upper_bound": 30.0
},
"preset_modes": [
Expand Down Expand Up @@ -964,8 +940,7 @@
"vacation_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 28.0,
"setpoint_low": 16.0,
"setpoint": 16.0,
"upper_bound": 30.0
},
"vendor": "Plugwise",
Expand Down Expand Up @@ -1078,8 +1053,7 @@
"asleep_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 21.5,
"setpoint_low": 17.5,
"setpoint": 17.5,
"upper_bound": 30.0
},
"available_schedules": [
Expand All @@ -1091,27 +1065,24 @@
"away_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 25.0,
"setpoint_low": 17.5,
"setpoint": 17.5,
"upper_bound": 30.0
},
"climate_mode": "cool",
"climate_mode": "heat",
"control_state": "idle",
"dev_class": "climate",
"home_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 22.0,
"setpoint_low": 17.5,
"setpoint": 17.5,
"upper_bound": 30.0
},
"model": "ThermoZone",
"name": "Slaapkamer JM",
"no_frost_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 30.0,
"setpoint_low": 10.0,
"setpoint": 10.0,
"upper_bound": 30.0
},
"preset_modes": [
Expand Down Expand Up @@ -1143,8 +1114,7 @@
"vacation_preset_temperature": {
"lower_bound": 4.0,
"resolution": 0.5,
"setpoint_high": 28.0,
"setpoint_low": 16.0,
"setpoint": 16.0,
"upper_bound": 30.0
},
"vendor": "Plugwise",
Expand Down
12 changes: 7 additions & 5 deletions plugwise/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ def _climate_data(self, location_id: str, entity: GwEntityData) -> None:
if entity.get("location") is not None:
loc_id = entity["location"]

zone_cools = self._cooling_present and self._cooling_allowed(loc_id)

# Presets
entity["preset_modes"] = None
entity["active_preset"] = None
Expand All @@ -277,7 +279,7 @@ def _climate_data(self, location_id: str, entity: GwEntityData) -> None:
entity["active_preset"] = self._preset(loc_id)
# Only a zone's own rule can be edited without touching other zones
if self._preset_rule_id(loc_id) is not None:
self._preset_temperatures(presets, entity)
self._preset_temperatures(zone_cools, presets, entity)

# Schedule
entity["available_schedules"] = [OFF]
Expand All @@ -293,7 +295,7 @@ def _climate_data(self, location_id: str, entity: GwEntityData) -> None:
self._count += 1
if sel_schedule == OFF:
entity["climate_mode"] = "heat"
if self._cooling_present:
if zone_cools:
entity["climate_mode"] = (
"cool" if self.check_reg_mode("cooling") else "heat_cool"
)
Expand All @@ -306,17 +308,17 @@ def _climate_data(self, location_id: str, entity: GwEntityData) -> None:
)

def _preset_temperatures(
self, presets: dict[str, list[float]], entity: GwEntityData
self, zone_cools: bool, presets: dict[str, list[float]], entity: GwEntityData
) -> None:
"""Helper-function for _climate_data().

Add the setpoints of each preset as an adjustable value: the heating setpoint,
or with cooling present the heating (low) and cooling (high) setpoints.
or where the zone may cool the heating (low) and cooling (high) setpoints.
"""
for key, preset in PRESET_TEMPERATURES.items():
if preset in presets:
heating, cooling = presets[preset]
if self._cooling_present:
if zone_cools:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
entity[key] = ActuatorData(
lower_bound=MIN_SETPOINT,
resolution=PRESET_TEMPERATURE_RESOLUTION,
Expand Down
16 changes: 16 additions & 0 deletions plugwise/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,22 @@ def _preset(self, loc_id: str) -> str | None:

return None # pragma: no cover

def _cooling_allowed(self, loc_id: str) -> bool:
"""Helper-function for data.py: _climate_data() and smile.py: set_preset_temperature().

Collect whether cooling is allowed in a zone, based on Location ID.
Assume it is where the zone says nothing, leaving the gateway-wide
capability to decide.
"""
locator = (
f'./location[@id="{loc_id}"]/actuator_functionalities'
"/thermostat_functionality/cooling_allowed"
)
if (allowed := self._domain_objects.find(locator)) is not None:
return str(allowed.text) == "true"

return True

def _presets(self, loc_id: str) -> dict[str, list[float]]:
"""Collect Presets for a Thermostat based on location_id."""
presets: dict[str, list[float]] = {}
Expand Down
Loading
Loading