lifx-emulator 1.0.0__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.
- lifx_emulator/__init__.py +31 -0
- lifx_emulator/__main__.py +607 -0
- lifx_emulator/api.py +1825 -0
- lifx_emulator/async_storage.py +308 -0
- lifx_emulator/constants.py +33 -0
- lifx_emulator/device.py +750 -0
- lifx_emulator/device_states.py +114 -0
- lifx_emulator/factories.py +380 -0
- lifx_emulator/handlers/__init__.py +39 -0
- lifx_emulator/handlers/base.py +49 -0
- lifx_emulator/handlers/device_handlers.py +340 -0
- lifx_emulator/handlers/light_handlers.py +372 -0
- lifx_emulator/handlers/multizone_handlers.py +249 -0
- lifx_emulator/handlers/registry.py +110 -0
- lifx_emulator/handlers/tile_handlers.py +309 -0
- lifx_emulator/observers.py +139 -0
- lifx_emulator/products/__init__.py +28 -0
- lifx_emulator/products/generator.py +771 -0
- lifx_emulator/products/registry.py +1446 -0
- lifx_emulator/products/specs.py +242 -0
- lifx_emulator/products/specs.yml +327 -0
- lifx_emulator/protocol/__init__.py +1 -0
- lifx_emulator/protocol/base.py +334 -0
- lifx_emulator/protocol/const.py +8 -0
- lifx_emulator/protocol/generator.py +1371 -0
- lifx_emulator/protocol/header.py +159 -0
- lifx_emulator/protocol/packets.py +1351 -0
- lifx_emulator/protocol/protocol_types.py +844 -0
- lifx_emulator/protocol/serializer.py +379 -0
- lifx_emulator/scenario_manager.py +402 -0
- lifx_emulator/scenario_persistence.py +206 -0
- lifx_emulator/server.py +482 -0
- lifx_emulator/state_restorer.py +259 -0
- lifx_emulator/state_serializer.py +130 -0
- lifx_emulator/storage_protocol.py +100 -0
- lifx_emulator-1.0.0.dist-info/METADATA +445 -0
- lifx_emulator-1.0.0.dist-info/RECORD +40 -0
- lifx_emulator-1.0.0.dist-info/WHEEL +4 -0
- lifx_emulator-1.0.0.dist-info/entry_points.txt +2 -0
- lifx_emulator-1.0.0.dist-info/licenses/LICENSE +35 -0
|
@@ -0,0 +1,1446 @@
|
|
|
1
|
+
"""LIFX product definitions and capability detection.
|
|
2
|
+
|
|
3
|
+
DO NOT EDIT THIS FILE MANUALLY.
|
|
4
|
+
Generated from https://github.com/LIFX/products/blob/master/products.json
|
|
5
|
+
by products/generator.py
|
|
6
|
+
|
|
7
|
+
This module provides pre-generated product information for efficient runtime lookups.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from enum import IntEnum
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ProductCapability(IntEnum):
|
|
17
|
+
"""Product capability flags."""
|
|
18
|
+
|
|
19
|
+
COLOR = 1
|
|
20
|
+
INFRARED = 2
|
|
21
|
+
MULTIZONE = 4
|
|
22
|
+
CHAIN = 8
|
|
23
|
+
MATRIX = 16
|
|
24
|
+
RELAYS = 32
|
|
25
|
+
BUTTONS = 64
|
|
26
|
+
HEV = 128
|
|
27
|
+
EXTENDED_MULTIZONE = 256
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class TemperatureRange:
|
|
32
|
+
"""Color temperature range in Kelvin."""
|
|
33
|
+
|
|
34
|
+
min: int
|
|
35
|
+
max: int
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class ProductInfo:
|
|
40
|
+
"""Information about a LIFX product.
|
|
41
|
+
|
|
42
|
+
Attributes:
|
|
43
|
+
pid: Product ID
|
|
44
|
+
name: Product name
|
|
45
|
+
vendor: Vendor ID (always 1 for LIFX)
|
|
46
|
+
capabilities: Bitfield of ProductCapability flags
|
|
47
|
+
temperature_range: Min/max color temperature in Kelvin
|
|
48
|
+
min_ext_mz_firmware: Minimum firmware version for extended multizone
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
pid: int
|
|
52
|
+
name: str
|
|
53
|
+
vendor: int
|
|
54
|
+
capabilities: int
|
|
55
|
+
temperature_range: TemperatureRange | None
|
|
56
|
+
min_ext_mz_firmware: int | None
|
|
57
|
+
|
|
58
|
+
def has_capability(self, capability: ProductCapability) -> bool:
|
|
59
|
+
"""Check if product has a specific capability.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
capability: Capability to check
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
True if product has the capability
|
|
66
|
+
"""
|
|
67
|
+
return bool(self.capabilities & capability)
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def has_color(self) -> bool:
|
|
71
|
+
"""Check if product supports color."""
|
|
72
|
+
return self.has_capability(ProductCapability.COLOR)
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def has_infrared(self) -> bool:
|
|
76
|
+
"""Check if product supports infrared."""
|
|
77
|
+
return self.has_capability(ProductCapability.INFRARED)
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def has_multizone(self) -> bool:
|
|
81
|
+
"""Check if product supports multizone."""
|
|
82
|
+
return self.has_capability(ProductCapability.MULTIZONE)
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def has_chain(self) -> bool:
|
|
86
|
+
"""Check if product supports chaining."""
|
|
87
|
+
return self.has_capability(ProductCapability.CHAIN)
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def has_matrix(self) -> bool:
|
|
91
|
+
"""Check if product supports matrix (2D grid)."""
|
|
92
|
+
return self.has_capability(ProductCapability.MATRIX)
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def has_relays(self) -> bool:
|
|
96
|
+
"""Check if product has relays."""
|
|
97
|
+
return self.has_capability(ProductCapability.RELAYS)
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def has_buttons(self) -> bool:
|
|
101
|
+
"""Check if product has buttons."""
|
|
102
|
+
return self.has_capability(ProductCapability.BUTTONS)
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def has_hev(self) -> bool:
|
|
106
|
+
"""Check if product supports HEV."""
|
|
107
|
+
return self.has_capability(ProductCapability.HEV)
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def has_extended_multizone(self) -> bool:
|
|
111
|
+
"""Check if product supports extended multizone."""
|
|
112
|
+
return self.has_capability(ProductCapability.EXTENDED_MULTIZONE)
|
|
113
|
+
|
|
114
|
+
def supports_extended_multizone(self, firmware_version: int | None = None) -> bool:
|
|
115
|
+
"""Check if extended multizone is supported for given firmware version.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
firmware_version: Firmware version to check (optional)
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
True if extended multizone is supported
|
|
122
|
+
"""
|
|
123
|
+
if not self.has_extended_multizone:
|
|
124
|
+
return False
|
|
125
|
+
if self.min_ext_mz_firmware is None:
|
|
126
|
+
return True
|
|
127
|
+
if firmware_version is None:
|
|
128
|
+
return True
|
|
129
|
+
return firmware_version >= self.min_ext_mz_firmware
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# Pre-generated product definitions
|
|
133
|
+
PRODUCTS: dict[int, ProductInfo] = {
|
|
134
|
+
1: ProductInfo(
|
|
135
|
+
pid=1,
|
|
136
|
+
name="LIFX Original 1000",
|
|
137
|
+
vendor=1,
|
|
138
|
+
capabilities=ProductCapability.COLOR,
|
|
139
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
140
|
+
min_ext_mz_firmware=None,
|
|
141
|
+
),
|
|
142
|
+
3: ProductInfo(
|
|
143
|
+
pid=3,
|
|
144
|
+
name="LIFX Color 650",
|
|
145
|
+
vendor=1,
|
|
146
|
+
capabilities=ProductCapability.COLOR,
|
|
147
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
148
|
+
min_ext_mz_firmware=None,
|
|
149
|
+
),
|
|
150
|
+
10: ProductInfo(
|
|
151
|
+
pid=10,
|
|
152
|
+
name="LIFX White 800 (Low Voltage)",
|
|
153
|
+
vendor=1,
|
|
154
|
+
capabilities=0,
|
|
155
|
+
temperature_range=TemperatureRange(min=2700, max=6500),
|
|
156
|
+
min_ext_mz_firmware=None,
|
|
157
|
+
),
|
|
158
|
+
11: ProductInfo(
|
|
159
|
+
pid=11,
|
|
160
|
+
name="LIFX White 800 (High Voltage)",
|
|
161
|
+
vendor=1,
|
|
162
|
+
capabilities=0,
|
|
163
|
+
temperature_range=TemperatureRange(min=2700, max=6500),
|
|
164
|
+
min_ext_mz_firmware=None,
|
|
165
|
+
),
|
|
166
|
+
15: ProductInfo(
|
|
167
|
+
pid=15,
|
|
168
|
+
name="LIFX Color 1000",
|
|
169
|
+
vendor=1,
|
|
170
|
+
capabilities=ProductCapability.COLOR,
|
|
171
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
172
|
+
min_ext_mz_firmware=None,
|
|
173
|
+
),
|
|
174
|
+
18: ProductInfo(
|
|
175
|
+
pid=18,
|
|
176
|
+
name="LIFX White 900 BR30 (Low Voltage)",
|
|
177
|
+
vendor=1,
|
|
178
|
+
capabilities=0,
|
|
179
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
180
|
+
min_ext_mz_firmware=None,
|
|
181
|
+
),
|
|
182
|
+
19: ProductInfo(
|
|
183
|
+
pid=19,
|
|
184
|
+
name="LIFX White 900 BR30 (High Voltage)",
|
|
185
|
+
vendor=1,
|
|
186
|
+
capabilities=0,
|
|
187
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
188
|
+
min_ext_mz_firmware=None,
|
|
189
|
+
),
|
|
190
|
+
20: ProductInfo(
|
|
191
|
+
pid=20,
|
|
192
|
+
name="LIFX Color 1000 BR30",
|
|
193
|
+
vendor=1,
|
|
194
|
+
capabilities=ProductCapability.COLOR,
|
|
195
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
196
|
+
min_ext_mz_firmware=None,
|
|
197
|
+
),
|
|
198
|
+
22: ProductInfo(
|
|
199
|
+
pid=22,
|
|
200
|
+
name="LIFX Color 1000",
|
|
201
|
+
vendor=1,
|
|
202
|
+
capabilities=ProductCapability.COLOR,
|
|
203
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
204
|
+
min_ext_mz_firmware=None,
|
|
205
|
+
),
|
|
206
|
+
27: ProductInfo(
|
|
207
|
+
pid=27,
|
|
208
|
+
name="LIFX A19",
|
|
209
|
+
vendor=1,
|
|
210
|
+
capabilities=ProductCapability.COLOR,
|
|
211
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
212
|
+
min_ext_mz_firmware=None,
|
|
213
|
+
),
|
|
214
|
+
28: ProductInfo(
|
|
215
|
+
pid=28,
|
|
216
|
+
name="LIFX BR30",
|
|
217
|
+
vendor=1,
|
|
218
|
+
capabilities=ProductCapability.COLOR,
|
|
219
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
220
|
+
min_ext_mz_firmware=None,
|
|
221
|
+
),
|
|
222
|
+
29: ProductInfo(
|
|
223
|
+
pid=29,
|
|
224
|
+
name="LIFX A19 Night Vision",
|
|
225
|
+
vendor=1,
|
|
226
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
227
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
228
|
+
min_ext_mz_firmware=None,
|
|
229
|
+
),
|
|
230
|
+
30: ProductInfo(
|
|
231
|
+
pid=30,
|
|
232
|
+
name="LIFX BR30 Night Vision",
|
|
233
|
+
vendor=1,
|
|
234
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
235
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
236
|
+
min_ext_mz_firmware=None,
|
|
237
|
+
),
|
|
238
|
+
31: ProductInfo(
|
|
239
|
+
pid=31,
|
|
240
|
+
name="LIFX Z",
|
|
241
|
+
vendor=1,
|
|
242
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
243
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
244
|
+
min_ext_mz_firmware=None,
|
|
245
|
+
),
|
|
246
|
+
32: ProductInfo(
|
|
247
|
+
pid=32,
|
|
248
|
+
name="LIFX Z",
|
|
249
|
+
vendor=1,
|
|
250
|
+
capabilities=ProductCapability.COLOR
|
|
251
|
+
| ProductCapability.MULTIZONE
|
|
252
|
+
| ProductCapability.EXTENDED_MULTIZONE,
|
|
253
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
254
|
+
min_ext_mz_firmware=131149,
|
|
255
|
+
),
|
|
256
|
+
36: ProductInfo(
|
|
257
|
+
pid=36,
|
|
258
|
+
name="LIFX Downlight",
|
|
259
|
+
vendor=1,
|
|
260
|
+
capabilities=ProductCapability.COLOR,
|
|
261
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
262
|
+
min_ext_mz_firmware=None,
|
|
263
|
+
),
|
|
264
|
+
37: ProductInfo(
|
|
265
|
+
pid=37,
|
|
266
|
+
name="LIFX Downlight",
|
|
267
|
+
vendor=1,
|
|
268
|
+
capabilities=ProductCapability.COLOR,
|
|
269
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
270
|
+
min_ext_mz_firmware=None,
|
|
271
|
+
),
|
|
272
|
+
38: ProductInfo(
|
|
273
|
+
pid=38,
|
|
274
|
+
name="LIFX Beam",
|
|
275
|
+
vendor=1,
|
|
276
|
+
capabilities=ProductCapability.COLOR
|
|
277
|
+
| ProductCapability.MULTIZONE
|
|
278
|
+
| ProductCapability.EXTENDED_MULTIZONE,
|
|
279
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
280
|
+
min_ext_mz_firmware=131149,
|
|
281
|
+
),
|
|
282
|
+
39: ProductInfo(
|
|
283
|
+
pid=39,
|
|
284
|
+
name="LIFX Downlight White to Warm",
|
|
285
|
+
vendor=1,
|
|
286
|
+
capabilities=0,
|
|
287
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
288
|
+
min_ext_mz_firmware=None,
|
|
289
|
+
),
|
|
290
|
+
40: ProductInfo(
|
|
291
|
+
pid=40,
|
|
292
|
+
name="LIFX Downlight",
|
|
293
|
+
vendor=1,
|
|
294
|
+
capabilities=ProductCapability.COLOR,
|
|
295
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
296
|
+
min_ext_mz_firmware=None,
|
|
297
|
+
),
|
|
298
|
+
43: ProductInfo(
|
|
299
|
+
pid=43,
|
|
300
|
+
name="LIFX A19",
|
|
301
|
+
vendor=1,
|
|
302
|
+
capabilities=ProductCapability.COLOR,
|
|
303
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
304
|
+
min_ext_mz_firmware=None,
|
|
305
|
+
),
|
|
306
|
+
44: ProductInfo(
|
|
307
|
+
pid=44,
|
|
308
|
+
name="LIFX BR30",
|
|
309
|
+
vendor=1,
|
|
310
|
+
capabilities=ProductCapability.COLOR,
|
|
311
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
312
|
+
min_ext_mz_firmware=None,
|
|
313
|
+
),
|
|
314
|
+
45: ProductInfo(
|
|
315
|
+
pid=45,
|
|
316
|
+
name="LIFX A19 Night Vision",
|
|
317
|
+
vendor=1,
|
|
318
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
319
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
320
|
+
min_ext_mz_firmware=None,
|
|
321
|
+
),
|
|
322
|
+
46: ProductInfo(
|
|
323
|
+
pid=46,
|
|
324
|
+
name="LIFX BR30 Night Vision",
|
|
325
|
+
vendor=1,
|
|
326
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
327
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
328
|
+
min_ext_mz_firmware=None,
|
|
329
|
+
),
|
|
330
|
+
49: ProductInfo(
|
|
331
|
+
pid=49,
|
|
332
|
+
name="LIFX Mini Color",
|
|
333
|
+
vendor=1,
|
|
334
|
+
capabilities=ProductCapability.COLOR,
|
|
335
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
336
|
+
min_ext_mz_firmware=None,
|
|
337
|
+
),
|
|
338
|
+
50: ProductInfo(
|
|
339
|
+
pid=50,
|
|
340
|
+
name="LIFX Mini White to Warm",
|
|
341
|
+
vendor=1,
|
|
342
|
+
capabilities=0,
|
|
343
|
+
temperature_range=TemperatureRange(min=1500, max=6500),
|
|
344
|
+
min_ext_mz_firmware=None,
|
|
345
|
+
),
|
|
346
|
+
51: ProductInfo(
|
|
347
|
+
pid=51,
|
|
348
|
+
name="LIFX Mini White",
|
|
349
|
+
vendor=1,
|
|
350
|
+
capabilities=0,
|
|
351
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
352
|
+
min_ext_mz_firmware=None,
|
|
353
|
+
),
|
|
354
|
+
52: ProductInfo(
|
|
355
|
+
pid=52,
|
|
356
|
+
name="LIFX GU10",
|
|
357
|
+
vendor=1,
|
|
358
|
+
capabilities=ProductCapability.COLOR,
|
|
359
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
360
|
+
min_ext_mz_firmware=None,
|
|
361
|
+
),
|
|
362
|
+
53: ProductInfo(
|
|
363
|
+
pid=53,
|
|
364
|
+
name="LIFX GU10",
|
|
365
|
+
vendor=1,
|
|
366
|
+
capabilities=ProductCapability.COLOR,
|
|
367
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
368
|
+
min_ext_mz_firmware=None,
|
|
369
|
+
),
|
|
370
|
+
55: ProductInfo(
|
|
371
|
+
pid=55,
|
|
372
|
+
name="LIFX Tile",
|
|
373
|
+
vendor=1,
|
|
374
|
+
capabilities=ProductCapability.COLOR
|
|
375
|
+
| ProductCapability.CHAIN
|
|
376
|
+
| ProductCapability.MATRIX,
|
|
377
|
+
temperature_range=TemperatureRange(min=2500, max=9000),
|
|
378
|
+
min_ext_mz_firmware=None,
|
|
379
|
+
),
|
|
380
|
+
57: ProductInfo(
|
|
381
|
+
pid=57,
|
|
382
|
+
name="LIFX Candle",
|
|
383
|
+
vendor=1,
|
|
384
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
385
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
386
|
+
min_ext_mz_firmware=None,
|
|
387
|
+
),
|
|
388
|
+
59: ProductInfo(
|
|
389
|
+
pid=59,
|
|
390
|
+
name="LIFX Mini Color",
|
|
391
|
+
vendor=1,
|
|
392
|
+
capabilities=ProductCapability.COLOR,
|
|
393
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
394
|
+
min_ext_mz_firmware=None,
|
|
395
|
+
),
|
|
396
|
+
60: ProductInfo(
|
|
397
|
+
pid=60,
|
|
398
|
+
name="LIFX Mini White to Warm",
|
|
399
|
+
vendor=1,
|
|
400
|
+
capabilities=0,
|
|
401
|
+
temperature_range=TemperatureRange(min=1500, max=6500),
|
|
402
|
+
min_ext_mz_firmware=None,
|
|
403
|
+
),
|
|
404
|
+
61: ProductInfo(
|
|
405
|
+
pid=61,
|
|
406
|
+
name="LIFX Mini White",
|
|
407
|
+
vendor=1,
|
|
408
|
+
capabilities=0,
|
|
409
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
410
|
+
min_ext_mz_firmware=None,
|
|
411
|
+
),
|
|
412
|
+
62: ProductInfo(
|
|
413
|
+
pid=62,
|
|
414
|
+
name="LIFX A19",
|
|
415
|
+
vendor=1,
|
|
416
|
+
capabilities=ProductCapability.COLOR,
|
|
417
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
418
|
+
min_ext_mz_firmware=None,
|
|
419
|
+
),
|
|
420
|
+
63: ProductInfo(
|
|
421
|
+
pid=63,
|
|
422
|
+
name="LIFX BR30",
|
|
423
|
+
vendor=1,
|
|
424
|
+
capabilities=ProductCapability.COLOR,
|
|
425
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
426
|
+
min_ext_mz_firmware=None,
|
|
427
|
+
),
|
|
428
|
+
64: ProductInfo(
|
|
429
|
+
pid=64,
|
|
430
|
+
name="LIFX A19 Night Vision",
|
|
431
|
+
vendor=1,
|
|
432
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
433
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
434
|
+
min_ext_mz_firmware=None,
|
|
435
|
+
),
|
|
436
|
+
65: ProductInfo(
|
|
437
|
+
pid=65,
|
|
438
|
+
name="LIFX BR30 Night Vision",
|
|
439
|
+
vendor=1,
|
|
440
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
441
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
442
|
+
min_ext_mz_firmware=None,
|
|
443
|
+
),
|
|
444
|
+
66: ProductInfo(
|
|
445
|
+
pid=66,
|
|
446
|
+
name="LIFX Mini White",
|
|
447
|
+
vendor=1,
|
|
448
|
+
capabilities=0,
|
|
449
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
450
|
+
min_ext_mz_firmware=None,
|
|
451
|
+
),
|
|
452
|
+
68: ProductInfo(
|
|
453
|
+
pid=68,
|
|
454
|
+
name="LIFX Candle",
|
|
455
|
+
vendor=1,
|
|
456
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
457
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
458
|
+
min_ext_mz_firmware=None,
|
|
459
|
+
),
|
|
460
|
+
70: ProductInfo(
|
|
461
|
+
pid=70,
|
|
462
|
+
name="LIFX Switch",
|
|
463
|
+
vendor=1,
|
|
464
|
+
capabilities=ProductCapability.RELAYS | ProductCapability.BUTTONS,
|
|
465
|
+
temperature_range=None,
|
|
466
|
+
min_ext_mz_firmware=None,
|
|
467
|
+
),
|
|
468
|
+
71: ProductInfo(
|
|
469
|
+
pid=71,
|
|
470
|
+
name="LIFX Switch",
|
|
471
|
+
vendor=1,
|
|
472
|
+
capabilities=ProductCapability.RELAYS | ProductCapability.BUTTONS,
|
|
473
|
+
temperature_range=None,
|
|
474
|
+
min_ext_mz_firmware=None,
|
|
475
|
+
),
|
|
476
|
+
81: ProductInfo(
|
|
477
|
+
pid=81,
|
|
478
|
+
name="LIFX Candle White to Warm",
|
|
479
|
+
vendor=1,
|
|
480
|
+
capabilities=0,
|
|
481
|
+
temperature_range=TemperatureRange(min=2200, max=6500),
|
|
482
|
+
min_ext_mz_firmware=None,
|
|
483
|
+
),
|
|
484
|
+
82: ProductInfo(
|
|
485
|
+
pid=82,
|
|
486
|
+
name="LIFX Filament Clear",
|
|
487
|
+
vendor=1,
|
|
488
|
+
capabilities=0,
|
|
489
|
+
temperature_range=TemperatureRange(min=2100, max=2100),
|
|
490
|
+
min_ext_mz_firmware=None,
|
|
491
|
+
),
|
|
492
|
+
85: ProductInfo(
|
|
493
|
+
pid=85,
|
|
494
|
+
name="LIFX Filament Amber",
|
|
495
|
+
vendor=1,
|
|
496
|
+
capabilities=0,
|
|
497
|
+
temperature_range=TemperatureRange(min=2000, max=2000),
|
|
498
|
+
min_ext_mz_firmware=None,
|
|
499
|
+
),
|
|
500
|
+
87: ProductInfo(
|
|
501
|
+
pid=87,
|
|
502
|
+
name="LIFX Mini White",
|
|
503
|
+
vendor=1,
|
|
504
|
+
capabilities=0,
|
|
505
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
506
|
+
min_ext_mz_firmware=None,
|
|
507
|
+
),
|
|
508
|
+
88: ProductInfo(
|
|
509
|
+
pid=88,
|
|
510
|
+
name="LIFX Mini White",
|
|
511
|
+
vendor=1,
|
|
512
|
+
capabilities=0,
|
|
513
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
514
|
+
min_ext_mz_firmware=None,
|
|
515
|
+
),
|
|
516
|
+
89: ProductInfo(
|
|
517
|
+
pid=89,
|
|
518
|
+
name="LIFX Switch",
|
|
519
|
+
vendor=1,
|
|
520
|
+
capabilities=ProductCapability.RELAYS | ProductCapability.BUTTONS,
|
|
521
|
+
temperature_range=None,
|
|
522
|
+
min_ext_mz_firmware=None,
|
|
523
|
+
),
|
|
524
|
+
90: ProductInfo(
|
|
525
|
+
pid=90,
|
|
526
|
+
name="LIFX Clean",
|
|
527
|
+
vendor=1,
|
|
528
|
+
capabilities=ProductCapability.COLOR | ProductCapability.HEV,
|
|
529
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
530
|
+
min_ext_mz_firmware=None,
|
|
531
|
+
),
|
|
532
|
+
91: ProductInfo(
|
|
533
|
+
pid=91,
|
|
534
|
+
name="LIFX Color",
|
|
535
|
+
vendor=1,
|
|
536
|
+
capabilities=ProductCapability.COLOR,
|
|
537
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
538
|
+
min_ext_mz_firmware=None,
|
|
539
|
+
),
|
|
540
|
+
92: ProductInfo(
|
|
541
|
+
pid=92,
|
|
542
|
+
name="LIFX Color",
|
|
543
|
+
vendor=1,
|
|
544
|
+
capabilities=ProductCapability.COLOR,
|
|
545
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
546
|
+
min_ext_mz_firmware=None,
|
|
547
|
+
),
|
|
548
|
+
93: ProductInfo(
|
|
549
|
+
pid=93,
|
|
550
|
+
name="LIFX A19 US",
|
|
551
|
+
vendor=1,
|
|
552
|
+
capabilities=ProductCapability.COLOR,
|
|
553
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
554
|
+
min_ext_mz_firmware=None,
|
|
555
|
+
),
|
|
556
|
+
94: ProductInfo(
|
|
557
|
+
pid=94,
|
|
558
|
+
name="LIFX BR30",
|
|
559
|
+
vendor=1,
|
|
560
|
+
capabilities=ProductCapability.COLOR,
|
|
561
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
562
|
+
min_ext_mz_firmware=None,
|
|
563
|
+
),
|
|
564
|
+
96: ProductInfo(
|
|
565
|
+
pid=96,
|
|
566
|
+
name="LIFX Candle White to Warm",
|
|
567
|
+
vendor=1,
|
|
568
|
+
capabilities=0,
|
|
569
|
+
temperature_range=TemperatureRange(min=2200, max=6500),
|
|
570
|
+
min_ext_mz_firmware=None,
|
|
571
|
+
),
|
|
572
|
+
97: ProductInfo(
|
|
573
|
+
pid=97,
|
|
574
|
+
name="LIFX A19",
|
|
575
|
+
vendor=1,
|
|
576
|
+
capabilities=ProductCapability.COLOR,
|
|
577
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
578
|
+
min_ext_mz_firmware=None,
|
|
579
|
+
),
|
|
580
|
+
98: ProductInfo(
|
|
581
|
+
pid=98,
|
|
582
|
+
name="LIFX BR30",
|
|
583
|
+
vendor=1,
|
|
584
|
+
capabilities=ProductCapability.COLOR,
|
|
585
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
586
|
+
min_ext_mz_firmware=None,
|
|
587
|
+
),
|
|
588
|
+
99: ProductInfo(
|
|
589
|
+
pid=99,
|
|
590
|
+
name="LIFX Clean",
|
|
591
|
+
vendor=1,
|
|
592
|
+
capabilities=ProductCapability.COLOR | ProductCapability.HEV,
|
|
593
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
594
|
+
min_ext_mz_firmware=None,
|
|
595
|
+
),
|
|
596
|
+
100: ProductInfo(
|
|
597
|
+
pid=100,
|
|
598
|
+
name="LIFX Filament Clear",
|
|
599
|
+
vendor=1,
|
|
600
|
+
capabilities=0,
|
|
601
|
+
temperature_range=TemperatureRange(min=2100, max=2100),
|
|
602
|
+
min_ext_mz_firmware=None,
|
|
603
|
+
),
|
|
604
|
+
101: ProductInfo(
|
|
605
|
+
pid=101,
|
|
606
|
+
name="LIFX Filament Amber",
|
|
607
|
+
vendor=1,
|
|
608
|
+
capabilities=0,
|
|
609
|
+
temperature_range=TemperatureRange(min=2000, max=2000),
|
|
610
|
+
min_ext_mz_firmware=None,
|
|
611
|
+
),
|
|
612
|
+
109: ProductInfo(
|
|
613
|
+
pid=109,
|
|
614
|
+
name="LIFX A19 Night Vision",
|
|
615
|
+
vendor=1,
|
|
616
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
617
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
618
|
+
min_ext_mz_firmware=None,
|
|
619
|
+
),
|
|
620
|
+
110: ProductInfo(
|
|
621
|
+
pid=110,
|
|
622
|
+
name="LIFX BR30 Night Vision",
|
|
623
|
+
vendor=1,
|
|
624
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
625
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
626
|
+
min_ext_mz_firmware=None,
|
|
627
|
+
),
|
|
628
|
+
111: ProductInfo(
|
|
629
|
+
pid=111,
|
|
630
|
+
name="LIFX A19 Night Vision",
|
|
631
|
+
vendor=1,
|
|
632
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
633
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
634
|
+
min_ext_mz_firmware=None,
|
|
635
|
+
),
|
|
636
|
+
112: ProductInfo(
|
|
637
|
+
pid=112,
|
|
638
|
+
name="LIFX BR30 Night Vision Intl",
|
|
639
|
+
vendor=1,
|
|
640
|
+
capabilities=ProductCapability.COLOR | ProductCapability.INFRARED,
|
|
641
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
642
|
+
min_ext_mz_firmware=None,
|
|
643
|
+
),
|
|
644
|
+
113: ProductInfo(
|
|
645
|
+
pid=113,
|
|
646
|
+
name="LIFX Mini WW US",
|
|
647
|
+
vendor=1,
|
|
648
|
+
capabilities=0,
|
|
649
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
650
|
+
min_ext_mz_firmware=None,
|
|
651
|
+
),
|
|
652
|
+
114: ProductInfo(
|
|
653
|
+
pid=114,
|
|
654
|
+
name="LIFX Mini WW Intl",
|
|
655
|
+
vendor=1,
|
|
656
|
+
capabilities=0,
|
|
657
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
658
|
+
min_ext_mz_firmware=None,
|
|
659
|
+
),
|
|
660
|
+
115: ProductInfo(
|
|
661
|
+
pid=115,
|
|
662
|
+
name="LIFX Switch",
|
|
663
|
+
vendor=1,
|
|
664
|
+
capabilities=ProductCapability.RELAYS | ProductCapability.BUTTONS,
|
|
665
|
+
temperature_range=None,
|
|
666
|
+
min_ext_mz_firmware=None,
|
|
667
|
+
),
|
|
668
|
+
116: ProductInfo(
|
|
669
|
+
pid=116,
|
|
670
|
+
name="LIFX Switch",
|
|
671
|
+
vendor=1,
|
|
672
|
+
capabilities=ProductCapability.RELAYS | ProductCapability.BUTTONS,
|
|
673
|
+
temperature_range=None,
|
|
674
|
+
min_ext_mz_firmware=None,
|
|
675
|
+
),
|
|
676
|
+
117: ProductInfo(
|
|
677
|
+
pid=117,
|
|
678
|
+
name="LIFX Z US",
|
|
679
|
+
vendor=1,
|
|
680
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
681
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
682
|
+
min_ext_mz_firmware=None,
|
|
683
|
+
),
|
|
684
|
+
118: ProductInfo(
|
|
685
|
+
pid=118,
|
|
686
|
+
name="LIFX Z Intl",
|
|
687
|
+
vendor=1,
|
|
688
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
689
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
690
|
+
min_ext_mz_firmware=None,
|
|
691
|
+
),
|
|
692
|
+
119: ProductInfo(
|
|
693
|
+
pid=119,
|
|
694
|
+
name="LIFX Beam US",
|
|
695
|
+
vendor=1,
|
|
696
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
697
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
698
|
+
min_ext_mz_firmware=None,
|
|
699
|
+
),
|
|
700
|
+
120: ProductInfo(
|
|
701
|
+
pid=120,
|
|
702
|
+
name="LIFX Beam Intl",
|
|
703
|
+
vendor=1,
|
|
704
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
705
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
706
|
+
min_ext_mz_firmware=None,
|
|
707
|
+
),
|
|
708
|
+
121: ProductInfo(
|
|
709
|
+
pid=121,
|
|
710
|
+
name="LIFX Downlight Intl",
|
|
711
|
+
vendor=1,
|
|
712
|
+
capabilities=ProductCapability.COLOR,
|
|
713
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
714
|
+
min_ext_mz_firmware=None,
|
|
715
|
+
),
|
|
716
|
+
122: ProductInfo(
|
|
717
|
+
pid=122,
|
|
718
|
+
name="LIFX Downlight US",
|
|
719
|
+
vendor=1,
|
|
720
|
+
capabilities=ProductCapability.COLOR,
|
|
721
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
722
|
+
min_ext_mz_firmware=None,
|
|
723
|
+
),
|
|
724
|
+
123: ProductInfo(
|
|
725
|
+
pid=123,
|
|
726
|
+
name="LIFX Color US",
|
|
727
|
+
vendor=1,
|
|
728
|
+
capabilities=ProductCapability.COLOR,
|
|
729
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
730
|
+
min_ext_mz_firmware=None,
|
|
731
|
+
),
|
|
732
|
+
124: ProductInfo(
|
|
733
|
+
pid=124,
|
|
734
|
+
name="LIFX Colour Intl",
|
|
735
|
+
vendor=1,
|
|
736
|
+
capabilities=ProductCapability.COLOR,
|
|
737
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
738
|
+
min_ext_mz_firmware=None,
|
|
739
|
+
),
|
|
740
|
+
125: ProductInfo(
|
|
741
|
+
pid=125,
|
|
742
|
+
name="LIFX White to Warm US",
|
|
743
|
+
vendor=1,
|
|
744
|
+
capabilities=0,
|
|
745
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
746
|
+
min_ext_mz_firmware=None,
|
|
747
|
+
),
|
|
748
|
+
126: ProductInfo(
|
|
749
|
+
pid=126,
|
|
750
|
+
name="LIFX White to Warm Intl",
|
|
751
|
+
vendor=1,
|
|
752
|
+
capabilities=0,
|
|
753
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
754
|
+
min_ext_mz_firmware=None,
|
|
755
|
+
),
|
|
756
|
+
127: ProductInfo(
|
|
757
|
+
pid=127,
|
|
758
|
+
name="LIFX White US",
|
|
759
|
+
vendor=1,
|
|
760
|
+
capabilities=0,
|
|
761
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
762
|
+
min_ext_mz_firmware=None,
|
|
763
|
+
),
|
|
764
|
+
128: ProductInfo(
|
|
765
|
+
pid=128,
|
|
766
|
+
name="LIFX White Intl",
|
|
767
|
+
vendor=1,
|
|
768
|
+
capabilities=0,
|
|
769
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
770
|
+
min_ext_mz_firmware=None,
|
|
771
|
+
),
|
|
772
|
+
129: ProductInfo(
|
|
773
|
+
pid=129,
|
|
774
|
+
name="LIFX Color US",
|
|
775
|
+
vendor=1,
|
|
776
|
+
capabilities=ProductCapability.COLOR,
|
|
777
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
778
|
+
min_ext_mz_firmware=None,
|
|
779
|
+
),
|
|
780
|
+
130: ProductInfo(
|
|
781
|
+
pid=130,
|
|
782
|
+
name="LIFX Colour Intl",
|
|
783
|
+
vendor=1,
|
|
784
|
+
capabilities=ProductCapability.COLOR,
|
|
785
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
786
|
+
min_ext_mz_firmware=None,
|
|
787
|
+
),
|
|
788
|
+
131: ProductInfo(
|
|
789
|
+
pid=131,
|
|
790
|
+
name="LIFX White To Warm US",
|
|
791
|
+
vendor=1,
|
|
792
|
+
capabilities=0,
|
|
793
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
794
|
+
min_ext_mz_firmware=None,
|
|
795
|
+
),
|
|
796
|
+
132: ProductInfo(
|
|
797
|
+
pid=132,
|
|
798
|
+
name="LIFX White To Warm Intl",
|
|
799
|
+
vendor=1,
|
|
800
|
+
capabilities=0,
|
|
801
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
802
|
+
min_ext_mz_firmware=None,
|
|
803
|
+
),
|
|
804
|
+
133: ProductInfo(
|
|
805
|
+
pid=133,
|
|
806
|
+
name="LIFX White US",
|
|
807
|
+
vendor=1,
|
|
808
|
+
capabilities=0,
|
|
809
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
810
|
+
min_ext_mz_firmware=None,
|
|
811
|
+
),
|
|
812
|
+
134: ProductInfo(
|
|
813
|
+
pid=134,
|
|
814
|
+
name="LIFX White Intl",
|
|
815
|
+
vendor=1,
|
|
816
|
+
capabilities=0,
|
|
817
|
+
temperature_range=TemperatureRange(min=2700, max=2700),
|
|
818
|
+
min_ext_mz_firmware=None,
|
|
819
|
+
),
|
|
820
|
+
135: ProductInfo(
|
|
821
|
+
pid=135,
|
|
822
|
+
name="LIFX GU10 Color US",
|
|
823
|
+
vendor=1,
|
|
824
|
+
capabilities=ProductCapability.COLOR,
|
|
825
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
826
|
+
min_ext_mz_firmware=None,
|
|
827
|
+
),
|
|
828
|
+
136: ProductInfo(
|
|
829
|
+
pid=136,
|
|
830
|
+
name="LIFX GU10 Colour Intl",
|
|
831
|
+
vendor=1,
|
|
832
|
+
capabilities=ProductCapability.COLOR,
|
|
833
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
834
|
+
min_ext_mz_firmware=None,
|
|
835
|
+
),
|
|
836
|
+
137: ProductInfo(
|
|
837
|
+
pid=137,
|
|
838
|
+
name="LIFX Candle Color US",
|
|
839
|
+
vendor=1,
|
|
840
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
841
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
842
|
+
min_ext_mz_firmware=None,
|
|
843
|
+
),
|
|
844
|
+
138: ProductInfo(
|
|
845
|
+
pid=138,
|
|
846
|
+
name="LIFX Candle Colour Intl",
|
|
847
|
+
vendor=1,
|
|
848
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
849
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
850
|
+
min_ext_mz_firmware=None,
|
|
851
|
+
),
|
|
852
|
+
141: ProductInfo(
|
|
853
|
+
pid=141,
|
|
854
|
+
name="LIFX Neon US",
|
|
855
|
+
vendor=1,
|
|
856
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
857
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
858
|
+
min_ext_mz_firmware=None,
|
|
859
|
+
),
|
|
860
|
+
142: ProductInfo(
|
|
861
|
+
pid=142,
|
|
862
|
+
name="LIFX Neon Intl",
|
|
863
|
+
vendor=1,
|
|
864
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
865
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
866
|
+
min_ext_mz_firmware=None,
|
|
867
|
+
),
|
|
868
|
+
143: ProductInfo(
|
|
869
|
+
pid=143,
|
|
870
|
+
name="LIFX String US",
|
|
871
|
+
vendor=1,
|
|
872
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
873
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
874
|
+
min_ext_mz_firmware=None,
|
|
875
|
+
),
|
|
876
|
+
144: ProductInfo(
|
|
877
|
+
pid=144,
|
|
878
|
+
name="LIFX String Intl",
|
|
879
|
+
vendor=1,
|
|
880
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
881
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
882
|
+
min_ext_mz_firmware=None,
|
|
883
|
+
),
|
|
884
|
+
161: ProductInfo(
|
|
885
|
+
pid=161,
|
|
886
|
+
name="LIFX Outdoor Neon US",
|
|
887
|
+
vendor=1,
|
|
888
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
889
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
890
|
+
min_ext_mz_firmware=None,
|
|
891
|
+
),
|
|
892
|
+
162: ProductInfo(
|
|
893
|
+
pid=162,
|
|
894
|
+
name="LIFX Outdoor Neon Intl",
|
|
895
|
+
vendor=1,
|
|
896
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
897
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
898
|
+
min_ext_mz_firmware=None,
|
|
899
|
+
),
|
|
900
|
+
163: ProductInfo(
|
|
901
|
+
pid=163,
|
|
902
|
+
name="LIFX A19 US",
|
|
903
|
+
vendor=1,
|
|
904
|
+
capabilities=ProductCapability.COLOR,
|
|
905
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
906
|
+
min_ext_mz_firmware=None,
|
|
907
|
+
),
|
|
908
|
+
164: ProductInfo(
|
|
909
|
+
pid=164,
|
|
910
|
+
name="LIFX BR30 US",
|
|
911
|
+
vendor=1,
|
|
912
|
+
capabilities=ProductCapability.COLOR,
|
|
913
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
914
|
+
min_ext_mz_firmware=None,
|
|
915
|
+
),
|
|
916
|
+
165: ProductInfo(
|
|
917
|
+
pid=165,
|
|
918
|
+
name="LIFX A19 Intl",
|
|
919
|
+
vendor=1,
|
|
920
|
+
capabilities=ProductCapability.COLOR,
|
|
921
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
922
|
+
min_ext_mz_firmware=None,
|
|
923
|
+
),
|
|
924
|
+
166: ProductInfo(
|
|
925
|
+
pid=166,
|
|
926
|
+
name="LIFX BR30 Intl",
|
|
927
|
+
vendor=1,
|
|
928
|
+
capabilities=ProductCapability.COLOR,
|
|
929
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
930
|
+
min_ext_mz_firmware=None,
|
|
931
|
+
),
|
|
932
|
+
167: ProductInfo(
|
|
933
|
+
pid=167,
|
|
934
|
+
name="LIFX Downlight",
|
|
935
|
+
vendor=1,
|
|
936
|
+
capabilities=ProductCapability.COLOR,
|
|
937
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
938
|
+
min_ext_mz_firmware=None,
|
|
939
|
+
),
|
|
940
|
+
168: ProductInfo(
|
|
941
|
+
pid=168,
|
|
942
|
+
name="LIFX Downlight",
|
|
943
|
+
vendor=1,
|
|
944
|
+
capabilities=ProductCapability.COLOR,
|
|
945
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
946
|
+
min_ext_mz_firmware=None,
|
|
947
|
+
),
|
|
948
|
+
169: ProductInfo(
|
|
949
|
+
pid=169,
|
|
950
|
+
name="LIFX A21 1600lm US",
|
|
951
|
+
vendor=1,
|
|
952
|
+
capabilities=ProductCapability.COLOR,
|
|
953
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
954
|
+
min_ext_mz_firmware=None,
|
|
955
|
+
),
|
|
956
|
+
170: ProductInfo(
|
|
957
|
+
pid=170,
|
|
958
|
+
name="LIFX A21 1600lm Intl",
|
|
959
|
+
vendor=1,
|
|
960
|
+
capabilities=ProductCapability.COLOR,
|
|
961
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
962
|
+
min_ext_mz_firmware=None,
|
|
963
|
+
),
|
|
964
|
+
171: ProductInfo(
|
|
965
|
+
pid=171,
|
|
966
|
+
name="LIFX Round Spot US",
|
|
967
|
+
vendor=1,
|
|
968
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
969
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
970
|
+
min_ext_mz_firmware=None,
|
|
971
|
+
),
|
|
972
|
+
173: ProductInfo(
|
|
973
|
+
pid=173,
|
|
974
|
+
name="LIFX Round Path US",
|
|
975
|
+
vendor=1,
|
|
976
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
977
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
978
|
+
min_ext_mz_firmware=None,
|
|
979
|
+
),
|
|
980
|
+
174: ProductInfo(
|
|
981
|
+
pid=174,
|
|
982
|
+
name="LIFX Square Path US",
|
|
983
|
+
vendor=1,
|
|
984
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
985
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
986
|
+
min_ext_mz_firmware=None,
|
|
987
|
+
),
|
|
988
|
+
175: ProductInfo(
|
|
989
|
+
pid=175,
|
|
990
|
+
name="LIFX PAR38 US",
|
|
991
|
+
vendor=1,
|
|
992
|
+
capabilities=ProductCapability.COLOR,
|
|
993
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
994
|
+
min_ext_mz_firmware=None,
|
|
995
|
+
),
|
|
996
|
+
176: ProductInfo(
|
|
997
|
+
pid=176,
|
|
998
|
+
name="LIFX Ceiling US",
|
|
999
|
+
vendor=1,
|
|
1000
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1001
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1002
|
+
min_ext_mz_firmware=None,
|
|
1003
|
+
),
|
|
1004
|
+
177: ProductInfo(
|
|
1005
|
+
pid=177,
|
|
1006
|
+
name="LIFX Ceiling Intl",
|
|
1007
|
+
vendor=1,
|
|
1008
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1009
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1010
|
+
min_ext_mz_firmware=None,
|
|
1011
|
+
),
|
|
1012
|
+
178: ProductInfo(
|
|
1013
|
+
pid=178,
|
|
1014
|
+
name="LIFX Downlight US",
|
|
1015
|
+
vendor=1,
|
|
1016
|
+
capabilities=ProductCapability.COLOR,
|
|
1017
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1018
|
+
min_ext_mz_firmware=None,
|
|
1019
|
+
),
|
|
1020
|
+
179: ProductInfo(
|
|
1021
|
+
pid=179,
|
|
1022
|
+
name="LIFX Downlight US",
|
|
1023
|
+
vendor=1,
|
|
1024
|
+
capabilities=ProductCapability.COLOR,
|
|
1025
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1026
|
+
min_ext_mz_firmware=None,
|
|
1027
|
+
),
|
|
1028
|
+
180: ProductInfo(
|
|
1029
|
+
pid=180,
|
|
1030
|
+
name="LIFX Downlight US",
|
|
1031
|
+
vendor=1,
|
|
1032
|
+
capabilities=ProductCapability.COLOR,
|
|
1033
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1034
|
+
min_ext_mz_firmware=None,
|
|
1035
|
+
),
|
|
1036
|
+
181: ProductInfo(
|
|
1037
|
+
pid=181,
|
|
1038
|
+
name="LIFX Color US",
|
|
1039
|
+
vendor=1,
|
|
1040
|
+
capabilities=ProductCapability.COLOR,
|
|
1041
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1042
|
+
min_ext_mz_firmware=None,
|
|
1043
|
+
),
|
|
1044
|
+
182: ProductInfo(
|
|
1045
|
+
pid=182,
|
|
1046
|
+
name="LIFX Colour Intl",
|
|
1047
|
+
vendor=1,
|
|
1048
|
+
capabilities=ProductCapability.COLOR,
|
|
1049
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1050
|
+
min_ext_mz_firmware=None,
|
|
1051
|
+
),
|
|
1052
|
+
185: ProductInfo(
|
|
1053
|
+
pid=185,
|
|
1054
|
+
name="LIFX Candle Color US",
|
|
1055
|
+
vendor=1,
|
|
1056
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1057
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1058
|
+
min_ext_mz_firmware=None,
|
|
1059
|
+
),
|
|
1060
|
+
186: ProductInfo(
|
|
1061
|
+
pid=186,
|
|
1062
|
+
name="LIFX Candle Colour Intl",
|
|
1063
|
+
vendor=1,
|
|
1064
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1065
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1066
|
+
min_ext_mz_firmware=None,
|
|
1067
|
+
),
|
|
1068
|
+
187: ProductInfo(
|
|
1069
|
+
pid=187,
|
|
1070
|
+
name="LIFX Candle Color US",
|
|
1071
|
+
vendor=1,
|
|
1072
|
+
capabilities=ProductCapability.COLOR,
|
|
1073
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1074
|
+
min_ext_mz_firmware=None,
|
|
1075
|
+
),
|
|
1076
|
+
188: ProductInfo(
|
|
1077
|
+
pid=188,
|
|
1078
|
+
name="LIFX Candle Colour Intl",
|
|
1079
|
+
vendor=1,
|
|
1080
|
+
capabilities=ProductCapability.COLOR,
|
|
1081
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1082
|
+
min_ext_mz_firmware=None,
|
|
1083
|
+
),
|
|
1084
|
+
201: ProductInfo(
|
|
1085
|
+
pid=201,
|
|
1086
|
+
name='LIFX Ceiling 13x26" US',
|
|
1087
|
+
vendor=1,
|
|
1088
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1089
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1090
|
+
min_ext_mz_firmware=None,
|
|
1091
|
+
),
|
|
1092
|
+
202: ProductInfo(
|
|
1093
|
+
pid=202,
|
|
1094
|
+
name='LIFX Ceiling 13x26" Intl',
|
|
1095
|
+
vendor=1,
|
|
1096
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1097
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1098
|
+
min_ext_mz_firmware=None,
|
|
1099
|
+
),
|
|
1100
|
+
203: ProductInfo(
|
|
1101
|
+
pid=203,
|
|
1102
|
+
name="LIFX String US",
|
|
1103
|
+
vendor=1,
|
|
1104
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
1105
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1106
|
+
min_ext_mz_firmware=None,
|
|
1107
|
+
),
|
|
1108
|
+
204: ProductInfo(
|
|
1109
|
+
pid=204,
|
|
1110
|
+
name="LIFX String Intl",
|
|
1111
|
+
vendor=1,
|
|
1112
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
1113
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1114
|
+
min_ext_mz_firmware=None,
|
|
1115
|
+
),
|
|
1116
|
+
205: ProductInfo(
|
|
1117
|
+
pid=205,
|
|
1118
|
+
name="LIFX Indoor Neon US",
|
|
1119
|
+
vendor=1,
|
|
1120
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
1121
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1122
|
+
min_ext_mz_firmware=None,
|
|
1123
|
+
),
|
|
1124
|
+
206: ProductInfo(
|
|
1125
|
+
pid=206,
|
|
1126
|
+
name="LIFX Indoor Neon Intl",
|
|
1127
|
+
vendor=1,
|
|
1128
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
1129
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1130
|
+
min_ext_mz_firmware=None,
|
|
1131
|
+
),
|
|
1132
|
+
213: ProductInfo(
|
|
1133
|
+
pid=213,
|
|
1134
|
+
name="LIFX Permanent Outdoor US",
|
|
1135
|
+
vendor=1,
|
|
1136
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
1137
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1138
|
+
min_ext_mz_firmware=None,
|
|
1139
|
+
),
|
|
1140
|
+
214: ProductInfo(
|
|
1141
|
+
pid=214,
|
|
1142
|
+
name="LIFX Permanent Outdoor Intl",
|
|
1143
|
+
vendor=1,
|
|
1144
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MULTIZONE,
|
|
1145
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1146
|
+
min_ext_mz_firmware=None,
|
|
1147
|
+
),
|
|
1148
|
+
215: ProductInfo(
|
|
1149
|
+
pid=215,
|
|
1150
|
+
name="LIFX Candle Color US",
|
|
1151
|
+
vendor=1,
|
|
1152
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1153
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1154
|
+
min_ext_mz_firmware=None,
|
|
1155
|
+
),
|
|
1156
|
+
216: ProductInfo(
|
|
1157
|
+
pid=216,
|
|
1158
|
+
name="LIFX Candle Colour Intl",
|
|
1159
|
+
vendor=1,
|
|
1160
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1161
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1162
|
+
min_ext_mz_firmware=None,
|
|
1163
|
+
),
|
|
1164
|
+
217: ProductInfo(
|
|
1165
|
+
pid=217,
|
|
1166
|
+
name="LIFX Tube US",
|
|
1167
|
+
vendor=1,
|
|
1168
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1169
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1170
|
+
min_ext_mz_firmware=None,
|
|
1171
|
+
),
|
|
1172
|
+
218: ProductInfo(
|
|
1173
|
+
pid=218,
|
|
1174
|
+
name="LIFX Tube Intl",
|
|
1175
|
+
vendor=1,
|
|
1176
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1177
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1178
|
+
min_ext_mz_firmware=None,
|
|
1179
|
+
),
|
|
1180
|
+
219: ProductInfo(
|
|
1181
|
+
pid=219,
|
|
1182
|
+
name="LIFX Luna US",
|
|
1183
|
+
vendor=1,
|
|
1184
|
+
capabilities=ProductCapability.COLOR
|
|
1185
|
+
| ProductCapability.MATRIX
|
|
1186
|
+
| ProductCapability.BUTTONS,
|
|
1187
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1188
|
+
min_ext_mz_firmware=None,
|
|
1189
|
+
),
|
|
1190
|
+
220: ProductInfo(
|
|
1191
|
+
pid=220,
|
|
1192
|
+
name="LIFX Luna Intl",
|
|
1193
|
+
vendor=1,
|
|
1194
|
+
capabilities=ProductCapability.COLOR
|
|
1195
|
+
| ProductCapability.MATRIX
|
|
1196
|
+
| ProductCapability.BUTTONS,
|
|
1197
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1198
|
+
min_ext_mz_firmware=None,
|
|
1199
|
+
),
|
|
1200
|
+
221: ProductInfo(
|
|
1201
|
+
pid=221,
|
|
1202
|
+
name="LIFX Round Spot Intl",
|
|
1203
|
+
vendor=1,
|
|
1204
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1205
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1206
|
+
min_ext_mz_firmware=None,
|
|
1207
|
+
),
|
|
1208
|
+
222: ProductInfo(
|
|
1209
|
+
pid=222,
|
|
1210
|
+
name="LIFX Round Path Intl",
|
|
1211
|
+
vendor=1,
|
|
1212
|
+
capabilities=ProductCapability.COLOR | ProductCapability.MATRIX,
|
|
1213
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1214
|
+
min_ext_mz_firmware=None,
|
|
1215
|
+
),
|
|
1216
|
+
223: ProductInfo(
|
|
1217
|
+
pid=223,
|
|
1218
|
+
name="LIFX Downlight US",
|
|
1219
|
+
vendor=1,
|
|
1220
|
+
capabilities=ProductCapability.COLOR,
|
|
1221
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1222
|
+
min_ext_mz_firmware=None,
|
|
1223
|
+
),
|
|
1224
|
+
224: ProductInfo(
|
|
1225
|
+
pid=224,
|
|
1226
|
+
name="LIFX Downlight Intl",
|
|
1227
|
+
vendor=1,
|
|
1228
|
+
capabilities=ProductCapability.COLOR,
|
|
1229
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1230
|
+
min_ext_mz_firmware=None,
|
|
1231
|
+
),
|
|
1232
|
+
225: ProductInfo(
|
|
1233
|
+
pid=225,
|
|
1234
|
+
name="LIFX PAR38 INTL",
|
|
1235
|
+
vendor=1,
|
|
1236
|
+
capabilities=ProductCapability.COLOR,
|
|
1237
|
+
temperature_range=TemperatureRange(min=1500, max=9000),
|
|
1238
|
+
min_ext_mz_firmware=None,
|
|
1239
|
+
),
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
|
|
1243
|
+
class ProductRegistry:
|
|
1244
|
+
"""Registry of LIFX products and their capabilities."""
|
|
1245
|
+
|
|
1246
|
+
def __init__(self) -> None:
|
|
1247
|
+
"""Initialize product registry with pre-generated data."""
|
|
1248
|
+
self._products = PRODUCTS.copy() # Copy to allow test overrides
|
|
1249
|
+
self._loaded = True # Always loaded in generated registry
|
|
1250
|
+
|
|
1251
|
+
def load_from_dict(self, data: dict | list) -> None:
|
|
1252
|
+
"""Load products from parsed JSON data (for testing).
|
|
1253
|
+
|
|
1254
|
+
Args:
|
|
1255
|
+
data: Parsed products.json dictionary or array
|
|
1256
|
+
"""
|
|
1257
|
+
from typing import Any
|
|
1258
|
+
|
|
1259
|
+
# Clear existing products
|
|
1260
|
+
self._products.clear()
|
|
1261
|
+
|
|
1262
|
+
# Handle both array and object formats
|
|
1263
|
+
all_vendors = []
|
|
1264
|
+
if isinstance(data, list):
|
|
1265
|
+
all_vendors = data
|
|
1266
|
+
else:
|
|
1267
|
+
all_vendors = [data]
|
|
1268
|
+
|
|
1269
|
+
# Process each vendor
|
|
1270
|
+
for vendor_data in all_vendors:
|
|
1271
|
+
vendor_id = vendor_data.get("vid", 1)
|
|
1272
|
+
defaults = vendor_data.get("defaults", {})
|
|
1273
|
+
default_features = defaults.get("features", {})
|
|
1274
|
+
|
|
1275
|
+
# Parse each product
|
|
1276
|
+
for product in vendor_data.get("products", []):
|
|
1277
|
+
pid = product["pid"]
|
|
1278
|
+
name = product["name"]
|
|
1279
|
+
|
|
1280
|
+
# Merge features with defaults
|
|
1281
|
+
prod_features = product.get("features", {})
|
|
1282
|
+
features: dict[str, Any] = {**default_features, **prod_features}
|
|
1283
|
+
|
|
1284
|
+
# Build capabilities bitfield
|
|
1285
|
+
capabilities = 0
|
|
1286
|
+
if features.get("color"):
|
|
1287
|
+
capabilities |= ProductCapability.COLOR
|
|
1288
|
+
if features.get("infrared"):
|
|
1289
|
+
capabilities |= ProductCapability.INFRARED
|
|
1290
|
+
if features.get("multizone"):
|
|
1291
|
+
capabilities |= ProductCapability.MULTIZONE
|
|
1292
|
+
if features.get("chain"):
|
|
1293
|
+
capabilities |= ProductCapability.CHAIN
|
|
1294
|
+
if features.get("matrix"):
|
|
1295
|
+
capabilities |= ProductCapability.MATRIX
|
|
1296
|
+
if features.get("relays"):
|
|
1297
|
+
capabilities |= ProductCapability.RELAYS
|
|
1298
|
+
if features.get("buttons"):
|
|
1299
|
+
capabilities |= ProductCapability.BUTTONS
|
|
1300
|
+
if features.get("hev"):
|
|
1301
|
+
capabilities |= ProductCapability.HEV
|
|
1302
|
+
|
|
1303
|
+
# Check for extended multizone in upgrades
|
|
1304
|
+
min_ext_mz_firmware = None
|
|
1305
|
+
for upgrade in product.get("upgrades", []):
|
|
1306
|
+
if upgrade.get("features", {}).get("extended_multizone"):
|
|
1307
|
+
capabilities |= ProductCapability.EXTENDED_MULTIZONE
|
|
1308
|
+
# Parse firmware version (major.minor format)
|
|
1309
|
+
major = upgrade.get("major", 0)
|
|
1310
|
+
minor = upgrade.get("minor", 0)
|
|
1311
|
+
min_ext_mz_firmware = (major << 16) | minor
|
|
1312
|
+
break
|
|
1313
|
+
|
|
1314
|
+
# Parse temperature range
|
|
1315
|
+
temp_range = None
|
|
1316
|
+
if "temperature_range" in features:
|
|
1317
|
+
temp_list = features["temperature_range"]
|
|
1318
|
+
if len(temp_list) >= 2:
|
|
1319
|
+
temp_range = TemperatureRange(
|
|
1320
|
+
min=temp_list[0], max=temp_list[1]
|
|
1321
|
+
)
|
|
1322
|
+
|
|
1323
|
+
product_info = ProductInfo(
|
|
1324
|
+
pid=pid,
|
|
1325
|
+
name=name,
|
|
1326
|
+
vendor=vendor_id,
|
|
1327
|
+
capabilities=capabilities,
|
|
1328
|
+
temperature_range=temp_range,
|
|
1329
|
+
min_ext_mz_firmware=min_ext_mz_firmware,
|
|
1330
|
+
)
|
|
1331
|
+
|
|
1332
|
+
self._products[pid] = product_info
|
|
1333
|
+
|
|
1334
|
+
self._loaded = True
|
|
1335
|
+
|
|
1336
|
+
@property
|
|
1337
|
+
def is_loaded(self) -> bool:
|
|
1338
|
+
"""Check if registry has been loaded."""
|
|
1339
|
+
return self._loaded
|
|
1340
|
+
|
|
1341
|
+
def get_product(self, pid: int) -> ProductInfo | None:
|
|
1342
|
+
"""Get product info by product ID.
|
|
1343
|
+
|
|
1344
|
+
Args:
|
|
1345
|
+
pid: Product ID
|
|
1346
|
+
|
|
1347
|
+
Returns:
|
|
1348
|
+
ProductInfo if found, None otherwise
|
|
1349
|
+
"""
|
|
1350
|
+
return self._products.get(pid)
|
|
1351
|
+
|
|
1352
|
+
def get_device_class_name(
|
|
1353
|
+
self, pid: int, firmware_version: int | None = None
|
|
1354
|
+
) -> str:
|
|
1355
|
+
"""Get appropriate device class name for a product.
|
|
1356
|
+
|
|
1357
|
+
Args:
|
|
1358
|
+
pid: Product ID
|
|
1359
|
+
firmware_version: Firmware version (optional)
|
|
1360
|
+
|
|
1361
|
+
Returns:
|
|
1362
|
+
Device class name: "TileDevice", "MultiZoneLight", "HevLight",
|
|
1363
|
+
"InfraredLight", "Light", or "Device"
|
|
1364
|
+
"""
|
|
1365
|
+
product = self.get_product(pid)
|
|
1366
|
+
if product is None:
|
|
1367
|
+
# Unknown product - default to Light if we don't know
|
|
1368
|
+
return "Light"
|
|
1369
|
+
|
|
1370
|
+
# Matrix devices (Tiles, Candles) → TileDevice
|
|
1371
|
+
if product.has_matrix:
|
|
1372
|
+
return "TileDevice"
|
|
1373
|
+
|
|
1374
|
+
# MultiZone devices (Strips, Beams) → MultiZoneLight
|
|
1375
|
+
if product.has_multizone:
|
|
1376
|
+
return "MultiZoneLight"
|
|
1377
|
+
|
|
1378
|
+
# HEV lights → HevLight
|
|
1379
|
+
if product.has_hev:
|
|
1380
|
+
return "HevLight"
|
|
1381
|
+
|
|
1382
|
+
# Infrared lights → InfraredLight
|
|
1383
|
+
if product.has_infrared:
|
|
1384
|
+
return "InfraredLight"
|
|
1385
|
+
|
|
1386
|
+
# Color lights → Light
|
|
1387
|
+
if product.has_color:
|
|
1388
|
+
return "Light"
|
|
1389
|
+
|
|
1390
|
+
# Devices with relays (switches/relays) → Device
|
|
1391
|
+
if product.has_relays:
|
|
1392
|
+
return "Device"
|
|
1393
|
+
|
|
1394
|
+
# Devices with buttons but no color (switches) → Device
|
|
1395
|
+
if product.has_buttons:
|
|
1396
|
+
return "Device"
|
|
1397
|
+
|
|
1398
|
+
# Everything else (basic lights, white-to-warm lights) → Light
|
|
1399
|
+
# These have no special capabilities but still support Light protocol
|
|
1400
|
+
return "Light"
|
|
1401
|
+
|
|
1402
|
+
def __len__(self) -> int:
|
|
1403
|
+
"""Get number of products in registry."""
|
|
1404
|
+
return len(self._products)
|
|
1405
|
+
|
|
1406
|
+
def __contains__(self, pid: int) -> bool:
|
|
1407
|
+
"""Check if product ID exists in registry."""
|
|
1408
|
+
return pid in self._products
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
# Global registry instance
|
|
1412
|
+
_registry = ProductRegistry()
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
def get_registry() -> ProductRegistry:
|
|
1416
|
+
"""Get the global product registry.
|
|
1417
|
+
|
|
1418
|
+
Returns:
|
|
1419
|
+
Global ProductRegistry instance
|
|
1420
|
+
"""
|
|
1421
|
+
return _registry
|
|
1422
|
+
|
|
1423
|
+
|
|
1424
|
+
def get_product(pid: int) -> ProductInfo | None:
|
|
1425
|
+
"""Get product info by product ID.
|
|
1426
|
+
|
|
1427
|
+
Args:
|
|
1428
|
+
pid: Product ID
|
|
1429
|
+
|
|
1430
|
+
Returns:
|
|
1431
|
+
ProductInfo if found, None otherwise
|
|
1432
|
+
"""
|
|
1433
|
+
return _registry.get_product(pid)
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
def get_device_class_name(pid: int, firmware_version: int | None = None) -> str:
|
|
1437
|
+
"""Get appropriate device class name for a product.
|
|
1438
|
+
|
|
1439
|
+
Args:
|
|
1440
|
+
pid: Product ID
|
|
1441
|
+
firmware_version: Firmware version (optional)
|
|
1442
|
+
|
|
1443
|
+
Returns:
|
|
1444
|
+
Device class name: "TileDevice", "MultiZoneLight", "Light", or "Device"
|
|
1445
|
+
"""
|
|
1446
|
+
return _registry.get_device_class_name(pid, firmware_version)
|