lifx-emulator 2.4.0__tar.gz → 3.1.0__tar.gz
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-3.1.0/CHANGELOG.md +43 -0
- lifx_emulator-3.1.0/PKG-INFO +103 -0
- lifx_emulator-3.1.0/README.md +74 -0
- {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/pyproject.toml +25 -84
- lifx_emulator-3.1.0/src/lifx_emulator_app/__init__.py +10 -0
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/__main__.py +2 -3
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/__init__.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/app.py +9 -4
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/mappers/__init__.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/mappers/device_mapper.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/models.py +1 -2
- lifx_emulator-3.1.0/src/lifx_emulator_app/api/routers/__init__.py +11 -0
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/routers/devices.py +2 -2
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/routers/monitoring.py +1 -1
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/routers/scenarios.py +1 -1
- lifx_emulator-3.1.0/src/lifx_emulator_app/api/services/__init__.py +8 -0
- {lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/services/device_service.py +3 -2
- lifx_emulator-3.1.0/src/lifx_emulator_app/api/static/dashboard.js +588 -0
- lifx_emulator-3.1.0/src/lifx_emulator_app/api/templates/dashboard.html +357 -0
- lifx_emulator-3.1.0/tests/conftest.py +9 -0
- {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_api.py +3 -4
- {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_api_validation.py +1 -2
- {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_cli.py +41 -42
- {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/tests/test_cli_validation.py +1 -2
- lifx_emulator-2.4.0/.github/workflows/ci.yml +0 -188
- lifx_emulator-2.4.0/.github/workflows/docs.yml +0 -111
- lifx_emulator-2.4.0/.pre-commit-config.yaml +0 -101
- lifx_emulator-2.4.0/CLAUDE.md +0 -957
- lifx_emulator-2.4.0/LICENSE +0 -35
- lifx_emulator-2.4.0/PKG-INFO +0 -107
- lifx_emulator-2.4.0/README.md +0 -79
- lifx_emulator-2.4.0/docs/advanced/device-management-api.md +0 -658
- lifx_emulator-2.4.0/docs/advanced/index.md +0 -145
- lifx_emulator-2.4.0/docs/advanced/scenario-api.md +0 -809
- lifx_emulator-2.4.0/docs/advanced/scenarios.md +0 -406
- lifx_emulator-2.4.0/docs/advanced/storage.md +0 -291
- lifx_emulator-2.4.0/docs/api/device.md +0 -489
- lifx_emulator-2.4.0/docs/api/factories.md +0 -340
- lifx_emulator-2.4.0/docs/api/index.md +0 -265
- lifx_emulator-2.4.0/docs/api/products.md +0 -539
- lifx_emulator-2.4.0/docs/api/protocol.md +0 -718
- lifx_emulator-2.4.0/docs/api/server.md +0 -437
- lifx_emulator-2.4.0/docs/api/storage.md +0 -680
- lifx_emulator-2.4.0/docs/architecture/device-state.md +0 -3
- lifx_emulator-2.4.0/docs/architecture/index.md +0 -76
- lifx_emulator-2.4.0/docs/architecture/overview.md +0 -373
- lifx_emulator-2.4.0/docs/architecture/packet-flow.md +0 -3
- lifx_emulator-2.4.0/docs/architecture/protocol.md +0 -3
- lifx_emulator-2.4.0/docs/assets/favicon.png +0 -1
- lifx_emulator-2.4.0/docs/changelog.md +0 -99
- lifx_emulator-2.4.0/docs/faq.md +0 -574
- lifx_emulator-2.4.0/docs/getting-started/cli.md +0 -483
- lifx_emulator-2.4.0/docs/getting-started/index.md +0 -83
- lifx_emulator-2.4.0/docs/getting-started/installation.md +0 -165
- lifx_emulator-2.4.0/docs/getting-started/quickstart.md +0 -182
- lifx_emulator-2.4.0/docs/guide/best-practices.md +0 -696
- lifx_emulator-2.4.0/docs/guide/device-types.md +0 -442
- lifx_emulator-2.4.0/docs/guide/framebuffers.md +0 -209
- lifx_emulator-2.4.0/docs/guide/index.md +0 -90
- lifx_emulator-2.4.0/docs/guide/integration-testing.md +0 -788
- lifx_emulator-2.4.0/docs/guide/products-and-specs.md +0 -229
- lifx_emulator-2.4.0/docs/guide/testing-scenarios.md +0 -673
- lifx_emulator-2.4.0/docs/guide/web-interface.md +0 -490
- lifx_emulator-2.4.0/docs/index.md +0 -169
- lifx_emulator-2.4.0/docs/reference/glossary.md +0 -352
- lifx_emulator-2.4.0/docs/reference/troubleshooting.md +0 -845
- lifx_emulator-2.4.0/docs/stylesheets/extra.css +0 -37
- lifx_emulator-2.4.0/docs/tutorials/01-first-device.md +0 -261
- lifx_emulator-2.4.0/docs/tutorials/02-basic.md +0 -345
- lifx_emulator-2.4.0/docs/tutorials/03-integration.md +0 -642
- lifx_emulator-2.4.0/docs/tutorials/04-advanced-scenarios.md +0 -583
- lifx_emulator-2.4.0/docs/tutorials/05-cicd.md +0 -696
- lifx_emulator-2.4.0/docs/tutorials/index.md +0 -108
- lifx_emulator-2.4.0/mkdocs.yml +0 -266
- lifx_emulator-2.4.0/renovate.json +0 -161
- lifx_emulator-2.4.0/src/lifx_emulator/__init__.py +0 -31
- lifx_emulator-2.4.0/src/lifx_emulator/api/routers/__init__.py +0 -11
- lifx_emulator-2.4.0/src/lifx_emulator/api/services/__init__.py +0 -8
- lifx_emulator-2.4.0/src/lifx_emulator/api/templates/dashboard.html +0 -899
- lifx_emulator-2.4.0/src/lifx_emulator/constants.py +0 -33
- lifx_emulator-2.4.0/src/lifx_emulator/devices/__init__.py +0 -37
- lifx_emulator-2.4.0/src/lifx_emulator/devices/device.py +0 -395
- lifx_emulator-2.4.0/src/lifx_emulator/devices/manager.py +0 -256
- lifx_emulator-2.4.0/src/lifx_emulator/devices/observers.py +0 -139
- lifx_emulator-2.4.0/src/lifx_emulator/devices/persistence.py +0 -308
- lifx_emulator-2.4.0/src/lifx_emulator/devices/state_restorer.py +0 -259
- lifx_emulator-2.4.0/src/lifx_emulator/devices/state_serializer.py +0 -157
- lifx_emulator-2.4.0/src/lifx_emulator/devices/states.py +0 -381
- lifx_emulator-2.4.0/src/lifx_emulator/factories/__init__.py +0 -39
- lifx_emulator-2.4.0/src/lifx_emulator/factories/builder.py +0 -375
- lifx_emulator-2.4.0/src/lifx_emulator/factories/default_config.py +0 -158
- lifx_emulator-2.4.0/src/lifx_emulator/factories/factory.py +0 -252
- lifx_emulator-2.4.0/src/lifx_emulator/factories/firmware_config.py +0 -77
- lifx_emulator-2.4.0/src/lifx_emulator/factories/serial_generator.py +0 -82
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/__init__.py +0 -39
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/base.py +0 -49
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/device_handlers.py +0 -322
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/light_handlers.py +0 -503
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/multizone_handlers.py +0 -249
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/registry.py +0 -110
- lifx_emulator-2.4.0/src/lifx_emulator/handlers/tile_handlers.py +0 -488
- lifx_emulator-2.4.0/src/lifx_emulator/products/__init__.py +0 -28
- lifx_emulator-2.4.0/src/lifx_emulator/products/generator.py +0 -1079
- lifx_emulator-2.4.0/src/lifx_emulator/products/registry.py +0 -1530
- lifx_emulator-2.4.0/src/lifx_emulator/products/specs.py +0 -284
- lifx_emulator-2.4.0/src/lifx_emulator/products/specs.yml +0 -386
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/__init__.py +0 -1
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/base.py +0 -446
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/const.py +0 -8
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/generator.py +0 -1384
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/header.py +0 -159
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/packets.py +0 -1351
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/protocol_types.py +0 -817
- lifx_emulator-2.4.0/src/lifx_emulator/protocol/serializer.py +0 -379
- lifx_emulator-2.4.0/src/lifx_emulator/repositories/__init__.py +0 -22
- lifx_emulator-2.4.0/src/lifx_emulator/repositories/device_repository.py +0 -155
- lifx_emulator-2.4.0/src/lifx_emulator/repositories/storage_backend.py +0 -107
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/__init__.py +0 -22
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/manager.py +0 -322
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/models.py +0 -112
- lifx_emulator-2.4.0/src/lifx_emulator/scenarios/persistence.py +0 -241
- lifx_emulator-2.4.0/src/lifx_emulator/server.py +0 -464
- lifx_emulator-2.4.0/tests/conftest.py +0 -239
- lifx_emulator-2.4.0/tests/test_async_storage.py +0 -246
- lifx_emulator-2.4.0/tests/test_backwards_compatibility.py +0 -943
- lifx_emulator-2.4.0/tests/test_device.py +0 -541
- lifx_emulator-2.4.0/tests/test_device_edge_cases.py +0 -231
- lifx_emulator-2.4.0/tests/test_device_handlers_extended.py +0 -723
- lifx_emulator-2.4.0/tests/test_device_manager.py +0 -288
- lifx_emulator-2.4.0/tests/test_handler_registry.py +0 -103
- lifx_emulator-2.4.0/tests/test_integration.py +0 -463
- lifx_emulator-2.4.0/tests/test_light_handlers_extended.py +0 -788
- lifx_emulator-2.4.0/tests/test_multizone_handlers_extended.py +0 -560
- lifx_emulator-2.4.0/tests/test_observers.py +0 -164
- lifx_emulator-2.4.0/tests/test_products_generator.py +0 -1120
- lifx_emulator-2.4.0/tests/test_products_specs.py +0 -366
- lifx_emulator-2.4.0/tests/test_protocol_generator.py +0 -815
- lifx_emulator-2.4.0/tests/test_protocol_types_coverage.py +0 -118
- lifx_emulator-2.4.0/tests/test_repositories.py +0 -131
- lifx_emulator-2.4.0/tests/test_scenario_manager.py +0 -431
- lifx_emulator-2.4.0/tests/test_scenario_persistence.py +0 -271
- lifx_emulator-2.4.0/tests/test_serializer.py +0 -460
- lifx_emulator-2.4.0/tests/test_server.py +0 -545
- lifx_emulator-2.4.0/tests/test_state_restorer.py +0 -270
- lifx_emulator-2.4.0/tests/test_switch_devices.py +0 -335
- lifx_emulator-2.4.0/tests/test_tile_handlers_extended.py +0 -1265
- lifx_emulator-2.4.0/uv.lock +0 -1411
- {lifx_emulator-2.4.0 → lifx_emulator-3.1.0}/.gitignore +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
<!-- version list -->
|
|
4
|
+
|
|
5
|
+
## v3.1.0 (2026-01-11)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- Add Python 3.10 support
|
|
10
|
+
([`c19eee5`](https://github.com/Djelibeybi/lifx-emulator/commit/c19eee5181fc3e0e3b4ef9fc3e6d47308dce7a0f))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## v3.0.2 (2025-12-24)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
- **api**: Eliminate XSS vulnerabilities and extract dashboard JavaScript
|
|
18
|
+
([`8302a09`](https://github.com/Djelibeybi/lifx-emulator/commit/8302a0947b326e73f6c2f15de85986a464a307ad))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## v3.0.1 (2025-11-26)
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
- Adjust uv build for new monorepo layout
|
|
26
|
+
([`a0d5b7c`](https://github.com/Djelibeybi/lifx-emulator/commit/a0d5b7c1c1ab5659acc8554931f6c441654add05))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## v3.0.0 (2025-11-26)
|
|
30
|
+
|
|
31
|
+
### Refactoring
|
|
32
|
+
|
|
33
|
+
- Split into monorepo with separate library and CLI packages
|
|
34
|
+
([`402fe6e`](https://github.com/Djelibeybi/lifx-emulator/commit/402fe6e6c42e4fb730d076cd4dd0bfe7743b2c57))
|
|
35
|
+
|
|
36
|
+
### Breaking Changes
|
|
37
|
+
|
|
38
|
+
- The project is now split into two packages:
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## v2.4.0 (2025-11-26)
|
|
42
|
+
|
|
43
|
+
- Initial Release
|
|
@@ -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,74 @@
|
|
|
1
|
+
# lifx-emulator
|
|
2
|
+
|
|
3
|
+
Standalone LIFX device emulator with CLI and HTTP management API.
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install lifx-emulator
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Start with default configuration (1 color light)
|
|
17
|
+
lifx-emulator
|
|
18
|
+
|
|
19
|
+
# Create multiple device types
|
|
20
|
+
lifx-emulator --color 2 --multizone 1 --tile 1
|
|
21
|
+
|
|
22
|
+
# Enable HTTP management API
|
|
23
|
+
lifx-emulator --api
|
|
24
|
+
|
|
25
|
+
# List available LIFX products
|
|
26
|
+
lifx-emulator list-products
|
|
27
|
+
|
|
28
|
+
# Create devices by product ID
|
|
29
|
+
lifx-emulator --product 27 --product 38 --product 55
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Command-line interface for quick emulator setup
|
|
35
|
+
- HTTP management API with web dashboard
|
|
36
|
+
- Real-time device monitoring and management
|
|
37
|
+
- Support for all LIFX device types (color, multizone, tile, infrared, HEV, switch)
|
|
38
|
+
- Persistent device state across restarts
|
|
39
|
+
- Testing scenarios for protocol edge cases
|
|
40
|
+
|
|
41
|
+
## HTTP Management API
|
|
42
|
+
|
|
43
|
+
Enable with `--api` to get:
|
|
44
|
+
|
|
45
|
+
- **Web Dashboard**: `http://localhost:8080` - Real-time monitoring UI
|
|
46
|
+
- **REST API**: Device management, statistics, and scenario control
|
|
47
|
+
- **OpenAPI Docs**: `http://localhost:8080/docs` - Interactive API documentation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Start with API server
|
|
51
|
+
lifx-emulator --color 2 --api --api-port 9090
|
|
52
|
+
|
|
53
|
+
# Add a device via API
|
|
54
|
+
curl -X POST http://localhost:9090/api/devices \
|
|
55
|
+
-H "Content-Type: application/json" \
|
|
56
|
+
-d '{"product_id": 27}'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Documentation
|
|
60
|
+
|
|
61
|
+
Full documentation is available at: **https://djelibeybi.github.io/lifx-emulator**
|
|
62
|
+
|
|
63
|
+
- [Installation Guide](https://djelibeybi.github.io/lifx-emulator/getting-started/installation/)
|
|
64
|
+
- [CLI Reference](https://djelibeybi.github.io/lifx-emulator/cli/cli-reference/)
|
|
65
|
+
- [Web Interface](https://djelibeybi.github.io/lifx-emulator/cli/web-interface/)
|
|
66
|
+
- [REST API](https://djelibeybi.github.io/lifx-emulator/cli/device-management-api/)
|
|
67
|
+
|
|
68
|
+
## Related Packages
|
|
69
|
+
|
|
70
|
+
- **[lifx-emulator-core](https://pypi.org/project/lifx-emulator-core/)**: Core library for embedding the emulator in your own projects
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
[UPL-1.0](https://opensource.org/licenses/UPL)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "lifx-emulator"
|
|
3
|
-
version = "
|
|
4
|
-
description = "LIFX Emulator
|
|
3
|
+
version = "3.1.0"
|
|
4
|
+
description = "Standalone LIFX Emulator with CLI and HTTP management API"
|
|
5
5
|
readme = "README.md"
|
|
6
|
-
requires-python = ">=3.
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
7
|
dependencies = [
|
|
8
|
+
"lifx-emulator-core>=2.4.0",
|
|
8
9
|
"cyclopts>=4.2.0",
|
|
9
10
|
"fastapi>=0.115.0",
|
|
10
|
-
"pyyaml>=6.0.3",
|
|
11
11
|
"rich>=14.2.0",
|
|
12
12
|
"uvicorn>=0.34.0",
|
|
13
13
|
]
|
|
@@ -20,79 +20,35 @@ maintainers = [
|
|
|
20
20
|
{name = "Avi Miller", email = "me@dje.li"}
|
|
21
21
|
]
|
|
22
22
|
classifiers = [
|
|
23
|
+
"Environment :: Console",
|
|
23
24
|
"Framework :: AsyncIO",
|
|
25
|
+
"Framework :: FastAPI",
|
|
24
26
|
"Framework :: Pytest",
|
|
25
27
|
"Intended Audience :: Developers",
|
|
26
28
|
"Natural Language :: English",
|
|
27
29
|
"Operating System :: OS Independent",
|
|
30
|
+
"Programming Language :: Python :: 3.10",
|
|
28
31
|
"Programming Language :: Python :: 3.11",
|
|
29
32
|
"Programming Language :: Python :: 3.12",
|
|
30
33
|
"Programming Language :: Python :: 3.13",
|
|
31
34
|
"Programming Language :: Python :: 3.14",
|
|
32
|
-
"Topic :: Software Development ::
|
|
33
|
-
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
35
|
+
"Topic :: Software Development :: Testing",
|
|
34
36
|
"Typing :: Typed"
|
|
35
37
|
]
|
|
36
38
|
|
|
37
39
|
[project.scripts]
|
|
38
|
-
lifx-emulator = "
|
|
39
|
-
|
|
40
|
-
[dependency-groups]
|
|
41
|
-
dev = [
|
|
42
|
-
"hatchling>=1.27.0",
|
|
43
|
-
"httpx>=0.28.0",
|
|
44
|
-
"pyright>=1.1.407",
|
|
45
|
-
"pytest>=8.4.2",
|
|
46
|
-
"pytest-asyncio>=0.24.0",
|
|
47
|
-
"pytest-cov>=7.0.0",
|
|
48
|
-
"pytest-sugar>=1.1.1",
|
|
49
|
-
"ruff>=0.14.2",
|
|
50
|
-
"mkdocs>=1.6.0",
|
|
51
|
-
"mkdocs-material>=9.6.0",
|
|
52
|
-
"mkdocstrings[python]>=0.27.0",
|
|
53
|
-
"mkdocs-git-revision-date-localized-plugin>=1.4.0",
|
|
54
|
-
"mkdocs-llmstxt>=0.3.0",
|
|
55
|
-
]
|
|
40
|
+
lifx-emulator = "lifx_emulator_app.__main__:main"
|
|
56
41
|
|
|
57
42
|
[build-system]
|
|
58
43
|
requires = ["hatchling"]
|
|
59
44
|
build-backend = "hatchling.build"
|
|
60
45
|
|
|
61
46
|
[tool.hatch.build.targets.wheel]
|
|
62
|
-
packages = ["src/
|
|
63
|
-
|
|
64
|
-
[tool.ruff]
|
|
65
|
-
line-length = 88
|
|
66
|
-
indent-width = 4
|
|
67
|
-
target-version = "py311"
|
|
68
|
-
|
|
69
|
-
[tool.ruff.format]
|
|
70
|
-
quote-style = "double"
|
|
71
|
-
indent-style = "space"
|
|
72
|
-
docstring-code-format = true
|
|
73
|
-
docstring-code-line-length = "dynamic"
|
|
74
|
-
|
|
75
|
-
[tool.ruff.lint]
|
|
76
|
-
select = ["E", "F", "I", "N", "W", "UP"]
|
|
77
|
-
ignore = []
|
|
78
|
-
|
|
79
|
-
# Complexity and code quality limits
|
|
80
|
-
[tool.ruff.lint.mccabe]
|
|
81
|
-
max-complexity = 10
|
|
82
|
-
|
|
83
|
-
[tool.ruff.lint.pylint]
|
|
84
|
-
max-args = 5
|
|
85
|
-
max-branches = 12
|
|
86
|
-
max-statements = 50
|
|
87
|
-
|
|
88
|
-
[tool.ruff.lint.per-file-ignores]
|
|
89
|
-
"src/lifx_emulator/protocol/generator.py" = ["E501"]
|
|
90
|
-
"src/lifx_emulator/protocol/packets.py" = ["E501"]
|
|
91
|
-
|
|
47
|
+
packages = ["src/lifx_emulator_app"]
|
|
92
48
|
|
|
93
49
|
[tool.pyright]
|
|
94
50
|
typeCheckingMode = "standard"
|
|
95
|
-
pythonVersion = "3.
|
|
51
|
+
pythonVersion = "3.10"
|
|
96
52
|
include = ["src"]
|
|
97
53
|
exclude = ["**/__pycache__"]
|
|
98
54
|
|
|
@@ -102,43 +58,28 @@ pythonpath = ["src"]
|
|
|
102
58
|
python_files = ["test_*.py"]
|
|
103
59
|
python_classes = ["Test*"]
|
|
104
60
|
python_functions = ["test_*"]
|
|
105
|
-
addopts = """\
|
|
106
|
-
-v
|
|
107
|
-
-Wdefault
|
|
108
|
-
--cov=lifx_emulator
|
|
109
|
-
--cov-branch
|
|
110
|
-
--cov-report=xml
|
|
111
|
-
--cov-report=term-missing:skip-covered
|
|
112
|
-
--junitxml=junit.xml -o junit_family=legacy
|
|
113
|
-
"""
|
|
114
61
|
asyncio_mode = "auto"
|
|
115
62
|
asyncio_default_fixture_loop_scope = "function"
|
|
116
63
|
|
|
117
|
-
[tool.coverage.run]
|
|
118
|
-
omit = [
|
|
119
|
-
"src/lifx_emulator/protocol/generator.py",
|
|
120
|
-
"src/lifx_emulator/protocol/protocol_types.py",
|
|
121
|
-
"src/lifx_emulator/products/generator.py",
|
|
122
|
-
"src/lifx_emulator/products/registry.py",
|
|
123
|
-
]
|
|
124
|
-
|
|
125
|
-
[tool.coverage.report]
|
|
126
|
-
exclude_lines = [
|
|
127
|
-
"pragma: no cover",
|
|
128
|
-
"@overload",
|
|
129
|
-
"if TYPE_CHECKING",
|
|
130
|
-
"raise NotImplementedError",
|
|
131
|
-
'if __name__ == "__main__":',
|
|
132
|
-
]
|
|
133
|
-
|
|
134
64
|
[tool.semantic_release]
|
|
65
|
+
commit_parser = "conventional-monorepo"
|
|
66
|
+
commit_message = """\
|
|
67
|
+
chore(release): lifx-emulator@{version}
|
|
68
|
+
|
|
69
|
+
Automatically generated by python-semantic-release
|
|
70
|
+
"""
|
|
71
|
+
tag_format = "app-v{version}"
|
|
135
72
|
version_toml = ["pyproject.toml:project.version"]
|
|
136
73
|
build_command = """
|
|
137
74
|
uv lock --upgrade-package "$PACKAGE_NAME"
|
|
138
|
-
git add uv.lock
|
|
139
|
-
uv build
|
|
75
|
+
git add ../../uv.lock
|
|
76
|
+
uv build --package lifx-emulator --out-dir dist/
|
|
140
77
|
"""
|
|
141
78
|
|
|
79
|
+
[tool.semantic_release.commit_parser_options]
|
|
80
|
+
path_filters = ["."]
|
|
81
|
+
scope_prefix = "app-"
|
|
82
|
+
|
|
142
83
|
[tool.semantic_release.branches.main]
|
|
143
84
|
match = "main"
|
|
144
85
|
prerelease = false
|
|
@@ -161,7 +102,7 @@ exclude_commit_patterns = [
|
|
|
161
102
|
]
|
|
162
103
|
|
|
163
104
|
[tool.semantic_release.changelog.default_templates]
|
|
164
|
-
changelog_file = "
|
|
105
|
+
changelog_file = "CHANGELOG.md"
|
|
165
106
|
output_format = "md"
|
|
166
107
|
|
|
167
108
|
[tool.semantic_release.remote]
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/__main__.py
RENAMED
|
@@ -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
|
|
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))
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/__init__.py
RENAMED
|
@@ -10,7 +10,7 @@ of concerns.
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
# Import from new refactored structure
|
|
13
|
-
from
|
|
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
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/app.py
RENAMED
|
@@ -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
|
|
23
|
-
from
|
|
24
|
-
from
|
|
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
|
-
#
|
|
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)
|
|
@@ -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
|
|
10
|
+
from lifx_emulator_app.api.models import ColorHsbk, DeviceInfo
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class DeviceMapper:
|
{lifx_emulator-2.4.0/src/lifx_emulator → lifx_emulator-3.1.0/src/lifx_emulator_app}/api/models.py
RENAMED
|
@@ -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
|
|
13
|
-
from
|
|
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
|
|
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
|
|
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
|
|