Mercurial > code > home > repos > light-bridge
view protocols.py @ 27:32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
author | drewp@bigasterisk.com |
---|---|
date | Sat, 23 Mar 2024 15:25:02 -0700 |
parents | 33b3eb24506e |
children | fb2e91f230f4 |
line wrap: on
line source
import logging import json import aiohttp from color_convert import DeviceColor from mqtt_io import MqttIo log = logging.getLogger('prot') class Transport: def linked(self): return {'label': str(self)} async def send(self, dc: DeviceColor): raise TypeError def to8(x: float): return int(x * 255) def zbColorMessage(dc: DeviceColor) -> dict: return { "transition": 0, "brightness": to8(dc.brightness), "color": { "hex": "#%02x%02x%02x" % (to8(dc.r), to8(dc.g), to8(dc.b)) }, } def zbBrightnessMessage(dc: DeviceColor) -> dict: return { "transition": 0, "brightness": to8(dc.brightness), } def zbWhiteSpectrumMessage(dc: DeviceColor) -> dict: return { "transition": 0, "brightness": to8(dc.brightness), # temperature todo } def zbRelayMessage(dc: DeviceColor) -> dict: return {'state': 'ON' if dc.brightness else 'OFF'} def espColorMessage(dc: DeviceColor) -> dict: return { "state": 'ON', "color": { "r": to8(dc.r), "g": to8(dc.g), "b": to8(dc.b), "w": to8(dc.w) }, } def z2mSet(name): return f'zigbee/{name}/set' class ZigbeeTransport(Transport): def __init__(self, mqtt: MqttIo, name: str, ieee: str, topic=z2mSet, msg=zbColorMessage): self.mqtt = mqtt self.name = name self.ieee = ieee self.topic = topic self.msg = msg def linked(self): return {'url': f'https://bigasterisk.com/zigbee/console/#/device/{self.ieee}/info', 'label': self.name} async def send(self, dc: DeviceColor): await self.mqtt.publish(self.topic(self.name), json.dumps(self.msg(dc))) class SonoffRelayTransport(Transport): def __init__(self, mqtt: MqttIo, name: str): self.mqtt = mqtt self.name = name def linked(self): return {'label': self.name} async def send(self, dc: DeviceColor): topic = f'{self.name}/switch/sonoff_basic_relay/command' msg = 'ON' if dc.brightness else 'OFF' log.info(f'sonoff {topic=} {msg=}') await self.mqtt.publish(topic, msg) class _WebTransport(Transport): def __init__(self, hostname: str): self.hostname = hostname self._session = aiohttp.ClientSession() def linked(self): return {'url': f'http://{self.hostname}/', 'label': self.hostname} class TasmotaWebTransport(_WebTransport): async def send(self, dc: DeviceColor): cmnd = 'Color ' + ','.join(str(to8(x)) for x in (dc.r, dc.g, dc.b, dc.cw, dc.ww)) async with self._session.get(f'http://{self.hostname}/cm', params={'cmnd': cmnd}) as resp: await resp.text() # {"POWER":"ON","Dimmer":21,"Color":"3636363600","HSBColor":"0,0,21","White":21,"CT":153,"Channel":[21,21,21,21,0]} class WledTransport(_WebTransport): async def send(self, dc: DeviceColor): # see https://kno.wled.ge/interfaces/json-api/ msg = { 'seg': [{ "cct": 128, # 0 warm; 255 cool "col": [[to8(x) for x in [dc.r, dc.g, dc.b, dc.cw]], [], []] }] } async with self._session.post(f'http://{self.hostname}/json/state', headers={'content-type': 'application/json'}, data=json.dumps(msg)) as resp: await resp.text() # {"POWER":"ON","Dimmer":21,"Color":"3636363600","HSBColor":"0,0,21","White":21,"CT":153,"Channel":[21,21,21,21,0]} class ShellyGen1WebTransport(_WebTransport): async def send(self, dc: DeviceColor): # also see https://shelly-api-docs.shelly.cloud/gen1/#shelly-rgbw2-color-status for metrics async with self._session.get(f'http://{self.hostname}/light/0', params={ 'red': to8(dc.r), 'green': to8(dc.g), 'blue': to8(dc.b), 'white': to8(dc.w), }) as resp: await resp.text() # {..."mode":"color","red":255,"green":242,"blue":0,"white":255,"gain":59,"effect":0,"transition":0,"power":18.00,"overpower":false}