blebox-uniapi 2.5.1__tar.gz → 2.5.3__tar.gz

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.
Files changed (38) hide show
  1. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/PKG-INFO +1 -1
  2. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/__init__.py +1 -1
  3. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/binary_sensor.py +64 -6
  4. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/box_types.py +3 -0
  5. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/cover.py +14 -2
  6. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/light.py +10 -2
  7. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/sensor.py +18 -3
  8. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/switch.py +11 -0
  9. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/PKG-INFO +1 -1
  10. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/setup.cfg +1 -1
  11. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/setup.py +1 -1
  12. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/CONTRIBUTING.rst +0 -0
  13. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/HISTORY.rst +0 -0
  14. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/LICENSE +0 -0
  15. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/MANIFEST.in +0 -0
  16. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/README.rst +0 -0
  17. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/box.py +0 -0
  18. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/button.py +0 -0
  19. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/climate.py +0 -0
  20. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/error.py +0 -0
  21. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/feature.py +0 -0
  22. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/jfollow.py +0 -0
  23. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/session.py +0 -0
  24. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/SOURCES.txt +0 -0
  25. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/dependency_links.txt +0 -0
  26. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/not-zip-safe +0 -0
  27. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/requires.txt +0 -0
  28. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/top_level.txt +0 -0
  29. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/Makefile +0 -0
  30. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/authors.rst +0 -0
  31. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/conf.py +0 -0
  32. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/contributing.rst +0 -0
  33. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/history.rst +0 -0
  34. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/index.rst +0 -0
  35. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/installation.rst +0 -0
  36. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/make.bat +0 -0
  37. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/readme.rst +0 -0
  38. {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/usage.rst +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: blebox_uniapi
3
- Version: 2.5.1
3
+ Version: 2.5.3
4
4
  Summary: Python API for accessing BleBox smart home devices
5
5
  Home-page: https://github.com/blebox/blebox_uniapi
6
6
  Author: BleBox
@@ -2,4 +2,4 @@
2
2
 
3
3
  __author__ = """BleBox"""
4
4
  __email__ = "opensource@blebox.eu"
5
- __version__ = "2.5.1"
5
+ __version__ = "2.5.3"
@@ -1,4 +1,4 @@
1
- from typing import Union, TYPE_CHECKING
1
+ from typing import Union, Optional, TYPE_CHECKING
2
2
 
3
3
  from .feature import Feature
4
4
 
@@ -9,9 +9,19 @@ if TYPE_CHECKING:
9
9
  class BinarySensor(Feature):
10
10
  """Class representing sensor with bool state."""
11
11
 
12
- def __init__(self, product: "Box", alias: str, methods: dict):
12
+ def __init__(self, product: "Box", alias: str, methods: dict, sensor_id: Optional[int] = None, name: Optional[str] = None):
13
+ self._sensor_id = sensor_id
14
+ self._name = name
13
15
  super().__init__(product, alias, methods)
14
16
 
17
+ @property
18
+ def index(self) -> Optional[int]:
19
+ return self._sensor_id
20
+
21
+ @property
22
+ def name(self) -> Optional[str]:
23
+ return self._name
24
+
15
25
  @classmethod
16
26
  def many_from_config(
17
27
  cls, product, box_type_config, extended_state
@@ -19,6 +29,8 @@ class BinarySensor(Feature):
19
29
  type_class_map = {
20
30
  "rain": Rain,
21
31
  "flood": Flood,
32
+ "openStatus": Open,
33
+ "binary": Input,
22
34
  }
23
35
 
24
36
  output_list = list()
@@ -39,6 +51,8 @@ class BinarySensor(Feature):
39
51
  product=product,
40
52
  alias=sensor_type + "_" + str(sensor_id),
41
53
  methods=value_method,
54
+ sensor_id=sensor_id,
55
+ name=sensor.get("name"),
42
56
  )
43
57
  )
44
58
 
@@ -46,9 +60,9 @@ class BinarySensor(Feature):
46
60
 
47
61
 
48
62
  class Rain(BinarySensor):
49
- def __init__(self, product: "Box", alias: str, methods: dict):
63
+ def __init__(self, product: "Box", alias: str, methods: dict, sensor_id: Optional[int] = None, name: Optional[str] = None):
50
64
  self._device_class = "moisture"
