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.
Files changed (40) hide show
  1. lifx_emulator/__init__.py +31 -0
  2. lifx_emulator/__main__.py +607 -0
  3. lifx_emulator/api.py +1825 -0
  4. lifx_emulator/async_storage.py +308 -0
  5. lifx_emulator/constants.py +33 -0
  6. lifx_emulator/device.py +750 -0
  7. lifx_emulator/device_states.py +114 -0
  8. lifx_emulator/factories.py +380 -0
  9. lifx_emulator/handlers/__init__.py +39 -0
  10. lifx_emulator/handlers/base.py +49 -0
  11. lifx_emulator/handlers/device_handlers.py +340 -0
  12. lifx_emulator/handlers/light_handlers.py +372 -0
  13. lifx_emulator/handlers/multizone_handlers.py +249 -0
  14. lifx_emulator/handlers/registry.py +110 -0
  15. lifx_emulator/handlers/tile_handlers.py +309 -0
  16. lifx_emulator/observers.py +139 -0
  17. lifx_emulator/products/__init__.py +28 -0
  18. lifx_emulator/products/generator.py +771 -0
  19. lifx_emulator/products/registry.py +1446 -0
  20. lifx_emulator/products/specs.py +242 -0
  21. lifx_emulator/products/specs.yml +327 -0
  22. lifx_emulator/protocol/__init__.py +1 -0
  23. lifx_emulator/protocol/base.py +334 -0
  24. lifx_emulator/protocol/const.py +8 -0
  25. lifx_emulator/protocol/generator.py +1371 -0
  26. lifx_emulator/protocol/header.py +159 -0
  27. lifx_emulator/protocol/packets.py +1351 -0
  28. lifx_emulator/protocol/protocol_types.py +844 -0
  29. lifx_emulator/protocol/serializer.py +379 -0
  30. lifx_emulator/scenario_manager.py +402 -0
  31. lifx_emulator/scenario_persistence.py +206 -0
  32. lifx_emulator/server.py +482 -0
  33. lifx_emulator/state_restorer.py +259 -0
  34. lifx_emulator/state_serializer.py +130 -0
  35. lifx_emulator/storage_protocol.py +100 -0
  36. lifx_emulator-1.0.0.dist-info/METADATA +445 -0
  37. lifx_emulator-1.0.0.dist-info/RECORD +40 -0
  38. lifx_emulator-1.0.0.dist-info/WHEEL +4 -0
  39. lifx_emulator-1.0.0.dist-info/entry_points.txt +2 -0
  40. lifx_emulator-1.0.0.dist-info/licenses/LICENSE +35 -0
