PyPlumIO 0.5.30__py3-none-any.whl → 0.5.31__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
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: PyPlumIO
3
- Version: 0.5.30
3
+ Version: 0.5.31
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
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.9
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
20
21
  Classifier: Topic :: Software Development :: Libraries
21
22
  Classifier: Topic :: Home Automation
22
23
  Requires-Python: >=3.9
@@ -27,14 +28,14 @@ Requires-Dist: pyserial-asyncio==0.6
27
28
  Requires-Dist: typing-extensions==4.12.2
28
29
  Provides-Extra: test
29
30
  Requires-Dist: codespell==2.3.0; extra == "test"
30
- Requires-Dist: coverage==7.6.8; extra == "test"
31
- Requires-Dist: mypy==1.13.0; extra == "test"
31
+ Requires-Dist: coverage==7.6.10; extra == "test"
32
+ Requires-Dist: mypy==1.14.1; extra == "test"
32
33
  Requires-Dist: pyserial-asyncio-fast==0.14; extra == "test"
33
34
  Requires-Dist: pytest==8.3.4; extra == "test"
34
- Requires-Dist: pytest-asyncio==0.24.0; extra == "test"
35
- Requires-Dist: ruff==0.8.1; extra == "test"
35
+ Requires-Dist: pytest-asyncio==0.25.2; extra == "test"
36
+ Requires-Dist: ruff==0.9.2; extra == "test"
36
37
  Requires-Dist: tox==4.23.2; extra == "test"
37
- Requires-Dist: types-pyserial==3.5.0.20240826; extra == "test"
38
+ Requires-Dist: types-pyserial==3.5.0.20241221; extra == "test"
38
39
  Provides-Extra: docs
39
40
  Requires-Dist: sphinx==8.1.3; extra == "docs"
40
41
  Requires-Dist: sphinx_rtd_theme==3.0.2; extra == "docs"
@@ -1,15 +1,15 @@
1
1
  pyplumio/__init__.py,sha256=ditJTIOFGJDg60atHzOpiggdUrZHpSynno7MtpZUGVk,3299
2
2
  pyplumio/__main__.py,sha256=3IwHHSq-iay5FaeMc95klobe-xv82yydSKcBE7BFZ6M,500
3
- pyplumio/_version.py,sha256=PRcySwknPDLJzIxasFyVZNYI8LFj_28fjnJMHK2q0Ko,413
3
+ pyplumio/_version.py,sha256=Kr7Tq9KjyxEp8tm444HGzXvFWTTLR8xyIJ5ABXwwKGA,413
4
4
  pyplumio/connection.py,sha256=6mUbcjGxxEhMVIbzZgCqH-Ez-fcYoRj7ZbVSzpikpNA,5949
5
5
  pyplumio/const.py,sha256=LyXa5aVy2KxnZq7H7F8s5SYsAgEC2UzZYMMRauliB2E,5502
6
6
  pyplumio/exceptions.py,sha256=Wn-y5AJ5xfaBlHhTUVKB27_0Us8_OVHqh-sicnr9sYA,700
7
- pyplumio/filters.py,sha256=KK_AV_EHy5gj9s9BNZbn9i0RnT3uZsdEg6gdve1WYrY,11152
7
+ pyplumio/filters.py,sha256=AMW1zHQ1YjJfHX7e87Dhv7AGixJ3y9Vn-_JAQn7vIsg,12526
8
8
  pyplumio/protocol.py,sha256=VRxrj8vZ1FMawqblKkyxg_V61TBSvVynd9u0JXYnMUU,8090
9
9
  pyplumio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  pyplumio/stream.py,sha256=mtMpnUR3TfEmL5JUGXr6GnpPGBwzCokqIKDWp4vYiVg,4654
11
11
  pyplumio/utils.py,sha256=TnBzRopinyp92wruguijxcIYmaeyNVTFX0dygI5FCMU,823
12
- pyplumio/devices/__init__.py,sha256=YN09bGsyJ5WVmF8_-veUckqUl57eBwmfNr8M5qhyqy0,8149
12
+ pyplumio/devices/__init__.py,sha256=BEUpL2XxEk4YDfp4w0VX_LI4JQwK27eGWoJ6al_e1nE,8038
13
13
  pyplumio/devices/ecomax.py,sha256=ybFLJN7O3unBcyzuVmYTssBv86bPiiTGvFpFJezwUE4,15478
