Skip to content

Commit

Permalink
Support RGBCT bulbs
Browse files Browse the repository at this point in the history
  • Loading branch information
kuba2k2 committed Sep 13, 2023
1 parent c1b781e commit e02fb8d
Show file tree
Hide file tree
Showing 6 changed files with 570 additions and 33 deletions.
7 changes: 3 additions & 4 deletions ltctplugin/upk2esphome/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import json
import os
from logging import debug, error, info, warning
from logging import debug, error, exception, info, warning
from os.path import dirname, isfile

import wx
Expand All @@ -11,7 +11,6 @@
from ltchiptool.gui.base.zc import ZeroconfBase
from ltchiptool.gui.panels.base import BasePanel
from ltchiptool.gui.utils import on_event
from ltchiptool.util.logging import LoggingHandler
from zeroconf import IPVersion, ServiceInfo

from upk2esphome import Opts, YamlResult, upk2esphome
Expand Down Expand Up @@ -356,7 +355,7 @@ def OnDoCloudcutterClick(self):
self.EnableAll()
except Exception as e:
self.EnableAll()
LoggingHandler.get().emit_exception(e)
exception(None, exc_info=e)
return

dialog = wx.SingleChoiceDialog(
Expand All @@ -377,7 +376,7 @@ def OnDoCloudcutterClick(self):
self.EnableAll()
except Exception as e:
self.EnableAll()
LoggingHandler.get().emit_exception(e)
exception(None, exc_info=e)
return

self.data = device
Expand Down
93 changes: 64 additions & 29 deletions upk2esphome/parts/bulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,87 @@
from upk2esphome.opts import Opts
from upk2esphome.result import YamlResult

colors = ["red", "green", "blue", "cold", "warm"]
platforms = {
COLORS_STD = ["red", "green", "blue", "cold", "warm"]
COLORS_ALL = [*COLORS_STD, "brightness", "temperature"]
EXTRAS_CW = {
"cold_white_color_temperature": "6500 K",
"warm_white_color_temperature": "2700 K",
}
EXTRAS_RGBCW = {
"color_interlock": True,
**EXTRAS_CW,
}

# { found_colors: (esphome_platform, {color_translation}, {extra_opts}) }
COLOR_PLATFORMS = {
# Red, Green, Blue
"rgb": ("rgb", {}, {}),
# Red, Green, Blue, Warm
"rgbw": ("rgbw", {"warm": "white"}, {}),
# Red, Green, Blue, Cold
"rgbc": ("rgbw", {"cold": "white"}, {}),
# Red, Green, Blue, Cold, Warm
"rgbcw": (
"rgbww",
{"cold": "cold_white", "warm": "warm_white"},
{
"color_interlock": True,
"cold_white_color_temperature": "6500 K",
"warm_white_color_temperature": "2700 K",
},
EXTRAS_RGBCW,
),
# Red, Green, Blue, Brightness, Temperature
"rgbbt": (
"rgbct",
{"brightness": "white_brightness", "temperature": "color_temperature"},
EXTRAS_RGBCW,
),
# Cold, Warm
"cw": (
"cwww",
{"cold": "cold_white", "warm": "warm_white"},
{
"cold_white_color_temperature": "6500 K",
"warm_white_color_temperature": "2700 K",
},
EXTRAS_CW,
),
# Brightness, Temperature
"bt": (
"color_temperature",
{"temperature": "color_temperature"},
EXTRAS_CW,
),
# Cold
"c": ("monochromatic", {"cold": "output"}, {}),
# Warm
"w": ("monochromatic", {"warm": "output"}, {}),
}
cmods = {
"rgbcw": "rgbww",
"rgb": "rgb",
"cw": "cwww",
"c": "monochromatic",
"rgbc": "rgbw",

# { (cmod, cwtype): esphome_platform }
CMOD_PLATFORM = {
("rgbcw", 0): "rgbww",
("rgbcw", 1): "rgbct",
("rgb", 0): "rgb",
("cw", 0): "cwww",
("cw", 1): "color_temperature",
("c", 0): "monochromatic",
("rgbc", 0): "rgbw",
}


def get_platform(found: set[str]) -> str | None:
def get_platform(found: set[str]):
key = sorted(c[0] for c in found)
for name, platform in platforms.items():
for name, platform in COLOR_PLATFORMS.items():
if sorted(name) == key:
return platform
return None


def gen_pwm(yr: YamlResult, config: dict) -> set[str]:
found = set()
for color in colors:
is_ct = config.get("cwtype", 0) == 1
for color in COLORS_STD:
pin = config.get(f"{color[0]}_pin", None)
inv = config.get(f"{color[0]}_lv", None) == 0
if pin is None:
continue
if is_ct and color == "cold":
color = "brightness"
elif is_ct and color == "warm":
color = "temperature"
found.add(color)

yr.log(f" - color {color}: pin P{pin}, inverted {inv}")
Expand Down Expand Up @@ -89,7 +121,7 @@ def gen_i2c_sm2235(yr: YamlResult, config: dict):
yr.log(f" - white channels power: {cur_white}")

found = set()
for color in colors:
for color in COLORS_STD:
channel = f"iic{color[0]}"
if channel not in config:
continue
Expand Down Expand Up @@ -144,7 +176,7 @@ def gen_i2c_sm2135eh(yr: YamlResult, config: dict):
yr.log(f" - white channels current: {cur_white} mA")

found = set()
for color in colors:
for color in COLORS_STD:
channel = f"iic{color[0]}"
if channel not in config:
continue
Expand Down Expand Up @@ -178,7 +210,7 @@ def gen_i2c_bp5758d(yr: YamlResult, config: dict):
cur_warm = config.get("dwcur", None)

found = set()
for color in colors:
for color in COLORS_STD:
channel = f"iic{color[0]}"
if channel not in config:
continue
Expand Down Expand Up @@ -223,7 +255,7 @@ def gen_i2c_bp1658cj(yr: YamlResult, config: dict):
yr.log(f" - white channels power: {cur_white}")

found = set()
for color in colors:
for color in COLORS_STD:
channel = f"iic{color[0]}"
if channel not in config:
continue
Expand Down Expand Up @@ -279,15 +311,18 @@ def generate(yr: YamlResult, config: ConfigData, opts: Opts):
**opts,
}
# add channels
for color in colors:
for color in COLORS_ALL:
if color not in found:
continue
key = mapping.get(color, color)
light[key] = f"output_{color}"
# add light component
yr.light(light)
# check cmod matching
if "cmod" in config:
cmod = config["cmod"]
if cmods[cmod] != name:
yr.warn(f"Module 'cmod': {cmod} doesn't match platform {name}")
cmod = config.get("cmod", None)
cwtype = config.get("cwtype", 0)
if (cmod, cwtype) in CMOD_PLATFORM:
if CMOD_PLATFORM[cmod, cwtype] != name:
yr.warn(
f"Module cmod:{cmod}/cwtype:{cwtype} doesn't match platform {name}"
)
File renamed without changes.
141 changes: 141 additions & 0 deletions upk2esphome/tests/bulb_pwm_cw.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"manufacturer": "Kobi",
"name": "Oprawa Smart LED Moon",
"key": "keytg5kq8gvkv9dh",
"ap_ssid": "SmartLife",
"github_issues": [
264
],
"image_urls": [
"https://tuya-cloudcutter.github.io/images/kobi-oprawa-smart-led-moon.jpg"
],
"profiles": [
{
"slug": "oem-bk7231s-light-ty-2.9.16-sdk-1.0.8-40.00",
"name": "2.9.16 - BK7231T",
"type": "CLASSIC",
"sub_name": "oem_bk7231s_light_ty",
"icon": "lightbulb-outline"
}
],
"schemas": {
"0000021ioj": [
{
"type": "obj",
"mode": "rw",
"property": {
"type": "bool"
},
"id": 20
},
{
"type": "obj",
"mode": "rw",
"property": {
"range": [
"white",
"colour",
"scene",
"music"
],
"type": "enum"
},
"id": 21
},
{
"type": "obj",
"mode": "rw",
"property": {
"min": 10,
"max": 1000,
"scale": 0,
"step": 1,
"type": "value"
},
"id": 22
},
{
"type": "obj",
"mode": "rw",
"property": {
"min": 0,
"max": 1000,
"scale": 0,
"step": 1,
"type": "value"
},
"id": 23
},
{
"type": "obj",
"mode": "rw",
"property": {
"type": "string",
"maxlen": 255
},
"id": 25
},
{
"type": "obj",
"mode": "rw",
"property": {
"min": 0,
"max": 86400,
"scale": 0,
"step": 1,
"type": "value"
},
"id": 26
},
{
"type": "obj",
"mode": "wr",
"property": {
"type": "string",
"maxlen": 255
},
"id": 28
}
]
},
"device_configuration": {
"Jsonver": "1.1.8",
"brightmax": 100,
"brightmin": 10,
"c_lv": 1,
"c_pin": 7,
"cagt": 20,
"category": "0502",
"cmod": "cw",
"colormax": 100,
"colormin": 10,
"crc": 100,
"ctrl_lv": 1,
"ctrl_pin": 14,
"cwmaxp": 100,
"cwtype": 0,
"defbright": 50,
"defcolor": "c",
"deftemp": 0,
"dmod": 0,
"module": "WB3L",
"onoffmode": 0,
"pmemory": 1,
"prodagain": 0,
"pwmhz": 1000,
"remdmode": 0,
"rgbt": 0,
"rstbr": 50,
"rstcor": "c",
"rstnum": 3,
"rsttemp": 0,
"title20": 1,
"w_lv": 1,
"w_pin": 6,
"wfcfg": "spcl",
"wfct": 3,
"wt": 20
},
"slug": "kobi-oprawa-smart-led-moon",
"image_url": "https://tuya-cloudcutter.github.io/images/thumbs/kobi-oprawa-smart-led-moon.jpg"
}
Loading

0 comments on commit e02fb8d

Please sign in to comment.