Skip to content

Commit

Permalink
Merge pull request #380 from plugwise/improve-typing-2
Browse files Browse the repository at this point in the history
 Optimize and rearrange typing-related constants, implement and cleanup.
  • Loading branch information
bouwew committed Sep 3, 2023
2 parents 00b9297 + d42ca44 commit 0ef08d3
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 106 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Ongoing

- Extend p1v4_442_triple userdata to include a Plugwise notification, extending the related fixture which is used in PW-beta and Core Plugwise.
- Optimize and rearrange typing-related constants, implement and cleanup.

## v0.32.1 Improve typing, bugfix

Expand Down
13 changes: 5 additions & 8 deletions plugwise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
"""
from __future__ import annotations

from typing import cast

import aiohttp
from defusedxml import ElementTree as etree

Expand Down Expand Up @@ -34,7 +32,6 @@
SYSTEM,
ZONE_THERMOSTATS,
ActuatorData,
ApplianceData,
DeviceData,
PlugwiseData,
)
Expand Down Expand Up @@ -93,7 +90,7 @@ def _all_device_data(self) -> None:
Collect initial data for each device and add to self.gw_data and self.gw_devices.
"""
for device_id, device in self._appl_data.items():
self.gw_devices.update({device_id: cast(DeviceData, device)})
self.gw_devices.update({device_id: device})

data = self._get_device_data(device_id)
# Add plugwise notification binary_sensor to the relevant gateway
Expand Down Expand Up @@ -160,7 +157,7 @@ def get_all_devices(self) -> None:
self._all_device_data()

