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.
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/PKG-INFO +1 -1
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/__init__.py +1 -1
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/binary_sensor.py +64 -6
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/box_types.py +3 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/cover.py +14 -2
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/light.py +10 -2
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/sensor.py +18 -3
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/switch.py +11 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/PKG-INFO +1 -1
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/setup.cfg +1 -1
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/setup.py +1 -1
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/CONTRIBUTING.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/HISTORY.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/LICENSE +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/MANIFEST.in +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/README.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/box.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/button.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/climate.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/error.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/feature.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/jfollow.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi/session.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/SOURCES.txt +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/dependency_links.txt +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/not-zip-safe +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/requires.txt +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/blebox_uniapi.egg-info/top_level.txt +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/Makefile +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/authors.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/conf.py +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/contributing.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/history.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/index.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/installation.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/make.bat +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/readme.rst +0 -0
- {blebox_uniapi-2.5.1 → blebox_uniapi-2.5.3}/docs/usage.rst +0 -0
|
@@ -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
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|