14
14
  pyplumio/devices/ecoster.py,sha256=jNWli7ye9T6yfkcFJZhhUHH7KOv-L6AgYFp_dKyv3OM,263
15
15
  pyplumio/devices/mixer.py,sha256=CnHWrJELtFgs2YTHGpQwKr2UTRdetX76OvLBA2PH-fs,3207
@@ -22,7 +22,7 @@ pyplumio/helpers/__init__.py,sha256=H2xxdkF-9uADLwEbfBUoxNTdwru3L5Z2cfJjgsuRsn0,
22
22
  pyplumio/helpers/data_types.py,sha256=nB3afOLmppgSCWkZoX1-1yWPNMMNSem77x7XQ1Mi8H8,9103
23
23
  pyplumio/helpers/event_manager.py,sha256=xQOfiP_nP1Pz5zhB6HU5gXyyJXjhisYshL8_HRxDgt8,6412
24
24
  pyplumio/helpers/factory.py,sha256=6ArzJDq3MiiMaRpMEP0kC6wJWsoqOqe32V1RCxg1478,1005
25
- pyplumio/helpers/parameter.py,sha256=yO3KSX8FtU-dMe5FzNW-RXs5yW-lYu2F5Po-4ghcSnM,12533
25
+ pyplumio/helpers/parameter.py,sha256=hOGYkhd7-MG1euNdbHYN_2vXFlWPi-XLy_yAotYSyck,12311
26
26
  pyplumio/helpers/schedule.py,sha256=PnVEkgthg6tHpHvZK9fXJz9VKNDyQ_7BFT4TTVEwNhI,5310
27
27
  pyplumio/helpers/task_manager.py,sha256=HAd69yGTRL0zQsu-ywnbLu1UXiJzgHWuhYWA--vs4lQ,1181
28
28
  pyplumio/helpers/timeout.py,sha256=JAhWNtIpcXyVILIwHWVy5mYofqbbRDGKLdTUKkQuajs,772
@@ -31,13 +31,13 @@ pyplumio/structures/__init__.py,sha256=EjK-5qJZ0F7lpP2b6epvTMg9cIBl4Kn91nqNkEcLw
31
31
  pyplumio/structures/alerts.py,sha256=8ievMl5_tUBlnTLCiZoIloucIngCcoAYy6uI9sSXrt0,3664
32
32
  pyplumio/structures/boiler_load.py,sha256=p3mOzZUU-g7A2tG_yp8podEqpI81hlsOZmHELyPNRY8,838
33
33
  pyplumio/structures/boiler_power.py,sha256=72qsvccg49FdRdXv2f2K5sGpjT7wAOLFjlIGWpO-DVg,901
34
- pyplumio/structures/ecomax_parameters.py,sha256=ki9YSzVRhCD_rYHFogJoyk0NwyNlWdZrHcp-rrCuKCU,28440
34
+ pyplumio/structures/ecomax_parameters.py,sha256=wLwhTdKee-UtCU5NuRfOHRPvnjDOtDNUDeUgeO0VH8w,27974
35
35
  pyplumio/structures/fan_power.py,sha256=Q5fv-7_2NVuLeQPIVIylvgN7M8-a9D8rRUE0QGjyS3w,871
36
36
  pyplumio/structures/frame_versions.py,sha256=hbcVuhuPNy5qd39Vk7w4WdPCW-TNx1cAYWzA2mXocyk,1548
37
37
  pyplumio/structures/fuel_consumption.py,sha256=_p2dI4H67Eopn7IF0Gj77A8c_8lNKhhDDAtmugxLd4s,976
38
38
  pyplumio/structures/fuel_level.py,sha256=mJpp1dnRD1wXi_6EyNX7TNXosjcr905rSHOnuZ5VD74,1069
39
39
  pyplumio/structures/lambda_sensor.py,sha256=JNSCiBJoM8Uk3OGbmFIigaLOntQST5U_UrmCpaQBlM0,1595
