lifx-emulator 2.4.0__py3-none-any.whl → 3.1.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.
Files changed (70) hide show
  1. lifx_emulator-3.1.0.dist-info/METADATA +103 -0
  2. lifx_emulator-3.1.0.dist-info/RECORD +19 -0
  3. {lifx_emulator-2.4.0.dist-info → lifx_emulator-3.1.0.dist-info}/WHEEL +1 -1
  4. lifx_emulator-3.1.0.dist-info/entry_points.txt +2 -0
  5. lifx_emulator_app/__init__.py +10 -0
  6. {lifx_emulator → lifx_emulator_app}/__main__.py +2 -3
  7. {lifx_emulator → lifx_emulator_app}/api/__init__.py +1 -1
  8. {lifx_emulator → lifx_emulator_app}/api/app.py +9 -4
  9. {lifx_emulator → lifx_emulator_app}/api/mappers/__init__.py +1 -1
  10. {lifx_emulator → lifx_emulator_app}/api/mappers/device_mapper.py +1 -1
  11. {lifx_emulator → lifx_emulator_app}/api/models.py +1 -2
  12. lifx_emulator_app/api/routers/__init__.py +11 -0
  13. {lifx_emulator → lifx_emulator_app}/api/routers/devices.py +2 -2
  14. {lifx_emulator → lifx_emulator_app}/api/routers/monitoring.py +1 -1
  15. {lifx_emulator → lifx_emulator_app}/api/routers/scenarios.py +1 -1
  16. lifx_emulator_app/api/services/__init__.py +8 -0
  17. {lifx_emulator → lifx_emulator_app}/api/services/device_service.py +3 -2
  18. lifx_emulator_app/api/static/dashboard.js +588 -0
  19. lifx_emulator_app/api/templates/dashboard.html +357 -0
  20. lifx_emulator/__init__.py +0 -31
  21. lifx_emulator/api/routers/__init__.py +0 -11
  22. lifx_emulator/api/services/__init__.py +0 -8
  23. lifx_emulator/api/templates/dashboard.html +0 -899
  24. lifx_emulator/constants.py +0 -33
  25. lifx_emulator/devices/__init__.py +0 -37
  26. lifx_emulator/devices/device.py +0 -395
  27. lifx_emulator/devices/manager.py +0 -256
  28. lifx_emulator/devices/observers.py +0 -139
  29. lifx_emulator/devices/persistence.py +0 -308
  30. lifx_emulator/devices/state_restorer.py +0 -259
  31. lifx_emulator/devices/state_serializer.py +0 -157
  32. lifx_emulator/devices/states.py +0 -381
  33. lifx_emulator/factories/__init__.py +0 -39
  34. lifx_emulator/factories/builder.py +0 -375
  35. lifx_emulator/factories/default_config.py +0 -158
  36. lifx_emulator/factories/factory.py +0 -252
  37. lifx_emulator/factories/firmware_config.py +0 -77
  38. lifx_emulator/factories/serial_generator.py +0 -82
  39. lifx_emulator/handlers/__init__.py +0 -39
  40. lifx_emulator/handlers/base.py +0 -49
  41. lifx_emulator/handlers/device_handlers.py +0 -322
  42. lifx_emulator/handlers/light_handlers.py +0 -503
  43. lifx_emulator/handlers/multizone_handlers.py +0 -249
  44. lifx_emulator/handlers/registry.py +0 -110
  45. lifx_emulator/handlers/tile_handlers.py +0 -488
  46. lifx_emulator/products/__init__.py +0 -28
  47. lifx_emulator/products/generator.py +0 -1079
  48. lifx_emulator/products/registry.py +0 -1530
  49. lifx_emulator/products/specs.py +0 -284
  50. lifx_emulator/products/specs.yml +0 -386
  51. lifx_emulator/protocol/__init__.py +0 -1
  52. lifx_emulator/protocol/base.py +0 -446
  53. lifx_emulator/protocol/const.py +0 -8
  54. lifx_emulator/protocol/generator.py +0 -1384
  55. lifx_emulator/protocol/header.py +0 -159
  56. lifx_emulator/protocol/packets.py +0 -1351
  57. lifx_emulator/protocol/protocol_types.py +0 -817
  58. lifx_emulator/protocol/serializer.py +0 -379
  59. lifx_emulator/repositories/__init__.py +0 -22
  60. lifx_emulator/repositories/device_repository.py +0 -155
  61. lifx_emulator/repositories/storage_backend.py +0 -107
  62. lifx_emulator/scenarios/__init__.py +0 -22
  63. lifx_emulator/scenarios/manager.py +0 -322
  64. lifx_emulator/scenarios/models.py +0 -112
  65. lifx_emulator/scenarios/persistence.py +0 -241
  66. lifx_emulator/server.py +0 -464
  67. lifx_emulator-2.4.0.dist-info/METADATA +0 -107
  68. lifx_emulator-2.4.0.dist-info/RECORD +0 -62
  69. lifx_emulator-2.4.0.dist-info/entry_points.txt +0 -2
  70. lifx_emulator-2.4.0.dist-info/licenses/LICENSE +0 -35
