def set_light(address, light, data, rgb=None): for key, value in data.items(): light["state"][key] = value on = light["state"]["on"] if on: sendOnCmd(address) colormode = light["state"]["colormode"] if colormode == "xy": xy = light["state"]["xy"] if rgb: r, g, b = rgbBrightness(rgb, light["state"]["bri"]) else: r, g, b = convert_xy(xy[0], xy[1], light["state"]["bri"]) (hue, saturation, value) = colorsys.rgb_to_hsv(r, g, b) sendHueCmd(address, hue * 255) sendSaturationCmd(address, (1 - saturation) * 100) elif colormode == "ct": ct = light["state"]["ct"] ct01 = (ct - 153) / (500 - 153 ) #map color temperature from 153-500 to 0-1 sendKelvinCmd(address, (1 - ct01) * 100) sendBrightnessCmd(address, (light["state"]["bri"] / 255) * 100) if not on: sendOffCmd(address)
def set_light(address, light, data, rgb=None): logging.debug("tasmota: <set_light> invoked! IP=" + address["ip"]) for key, value in data.items(): logging.debug("tasmota: key " + key) if key == "on": if value: sendRequest("http://" + address["ip"] + "/cm?cmnd=Power%20on") else: sendRequest("http://" + address["ip"] + "/cm?cmnd=Power%20off") elif key == "bri": brightness = int(100.0 * (value / 254.0)) sendRequest("http://" + address["ip"] + "/cm?cmnd=Dimmer%20" + str(brightness)) elif key == "ct": color = {} elif key == "xy": if rgb: color = rgbBrightness(rgb, light["state"]["bri"]) else: color = convert_xy(value[0], value[1], light["state"]["bri"]) sendRequest("http://" + address["ip"] + "/cm?cmnd=Color%20" + str(color[0]) + "," + str(color[1]) + "," + str(color[2])) elif key == "alert": if value == "select": sendRequest("http://" + address["ip"] + "/cm?cmnd=dimmer%20100")
def set_light(address, light, data, rgb = None): ip = address["ip"] if ip in Connections: c = Connections[ip] else: c = YeelightConnection(ip) Connections[ip] = c method = 'TCP' payload = {} transitiontime = 400 cmdPrefix = '' if "backlight" in address and address["backlight"]: cmdPrefix = "bg_" if "transitiontime" in data: transitiontime = int(data["transitiontime"] * 100) for key, value in data.items(): if key == "on": if value: payload[cmdPrefix + "set_power"] = ["on", "smooth", transitiontime] else: payload[cmdPrefix + "set_power"] = ["off", "smooth", transitiontime] elif key == "bri": payload[cmdPrefix + "set_bright"] = [int(value / 2.55) + 1, "smooth", transitiontime] elif key == "ct": #if ip[:-3] == "201" or ip[:-3] == "202": if light["name"].find("desklamp") > 0: if value > 369: value = 369 payload[cmdPrefix + "set_ct_abx"] = [int((-4800/347) * value + 2989900/347), "smooth", transitiontime] elif key == "hue": payload[cmdPrefix + "set_hsv"] = [int(value / 182), int(light["state"]["sat"] / 2.54), "smooth", transitiontime] elif key == "sat": payload[cmdPrefix + "set_hsv"] = [int(light["state"]["hue"] / 182), int(value / 2.54), "smooth", transitiontime] elif key == "xy": bri = light["state"]["bri"] if rgb: color = rgbBrightness(rgb, bri) else: color = convert_xy(value[0], value[1], bri) payload[cmdPrefix + "set_rgb"] = [(color[0] * 65536) + (color[1] * 256) + color[2], "smooth", transitiontime] #according to docs, yeelight needs this to set rgb. its r * 65536 + g * 256 + b elif key == "alert" and value != "none": payload[cmdPrefix + "start_cf"] = [ 4, 0, "1000, 2, 5500, 100, 1000, 2, 5500, 1, 1000, 2, 5500, 100, 1000, 2, 5500, 1"] # yeelight uses different functions for each action, so it has to check for each function # see page 9 http://www.yeelight.com/download/Yeelight_Inter-Operation_Spec.pdf # check if hue wants to change brightness for key, value in payload.items(): try: c.command(key, value) except Exception as e: if not c._music and c._connected: c.disconnect() raise e if not c._music and c._connected: c.disconnect()
def set_light(address, light, data, rgb=None): global prevOn # Assign all data elements to the "Object" light. for key, value in data.items(): light["state"][key] = value on = light["state"]["on"] colormode = light["state"]["colormode"] if (on != prevOn): sendOnCmd(address) if (('xy' in data) or ('ct' in data) or rgb): if (colormode == "xy"): if rgb: # this one is more performant than the "else" block r, g, b = rgbBrightness(rgb, light["state"]["bri"]) else: xy = light["state"]["xy"] r, g, b = convert_xy(xy[0], xy[1], light["state"]["bri"]) (hue, saturation, value) = colorsys.rgb_to_hsv(r, g, b) sendHueCmd(address, hue * 255) sendSaturationCmd(address, (1 - saturation) * 100) elif colormode == "ct": ct = light["state"]["ct"] ct01 = (ct - 153) / (500 - 153 ) # map color temperature from 153-500 to 0-1 sendKelvinCmd(address, (1 - ct01) * 100) if ("bri" in data): sendBrightnessCmd(address, (light["state"]["bri"] / 255) * 100) if not on: sendOffCmd(address) prevOn = on
def set_light(address, light, data, rgb=None): logging.debug("ESPHome: <set_light> invoked! IP=" + address["ip"]) logging.debug(light["modelid"]) logging.debug(data) ct_boost = int(address["ct_boost"]) rgb_boost = int(address["rgb_boost"]) request_data = "" # one breath cycle, temporary for now until breath implemented in esphome firmware if ("alert" in data) and (data['alert'] == "select"): request_data = request_data + "/switch/alert/turn_on" # elif ("alert" in data) and (data['alert'] == "lselect"): #15 second breath cycle # request_data = request_data + "/switch/alert/turn_on" # elif ("alert" in data) and (data['alert'] == "none"): # request_data = request_data + "/switch/alert/turn_off" else: request_data = request_data + getLightType(light, address, data) if "white_led" in request_data: postRequest(address["ip"], "/light/color_led/turn_off") else: postRequest(address["ip"], "/light/white_led/turn_off") if "on" in data: if not (data['on']): request_data = request_data + "/turn_off" else: request_data = request_data + "/turn_on" else: request_data = request_data + "/turn_on" if address["esphome_model"] != "ESPHome-Toggle": if "bri" in data: brightness = int(data['bri']) if address["esphome_model"] == "ESPHome-RGBW": if light["state"]["colormode"] == "ct": brightness = ct_boost + brightness elif light["state"]["colormode"] == "xy": brightness = rgb_boost + brightness elif address["esphome_model"] == "ESPHome-CT": brightness = ct_boost + brightness elif address["esphome_model"] == "ESPHome-RGB": brightness = rgb_boost + brightness elif address["esphome_model"] == "ESPHome-Dimmable": brightness = ct_boost + brightness if brightness > 255: # do not send brightness values over 255 brightness = 255 request_data = addRequest(request_data, "brightness", brightness) if address["esphome_model"] in [ "ESPHome-RGBW", "ESPHome-RGB", "ESPHome-CT" ]: if ("xy" in data) and (address["esphome_model"] in ["ESPHome-RGBW", "ESPHome-RGB"]): if rgb: color = rgbBrightness(rgb, light["state"]["bri"]) else: color = convert_xy(data['xy'][0], data['xy'][1], light["state"]["bri"]) request_data = addRequest(request_data, "r", color[0]) request_data = addRequest(request_data, "g", color[1]) request_data = addRequest(request_data, "b", color[2]) elif "ct" in data and (address["esphome_model"] in ["ESPHome-RGBW", "ESPHome-CT"]): request_data = addRequest(request_data, "color_temp", data['ct']) elif (("hue" in data) or ("sat" in data)) and (address["esphome_model"] in [ "ESPHome-RGBW", "ESPHome-RGB" ]): if (("hue" in data) and ("sat" in data)): hue = data['hue'] sat = data['sat'] elif "hue" in data: hue = data['hue'] sat = light["state"]["sat"] elif "sat" in data: hue = light["state"]["hue"] sat = data['sat'] if "bri" not in data: bri = light["state"]["bri"] else: bri = data['bri'] color = hsv_to_rgb(hue, sat, bri) request_data = addRequest(request_data, "r", color[0]) request_data = addRequest(request_data, "g", color[1]) request_data = addRequest(request_data, "b", color[2]) if "transitiontime" in data: request_data = addRequest(request_data, "transition", data['transitiontime'] / 10) else: # Utilize default interval of 0.4 request_data = addRequest(request_data, "transition", 0.4) postRequest(address["ip"], request_data)
def sendLightRequest(light, data, lights, addresses, rgb=None, entertainmentHostIP=None): payload = {} if light in addresses: protocol_name = addresses[light]["protocol"] for protocol in protocols: if "protocols." + protocol_name == protocol.__name__: try: if entertainmentHostIP and protocol_name == "yeelight": protocol.enableMusic(addresses[light]["ip"], entertainmentHostIP) if protocol_name in [ "yeelight", "mi_box", "esphome", "tasmota" ]: protocol.set_light(addresses[light], lights[light], data, rgb) else: protocol.set_light(addresses[light], lights[light], data) except Exception as e: lights[light]["state"]["reachable"] = False logging.warning( lights[light]["name"] + " light not reachable: %s", e) return if addresses[light]["protocol"] == "native": #ESP8266 light or strip url = "http://" + addresses[light]["ip"] + "/set?light=" + str( addresses[light]["light_nr"]) method = 'GET' for key, value in data.items(): if key == "xy": url += "&x=" + str(value[0]) + "&y=" + str(value[1]) else: url += "&" + key + "=" + str(value) elif addresses[light]["protocol"] in [ "hue", "deconz" ]: #Original Hue light or Deconz light url = "http://" + addresses[light]["ip"] + "/api/" + addresses[ light]["username"] + "/lights/" + addresses[light][ "light_id"] + "/state" method = 'PUT' payload.update(data) elif addresses[light]["protocol"] == "domoticz": #Domoticz protocol url = "http://" + addresses[light][ "ip"] + "/json.htm?type=command&idx=" + addresses[light][ "light_id"] method = 'GET' if "on" in data and not "bri" in data and not "ct" in data and not "xy" in data: for key, value in data.items(): url += "¶m=switchlight" if key == "on": if value: url += "&switchcmd=On" else: url += "&switchcmd=Off" else: url += "¶m=setcolbrightnessvalue" color_data = {} old_light_state = lights[light]["state"] colormode = old_light_state["colormode"] ct = old_light_state["ct"] bri = old_light_state["bri"] xy = old_light_state["xy"] if "bri" in data: bri = data["bri"] if "ct" in data: ct = data["ct"] if "xy" in data: xy = data["xy"] bri = int(bri) color_data[ "m"] = 1 #0: invalid, 1: white, 2: color temp, 3: rgb, 4: custom if colormode == "ct": color_data["m"] = 2 ct01 = (ct - 153) / ( 500 - 153) #map color temperature from 153-500 to 0-1 ct255 = ct01 * 255 #map color temperature from 0-1 to 0-255 color_data["t"] = ct255 elif colormode == "xy": color_data["m"] = 3 if rgb: (color_data["r"], color_data["g"], color_data["b"]) = rgbBrightness(rgb, bri) else: (color_data["r"], color_data["g"], color_data["b"]) = convert_xy(xy[0], xy[1], bri) url += "&color=" + json.dumps(color_data) url += "&brightness=" + str(round(float(bri) / 255 * 100)) urlObj = {} urlObj["url"] = url elif addresses[light]["protocol"] == "jeedom": #Jeedom protocol url = "http://" + addresses[light][ "ip"] + "/core/api/jeeApi.php?apikey=" + addresses[light][ "light_api"] + "&type=cmd&id=" method = 'GET' for key, value in data.items(): if key == "on": if value: url += addresses[light]["light_on"] else: url += addresses[light]["light_off"] elif key == "bri": url += addresses[light]["light_slider"] + "&slider=" + str( round(float(value) / 255 * 100) ) # jeedom range from 0 to 100 (for zwave devices) instead of 0-255 of bridge elif addresses[light]["protocol"] == "milight": #MiLight bulb url = "http://" + addresses[light][ "ip"] + "/gateways/" + addresses[light][ "device_id"] + "/" + addresses[light]["mode"] + "/" + str( addresses[light]["group"]) method = 'PUT' for key, value in data.items(): if key == "on": payload["status"] = value elif key == "bri": payload["brightness"] = value elif key == "ct": payload["color_temp"] = int(value / 1.6 + 153) elif key == "hue": payload["hue"] = value / 180 elif key == "sat": payload["saturation"] = value * 100 / 255 elif key == "xy": payload["color"] = {} if rgb: payload["color"]["r"], payload["color"]["g"], payload[ "color"]["b"] = rgbBrightness( rgb, lights[light]["state"]["bri"]) else: payload["color"]["r"], payload["color"]["g"], payload[ "color"]["b"] = convert_xy( value[0], value[1], lights[light]["state"]["bri"]) logging.info(json.dumps(payload)) elif addresses[light][ "protocol"] == "ikea_tradfri": #IKEA Tradfri bulb url = "coaps://" + addresses[light]["ip"] + ":5684/15001/" + str( addresses[light]["device_id"]) for key, value in data.items(): if key == "on": payload["5850"] = int(value) elif key == "transitiontime": payload["5712"] = value elif key == "bri": if value > 254: value = 254 payload["5851"] = value elif key == "ct": if value < 270: payload["5706"] = "f5faf6" elif value < 385: payload["5706"] = "f1e0b5" else: payload["5706"] = "efd275" elif key == "xy": payload["5709"] = int(value[0] * 65535) payload["5710"] = int(value[1] * 65535) if "hue" in data or "sat" in data: if ("hue" in data): hue = data["hue"] else: hue = lights[light]["state"]["hue"] if ("sat" in data): sat = data["sat"] else: sat = lights[light]["state"]["sat"] if ("bri" in data): bri = data["bri"] else: bri = lights[light]["state"]["bri"] rgbValue = hsv_to_rgb(hue, sat, bri) xyValue = convert_rgb_xy(rgbValue[0], rgbValue[1], rgbValue[2]) payload["5709"] = int(xyValue[0] * 65535) payload["5710"] = int(xyValue[1] * 65535) if "5850" in payload and payload["5850"] == 0: payload.clear( ) #setting brightnes will turn on the ligh even if there was a request to power off payload["5850"] = 0 elif "5850" in payload and "5851" in payload: #when setting brightness don't send also power on command del payload["5850"] elif addresses[light]["protocol"] == "flex": msg = bytearray() if "on" in data: if data["on"]: msg = bytearray([0x71, 0x23, 0x8a, 0x0f]) else: msg = bytearray([0x71, 0x24, 0x8a, 0x0f]) checksum = sum(msg) & 0xFF msg.append(checksum) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP sock.sendto(msg, (addresses[light]["ip"], 48899)) if ("bri" in data and lights[light]["state"]["colormode"] == "xy") or "xy" in data: logging.info(pretty_json(data)) bri = data["bri"] if "bri" in data else lights[light]["state"][ "bri"] xy = data["xy"] if "xy" in data else lights[light]["state"][ "xy"] if rgb: color = rgbBrightness(rgb, bri) else: color = convert_xy(xy[0], xy[1], bri) msg = bytearray( [0x41, color[0], color[1], color[2], 0x00, 0xf0, 0x0f]) checksum = sum(msg) & 0xFF msg.append(checksum) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP sock.sendto(msg, (addresses[light]["ip"], 48899)) elif ("bri" in data and lights[light]["state"]["colormode"] == "ct") or "ct" in data: bri = data["bri"] if "bri" in data else lights[light]["state"][ "bri"] msg = bytearray([0x41, 0x00, 0x00, 0x00, bri, 0x0f, 0x0f]) checksum = sum(msg) & 0xFF msg.append(checksum) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP sock.sendto(msg, (addresses[light]["ip"], 48899)) try: if addresses[light]["protocol"] == "ikea_tradfri": if "5712" not in payload: payload[ "5712"] = 4 #If no transition add one, might also add check to prevent large transitiontimes check_output("./coap-client-linux -m put -u \"" + addresses[light]["identity"] + "\" -k \"" + addresses[light]["preshared_key"] + "\" -e '{ \"3311\": [" + json.dumps(payload) + "] }' \"" + url + "\"", shell=True) elif addresses[light]["protocol"] in ["hue", "deconz"]: color = {} if "xy" in payload: color["xy"] = payload["xy"] del (payload["xy"]) elif "ct" in payload: color["ct"] = payload["ct"] del (payload["ct"]) elif "hue" in payload: color["hue"] = payload["hue"] del (payload["hue"]) elif "sat" in payload: color["sat"] = payload["sat"] del (payload["sat"]) if len(payload) != 0: sendRequest(url, method, json.dumps(payload)) if addresses[light]["protocol"] == "deconz": sleep(0.7) if len(color) != 0: if "transitiontime" in payload: color["transitiontime"] = payload["transitiontime"] if "bri" in payload and not "ct" in payload: color["bri"] = payload["bri"] sendRequest(url, method, json.dumps(color)) else: sendRequest(url, method, json.dumps(payload)) except: lights[light]["state"]["reachable"] = False logging.info("request error") else: lights[light]["state"]["reachable"] = True logging.info("LightRequest: " + url)