40
- pyplumio/structures/mixer_parameters.py,sha256=S_YOigzM9TsdEjk5EluME5fJ8owO84-xOFT9tTdBgEo,9553
40
+ pyplumio/structures/mixer_parameters.py,sha256=idF3tYukfAz1EM1CE-hZBjjmGrNZN6X1MlcZr3FHrzA,9089
41
41
  pyplumio/structures/mixer_sensors.py,sha256=-cN7U-Fr2fmAQ5McQL7bZUC8CFlb1y8TN0f_dqy3UK0,2312
42
42
  pyplumio/structures/modules.py,sha256=oXUIqrOAV1dZzBV5zUH3HDUSFvNOjpUSx0TF9nZVnbs,2569
43
43
  pyplumio/structures/network_info.py,sha256=kPxmIaDGm5SyLRKVFzcrODlUtB0u5JjiZqekoKSyDpA,4159
@@ -48,13 +48,13 @@ pyplumio/structures/product_info.py,sha256=uiEN6DFQlzmBvQByTirFzXQShoex0YGdFS9WI
48
48
  pyplumio/structures/program_version.py,sha256=R-medELYHDlk_ALsw5HOVbZRb7JD3yBUsGwqwVCjrkU,2550
49
49
  pyplumio/structures/regulator_data.py,sha256=z2mSE-cxImn8YRr_yZCcDlIbXnKdETkN7GigV5vEJqA,2265
50
50
  pyplumio/structures/regulator_data_schema.py,sha256=XM6M9ep3NyogbLPqp88mMTg8Sa9e5SFzV5I5pSYw5GY,1487
51
- pyplumio/structures/schedules.py,sha256=rKPWC5qcKAh6xxs91oY23NqQcWby8e3gXrD6qJAVDGo,7153
51
+ pyplumio/structures/schedules.py,sha256=_D8HmxMVvAAPb0cc_xSxXFRNwR9u-RWuyTy0Z5KscUk,6717
52
52
  pyplumio/structures/statuses.py,sha256=wkoynyMRr1VREwfBC6vU48kPA8ZQ83pcXuciy2xHJrk,1166
53
53
  pyplumio/structures/temperatures.py,sha256=1CDzehNmbALz1Jyt_9gZNIk52q6Wv-xQXjijVDCVYec,2337
54
- pyplumio/structures/thermostat_parameters.py,sha256=6r8_EU9T1IJ0vzZMduiLzsAaaWr6cKW_zHHAGsfGZI4,8804
54
+ pyplumio/structures/thermostat_parameters.py,sha256=QA-ZyulBG3P10sqgdI7rmpQYlKm9SJIXxBxAXs8Bwow,8295
55
55
  pyplumio/structures/thermostat_sensors.py,sha256=8e1TxYIJTQKT0kIGO9gG4hGdLOBUpIhiPToQyOMyeNE,3237
56
- PyPlumIO-0.5.30.dist-info/LICENSE,sha256=m-UuZFjXJ22uPTGm9kSHS8bqjsf5T8k2wL9bJn1Y04o,1088
57
- PyPlumIO-0.5.30.dist-info/METADATA,sha256=KMMtx2B4gTlnFBoLVzVHGs75Od9qf6BN1tH3pqeYgqM,5458
58
- PyPlumIO-0.5.30.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
59
- PyPlumIO-0.5.30.dist-info/top_level.txt,sha256=kNBz9UPPkPD9teDn3U_sEy5LjzwLm9KfADCXtBlbw8A,9
60
- PyPlumIO-0.5.30.dist-info/RECORD,,
56
+ PyPlumIO-0.5.31.dist-info/LICENSE,sha256=m-UuZFjXJ22uPTGm9kSHS8bqjsf5T8k2wL9bJn1Y04o,1088
57
+ PyPlumIO-0.5.31.dist-info/METADATA,sha256=thPWL1GWRLLFkIdMOBz4CUN4LZmGxEA_BvvWYKjR-xA,5510
58
+ PyPlumIO-0.5.31.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
59
+ PyPlumIO-0.5.31.dist-info/top_level.txt,sha256=kNBz9UPPkPD9teDn3U_sEy5LjzwLm9KfADCXtBlbw8A,9
60
+ PyPlumIO-0.5.31.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
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.30'
16
- __version_tuple__ = version_tuple = (0, 5, 30)
15
+ __version__ = version = '0.5.31'
16
+ __version_tuple__ = version_tuple = (0, 5, 31)
@@ -107,9 +107,6 @@ class Device(ABC, EventManager):
107
107
  this value is used to determine failure when
