A couple of years ago, on a much older version of home assistant, I wrote a very quick and dirty custom component to control my “Lifesmart Cololight Quantum” lights bought from AliExpress.
In the old version. I had one file called “quantumlight.py” in the folder “config/custom_components/light”
I tried dropping it in there on the new version (I am on the latest 2022.3.7) but this does not seem to work. What do I need to do to bring this up to speed so I can use it again?
Here is the contents of the quantumlight.py
"""
Support for Quantum lights.
"""
import logging
import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, SUPPORT_EFFECT, ATTR_EFFECT, Light,
PLATFORM_SCHEMA)
from homeassistant.const import CONF_NAME
import homeassistant.helpers.config_validation as cv
import homeassistant.util.color as color_util
import socket
import codecs
import colorsys
IPADDR = '192.168.0.45'
PORTNUM = 8900
_LOGGER = logging.getLogger(__name__)
CONF_IP = 'ip'
DEFAULT_NAME = 'Quantum Light'
SUPPORT_QUANTUM = SUPPORT_BRIGHTNESS | SUPPORT_COLOR | SUPPORT_EFFECT
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_IP, default="192.168.0.209"): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})
EFFECT_SAVASANA = "Savasana"
EFFECT_SUNRISE = "Sunrise"
EFFECT_UNICORNS = "Unicorns"
EFFECT_PENSIVE = "Pensive"
EFFECT_CIRCUS = "The Circus"
EFFECT_INSTAGRAMMER = "Instagrammer"
EFFECT_EIGHTIESCLUB= "80's Club"
EFFECT_CHERRYBLOSSOMS = "Cherry Blossoms"
EFFECT_COCKTAILPARADE = "Cocktail Parade"
EFFECT_CUSTOMIZED = "Customized"
QUANTUM_EFFECT_LIST = [
EFFECT_SAVASANA,
EFFECT_SUNRISE,
EFFECT_UNICORNS,
EFFECT_PENSIVE,
EFFECT_CIRCUS,
EFFECT_INSTAGRAMMER,
EFFECT_EIGHTIESCLUB,
EFFECT_CHERRYBLOSSOMS,
EFFECT_COCKTAILPARADE,
EFFECT_CUSTOMIZED]
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up Quantum device specified by serial number."""
name = config.get(CONF_NAME)
serial = config.get(CONF_IP)
stick = "hello"
add_entities([QuantumLight(stick, name)], True)
class QuantumLight(Light):
"""Representation of a Quantum light."""
def __init__(self, stick, name):
"""Initialize the light."""
self._name = name
self._hs_color = None
self._effect = None
self._brightness = 255
self._isOn = False
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
@property
def should_poll(self):
"""Set up polling."""
return True
@property
def name(self):
"""Return the name of the light."""
return self._name
@property
def brightness(self):
"""Read back the brightness of the light."""
return self._brightness
@property
def effect(self):
"""Read back the effect of the light."""
return self._effect
@property
def hs_color(self):
"""Read back the color of the light."""
return self._hs_color
@property
def is_on(self):
"""Return True if entity is on."""
return self._isOn
@property
def supported_features(self):
"""Flag supported features."""
return SUPPORT_QUANTUM
@property
def effect_list(self):
"""Return the list of supported effects."""
return QUANTUM_EFFECT_LIST
# def update(self):
# """Read back the device state."""
# //rgb_color = self._stick.get_color()
# hsv = color_util.color_RGB_to_hsv(*rgb_color)
# self._hs_color = hsv[:2]
# self._brightness = hsv[2]
def turn_on(self, **kwargs):
"""Turn the device on."""
self._socket.connect((IPADDR, PORTNUM))
_LOGGER.info(kwargs)
self._isOn=True
if ATTR_HS_COLOR in kwargs:
self._hs_color = kwargs[ATTR_HS_COLOR]
self._effect = None
if ATTR_BRIGHTNESS in kwargs:
self._brightness = kwargs[ATTR_BRIGHTNESS]
if ATTR_EFFECT in kwargs:
self._effect = kwargs[ATTR_EFFECT]
self._hs_color = None
else:
decode_hex = codecs.getdecoder("hex_codec")
self._socket.send(decode_hex('535a3030000000000020000000000000000000000000000000003900000000000000000004390301cf0f')[0]) #
#Brightness
if self._brightness is not None:
hexBrightnessArr = ['53','5a','30','30','00','00','00','00','00','20','00','00','00','00','00','00','00','00','00','00','00','00','00','00','00','00','83','00','00','00','00','00','00','00','00','00','04','83','03','01','cf','20']
intBrightnessArr = []
for x in hexBrightnessArr:
intBrightnessArr.append(int(x, 16))
maxBrightness = 100
if self._hs_color is None:
maxBrightness = 100
brightnessval = int((((self._brightness - 0) * (maxBrightness - 0)) / (255 - 0)) + 0)
intBrightnessArr[41] = brightnessval
_LOGGER.info(brightnessval)
bytes = bytearray(intBrightnessArr)
self._socket.send(bytes)
#Colour
if self._hs_color is not None:
rgb = list(color_util.color_hs_to_RGB(*self._hs_color))
hexColourArr = ['53','5a','30','30','00','00','00','00','00','23','00','00','00','00','00','00','00','00','00','00','00','00','00','00','00','00','5a','00','00','00','00','00','00','00','00','00','04','5a','06','02','ff','00','ff','00','04']
intColourArr = []
for x in hexColourArr:
intColourArr.append(int(x, 16))
intColourArr[42] = rgb[0] if rgb[0] < 255 else 255
intColourArr[43] = rgb[1] if rgb[1] < 255 else 255
intColourArr[44] = rgb[2] if rgb[2] < 255 else 255
bytes = bytearray(intColourArr)
self._socket.send(bytes)
if self._effect is not None:
effects_map = {
EFFECT_SAVASANA: '535a3030000000000023000000000000000000000000000000004400000000000000000004440602ff04970400',
EFFECT_SUNRISE: '535a3030000000000023000000000000000000000000000000004500000000000000000004450602ff01c10a00',
EFFECT_UNICORNS: '535a3030000000000023000000000000000000000000000000004600000000000000000004460602ff049a0e00',
EFFECT_PENSIVE: '535a3030000000000023000000000000000000000000000000004700000000000000000004470602ff04c40600',
EFFECT_CIRCUS: '535a3030000000000023000000000000000000000000000000004800000000000000000004480602ff04810130',
EFFECT_INSTAGRAMMER: '535a3030000000000023000000000000000000000000000000004900000000000000000004490602ff03bc0190',
EFFECT_EIGHTIESCLUB: '535a3030000000000023000000000000000000000000000000004a000000000000000000044a0602ff049a0000',
EFFECT_CHERRYBLOSSOMS: '535a3030000000000023000000000000000000000000000000004b000000000000000000044b0602ff04940800',
EFFECT_COCKTAILPARADE: '535a3030000000000023000000000000000000000000000000004100000000000000000004410602ff05bd0690',
EFFECT_CUSTOMIZED: '535a3030000000000023000000000000000000000000000000004c000000000000000000044c0602ff06940900',
}
effectCommand = effects_map[self._effect]
decode_hex = codecs.getdecoder("hex_codec")
self._socket.send(decode_hex(effectCommand)[0])
def turn_off(self, **kwargs):
"""Turn the device off."""
self._socket.connect((IPADDR, PORTNUM))
decode_hex = codecs.getdecoder("hex_codec")
self._socket.send(decode_hex('535a3030000000000020000000000000000000000000000000003800000000000000000004380301ce1e')[0])
self._isOn=False