51
- super().__init__(product, alias, methods)
65
+ super().__init__(product, alias, methods, sensor_id=sensor_id, name=name)
52
66
 
53
67
  @property
54
68
  def state(self) -> bool:
@@ -71,9 +85,9 @@ class Rain(BinarySensor):
71
85
 
72
86
 
73
87
  class Flood(BinarySensor):
74
- def __init__(self, product: "Box", alias: str, methods: dict):
88
+ def __init__(self, product: "Box", alias: str, methods: dict, sensor_id: Optional[int] = None, name: Optional[str] = None):
75
89
  self._device_class = "moisture"
76
- super().__init__(product, alias, methods)
90
+ super().__init__(product, alias, methods, sensor_id=sensor_id, name=name)
77
91
 
78
92
  @property
79
93
  def state(self) -> bool:
@@ -94,3 +108,47 @@ class Flood(BinarySensor):
94
108
 
95
109
  def after_update(self) -> None:
96
110
  self._current = self._read_flood("flood")
111
+
112
+
113
+ class Open(BinarySensor):
114
+ def __init__(self, product: "Box", alias: str, methods: dict):
115
+ self._device_class = "open"
116
+ super().__init__(product, alias, methods)
117
+
118
+ @property
119
+ def state(self) -> bool:
120
+ return self._current != 4 # 4 = closed, 0-3 = open
121
+
122
+ def _read_input(self, field: str) -> Union[float, int, None]:
123
+ product = self._product
124
+
125
+ if product.last_data is not None:
126
+ raw = self.raw_value(field)
127
+ if raw is not None: # no reading
128
+ return self.raw_value("openStatus")
129
+ return 0
130
+
131
+ def after_update(self) -> None:
132
+ self._current = self._read_input("openStatus")
133
+
134
+
135
+ class Input(BinarySensor):
136
+ def __init__(self, product: "Box", alias: str, methods: dict):
137
+ self._device_class = "input"
138
+ super().__init__(product, alias, methods)
139
+
140
+ @property
141
+ def state(self) -> bool:
142
+ return self._current > 0
143
+
144
+ def _read_input(self, field: str) -> Union[float, int, None]:
145
+ product = self._product
146
+
147
+ if product.last_data is not None:
148
+ raw = self.raw_value(field)
149
+ if raw is not None: # no reading
150
+ return self.raw_value("binary")
151
+ return 0
152
+
153
+ def after_update(self) -> None:
154
+ self._current = self._read_input("binary")
@@ -720,6 +720,7 @@ BOX_TYPE_CONF: dict[str, dict[int, dict[str, Any]]] = {
720
720
  "temperature": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'temperature']|[0]|value",
721
721
  "wind": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'wind']|[0]|value",
722
722
  "humidity": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'humidity']|[0]|value",
723
+ "openStatus": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'openStatus']|[0]|value",
723
724
  },
724
725
  ]
725
726
  ],
@@ -729,6 +730,8 @@ BOX_TYPE_CONF: dict[str, dict[int, dict[str, Any]]] = {
729
730
  {
730
731
  "rain": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'rain']|[0]|value",
731
732
  "flood": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'flood']|[0]|value",
733
+ "openStatus": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'openStatus']|[0]|value",
734
+ "binary": lambda x: f"multiSensor.sensors[?id == `{x}`]|[?type == 'binary']|[0]|value",
732
735
  },
733
736
  ]
734
737
  ],
@@ -118,6 +118,11 @@ class Gate:
118
118
  def min_position(self) -> int:
119
119
  return 0
120
120
 
121
+ @property
122
+ def is_position_inverted(self) -> bool:
123
+ # shutterBox/gateController: % closed (0=open, 100=closed), inverted vs HA convention
124
+ return True
125
+
121
126
  @property
122
127
  def is_slider(self) -> bool:
123
128
  return True
@@ -176,6 +181,11 @@ class Shutter(Gate):
176
181
  class GateBox(Gate):
177
182
  _control_type: Optional[GateBoxControlType]
178
183
 
184
+ @property
185
+ def is_position_inverted(self) -> bool:
186
+ # gateBox: (0=closed, 100=open), matches HA convention
187
+ return False
188
+
179
189
  @property
