python-dali 0.9__py3-none-any.whl → 0.11__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.
- dali/address.py +198 -57
- dali/command.py +24 -3
- dali/device/__init__.py +5 -0
- dali/device/general.py +650 -118
- dali/device/helpers.py +238 -0
- dali/device/light.py +209 -0
- dali/device/occupancy.py +322 -0
- dali/device/pushbutton.py +325 -0
- dali/device/sequences.py +277 -0
- dali/driver/atxled.py +154 -0
- dali/driver/hid.py +150 -56
- dali/driver/serial.py +1668 -0
- dali/driver/trace_logging.py +64 -0
- dali/frame.py +7 -35
- dali/gear/__init__.py +1 -0
- dali/gear/colour.py +432 -0
- dali/gear/general.py +29 -23
- dali/gear/led.py +19 -2
- dali/gear/sequences.py +113 -0
- dali/memory/location.py +139 -38
- dali/tests/fakes.py +392 -56
- dali/tests/fakes_serial.py +369 -0
- dali/tests/test_colour.py +69 -0
- dali/tests/test_command.py +12 -1
- dali/tests/test_device_sequences.py +365 -0
- dali/tests/test_dummy.py +194 -0
- dali/tests/test_events.py +359 -0
- dali/tests/test_fakes.py +266 -0
- dali/tests/test_frame.py +0 -42
- dali/tests/test_memory.py +36 -9
- dali/version.py +1 -1
- {python_dali-0.9.dist-info → python_dali-0.11.dist-info}/METADATA +39 -4
- python_dali-0.11.dist-info/RECORD +58 -0
- {python_dali-0.9.dist-info → python_dali-0.11.dist-info}/WHEEL +1 -1
- python_dali-0.9.dist-info/RECORD +0 -42
- {python_dali-0.9.dist-info → python_dali-0.11.dist-info}/COPYING +0 -0
- {python_dali-0.9.dist-info → python_dali-0.11.dist-info}/COPYING.LESSER +0 -0
- {python_dali-0.9.dist-info → python_dali-0.11.dist-info}/LICENSE +0 -0
- {python_dali-0.9.dist-info → python_dali-0.11.dist-info}/top_level.txt +0 -0
dali/address.py
CHANGED
|
@@ -30,11 +30,12 @@ _bad_frame_length = IncompatibleFrame("Unsupported frame size")
|
|
|
30
30
|
# Address bytes
|
|
31
31
|
###############################################################################
|
|
32
32
|
|
|
33
|
+
|
|
33
34
|
class AddressTracker(type):
|
|
34
35
|
"""Metaclass keeping track of all the types of Address we understand."""
|
|
35
36
|
|
|
36
37
|
def __init__(cls, name, bases, attrs):
|
|
37
|
-
if not hasattr(cls,
|
|
38
|
+
if not hasattr(cls, "_addrtypes"):
|
|
38
39
|
cls._addrtypes = []
|
|
39
40
|
else:
|
|
40
41
|
cls._addrtypes.append(cls)
|
|
@@ -43,6 +44,8 @@ class AddressTracker(type):
|
|
|
43
44
|
class Address(metaclass=AddressTracker):
|
|
44
45
|
"""An address for one or more ballasts."""
|
|
45
46
|
|
|
47
|
+
required_frame_size = None
|
|
48
|
+
|
|
46
49
|
@classmethod
|
|
47
50
|
def from_frame(cls, f):
|
|
48
51
|
"""Return an Address object
|
|
@@ -64,72 +67,131 @@ class Address(metaclass=AddressTracker):
|
|
|
64
67
|
return "<no address>"
|
|
65
68
|
|
|
66
69
|
|
|
67
|
-
class
|
|
68
|
-
"""
|
|
70
|
+
class GearAddress(Address):
|
|
71
|
+
"""Base class for control gear addresses"""
|
|
72
|
+
|
|
73
|
+
required_frame_size = 16
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class DeviceAddress(Address):
|
|
77
|
+
"""Base class for control device addresses"""
|
|
78
|
+
|
|
79
|
+
required_frame_size = 24
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class GearBroadcast(GearAddress):
|
|
83
|
+
"""All control gear connected to the network"""
|
|
69
84
|
|
|
70
85
|
@classmethod
|
|
71
86
|
def from_frame(cls, f):
|
|
72
87
|
if len(f) == 16:
|
|
73
|
-
if f[15:9] ==
|
|
74
|
-
return cls()
|
|
75
|
-
elif len(f) == 24:
|
|
76
|
-
if f[16] and f[23:17] == 0x7f:
|
|
88
|
+
if f[15:9] == 0x7F:
|
|
77
89
|
return cls()
|
|
78
90
|
|
|
79
91
|
def add_to_frame(self, f):
|
|
80
92
|
if len(f) == 16:
|
|
81
|
-
f[15:9] =
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
f[15:9] = 0x7F
|
|
94
|
+
else:
|
|
95
|
+
raise _bad_frame_length
|
|
96
|
+
|
|
97
|
+
def __eq__(self, other):
|
|
98
|
+
return isinstance(other, GearBroadcast)
|
|
99
|
+
|
|
100
|
+
def __str__(self):
|
|
101
|
+
return "<broadcast (control gear)>"
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# Broadcast alias provided for legacy purposes, new code should avoid
|
|
105
|
+
# ambiguity by using either GearBroadcast or DeviceBroadcast
|
|
106
|
+
Broadcast = GearBroadcast
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class DeviceBroadcast(DeviceAddress):
|
|
110
|
+
"""All control devices connected to the network"""
|
|
111
|
+
|
|
112
|
+
@classmethod
|
|
113
|
+
def from_frame(cls, f):
|
|
114
|
+
if len(f) == 24:
|
|
115
|
+
if f[16] and f[23:17] == 0x7F:
|
|
116
|
+
return cls()
|
|
117
|
+
|
|
118
|
+
def add_to_frame(self, f):
|
|
119
|
+
if len(f) == 24:
|
|
120
|
+
f[23:17] = 0x7F
|
|
84
121
|
else:
|
|
85
122
|
raise _bad_frame_length
|
|
86
123
|
|
|
87
124
|
def __eq__(self, other):
|
|
88
|
-
return isinstance(other,
|
|
125
|
+
return isinstance(other, DeviceBroadcast)
|
|
89
126
|
|
|
90
127
|
def __str__(self):
|
|
91
|
-
return "<broadcast>"
|
|
128
|
+
return "<broadcast (control device)>"
|
|
92
129
|
|
|
93
130
|
|
|
94
|
-
class
|
|
95
|
-
"""All unaddressed control gear
|
|
131
|
+
class GearBroadcastUnaddressed(GearAddress):
|
|
132
|
+
"""All unaddressed control gear
|
|
96
133
|
|
|
97
|
-
All control gear
|
|
98
|
-
address assigned.
|
|
134
|
+
All control gear in the system that have no short address assigned.
|
|
99
135
|
"""
|
|
100
136
|
|
|
101
137
|
@classmethod
|
|
102
138
|
def from_frame(cls, f):
|
|
103
139
|
if len(f) == 16:
|
|
104
|
-
if f[15:9] ==
|
|
105
|
-
return cls()
|
|
106
|
-
elif len(f) == 24:
|
|
107
|
-
if f[16] and f[23:17] == 0x7e:
|
|
140
|
+
if f[15:9] == 0x7E:
|
|
108
141
|
return cls()
|
|
109
142
|
|
|
110
143
|
def add_to_frame(self, f):
|
|
111
144
|
if len(f) == 16:
|
|
112
|
-
f[15:9] =
|
|
113
|
-
|
|
114
|
-
|
|
145
|
+
f[15:9] = 0x7E
|
|
146
|
+
else:
|
|
147
|
+
raise _bad_frame_length
|
|
148
|
+
|
|
149
|
+
def __eq__(self, other):
|
|
150
|
+
return isinstance(other, GearBroadcastUnaddressed)
|
|
151
|
+
|
|
152
|
+
def __str__(self):
|
|
153
|
+
return "<broadcast unaddressed (control gear)>"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# BroadcastUnaddressed alias provided for legacy purposes, new code should
|
|
157
|
+
# avoid ambiguity by using either GearBroadcastUnaddressed or
|
|
158
|
+
# DeviceBroadcastUnaddressed
|
|
159
|
+
BroadcastUnaddressed = GearBroadcastUnaddressed
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class DeviceBroadcastUnaddressed(DeviceAddress):
|
|
163
|
+
"""All unaddressed control devices
|
|
164
|
+
|
|
165
|
+
All control devices in the system that have no short address assigned.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
@classmethod
|
|
169
|
+
def from_frame(cls, f):
|
|
170
|
+
if len(f) == 24:
|
|
171
|
+
if f[16] and f[23:17] == 0x7E:
|
|
172
|
+
return cls()
|
|
173
|
+
|
|
174
|
+
def add_to_frame(self, f):
|
|
175
|
+
if len(f) == 24:
|
|
176
|
+
f[23:17] = 0x7E
|
|
115
177
|
else:
|
|
116
178
|
raise _bad_frame_length
|
|
117
179
|
|
|
118
180
|
def __eq__(self, other):
|
|
119
|
-
return isinstance(other,
|
|
181
|
+
return isinstance(other, DeviceBroadcastUnaddressed)
|
|
120
182
|
|
|
121
183
|
def __str__(self):
|
|
122
|
-
return "<broadcast unaddressed>"
|
|
184
|
+
return "<broadcast unaddressed (control device)>"
|
|
123
185
|
|
|
124
186
|
|
|
125
|
-
class
|
|
126
|
-
"""All control gear
|
|
187
|
+
class GearGroup(GearAddress):
|
|
188
|
+
"""All control gear that are members of the specified group"""
|
|
127
189
|
|
|
128
|
-
def __init__(self, group):
|
|
190
|
+
def __init__(self, group: int):
|
|
129
191
|
if not isinstance(group, int):
|
|
130
192
|
raise ValueError("group must be an integer")
|
|
131
|
-
if group < 0 or group >
|
|
132
|
-
raise ValueError("group must be in the range 0..
|
|
193
|
+
if group < 0 or group > 15:
|
|
194
|
+
raise ValueError("group must be in the range 0..15")
|
|
133
195
|
self.group = group
|
|
134
196
|
|
|
135
197
|
@classmethod
|
|
@@ -137,32 +199,59 @@ class Group(Address):
|
|
|
137
199
|
if len(f) == 16:
|
|
138
200
|
if f[15:13] == 0x4:
|
|
139
201
|
return cls(f[12:9])
|
|
140
|
-
elif len(f) == 24:
|
|
141
|
-
if f[16] and f[23:22] == 0x2:
|
|
142
|
-
return cls(f[21:17])
|
|
143
202
|
|
|
144
203
|
def add_to_frame(self, f):
|
|
145
204
|
if len(f) == 16:
|
|
146
|
-
if self.group > 15:
|
|
147
|
-
raise IncompatibleFrame(
|
|
148
|
-
"Groups 16..31 are not supported in 16-bit forward frames")
|
|
149
205
|
f[15:13] = 0x4
|
|
150
206
|
f[12:9] = self.group
|
|
151
|
-
|
|
207
|
+
else:
|
|
208
|
+
raise _bad_frame_length
|
|
209
|
+
|
|
210
|
+
def __eq__(self, other):
|
|
211
|
+
return isinstance(other, GearGroup) and other.group == self.group
|
|
212
|
+
|
|
213
|
+
def __str__(self):
|
|
214
|
+
return f"<group (control gear) {self.group}>"
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# Group alias provided for legacy purposes, new code should avoid ambiguity
|
|
218
|
+
# by using either GearGroup or DeviceGroup
|
|
219
|
+
Group = GearGroup
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class DeviceGroup(DeviceAddress):
|
|
223
|
+
"""All control devices that are members of the specified group"""
|
|
224
|
+
|
|
225
|
+
def __init__(self, group: int):
|
|
226
|
+
if not isinstance(group, int):
|
|
227
|
+
raise ValueError("group must be an integer")
|
|
228
|
+
if group < 0 or group > 31:
|
|
229
|
+
raise ValueError("group must be in the range 0..31")
|
|
230
|
+
self.group = group
|
|
231
|
+
|
|
232
|
+
@classmethod
|
|
233
|
+
def from_frame(cls, f):
|
|
234
|
+
if len(f) == 24:
|
|
235
|
+
if f[16] and f[23:22] == 0x2:
|
|
236
|
+
return cls(f[21:17])
|
|
237
|
+
|
|
238
|
+
def add_to_frame(self, f):
|
|
239
|
+
if len(f) == 24:
|
|
152
240
|
f[23:22] = 0x2
|
|
153
241
|
f[21:17] = self.group
|
|
154
242
|
else:
|
|
155
243
|
raise _bad_frame_length
|
|
156
244
|
|
|
157
245
|
def __eq__(self, other):
|
|
158
|
-
return isinstance(other,
|
|
246
|
+
return isinstance(other, DeviceGroup) and other.group == self.group
|
|
159
247
|
|
|
160
248
|
def __str__(self):
|
|
161
|
-
return "<group
|
|
249
|
+
return f"<group (control device) {self.group}>"
|
|
162
250
|
|
|
163
251
|
|
|
164
|
-
class
|
|
165
|
-
"""
|
|
252
|
+
class GearShort(GearAddress):
|
|
253
|
+
"""
|
|
254
|
+
The control gear that has this address.
|
|
166
255
|
|
|
167
256
|
In a correctly configured DALI network, no more than one control
|
|
168
257
|
gear will have a particular short address, and no more than one
|
|
@@ -184,25 +273,63 @@ class Short(Address):
|
|
|
184
273
|
if len(f) == 16:
|
|
185
274
|
if not f[15]:
|
|
186
275
|
return cls(f[14:9])
|
|
187
|
-
elif len(f) == 24:
|
|
188
|
-
if f[16] and not f[23]:
|
|
189
|
-
return cls(f[22:17])
|
|
190
276
|
|
|
191
277
|
def add_to_frame(self, f):
|
|
192
278
|
if len(f) == 16:
|
|
193
279
|
f[15] = False
|
|
194
280
|
f[14:9] = self.address
|
|
195
|
-
|
|
281
|
+
else:
|
|
282
|
+
raise _bad_frame_length
|
|
283
|
+
|
|
284
|
+
def __eq__(self, other):
|
|
285
|
+
return isinstance(other, GearShort) and other.address == self.address
|
|
286
|
+
|
|
287
|
+
def __str__(self):
|
|
288
|
+
return f"<address (control gear) {self.address}>"
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
# Short alias provided for legacy purposes, new code should avoid ambiguity
|
|
292
|
+
# by using either GearShort or DeviceShort
|
|
293
|
+
Short = GearShort
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class DeviceShort(DeviceAddress):
|
|
297
|
+
"""
|
|
298
|
+
The control device that has this address.
|
|
299
|
+
|
|
300
|
+
In a correctly configured DALI network, no more than one control
|
|
301
|
+
gear will have a particular short address, and no more than one
|
|
302
|
+
control device will have a particular short address. The short
|
|
303
|
+
address spaces for control gear and control devices are separate;
|
|
304
|
+
it is legal for a control gear and control device to share a short
|
|
305
|
+
address.
|
|
306
|
+
"""
|
|
307
|
+
|
|
308
|
+
def __init__(self, address: int):
|
|
309
|
+
if not isinstance(address, int):
|
|
310
|
+
raise ValueError("address must be an integer")
|
|
311
|
+
if address < 0 or address > 63:
|
|
312
|
+
raise ValueError("address must be in the range 0..63")
|
|
313
|
+
self.address = address
|
|
314
|
+
|
|
315
|
+
@classmethod
|
|
316
|
+
def from_frame(cls, f):
|
|
317
|
+
if len(f) == 24:
|
|
318
|
+
if f[16] and not f[23]:
|
|
319
|
+
return cls(f[22:17])
|
|
320
|
+
|
|
321
|
+
def add_to_frame(self, f):
|
|
322
|
+
if len(f) == 24:
|
|
196
323
|
f[23] = False
|
|
197
324
|
f[22:17] = self.address
|
|
198
325
|
else:
|
|
199
326
|
raise _bad_frame_length
|
|
200
327
|
|
|
201
328
|
def __eq__(self, other):
|
|
202
|
-
return isinstance(other,
|
|
329
|
+
return isinstance(other, DeviceShort) and other.address == self.address
|
|
203
330
|
|
|
204
331
|
def __str__(self):
|
|
205
|
-
return "<address
|
|
332
|
+
return f"<address (control device) {self.address}>"
|
|
206
333
|
|
|
207
334
|
|
|
208
335
|
from_frame = Address.from_frame
|
|
@@ -212,13 +339,27 @@ from_frame = Address.from_frame
|
|
|
212
339
|
# Instance bytes
|
|
213
340
|
###############################################################################
|
|
214
341
|
|
|
342
|
+
|
|
215
343
|
class Instance:
|
|
216
344
|
def __init__(self):
|
|
217
345
|
raise NotImplementedError
|
|
218
346
|
|
|
347
|
+
@property
|
|
348
|
+
def value(self):
|
|
349
|
+
if hasattr(self, "_value"):
|
|
350
|
+
return self._value
|
|
351
|
+
|
|
219
352
|
def add_to_frame(self, f):
|
|
220
353
|
raise NotImplementedError
|
|
221
354
|
|
|
355
|
+
def __eq__(self, other):
|
|
356
|
+
if isinstance(other, self.__class__):
|
|
357
|
+
if hasattr(self, "_value") and hasattr(other, "_value"):
|
|
358
|
+
if self._value == other._value:
|
|
359
|
+
return True
|
|
360
|
+
|
|
361
|
+
return False
|
|
362
|
+
|
|
222
363
|
|
|
223
364
|
class ReservedInstance(Instance):
|
|
224
365
|
"""A reserved instance byte."""
|
|
@@ -278,7 +419,7 @@ class InstanceGroup(_AddressedInstance):
|
|
|
278
419
|
|
|
279
420
|
|
|
280
421
|
class InstanceType(_AddressedInstance):
|
|
281
|
-
_flags =
|
|
422
|
+
_flags = 0xC0
|
|
282
423
|
|
|
283
424
|
|
|
284
425
|
class FeatureInstanceNumber(_AddressedInstance):
|
|
@@ -286,7 +427,7 @@ class FeatureInstanceNumber(_AddressedInstance):
|
|
|
286
427
|
|
|
287
428
|
|
|
288
429
|
class FeatureInstanceGroup(_AddressedInstance):
|
|
289
|
-
_flags =
|
|
430
|
+
_flags = 0xA0
|
|
290
431
|
|
|
291
432
|
|
|
292
433
|
class FeatureInstanceType(_AddressedInstance):
|
|
@@ -294,19 +435,19 @@ class FeatureInstanceType(_AddressedInstance):
|
|
|
294
435
|
|
|
295
436
|
|
|
296
437
|
class FeatureInstanceBroadcast(_UnaddressedInstance):
|
|
297
|
-
_val =
|
|
438
|
+
_val = 0xFD
|
|
298
439
|
|
|
299
440
|
|
|
300
441
|
class InstanceBroadcast(_UnaddressedInstance):
|
|
301
|
-
_val =
|
|
442
|
+
_val = 0xFF
|
|
302
443
|
|
|
303
444
|
|
|
304
445
|
class FeatureDevice(_UnaddressedInstance):
|
|
305
|
-
_val =
|
|
446
|
+
_val = 0xFC
|
|
306
447
|
|
|
307
448
|
|
|
308
449
|
class Device(_UnaddressedInstance):
|
|
309
|
-
_val =
|
|
450
|
+
_val = 0xFE
|
|
310
451
|
|
|
311
452
|
|
|
312
453
|
def instance_from_frame(f):
|
|
@@ -327,12 +468,12 @@ def instance_from_frame(f):
|
|
|
327
468
|
return FeatureInstanceGroup(p)
|
|
328
469
|
elif flags == 3:
|
|
329
470
|
return FeatureInstanceType(p)
|
|
330
|
-
elif b ==
|
|
471
|
+
elif b == 0xFD:
|
|
331
472
|
return FeatureInstanceBroadcast()
|
|
332
|
-
elif b ==
|
|
473
|
+
elif b == 0xFF:
|
|
333
474
|
return InstanceBroadcast()
|
|
334
|
-
elif b ==
|
|
475
|
+
elif b == 0xFC:
|
|
335
476
|
return FeatureDevice()
|
|
336
|
-
elif b ==
|
|
477
|
+
elif b == 0xFE:
|
|
337
478
|
return Device()
|
|
338
479
|
return ReservedInstance(b)
|
dali/command.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"""Declaration of base types for dali commands and their responses."""
|
|
2
2
|
|
|
3
|
+
from enum import IntEnum
|
|
3
4
|
from dali import address
|
|
4
5
|
from dali import frame
|
|
5
6
|
from dali.exceptions import MissingResponse
|
|
@@ -158,6 +159,21 @@ class BitmapResponse(Response, metaclass=BitmapResponseBitDict):
|
|
|
158
159
|
return "{}".format(e)
|
|
159
160
|
|
|
160
161
|
|
|
162
|
+
class EnumResponse(Response):
|
|
163
|
+
"""
|
|
164
|
+
A response that consists of a number from a pre-defined enumerator
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
enumerator: IntEnum = None
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def value(self):
|
|
171
|
+
_value = super().value
|
|
172
|
+
if _value:
|
|
173
|
+
return self.enumerator(_value.as_integer) # noqa
|
|
174
|
+
return _value
|
|
175
|
+
|
|
176
|
+
|
|
161
177
|
class Command(metaclass=_CommandTracker):
|
|
162
178
|
"""A command frame.
|
|
163
179
|
|
|
@@ -191,7 +207,10 @@ class Command(metaclass=_CommandTracker):
|
|
|
191
207
|
devicetype = 0
|
|
192
208
|
|
|
193
209
|
def __init__(self, f):
|
|
194
|
-
|
|
210
|
+
if not isinstance(f, frame.ForwardFrame):
|
|
211
|
+
raise TypeError(
|
|
212
|
+
f"{self.__class__.__name__} expected a ForwardFrame, not a {type(f)}"
|
|
213
|
+
)
|
|
195
214
|
self._data = f
|
|
196
215
|
|
|
197
216
|
_framesizes = {}
|
|
@@ -202,7 +221,7 @@ class Command(metaclass=_CommandTracker):
|
|
|
202
221
|
subs.append(subclass)
|
|
203
222
|
|
|
204
223
|
@classmethod
|
|
205
|
-
def from_frame(cls, f, devicetype=0):
|
|
224
|
+
def from_frame(cls, f, devicetype=0, dev_inst_map=None):
|
|
206
225
|
"""Return a Command instance corresponding to the supplied frame.
|
|
207
226
|
|
|
208
227
|
If the device type the command is intended for is known
|
|
@@ -211,6 +230,8 @@ class Command(metaclass=_CommandTracker):
|
|
|
211
230
|
|
|
212
231
|
:parameter frame: a forward frame
|
|
213
232
|
:parameter devicetype: type of device frame is intended for
|
|
233
|
+
:param dev_inst_map: An instance of DeviceInstanceTypeMapper to
|
|
234
|
+
assist with DALI events
|
|
214
235
|
|
|
215
236
|
:returns: Return a Command instance corresponding to the
|
|
216
237
|
frame. Returns None if there is no match.
|
|
@@ -222,7 +243,7 @@ class Command(metaclass=_CommandTracker):
|
|
|
222
243
|
subs = cls._framesizes.get(len(f), [])
|
|
223
244
|
|
|
224
245
|
for c in subs:
|
|
225
|
-
r = c.from_frame(f, devicetype=devicetype)
|
|
246
|
+
r = c.from_frame(f, devicetype=devicetype, dev_inst_map=dev_inst_map)
|
|
226
247
|
if r:
|
|
227
248
|
return r
|
|
228
249
|
|
dali/device/__init__.py
CHANGED
|
@@ -4,3 +4,8 @@ This module declares commands, responses and event messages defined in
|
|
|
4
4
|
part 103 ("General requirements - Control devices") and parts 3xx
|
|
5
5
|
(particular requirements for control devices).
|
|
6
6
|
"""
|
|
7
|
+
import dali.device.general
|
|
8
|
+
import dali.device.sequences
|
|
9
|
+
import dali.device.pushbutton # noqa: F401
|
|
10
|
+
import dali.device.occupancy # noqa: F401
|
|
11
|
+
import dali.device.light # noqa: F401
|