108
108
  retrying and doesn't block, defaults to `None`
109
109
  :type timeout: float, optional
110
- :return: `True` if parameter was successfully set, `False`
111
- otherwise.
112
- :rtype: bool
113
110
  """
114
111
  self.create_task(self.set(name, value, retries, timeout))
115
112
 
pyplumio/filters.py CHANGED
@@ -125,6 +125,52 @@ class Filter(ABC):
125
125
  """Set a new value for the callback."""
126
126
 
127
127
 
128
+ class _Clamp(Filter):
129
+ """Represents a clamp filter.
130
+
131
+ Calls callback with a value clamped between specified boundaries.
132
+ """
133
+
134
+ __slots__ = ("_min_value", "_max_value")
135
+
136
+ _min_value: float
137
+ _max_value: float
138
+
139
+ def __init__(self, callback: Callback, min_value: float, max_value: float) -> None:
140
+ """Initialize a new clamp filter."""
141
+ super().__init__(callback)
142
+ self._min_value = min_value
143
+ self._max_value = max_value
144
+
145
+ async def __call__(self, new_value: Any) -> Any:
146
+ """Set a new value for the callback."""
147
+ if new_value < self._min_value:
148
+ return await self._callback(self._min_value)
149
+
150
+ if new_value > self._max_value:
151
+ return await self._callback(self._max_value)
152
+
153
+ return await self._callback(new_value)
154
+
155
+
156
+ def clamp(callback: Callback, min_value: float, max_value: float) -> _Clamp:
157
+ """Return a clamp filter.
158
+
159
+ A callback function will be called with value clamped between
160
+ specified boundaries.
161
+
162
+ :param callback: A callback function to be awaited on new value
163
+ :type callback: Callback
164
+ :param min_value: A lower boundary
165
+ :type min_value: float
166
+ :param max_value: An upper boundary
167
+ :type max_value: float
168
+ :return: An instance of callable filter
169
+ :rtype: _Clamp
170
+ """
171
+ return _Clamp(callback, min_value, max_value)
172
+
173
+
128
174
  class _OnChange(Filter):
129
175
  """Represents a value changed filter.
130
176
 
@@ -151,7 +197,7 @@ def on_change(callback: Callback) -> _OnChange:
151
197
 
152
198
  :param callback: A callback function to be awaited on value change
153
199
  :type callback: Callback
154
- :return: A instance of callable filter
200
+ :return: An instance of callable filter
155
201
  :rtype: _OnChange
156
202
  """
157
203
  return _OnChange(callback)
@@ -201,7 +247,7 @@ def debounce(callback: Callback, min_calls: int) -> _Debounce:
201
247
  :param min_calls: Value shouldn't change for this amount of
202
248
  filter calls
203
249
  :type min_calls: int
204
- :return: A instance of callable filter
250
+ :return: An instance of callable filter
205
251
  :rtype: _Debounce
206
252
  """
207
253
  return _Debounce(callback, min_calls)
@@ -248,7 +294,7 @@ def throttle(callback: Callback, seconds: float) -> _Throttle:
248
294
  :param seconds: A callback will be awaited at most once per
249
295
  this amount of seconds
250
296
  :type seconds: float
251
- :return: A instance of callable filter
297
+ :return: An instance of callable filter
252
298
  :rtype: _Throttle
253
299
  """
254
300
  return _Throttle(callback, seconds)
@@ -285,7 +331,7 @@ def delta(callback: Callback) -> _Delta:
285
331
  :param callback: A callback function that will be awaited with
286
332
  difference between values in two subsequent calls
287
333
  :type callback: Callback
288
- :return: A instance of callable filter
334
+ :return: An instance of callable filter
289
335
  :rtype: _Delta
290
336
  """
291
337
  return _Delta(callback)
@@ -340,7 +386,7 @@ def aggregate(callback: Callback, seconds: float) -> _Aggregate:
340
386
  :param seconds: A callback will be awaited with a sum of values
341
387
  aggregated over this amount of seconds.
342
388
  :type seconds: float
343
- :return: A instance of callable filter
389
+ :return: An instance of callable filter
344
390
  :rtype: _Aggregate
