Mercurial > code > home > repos > light-bridge
annotate protocols.py @ 29:35affd4d37d4 default tip
add 1st ikea color light
author | drewp@bigasterisk.com |
---|---|
date | Sat, 14 Dec 2024 22:36:29 -0800 |
parents | fb2e91f230f4 |
children |
rev | line source |
---|---|
28 | 1 import json |
20 | 2 import logging |
28 | 3 from enum import Enum |
4 | |
20 | 5 import aiohttp |
28 | 6 |
15 | 7 from color_convert import DeviceColor |
8 from mqtt_io import MqttIo | |
9 | |
20 | 10 log = logging.getLogger('prot') |
15 | 11 |
21 | 12 |
15 | 13 class Transport: |
14 | |
15 def linked(self): | |
16 return {'label': str(self)} | |
17 | |
18 async def send(self, dc: DeviceColor): | |
19 raise TypeError | |
20 | |
21 | |
21 | 22 def to8(x: float): |
23 return int(x * 255) | |
24 | |
25 | |
26 def zbColorMessage(dc: DeviceColor) -> dict: | |
27 return { | |
28 "transition": 0, | |
29 "brightness": to8(dc.brightness), | |
30 "color": { | |
31 "hex": "#%02x%02x%02x" % (to8(dc.r), to8(dc.g), to8(dc.b)) | |
32 }, | |
33 } | |
34 | |
15 | 35 |
21 | 36 def zbBrightnessMessage(dc: DeviceColor) -> dict: |
37 return { | |
38 "transition": 0, | |
39 "brightness": to8(dc.brightness), | |
40 } | |
41 | |
42 | |
43 def zbWhiteSpectrumMessage(dc: DeviceColor) -> dict: | |
44 return { | |
45 "transition": 0, | |
46 "brightness": to8(dc.brightness), | |
47 # temperature todo | |
48 } | |
49 | |
23 | 50 |
21 | 51 def zbRelayMessage(dc: DeviceColor) -> dict: |
52 return {'state': 'ON' if dc.brightness else 'OFF'} | |
53 | |
23 | 54 |
55 def espColorMessage(dc: DeviceColor) -> dict: | |
56 return { | |
26
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
57 "state": 'ON', |
23 | 58 "color": { |
59 "r": to8(dc.r), | |
60 "g": to8(dc.g), | |
61 "b": to8(dc.b), | |
62 "w": to8(dc.w) | |
63 }, | |
64 } | |
65 | |
66 | |
21 | 67 def z2mSet(name): |
68 return f'zigbee/{name}/set' | |
15 | 69 |
23 | 70 |
15 | 71 class ZigbeeTransport(Transport): |
72 | |
21 | 73 def __init__(self, mqtt: MqttIo, name: str, ieee: str, topic=z2mSet, msg=zbColorMessage): |
15 | 74 self.mqtt = mqtt |
75 self.name = name | |
76 self.ieee = ieee | |
23 | 77 self.topic = topic |
21 | 78 self.msg = msg |
15 | 79 |
80 def linked(self): | |
20 | 81 return {'url': f'https://bigasterisk.com/zigbee/console/#/device/{self.ieee}/info', 'label': self.name} |
15 | 82 |
83 async def send(self, dc: DeviceColor): | |
21 | 84 await self.mqtt.publish(self.topic(self.name), json.dumps(self.msg(dc))) |
20 | 85 |
86 | |
87 class SonoffRelayTransport(Transport): | |
88 | |
89 def __init__(self, mqtt: MqttIo, name: str): | |
90 self.mqtt = mqtt | |
91 self.name = name | |
92 | |
93 def linked(self): | |
94 return {'label': self.name} | |
95 | |
96 async def send(self, dc: DeviceColor): | |
97 topic = f'{self.name}/switch/sonoff_basic_relay/command' | |
98 msg = 'ON' if dc.brightness else 'OFF' | |
99 log.info(f'sonoff {topic=} {msg=}') | |
100 await self.mqtt.publish(topic, msg) | |
101 | |
102 | |
103 class _WebTransport(Transport): | |
104 | |
105 def __init__(self, hostname: str): | |
106 self.hostname = hostname | |
107 self._session = aiohttp.ClientSession() | |
108 | |
109 def linked(self): | |
110 return {'url': f'http://{self.hostname}/', 'label': self.hostname} | |
111 | |
112 | |
113 class TasmotaWebTransport(_WebTransport): | |
114 | |
115 async def send(self, dc: DeviceColor): | |
23 | 116 cmnd = 'Color ' + ','.join(str(to8(x)) for x in (dc.r, dc.g, dc.b, dc.cw, dc.ww)) |
20 | 117 async with self._session.get(f'http://{self.hostname}/cm', params={'cmnd': cmnd}) as resp: |
118 await resp.text() | |
119 # {"POWER":"ON","Dimmer":21,"Color":"3636363600","HSBColor":"0,0,21","White":21,"CT":153,"Channel":[21,21,21,21,0]} | |
120 | |
121 | |
28 | 122 class WledControl(Enum): |
123 wholeStringColor = 'wholeStringColor' | |
124 brightness = 'brightness' | |
125 | |
126 | |
26
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
127 class WledTransport(_WebTransport): |
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
128 |
28 | 129 def __init__(self, hostname: str, control: WledControl): |
130 super().__init__(hostname) | |
131 self.control = control | |
132 | |
26
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
133 async def send(self, dc: DeviceColor): |
28 | 134 if self.control == WledControl.wholeStringColor: |
135 # see https://kno.wled.ge/interfaces/json-api/ | |
136 msg = { | |
137 'seg': [{ | |
138 "cct": 128, # 0 warm; 255 cool | |
139 "col": [[to8(x) for x in [dc.r, dc.g, dc.b, dc.cw]], [], []] | |
140 }] | |
141 } | |
142 elif self.control == WledControl.brightness: | |
143 msg = {"bri": to8(dc.brightness)} | |
144 else: | |
145 raise NotImplementedError | |
26
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
146 async with self._session.post(f'http://{self.hostname}/json/state', headers={'content-type': 'application/json'}, data=json.dumps(msg)) as resp: |
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
147 await resp.text() |
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
148 |
33b3eb24506e
wled (single bulb) support. more lights
drewp@bigasterisk.com
parents:
23
diff
changeset
|
149 |
20 | 150 class ShellyGen1WebTransport(_WebTransport): |
151 | |
152 async def send(self, dc: DeviceColor): | |
153 # also see https://shelly-api-docs.shelly.cloud/gen1/#shelly-rgbw2-color-status for metrics | |
23 | 154 async with self._session.get(f'http://{self.hostname}/light/0', params={ |
155 'red': to8(dc.r), | |
156 'green': to8(dc.g), | |
157 'blue': to8(dc.b), | |
158 'white': to8(dc.w), | |
159 }) as resp: | |
20 | 160 await resp.text() |
161 # {..."mode":"color","red":255,"green":242,"blue":0,"white":255,"gain":59,"effect":0,"transition":0,"power":18.00,"overpower":false} |