Skip to content

Commit 9f2d79c

Browse files
authored
Merge pull request #258 from plugwise/elga_update
Elga-related improvements, and more updates
2 parents be71186 + 6f78623 commit 9f2d79c

File tree

11 files changed

+122
-75
lines changed

11 files changed

+122
-75
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
# v0.27.1: More cooling-related updates, based on additional info from Plugwise
4+
- Updates for Anna+Elga and Adam-OnOff systems
5+
- Loria/Thermastage fix
6+
37
# v0.27.0: Smile P1: support 3-phase measurements
48

59
(# v0.26.0: not released)

plugwise/helper.py

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def schedules_temps(
124124
"""
125125
Helper-function for schedules().
126126
127-
Obtain the schedule temperature of the schedule.
127+
Obtain the temperature-setpoints of the schedule.
128128
"""
129129
if name == NONE:
130130
return [] # pragma: no cover
@@ -965,6 +965,26 @@ def _cleanup_data(self, data: dict[str, Any]) -> None:
965965
if not self._elga and "cooling_enabled" in data:
966966
data.pop("cooling_enabled") # pragma: no cover
967967

968+
def _process_c_heating_state(self, data: dict[str, Any]) -> None:
969+
"""
970+
Helper-function for _get_appliance_data().
971+
972+
Process the central_heating_state value.
973+
"""
974+
if self._on_off_device:
975+
# Anna + OnOff heater: use central_heating_state to show heating_state
976+
# Solution for Core issue #81839
977+
if self.smile_name == "Smile Anna":
978+
data["heating_state"] = data["c_heating_state"]
979+
980+
if self.smile_name == "Adam":
981+
data["heating_state"] = False
982+
# Adam + OnOff cooling: use central_heating_state to show heating/cooling_state
983+
if self._cooling_enabled:
984+
data["cooling_state"] = data["c_heating_state"]
985+
else:
986+
data["heating_state"] = data["c_heating_state"]
987+
968988
def _get_appliance_data(self, d_id: str) -> DeviceData:
969989
"""
970990
Helper-function for smile.py: _get_device_data().
@@ -1000,52 +1020,38 @@ def _get_appliance_data(self, d_id: str) -> DeviceData:
10001020
if d_id == self.gateway_id and self.smile_name == "Adam":
10011021
self._get_regulation_mode(appliance, data)
10021022

1003-
# Anna + Elga and Adam/Anna + OnOff heater/cooler don't use intended_central_heating_state
1004-
# to show the generic heating state
10051023
if "c_heating_state" in data:
1006-
if self._elga or (
1007-
self.smile_name in ("Adam", "Smile Anna") and self._on_off_device
1008-
):
1009-
data["heating_state"] = data["c_heating_state"]
1010-
# Heating is not active when intended_boiler_temperature is 0
1011-
if (
1012-
"intended_boiler_temperature" in data
1013-
and data["intended_boiler_temperature"] == 0
1014-
):
1015-
data["heating_state"] = False
1016-
# For Adam + OnOff cooling, central_heating_state = True means cooling is active
1017-
# For Smile Anna, _cooling_active will be corrected in the next if-construc
1018-
if self._cooling_present:
1019-
self._cooling_active = True
1020-
1021-
# Finally, remove c_heating_state from the output
1024+
self._process_c_heating_state(data)
1025+
# Remove c_heating_state after processing
10221026
data.pop("c_heating_state")
10231027

1024-
if (
1025-
d_id == self._heater_id
1026-
and self.smile_name == "Smile Anna"
1027-
and self._cooling_present
1028-
):
1029-
# Use elga_status_code or cooling_enabled to set _cooling_enabled to True
1030-
# Elga
1028+
if d_id == self._heater_id and self.smile_name == "Smile Anna":
10311029
if "elga_status_code" in data:
1032-
if "cooling_enabled" in data and not data["cooling_enabled"]:
1033-
self._cooling_present = False
1034-
self._cooling_enabled = data["elga_status_code"] in [8, 9]
1035-
self._cooling_active = data["elga_status_code"] == 8
1030+
# Base heating_/cooling_state on the elga-status-code
1031+
data["heating_state"] = False
1032+
data["cooling_state"] = False
1033+
if data["elga_status_code"] in [4, 10] or (
1034+
data["elga_status_code"] in [3, 5, 6, 11] and not data["dhw_state"]
1035+
):
1036+
data["heating_state"] = True
1037+
if data["elga_status_code"] == 8:
1038+
data["cooling_state"] = self._cooling_active = True
1039+
10361040
data.pop("elga_status_code", None)
1041+
1042+
# Determine _cooling_present and _cooling_enabled
1043+
if "cooling_enabled" in data and data["cooling_enabled"]:
1044+
self._cooling_present = self._cooling_enabled = True
1045+
data["model"] = "Generic heater/cooler"
1046+
10371047
# Elga has no cooling-switch
10381048
if "cooling_ena_switch" in data:
10391049
data.pop("cooling_ena_switch")
10401050
else:
1041-
# Loria/Thermastate: look at cooling_state, not at cooling_enabled, not available on R32!
1042-
# Anna + Elga >= 4.3.7: the Elga cooling-enabled state is shown but there is no cooling-switch
1043-
for item in ("cooling_enabled", "cooling_ena_switch"):
1044-
if item in data:
1045-
self._cooling_enabled = data[item]
1046-
self._cooling_active = data["cooling_state"]
1047-
# Execute one time is enough
1048-
break
1051+
# Loria/Thermastage: cooling-related is based on cooling_state and modulation_level
1052+
if "cooling_state" in data:
1053+
self._cooling_enabled = data["cooling_state"]
1054+
self._cooling_active = data["modulation_level"] == 100
10491055

10501056
self._cleanup_data(data)
10511057

plugwise/smile.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,6 @@ class SmileData(SmileHelper):
5454

5555
def update_for_cooling(self, device: DeviceData) -> None:
5656
"""Helper-function for adding/updating various cooling-related values."""
57-
# For Adam + on/off cooling, modify heating_state and cooling_state
58-
# based on provided info by Plugwise
59-
if (
60-
self.smile_name == "Adam"
61-
and device["dev_class"] == "heater_central"
62-
and self._on_off_device
63-
and self._cooling_active
64-
and device["binary_sensors"]["heating_state"]
65-
):
66-
device["binary_sensors"]["cooling_state"] = True
67-
device["binary_sensors"]["heating_state"] = False
68-
6957
# Add setpoint_low and setpoint_high when cooling is enabled
7058
if device["dev_class"] not in ZONE_THERMOSTATS:
7159
return
@@ -142,16 +130,13 @@ def get_all_devices(self) -> None:
142130
self._on_off_device = onoff_boiler is not None
143131
self._opentherm_device = open_therm_boiler is not None
144132

145-
# Determine if the Adam or Anna has cooling capability
133+
# Determine the presence of special features
146134
locator_1 = "./gateway/features/cooling"
147135
locator_2 = "./gateway/features/elga_support"
148136
search = self._domain_objects
149-
self._cooling_present = False
150137
if search.find(locator_1) is not None:
151138
self._cooling_present = True
152-
# Alternative method for the Anna with Elga
153-
elif search.find(locator_2) is not None:
154-
self._cooling_present = True
139+
if search.find(locator_2) is not None:
155140
self._elga = True
156141

157142
# Gather all the device and initial data

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "plugwise"
7-
version = "0.27.0"
7+
version = "0.27.1"
88
license = {file = "LICENSE"}
99
description = "Plugwise Smile (Adam/Anna/P1), Stretch and USB (Stick) module for Python 3."
1010
readme = "README.md"

tests/test_smile.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3707,12 +3707,12 @@ async def test_connect_p1v3_full_option(self):
37073707

37083708
@pytest.mark.asyncio
37093709
async def test_connect_anna_heatpump_heating(self):
3710-
"""Test a Anna with Elga setup in heating mode."""
3710+
"""Test an Anna with Elga, cooling-mode off, in heating mode."""
37113711
testdata = {
37123712
"1cbf783bb11e4a7c8a6843dee3a86927": {
37133713
"dev_class": "heater_central",
37143714
"location": "a57efe5f145f498c9be62a9b63626fbf",
3715-
"model": "Generic heater/cooler",
3715+
"model": "Generic heater",
37163716
"name": "OpenTherm",
37173717
"vendor": "Techneco",
37183718
"maximum_boiler_temperature": {
@@ -3856,6 +3856,7 @@ async def test_connect_anna_heatpump_cooling(self):
38563856
"dhw_state": False,
38573857
"heating_state": False,
38583858
"compressor_state": True,
3859+
"cooling_enabled": True,
38593860
"cooling_state": True,
38603861
"slave_boiler_state": False,
38613862
"flame_state": False,
@@ -3916,7 +3917,7 @@ async def test_connect_anna_heatpump_cooling(self):
39163917
assert not smile._smile_legacy
39173918

39183919
await self.device_test(smile, testdata)
3919-
assert self.device_items == 59
3920+
assert self.device_items == 60
39203921
assert self.cooling_present
39213922
assert not self.notifications
39223923

@@ -4030,8 +4031,7 @@ async def test_connect_anna_elga_2(self):
40304031
"name": "Anna",
40314032
"vendor": "Plugwise",
40324033
"thermostat": {
4033-
"setpoint_low": 19.5,
4034-
"setpoint_high": 23.0,
4034+
"setpoint": 19.5,
40354035
"lower_bound": 4.0,
40364036
"upper_bound": 30.0,
40374037
"resolution": 0.1,
@@ -4044,17 +4044,16 @@ async def test_connect_anna_elga_2(self):
40444044
"mode": "auto",
40454045
"sensors": {
40464046
"temperature": 20.9,
4047+
"setpoint": 19.5,
40474048
"illuminance": 0.5,
40484049
"cooling_activation_outdoor_temperature": 26.0,
40494050
"cooling_deactivation_threshold": 3.0,
4050-
"setpoint_low": 19.5,
4051-
"setpoint_high": 23.0,
40524051
},
40534052
},
40544053
"573c152e7d4f4720878222bd75638f5b": {
40554054
"dev_class": "heater_central",
40564055
"location": "d34dfe6ab90b410c98068e75de3eb631",
4057-
"model": "Generic heater/cooler",
4056+
"model": "Generic heater",
40584057
"name": "OpenTherm",
40594058
"vendor": "Techneco",
40604059
"maximum_boiler_temperature": {
@@ -4068,7 +4067,7 @@ async def test_connect_anna_elga_2(self):
40684067
"dhw_state": False,
40694068
"heating_state": False,
40704069
"compressor_state": False,
4071-
"cooling_state": False,
4070+
"cooling_enabled": False,
40724071
"slave_boiler_state": False,
40734072
"flame_state": False,
40744073
},
@@ -4110,9 +4109,9 @@ async def test_connect_anna_elga_2(self):
41104109
assert not smile._smile_legacy
41114110

41124111
await self.device_test(smile, testdata)
4113-
assert self.device_items == 58
4112+
assert self.device_items == 56
41144113
assert smile.gateway_id == "fb49af122f6e4b0f91267e1cf7666d6f"
4115-
assert self.cooling_present
4114+
assert not self.cooling_present
41164115
assert not self.notifications
41174116

41184117
await smile.close_connection()
@@ -4131,8 +4130,7 @@ async def test_connect_anna_elga_2_schedule_off(self):
41314130
"name": "Anna",
41324131
"vendor": "Plugwise",
41334132
"thermostat": {
4134-
"setpoint_low": 19.5,
4135-
"setpoint_high": 30.0,
4133+
"setpoint": 19.5,
41364134
"lower_bound": 4.0,
41374135
"upper_bound": 30.0,
41384136
"resolution": 0.1,
@@ -4142,14 +4140,13 @@ async def test_connect_anna_elga_2_schedule_off(self):
41424140
"available_schedules": ["Thermostat schedule"],
41434141
"selected_schedule": "None",
41444142
"last_used": "Thermostat schedule",
4145-
"mode": "heat_cool",
4143+
"mode": "heat",
41464144
"sensors": {
41474145
"temperature": 20.9,
4146+
"setpoint": 19.5,
41484147
"illuminance": 0.5,
41494148
"cooling_activation_outdoor_temperature": 26.0,
41504149
"cooling_deactivation_threshold": 3.0,
4151-
"setpoint_low": 19.5,
4152-
"setpoint_high": 30.0,
41534150
},
41544151
}
41554152
}
@@ -4159,8 +4156,8 @@ async def test_connect_anna_elga_2_schedule_off(self):
41594156
assert smile.smile_hostname == "smile000000"
41604157

41614158
await self.device_test(smile, testdata)
4162-
assert smile._cooling_present
4163-
assert self.device_items == 58
4159+
assert not smile._cooling_present
4160+
assert self.device_items == 56
41644161

41654162
await smile.close_connection()
41664163
await self.disconnect(server, client)

userdata/anna_elga_2/core.appliances.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,17 @@
985985
<measurement log_date="2022-03-10T19:00:42.322+01:00">14.00</measurement>
986986
</period>
987987
</point_log>
988+
<point_log id='9257714483e4423a8a3423072eda3d40'>
989+
<type>cooling_enabled</type>
990+
<unit></unit>
991+
<updated_date>2022-11-02T03:57:23.207+01:00</updated_date>
992+
<last_consecutive_log_date>2022-11-02T03:57:23.207+01:00</last_consecutive_log_date>
993+
<interval/>
994+
<cooling_toggle id='b556a934246f4d99979288841e7ee58a'/>
995+
<period start_date="2022-11-02T03:57:23.207+01:00" end_date="2022-11-02T03:57:23.207+01:00">
996+
<measurement log_date="2022-11-02T03:57:23.207+01:00">off</measurement>
997+
</period>
998+
</point_log>
988999
</logs>
9891000
<actuator_functionalities>
9901001
<timer_functionality id='00a41642a7764d1d80fe37b0cd493730'>

userdata/anna_elga_2_cooling/core.appliances.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,17 @@
996996
<measurement log_date="2022-03-10T19:00:42.322+01:00">30.00</measurement>
997997
</period>
998998
</point_log>
999+
<point_log id='9257714483e4423a8a3423072eda3d40'>
1000+
<type>cooling_enabled</type>
1001+
<unit></unit>
1002+
<updated_date>2022-11-02T03:57:23.207+01:00</updated_date>
1003+
<last_consecutive_log_date>2022-11-02T03:57:23.207+01:00</last_consecutive_log_date>
1004+
<interval/>
1005+
<cooling_toggle id='b556a934246f4d99979288841e7ee58a'/>
1006+
<period start_date="2022-11-02T03:57:23.207+01:00" end_date="2022-11-02T03:57:23.207+01:00">
1007+
<measurement log_date="2022-11-02T03:57:23.207+01:00">on</measurement>
1008+
</period>
1009+
</point_log>
9991010
</logs>
10001011
<actuator_functionalities>
10011012
<timer_functionality id='00a41642a7764d1d80fe37b0cd493730'>

userdata/anna_elga_2_schedule_off/core.appliances.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,17 @@
985985
<measurement log_date="2022-03-10T19:00:42.322+01:00">14.00</measurement>
986986
</period>
987987
</point_log>
988+
<point_log id='9257714483e4423a8a3423072eda3d40'>
989+
<type>cooling_enabled</type>
990+
<unit></unit>
991+
<updated_date>2022-11-02T03:57:23.207+01:00</updated_date>
992+
<last_consecutive_log_date>2022-11-02T03:57:23.207+01:00</last_consecutive_log_date>
993+
<interval/>
994+
<cooling_toggle id='b556a934246f4d99979288841e7ee58a'/>
995+
<period start_date="2022-11-02T03:57:23.207+01:00" end_date="2022-11-02T03:57:23.207+01:00">
996+
<measurement log_date="2022-11-02T03:57:23.207+01:00">off</measurement>
997+
</period>
998+
</point_log>
988999
</logs>
9891000
<actuator_functionalities>
9901001
<timer_functionality id='00a41642a7764d1d80fe37b0cd493730'>

userdata/anna_heatpump_cooling/core.appliances.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,17 @@
757757
</period>
758758
<fault_code id='c2f0f2af06284c9999e1446431bb0438'/>
759759
</point_log>
760+
<point_log id='9257714483e4423a8a3423072eda3d40'>
761+
<type>cooling_enabled</type>
762+
<unit></unit>
763+
<updated_date>2022-11-02T03:57:23.207+01:00</updated_date>
764+
<last_consecutive_log_date>2022-11-02T03:57:23.207+01:00</last_consecutive_log_date>
765+
<interval/>
766+
<cooling_toggle id='b556a934246f4d99979288841e7ee58a'/>
767+
<period start_date="2022-11-02T03:57:23.207+01:00" end_date="2022-11-02T03:57:23.207+01:00">
768+
<measurement log_date="2022-11-02T03:57:23.207+01:00">on</measurement>
769+
</period>
770+
</point_log>
760771
</logs>
761772
<actuator_functionalities>
762773
<offset_functionality id='0150ad6c0a2d47aba4c490e88205d026'>

userdata/anna_heatpump_cooling_to_off/core.appliances.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,17 @@
757757
</period>
758758
<fault_code id='c2f0f2af06284c9999e1446431bb0438'/>
759759
</point_log>
760+
<point_log id='9257714483e4423a8a3423072eda3d40'>
761+
<type>cooling_enabled</type>
762+
<unit></unit>
763+
<updated_date>2022-11-02T03:57:23.207+01:00</updated_date>
764+
<last_consecutive_log_date>2022-11-02T03:57:23.207+01:00</last_consecutive_log_date>
765+
<interval/>
766+
<cooling_toggle id='b556a934246f4d99979288841e7ee58a'/>
767+
<period start_date="2022-11-02T03:57:23.207+01:00" end_date="2022-11-02T03:57:23.207+01:00">
768+
<measurement log_date="2022-11-02T03:57:23.207+01:00">off</measurement>
769+
</period>
770+
</point_log>
760771
</logs>
761772
<actuator_functionalities>
762773
<offset_functionality id='0150ad6c0a2d47aba4c490e88205d026'>

0 commit comments

Comments
 (0)