PyPlumIO 0.5.6__py3-none-any.whl → 0.5.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyPlumIO
3
- Version: 0.5.6
3
+ Version: 0.5.7
4
4
  Summary: PyPlumIO is a native ecoNET library for Plum ecoMAX controllers.
5
5
  Author-email: Denis Paavilainen <denpa@denpa.pro>
6
6
  License: MIT License
@@ -44,17 +44,12 @@ Devices can be connected directly via RS-485 to USB adapter or through network b
44
44
  ![RS-485 converters](https://raw.githubusercontent.com/denpamusic/PyPlumIO/main/images/rs485.png)
45
45
 
46
46
  ## Table of contents
47
- - [Usage](https://pyplumio.denpa.pro/usage.html)
48
- - [Connecting](https://pyplumio.denpa.pro/usage.html#connecting)
49
- - [Reading](https://pyplumio.denpa.pro/usage.html#reading)
50
- - [Writing](https://pyplumio.denpa.pro/usage.html#writing)
51
- - [Parameters](https://pyplumio.denpa.pro/usage.html#parameters)
52
- - [Callbacks](https://pyplumio.denpa.pro/usage.html#callbacks)
53
- - [Filters](https://pyplumio.denpa.pro/usage.html#filters)
54
- - [Regulator Data](https://pyplumio.denpa.pro/usage.html#regulator-data)
55
- - [Mixers/Thermostats](https://pyplumio.denpa.pro/usage.html#mixers-thermostats)
56
- - [Schedules](https://pyplumio.denpa.pro/usage.html#schedules)
57
- - [Network Information](https://pyplumio.denpa.pro/usage.html#network-information)
47
+ - [Connecting](https://pyplumio.denpa.pro/connecting.html)
48
+ - [Reading](https://pyplumio.denpa.pro/reading.html)
49
+ - [Writing](https://pyplumio.denpa.pro/writing.html)
50
+ - [Callbacks](https://pyplumio.denpa.pro/callbacks.html)
51
+ - [Mixers/Thermostats](https://pyplumio.denpa.pro/mixers_thermostats.html)
52
+ - [Schedules](https://pyplumio.denpa.pro/schedules.html)
58
53
  - [Protocol](https://pyplumio.denpa.pro/protocol.html)
59
54
  - [Frame Structure](https://pyplumio.denpa.pro/protocol.html#frame-structure)
60
55
  - [Requests and Responses](https://pyplumio.denpa.pro/protocol.html#requests-and-responses)
@@ -0,0 +1,60 @@
1
+ pyplumio/__init__.py,sha256=JpT80zjHEk7N9e5sY4N53sOyUr8D7K3wU6cShkySeqI,3846
2
+ pyplumio/__main__.py,sha256=oop76iR-XDHhMFhW4LO8-xTnBHsqzUQ5VVh__94OaqY,499
3
+ pyplumio/_version.py,sha256=WG2gUkVRG4TIqG0-naezn012emNIbgERkkZYUI1CHww,411
4
+ pyplumio/connection.py,sha256=gxf4qoVRDz_ZYOEnGGnrs0QCGHxpclNWXE7_yzWDhN0,6522
5
+ pyplumio/const.py,sha256=lDHu7QkP8zKWDc5anOgyQGiXcF4Unv7hyibXfmoPDQk,3832
6
+ pyplumio/exceptions.py,sha256=cpLGRl9db6cU1Z6WXhQ7yl1V7Te193QymWiOoRF8KAI,798
7
+ pyplumio/filters.py,sha256=Q8ffCv7vH0wgTwrPKEfp861E44ev5yi41W9x19VKckc,10284
8
+ pyplumio/protocol.py,sha256=MuhnZ7fFT318X916-kH3TlMmJtVFE20PaHsbmkzKT84,8699
9
+ pyplumio/stream.py,sha256=g_lZkMWuYmFQ4mZrkP6kLxrmWpnQrLmiBIv0f-to38U,4024
10
+ pyplumio/utils.py,sha256=5QF-oJar4DfaaUHqrMIfKPFJFWGBLQfgo4nYo4doJWw,651
11
+ pyplumio/devices/__init__.py,sha256=DsPes_1xsfqW3RCfP2lnQcrdoA8ej16UNaNW89UFMWo,6488
12
+ pyplumio/devices/ecomax.py,sha256=wjm66TL9X_QU9KbmTD7fwsoACKNjM_K9nghzOlE1TEw,16469
13
+ pyplumio/devices/ecoster.py,sha256=QH68bzs199x9Id-wOY6J5WddyR69STNQi8SxaWDwKG4,312
14
+ pyplumio/devices/mixer.py,sha256=7PWwaMQ-cezvIRNot3OkemipT65lLFv4kTXPXAaH4oY,2962
15
+ pyplumio/devices/thermostat.py,sha256=BIYuSuv-1bUjGbMmWkWR0ej-57chYO9YPM5W-vAy55M,2418
16
+ pyplumio/frames/__init__.py,sha256=M0kTQii4Ver3WRCOC8eeXOb910mCDOLsUbJarksT72g,7410
17
+ pyplumio/frames/messages.py,sha256=BS5d4M1pz99pNQhu8OgE2Q6ejNO8qT2R621lUPvD9fs,3672
18
+ pyplumio/frames/requests.py,sha256=A7ixLYAzY-nebJ9DcLH55RkhNNum8JnBGr5Dv2SP4SU,7333
19
+ pyplumio/frames/responses.py,sha256=z7m0MRUVckadoghzm9por0Wn879z1C9zGk5lPZfgFqE,6647
20
+ pyplumio/helpers/__init__.py,sha256=H2xxdkF-9uADLwEbfBUoxNTdwru3L5Z2cfJjgsuRsn0,31
21
+ pyplumio/helpers/data_types.py,sha256=AGMDOlz7B_dxf2qsyfUrpb2aN9I-H9tIj40twt4ankg,7903
22
+ pyplumio/helpers/event_manager.py,sha256=uxeFFsyIiZ33f22Q_Wx0PI1aoOI2lkZa2fPZ0QGCCZw,5980
23
+ pyplumio/helpers/factory.py,sha256=403RYqlKbWRmL-RngzL1e2p5iI5_JTzwf65HeNxHfwM,527
24
+ pyplumio/helpers/parameter.py,sha256=5FXrftafV31YaFx-UamhBncrZjWeMOaHsmsoYIcd3VY,8549
25
+ pyplumio/helpers/schedule.py,sha256=gNZcgLfa-D3Y6Vx77U61cm6bMlD5iIxl0f1m5FZIkBM,4859
26
+ pyplumio/helpers/task_manager.py,sha256=fZyBmHik7rU9Kb4EECQWqVrJPUlEtEyxrEUJcf8RVYc,1072
27
+ pyplumio/helpers/timeout.py,sha256=UstSwBfrLO_YhUHHvhIgunAw89s6PocR80nmU5LN4oI,915
28
+ pyplumio/helpers/typing.py,sha256=gn7TWudOAqViQYMQk1vCk9_JnsFs8Q1KK3FrvkyI8AI,478
29
+ pyplumio/helpers/uid.py,sha256=FTwuET3WLNyEkAHpxD4ZA3hu-l_JCS6pq12xibAQs6s,974
30
+ pyplumio/structures/__init__.py,sha256=L976WdfoNb_Mmv-pN86XKBLEZydsVlD_Xlw85cnCS3E,1247
31
+ pyplumio/structures/alerts.py,sha256=gkUOYCFt5PvLusrrI9jw3qjvvbVYaX2BgUztW9CkYC0,2986
32
+ pyplumio/structures/boiler_load.py,sha256=tRlKr5gZQ-UZh042f98wH3ctOuXgCAb16ne_zFP5I28,860
33
+ pyplumio/structures/boiler_power.py,sha256=BRl3QkPtoFoEVHUeWN5KKkxATIO4-EZB-0fEsvRKECI,923
34
+ pyplumio/structures/ecomax_parameters.py,sha256=71c-dMSx3QebyAF1okO5hc6DQcJ9V-c3NRkTN8thSYY,25939
35
+ pyplumio/structures/fan_power.py,sha256=cBLmns_nh8I5eDNehFM1QMe5eqlUC-QBBm1i0kTbj38,893
36
+ pyplumio/structures/frame_versions.py,sha256=SkHrgehJbf14Qf_uKY8zlZp8d8WjgAq3Swwjf1Y1trw,1572
37
+ pyplumio/structures/fuel_consumption.py,sha256=qxT8vtOX6VIv6MgvTalYlsN7FIBzXL3ba8VHO2b6mbs,998
38
+ pyplumio/structures/fuel_level.py,sha256=XqqciKIBM8-zmG_JNc9ILff3Rgd4aCgvht7STrw9Dz0,851
39
+ pyplumio/structures/lambda_sensor.py,sha256=2aEZjY8y7qV76Ky4gE4Ui7zWyXxCQRdtMingtMBKhF0,1475
40
+ pyplumio/structures/mixer_parameters.py,sha256=ssYHpReiPC7kpNiCwgqMkbR8Wwkqh4wCQqhKUbLWPQg,8194
41
+ pyplumio/structures/mixer_sensors.py,sha256=sKm1gIoRcCLVad-9MqOkEwu_bXIZy-3Kbi2kCd5wOkM,2243
42
+ pyplumio/structures/modules.py,sha256=y1WRxKk3vW3erquzsVd4G7mDLlna8DttueeUu0jCgYw,2532
43
+ pyplumio/structures/network_info.py,sha256=O09zE4AzU-yEi_yMB4VPN-2_BYNasCAbOBANLJbh4P0,4013
44
+ pyplumio/structures/output_flags.py,sha256=JY_IVncL_ZnIV2xXfEXLDK8x2tPulIW1PZpWVHgC-C4,1367
45
+ pyplumio/structures/outputs.py,sha256=dS0dYsl9bWLuZmj5rt0Dcg1chyQhjFOIwA6KU4Yw76g,1938
46
+ pyplumio/structures/pending_alerts.py,sha256=L_uaizbL_H3gYkpPBN0T0H8Q4jNo17-5-QamiF5tQO0,761
47
+ pyplumio/structures/product_info.py,sha256=hkUGlbEr-OtpCHozGI_8R_uLB5cyYwe9dJ1Xz-Sqdoc,2396
48
+ pyplumio/structures/program_version.py,sha256=5gOmKpbr2ftsXtJ5Hqkg__30DRYtB-CAx5sXIvCLQeM,2477
49
+ pyplumio/structures/regulator_data.py,sha256=9rEy_JLij9XE2Kyc5jgWAfJKJG3OmL2W2Bix6t2zKnU,2544
50
+ pyplumio/structures/regulator_data_schema.py,sha256=W2b3-n3PZoo4pU2esqeCWP-_zz1AxymJ9Y6fcS_y6bg,1517
51
+ pyplumio/structures/schedules.py,sha256=4I74MHutWcb_i-z2ZvDxdavSnOUivWRBhvjRnK5aKK0,6125
52
+ pyplumio/structures/statuses.py,sha256=IWcQ1TNfvhVitF_vxTeF3c4txpU54NOyi4l445SJVk8,1188
53
+ pyplumio/structures/temperatures.py,sha256=znL_gSfVeO8hAvl2GYRyRiYC3E3PSS6JmJXAJoTYea8,2359
54
+ pyplumio/structures/thermostat_parameters.py,sha256=mqoqLSAPW3TfuFImEHGWmvvd-LCPR6pFcfH0Y8kd0Xg,7691
55
+ pyplumio/structures/thermostat_sensors.py,sha256=sEH42iq05Wijfhfrv9o4iJcxX8EOcPoWcLpzUpq3qQ8,3071
56
+ PyPlumIO-0.5.7.dist-info/LICENSE,sha256=g56wJgobsehVtkJD8MhM6isAnsdOUmRPv7fIaXI4Joo,1067
57
+ PyPlumIO-0.5.7.dist-info/METADATA,sha256=YVfg3gm8Tfq0l-953p69oGyJld0ihjaaj9R1PPW8HVY,4463
58
+ PyPlumIO-0.5.7.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
59
+ PyPlumIO-0.5.7.dist-info/top_level.txt,sha256=kNBz9UPPkPD9teDn3U_sEy5LjzwLm9KfADCXtBlbw8A,9
60
+ PyPlumIO-0.5.7.dist-info/RECORD,,
pyplumio/__init__.py CHANGED
@@ -3,39 +3,106 @@ from __future__ import annotations
3
3
 
4
4
  from pyplumio._version import __version__, __version_tuple__
5
5
  from pyplumio.connection import Connection, SerialConnection, TcpConnection
6
+ from pyplumio.protocol import AsyncProtocol, Protocol
6
7
  from pyplumio.structures.network_info import EthernetParameters, WirelessParameters
7
8
 
8
9
 
9
10
  def open_serial_connection(
10
- device: str, baudrate: int = 115200, **kwargs
11
+ device: str,
12
+ baudrate: int = 115200,
13
+ *,
14
+ ethernet_parameters: EthernetParameters | None = None,
15
+ wireless_parameters: WirelessParameters | None = None,
16
+ reconnect_on_failure: bool = True,
17
+ protocol: type[Protocol] = AsyncProtocol,
18
+ **kwargs,
11
19
  ) -> SerialConnection:
12
- """Create a serial connection."""
13
- return SerialConnection(device, baudrate, **kwargs)
20
+ r"""Create a serial connection.
14
21
 
22
+ :param device: Serial port device name. e. g. /dev/ttyUSB0
23
+ :type device: str
24
+ :param baudrate: Serial port baud rate, defaults to 115200
25
+ :type baudrate: int, optional
26
+ :param ethernet_parameters: Ethernet parameters to send to an
27
+ ecoMAX controller
28
+ :type ethernet_parameters: EthernetParameters, optional
29
+ :param wireless_parameters: Wireless parameters to send to an
30
+ ecoMAX controller
31
+ :type wireless_parameters: WirelessParameters, optional
32
+ :param reconnect_on_failure: `True` if PyPlumIO should try
33
+ reconnecting on failure, otherwise `False`, default to `True`
34
+ :type reconnect_on_failure: bool, optional
35
+ :param protocol: Protocol that will be used for communication with
36
+ the ecoMAX controller, default to AsyncProtocol
37
+ :type protocol: Protocol, optional
38
+ :param \**kwargs: Additional keyword arguments to be passed to
39
+ serial_asyncio.open_serial_connection()
40
+ :return: An instance of serial connection
41
+ :rtype: SerialConnection
42
+ """
43
+ return SerialConnection(
44
+ device,
45
+ baudrate,
46
+ ethernet_parameters=ethernet_parameters,
47
+ wireless_parameters=wireless_parameters,
48
+ reconnect_on_failure=reconnect_on_failure,
49
+ protocol=protocol,
50
+ **kwargs,
51
+ )
15
52
 
16
- def open_tcp_connection(host: str, port: int, **kwargs) -> TcpConnection:
17
- """Create a TCP connection."""
18
- return TcpConnection(host, port, **kwargs)
19
53
 
54
+ def open_tcp_connection(
55
+ host: str,
56
+ port: int,
57
+ *,
58
+ ethernet_parameters: EthernetParameters | None = None,
59
+ wireless_parameters: WirelessParameters | None = None,
60
+ reconnect_on_failure: bool = True,
61
+ protocol: type[Protocol] = AsyncProtocol,
62
+ **kwargs,
63
+ ) -> TcpConnection:
64
+ r"""Create a TCP connection.
20
65
 
21
- def ethernet_parameters(**kwargs) -> EthernetParameters:
22
- """Return an instance of ethernet parameters dataclass."""
23
- return EthernetParameters(status=True, **kwargs)
24
-
25
-
26
- def wireless_parameters(**kwargs) -> WirelessParameters:
27
- """Return an instance of wireless parameters dataclass."""
28
- return WirelessParameters(status=True, **kwargs)
66
+ :param host: IP address or host name of the remote RS-485 server
67
+ :type host: str
68
+ :param port: Port that remote RS-485 server is listening to
69
+ :type port: int
70
+ :param ethernet_parameters: Ethernet parameters to send to an
71
+ ecoMAX controller
72
+ :type ethernet_parameters: EthernetParameters, optional
73
+ :param wireless_parameters: Wireless parameters to send to an
74
+ ecoMAX controller
75
+ :type wireless_parameters: WirelessParameters, optional
76
+ :param reconnect_on_failure: `True` if PyPlumIO should try
77
+ reconnecting on failure, otherwise `False`, default to `True`
78
+ :type reconnect_on_failure: bool, optional
79
+ :param protocol: Protocol that will be used for communication with
80
+ the ecoMAX controller, default to AsyncProtocol
81
+ :type protocol: Protocol, optional
82
+ :param \**kwargs: Additional keyword arguments to be passed to
83
+ asyncio.open_connection()
84
+ :return: An instance of TCP connection
85
+ :rtype: TcpConnection
86
+ """
87
+ return TcpConnection(
88
+ host,
89
+ port,
90
+ ethernet_parameters=ethernet_parameters,
91
+ wireless_parameters=wireless_parameters,
92
+ reconnect_on_failure=reconnect_on_failure,
93
+ protocol=protocol,
94
+ **kwargs,
95
+ )
29
96
 
30
97
 
31
98
  __all__ = [
32
99
  "Connection",
33
100
  "SerialConnection",
34
101
  "TcpConnection",
102
+ "EthernetParameters",
103
+ "WirelessParameters",
35
104
  "open_serial_connection",
36
105
  "open_tcp_connection",
37
- "ethernet_parameters",
38
- "wireless_parameters",
39
106
  "__version__",
40
107
  "__version_tuple__",
41
108
  ]
pyplumio/_version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.5.6'
16
- __version_tuple__ = version_tuple = (0, 5, 6)
15
+ __version__ = version = '0.5.7'
16
+ __version_tuple__ = version_tuple = (0, 5, 7)
pyplumio/connection.py CHANGED
@@ -12,7 +12,8 @@ import serial_asyncio
12
12
 
13
13
  from pyplumio.exceptions import ConnectionFailedError
14
14
  from pyplumio.helpers.timeout import timeout
15
- from pyplumio.protocol import Protocol
15
+ from pyplumio.protocol import AsyncProtocol, Protocol
16
+ from pyplumio.structures.network_info import EthernetParameters, WirelessParameters
16
17
 
17
18
  _LOGGER = logging.getLogger(__name__)
18
19
 
@@ -26,29 +27,28 @@ class Connection(ABC):
26
27
  All specific connection classes MUST be inherited from this class.
27
28
  """
28
29
 
29
- __slots__ = ("_kwargs", "_protocol", "_closing", "_reconnect_on_failure")
30
-
31
- _kwargs: MutableMapping[str, Any]
32
- _protocol: Protocol
33
30
  _closing: bool
31
+ _protocol: Protocol
34
32
  _reconnect_on_failure: bool
33
+ _kwargs: MutableMapping[str, Any]
35
34
 
36
35
  def __init__(
37
36
  self,
37
+ ethernet_parameters: EthernetParameters | None = None,
38
+ wireless_parameters: WirelessParameters | None = None,
38
39
  reconnect_on_failure: bool = True,
39
- ethernet_parameters=None,
40
- wireless_parameters=None,
40
+ protocol: type[Protocol] = AsyncProtocol,
41
41
  **kwargs,
42
42
  ):
43
43
  """Initialize a new connection."""
44
- self._kwargs = kwargs
45
44
  self._closing = False
46
- self._protocol = Protocol(
45
+ self._reconnect_on_failure = reconnect_on_failure
46
+ self._protocol = protocol(
47
47
  self._connection_lost,
48
48
  ethernet_parameters,
49
49
  wireless_parameters,
50
50
  )
51
- self._reconnect_on_failure = reconnect_on_failure
51
+ self._kwargs = kwargs
52
52
 
53
53
  async def __aenter__(self):
54
54
  """Provide an entry point for the context manager."""
@@ -125,9 +125,25 @@ class TcpConnection(Connection):
125
125
  host: str
126
126
  port: int
127
127
 
128
- def __init__(self, host: str, port: int, **kwargs):
128
+ def __init__(
129
+ self,
130
+ host: str,
131
+ port: int,
132
+ *,
133
+ ethernet_parameters: EthernetParameters | None = None,
134
+ wireless_parameters: WirelessParameters | None = None,
135
+ reconnect_on_failure: bool = True,
136
+ protocol: type[Protocol] = AsyncProtocol,
137
+ **kwargs,
138
+ ):
129
139
  """Initialize a new TCP connection."""
130
- super().__init__(**kwargs)
140
+ super().__init__(
141
+ ethernet_parameters,
142
+ wireless_parameters,
143
+ reconnect_on_failure,
144
+ protocol,
145
+ **kwargs,
146
+ )
131
147
  self.host = host
132
148
  self.port = port
133
149
 
@@ -153,9 +169,25 @@ class SerialConnection(Connection):
153
169
  device: str
154
170
  baudrate: int
155
171
 
156
- def __init__(self, device: str, baudrate: int = 115200, **kwargs):
172
+ def __init__(
173
+ self,
174
+ device: str,
175
+ baudrate: int = 115200,
176
+ *,
177
+ ethernet_parameters: EthernetParameters | None = None,
178
+ wireless_parameters: WirelessParameters | None = None,
179
+ reconnect_on_failure: bool = True,
180
+ protocol: type[Protocol] = AsyncProtocol,
181
+ **kwargs,
182
+ ):
157
183
  """Initialize a new serial connection."""
158
- super().__init__(**kwargs)
184
+ super().__init__(
185
+ ethernet_parameters,
186
+ wireless_parameters,
187
+ reconnect_on_failure,
188
+ protocol,
189
+ **kwargs,
190
+ )
159
191
  self.device = device
160
192
  self.baudrate = baudrate
161
193
 
pyplumio/const.py CHANGED
@@ -133,7 +133,7 @@ class FrameType(IntEnum):
133
133
  REQUEST_ECOMAX_CONTROL = 59
134
134
  REQUEST_ALERTS = 61
135
135
  REQUEST_PROGRAM_VERSION = 64
136
- REQUEST_DATA_SCHEMA = 85
136
+ REQUEST_REGULATOR_DATA_SCHEMA = 85
137
137
  REQUEST_THERMOSTAT_PARAMETERS = 92
138
138
  REQUEST_SET_THERMOSTAT_PARAMETER = 93
139
139
  RESPONSE_DEVICE_AVAILABLE = 176
@@ -147,7 +147,7 @@ class FrameType(IntEnum):
147
147
  RESPONSE_ECOMAX_CONTROL = 187
148
148
  RESPONSE_ALERTS = 189
149
149
  RESPONSE_PROGRAM_VERSION = 192
150
- RESPONSE_DATA_SCHEMA = 213
150
+ RESPONSE_REGULATOR_DATA_SCHEMA = 213
151
151
  RESPONSE_THERMOSTAT_PARAMETERS = 220
152
152
  RESPONSE_SET_THERMOSTAT_PARAMETER = 221
153
153
  MESSAGE_REGULATOR_DATA = 8
@@ -58,8 +58,23 @@ class Device(ABC, EventManager):
58
58
  ) -> bool:
59
59
  """Set a parameter value.
60
60
 
61
- Name should point to a valid parameter object, otherwise
62
- raise ParameterNotFoundError.
61
+ :param name: Name of the parameter
62
+ :type name: str
63
+ :param value: New value for the parameter
64
+ :type value: int | float | bool | Literal["on"] | Literal["off"]
65
+ :param timeout: Wait this amount of seconds for confirmation,
66
+ defaults to `None`
67
+ :type timeout: float, optional
68
+ :param retries: Try setting parameter for this amount of
69
+ times, defaults to 5
70
+ :type retries: int, optional
71
+ :return: `True` if parameter was successfully set, `False`
72
+ otherwise.
73
+ :rtype: bool
74
+ :raise pyplumio.exceptions.ParameterNotFoundError: when
75
+ parameter with the specified name is not found
76
+ :raise asyncio.TimeoutError: when waiting past specified timeout
77
+ :raise ValueError: when a new value is outside of allowed range
63
78
  """
64
79
  parameter = await self.get(name, timeout=timeout)
65
80
  if not isinstance(parameter, Parameter):
@@ -74,11 +89,28 @@ class Device(ABC, EventManager):
74
89
  timeout: float | None = None,
75
90
  retries: int = SET_RETRIES,
76
91
  ) -> None:
77
- """Set a parameter value without waiting for the result."""
92
+ """Set a parameter value without waiting for the result.
93
+
94
+ :param name: Name of the parameter
95
+ :type name: str
96
+ :param value: New value for the parameter
97
+ :type value: int | float | bool | Literal["on"] | Literal["off"]
98
+ :param timeout: Wait this amount of seconds for confirmation.
99
+ As this method operates in the background without waiting,
100
+ this value is used to determine failure when
101
+ retrying and doesn't block, defaults to `None`
102
+ :type timeout: float, optional
103
+ :param retries: Try setting parameter for this amount of
104
+ times, defaults to 5
105
+ :type retries: int, optional
106
+ :return: `True` if parameter was successfully set, `False`
107
+ otherwise.
108
+ :rtype: bool
109
+ """
78
110
  self.create_task(self.set(name, value, timeout, retries))
79
111
 
80
112
 
81
- class Addressable(Device, ABC):
113
+ class AddressableDevice(Device, ABC):
82
114
  """Represents an addressable device."""
83
115
 
84
116
  address: ClassVar[int]
@@ -149,10 +181,10 @@ class Addressable(Device, ABC):
149
181
  class SubDevice(Device, ABC):
150
182
  """Represents the sub-device."""
151
183
 
152
- parent: Addressable
184
+ parent: AddressableDevice
153
185
  index: int
154
186
 
155
- def __init__(self, queue: asyncio.Queue, parent: Addressable, index: int = 0):
187
+ def __init__(self, queue: asyncio.Queue, parent: AddressableDevice, index: int = 0):
156
188
  """Initialize a new sub-device object."""
157
189
  super().__init__(queue)
158
190
  self.parent = parent
@@ -16,7 +16,7 @@ from pyplumio.const import (
16
16
  DeviceType,
17
17
  FrameType,
18
18
  )
19
- from pyplumio.devices import Addressable
19
+ from pyplumio.devices import AddressableDevice
20
20
  from pyplumio.devices.mixer import Mixer
21
21
  from pyplumio.devices.thermostat import Thermostat
22
22
  from pyplumio.filters import on_change
@@ -32,7 +32,6 @@ from pyplumio.helpers.parameter import ParameterValues
32
32
  from pyplumio.helpers.schedule import Schedule, ScheduleDay
33
33
  from pyplumio.helpers.typing import EventDataType
34
34
  from pyplumio.structures.alerts import ATTR_ALERTS
35
- from pyplumio.structures.data_schema import ATTR_SCHEMA
36
35
  from pyplumio.structures.ecomax_parameters import (
37
36
  ATTR_ECOMAX_CONTROL,
38
37
  ATTR_ECOMAX_PARAMETERS,
@@ -49,6 +48,7 @@ from pyplumio.structures.mixer_parameters import ATTR_MIXER_PARAMETERS
49
48
  from pyplumio.structures.mixer_sensors import ATTR_MIXER_SENSORS
50
49
  from pyplumio.structures.network_info import ATTR_NETWORK, NetworkInfo
51
50
  from pyplumio.structures.product_info import ATTR_PRODUCT, ProductInfo
51
+ from pyplumio.structures.regulator_data_schema import ATTR_REGDATA_SCHEMA
52
52
  from pyplumio.structures.schedules import (
53
53
  ATTR_SCHEDULE_PARAMETERS,
54
54
  ATTR_SCHEDULES,
@@ -73,7 +73,7 @@ MAX_TIME_SINCE_LAST_FUEL_UPDATE_NS: Final = 300 * 1000000000
73
73
  SETUP_FRAME_TYPES: tuple[DataFrameDescription, ...] = (
74
74
  DataFrameDescription(frame_type=FrameType.REQUEST_UID, provides=ATTR_PRODUCT),
75
75
  DataFrameDescription(
76
- frame_type=FrameType.REQUEST_DATA_SCHEMA, provides=ATTR_SCHEMA
76
+ frame_type=FrameType.REQUEST_REGULATOR_DATA_SCHEMA, provides=ATTR_REGDATA_SCHEMA
77
77
  ),
78
78
  DataFrameDescription(
79
79
  frame_type=FrameType.REQUEST_ECOMAX_PARAMETERS, provides=ATTR_ECOMAX_PARAMETERS
@@ -95,7 +95,7 @@ SETUP_FRAME_TYPES: tuple[DataFrameDescription, ...] = (
95
95
  _LOGGER = logging.getLogger(__name__)
96
96
 
97
97
 
98
- class EcoMAX(Addressable):
98
+ class EcoMAX(AddressableDevice):
99
99
  """Represents an ecoMAX controller."""
100
100
 
101
101
  address: ClassVar[int] = DeviceType.ECOMAX
@@ -4,10 +4,10 @@ from __future__ import annotations
4
4
  from typing import ClassVar
5
5
 
6
6
  from pyplumio.const import DeviceType
7
- from pyplumio.devices import Addressable
7
+ from pyplumio.devices import AddressableDevice
8
8
 
9
9
 
10
- class EcoSTER(Addressable):
10
+ class EcoSTER(AddressableDevice):
11
11
  """Represents an ecoSTER thermostat."""
12
12
 
13
13
  address: ClassVar[int] = DeviceType.ECOSTER
pyplumio/devices/mixer.py CHANGED
@@ -5,7 +5,7 @@ import asyncio
5
5
  import logging
6
6
  from typing import Sequence
7
7
 
8
- from pyplumio.devices import Addressable, SubDevice
8
+ from pyplumio.devices import AddressableDevice, SubDevice
9
9
  from pyplumio.helpers.parameter import ParameterValues
10
10
  from pyplumio.helpers.typing import EventDataType
11
11
  from pyplumio.structures.mixer_parameters import (
@@ -24,7 +24,7 @@ _LOGGER = logging.getLogger(__name__)
24
24
  class Mixer(SubDevice):
25
25
  """Represents an mixer."""
26
26
 
27
- def __init__(self, queue: asyncio.Queue, parent: Addressable, index: int = 0):
27
+ def __init__(self, queue: asyncio.Queue, parent: AddressableDevice, index: int = 0):
28
28
  """Initialize a new mixer."""
29
29
  super().__init__(queue, parent, index)
30
30
  self.subscribe(ATTR_MIXER_SENSORS, self._handle_sensors)
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
  import asyncio
5
5
  from typing import Sequence
6
6
 
7
- from pyplumio.devices import Addressable, SubDevice
7
+ from pyplumio.devices import AddressableDevice, SubDevice
8
8
  from pyplumio.helpers.parameter import ParameterValues
9
9
  from pyplumio.helpers.typing import EventDataType
10
10
  from pyplumio.structures.thermostat_parameters import (
@@ -20,7 +20,7 @@ from pyplumio.structures.thermostat_sensors import ATTR_THERMOSTAT_SENSORS
20
20
  class Thermostat(SubDevice):
21
21
  """Represents a thermostat."""
22
22
 
23
- def __init__(self, queue: asyncio.Queue, parent: Addressable, index: int = 0):
23
+ def __init__(self, queue: asyncio.Queue, parent: AddressableDevice, index: int = 0):
24
24
  """Initialize a new thermostat."""
25
25
  super().__init__(queue, parent, index)
26
26
  self.subscribe(ATTR_THERMOSTAT_SENSORS, self._handle_sensors)
pyplumio/filters.py CHANGED
@@ -96,6 +96,8 @@ class _OnChange(Filter):
96
96
  previous callback call.
97
97
  """
98
98
 
99
+ __slots__ = ()
100
+
99
101
  async def __call__(self, new_value):
100
102
  """Set a new value for the callback."""
101
103
  if self._value == UNDEFINED or _significantly_changed(self._value, new_value):
@@ -109,6 +111,11 @@ def on_change(callback: EventCallbackType) -> _OnChange:
109
111
 
110
112
  A callback function will only be called if value is changed from the
111
113
  previous call.
114
+
115
+ :param callback: A callback function to be awaited on value change
116
+ :type callback: Callable[[Any], Awaitable[Any]]
117
+ :return: A instance of callable filter
118
+ :rtype: _OnChange
112
119
  """
113
120
  return _OnChange(callback)
114
121
 
@@ -125,7 +132,7 @@ class _Debounce(Filter):
125
132
  _calls: int
126
133
  _min_calls: int
127
134
 
128
- def __init__(self, callback: EventCallbackType, min_calls: int = 3):
135
+ def __init__(self, callback: EventCallbackType, min_calls: int):
129
136
  """Initialize a new debounce filter."""
130
137
  super().__init__(callback)
131
138
  self._calls = 0
@@ -149,6 +156,14 @@ def debounce(callback: EventCallbackType, min_calls) -> _Debounce:
149
156
 
150
157
  A callback function will only called once value is stabilized
151
158
  across multiple filter calls.
159
+
160
+ :param callback: A callback function to be awaited on value change
161
+ :type callback: Callable[[Any], Awaitable[Any]]
162
+ :param min_calls: Value shouldn't change for this amount of
163
+ filter calls
164
+ :type min_calls: int
165
+ :return: A instance of callable filter
166
+ :rtype: _Debounce
152
167
  """
153
168
  return _Debounce(callback, min_calls)
154
169
 
@@ -187,6 +202,15 @@ def throttle(callback: EventCallbackType, seconds: float) -> _Throttle:
187
202
 
188
203
  A callback function will only be called once a certain amount of
189
204
  seconds passed since the last call.
205
+
206
+ :param callback: A callback function that will be awaited once
207
+ filter conditions are fulfilled
208
+ :type callback: Callable[[Any], Awaitable[Any]]
209
+ :param seconds: A callback will be awaited at most once per
210
+ this amount of seconds
211
+ :type seconds: float
212
+ :return: A instance of callable filter
213
+ :rtype: _Throttle
190
214
  """
191
215
  return _Throttle(callback, seconds)
192
216
 
@@ -197,6 +221,8 @@ class _Delta(Filter):
197
221
  Calls a callback with a difference between two subsequent values.
198
222
  """
199
223
 
224
+ __slots__ = ()
225
+
200
226
  async def __call__(self, new_value):
201
227
  """Set a new value for the callback."""
202
228
  if self._value == UNDEFINED or _significantly_changed(self._value, new_value):
@@ -214,6 +240,12 @@ def delta(callback: EventCallbackType) -> _Delta:
214
240
 
215
241
  A callback function will be called with a difference between two
216
242
  subsequent value.
243
+
244
+ :param callback: A callback function that will be awaited with
245
+ difference between values in two subsequent calls
246
+ :type callback: Callable[[Any], Awaitable[Any]]
247
+ :return: A instance of callable filter
248
+ :rtype: _Delta
217
249
  """
218
250
  return _Delta(callback)
219
251
 
@@ -259,7 +291,16 @@ def aggregate(callback: EventCallbackType, seconds: float) -> _Aggregate:
259
291
  """An aggregate filter.
260
292
 
261
293
  A callback function will be called with a sum of values collected
262
- over a specified time period.
294
+ over a specified time period. Can only be used with numeric values.
295
+
296
+ :param callback: A callback function to be awaited once filter
297
+ conditions are fulfilled
298
+ :type callback: Callable[[Any], Awaitable[Any]]
299
+ :param seconds: A callback will be awaited with a sum of values
300
+ aggregated over this amount of seconds.
301
+ :type seconds: float
302
+ :return: A instance of callable filter
303
+ :rtype: _Aggregate
263
304
  """
264
305
  return _Aggregate(callback, seconds)
265
306
 
@@ -272,6 +313,10 @@ class _Custom(Filter):
272
313
  returns true.
273
314
  """
274
315
 
316
+ __slots__ = ("_filter_fn",)
317
+
318
+ filter_fn: Callable[[Any], bool]
319
+
275
320
  def __init__(self, callback: EventCallbackType, filter_fn: Callable[[Any], bool]):
276
321
  """Initialize a new custom filter."""
277
322
  super().__init__(callback)
@@ -289,5 +334,14 @@ def custom(callback: EventCallbackType, filter_fn: Callable[[Any], bool]) -> _Cu
289
334
  A callback function will be called when user-defined filter
290
335
  function, that's being called with the value as an argument,
291
336
  returns true.
337
+
338
+ :param callback: A callback function to be awaited when
339
+ filter function return true
340
+ :type callback: Callable[[Any], Awaitable[Any]]
341
+ :param filter_fn: Filter function, that will be called with a
342
+ value and should return `True` to await filter's callback
343
+ :type filter_fn: Callable[[Any], bool]
344
+ :return: A instance of callable filter
345
+ :rtype: _Custom
292
346
  """
293
347
  return _Custom(callback, filter_fn)