PyPlumIO 0.5.22__py3-none-any.whl → 0.5.23__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.
@@ -2,12 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from abc import ABC
5
+ from abc import ABC, abstractmethod
6
6
  import asyncio
7
7
  from dataclasses import dataclass
8
8
  import logging
9
9
  from typing import TYPE_CHECKING, Any, Final, Literal, TypeVar, Union
10
10
 
11
+ from dataslots import dataslots
12
+ from typing_extensions import TypeAlias
13
+
11
14
  from pyplumio.const import BYTE_UNDEFINED, STATE_OFF, STATE_ON, UnitOfMeasurement
12
15
  from pyplumio.frames import Request
13
16
 
@@ -19,7 +22,8 @@ _LOGGER = logging.getLogger(__name__)
19
22
  SET_TIMEOUT: Final = 5
20
23
  SET_RETRIES: Final = 5
21
24
 
22
- ParameterValueType = Union[int, float, bool, Literal["off"], Literal["on"]]
25
+ ParameterValueType: TypeAlias = Union[int, float, bool, Literal["off", "on"]]
26
+ ParameterT = TypeVar("ParameterT", bound="Parameter")
23
27
 
24
28
 
25
29
  def unpack_parameter(
@@ -46,13 +50,10 @@ def check_parameter(data: bytearray) -> bool:
46
50
 
47
51
 
48
52
  def _normalize_parameter_value(value: ParameterValueType) -> int:
49
- """Normalize a parameter value to an integer."""
50
- if isinstance(value, str):
53
+ """Normalize a parameter value."""
54
+ if value in (STATE_OFF, STATE_ON):
51
55
  return 1 if value == STATE_ON else 0
52
56
 
53
- if isinstance(value, ParameterValues):
54
- value = value.value
55
-
56
57
  return int(value)
57
58
 
58
59
 
@@ -67,21 +68,16 @@ class ParameterValues:
67
68
  max_value: int
68
69
 
69
70
 
71
+ @dataslots
70
72
  @dataclass
71
- class ParameterDescription(ABC):
73
+ class ParameterDescription:
72
74
  """Represents a parameter description."""
73
75
 
74
76
  name: str
75
- unit_of_measurement: UnitOfMeasurement | Literal["%"] | None = None
76
-
77
-
78
- @dataclass
79
- class BinaryParameterDescription(ParameterDescription, ABC):
80
- """Represent a binary parameter description."""
81
77
 
82
78
 
83
79
  class Parameter(ABC):
84
- """Represents a parameter."""
80
+ """Represents a base parameter."""
85
81
 
86
82
  __slots__ = ("device", "description", "_pending_update", "_index", "_values")
87
83
 
@@ -118,6 +114,7 @@ class Parameter(ABC):
118
114
  def _call_relational_method(self, method_to_call: str, other: Any) -> Any:
119
115
  """Call a specified relational method."""
120
116
  handler = getattr(self.values.value, method_to_call)
117
+ other = other.value if isinstance(other, ParameterValues) else other
121
118
  return handler(_normalize_parameter_value(other))
122
119
 
123
120
  def __int__(self) -> int:
@@ -164,11 +161,7 @@ class Parameter(ABC):
164
161
  """Compare if parameter value is less that other."""
165
162
  return self._call_relational_method("__lt__", other)
166
163
 
167
- async def create_request(self) -> Request:
168
- """Create a request to change the parameter."""
169
- raise NotImplementedError
170
-
171
- async def set(self, value: ParameterValueType, retries: int = SET_RETRIES) -> bool:
164
+ async def set(self, value: Any, retries: int = SET_RETRIES) -> bool:
172
165
  """Set a parameter value."""
173
166
  if (value := _normalize_parameter_value(value)) == self.values.value:
174
167
  return True
@@ -194,10 +187,6 @@ class Parameter(ABC):
194
187
 
195
188
  return True
196
189
 
197
- def set_nowait(self, value: ParameterValueType, retries: int = SET_RETRIES) -> None:
198
- """Set a parameter value without waiting."""
199
- self.device.create_task(self.set(value, retries))
200
-
201
190
  def update(self, values: ParameterValues) -> None:
202
191
  """Update the parameter values."""
203
192
  self._values = values
@@ -213,26 +202,6 @@ class Parameter(ABC):
213
202
  """Return the parameter values."""
214
203
  return self._values
215
204
 
216
- @property
217
- def value(self) -> ParameterValueType:
218
- """Return the parameter value."""
219
- return self.values.value
220
-
221
- @property
222
- def min_value(self) -> ParameterValueType:
223
- """Return the minimum allowed value."""
224
- return self.values.min_value
225
-
226
- @property
227
- def max_value(self) -> ParameterValueType:
228
- """Return the maximum allowed value."""
229
- return self.values.max_value
230
-
231
- @property
232
- def unit_of_measurement(self) -> UnitOfMeasurement | Literal["%"] | None:
233
- """Return the unit of measurement."""
234
- return self.description.unit_of_measurement
235
-
236
205
  @classmethod
237
206
  def create_or_update(
238
207
  cls: type[ParameterT],
@@ -252,15 +221,101 @@ class Parameter(ABC):
252
221
 
253
222
  return parameter
254
223
 
224
+ @property
225
+ @abstractmethod
226
+ def value(self) -> Any:
227
+ """Return the value."""
228
+
229
+ @property
230
+ @abstractmethod
231
+ def min_value(self) -> Any:
232
+ """Return the minimum allowed value."""
233
+
234
+ @property
235
+ @abstractmethod
236
+ def max_value(self) -> Any:
237
+ """Return the maximum allowed value."""
238
+
239
+ @abstractmethod
240
+ async def create_request(self) -> Request:
241
+ """Create a request to change the parameter."""
255
242
 
256
- ParameterT = TypeVar("ParameterT", bound=Parameter)
257
243
 
244
+ @dataslots
245
+ @dataclass
246
+ class NumberDescription(ParameterDescription):
247
+ """Represents a parameter description."""
258
248
 
259
- class BinaryParameter(Parameter):
260
- """Represents binary device parameter."""
249
+ unit_of_measurement: UnitOfMeasurement | Literal["%"] | None = None
250
+
251
+
252
+ class Number(Parameter):
253
+ """Represents a number."""
254
+
255
+ __slots__ = ()
256
+
257
+ description: NumberDescription
258
+
259
+ async def set(self, value: int | float, retries: int = SET_RETRIES) -> bool:
260
+ """Set a parameter value."""
261
+ return await super().set(value, retries)
262
+
263
+ def set_nowait(self, value: int | float, retries: int = SET_RETRIES) -> None:
264
+ """Set a parameter value without waiting."""
265
+ self.device.create_task(self.set(value, retries))
266
+
267
+ async def create_request(self) -> Request:
268
+ """Create a request to change the number."""
269
+ return Request()
270
+
271
+ @property
272
+ def value(self) -> int | float:
273
+ """Return the value."""
274
+ return self.values.value
275
+
276
+ @property
277
+ def min_value(self) -> int | float:
278
+ """Return the minimum allowed value."""
279
+ return self.values.min_value
280
+
281
+ @property
282
+ def max_value(self) -> int | float:
283
+ """Return the maximum allowed value."""
284
+ return self.values.max_value
285
+
286
+ @property
287
+ def unit_of_measurement(self) -> UnitOfMeasurement | Literal["%"] | None:
288
+ """Return the unit of measurement."""
289
+ return self.description.unit_of_measurement
290
+
291
+
292
+ @dataslots
293
+ @dataclass
294
+ class SwitchDescription(ParameterDescription):
295
+ """Represents a switch description."""
296
+
297
+
298
+ class Switch(Parameter):
299
+ """Represents a switch."""
300
+
301
+ __slots__ = ()
302
+
303
+ description: SwitchDescription
304
+
305
+ async def set(
306
+ self, value: bool | Literal["off", "on"], retries: int = SET_RETRIES
307
+ ) -> bool:
308
+ """Set a parameter value."""
309
+ return await super().set(value, retries)
310
+
311
+ def set_nowait(
312
+ self, value: bool | Literal["off", "on"], retries: int = SET_RETRIES
313
+ ) -> None:
314
+ """Set a switch value without waiting."""
315
+ self.device.create_task(self.set(value, retries))
261
316
 
262
317
  async def turn_on(self) -> bool:
263
- """Set a parameter value to 'on'.
318
+ """Set a switch value to 'on'.
264
319
 
265
320
  :return: `True` if parameter was successfully turned on, `False`
266
321
  otherwise.
@@ -269,7 +324,7 @@ class BinaryParameter(Parameter):
269
324
  return await self.set(STATE_ON)
270
325
 
271
326
  async def turn_off(self) -> bool:
272
- """Set a parameter value to 'off'.
327
+ """Set a switch value to 'off'.
273
328
 
274
329
  :return: `True` if parameter was successfully turned off, `False`
275
330
  otherwise.
@@ -278,24 +333,28 @@ class BinaryParameter(Parameter):
278
333
  return await self.set(STATE_OFF)
279
334
 
280
335
  def turn_on_nowait(self) -> None:
281
- """Set a parameter value to 'on' without waiting."""
336
+ """Set a switch value to 'on' without waiting."""
282
337
  self.set_nowait(STATE_ON)
283
338
 
284
339
  def turn_off_nowait(self) -> None:
285
- """Set a parameter value to 'off' without waiting."""
340
+ """Set a switch value to 'off' without waiting."""
286
341
  self.set_nowait(STATE_OFF)
287
342
 
343
+ async def create_request(self) -> Request:
344
+ """Create a request to change the switch."""
345
+ return Request()
346
+
288
347
  @property
289
- def value(self) -> ParameterValueType:
290
- """Return the parameter value."""
348
+ def value(self) -> Literal["off", "on"]:
349
+ """Return the value."""
291
350
  return STATE_ON if self.values.value == 1 else STATE_OFF
292
351
 
293
352
  @property
294
- def min_value(self) -> ParameterValueType:
353
+ def min_value(self) -> Literal["off"]:
295
354
  """Return the minimum allowed value."""
296
355
  return STATE_OFF
297
356
 
298
357
  @property
299
- def max_value(self) -> ParameterValueType:
358
+ def max_value(self) -> Literal["on"]:
300
359
  """Return the maximum allowed value."""
301
360
  return STATE_ON
pyplumio/protocol.py CHANGED
@@ -8,6 +8,8 @@ from collections.abc import Awaitable, Callable
8
8
  from dataclasses import dataclass
9
9
  import logging
10
10
 
11
+ from typing_extensions import TypeAlias
12
+
11
13
  from pyplumio.const import ATTR_CONNECTED, DeviceType
12
14
  from pyplumio.devices import AddressableDevice
13
15
  from pyplumio.exceptions import ProtocolError
@@ -23,7 +25,7 @@ from pyplumio.structures.network_info import (
23
25
 
24
26
  _LOGGER = logging.getLogger(__name__)
25
27
 
26
- _Callback = Callable[[], Awaitable[None]]
28
+ _Callback: TypeAlias = Callable[[], Awaitable[None]]
27
29
 
28
30
 
29
31
  class Protocol(ABC):
@@ -111,7 +113,7 @@ class Queues:
111
113
  await asyncio.gather(self.read.join(), self.write.join())
112
114
 
113
115
 
114
- class AsyncProtocol(Protocol, EventManager):
116
+ class AsyncProtocol(Protocol, EventManager[AddressableDevice]):
115
117
  """Represents an async protocol.
116
118
 
117
119
  This protocol implements producer-consumers pattern using
@@ -128,7 +130,6 @@ class AsyncProtocol(Protocol, EventManager):
128
130
  """
129
131
 
130
132
  consumers_count: int
131
- data: dict[str, AddressableDevice]
132
133
  _network: NetworkInfo
133
134
  _queues: Queues
134
135