@@ -1,284 +0,0 @@
1
- """Product specs and defaults for LIFX devices.
2
-
3
- This module provides access to product-specific details that are not available
4
- in the upstream LIFX products.json catalog, such as default zone counts and
5
- tile configurations.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- from dataclasses import dataclass
11
- from pathlib import Path
12
-
13
- import yaml
14
-
15
-
16
- @dataclass
17
- class ProductSpecs:
18
- """Product-specific specs and defaults.
19
-
20
- Attributes:
21
- product_id: Product ID this applies to
22
- default_zone_count: Default number of zones for multizone devices
23
- min_zone_count: Minimum zones supported
24
- max_zone_count: Maximum zones supported
25
- default_tile_count: Default number of tiles in chain
26
- min_tile_count: Minimum tiles supported
27
- max_tile_count: Maximum tiles supported
28
- tile_width: Width of each tile in zones
29
- tile_height: Height of each tile in zones
30
- default_firmware_major: Default firmware major version
31
- default_firmware_minor: Default firmware minor version
32
- notes: Human-readable notes about this product
33
- """
34
-
35
- product_id: int
36
- default_zone_count: int | None = None
37
- min_zone_count: int | None = None
38
- max_zone_count: int | None = None
39
- default_tile_count: int | None = None
40
- min_tile_count: int | None = None
41
- max_tile_count: int | None = None
42
- tile_width: int | None = None
43
- tile_height: int | None = None
44
- default_firmware_major: int | None = None
45
- default_firmware_minor: int | None = None
46
- notes: str | None = None
47
-
48
- @property
49
- def has_multizone_specs(self) -> bool:
50
- """Check if this product has multizone-specific specs."""
51
- return self.default_zone_count is not None
52
-
53
- @property
54
- def has_matrix_specs(self) -> bool:
55
- """Check if this product has matrix-specific specs."""
56
- return self.tile_width is not None or self.tile_height is not None
57
-
58
- @property
59
- def has_firmware_specs(self) -> bool:
60
- """Check if this product has firmware version specs."""
61
- return (
62
- self.default_firmware_major is not None
63
- and self.default_firmware_minor is not None
64
- )
65
-
66
-
67
- class SpecsRegistry:
68
- """Registry of product specs loaded from specs.yml."""
69
-
70
- def __init__(self) -> None:
71
- """Initialize empty specs registry."""
72
- self._specs: dict[int, ProductSpecs] = {}
73
- self._loaded = False
74
-
75
- def load_from_file(self, specs_path: Path | None = None) -> None:
76
- """Load specs from YAML file.
77
-
78
- Args:
79
- specs_path: Path to specs.yml file. If None, uses default location.
80
- """
81
- if specs_path is None:
82
- specs_path = Path(__file__).parent / "specs.yml"
83
-
84
- if not specs_path.exists():
85
- # No specs file, that's okay - we'll use registry defaults only
86
- self._loaded = True
87
- return
88
-
89
- with open(specs_path) as f:
90
- data = yaml.safe_load(f)
91
-
92
- if not data or "products" not in data:
93
- self._loaded = True
94
- return
95
-
96
- # Parse product specs
97
- for pid, specs_data in data["products"].items():
98
- self._specs[int(pid)] = ProductSpecs(
99
- product_id=int(pid),
100
- default_zone_count=specs_data.get("default_zone_count"),
101
- min_zone_count=specs_data.get("min_zone_count"),
102
- max_zone_count=specs_data.get("max_zone_count"),
103
- default_tile_count=specs_data.get("default_tile_count"),
104
- min_tile_count=specs_data.get("min_tile_count"),
105
- max_tile_count=specs_data.get("max_tile_count"),
106
- tile_width=specs_data.get("tile_width"),
107
- tile_height=specs_data.get("tile_height"),
108
- default_firmware_major=specs_data.get("default_firmware_major"),
109
- default_firmware_minor=specs_data.get("default_firmware_minor"),
110
- notes=specs_data.get("notes"),
111
- )
112
-
113
- self._loaded = True
114
-
115
- @property
116
- def is_loaded(self) -> bool:
117
- """Check if specs have been loaded."""
118
- return self._loaded
119
-
120
- def get_specs(self, product_id: int) -> ProductSpecs | None:
121
- """Get specs for a specific product.
122
-
123
- Args:
124
- product_id: Product ID to look up
125
-
126
- Returns:
127
- ProductSpecs if found, None otherwise
128
- """
129
- if not self._loaded:
130
- self.load_from_file()
131
-
132
- return self._specs.get(product_id)
133
-
134
- def has_specs(self, product_id: int) -> bool:
135
- """Check if a product has specs defined.
136
-
137
- Args:
138
- product_id: Product ID to check
139
-
140
- Returns:
141
- True if specs exist for this product
142
- """
143
- if not self._loaded:
144
- self.load_from_file()
145
-
146
- return product_id in self._specs
147
-
148
- def get_default_zone_count(self, product_id: int) -> int | None:
149
- """Get default zone count for a multizone product.
150
-
151
- Args:
152
- product_id: Product ID
153
-
154
- Returns:
155
- Default zone count if defined, None otherwise
156
- """
157
- specs = self.get_specs(product_id)
158
- return specs.default_zone_count if specs else None
159
-
160
- def get_default_tile_count(self, product_id: int) -> int | None:
161
- """Get default tile count for a matrix product.
162
-
163
- Args:
164
- product_id: Product ID
165
-
166
- Returns:
167
- Default tile count if defined, None otherwise
168
- """
169
- specs = self.get_specs(product_id)
170
- return specs.default_tile_count if specs else None
171
-
172
- def get_tile_dimensions(self, product_id: int) -> tuple[int, int] | None:
173
- """Get tile dimensions for a matrix product.
174
-
175
- Args:
176
- product_id: Product ID
177
-
178
- Returns:
179
- Tuple of (width, height) if defined, None otherwise
180
- """
181
- specs = self.get_specs(product_id)
182
- if specs and specs.tile_width and specs.tile_height:
183
- return (specs.tile_width, specs.tile_height)
184
- return None
185
-
186
- def get_default_firmware_version(self, product_id: int) -> tuple[int, int] | None:
187
- """Get default firmware version for a product.
188
-
189
- Args:
190
- product_id: Product ID
191
-
192
- Returns:
193
- Tuple of (major, minor) if defined, None otherwise
194
- """
195
- specs = self.get_specs(product_id)
196
- if specs and specs.has_firmware_specs:
197
- # has_firmware_specs ensures both values are not None
198
- assert specs.default_firmware_major is not None # nosec
199
- assert specs.default_firmware_minor is not None # nosec
200
- return (specs.default_firmware_major, specs.default_firmware_minor)
201
- return None
202
-
203
- def __len__(self) -> int:
204
- """Get number of products with specs."""
205
- if not self._loaded:
206
- self.load_from_file()
207
- return len(self._specs)
208
-
209
- def __contains__(self, product_id: int) -> bool:
210
- """Check if product has specs."""
211
- return self.has_specs(product_id)
212
-
213
-
214
- # Global specs registry instance
215
- _specs_registry = SpecsRegistry()
216
-
217
-
218
- def get_specs_registry() -> SpecsRegistry:
219
- """Get the global specs registry.
220
-
221
- Returns:
222
- Global SpecsRegistry instance
223
- """
224
- return _specs_registry
225
-
226
-
227
- def get_specs(product_id: int) -> ProductSpecs | None:
228
- """Get specs for a specific product.
229
-
230
- Args:
231
- product_id: Product ID to look up
232
-
233
- Returns:
234
- ProductSpecs if found, None otherwise
235
- """
236
- return _specs_registry.get_specs(product_id)
237
-
238
-
239
- def get_default_zone_count(product_id: int) -> int | None:
240
- """Get default zone count for a multizone product.
241
-
242
- Args:
243
- product_id: Product ID
244
-
245
- Returns:
246
- Default zone count if defined, None otherwise
247
- """
248
- return _specs_registry.get_default_zone_count(product_id)
249
-
250
-
251
- def get_default_tile_count(product_id: int) -> int | None:
252
- """Get default tile count for a matrix product.
253
-
254
- Args:
255
- product_id: Product ID
256
-
257
- Returns:
258
- Default tile count if defined, None otherwise
259
- """
260
- return _specs_registry.get_default_tile_count(product_id)
261
-
262
-
263
- def get_tile_dimensions(product_id: int) -> tuple[int, int] | None:
264
- """Get tile dimensions for a matrix product.
265
-
266
- Args:
267
- product_id: Product ID
268
-
269
- Returns:
270
- Tuple of (width, height) if defined, None otherwise
271
- """
272
- return _specs_registry.get_tile_dimensions(product_id)
273
-
274
-
275
- def get_default_firmware_version(product_id: int) -> tuple[int, int] | None:
276
- """Get default firmware version for a product.
277
-
278
- Args:
279
- product_id: Product ID
280
-
281
- Returns:
282
- Tuple of (major, minor) if defined, None otherwise
283
- """
284
- return _specs_registry.get_default_firmware_version(product_id)
@@ -1,386 +0,0 @@
1
- # LIFX Product Specs and Defaults
2
- # =================================
3
- #
4
- # This file contains product-specific details that are not available in the
5
- # upstream LIFX products.json catalog, such as default zone counts, tile
6
- # configurations, firmware versions, and other device-specific defaults.
7
- #
8
- # These values are used by the emulator to create realistic device
9
- # configurations when specific parameters are not provided by the user.
10
- #
11
- # Format:
12
- # -------
13
- # products:
14
- # <product_id>:
15
- # # For multizone devices
16
- # default_zone_count: <number> # Default zones (e.g., 16)
17
- # min_zone_count: <number> # Minimum zones supported
18
- # max_zone_count: <number> # Maximum zones supported
19
- #
20
- # # For matrix devices (tiles, candles, etc.)
21
- # default_tile_count: <number> # Default number of tiles in chain
22
- # min_tile_count: <number> # Minimum tiles supported
23
- # max_tile_count: <number> # Maximum tiles supported
24
- # tile_width: <number> # Width of each tile in zones
25
- # tile_height: <number> # Height of each tile in zones
26
- #
27
- # # Host firmware version (optional, overrides auto firmware selection)
28
- # default_firmware_major: <number> # Firmware major version (e.g., 3)
29
- # default_firmware_minor: <number> # Firmware minor version (e.g., 70)
30
- #
31
- # # Other device-specific defaults
32
- # notes: "<string>" # Notes about product
33
- #
34
- # Firmware Version Notes:
35
- # ----------------------
36
- # If default_firmware_major and default_firmware_minor are both specified
37
- # they will be used as the default firmware version when creating devices
38
- # of that type. This overrides the automatic firmware version selection
39
- # based on extended_multizone capability (which defaults to 3.70 for extended
40
- # multizone or 2.60 for non-extended).
41
- #
42
- # Precedence order for firmware version:
43
- # 1. Explicit firmware_version parameter to create_device()
44
- # 2. Product-specific default from this specs.yml file
45
- # 3. Automatic selection based on extended_multizone flag
46
-
47
- products:
48
- # ========================================
49
- # Multizone Products (Linear Strips)
50
- # ========================================
51
-
52
- 31: # Original LIFX Z strip, 2 meters, 8 zones per meter
53
- default_zone_count: 16
54
- min_zone_count: 8
55
- max_zone_count: 16
56
- notes: Original LIFX Z strip, 2 meters, 8 zones per meter
57
-
58
- 32: # LIFX Z with extended multizone firmware support
59
- default_zone_count: 16
60
- min_zone_count: 8
61
- max_zone_count: 16
62
- notes: LIFX Z with extended multizone firmware support
63
-
64
- 38: # LIFX Beam, 8 individual beams, each with 10 zones and up to 2 corners
65
- default_zone_count: 80
66
- min_zone_count: 10
67
- max_zone_count: 82
68
- notes: LIFX Beam, 8 individual beams, each with 10 zones and up to 2 corners
69
-
70
- 117: # LIFX Z US variant
71
- default_zone_count: 16
72
- min_zone_count: 8
73
- max_zone_count: 16
74
- notes: LIFX Z US variant
75
-
76
- 118: # LIFX Z International variant
77
- default_zone_count: 16
78
- min_zone_count: 8
79
- max_zone_count: 16
80
- notes: LIFX Z International variant
81
-
82
- 119: # LIFX Beam US variant
83
- default_zone_count: 80
84
- min_zone_count: 10
85
- max_zone_count: 82
86
- notes: LIFX Beam US variant
87
-
88
- 120: # LIFX Beam International variant
89
- default_zone_count: 80
90
- min_zone_count: 10
91
- max_zone_count: 82
92
- notes: LIFX Beam International variant
93
-
94
- 141: # LIFX Neon flexible light strip
95
- default_zone_count: 24
96
- min_zone_count: 24
97
- max_zone_count: 48
98
- notes: LIFX Neon flexible light strip
99
-
100
- 142: # LIFX Neon International variant
101
- default_zone_count: 24
102
- min_zone_count: 24
103
- max_zone_count: 48
104
- notes: LIFX Neon International variant
105
-
106
- 143: # LIFX String lights
107
- default_zone_count: 36
108
- min_zone_count: 36
109
- max_zone_count: 72
110
- notes: LIFX String lights
111
-
112
- 144: # LIFX String International variant
113
- default_zone_count: 20
114
- min_zone_count: 36
115
- max_zone_count: 72
116
- notes: LIFX String International variant
117
-
118
- 161: # LIFX Outdoor Neon
119
- default_zone_count: 60
120
- min_zone_count: 60
121
- max_zone_count: 120
122
- notes: LIFX Outdoor Neon
123
-
124
- 162: # LIFX Outdoor Neon International variant
125
- default_zone_count: 60
126
- min_zone_count: 60
127
- max_zone_count: 120
128
- notes: LIFX Outdoor Neon International variant
129
-
130
- 203: # LIFX String US (newer model)
131
- default_zone_count: 36
132
- min_zone_count: 36
133
- max_zone_count: 72
134
- notes: LIFX String US (newer model)
135
-
136
- 204: # LIFX String International (newer model)
137
- default_zone_count: 36
138
- min_zone_count: 36
139
- max_zone_count: 72
140
- notes: LIFX String International (newer model)
141
-
142
- 205: # LIFX Indoor Neon US
143
- default_zone_count: 24
144
- min_zone_count: 24
145
- max_zone_count: 48
146
- notes: LIFX Indoor Neon US
147
-
148
- 206: # LIFX Indoor Neon Intl
149
- default_zone_count: 24
150
- min_zone_count: 24
151
- max_zone_count: 48
152
- notes: LIFX Indoor Neon Intl
153
-
154
- 213: # LIFX Permanent Outdoor US
155
- default_zone_count: 30
156
- min_zone_count: 30
157
- max_zone_count: 120
158
- notes: LIFX Permanent Outdoor US
159
-
160
- 214: # LIFX Permanent Outdoor Intl
161
- default_zone_count: 30
162
- min_zone_count: 30
163
- max_zone_count: 120
164
- notes: LIFX Permanent Outdoor Intl
165
-
166
- # ========================================
167
- # Matrix Products (Tiles, Candles, etc.)
168
- # ========================================
169
-
170
- 55: # LIFX Tile, 8x8 zone matrix, chainable up to 5
171
- default_tile_count: 5
172
- min_tile_count: 1
173
- max_tile_count: 5
174
- tile_width: 8
175
- tile_height: 8
176
- notes: LIFX Tile, 8x8 zone matrix, chainable up to 5
177
-
178
- 57: # LIFX Candle, 5x6 zone matrix, single unit
179
- default_tile_count: 1
180
- min_tile_count: 1
181
- max_tile_count: 1
182
- tile_width: 5
183
- tile_height: 6
184
- notes: LIFX Candle, 5x6 zone matrix, single unit
185
-
186
- 68: # LIFX Candle variant, 5x6 zone matrix
187
- default_tile_count: 1
188
- min_tile_count: 1
189
- max_tile_count: 1
190
- tile_width: 5
191
- tile_height: 6
192
- notes: LIFX Candle variant, 5x6 zone matrix
193
-
194
- 137: # LIFX Candle Color US 5x6 variant
195
- default_tile_count: 1
196
- min_tile_count: 1
197
- max_tile_count: 1
198
- tile_width: 5
199
- tile_height: 6
200
- notes: LIFX Candle Color US 5x6 variant
201
-
202
- 138: # LIFX Candle Colour 5x6 International variant
203
- default_tile_count: 1
204
- min_tile_count: 1
205
- max_tile_count: 1
206
- tile_width: 5
207
- tile_height: 6
208
- notes: LIFX Candle Colour 5x6 International variant
209
-
210
- 171: # LIFX Round Spot, 3x1 matrix
211
- default_tile_count: 1
212
- min_tile_count: 1
213
- max_tile_count: 1
214
- tile_width: 3
215
- tile_height: 1
216
- notes: LIFX Round Spot, 3x1 matrix
217
-
218
- 173: # LIFX Round Path, 3x2 matrix
219
- default_tile_count: 1
220
- min_tile_count: 1
221
- max_tile_count: 1
222
- tile_width: 3
223
- tile_height: 2
224
- notes: LIFX Round Path, 3x2 matrix
225
-
226
- 174: # LIFX Square Path, 3x2 matrix
227
- default_tile_count: 1
228
- min_tile_count: 1
229
- max_tile_count: 1
230
- tile_width: 3
231
- tile_height: 2
232
- notes: LIFX Square Path, 3x2 matrix
233
-
234
- 176: # LIFX Ceiling, 8x8 matrix, zones 1-63: downlight, zone 64: uplight
235
- default_tile_count: 1
236
- min_tile_count: 1
237
- max_tile_count: 1
238
- tile_width: 8
239
- tile_height: 8
240
- default_firmware_major: 4
241
- default_firmware_minor: 10
242
- notes: 'LIFX Ceiling, 8x8 matrix, zones 1-63: downlight, zone 64: uplight'
243
-
244
- 177: # LIFX Ceiling Intl
245
- default_tile_count: 1
246
- min_tile_count: 1
247
- max_tile_count: 1
248
- tile_width: 8
249
- tile_height: 8
250
- default_firmware_major: 4
251
- default_firmware_minor: 10
252
- notes: LIFX Ceiling Intl
253
-
254
- 185: # LIFX Candle Color US
255
- default_tile_count: 1
256
- min_tile_count: 1
257
- max_tile_count: 1
258
- tile_width: 5
259
- tile_height: 6
260
- notes: LIFX Candle Color US
261
-
262
- 186: # LIFX Candle Colour Intl
263
- default_tile_count: 1
264
- min_tile_count: 1
265
- max_tile_count: 1
266
- tile_width: 5
267
- tile_height: 6
268
- notes: LIFX Candle Colour Intl
269
-
270
- 201: # LIFX Ceiling 13x26" US
271
- default_tile_count: 1
272
- min_tile_count: 1
273
- max_tile_count: 1
274
- tile_width: 16
275
- tile_height: 8
276
- default_firmware_major: 4
277
- default_firmware_minor: 10
278
- notes: LIFX Ceiling 13x26" US
279
-
280
- 202: # LIFX Ceiling 13x26" Intl
281
- default_tile_count: 1
282
- min_tile_count: 1
283
- max_tile_count: 1
284
- tile_width: 16
285
- tile_height: 8
286
- default_firmware_major: 4
287
- default_firmware_minor: 10
288
- notes: LIFX Ceiling 13x26" Intl
289
-
290
- 215: # LIFX Candle Color US
291
- default_tile_count: 1
292
- min_tile_count: 1
293
- max_tile_count: 1
294
- tile_width: 5
295
- tile_height: 6
296
- notes: LIFX Candle Color US
297
-
298
- 216: # LIFX Candle Colour Intl
299
- default_tile_count: 1
300
- min_tile_count: 1
301
- max_tile_count: 1
302
- tile_width: 5
303
- tile_height: 6
304
- notes: LIFX Candle Colour Intl
305
-
306
- 217: # LIFX Tube US
307
- default_tile_count: 1
308
- min_tile_count: 1
309
- max_tile_count: 1
310
- tile_width: 5
311
- tile_height: 11
312
- notes: LIFX Tube US
313
-
314
- 218: # LIFX Tube Intl
315
- default_tile_count: 1
316
- min_tile_count: 1
317
- max_tile_count: 1
318
- tile_width: 5
319
- tile_height: 11
320
- notes: LIFX Tube Intl
321
-
322
- 219: # LIFX Luna US
323
- default_tile_count: 1
324
- min_tile_count: 1
325
- max_tile_count: 1
326
- tile_width: 7
327
- tile_height: 5
328
- notes: LIFX Luna US
329
-
330
- 220: # LIFX Luna Intl
331
- default_tile_count: 1
332
- min_tile_count: 1
333
- max_tile_count: 1
334
- tile_width: 7
335
- tile_height: 5
336
- notes: LIFX Luna Intl
337
-
338
- 221: # LIFX Round Spot Intl
339
- default_tile_count: 1
340
- min_tile_count: 1
341
- max_tile_count: 1
342
- tile_width: 3
343
- tile_height: 1
344
- notes: LIFX Round Spot Intl
345
-
346
- 222: # LIFX Round Path Intl
347
- default_tile_count: 1
348
- min_tile_count: 1
349
- max_tile_count: 1
350
- tile_width: 3
351
- tile_height: 2
352
- notes: LIFX Round Path Intl
353
-
354
- # ========================================
355
- # Switch Products (Relays)
356
- # ========================================
357
-
358
- 70: # LIFX Switch
359
- relay_count: 2
360
- default_firmware_major: 4
361
- default_firmware_minor: 100
362
- notes: LIFX Switch
363
-
364
- 71: # LIFX Switch
365
- relay_count: 2
366
- default_firmware_major: 4
367
- default_firmware_minor: 100
368
- notes: LIFX Switch
369
-
370
- 89: # LIFX Switch
371
- relay_count: 2
372
- default_firmware_major: 4
373
- default_firmware_minor: 100
374
- notes: LIFX Switch
375
-
376
- 115: # LIFX Switch
377
- relay_count: 2
378
- default_firmware_major: 4
379
- default_firmware_minor: 100
380
- notes: LIFX Switch
381
-
382
- 116: # LIFX Switch
383
- relay_count: 2
384
- default_firmware_major: 4
385
- default_firmware_minor: 100
386
- notes: LIFX Switch
@@ -1 +0,0 @@
1
- """LIFX protocol implementation and code generation."""