180
190
  def is_slider(self) -> bool:
181
191
  return False
@@ -189,8 +199,6 @@ class GateBox(Gate):
189
199
  return "primary"
190
200
 
191
201
  def read_state(self, alias: str, raw_value: Any, product: "Box") -> int:
192
- # Reinterpret state to match shutterBox
193
- # NOTE: shutterBox is inverted (0 == closed), gateBox isn't
194
202
  current = raw_value("position")
195
203
  desired = raw_value("desired")
196
204
 
@@ -329,6 +337,10 @@ class Cover(Feature):
329
337
  def has_tilt(self) -> bool:
330
338
  return self._attributes.has_tilt
331
339
 
340
+ @property
341
+ def is_position_inverted(self) -> bool:
342
+ return self._attributes.is_position_inverted
343
+
332
344
  @property
333
345
  def has_stop(self) -> bool:
334
346
  return self._has_stop
@@ -112,8 +112,10 @@ class Light(Feature):
112
112
  color_mode,
113
113
  effect_list,
114
114
  current_effect,
115
+ index: Optional[int] = None,
115
116
  ) -> None:
116
117
  super().__init__(product, alias, methods)
118
+ self._index = index
117
119
  config = self.CONFIG[product.type]
118
120
  self.mask = mask
119
121
  self.desired_color = desired_color
@@ -187,6 +189,7 @@ class Light(Feature):
187
189
  product,
188
190
  alias=alias + "_" + indicator,
189
191
  mask=mask,
192
+ index=i,
190
193
  **const_kwargs,
191
194
  )
192
195
  )
@@ -208,12 +211,13 @@ class Light(Feature):
208
211
  ct = ctx2
209
212
  if len(desired_color) > 8:
210
213
  ct = ctx2_v3
211
- for indicator, mask in ct.items():
214
+ for i, (indicator, mask) in enumerate(ct.items()):
212
215
  object_list.append(
213
216
  cls(
214
217
  product,
215
218
  alias=alias + "_" + indicator,
216
219
  mask=mask,
220
+ index=i,
217
221
  **const_kwargs,
218
222
  )
219
223
  )
@@ -247,6 +251,10 @@ class Light(Feature):
247
251
  else:
248
252
  return None
249
253
 
254
+ @property
255
+ def index(self) -> Optional[int]:
256
+ return self._index
257
+
250
258
  @property
251
259
  def effect_list(self):
252
260
  if isinstance(self._effect_list, dict):
@@ -506,7 +514,7 @@ class Light(Feature):
506
514
  if self.color_mode in (BleboxColorMode.RGBW, BleboxColorMode.RGBorW):
507
515
  return 255, 255, 255, 255
508
516
  if self.color_mode == BleboxColorMode.MONO:
509
- return 255
517
+ return [255]
510
518
  if self.color_mode in (BleboxColorMode.CT, BleboxColorMode.CTx2):
511
519
  return 255, 255
512
520
  else:
@@ -77,6 +77,7 @@ class SensorFactory:
77
77
  alias=alias,
78
78
  methods=materialized_methods,
79
79
  sensor_id=sensor_id,
80
+ name=sensor.get("name"),
80
81
  )
81
82
  object_list.append(feature)
82
83
 
@@ -110,9 +111,11 @@ class BaseSensor(Feature):
110
111
  methods: dict,
111
112
  sensor_type: str = None,
112
113
  sensor_id: Optional[int] = None,
114
+ name: Optional[str] = None,
113
115
  ):
114
116
  self._sensor_type = sensor_type
115
117
  self._sensor_id = sensor_id
118
+ self._name = name
116
119
  super().__init__(product, alias, methods)
117
120
 
118
121
  @property
@@ -135,6 +138,14 @@ class BaseSensor(Feature):
135
138
  def probe_id(self):
136
139
  return self.sensor_id
137
140
 
141
+ @property
142
+ def index(self) -> Optional[int]:
143
+ return self._sensor_id
144
+
145
+ @property
146
+ def name(self) -> Optional[str]:
147
+ return self._name
148
+
138
149
  @classmethod
139
150
  def many_from_config(cls, product, box_type_config, extended_state):
140
151
  raise NotImplementedError("Please use SensorFactory")