def _device_data_switching_group(
self, details: ApplianceData, device_data: DeviceData
self, details: DeviceData, device_data: DeviceData
) -> DeviceData:
"""Helper-function for _get_device_data().
Expand All @@ -178,7 +175,7 @@ def _device_data_switching_group(
return device_data

def _device_data_adam(
self, details: ApplianceData, device_data: DeviceData
self, details: DeviceData, device_data: DeviceData
) -> DeviceData:
"""Helper-function for _get_device_data().
Expand All @@ -196,7 +193,7 @@ def _device_data_adam(
return device_data

def _device_data_climate(
self, details: ApplianceData, device_data: DeviceData
self, details: DeviceData, device_data: DeviceData
) -> DeviceData:
"""Helper-function for _get_device_data().
Expand Down Expand Up @@ -249,7 +246,7 @@ def _device_data_climate(
return device_data

def _check_availability(
self, details: ApplianceData, device_data: DeviceData
self, details: DeviceData, device_data: DeviceData
) -> DeviceData:
"""Helper-function for _get_device_data().
Expand Down
188 changes: 95 additions & 93 deletions plugwise/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,6 @@
VOLUME_CUBIC_METERS: Final = "m³"
VOLUME_CUBIC_METERS_PER_HOUR: Final = "m³/h"

ACTUATOR_CLASSES: Final[tuple[str, ...]] = (
"heater_central",
"thermostat",
"thermostatic_radiator_valve",
"zone_thermometer",
"zone_thermostat",
)
ActuatorType = Literal[
"domestic_hot_water_setpoint",
"max_dhw_temperature",
"maximum_boiler_temperature",
"temperature_offset",
"thermostat",
]
ACTIVE_ACTUATORS: Final[tuple[str, ...]] = get_args(ActuatorType)
ActuatorDataType = Literal[
"lower_bound",
"resolution",
"setpoint",
"setpoint_high",
"setpoint_low",
"upper_bound",
]
DAYS: Final[dict[str, int]] = {
"mo": 0,
"tu": 1,
Expand Down Expand Up @@ -108,36 +85,10 @@
"070051": "Switch",
"080029": "Switch",
}
LIMITS: Final[tuple[str, ...]] = (
"offset",
"setpoint",
"resolution",
"lower_bound",
"upper_bound",
)

MAX_SETPOINT: Final[float] = 30.0
MIN_SETPOINT: Final[float] = 4.0
NONE: Final = "None"
SPECIAL_FORMAT: Final[tuple[str, ...]] = (ENERGY_KILO_WATT_HOUR, VOLUME_CUBIC_METERS)
SWITCH_GROUP_TYPES: Final[tuple[str, ...]] = ("switching", "report")
ZONE_THERMOSTATS: Final[tuple[str, ...]] = (
"thermostat",
"thermostatic_radiator_valve",
"zone_thermometer",
"zone_thermostat",
)
THERMOSTAT_CLASSES: Final[tuple[str, ...]] = (
"thermostat",
"thermo_sensor",
"zone_thermometer",
"zone_thermostat",
"thermostatic_radiator_valve",
)
SPECIAL_PLUG_TYPES: Final[tuple[str, ...]] = (
"central_heating_pump",
"valve_actuator",
"heater_electric",
)

# XML data paths
APPLIANCES: Final = "/core/appliances"
Expand All @@ -151,6 +102,7 @@

UOM = namedtuple("UOM", "unit_of_measurement")
DATA = namedtuple("DATA", "name unit_of_measurement")

# P1 related measurements:
P1_MEASUREMENTS: Final[dict[str, UOM]] = {
"electricity_consumed": UOM(POWER_WATT),
Expand Down Expand Up @@ -234,15 +186,6 @@
"outdoor_temperature": DATA("outdoor_air_temperature", TEMP_CELSIUS),
}

ToggleNameType = Literal[
"cooling_ena_switch",
"dhw_cm_switch",
]
TOGGLES: Final[dict[str, ToggleNameType]] = {
"cooling_enabled": "cooling_ena_switch",
"domestic_hot_water_comfort_mode": "dhw_cm_switch",
}

# Known types of Smiles and Stretches
SMILE = namedtuple("SMILE", "smile_type smile_name")
SMILES: Final[dict[str, SMILE]] = {
Expand All @@ -258,7 +201,32 @@
"stretch_v3": SMILE("stretch", "Stretch"),
}

# All available Binary Sensor, Sensor, and Switch Types
# Class, Literal and related tuple-definitions

ACTUATOR_CLASSES: Final[tuple[str, ...]] = (
"heater_central",
"thermostat",
"thermostatic_radiator_valve",
"zone_thermometer",
"zone_thermostat",
)
ActuatorType = Literal[
"domestic_hot_water_setpoint",
"max_dhw_temperature",
"maximum_boiler_temperature",
"temperature_offset",
"thermostat",
]
ACTIVE_ACTUATORS: Final[tuple[str, ...]] = get_args(ActuatorType)

ActuatorDataType = Literal[
"lower_bound",
"resolution",
"setpoint",
"setpoint_high",
"setpoint_low",
"upper_bound",
]

ApplianceType = Literal[
"dev_class",
Expand Down Expand Up @@ -291,6 +259,14 @@
"temperature_offset",
]

LIMITS: Final[tuple[str, ...]] = (
"offset",
"setpoint",
"resolution",
"lower_bound",
"upper_bound",
)

SelectType = Literal[
"select_dhw_mode",
"select_regulation_mode",
Expand Down Expand Up @@ -357,6 +333,14 @@
]
SENSORS: Final[tuple[str, ...]] = get_args(SensorType)

SPECIAL_PLUG_TYPES: Final[tuple[str, ...]] = (
"central_heating_pump",
"valve_actuator",
"heater_electric",
)

SPECIAL_FORMAT: Final[tuple[str, ...]] = (ENERGY_KILO_WATT_HOUR, VOLUME_CUBIC_METERS)

SwitchType = Literal[
"cooling_ena_switch",
"dhw_cm_switch",
Expand All @@ -365,20 +349,31 @@
]
SWITCHES: Final[tuple[str, ...]] = get_args(SwitchType)

SWITCH_GROUP_TYPES: Final[tuple[str, ...]] = ("switching", "report")

class ApplianceData(TypedDict, total=False):
"""The Appliance Data class."""
THERMOSTAT_CLASSES: Final[tuple[str, ...]] = (
"thermostat",
"thermo_sensor",
"zone_thermometer",
"zone_thermostat",
"thermostatic_radiator_valve",
)

dev_class: str
firmware: str | None
hardware: str
location: str
mac_address: str | None
members: list[str]
model: str
name: str
vendor: str
zigbee_mac_address: str | None
ToggleNameType = Literal[
"cooling_ena_switch",
"dhw_cm_switch",
]
TOGGLES: Final[dict[str, ToggleNameType]] = {
"cooling_enabled": "cooling_ena_switch",
"domestic_hot_water_comfort_mode": "dhw_cm_switch",
}

ZONE_THERMOSTATS: Final[tuple[str, ...]] = (
"thermostat",
"thermostatic_radiator_valve",
"zone_thermometer",
"zone_thermostat",
)


class GatewayData(TypedDict, total=False):
Expand Down Expand Up @@ -449,7 +444,6 @@ class SmileSensors(TypedDict, total=False):
electricity_produced_peak_interval: int
electricity_produced_peak_point: int
electricity_produced_point: float
elga_status_code: int
gas_consumed_cumulative: float
gas_consumed_interval: float
humidity: float
Expand Down Expand Up @@ -502,16 +496,30 @@ class ActuatorData(TypedDict, total=False):
upper_bound: float


class DeviceData(
ApplianceData,
SmileBinarySensors,
SmileSensors,
SmileSwitches,
TypedDict,
total=False,
):
class DeviceData(TypedDict, total=False):
"""The Device Data class, covering the collected and ordered output-data per device."""

# Appliance base data
dev_class: str
firmware: str | None
hardware: str
location: str
mac_address: str | None
members: list[str]
model: str
name: str
vendor: str
zigbee_mac_address: str | None

# For temporary use
cooling_enabled: bool
domestic_hot_water_setpoint: float
elga_status_code: int
c_heating_state: bool

# Device availability
available: bool | None

# Loria
select_dhw_mode: str
dhw_modes: list[str]
Expand All @@ -521,31 +529,25 @@ class DeviceData(
regulation_modes: list[str]

# Master Thermostats
preset_modes: list[str] | None
# Presets:
active_preset: str | None

preset_modes: list[str] | None
# Schedules:
available_schedules: list[str]
select_schedule: str
last_used: str | None
select_schedule: str

mode: str

# Extra for Adam Master Thermostats
control_state: str | bool

# For temporary use
c_heating_state: bool
modified: str

# Device availability
available: bool | None

# Dict-types
binary_sensors: SmileBinarySensors
max_dhw_temperature: ActuatorData
maximum_boiler_temperature: ActuatorData
temperature_offset: ActuatorData
sensors: SmileSensors
switches: SmileSwitches
temperature_offset: ActuatorData
thermostat: ActuatorData


Expand Down
9 changes: 4 additions & 5 deletions plugwise/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
ActuatorData,
ActuatorDataType,
ActuatorType,
ApplianceData,
ApplianceType,
BinarySensorType,
DeviceData,
Expand Down Expand Up @@ -309,7 +308,7 @@ class SmileHelper:
def __init__(self) -> None:
"""Set the constructor for this class."""
self._appliances: etree
self._appl_data: dict[str, ApplianceData] = {}
self._appl_data: dict[str, DeviceData] = {}
self._cooling_activation_outdoor_temp: float
self._cooling_deactivation_threshold: float
self._cooling_present = False
Expand Down Expand Up @@ -1101,7 +1100,7 @@ def _rank_thermostat(
thermo_matching: dict[str, int],
loc_id: str,
appliance_id: str,
appliance_details: ApplianceData,
appliance_details: DeviceData,
) -> None:
"""Helper-function for _scan_thermostats().
Expand Down Expand Up @@ -1176,12 +1175,12 @@ def _thermostat_uri(self, loc_id: str) -> str:

return f"{LOCATIONS};id={loc_id}/thermostat;id={thermostat_functionality_id}"

def _group_switches(self) -> dict[str, ApplianceData]:
def _group_switches(self) -> dict[str, DeviceData]:
"""Helper-function for smile.py: get_all_devices().
Collect switching- or pump-group info.
"""
switch_groups: dict[str, ApplianceData] = {}
switch_groups: dict[str, DeviceData] = {}
# P1 and Anna don't have switchgroups
if self.smile_type == "power" or self.smile_name == "Smile Anna":
return switch_groups
Expand Down

0 comments on commit 0ef08d3

Please sign in to comment.