@@ -0,0 +1,139 @@
1
+ """Observer pattern for activity tracking and event notification.
2
+
3
+ This module implements the Observer pattern to decouple activity tracking
4
+ from the server core, following the Open/Closed Principle.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections import deque
10
+ from dataclasses import dataclass
11
+ from typing import Any, Protocol
12
+
13
+
14
+ @dataclass
15
+ class PacketEvent:
16
+ """Represents a packet transmission or reception event.
17
+
18
+ Attributes:
19
+ timestamp: Unix timestamp of the event
20
+ direction: 'rx' for received, 'tx' for transmitted
21
+ packet_type: Numeric packet type identifier
22
+ packet_name: Human-readable packet name
23
+ addr: Network address string (host:port)
24
+ device: Device serial (for tx events) or None
25
+ target: Target identifier (for rx events) or None
26
+ """
27
+
28
+ timestamp: float
29
+ direction: str # 'rx' or 'tx'
30
+ packet_type: int
31
+ packet_name: str
32
+ addr: str
33
+ device: str | None = None # Device serial for tx events
34
+ target: str | None = None # Target for rx events
35
+
36
+
37
+ class ActivityObserver(Protocol):
38
+ """Protocol for observers that track packet activity.
39
+
40
+ Observers implementing this protocol can be attached to the server
41
+ to receive notifications of packet events.
42
+ """
43
+
44
+ def on_packet_received(self, event: PacketEvent) -> None:
45
+ """Called when a packet is received.
46
+
47
+ Args:
48
+ event: PacketEvent with direction='rx'
49
+ """
50
+ ...
51
+
52
+ def on_packet_sent(self, event: PacketEvent) -> None:
53
+ """Called when a packet is sent.
54
+
55
+ Args:
56
+ event: PacketEvent with direction='tx'
57
+ """
58
+ ...
59
+
60
+
61
+ class ActivityLogger:
62
+ """Observer that logs recent packet activity.
63
+
64
+ Maintains a rolling buffer of recent packet events for monitoring
65
+ and debugging purposes.
66
+ """
67
+
68
+ def __init__(self, max_events: int = 100):
69
+ """Initialize activity logger.
70
+
71
+ Args:
72
+ max_events: Maximum number of events to retain
73
+ """
74
+ self.recent_activity: deque[dict[str, Any]] = deque(maxlen=max_events)
75
+
76
+ def on_packet_received(self, event: PacketEvent) -> None:
77
+ """Record a received packet event.
78
+
79
+ Args:
80
+ event: PacketEvent with direction='rx'
81
+ """
82
+ self.recent_activity.append(
83
+ {
84
+ "timestamp": event.timestamp,
85
+ "direction": "rx",
86
+ "packet_type": event.packet_type,
87
+ "packet_name": event.packet_name,
88
+ "target": event.target,
89
+ "addr": event.addr,
90
+ }
91
+ )
92
+
93
+ def on_packet_sent(self, event: PacketEvent) -> None:
94
+ """Record a sent packet event.
95
+
96
+ Args:
97
+ event: PacketEvent with direction='tx'
98
+ """
99
+ self.recent_activity.append(
100
+ {
101
+ "timestamp": event.timestamp,
102
+ "direction": "tx",
103
+ "packet_type": event.packet_type,
104
+ "packet_name": event.packet_name,
105
+ "device": event.device,
106
+ "addr": event.addr,
107
+ }
108
+ )
109
+
110
+ def get_recent_activity(self) -> list[dict[str, Any]]:
111
+ """Get list of recent activity events.
112
+
113
+ Returns:
114
+ List of activity event dictionaries
115
+ """
116
+ return list(self.recent_activity)
117
+
118
+
119
+ class NullObserver:
120
+ """No-op observer for when activity tracking is disabled.
121
+
122
+ Allows code to unconditionally call notify without checking for None.
123
+ """
124
+
125
+ def on_packet_received(self, event: PacketEvent) -> None:
126
+ """No-op packet received handler.
127
+
128
+ Args:
129
+ event: PacketEvent (ignored)
130
+ """
131
+ pass
132
+
133
+ def on_packet_sent(self, event: PacketEvent) -> None:
134
+ """No-op packet sent handler.
135
+
136
+ Args:
137
+ event: PacketEvent (ignored)
138
+ """
139
+ pass
@@ -0,0 +1,28 @@
1
+ """LIFX product registry module.
2
+
3
+ This module provides product information and capability detection for LIFX devices.
4
+
5
+ The product registry is auto-generated from the official LIFX
6
+ products.json specification.
7
+ To update: run `uv run python -m lifx_emulator.products.generator`
8
+ """
9
+
10
+ from .registry import (
11
+ ProductCapability,
12
+ ProductInfo,
13
+ ProductRegistry,
14
+ TemperatureRange,
15
+ get_device_class_name,
16
+ get_product,
17
+ get_registry,
18
+ )
19
+
20
+ __all__ = [
21
+ "ProductCapability",
22
+ "ProductInfo",
23
+ "ProductRegistry",
24
+ "TemperatureRange",
25
+ "get_device_class_name",
26
+ "get_product",
27
+ "get_registry",
28
+ ]