@@ -154,6 +165,7 @@ class BaseSensor(Feature):
154
165
  @SensorFactory.register("illuminance", unit="lx", scale=100)
155
166
  @SensorFactory.register("humidity", unit="percentage", scale=100)
156
167
  @SensorFactory.register("wind", unit="m/s", scale=10)
168
+ @SensorFactory.register("openStatus", unit="")
157
169
  class GenericSensor(BaseSensor):
158
170
  def __init__(
159
171
  # base sensor params
@@ -162,6 +174,7 @@ class GenericSensor(BaseSensor):
162
174
  alias: str,
163
175
  methods: dict,
164
176
  sensor_id: Optional[int],
177
+ name: Optional[str] = None,
165
178
  *,
166
179
  # generalization params
167
180
  sensor_type: str,
@@ -169,7 +182,7 @@ class GenericSensor(BaseSensor):
169
182
  scale: float = 1,
170
183
  precision: Optional[int] = None,
171
184
  ):
172
- super().__init__(product, alias, methods, sensor_id=sensor_id)
185
+ super().__init__(product, alias, methods, sensor_id=sensor_id, name=name)
173
186
  self._unit = unit
174
187
  self._scale = scale
175
188
  self._precision = precision
@@ -225,8 +238,9 @@ class Temperature(BaseSensor):
225
238
  alias: str,
226
239
  methods: dict,
227
240
  sensor_id: Optional[int] = None,
241
+ name: Optional[str] = None,
228
242
  ):
229
- super().__init__(product, alias, methods, sensor_id=sensor_id)
243
+ super().__init__(product, alias, methods, sensor_id=sensor_id, name=name)
230
244
  self._unit = "celsius"
231
245
  self._device_class = "temperature"
232
246
 
@@ -258,8 +272,9 @@ class AirQuality(BaseSensor):
258
272
  alias: str,
259
273
  methods: dict,
260
274
  sensor_id: Optional[str] = None,
275
+ name: Optional[str] = None,
261
276
  ):
262
- super().__init__(product, alias, methods, sensor_id)
277
+ super().__init__(product, alias, methods, sensor_id, name=name)
263
278
  self._unit = "concentration_of_mp"
264
279
  self._device_class = alias
265
280
 
@@ -15,11 +15,13 @@ class Switch(Feature):
15
15
  methods: dict,
16
16
  dev_class: str,
17
17
  unit_id: Union[str, int, None] = 0,
18
+ name: Optional[str] = None,
18
19
  ):
19
20
  methods = self.resolve_access_method_paths(methods, str(unit_id))
20
21
  super().__init__(product, alias, methods)
21
22
  self._device_class = dev_class
22
23
  self._unit_id = unit_id
24
+ self._name = name
23
25
 
24
26
  @classmethod
25
27
  def many_from_config(
@@ -46,6 +48,7 @@ class Switch(Feature):
46
48
  methods,
47
49
  relay_type,
48
50
  relay_id,
51
+ name=relay.get("name"),
49
52
  )
50
53
  )
51
54
 
@@ -74,6 +77,14 @@ class Switch(Feature):
74
77
  unit = self._unit_id
75
78
  return [] if unit is None else [unit]
76
79
 
80
+ @property
81
+ def index(self) -> Optional[int]:
82
+ return self._unit_id
83
+
84
+ @property
85
+ def name(self) -> Optional[str]:
86
+ return self._name
87
+
77
88
  async def async_turn_on(self, **kwargs: Any) -> None:
78
89
  await self.async_api_command("on", *self._unit_args)
79
90
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: blebox-uniapi
3
- Version: 2.5.1
3
+ Version: 2.5.3
4
4
  Summary: Python API for accessing BleBox smart home devices
5
5
  Home-page: https://github.com/blebox/blebox_uniapi
6
6
  Author: BleBox
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 2.5.1
2
+ current_version = 2.5.3
3
3
  commit = True
4
4
  tag = True
5
5
 
@@ -23,7 +23,7 @@ test_requirements = [
23
23
  ]
24
24
 
25
25
  setup(
26
- version="2.5.1",
26
+ version="2.5.3",
27
27
  author="BleBox",
28
28
  author_email="opensource@blebox.eu",
29
29
  python_requires=">=3.9",
File without changes
File without changes
File without changes
File without changes