Mercurial > code > home > repos > light-bridge
annotate light.py @ 13:1c865af058e7
start make* funcs and add links to light addresses
author | drewp@bigasterisk.com |
---|---|
date | Sun, 28 Jan 2024 20:03:20 -0800 |
parents | 7cc004eafb82 |
children | e3dbd04dab96 |
rev | line source |
---|---|
2 | 1 import asyncio |
2 import logging | |
13
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
3 from dataclasses import dataclass |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
4 from typing import Callable |
2 | 5 |
5
7eeda7f4f9cd
spell it to_dict, for compat with DataClassJsonMixin
drewp@bigasterisk.com
parents:
4
diff
changeset
|
6 from color import Color |
7eeda7f4f9cd
spell it to_dict, for compat with DataClassJsonMixin
drewp@bigasterisk.com
parents:
4
diff
changeset
|
7 |
2 | 8 log = logging.getLogger('light') |
9 | |
10 | |
9 | 11 @dataclass(frozen=True) |
12 class DeviceColor: | |
13 """neutral representation of the adjusted color that we send to a device""" | |
14 r: float = 0 | |
15 g: float = 0 | |
16 b: float = 0 | |
17 w: float = 0 | |
18 x: float = 0 | |
19 y: float = 0 | |
20 | |
21 def summary(self) -> dict: | |
22 return dict([(k, round(v, 3)) for k, v in self.__dict__.items() if v > 0]) | |
23 | |
24 | |
13
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
25 class Address: |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
26 |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
27 def linked(self): |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
28 return {'label': str(self)} |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
29 |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
30 |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
31 class ZigbeeAddress(Address): |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
32 |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
33 def __init__(self, name: str, ieee: str): |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
34 self.name = name |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
35 self.ieee = ieee |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
36 |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
37 def linked(self): |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
38 return {'url': f'https://bigasterisk.com/zigbee/console/#/device/{self.ieee}/info', 'label': 'do-bar'} |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
39 |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
40 |
2 | 41 @dataclass |
42 class Light: | |
43 name: str | |
13
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
44 address: Address |
9 | 45 |
46 requestingColor: Color = Color.fromHex('#000000') | |
47 requestingDeviceColor: DeviceColor = DeviceColor() | |
48 | |
49 emittingColor: Color = Color.fromHex('#000000') | |
50 online: bool | None = None | |
51 latencyMs: float | None = None | |
52 | |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
53 notifyChanged: Callable | None = None |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
54 |
9 | 55 def __post_init__(self): |
56 self.requestingDeviceColor = self.deviceColor(self.requestingColor) | |
2 | 57 |
5
7eeda7f4f9cd
spell it to_dict, for compat with DataClassJsonMixin
drewp@bigasterisk.com
parents:
4
diff
changeset
|
58 def to_dict(self): |
9 | 59 d = { |
60 'name': self.name, | |
13
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
61 'address': self.address.linked(), |
9 | 62 'requestingColor': self.requestingColor.hex(), |
63 'requestingDeviceColor': self.requestingDeviceColor.summary(), | |
64 'emittingColor': self.emittingColor.hex(), | |
65 'online': self.online, | |
66 'latencyMs': self.latencyMs, | |
2 | 67 } |
68 | |
9 | 69 return {'light': d} |
70 | |
71 def deviceColor(self, c: Color) -> DeviceColor: | |
72 # do LUT here | |
73 return DeviceColor(r=c.r, g=c.g, b=c.b) | |
74 | |
75 async def setColor(self, c: Color): | |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
76 log.info(f'setColor from {self.requestingColor} to {c}') |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
77 if c == self.requestingColor: |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
78 return |
9 | 79 self.requestingColor = c |
80 self.requestingDeviceColor = self.deviceColor(self.requestingColor) | |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
81 if self.notifyChanged: |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
82 self.notifyChanged() |
9 | 83 |
2 | 84 |
13
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
85 def makeZbBar(name: str, ieee: str) -> Light: |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
86 return Light(name=name, address=ZigbeeAddress(name, ieee)) |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
87 |
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
88 |
2 | 89 class Lights: |
90 _d: dict[str, Light] = {} | |
91 | |
6 | 92 def __init__(self): |
13
1c865af058e7
start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents:
12
diff
changeset
|
93 self.add(makeZbBar('do-bar', '0xa4c13844948d2da4')) |
6 | 94 |
2 | 95 def add(self, d: Light): |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
96 d.notifyChanged = self.notifyChanged |
2 | 97 self._d[d.name] = d |
98 | |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
99 self.notifyChanged() |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
100 |
2 | 101 def byName(self, name: str) -> Light: |
102 return self._d[name] | |
103 | |
12 | 104 def to_dict(self): |
105 return {'lights': [d.to_dict() for d in sorted(self._d.values(), key=lambda r: r.name)]} | |
106 | |
107 # the following is bad. Get a better events lib. | |
108 _changeSleepTask: asyncio.Task | None = None | |
109 | |
2 | 110 async def changes(self): # yields None on any data change |
111 while True: | |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
112 log.info('Lights has a change') |
2 | 113 yield None |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
114 self._changeSleepTask = asyncio.create_task(self._sleep()) |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
115 try: |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
116 await self._changeSleepTask |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
117 except asyncio.CancelledError: |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
118 pass |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
119 self._changeSleepTask = None |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
120 |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
121 async def _sleep(self): |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
122 await asyncio.sleep(100) |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
123 |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
124 def notifyChanged(self): |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
125 log.info('Lights.notifyChanged()') |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
126 if self._changeSleepTask is not None: |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
9
diff
changeset
|
127 self._changeSleepTask.cancel() |