Skip to content

Commit 115ed74

Browse files
authored
Merge pull request #487 from plugwise/elga_cooling_not_supported
Fix for beta issue 574
2 parents 8addbd4 + 0b0e7a2 commit 115ed74

File tree

14 files changed

+5521
-18
lines changed

14 files changed

+5521
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Changelog
22

3-
## Ongoing
3+
## v0.36.2
44

5+
- Improve support for Anna+Elga systems that do not support cooling (fix for [#547](https://github.com/plugwise/plugwise-beta/issues/547)).
56
- Update test-fixtures for Plugwise-beta/Core Plugwise.
67
- Fix deprecation-warnings.
78

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
{
2+
"devices": {
3+
"015ae9ea3f964e668e490fa39da3870b": {
4+
"binary_sensors": {
5+
"plugwise_notification": false
6+
},
7+
"dev_class": "gateway",
8+
"firmware": "4.0.15",
9+
"hardware": "AME Smile 2.0 board",
10+
"location": "a57efe5f145f498c9be62a9b63626fbf",
11+
"mac_address": "012345670001",
12+
"model": "Gateway",
13+
"name": "Smile Anna",
14+
"sensors": {
15+
"outdoor_temperature": 20.2
16+
},
17+
"vendor": "Plugwise"
18+
},
19+
"1cbf783bb11e4a7c8a6843dee3a86927": {
20+
"available": true,
21+
"binary_sensors": {
22+
"compressor_state": true,
23+
"dhw_state": false,
24+
"flame_state": false,
25+
"heating_state": true,
26+
"slave_boiler_state": false
27+
},
28+
"dev_class": "heater_central",
29+
"location": "a57efe5f145f498c9be62a9b63626fbf",
30+
"max_dhw_temperature": {
31+
"lower_bound": 35.0,
32+
"resolution": 0.01,
33+
"setpoint": 53.0,
34+
"upper_bound": 60.0
35+
},
36+
"maximum_boiler_temperature": {
37+
"lower_bound": 0.0,
38+
"resolution": 1.0,
39+
"setpoint": 60.0,
40+
"upper_bound": 100.0
41+
},
42+
"model": "Generic heater",
43+
"name": "OpenTherm",
44+
"sensors": {
45+
"dhw_temperature": 46.3,
46+
"intended_boiler_temperature": 35.0,
47+
"modulation_level": 52,
48+
"outdoor_air_temperature": 3.0,
49+
"return_temperature": 25.1,
50+
"water_pressure": 1.57,
51+
"water_temperature": 29.1
52+
},
53+
"switches": {
54+
"dhw_cm_switch": false
55+
},
56+
"vendor": "Techneco"
57+
},
58+
"3cb70739631c4d17a86b8b12e8a5161b": {
59+
"active_preset": "home",
60+
"available_schedules": ["standaard", "off"],
61+
"dev_class": "thermostat",
62+
"firmware": "2018-02-08T11:15:53+01:00",
63+
"hardware": "6539-1301-5002",
64+
"location": "c784ee9fdab44e1395b8dee7d7a497d5",
65+
"mode": "auto",
66+
"model": "ThermoTouch",
67+
"name": "Anna",
68+
"preset_modes": ["no_frost", "home", "away", "asleep", "vacation"],
69+
"select_schedule": "standaard",
70+
"sensors": {
71+
"cooling_activation_outdoor_temperature": 21.0,
72+
"cooling_deactivation_threshold": 4.0,
73+
"illuminance": 86.0,
74+
"setpoint": 20.5,
75+
"temperature": 19.3
76+
},
77+
"temperature_offset": {
78+
"lower_bound": -2.0,
79+
"resolution": 0.1,
80+
"setpoint": -0.5,
81+
"upper_bound": 2.0
82+
},
83+
"thermostat": {
84+
"lower_bound": 4.0,
85+
"resolution": 0.1,
86+
"setpoint": 20.5,
87+
"upper_bound": 30.0
88+
},
89+
"vendor": "Plugwise"
90+
}
91+
},
92+
"gateway": {
93+
"cooling_present": false,
94+
"gateway_id": "015ae9ea3f964e668e490fa39da3870b",
95+
"heater_id": "1cbf783bb11e4a7c8a6843dee3a86927",
96+
"item_count": 62,
97+
"notifications": {},
98+
"smile_name": "Smile Anna"
99+
}
100+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
"015ae9ea3f964e668e490fa39da3870b",
3+
"1cbf783bb11e4a7c8a6843dee3a86927",
4+
"3cb70739631c4d17a86b8b12e8a5161b"
5+
]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

plugwise/constants.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
# Used with the Elga heatpump - marcelveldt
165165
"compressor_state": UOM(NONE),
166166
"cooling_state": UOM(NONE),
167+
"thermostat_supports_cooling": UOM(NONE),
167168
# Available with the Loria and Elga (newer Anna firmware) heatpumps
168169
"cooling_enabled": UOM(NONE),
169170
# Next 2 keys are used to show the state of the gas-heater used next to the Elga heatpump - marcelveldt
@@ -332,6 +333,13 @@
332333
"heater_electric",
333334
)
334335

336+
SpecialType = Literal[
337+
"c_heating_state",
338+
"thermostat_supports_cooling",
339+
]
340+
341+
SPECIALS: Final[tuple[str, ...]] = get_args(SpecialType)
342+
335343
SPECIAL_FORMAT: Final[tuple[str, ...]] = (ENERGY_KILO_WATT_HOUR, VOLUME_CUBIC_METERS)
336344

337345
SwitchType = Literal[
@@ -510,6 +518,7 @@ class DeviceData(TypedDict, total=False):
510518
domestic_hot_water_setpoint: float
511519
elga_status_code: int
512520
c_heating_state: bool
521+
thermostat_supports_cooling: bool
513522

514523
# Device availability
515524
available: bool | None

plugwise/helper.py

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
POWER_WATT,
4747
SENSORS,
4848
SPECIAL_PLUG_TYPES,
49+
SPECIALS,
4950
SWITCH_GROUP_TYPES,
5051
SWITCHES,
5152
TEMP_CELSIUS,
@@ -61,6 +62,7 @@
6162
GatewayData,
6263
ModelData,
6364
SensorType,
65+
SpecialType,
6466
SwitchType,
6567
ThermoLoc,
6668
ToggleNameType,
@@ -860,9 +862,10 @@ def _appliance_measurements(
860862
sw_key = cast(SwitchType, measurement)
861863
sw_value = appl_p_loc.text in ["on", "true"]
862864
data["switches"][sw_key] = sw_value
863-
case "c_heating_state":
864-
value = appl_p_loc.text in ["on", "true"]
865-
data["c_heating_state"] = value
865+
case _ as measurement if measurement in SPECIALS:
866+
sp_key = cast(SpecialType, measurement)
867+
sp_value = appl_p_loc.text in ["on", "true"]
868+
data[sp_key] = sp_value
866869
case "elga_status_code":
867870
data["elga_status_code"] = int(appl_p_loc.text)
868871

@@ -1003,10 +1006,14 @@ def _cleanup_data(self, data: DeviceData) -> None:
10031006
if "cooling_ena_switch" in data["switches"]:
10041007
data["switches"].pop("cooling_ena_switch") # pragma: no cover
10051008
self._count -= 1 # pragma: no cover
1006-
if not self._elga and "cooling_enabled" in data:
1007-
data.pop("cooling_enabled") # pragma: no cover
1009+
if "cooling_enabled" in data["binary_sensors"]:
1010+
data["binary_sensors"].pop("cooling_enabled") # pragma: no cover
10081011
self._count -= 1 # pragma: no cover
10091012

1013+
if "thermostat_supports_cooling" in data:
1014+
data.pop("thermostat_supports_cooling", None)
1015+
self._count -= 1
1016+
10101017
def _process_c_heating_state(self, data: DeviceData) -> None:
10111018
"""Helper-function for _get_measurement_data().
10121019
@@ -1100,19 +1107,21 @@ def _get_measurement_data(self, dev_id: str) -> DeviceData:
11001107
if self._is_thermostat and self.smile(ANNA) and dev_id == self._heater_id:
11011108
# Anna+Elga: base cooling_state on the elga-status-code
11021109
if "elga_status_code" in data:
1103-
# Techneco Elga has cooling-capability
1104-
self._cooling_present = True
1105-
data["model"] = "Generic heater/cooler"
1106-
self._cooling_enabled = data["elga_status_code"] in [8, 9]
1107-
data["binary_sensors"]["cooling_state"] = self._cooling_active = (
1108-
data["elga_status_code"] == 8
1109-
)
1110+
if data["thermostat_supports_cooling"]:
1111+
# Techneco Elga has cooling-capability
1112+
self._cooling_present = True
1113+
data["model"] = "Generic heater/cooler"
1114+
self._cooling_enabled = data["elga_status_code"] in [8, 9]
1115+
data["binary_sensors"]["cooling_state"] = self._cooling_active = (
1116+
data["elga_status_code"] == 8
1117+
)
1118+
# Elga has no cooling-switch
1119+
if "cooling_ena_switch" in data["switches"]:
1120+
data["switches"].pop("cooling_ena_switch")
1121+
self._count -= 1
1122+
11101123
data.pop("elga_status_code", None)
11111124
self._count -= 1
1112-
# Elga has no cooling-switch
1113-
if "cooling_ena_switch" in data["switches"]:
1114-
data["switches"].pop("cooling_ena_switch")
1115-
self._count -= 1
11161125

11171126
# Loria/Thermastage: cooling-related is based on cooling_state
11181127
# and modulation_level

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.36.1"
7+
version = "0.36.2"
88
license = {file = "LICENSE"}
99
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
1010
readme = "README.md"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{
2+
"015ae9ea3f964e668e490fa39da3870b": {
3+
"dev_class": "gateway",
4+
"firmware": "4.0.15",
5+
"hardware": "AME Smile 2.0 board",
6+
"location": "a57efe5f145f498c9be62a9b63626fbf",
7+
"mac_address": "012345670001",
8+
"model": "Gateway",
9+
"name": "Smile Anna",
10+
"vendor": "Plugwise",
11+
"binary_sensors": {
12+
"plugwise_notification": false
13+
},
14+
"sensors": {
15+
"outdoor_temperature": 20.2
16+
}
17+
},
18+
"1cbf783bb11e4a7c8a6843dee3a86927": {
19+
"dev_class": "heater_central",
20+
"location": "a57efe5f145f498c9be62a9b63626fbf",
21+
"model": "Generic heater",
22+
"name": "OpenTherm",
23+
"vendor": "Techneco",
24+
"maximum_boiler_temperature": {
25+
"setpoint": 60,
26+
"lower_bound": 0,
27+
"upper_bound": 100,
28+
"resolution": 1
29+
},
30+
"max_dhw_temperature": {
31+
"setpoint": 53,
32+
"lower_bound": 35,
33+
"upper_bound": 60,
34+
"resolution": 0.01
35+
},
36+
"available": true,
37+
"binary_sensors": {
38+
"dhw_state": false,
39+
"heating_state": true,
40+
"compressor_state": true,
41+
"slave_boiler_state": false,
42+
"flame_state": false
43+
},
44+
"sensors": {
45+
"water_temperature": 29.1,
46+
"dhw_temperature": 46.3,
47+
"intended_boiler_temperature": 35,
48+
"modulation_level": 52,
49+
"return_temperature": 25.1,
50+
"water_pressure": 1.57,
51+
"outdoor_air_temperature": 3
52+
},
53+
"switches": {
54+
"dhw_cm_switch": false
55+
}
56+
},
57+
"3cb70739631c4d17a86b8b12e8a5161b": {
58+
"dev_class": "thermostat",
59+
"firmware": "2018-02-08T11:15:53+01:00",
60+
"hardware": "6539-1301-5002",
61+
"location": "c784ee9fdab44e1395b8dee7d7a497d5",
62+
"model": "ThermoTouch",
63+
"name": "Anna",
64+
"vendor": "Plugwise",
65+
"temperature_offset": {
66+
"lower_bound": -2,
67+
"resolution": 0.1,
68+
"upper_bound": 2,
69+
"setpoint": -0.5
70+
},
71+
"thermostat": {
72+
"setpoint": 20.5,
73+
"lower_bound": 4,
74+
"upper_bound": 30,
75+
"resolution": 0.1
76+
},
77+
"preset_modes": ["no_frost", "home", "away", "asleep", "vacation"],
78+
"active_preset": "home",
79+
"available_schedules": ["standaard", "off"],
80+
"select_schedule": "standaard",
81+
"mode": "auto",
82+
"sensors": {
83+
"setpoint": 20.5,
84+
"temperature": 19.3,
85+
"illuminance": 86,
86+
"cooling_activation_outdoor_temperature": 21,
87+
"cooling_deactivation_threshold": 4
88+
}
89+
}
90+
}

tests/test_anna.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,32 @@ async def test_connect_anna_heatpump_cooling_fake_firmware(self):
408408
await smile.close_connection()
409409
await self.disconnect(server, client)
410410

411+
@pytest.mark.asyncio
412+
async def test_connect_anna_elga_no_cooling(self):
413+
"""Test an Anna with Elga, cooling-mode not used, in heating mode."""
414+
415+
self.smile_setup = "anna_elga_no_cooling"
416+
417+
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
418+
server, smile, client = await self.connect_wrapper()
419+
assert smile.smile_hostname == "smile000000"
420+
421+
self.validate_test_basics(
422+
_LOGGER,
423+
smile,
424+
smile_version="4.0.15",
425+
)
426+
427+
await self.device_test(smile, "2020-04-12 00:00:01", testdata)
428+
assert smile.gateway_id == "015ae9ea3f964e668e490fa39da3870b"
429+
assert smile._last_active["c784ee9fdab44e1395b8dee7d7a497d5"] == "standaard"
430+
assert smile.device_items == 62
431+
assert not self.notifications
432+
assert not self.cooling_present
433+
434+
await smile.close_connection()
435+
await self.disconnect(server, client)
436+
411437
@pytest.mark.asyncio
412438
async def test_connect_anna_elga_2(self):
413439
"""Test a 2nd Anna with Elga setup, cooling off, in idle mode (with missing outdoor temperature - solved)."""

0 commit comments

Comments
 (0)