345
391
  """
346
392
  return _Aggregate(callback, seconds)
@@ -382,7 +428,7 @@ def custom(callback: Callback, filter_fn: Callable[[Any], bool]) -> _Custom:
382
428
  :param filter_fn: Filter function, that will be called with a
383
429
  value and should return `True` to await filter's callback
384
430
  :type filter_fn: Callable[[Any], bool]
385
- :return: A instance of callable filter
431
+ :return: An instance of callable filter
386
432
  :rtype: _Custom
387
433
  """
388
434
  return _Custom(callback, filter_fn)
@@ -184,16 +184,31 @@ class Parameter(ABC):
184
184
  )
185
185
  return type(self)(self.device, self.description, values)
186
186
 
187
- async def set(self, value: Any, retries: int = 5, timeout: float = 5.0) -> bool:
188
- """Set a parameter value."""
189
- if (value := _normalize_parameter_value(value)) == self.values.value:
190
- return True
187
+ def validate(self, value: ParameterValue) -> int:
188
+ """Validate a parameter value."""
189
+ value = _normalize_parameter_value(value)
190
+ if value == self.values.value:
191
+ raise ValueError("Parameter value is unchanged.")
191
192
 
192
193
  if value < self.values.min_value or value > self.values.max_value:
193
194
  raise ValueError(
194
195
  f"Value must be between '{self.min_value}' and '{self.max_value}'"
195
196
  )
196
197
 
198
+ return value
199
+
200
+ async def set(self, value: Any, retries: int = 5, timeout: float = 5.0) -> bool:
201
+ """Set a parameter value."""
202
+ return await self._try_set(self.validate(value), retries, timeout)
203
+
204
+ def set_nowait(self, value: Any, retries: int = 5, timeout: float = 5.0) -> None:
205
+ """Set a parameter value without waiting."""
206
+ self.device.create_task(self._try_set(self.validate(value), retries, timeout))
207
+
208
+ async def _try_set(
209
+ self, value: Any, retries: int = 5, timeout: float = 5.0
210
+ ) -> bool:
211
+ """Try to set a parameter value."""
197
212
  self._previous_value = self._values.value
198
213
  self._values.value = value
199
214
  self._pending_update = True
@@ -206,9 +221,6 @@ class Parameter(ABC):
206
221
  return False
207
222
 
208
223
  await self.device.queue.put(await self.create_request())
209
- if not self.is_tracking_changes:
210
- await self.force_refresh()
211
-
212
224
  await asyncio.sleep(timeout)
213
225
  retries -= 1
214
226
 
@@ -221,15 +233,6 @@ class Parameter(ABC):
221
233
 
222
234
  self._values = values
223
235
 
224
- async def force_refresh(self) -> None:
225
- """Refresh the parameter from remote."""
226
- await self.device.queue.put(await self.create_refresh_request())
227
-
228
- @property
229
- def is_tracking_changes(self) -> bool:
230
- """Return True if remote's tracking changes, False otherwise."""
231
- return False
232
-
233
236
  @property
234
237
  def pending_update(self) -> bool:
235
238
  """Check if parameter is pending update on the device."""
@@ -278,10 +281,6 @@ class Parameter(ABC):
278
281
  async def create_request(self) -> Request:
279
282
  """Create a request to change the parameter."""
280
283
 
281
- @abstractmethod
282
- async def create_refresh_request(self) -> Request:
283
- """Create a request to refresh the parameter."""
284
-
285
284
 
286
285
  @dataslots
287
286
  @dataclass
@@ -308,16 +307,12 @@ class Number(Parameter):
308
307
  self, value: int | float, retries: int = 5, timeout: float = 5.0
309
308
  ) -> None:
310
309
  """Set a parameter value without waiting."""
311
- self.device.create_task(self.set(value, retries, timeout))
310
+ super().set_nowait(value, retries, timeout)
312
311
 
313
312
  async def create_request(self) -> Request:
314
313
  """Create a request to change the number."""
315
314
  return Request()
316
315
 
317
- async def create_refresh_request(self) -> Request:
318
- """Create a request to refresh the number."""
319
- return Request()
320
-
321
316
  @property
322
317
  def value(self) -> int | float:
323
318
  """Return the value."""
@@ -362,7 +357,7 @@ class Switch(Parameter):
362
357
  self, value: bool | Literal["off", "on"], retries: int = 5, timeout: float = 5.0
