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
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: lifx-emulator
3
+ Version: 3.1.0
4
+ Summary: Standalone LIFX Emulator with CLI and HTTP management API
5
+ Author-email: Avi Miller <me@dje.li>
6
+ Maintainer-email: Avi Miller <me@dje.li>
7
+ License-Expression: UPL-1.0
8
+ Classifier: Environment :: Console
9
+ Classifier: Framework :: AsyncIO
10
+ Classifier: Framework :: FastAPI
11
+ Classifier: Framework :: Pytest
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: cyclopts>=4.2.0
24
+ Requires-Dist: fastapi>=0.115.0
25
+ Requires-Dist: lifx-emulator-core>=2.4.0
26
+ Requires-Dist: rich>=14.2.0
27
+ Requires-Dist: uvicorn>=0.34.0
28
+ Description-Content-Type: text/markdown
29
+
30
+ # lifx-emulator
31
+
32
+ Standalone LIFX device emulator with CLI and HTTP management API.
33
+
34
+ This package provides a ready-to-run emulator for testing LIFX LAN protocol libraries. It includes a command-line interface and an optional HTTP API for runtime device management.
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install lifx-emulator
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ```bash
45
+ # Start with default configuration (1 color light)
46
+ lifx-emulator
47
+
48
+ # Create multiple device types
49
+ lifx-emulator --color 2 --multizone 1 --tile 1
50
+
51
+ # Enable HTTP management API
52
+ lifx-emulator --api
53
+
54
+ # List available LIFX products
55
+ lifx-emulator list-products
56
+
57
+ # Create devices by product ID
58
+ lifx-emulator --product 27 --product 38 --product 55
59
+ ```
60
+
61
+ ## Features
62
+
63
+ - Command-line interface for quick emulator setup
64
+ - HTTP management API with web dashboard
65
+ - Real-time device monitoring and management
66
+ - Support for all LIFX device types (color, multizone, tile, infrared, HEV, switch)
67
+ - Persistent device state across restarts
68
+ - Testing scenarios for protocol edge cases
69
+
70
+ ## HTTP Management API
71
+
72
+ Enable with `--api` to get:
73
+
74
+ - **Web Dashboard**: `http://localhost:8080` - Real-time monitoring UI
75
+ - **REST API**: Device management, statistics, and scenario control
76
+ - **OpenAPI Docs**: `http://localhost:8080/docs` - Interactive API documentation
77
+
78
+ ```bash
79
+ # Start with API server
80
+ lifx-emulator --color 2 --api --api-port 9090
81
+
82
+ # Add a device via API
83
+ curl -X POST http://localhost:9090/api/devices \
84
+ -H "Content-Type: application/json" \
85
+ -d '{"product_id": 27}'
86
+ ```
87
+
88
+ ## Documentation
89
+
90
+ Full documentation is available at: **https://djelibeybi.github.io/lifx-emulator**
91
+
92
+ - [Installation Guide](https://djelibeybi.github.io/lifx-emulator/getting-started/installation/)
93
+ - [CLI Reference](https://djelibeybi.github.io/lifx-emulator/cli/cli-reference/)
94
+ - [Web Interface](https://djelibeybi.github.io/lifx-emulator/cli/web-interface/)
95
+ - [REST API](https://djelibeybi.github.io/lifx-emulator/cli/device-management-api/)
96
+
97
+ ## Related Packages
98
+
99
+ - **[lifx-emulator-core](https://pypi.org/project/lifx-emulator-core/)**: Core library for embedding the emulator in your own projects
100
+
101
+ ## License
102
+
103
+ [UPL-1.0](https://opensource.org/licenses/UPL)
@@ -0,0 +1,19 @@
1
+ lifx_emulator_app/__init__.py,sha256=AJahGiWKb8U8yLQbJX21takbf-SoxDxMOGxjJeM7M5c,222
2
+ lifx_emulator_app/__main__.py,sha256=f_VwgZfwOdp3zQshv8JQqBX7gocE9ATZbZ3wQndlBvo,22060
3
+ lifx_emulator_app/api/__init__.py,sha256=bpdhugx7PAop5IQhkKnWE-a1hfI9gJoJiNRG2CCWe5A,651
4
+ lifx_emulator_app/api/app.py,sha256=QyHSzb0BYk341PlWLIcgHJHOYnFetcG0FQsVlVY_OX8,5126
5
+ lifx_emulator_app/api/models.py,sha256=fiX9hDmR1C12tzet-kGPmbaG_qiZfiprgy-uxwIcEsE,3970
6
+ lifx_emulator_app/api/mappers/__init__.py,sha256=-lGAg-s16eTMl2_D-3bPu-EMqD2kaPzXHqSrKCnmW2w,156
7
+ lifx_emulator_app/api/mappers/device_mapper.py,sha256=WAo-_PJ2kX3J4GUW_Sjoype1d_uaIh-PtXPfMUAujUY,4155
8
+ lifx_emulator_app/api/routers/__init__.py,sha256=TKPypociZ_uo2YCyW5zIeUfalUh_PkzCVt31MHg9ZPc,381
9
+ lifx_emulator_app/api/routers/devices.py,sha256=5_0Id09Z6yOB3s-uAEAU4oNribV49IitC0-_Bmx3bCk,4218
10
+ lifx_emulator_app/api/routers/monitoring.py,sha256=i82_s61caYd9UvMb4MqWPLP7LuFh5KN8Qkw4_dZr3O0,1460
11
+ lifx_emulator_app/api/routers/scenarios.py,sha256=pWXTliY9MIk-DCxDOZ1cjeAFgHn79ExvY-6lj-yHPWk,9747
12
+ lifx_emulator_app/api/services/__init__.py,sha256=cdKZItYE-KkMX44V9xJW_PHHnJoAw5I7Uw1a1YKHgMI,285
13
+ lifx_emulator_app/api/services/device_service.py,sha256=A2rCuZ1aAJ1tThKM6BYorKAjlaDgDaFCT5C9KUHfAvc,6303
14
+ lifx_emulator_app/api/static/dashboard.js,sha256=eJOtBzTLRPYmMVuft5GC8r7Ae6x_JWZs9nqrmKaOILA,20177
15
+ lifx_emulator_app/api/templates/dashboard.html,sha256=6vqMpsAtCBXASHOLnXn3_uZ-U5r7-P3FPo8_NJiMitk,10194
16
+ lifx_emulator-3.1.0.dist-info/METADATA,sha256=hOg5mr27_HE83CfaYyjaF_5N4BClqSa3iYQ8kLsr2ec,3225
17
+ lifx_emulator-3.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
18
+ lifx_emulator-3.1.0.dist-info/entry_points.txt,sha256=tNZHeJTPUXNxu_nuk99ArXLKgwYLhIVVxN7YiaiXBOA,66
19
+ lifx_emulator-3.1.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ lifx-emulator = lifx_emulator_app.__main__:main
@@ -0,0 +1,10 @@
1
+ """LIFX Emulator Application
2
+
3
+ Standalone CLI and HTTP management API for the LIFX Emulator.
4
+ """
5
+
6
+ from importlib.metadata import version as get_version
7
+
8
+ __version__ = get_version("lifx-emulator")
9
+
10
+ __all__ = ["__version__"]
@@ -6,8 +6,6 @@ import signal
6
6
  from typing import Annotated
7
7
 
8
8
  import cyclopts
9
- from rich.logging import RichHandler
10
-
11
9
  from lifx_emulator.constants import LIFX_UDP_PORT
12
10
  from lifx_emulator.devices import (
13
11
  DEFAULT_STORAGE_DIR,
@@ -28,6 +26,7 @@ from lifx_emulator.products.registry import get_registry
28
26
  from lifx_emulator.repositories import DeviceRepository
29
27
  from lifx_emulator.scenarios import ScenarioPersistenceAsyncFile
30
28
  from lifx_emulator.server import EmulatedLifxServer
29
+ from rich.logging import RichHandler
31
30
 
32
31
  app = cyclopts.App(
33
32
  name="lifx-emulator",
@@ -529,7 +528,7 @@ async def run(
529
528
  # Start API server if enabled
530
529
  api_task = None
531
530
  if api:
532
- from lifx_emulator.api import run_api_server
531
+ from lifx_emulator_app.api import run_api_server
533
532
 
534
533
  logger.info("Starting HTTP API server on http://%s:%s", api_host, api_port)
535
534
  api_task = asyncio.create_task(run_api_server(server, api_host, api_port))
@@ -10,7 +10,7 @@ of concerns.
10
10
  """
11
11
 
12
12
  # Import from new refactored structure
13
- from lifx_emulator.api.app import create_api_app, run_api_server
13
+ from lifx_emulator_app.api.app import create_api_app, run_api_server
14
14
 
15
15
  # Note: HTML_UI remains in the old lifx_emulator/api.py file temporarily
16
16
  # TODO: Phase 1.1d - extract HTML template to separate file
@@ -14,19 +14,21 @@ from typing import TYPE_CHECKING
14
14
 
15
15
  from fastapi import FastAPI, Request
16
16
  from fastapi.responses import HTMLResponse
17
+ from fastapi.staticfiles import StaticFiles
17
18
  from fastapi.templating import Jinja2Templates
18
19
 
19
20
  if TYPE_CHECKING:
20
21
  from lifx_emulator.server import EmulatedLifxServer
21
22
 
22
- from lifx_emulator.api.routers.devices import create_devices_router
23
- from lifx_emulator.api.routers.monitoring import create_monitoring_router
24
- from lifx_emulator.api.routers.scenarios import create_scenarios_router
23
+ from lifx_emulator_app.api.routers.devices import create_devices_router
24
+ from lifx_emulator_app.api.routers.monitoring import create_monitoring_router
25
+ from lifx_emulator_app.api.routers.scenarios import create_scenarios_router
25
26
 
26
27
  logger = logging.getLogger(__name__)
27
28
 
28
- # Template directory for web UI
29
+ # Asset directories for web UI
29
30
  TEMPLATES_DIR = Path(__file__).parent / "templates"
31
+ STATIC_DIR = Path(__file__).parent / "static"
30
32
  templates = Jinja2Templates(directory=str(TEMPLATES_DIR))
31
33
 
32
34
 
@@ -102,6 +104,9 @@ The API is organized into three main routers:
102
104
  """Serve embedded web UI dashboard."""
103
105
  return templates.TemplateResponse(request, "dashboard.html")
104
106
 
107
+ # Mount static files for JS/CSS assets (cached by browsers)
108
+ app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
109
+
105
110
  # Include routers with server dependency injection
106
111
  monitoring_router = create_monitoring_router(server)
107
112
  devices_router = create_devices_router(server)
@@ -1,5 +1,5 @@
1
1
  """Mappers for converting domain models to API models."""
2
2
 
3
- from lifx_emulator.api.mappers.device_mapper import DeviceMapper
3
+ from lifx_emulator_app.api.mappers.device_mapper import DeviceMapper
4
4
 
5
5
  __all__ = ["DeviceMapper"]
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
7
7
  if TYPE_CHECKING:
8
8
  from lifx_emulator.devices import EmulatedLifxDevice
9
9
 
10
- from lifx_emulator.api.models import ColorHsbk, DeviceInfo
10
+ from lifx_emulator_app.api.models import ColorHsbk, DeviceInfo
11
11
 
12
12
 
13
13
  class DeviceMapper:
@@ -1,9 +1,8 @@
1
1
  """Pydantic models for API requests and responses."""
2
2
 
3
- from pydantic import BaseModel, Field, field_validator
4
-
5
3
  # Import shared domain models
6
4
  from lifx_emulator.scenarios import ScenarioConfig
5
+ from pydantic import BaseModel, Field, field_validator
7
6
 
8
7
 
9
8
  class DeviceCreateRequest(BaseModel):
@@ -0,0 +1,11 @@
1
+ """API routers for LIFX emulator endpoints."""
2
+
3
+ from lifx_emulator_app.api.routers.devices import create_devices_router
4
+ from lifx_emulator_app.api.routers.monitoring import create_monitoring_router
5
+ from lifx_emulator_app.api.routers.scenarios import create_scenarios_router
6
+
7
+ __all__ = [
8
+ "create_monitoring_router",
9
+ "create_devices_router",
10
+ "create_scenarios_router",
11
+ ]
@@ -9,8 +9,8 @@ from fastapi import APIRouter, HTTPException
9
9
  if TYPE_CHECKING:
10
10
  from lifx_emulator.server import EmulatedLifxServer
11
11
 
12
- from lifx_emulator.api.models import DeviceCreateRequest, DeviceInfo
13
- from lifx_emulator.api.services.device_service import (
12
+ from lifx_emulator_app.api.models import DeviceCreateRequest, DeviceInfo
13
+ from lifx_emulator_app.api.services.device_service import (
14
14
  DeviceAlreadyExistsError,
15
15
  DeviceCreationError,
16
16
  DeviceNotFoundError,
@@ -9,7 +9,7 @@ from fastapi import APIRouter
9
9
  if TYPE_CHECKING:
10
10
  from lifx_emulator.server import EmulatedLifxServer
11
11
 
12
- from lifx_emulator.api.models import ActivityEvent, ServerStats
12
+ from lifx_emulator_app.api.models import ActivityEvent, ServerStats
13
13
 
14
14
 
15
15
  def create_monitoring_router(server: EmulatedLifxServer) -> APIRouter:
@@ -9,7 +9,7 @@ from fastapi import APIRouter, HTTPException
9
9
  if TYPE_CHECKING:
10
10
  from lifx_emulator.server import EmulatedLifxServer
11
11
 
12
- from lifx_emulator.api.models import ScenarioConfig, ScenarioResponse
12
+ from lifx_emulator_app.api.models import ScenarioConfig, ScenarioResponse
13
13
 
14
14
 
15
15
  def _validate_device_serial(serial: str) -> bool:
@@ -0,0 +1,8 @@
1
+ """Business logic services for API endpoints."""
2
+
3
+ from lifx_emulator_app.api.services.device_service import DeviceService
4
+
5
+ # TODO: Create ScenarioService (Phase 1.1b completion)
6
+ # from lifx_emulator_app.api.services.scenario_service import ScenarioService
7
+
8
+ __all__ = ["DeviceService"]
@@ -13,10 +13,11 @@ from typing import TYPE_CHECKING
13
13
  if TYPE_CHECKING:
14
14
  from lifx_emulator.server import EmulatedLifxServer
15
15
 
16
- from lifx_emulator.api.mappers import DeviceMapper
17
- from lifx_emulator.api.models import DeviceCreateRequest, DeviceInfo
18
16
  from lifx_emulator.factories import create_device
19
17
 
18
+ from lifx_emulator_app.api.mappers import DeviceMapper
19
+ from lifx_emulator_app.api.models import DeviceCreateRequest, DeviceInfo
20
+
20
21
  logger = logging.getLogger(__name__)
21
22
 
22
23