Skip to content

Commit c21bfc0

Browse files
committed
Reworking
1 parent f1ee968 commit c21bfc0

File tree

6 files changed

+94
-45
lines changed

6 files changed

+94
-45
lines changed

plugwise/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ def get_all_devices(self) -> None:
308308

309309
async def async_update(self) -> PlugwiseData:
310310
"""Perform an incremental update for updating the various device states."""
311-
data = PlugwiseData({}, {})
311+
data = PlugwiseData({}, {}, {})
312312
try:
313313
data = await self._smile_api.async_update()
314314
self.gateway_id = data.gateway["gateway_id"]

plugwise/constants.py

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@
144144
"relay": UOM(NONE),
145145
}
146146

147+
# Climate related measurements
148+
CLIMATE_MEASUREMENTS: Final[dict[str, DATA | UOM]] = {
149+
"temperature": UOM(TEMP_CELSIUS), # HA Core thermostat current_temperature
150+
"thermostat": DATA("setpoint", TEMP_CELSIUS), # HA Core thermostat setpoint
151+
}
152+
147153
# Heater Central related measurements
148154
HEATER_CENTRAL_MEASUREMENTS: Final[dict[str, DATA | UOM]] = {
149155
"boiler_state": DATA(
@@ -492,7 +498,7 @@ class ThermoLoc(TypedDict, total=False):
492498
"""Thermo Location class."""
493499

494500
name: str
495-
primary: str | None
501+
primary: set[str]
496502
primary_prio: int
497503
secondary: set[str]
498504

@@ -508,6 +514,25 @@ class ActuatorData(TypedDict, total=False):
508514
upper_bound: float
509515

510516

517+
class ClimateData(TypedDict, total=False):
518+
"""The Climate Data class, covering the collected and ordered output-data per location."""
519+
520+
dev_class: str
521+
name: str
522+
members: dict[str, str] # TODO complete
523+
climate_mode: str
524+
# Extra for Adam Master Thermostats
525+
control_state: str | bool
526+
# Presets:
527+
active_preset: str | None
528+
preset_modes: list[str] | None
529+
# Schedules:
530+
available_schedules: list[str]
531+
select_schedule: str
532+
533+
thermostat: ActuatorData
534+
535+
511536
class DeviceData(TypedDict, total=False):
512537
"""The Device Data class, covering the collected and ordered output-data per device."""
513538

@@ -544,32 +569,19 @@ class DeviceData(TypedDict, total=False):
544569
select_gateway_mode: str
545570
select_regulation_mode: str
546571

547-
# Master Thermostats
548-
# Presets:
549-
active_preset: str | None
550-
preset_modes: list[str] | None
551-
# Schedules:
552-
available_schedules: list[str]
553-
last_used: str | None
554-
select_schedule: str
555-
556-
climate_mode: str
557-
# Extra for Adam Master Thermostats
558-
control_state: str | bool
559-
560572
# Dict-types
561573
binary_sensors: SmileBinarySensors
562574
max_dhw_temperature: ActuatorData
563575
maximum_boiler_temperature: ActuatorData
564576
sensors: SmileSensors
565577
switches: SmileSwitches
566578
temperature_offset: ActuatorData
567-
thermostat: ActuatorData
568579

569580

570581
@dataclass
571582
class PlugwiseData:
572583
"""Plugwise data provided as output."""
573584

574585
gateway: GatewayData
586+
climates: dict[str, ClimateData]
575587
devices: dict[str, DeviceData]

plugwise/data.py

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ def _all_device_data(self) -> None:
3535
Collect data for each device and add to self.gw_data and self.gw_devices.
3636
"""
3737
self._update_gw_devices()
38+
self._update_climates()
3839
self.gw_data.update(
3940
{
4041
"gateway_id": self.gateway_id,
@@ -49,6 +50,15 @@ def _all_device_data(self) -> None:
4950
{"heater_id": self._heater_id, "cooling_present": self._cooling_present}
5051
)
5152

53+
def _update_climates(self) -> None:
54+
"""Helper-function for _all_device_data() and async_update().
55+
56+
Collect data for each climate-location and add to self.climate_data.
57+
"""
58+
for location_id, climate in self.climate_data.items():
59+
data = self._get_location_data(location_id)
60+
climate.update(data)
61+
5262
def _update_gw_devices(self) -> None:
5363
"""Helper-function for _all_device_data() and async_update().
5464
@@ -140,10 +150,24 @@ def _update_for_cooling(self, device: DeviceData) -> None:
140150
sensors["setpoint_high"] = temp_dict["setpoint_high"]
141151
self._count += 2
142152

143-
def _get_device_data(self, dev_id: str) -> DeviceData:
153+
def _get_location_data(self, loc_id: str) -> DeviceData:
144154
"""Helper-function for _all_device_data() and async_update().
145155
146-
Provide device-data, based on Location ID (= dev_id), from APPLIANCES.
156+
Provide device-data, based on Location ID (= loc_id).
157+
"""
158+
climate = self.climate_data[loc_id]
159+
data = self._get_climate_data(loc_id)
160+
if ctrl_state := self._control_state(loc_id):
161+
data["control_state"] = ctrl_state
162+
self._count += 1
163+
164+
# Thermostat data (presets, temperatures etc)
165+
self._device_data_climate(loc_id, climate, data)
166+
167+
def _get_device_data(self, dev_id: str) -> DeviceData:
168+
"""Helper-function for _update_gw_devices() and async_update().
169+
170+
Provide device-data, based on appliance_id ()= dev_id).
147171
"""
148172
device = self.gw_devices[dev_id]
149173
data = self._get_measurement_data(dev_id)
@@ -162,13 +186,7 @@ def _get_device_data(self, dev_id: str) -> DeviceData:
162186
# Switching groups data
163187
self._device_data_switching_group(device, data)
164188
# Adam data
165-
self._device_data_adam(device, data)
166-
# Skip obtaining data for (Adam) secondary thermostats
167-
if device["dev_class"] not in ZONE_THERMOSTATS:
168-
return data
169-
170-
# Thermostat data (presets, temperatures etc)
171-
self._device_data_climate(device, data)
189+
self._device_data_adam(dev_id, device, data)
172190

173191
return data
174192

@@ -187,7 +205,7 @@ def _check_availability(
187205
if message in msg:
188206
data["available"] = False
189207

190-
def _device_data_adam(self, device: DeviceData, data: DeviceData) -> None:
208+
def _device_data_adam(self, loc_id: str, device: DeviceData, data: DeviceData) -> None:
191209
"""Helper-function for _get_device_data().
192210
193211
Determine Adam heating-status for on-off heating via valves,
@@ -211,20 +229,12 @@ def _device_data_adam(self, device: DeviceData, data: DeviceData) -> None:
211229
data["gateway_modes"] = self._gw_allowed_modes
212230
self._count += 1
213231

214-
# Control_state, only available for Adam primary thermostats
215-
if device["dev_class"] in ZONE_THERMOSTATS:
216-
loc_id = device["location"]
217-
if ctrl_state := self._control_state(loc_id):
218-
data["control_state"] = ctrl_state
219-
self._count += 1
220232

221-
def _device_data_climate(self, device: DeviceData, data: DeviceData) -> None:
233+
def _device_data_climate(self, loc_id: str, device: DeviceData, data: DeviceData) -> None:
222234
"""Helper-function for _get_device_data().
223235
224236
Determine climate-control device data.
225237
"""
226-
loc_id = device["location"]
227-
228238
# Presets
229239
data["preset_modes"] = None
230240
data["active_preset"] = None

plugwise/helper.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
ADAM,
1616
ANNA,
1717
ATTR_NAME,
18+
CLIMATE_MEASUREMENTS,
1819
DATA,
1920
DEVICE_MEASUREMENTS,
2021
DHW_SETPOINT,
@@ -35,6 +36,7 @@
3536
ActuatorData,
3637
ActuatorDataType,
3738
ActuatorType,
39+
ClimateData,
3840
DeviceData,
3941
GatewayData,
4042
SensorType,
@@ -248,6 +250,7 @@ def __init__(self) -> None:
248250
self._cooling_enabled = False
249251

250252
self.gateway_id: str
253+
self.climate_data: ClimateData = {}
251254
self.gw_data: GatewayData = {}
252255
self.gw_devices: dict[str, DeviceData] = {}
253256
self.loc_data: dict[str, ThermoLoc]
@@ -480,6 +483,20 @@ def _get_appliances_with_offset_functionality(self) -> list[str]:
480483

481484
return therm_list
482485

486+
def _get_climate_data(self, loc_id: str) -> ClimateData:
487+
"""Helper-function for smile.py: _get_device_data().
488+
489+
Collect the location-data based on location id.
490+
"""
491+
data: ClimateData = {"sensors": {}}
492+
measurements = CLIMATE_MEASUREMENTS
493+
if (
494+
location := self._domain_objects.find(f'./location[@id="{loc_id}"]')
495+
) is not None:
496+
self._appliance_measurements(location, data, measurements)
497+
if location.find("type").text in ACTUATOR_CLASSES:
498+
self._get_actuator_functionalities(location, device, data)
499+
483500
def _get_measurement_data(self, dev_id: str) -> DeviceData:
484501
"""Helper-function for smile.py: _get_device_data().
485502
@@ -619,11 +636,14 @@ def _appliance_measurements(
619636
appl_i_loc.text, ENERGY_WATT_HOUR
620637
)
621638

622-
self._count += len(data["binary_sensors"])
623-
self._count += len(data["sensors"])
624-
self._count += len(data["switches"])
639+
if data.get("binary_sensors"):
640+
self._count += len(data["binary_sensors"]) - 1
641+
if data.get("sensors"):
642+
self._count += len(data["sensors"]) -1
643+
if data.get("switches"):
644+
self._count += len(data["switches"]) -1
625645
# Don't count the above top-level dicts, only the remaining single items
626-
self._count += len(data) - 3
646+
#self._count += len(data) - 3
627647

628648
def _get_toggle_state(
629649
self, xml: etree, toggle: str, name: ToggleNameType, data: DeviceData
@@ -660,9 +680,9 @@ def _get_actuator_functionalities(
660680
"""Helper-function for _get_measurement_data()."""
661681
for item in ACTIVE_ACTUATORS:
662682
# Skip max_dhw_temperature, not initially valid,
663-
# skip thermostat for thermo_sensors
683+
# skip thermostat for all but climates
664684
if item == "max_dhw_temperature" or (
665-
item == "thermostat" and device["dev_class"] == "thermo_sensor"
685+
item == "thermostat" and device["dev_class"] != "climate"
666686
):
667687
continue
668688

@@ -813,12 +833,12 @@ def _scan_thermostats(self) -> None:
813833

814834
for loc_id, loc_data in list(self._thermo_locs.items()):
815835
if loc_data["primary_prio"] != 0:
816-
self.gw_devices.update(
836+
self.climate_data.update(
817837
{
818838
loc_id: {
819839
"dev_class": "climate",
820840
"name": loc_data["name"],
821-
"devices": loc_data["primary"]
841+
"members": {"primary": loc_data["primary"], "secondary": loc_data["secondary"]}
822842
}
823843
}
824844
)
@@ -864,7 +884,7 @@ def _rank_thermostat(
864884
if thermo_matching[appl_class] > self._thermo_locs[loc_id]["primary_prio"]:
865885
# Demote former primary
866886
if (tl_primary:= self._thermo_locs[loc_id]["primary"]):
867-
self._thermo_locs[loc_id]["secondary"].update(tl_primary)
887+
self._thermo_locs[loc_id]["secondary"].add(tl_primary)
868888

869889
# Crown primary
870890
self._thermo_locs[loc_id]["primary_prio"] = thermo_matching[appl_class]

plugwise/smile.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
NOTIFICATIONS,
2424
OFF,
2525
RULES,
26+
ClimateData,
2627
DeviceData,
2728
GatewayData,
2829
PlugwiseData,
@@ -126,6 +127,7 @@ def get_all_devices(self) -> None:
126127

127128
async def async_update(self) -> PlugwiseData:
128129
"""Perform an incremental update for updating the various device states."""
130+
self.climate_data: ClimateData = {}
129131
self.gw_data: GatewayData = {}
130132
self.gw_devices: dict[str, DeviceData] = {}
131133
try:
@@ -141,7 +143,11 @@ async def async_update(self) -> PlugwiseData:
141143
except KeyError as err:
142144
raise DataMissingError("No Plugwise data received") from err
143145

144-
return PlugwiseData(self.gw_data, self.gw_devices)
146+
return PlugwiseData(
147+
gateway=self.gw_data,
148+
climates=self.climate_data,
149+
devices=self.gw_devices,
150+
)
145151

146152
########################################################################################################
147153
### API Set and HA Service-related Functions ###

tests/test_init.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ async def device_test(
596596
_LOGGER.info("Gateway id = %s", data.gateway["gateway_id"])
597597
_LOGGER.info("Hostname = %s", smile.smile_hostname)
598598
_LOGGER.info("Gateway data = %s", data.gateway)
599+
_LOGGER.info("Climate data = %s", data.climates)
599600
_LOGGER.info("Device list = %s", data.devices)
600601
self.show_setup(location_list, data.devices)
601602

0 commit comments

Comments
 (0)