twist-innovation-api 0.0.4__py3-none-any.whl → 0.0.5__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.
- twist/BackendAdapter.py +28 -56
- twist/TwistAPI.py +1 -9
- twist/{TwistLouvre.py → TwistShutter.py} +8 -8
- {twist_innovation_api-0.0.4.dist-info → twist_innovation_api-0.0.5.dist-info}/METADATA +1 -1
- {twist_innovation_api-0.0.4.dist-info → twist_innovation_api-0.0.5.dist-info}/RECORD +8 -9
- twist/TwistCbShutter.py +0 -33
- {twist_innovation_api-0.0.4.dist-info → twist_innovation_api-0.0.5.dist-info}/LICENSE +0 -0
- {twist_innovation_api-0.0.4.dist-info → twist_innovation_api-0.0.5.dist-info}/WHEEL +0 -0
- {twist_innovation_api-0.0.4.dist-info → twist_innovation_api-0.0.5.dist-info}/top_level.txt +0 -0
twist/BackendAdapter.py
CHANGED
|
@@ -24,41 +24,23 @@ import aiohttp
|
|
|
24
24
|
from typing import Optional, Type, Dict
|
|
25
25
|
from .TwistModel import TwistModel
|
|
26
26
|
from .TwistLight import TwistLight
|
|
27
|
-
from .
|
|
27
|
+
from .TwistShutter import TwistShutter
|
|
28
28
|
from .TwistRgb import TwistRgb
|
|
29
29
|
from .TwistSensor import TwistSensor
|
|
30
|
-
from .TwistCbShutter import TwistCbShutter
|
|
31
30
|
from .TwistGarage import TwistGarage
|
|
32
31
|
from .TwistRelay import TwistRelay
|
|
33
32
|
from .TwistButton import TwistButton
|
|
34
33
|
from .TwistBinarySensor import TwistBinarySensor
|
|
35
34
|
|
|
36
35
|
|
|
37
|
-
# Type mapping: maps backend type strings to Twist model classes
|
|
38
|
-
# Add new mappings here when new device types are added
|
|
39
|
-
TYPE_TO_MODEL_MAP: Dict[str, Type[TwistModel]] = {
|
|
40
|
-
"Mono_Light": TwistLight,
|
|
41
|
-
"TB_Shutter": TwistLouvre,
|
|
42
|
-
"Louvre": TwistLouvre,
|
|
43
|
-
"RGB": TwistRgb,
|
|
44
|
-
"Sensor": TwistSensor,
|
|
45
|
-
"CB_Shutter": TwistCbShutter,
|
|
46
|
-
"PB_Shutter": TwistCbShutter,
|
|
47
|
-
"Garage": TwistGarage,
|
|
48
|
-
"Relay": TwistRelay,
|
|
49
|
-
"Button": TwistButton,
|
|
50
|
-
"Binary_Sensor": TwistBinarySensor,
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
36
|
class DeviceInfo:
|
|
55
37
|
"""Container for device information from backend"""
|
|
56
|
-
def __init__(self, device_id: int, model_id: int, name: str,
|
|
38
|
+
def __init__(self, device_id: int, model_id: int, name: str, model_class: Type[TwistModel],
|
|
57
39
|
device_key: str, device_allocation_model_key: Optional[str] = None):
|
|
58
40
|
self.device_id = device_id
|
|
59
41
|
self.model_id = model_id
|
|
60
42
|
self.name = name
|
|
61
|
-
self.
|
|
43
|
+
self.model_class = model_class
|
|
62
44
|
self.device_key = device_key
|
|
63
45
|
self.device_allocation_model_key = device_allocation_model_key
|
|
64
46
|
|
|
@@ -230,15 +212,15 @@ class BackendAdapter:
|
|
|
230
212
|
label = model.get("label", f"Model {model_index}")
|
|
231
213
|
device_allocation_model_key = model.get("deviceAllocationModelKey")
|
|
232
214
|
|
|
233
|
-
# Map model type name to
|
|
234
|
-
|
|
215
|
+
# Map model type name directly to model class
|
|
216
|
+
model_class = self._map_model_type_to_class(model_type_name)
|
|
235
217
|
|
|
236
|
-
if
|
|
218
|
+
if model_class:
|
|
237
219
|
device_info = DeviceInfo(
|
|
238
220
|
device_id=twist_id,
|
|
239
221
|
model_id=model_index,
|
|
240
222
|
name=label,
|
|
241
|
-
|
|
223
|
+
model_class=model_class,
|
|
242
224
|
device_key=device_key,
|
|
243
225
|
device_allocation_model_key=device_allocation_model_key
|
|
244
226
|
)
|
|
@@ -252,44 +234,34 @@ class BackendAdapter:
|
|
|
252
234
|
|
|
253
235
|
return device_list
|
|
254
236
|
|
|
255
|
-
def
|
|
237
|
+
def _map_model_type_to_class(self, model_type_name: str) -> Optional[Type[TwistModel]]:
|
|
256
238
|
"""
|
|
257
|
-
Map the
|
|
239
|
+
Map the API's modelTypeName directly to Twist model class
|
|
258
240
|
|
|
259
241
|
Args:
|
|
260
|
-
model_type_name: Model type name from the
|
|
242
|
+
model_type_name: Model type name from the API
|
|
261
243
|
|
|
262
244
|
Returns:
|
|
263
|
-
|
|
245
|
+
TwistModel subclass or None if unmapped
|
|
264
246
|
"""
|
|
265
|
-
# Mapping from new API model type names to internal device type strings
|
|
266
247
|
mapping = {
|
|
267
|
-
"Louvres":
|
|
268
|
-
"Mono Light":
|
|
269
|
-
"RGB":
|
|
270
|
-
"Temperature":
|
|
271
|
-
"CB Shutter":
|
|
272
|
-
"PB Shutter":
|
|
273
|
-
"
|
|
274
|
-
"
|
|
275
|
-
"
|
|
276
|
-
"
|
|
248
|
+
"Louvres": TwistShutter,
|
|
249
|
+
"Mono Light": TwistLight,
|
|
250
|
+
"RGB": TwistRgb,
|
|
251
|
+
"Temperature": TwistSensor,
|
|
252
|
+
"CB Shutter": TwistShutter,
|
|
253
|
+
"PB Shutter": TwistShutter,
|
|
254
|
+
"Shutter": TwistShutter,
|
|
255
|
+
"Garage": TwistGarage,
|
|
256
|
+
"Relay": TwistRelay,
|
|
257
|
+
"Button": TwistButton,
|
|
258
|
+
"Binary Sensor": TwistBinarySensor,
|
|
259
|
+
"Gateway": None, # Skip Gateway models
|
|
260
|
+
"Weather": None, # Skip Weather models
|
|
261
|
+
"Wind": None, # Skip Wind models
|
|
262
|
+
"Rain Sensor": None, # Skip Rain Sensor models
|
|
263
|
+
"Pergola Protection": None, # Skip logic models
|
|
264
|
+
"Unknown": None, # Skip unknown models
|
|
277
265
|
}
|
|
278
266
|
|
|
279
267
|
return mapping.get(model_type_name)
|
|
280
|
-
|
|
281
|
-
@staticmethod
|
|
282
|
-
def get_model_class(device_type: str) -> Type[TwistModel]:
|
|
283
|
-
"""
|
|
284
|
-
Get the appropriate model class for a device type.
|
|
285
|
-
|
|
286
|
-
This method maps backend device types to Twist model classes.
|
|
287
|
-
If a type is not recognized, it returns the base TwistModel class.
|
|
288
|
-
|
|
289
|
-
Args:
|
|
290
|
-
device_type: Device type string from backend
|
|
291
|
-
|
|
292
|
-
Returns:
|
|
293
|
-
Appropriate TwistModel subclass
|
|
294
|
-
"""
|
|
295
|
-
return TYPE_TO_MODEL_MAP.get(device_type, TwistModel)
|
twist/TwistAPI.py
CHANGED
|
@@ -97,13 +97,7 @@ class TwistAPI:
|
|
|
97
97
|
|
|
98
98
|
# Create models for this device
|
|
99
99
|
for info in infos:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if model_class == TwistModel:
|
|
103
|
-
print(f"Skipping unknown device type '{info.device_type}' for '{info.name}' (device {info.device_id}, model {info.model_id})")
|
|
104
|
-
continue
|
|
105
|
-
|
|
106
|
-
model = model_class(info.model_id, device)
|
|
100
|
+
model = info.model_class(info.model_id, device)
|
|
107
101
|
|
|
108
102
|
# Get product info if available using deviceAllocationModelKey
|
|
109
103
|
product_info = None
|
|
@@ -117,8 +111,6 @@ class TwistAPI:
|
|
|
117
111
|
model.product_name = None
|
|
118
112
|
model.name = info.name
|
|
119
113
|
|
|
120
|
-
model.device_type = info.device_type
|
|
121
|
-
|
|
122
114
|
# Add model at correct position in model_list
|
|
123
115
|
while len(device.model_list) <= info.model_id:
|
|
124
116
|
device.model_list.append(None)
|
|
@@ -22,7 +22,7 @@ from .TwistDevice import TwistModel
|
|
|
22
22
|
from enum import Enum
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class TwistShutter(TwistModel):
|
|
26
26
|
class EventIndexes(Enum):
|
|
27
27
|
OPEN = 0
|
|
28
28
|
STOP = 1
|
|
@@ -55,24 +55,24 @@ class TwistLouvre(TwistModel):
|
|
|
55
55
|
await self._update_callback(self)
|
|
56
56
|
|
|
57
57
|
async def open(self):
|
|
58
|
-
await self._activate_event(
|
|
58
|
+
await self._activate_event(TwistShutter.EventIndexes.OPEN)
|
|
59
59
|
|
|
60
60
|
async def stop(self):
|
|
61
|
-
await self._activate_event(
|
|
61
|
+
await self._activate_event(TwistShutter.EventIndexes.STOP)
|
|
62
62
|
|
|
63
63
|
async def close(self):
|
|
64
|
-
await self._activate_event(
|
|
64
|
+
await self._activate_event(TwistShutter.EventIndexes.CLOSE)
|
|
65
65
|
|
|
66
66
|
async def toggle(self):
|
|
67
|
-
await self._activate_event(
|
|
67
|
+
await self._activate_event(TwistShutter.EventIndexes.TOGGLE)
|
|
68
68
|
|
|
69
69
|
async def set_value(self, value: int, fading_time: int | None = None):
|
|
70
70
|
if fading_time is not None:
|
|
71
71
|
raise NotImplementedError("Fading time can't be used in this model")
|
|
72
72
|
else:
|
|
73
|
-
await self._activate_event(
|
|
73
|
+
await self._activate_event(TwistShutter.EventIndexes.VALUE, int(value * 655.35))
|
|
74
74
|
|
|
75
|
-
async def _activate_event(self, index:
|
|
75
|
+
async def _activate_event(self, index: TwistShutter.EventIndexes, value: int | None = None,
|
|
76
76
|
fading_time: int | None = None):
|
|
77
77
|
data = {
|
|
78
78
|
"i": index.value
|
|
@@ -89,5 +89,5 @@ class TwistLouvre(TwistModel):
|
|
|
89
89
|
|
|
90
90
|
def print_context(self):
|
|
91
91
|
print(
|
|
92
|
-
f"
|
|
92
|
+
f"Shutter Device: {self.parent_device.twist_id}, Model: {self.model_id}, Actual: {self.actual_state}, "
|
|
93
93
|
f"Requested: {self.requested_state}, Operating: {self.operating_time}, Current: {self.current}")
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
twist/BackendAdapter.py,sha256=
|
|
2
|
-
twist/TwistAPI.py,sha256=
|
|
1
|
+
twist/BackendAdapter.py,sha256=v-kjbuuHyktIjWX6MG_I3sH3ZQBawJhSiwBzzatZ3C0,9758
|
|
2
|
+
twist/TwistAPI.py,sha256=wjLl9tFs9krEaw8elTdXQJMqeuWAMXNS0nwJScXNMnY,6125
|
|
3
3
|
twist/TwistBinarySensor.py,sha256=k9gsF1dTR3E_kiB60R1SUuUc9oUGGRGs592fQqy2VPM,1747
|
|
4
4
|
twist/TwistButton.py,sha256=p5svcsU6maGwyWa06NnlKCGUXHoFzuwFPEQI0UqoGB4,2172
|
|
5
|
-
twist/TwistCbShutter.py,sha256=mWQa4ro30uI8qm0J1rkR8M0KP7IwxlCRfWt0wSyCOLA,1199
|
|
6
5
|
twist/TwistDevice.py,sha256=-ttj9LrZhR3BwLK4ADSe2TrTtY5Z3GMkz3BruUP_jCU,1159
|
|
7
6
|
twist/TwistGarage.py,sha256=RaE0Pi-1dE9FwHEIANf--Uig9tFt6EAZBt_lxjZgk18,2149
|
|
8
7
|
twist/TwistLight.py,sha256=6f-gPfP6v7BgaRJUFt7Q3r990y2L0812d76K_33KSTw,3230
|
|
9
|
-
twist/TwistLouvre.py,sha256=f2ocRjLkf3qC45hbcHdEOboA2mbkaxLaOa15tvkHOHY,3320
|
|
10
8
|
twist/TwistModel.py,sha256=HKDDm-vaRiNEF-a67N-cjWw2UZDiSPSRMkEmlAIUPTg,3667
|
|
11
9
|
twist/TwistRelay.py,sha256=VL9eKXSOoZ_9GHT8TGZKDU1hGH-cgoogoMmJWLfjOqc,2309
|
|
12
10
|
twist/TwistRgb.py,sha256=V7YuaqJaLTH3cL8CsQ3xIztfVKfqdMMJ7uyh9UZQDwA,3572
|
|
13
11
|
twist/TwistSensor.py,sha256=6eYrwtZFFFOHmoHS68JHmsyi6FVVzoQy19KooGU0vMI,1192
|
|
12
|
+
twist/TwistShutter.py,sha256=gXMbgV_Y-3GLzxE0K6XRP6qqDHEw0uySjZc82IOMsYY,3328
|
|
14
13
|
twist/TwistTypes.py,sha256=k1CdLqjhJi8MyrFZsHkDsEoL9gEXF-HQv6I-r3G7ngA,726
|
|
15
14
|
twist/__init__.py,sha256=gf8GHc9utiG0vD8GP3IfzLFHAG-ev1TXBIm0XUHxy38,201
|
|
16
|
-
twist_innovation_api-0.0.
|
|
17
|
-
twist_innovation_api-0.0.
|
|
18
|
-
twist_innovation_api-0.0.
|
|
19
|
-
twist_innovation_api-0.0.
|
|
20
|
-
twist_innovation_api-0.0.
|
|
15
|
+
twist_innovation_api-0.0.5.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
16
|
+
twist_innovation_api-0.0.5.dist-info/METADATA,sha256=qd3IkTYqKU2qVxeqaSltdVRQCKMJd_gdCu5zXXvzk5o,4139
|
|
17
|
+
twist_innovation_api-0.0.5.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
18
|
+
twist_innovation_api-0.0.5.dist-info/top_level.txt,sha256=mkoeBkRPFodjnd-3UDf9YndjTQ6Sriz-EKSI4nQ7brs,6
|
|
19
|
+
twist_innovation_api-0.0.5.dist-info/RECORD,,
|
twist/TwistCbShutter.py
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Copyright (C) 2025 Twist Innovation
|
|
2
|
-
# This program is free software: you can redistribute it and/or modify
|
|
3
|
-
# it under the terms of the GNU General Public License as published by
|
|
4
|
-
# the Free Software Foundation, either version 3 of the License, or
|
|
5
|
-
# (at your option) any later version.
|
|
6
|
-
#
|
|
7
|
-
# This program is distributed in the hope that it will be useful,
|
|
8
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
10
|
-
#
|
|
11
|
-
# See the GNU General Public License for more details:
|
|
12
|
-
# https://www.gnu.org/licenses/gpl-3.0.html
|
|
13
|
-
|
|
14
|
-
from __future__ import annotations
|
|
15
|
-
from typing import TYPE_CHECKING
|
|
16
|
-
|
|
17
|
-
if TYPE_CHECKING:
|
|
18
|
-
from TwistDevice import TwistDevice
|
|
19
|
-
from .TwistDevice import TwistModel
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class TwistCbShutter(TwistModel):
|
|
23
|
-
def __init__(self, model_id: int, parent_device: TwistDevice):
|
|
24
|
-
super().__init__(model_id, parent_device)
|
|
25
|
-
|
|
26
|
-
async def context_msg(self, payload: str):
|
|
27
|
-
self.parse_general_context(payload)
|
|
28
|
-
|
|
29
|
-
if self._update_callback is not None:
|
|
30
|
-
await self._update_callback(self)
|
|
31
|
-
|
|
32
|
-
def print_context(self):
|
|
33
|
-
print(f"Cb Shutter Device: {self.parent_device.twist_id}, Model: {self.model_id},")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|