view protocols.py @ 25:cee43f550577

add /lightNames
author drewp@bigasterisk.com
date Fri, 02 Feb 2024 20:52:09 -0800
parents 7d9a056e29fe
children 33b3eb24506e
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 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}