363
358
  ) -> None:
364
359
  """Set a switch value without waiting."""
365
- self.device.create_task(self.set(value, retries, timeout))
360
+ super().set_nowait(value, retries, timeout)
366
361
 
367
362
  async def turn_on(self) -> bool:
368
363
  """Set a switch value to 'on'.
@@ -394,10 +389,6 @@ class Switch(Parameter):
394
389
  """Create a request to change the switch."""
395
390
  return Request()
396
391
 
397
- async def create_refresh_request(self) -> Request:
398
- """Create a request to refresh the switch."""
399
- return Request()
400
-
401
392
  @property
402
393
  def value(self) -> Literal["off", "on"]:
403
394
  """Return the value."""
@@ -83,17 +83,6 @@ class EcomaxParameter(Parameter):
83
83
  data={ATTR_INDEX: self._index, ATTR_VALUE: self.values.value},
84
84
  )
85
85
 
86
- async def create_refresh_request(self) -> Request:
87
- """Create a request to refresh the parameter."""
88
- return await Request.create(
89
- FrameType.REQUEST_ECOMAX_PARAMETERS, recipient=self.device.address
90
- )
91
-
92
- @property
93
- def is_tracking_changes(self) -> bool:
94
- """Return True if remote's tracking changes, False otherwise."""
95
- return self.device.has_frame_version(FrameType.REQUEST_ECOMAX_PARAMETERS)
96
-
97
86
 
98
87
  @dataslots
99
88
  @dataclass
@@ -479,8 +468,8 @@ ECOMAX_PARAMETERS: dict[ProductType, tuple[EcomaxParameterDescription, ...]] = {
479
468
  ),
480
469
  EcomaxNumberDescription(
481
470
  name="max_fuel_flow",
482
- multiplier=0.1,
483
- unit_of_measurement=UnitOfMeasurement.KILOGRAMS_PER_HOUR,
471
+ multiplier=20,
472
+ unit_of_measurement=UnitOfMeasurement.GRAMS,
484
473
  ),
485
474
  EcomaxNumberDescription(
486
475
  name="feeder_calibration",
@@ -65,17 +65,6 @@ class MixerParameter(Parameter):
65
65
  },
66
66
  )
67
67
 
68
- async def create_refresh_request(self) -> Request:
69
- """Create a request to refresh the parameter."""
70
- return await Request.create(
71
- FrameType.REQUEST_MIXER_PARAMETERS, recipient=self.device.parent.address
72
- )
73
-
74
- @property
75
- def is_tracking_changes(self) -> bool:
76
- """Return True if remote's tracking changes, False otherwise."""
77
- return self.device.parent.has_frame_version(FrameType.REQUEST_MIXER_PARAMETERS)
78
-
79
68
 
80
69
  @dataslots
81
70
  @dataclass
@@ -107,17 +107,6 @@ class ScheduleParameter(Parameter):
107
107
  data=collect_schedule_data(schedule_name, self.device),
108
108
  )
109
109
 
110
- async def create_refresh_request(self) -> Request:
111
- """Create a request to refresh the parameter."""
112
- return await Request.create(
113
- FrameType.REQUEST_SCHEDULES, recipient=self.device.address
114
- )
115
-
116
- @property
117
- def is_tracking_changes(self) -> bool:
118
- """Return True if remote's tracking changes, False otherwise."""
119
- return self.device.has_frame_version(FrameType.REQUEST_SCHEDULES)
120
-
121
110
 
122
111
  @dataslots
123
112
  @dataclass
@@ -86,20 +86,6 @@ class ThermostatParameter(Parameter):
86
86
  },
87
87
  )
88
88
 
89
- async def create_refresh_request(self) -> Request:
90
- """Create a request to refresh the parameter."""
91
- return await Request.create(
92
- FrameType.REQUEST_THERMOSTAT_PARAMETERS,
93
- recipient=self.device.parent.address,
94
- )
95
-
96
- @property
97
- def is_tracking_changes(self) -> bool:
98
- """Return True if remote's tracking changes, False otherwise."""
99
- return self.device.parent.has_frame_version(
100
- FrameType.REQUEST_THERMOSTAT_PARAMETERS
101
- )
102
-
103
89
 
104
90
  @dataslots
105
91
  @dataclass