annotate light.py @ 17:1d15dc4d673f

cleanup color convert code path
author drewp@bigasterisk.com
date Sun, 28 Jan 2024 21:18:40 -0800
parents 61d4ccecfed8
children 24a574108365
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
1 import asyncio
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
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
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
5
5
7eeda7f4f9cd spell it to_dict, for compat with DataClassJsonMixin
drewp@bigasterisk.com
parents: 4
diff changeset
6 from color import Color
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
7 from color_convert import DeviceColor, zbConv
14
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
8 from mqtt_io import MqttIo
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
9 from protocols import Transport, ZigbeeTransport
5
7eeda7f4f9cd spell it to_dict, for compat with DataClassJsonMixin
drewp@bigasterisk.com
parents: 4
diff changeset
10
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
11 log = logging.getLogger('light')
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
12
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
13
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
14 @dataclass
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
15 class Light:
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
16 name: str
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
17 transport: Transport
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
18 convertColor: Callable[[Color], DeviceColor]
9
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
19
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
20 requestingColor: Color = Color.fromHex('#000000')
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
21 requestingDeviceColor: DeviceColor = DeviceColor()
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
22
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
23 emittingColor: Color = Color.fromHex('#000000')
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
24 online: bool | None = None
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
25 latencyMs: float | None = None
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
26
11
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
27 notifyChanged: Callable | None = None
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
28
9
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
29 def __post_init__(self):
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
30 self.requestingDeviceColor = self.convertColor(self.requestingColor)
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
31
5
7eeda7f4f9cd spell it to_dict, for compat with DataClassJsonMixin
drewp@bigasterisk.com
parents: 4
diff changeset
32 def to_dict(self):
9
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
33 d = {
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
34 'name': self.name,
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
35 'address': self.transport.linked(),
9
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
36 'requestingColor': self.requestingColor.hex(),
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
37 'requestingDeviceColor': self.requestingDeviceColor.summary(),
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
38 'emittingColor': self.emittingColor.hex(),
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
39 'online': self.online,
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
40 'latencyMs': self.latencyMs,
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
41 }
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
42
9
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
43 return {'light': d}
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
44
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
45 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
46 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
47 if c == self.requestingColor:
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
48 return
9
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
49 self.requestingColor = c
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
50 self.requestingDeviceColor = self.convertColor(self.requestingColor)
14
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
51
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
52 if self.notifyChanged:
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
53 self.notifyChanged()
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
54
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
55 # waits for the relevant round-trip
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
56 log.info(f'transport send {self.requestingDeviceColor.summary()}')
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
57 await self.transport.send(self.requestingDeviceColor)
14
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
58
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
59 self.emittingColor = self.requestingColor
11
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
60 if self.notifyChanged:
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
61 self.notifyChanged()
9
9f427d8073c3 redo data model; add ui colors
drewp@bigasterisk.com
parents: 6
diff changeset
62
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
63
14
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
64 def makeZbBar(mqtt: MqttIo, name: str, ieee: str) -> Light:
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
65 return Light(name=name, convertColor=zbConv, transport=ZigbeeTransport(mqtt, name, ieee))
13
1c865af058e7 start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents: 12
diff changeset
66
1c865af058e7 start make* funcs and add links to light addresses
drewp@bigasterisk.com
parents: 12
diff changeset
67
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
68 class Lights:
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
69 _d: dict[str, Light] = {}
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
70
14
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
71 def __init__(self, mqtt: MqttIo):
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
72 self.mqtt = mqtt
17
1d15dc4d673f cleanup color convert code path
drewp@bigasterisk.com
parents: 15
diff changeset
73
14
e3dbd04dab96 add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents: 13
diff changeset
74 self.add(makeZbBar(mqtt, 'do-bar', '0xa4c13844948d2da4'))
6
fc8ed0efcd72 move init to Lights
drewp@bigasterisk.com
parents: 5
diff changeset
75
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
76 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
77 d.notifyChanged = self.notifyChanged
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
78 self._d[d.name] = d
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
79
11
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
80 self.notifyChanged()
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
81
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
82 def byName(self, name: str) -> Light:
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
83 return self._d[name]
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
84
12
7cc004eafb82 refactor (approx)
drewp@bigasterisk.com
parents: 11
diff changeset
85 def to_dict(self):
7cc004eafb82 refactor (approx)
drewp@bigasterisk.com
parents: 11
diff changeset
86 return {'lights': [d.to_dict() for d in sorted(self._d.values(), key=lambda r: r.name)]}
7cc004eafb82 refactor (approx)
drewp@bigasterisk.com
parents: 11
diff changeset
87
7cc004eafb82 refactor (approx)
drewp@bigasterisk.com
parents: 11
diff changeset
88 # the following is bad. Get a better events lib.
7cc004eafb82 refactor (approx)
drewp@bigasterisk.com
parents: 11
diff changeset
89 _changeSleepTask: asyncio.Task | None = None
7cc004eafb82 refactor (approx)
drewp@bigasterisk.com
parents: 11
diff changeset
90
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
91 async def changes(self): # yields None on any data change
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
92 while True:
11
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
93 log.info('Lights has a change')
2
c6fd04e07db0 refactor light.py
drewp@bigasterisk.com
parents:
diff changeset
94 yield None
11
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
95 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
96 try:
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
97 await self._changeSleepTask
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
98 except asyncio.CancelledError:
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
99 pass
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
100 self._changeSleepTask = None
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
101
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
102 async def _sleep(self):
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
103 await asyncio.sleep(100)
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
104
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
105 def notifyChanged(self):
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
106 log.info('Lights.notifyChanged()')
028ed39aa78f more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents: 9
diff changeset
107 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
108 self._changeSleepTask.cancel()