From f939b7a123d101b9be2e695cb6eeca4744b98f10 Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 3 Nov 2017 12:06:48 +0200 Subject: [PATCH 01/28] first try to implement new tradfry gateway login --- BridgeEmulator/HueEmulator.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 282fb022..e9f70357 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -500,7 +500,7 @@ def sendLightRequest(light, data): else: transitiontime = 4 for key, value in payload.iteritems(): #ikea bulbs don't accept all arguments at once - print(check_output("./coap-client-linux -m put -u \"Client_identity\" -k \"" + bridge_config["lights_address"][light]["security_code"] + "\" -e '{ \"3311\": [" + json.dumps({key : value, "5712": transitiontime}) + "] }' \"" + url + "\"", shell=True).split("\n")[3]) + print(check_output("./coap-client-linux -m put -u \"Hue_emulator\" -k \"" + bridge_config["lights_address"][light]["preshared_key"] + "\" -e '{ \"3311\": [" + json.dumps({key : value, "5712": transitiontime}) + "] }' \"" + url + "\"", shell=True).split("\n")[3]) sleep(0.5) elif bridge_config["lights_address"][light]["protocol"] in ["hue", "deconz"]: print("scene details:") @@ -591,7 +591,7 @@ def syncWithLights(): #update Hue Bridge lights states bridge_config["lights"][light]["state"]["reachable"] = False elif bridge_config["lights_address"][light]["protocol"] == "ikea_tradfri": try: - light_stats = json.loads(check_output("./coap-client-linux -m get -u \"Client_identity\" -k \"" + bridge_config["lights_address"][light]["security_code"] + "\" \"coaps://" + bridge_config["lights_address"][light]["ip"] + ":5684/15001/" + str(bridge_config["lights_address"][light]["device_id"]) +"\"", shell=True).split("\n")[3]) + light_stats = json.loads(check_output("./coap-client-linux -m get -u \"Hue_emulator\" -k \"" + bridge_config["lights_address"][light]["preshared_key"] + "\" \"coaps://" + bridge_config["lights_address"][light]["ip"] + ":5684/15001/" + str(bridge_config["lights_address"][light]["device_id"]) +"\"", shell=True).split("\n")[3]) bridge_config["lights"][light]["state"]["on"] = bool(light_stats["3311"][0]["5850"]) bridge_config["lights"][light]["state"]["bri"] = light_stats["3311"][0]["5851"] if "5706" in light_stats["3311"][0]: @@ -954,11 +954,14 @@ def do_GET(self): self._set_headers_html() get_parameters = parse_qs(urlparse(self.path).query) if "code" in get_parameters: - tradri_devices = json.loads(check_output("./coap-client-linux -m get -u \"Client_identity\" -k \"" + get_parameters["code"][0] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001\"", shell=True).split("\n")[3]) + #register new identity + preshared_key = json.loads(check_output("./coap-client-linux -m post -u \"Client_identity\" -k \"" + get_parameters["code"][0] + "\" -e '{\"9090\":\"Hue_emulator\"}' \"coaps://" + get_parameters["ip"][0] + ":5684/15011/9063\"", shell=True).split("\n")[3]) + + tradri_devices = json.loads(check_output("./coap-client-linux -m get -u \"Hue_emulator\" -k \"" + preshared_key["9091"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001\"", shell=True).split("\n")[3]) pprint(tradri_devices) lights_found = 0 for device in tradri_devices: - device_parameters = json.loads(check_output("./coap-client-linux -m get -u \"Client_identity\" -k \"" + get_parameters["code"][0] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001/" + str(device) +"\"", shell=True).split("\n")[3]) + device_parameters = json.loads(check_output("./coap-client-linux -m get -u \"Hue_emulator\" -k \"" + preshared_key["9091"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001/" + str(device) +"\"", shell=True).split("\n")[3]) if "3311" in device_parameters: lights_found += 1 #register new tradfri light @@ -966,7 +969,7 @@ def do_GET(self): new_light_id = nextFreeId("lights") bridge_config["lights"][new_light_id] = {"state": {"on": False, "bri": 200, "hue": 0, "sat": 0, "xy": [0.0, 0.0], "ct": 461, "alert": "none", "effect": "none", "colormode": "ct", "reachable": True}, "type": "Extended color light", "name": device_parameters["9001"], "uniqueid": "1234567" + str(device), "modelid": "LLM010", "swversion": "66009461"} new_lights.update({new_light_id: {"name": device_parameters["9001"]}}) - bridge_config["lights_address"][new_light_id] = {"device_id": device, "security_code": get_parameters["code"][0], "ip": get_parameters["ip"][0], "protocol": "ikea_tradfri"} + bridge_config["lights_address"][new_light_id] = {"device_id": device, "preshared_key": preshared_key["9091"], "ip": get_parameters["ip"][0], "protocol": "ikea_tradfri"} if lights_found == 0: self.wfile.write(webformTradfri() + "
No lights where found") else: From f713a25ac6de25981843c9f20f9b7f70e433cc4f Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Wed, 15 Nov 2017 16:50:08 +0200 Subject: [PATCH 02/28] Perform light requests one by one --- BridgeEmulator/HueEmulator.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index e9f70357..268a2629 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -1238,7 +1238,7 @@ def do_PUT(self): bridge_config["lights"][light]["state"]["colormode"] = "ct" elif "hue" or "sat" in bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]: bridge_config["lights"][light]["state"]["colormode"] = "hs" - Thread(target=sendLightRequest, args=[light, bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]]).start() + sendLightRequest(light, bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]]) updateGroupStats(light) elif "bri_inc" in put_dictionary: bridge_config["groups"][url_pices[4]]["action"]["bri"] += int(put_dictionary["bri_inc"]) @@ -1251,7 +1251,7 @@ def do_PUT(self): put_dictionary.update({"bri": bridge_config["groups"][url_pices[4]]["action"]["bri"]}) for light in bridge_config["groups"][url_pices[4]]["lights"]: bridge_config["lights"][light]["state"].update(put_dictionary) - Thread(target=sendLightRequest, args=[light, put_dictionary]).start() + sendLightRequest(light, put_dictionary]) elif "ct_inc" in put_dictionary: bridge_config["groups"][url_pices[4]]["action"]["ct"] += int(put_dictionary["ct_inc"]) if bridge_config["groups"][url_pices[4]]["action"]["ct"] > 500: @@ -1263,13 +1263,13 @@ def do_PUT(self): put_dictionary.update({"ct": bridge_config["groups"][url_pices[4]]["action"]["ct"]}) for light in bridge_config["groups"][url_pices[4]]["lights"]: bridge_config["lights"][light]["state"].update(put_dictionary) - Thread(target=sendLightRequest, args=[light, put_dictionary]).start() + sendLightRequest(light, put_dictionary]) elif "scene_inc" in put_dictionary: switchScene(url_pices[4], put_dictionary["scene_inc"]) elif url_pices[4] == "0": #if group is 0 the scene applied to all lights for light in bridge_config["lights"].iterkeys(): bridge_config["lights"][light]["state"].update(put_dictionary) - Thread(target=sendLightRequest, args=[light, put_dictionary]).start() + sendLightRequest(light, put_dictionary]) for group in bridge_config["groups"].iterkeys(): bridge_config["groups"][group][url_pices[5]].update(put_dictionary) if "on" in put_dictionary: @@ -1282,9 +1282,9 @@ def do_PUT(self): bridge_config["groups"][url_pices[4]]["state"]["on"] = put_dictionary["on"] for light in bridge_config["groups"][url_pices[4]]["lights"]: bridge_config["lights"][light]["state"].update(put_dictionary) - Thread(target=sendLightRequest, args=[light, put_dictionary]).start() + sendLightRequest(light, put_dictionary]) elif url_pices[3] == "lights": #state is applied to a light - Thread(target=sendLightRequest, args=[url_pices[4], put_dictionary]).start() + sendLightRequest(url_pices[4], put_dictionary]) for key in put_dictionary.iterkeys(): if key in ["ct", "xy"]: #colormode must be set by bridge bridge_config["lights"][url_pices[4]]["state"]["colormode"] = key From 5818c2d6d5ea33a485f5c287483cb358fa34a380 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Wed, 15 Nov 2017 22:44:12 +0200 Subject: [PATCH 03/28] Fix compile error --- BridgeEmulator/HueEmulator.py | 70 +++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 268a2629..51f3f767 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -281,7 +281,7 @@ def switchScene(group, direction): bridge_config["lights"][light]["state"]["colormode"] = "ct" elif "hue" or "sat" in bridge_config["scenes"][matched_scene]["lightstates"][light]: bridge_config["lights"][light]["state"]["colormode"] = "hs" - Thread(target=sendLightRequest, args=[light, bridge_config["scenes"][matched_scene]["lightstates"][light]]).start() + sendLightRequest(light, bridge_config["scenes"][matched_scene]["lightstates"][light]) updateGroupStats(light) @@ -362,7 +362,7 @@ def rulesProcessor(sensor): print("ddx rule " + rule + " will be re validated after " + str(rule_result[1]) + " seconds") Thread(target=ddxRecheck, args=[rule, sensor, rule_result[1]]).start() -def sendRequest(url, method, data, time_out=3, delay=0): +def sendRequest(url, method, data, time_out=2, delay=0): if delay != 0: sleep(delay) if not url.startswith( 'http://' ): @@ -500,7 +500,7 @@ def sendLightRequest(light, data): else: transitiontime = 4 for key, value in payload.iteritems(): #ikea bulbs don't accept all arguments at once - print(check_output("./coap-client-linux -m put -u \"Hue_emulator\" -k \"" + bridge_config["lights_address"][light]["preshared_key"] + "\" -e '{ \"3311\": [" + json.dumps({key : value, "5712": transitiontime}) + "] }' \"" + url + "\"", shell=True).split("\n")[3]) + print(check_output("./coap-client-linux -m put -u \"Hue-EMulator\" -k \"" + bridge_config["lights_address"][light]["preshared_key"] + "\" -e '{ \"3311\": [" + json.dumps({key : value, "5712": transitiontime}) + "] }' \"" + url + "\"", shell=True).split("\n")[3]) sleep(0.5) elif bridge_config["lights_address"][light]["protocol"] in ["hue", "deconz"]: print("scene details:") @@ -570,6 +570,7 @@ def scanForLights(): #scan for ESP8266 lights and strips except Exception as e: print(ip + " is unknow device " + str(e)) scanDeconz() + scanTradfri() def syncWithLights(): #update Hue Bridge lights states for light in bridge_config["lights_address"]: @@ -591,7 +592,7 @@ def syncWithLights(): #update Hue Bridge lights states bridge_config["lights"][light]["state"]["reachable"] = False elif bridge_config["lights_address"][light]["protocol"] == "ikea_tradfri": try: - light_stats = json.loads(check_output("./coap-client-linux -m get -u \"Hue_emulator\" -k \"" + bridge_config["lights_address"][light]["preshared_key"] + "\" \"coaps://" + bridge_config["lights_address"][light]["ip"] + ":5684/15001/" + str(bridge_config["lights_address"][light]["device_id"]) +"\"", shell=True).split("\n")[3]) + light_stats = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["lights_address"][light]["preshared_key"] + "\" \"coaps://" + bridge_config["lights_address"][light]["ip"] + ":5684/15001/" + str(bridge_config["lights_address"][light]["device_id"]) +"\"", shell=True).split("\n")[3]) bridge_config["lights"][light]["state"]["on"] = bool(light_stats["3311"][0]["5850"]) bridge_config["lights"][light]["state"]["bri"] = light_stats["3311"][0]["5851"] if "5706" in light_stats["3311"][0]: @@ -617,6 +618,31 @@ def longPressButton(sensor, buttonevent): return +def scanTradfri(): + if "tradfri_psk" in bridge_config: + tradri_devices = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["tradfri_psk"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001\"", shell=True).split("\n")[3]) + pprint(tradri_devices) + lights_found = 0 + for device in tradri_devices: + device_parameters = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["tradfri_psk"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001/" + str(device) +"\"", shell=True).split("\n")[3]) + if "3311" in device_parameters: + new_light = True + for light in bridge_config["lights_address"]: + if bridge_config["lights_address"][light]["protocol"] == "ikea_tradfri" and bridge_config["lights_address"][light]["device_id"] == device: + new_light = False + break + if new_light: + lights_found += 1 + #register new tradfri lightdevice_id + print("register tradfi light " + device_parameters["9001"]) + new_light_id = nextFreeId("lights") + bridge_config["lights"][new_light_id] = {"state": {"on": False, "bri": 200, "hue": 0, "sat": 0, "xy": [0.0, 0.0], "ct": 461, "alert": "none", "effect": "none", "colormode": "ct", "reachable": True}, "type": "Extended color light", "name": device_parameters["9001"], "uniqueid": "1234567" + str(device), "modelid": "LLM010", "swversion": "66009461"} + new_lights.update({new_light_id: {"name": device_parameters["9001"]}}) + bridge_config["lights_address"][new_light_id] = {"device_id": device, "preshared_key": bridge_config["tradfri_psk"], "ip": get_parameters["ip"][0], "protocol": "ikea_tradfri"} + return lights_found + else: + return 0 + def websocketClient(): from ws4py.client.threadedclient import WebSocketClient class EchoClient(WebSocketClient): @@ -931,7 +957,7 @@ def updateAllLights(): payload["hue"] = bridge_config["lights"][light]["state"]["hue"] payload["sat"] = bridge_config["lights"][light]["state"]["sat"] - Thread(target=sendLightRequest, args=[light, payload]).start() + sendLightRequest(light, payload) sleep(0.5) print("update status for light " + light) @@ -955,21 +981,9 @@ def do_GET(self): get_parameters = parse_qs(urlparse(self.path).query) if "code" in get_parameters: #register new identity - preshared_key = json.loads(check_output("./coap-client-linux -m post -u \"Client_identity\" -k \"" + get_parameters["code"][0] + "\" -e '{\"9090\":\"Hue_emulator\"}' \"coaps://" + get_parameters["ip"][0] + ":5684/15011/9063\"", shell=True).split("\n")[3]) - - tradri_devices = json.loads(check_output("./coap-client-linux -m get -u \"Hue_emulator\" -k \"" + preshared_key["9091"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001\"", shell=True).split("\n")[3]) - pprint(tradri_devices) - lights_found = 0 - for device in tradri_devices: - device_parameters = json.loads(check_output("./coap-client-linux -m get -u \"Hue_emulator\" -k \"" + preshared_key["9091"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001/" + str(device) +"\"", shell=True).split("\n")[3]) - if "3311" in device_parameters: - lights_found += 1 - #register new tradfri light - print("register tradfi light " + device_parameters["9001"]) - new_light_id = nextFreeId("lights") - bridge_config["lights"][new_light_id] = {"state": {"on": False, "bri": 200, "hue": 0, "sat": 0, "xy": [0.0, 0.0], "ct": 461, "alert": "none", "effect": "none", "colormode": "ct", "reachable": True}, "type": "Extended color light", "name": device_parameters["9001"], "uniqueid": "1234567" + str(device), "modelid": "LLM010", "swversion": "66009461"} - new_lights.update({new_light_id: {"name": device_parameters["9001"]}}) - bridge_config["lights_address"][new_light_id] = {"device_id": device, "preshared_key": preshared_key["9091"], "ip": get_parameters["ip"][0], "protocol": "ikea_tradfri"} + registration = json.loads(check_output("./coap-client-linux -m post -u \"Client_identity\" -k \"" + get_parameters["code"][0] + "\" -e '{\"9090\":\"Hue-EMulator\"}' \"coaps://" + get_parameters["ip"][0] + ":5684/15011/9063\"", shell=True).split("\n")[3]) + bridge_config["tradfri_psk"] = registration["9091"] + lights_found = scanTradfri() if lights_found == 0: self.wfile.write(webformTradfri() + "
No lights where found") else: @@ -1139,7 +1153,7 @@ def do_POST(self): if ((url_pices[3] == "lights" or url_pices[3] == "sensors") and not bool(post_dictionary)): #if was a request to scan for lights of sensors Thread(target=scanForLights).start() - sleep(7) #give no more than 7 seconds for light scanning (otherwise will face app disconnection timeout) + sleep(5) #give no more than 5 seconds for light scanning (otherwise will face app disconnection timeout) self.wfile.write(json.dumps([{"success": {"/" + url_pices[3]: "Searching for new devices"}}])) else: #create object # find the first unused id for new object @@ -1238,7 +1252,7 @@ def do_PUT(self): bridge_config["lights"][light]["state"]["colormode"] = "ct" elif "hue" or "sat" in bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]: bridge_config["lights"][light]["state"]["colormode"] = "hs" - sendLightRequest(light, bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]]) + sendLightRequest(bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]) updateGroupStats(light) elif "bri_inc" in put_dictionary: bridge_config["groups"][url_pices[4]]["action"]["bri"] += int(put_dictionary["bri_inc"]) @@ -1251,7 +1265,7 @@ def do_PUT(self): put_dictionary.update({"bri": bridge_config["groups"][url_pices[4]]["action"]["bri"]}) for light in bridge_config["groups"][url_pices[4]]["lights"]: bridge_config["lights"][light]["state"].update(put_dictionary) - sendLightRequest(light, put_dictionary]) + sendLightRequest(light, put_dictionary) elif "ct_inc" in put_dictionary: bridge_config["groups"][url_pices[4]]["action"]["ct"] += int(put_dictionary["ct_inc"]) if bridge_config["groups"][url_pices[4]]["action"]["ct"] > 500: @@ -1263,13 +1277,13 @@ def do_PUT(self): put_dictionary.update({"ct": bridge_config["groups"][url_pices[4]]["action"]["ct"]}) for light in bridge_config["groups"][url_pices[4]]["lights"]: bridge_config["lights"][light]["state"].update(put_dictionary) - sendLightRequest(light, put_dictionary]) + sendLightRequest(light, put_dictionary) elif "scene_inc" in put_dictionary: switchScene(url_pices[4], put_dictionary["scene_inc"]) elif url_pices[4] == "0": #if group is 0 the scene applied to all lights for light in bridge_config["lights"].iterkeys(): bridge_config["lights"][light]["state"].update(put_dictionary) - sendLightRequest(light, put_dictionary]) + sendLightRequest(light, put_dictionary) for group in bridge_config["groups"].iterkeys(): bridge_config["groups"][group][url_pices[5]].update(put_dictionary) if "on" in put_dictionary: @@ -1282,9 +1296,9 @@ def do_PUT(self): bridge_config["groups"][url_pices[4]]["state"]["on"] = put_dictionary["on"] for light in bridge_config["groups"][url_pices[4]]["lights"]: bridge_config["lights"][light]["state"].update(put_dictionary) - sendLightRequest(light, put_dictionary]) + sendLightRequest(light, put_dictionary) elif url_pices[3] == "lights": #state is applied to a light - sendLightRequest(url_pices[4], put_dictionary]) + sendLightRequest(url_pices[4], put_dictionary) for key in put_dictionary.iterkeys(): if key in ["ct", "xy"]: #colormode must be set by bridge bridge_config["lights"][url_pices[4]]["state"]["colormode"] = key @@ -1353,7 +1367,7 @@ def run(server_class=HTTPServer, handler_class=S): if bridge_config["deconz"]["enabled"]: scanDeconz() try: - updateAllLights() + #updateAllLights() Thread(target=ssdpSearch).start() Thread(target=ssdpBroadcast).start() Thread(target=schedulerProcessor).start() From 3e890a9b2406473b417b30036a3f1f265c8ff6b2 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Sun, 19 Nov 2017 21:20:08 +0200 Subject: [PATCH 04/28] fix bug - add missing light argument --- BridgeEmulator/HueEmulator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 51f3f767..d82e41b4 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -1252,7 +1252,7 @@ def do_PUT(self): bridge_config["lights"][light]["state"]["colormode"] = "ct" elif "hue" or "sat" in bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]: bridge_config["lights"][light]["state"]["colormode"] = "hs" - sendLightRequest(bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]) + sendLightRequest(light, bridge_config["scenes"][put_dictionary["scene"]]["lightstates"][light]) updateGroupStats(light) elif "bri_inc" in put_dictionary: bridge_config["groups"][url_pices[4]]["action"]["bri"] += int(put_dictionary["bri_inc"]) From 6a35a039e2a3581598f1ed72a3c09a6b31314d93 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Sun, 19 Nov 2017 22:52:15 +0200 Subject: [PATCH 05/28] update description.xml content --- BridgeEmulator/HueEmulator.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index d82e41b4..d95d0095 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -779,7 +779,8 @@ def scanDeconz(): def description(): - return """ + return """ + 1 0 @@ -795,7 +796,16 @@ def description(): BSB002 http://www.meethue.com """ + mac.upper() + """ -MYUUID +uuid:2f402f80-da50-11e1-9b23-""" + mac + """ + + +(null) +(null) +(null) +(null) +(null) + + index.html From 15ef3dba1e4e8820910e2931ba1dd66c08757dc7 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 23 Nov 2017 21:16:41 +0200 Subject: [PATCH 06/28] update description.xml --- BridgeEmulator/HueEmulator.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index d95d0095..9cf85472 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -777,10 +777,9 @@ def scanDeconz(): - def description(): return """ - + 1 0 @@ -795,8 +794,8 @@ def description(): Philips hue bridge 2015 BSB002 http://www.meethue.com -""" + mac.upper() + """ -uuid:2f402f80-da50-11e1-9b23-""" + mac + """ +00008800bbee +uuid:2f402f80-da50-11e1-9b23-00008800bbee (null) @@ -818,13 +817,7 @@ def description(): image/png 120 -120 -24 -hue_logo_3.png - - - -""" +120 """ def webformTradfri(): return """ @@ -982,9 +975,14 @@ def _set_headers_html(self): self.send_header('Content-type', 'text/html') self.end_headers() + def _set_headers_xml(self): + self.send_response(200) + self.send_header('Content-type', 'application/xml') + self.end_headers() + def do_GET(self): if self.path == '/description.xml': - self._set_headers_html() + self._set_headers_xml() self.wfile.write(description()) elif self.path.startswith("/tradfri"): #setup Tradfri gateway self._set_headers_html() @@ -1377,7 +1375,7 @@ def run(server_class=HTTPServer, handler_class=S): if bridge_config["deconz"]["enabled"]: scanDeconz() try: - #updateAllLights() + updateAllLights() Thread(target=ssdpSearch).start() Thread(target=ssdpBroadcast).start() Thread(target=schedulerProcessor).start() From 997a7ccbdf56a0a330dee43985880bd235701bd1 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 23 Nov 2017 21:20:55 +0200 Subject: [PATCH 07/28] update description.xml --- BridgeEmulator/HueEmulator.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 9cf85472..f3dabd23 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -778,8 +778,8 @@ def scanDeconz(): def description(): - return """ - + return """ + 1 0 @@ -817,7 +817,14 @@ def description(): image/png 120 -120 """ +120 +24 +hue_logo_3.png + + + + +""" def webformTradfri(): return """ From a687b8b8071f288e364764661de182731ffec1ee Mon Sep 17 00:00:00 2001 From: Marius Date: Thu, 23 Nov 2017 22:07:14 +0200 Subject: [PATCH 08/28] add sketch for AI-Thinker_RGBW_Bulb --- Lights/Arduino/MY92XX_RGBW_Light/.DS_Store | Bin 0 -> 6148 bytes .../MY92XX_RGBW_Light/MY92XX_RGBW_Light.ino | 626 ++++++++++++++++++ Lights/Arduino/MY92XX_RGBW_Light/my92xx.cpp | 221 +++++++ Lights/Arduino/MY92XX_RGBW_Light/my92xx.h | 122 ++++ 4 files changed, 969 insertions(+) create mode 100644 Lights/Arduino/MY92XX_RGBW_Light/.DS_Store create mode 100644 Lights/Arduino/MY92XX_RGBW_Light/MY92XX_RGBW_Light.ino create mode 100644 Lights/Arduino/MY92XX_RGBW_Light/my92xx.cpp create mode 100644 Lights/Arduino/MY92XX_RGBW_Light/my92xx.h diff --git a/Lights/Arduino/MY92XX_RGBW_Light/.DS_Store b/Lights/Arduino/MY92XX_RGBW_Light/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ed1def276f50d2f28b3416024761c595b09718cf GIT binary patch literal 6148 zcmeHKJxfDD5S-N%0h@GMUTGy*+Z-XHf}Mq}Bz^@#9*F5*=g-#J-BS{tT3W~~?9Sc3 zox8j#-ev*VbaQ_SOaP4Oj(GDhG=J_su)UTsBAsWvV2K5886OAL-zS`VhzmSmP2c7( zafuCc*F5bB&v?ZNS8H@vt8Ou0b#pTPXP?oJ-@~|)NdYM!1*Cu!kOIFe;JueNK1fuQ z0#ZN +#include +#include +#include +#include +#include +#include +#include "my92xx.h" + +#define MY92XX_MODEL MY92XX_MODEL_MY9231 +#define MY92XX_CHIPS 1 +#define MY92XX_DI_PIN 12 +#define MY92XX_DCKI_PIN 14 + +#define PWM_CHANNELS 4 + +uint8_t PWM_PINS[PWM_CHANNELS] = {4, 3, 5, 6}; //RGBW order + +#define MY92XX_RED 4 +#define MY92XX_GREEN 3 +#define MY92XX_BLUE 5 + + +my92xx * _my92xx; + +// if you want to setup static ip uncomment these 3 lines and line 72 +//IPAddress strip_ip ( 192, 168, 10, 95); +//IPAddress gateway_ip ( 192, 168, 10, 1); +//IPAddress subnet_mask(255, 255, 255, 0); + +uint8_t rgbw[4], color_mode, scene; +bool light_state, in_transition; +int transitiontime, ct, hue, bri, sat; +float step_level[4], current_rgbw[4], x, y; +byte mac[6]; + +ESP8266WebServer server(80); + +void convert_hue() +{ + double hh, p, q, t, ff, s, v; + long i; + + rgbw[3] = 0; + s = sat / 255.0; + v = bri / 255.0; + + if (s <= 0.0) { // < is bogus, just shuts up warnings + rgbw[0] = v; + rgbw[1] = v; + rgbw[2] = v; + return; + } + hh = hue; + if (hh >= 65535.0) hh = 0.0; + hh /= 11850, 0; + i = (long)hh; + ff = hh - i; + p = v * (1.0 - s); + q = v * (1.0 - (s * ff)); + t = v * (1.0 - (s * (1.0 - ff))); + + switch (i) { + case 0: + rgbw[0] = v * 255.0; + rgbw[1] = t * 255.0; + rgbw[2] = p * 255.0; + break; + case 1: + rgbw[0] = q * 255.0; + rgbw[1] = v * 255.0; + rgbw[2] = p * 255.0; + break; + case 2: + rgbw[0] = p * 255.0; + rgbw[1] = v * 255.0; + rgbw[2] = t * 255.0; + break; + + case 3: + rgbw[0] = p * 255.0; + rgbw[1] = q * 255.0; + rgbw[2] = v * 255.0; + break; + case 4: + rgbw[0] = t * 255.0; + rgbw[1] = p * 255.0; + rgbw[2] = v * 255.0; + break; + case 5: + default: + rgbw[0] = v * 255.0; + rgbw[1] = p * 255.0; + rgbw[2] = q * 255.0; + break; + } + +} + +void convert_xy() +{ + float Y = bri / 250.0f; + + float z = 1.0f - x - y; + + float X = (Y / y) * x; + float Z = (Y / y) * z; + + // sRGB D65 conversion + float r = X * 3.2406f - Y * 1.5372f - Z * 0.4986f; + float g = -X * 0.9689f + Y * 1.8758f + Z * 0.0415f; + float b = X * 0.0557f - Y * 0.2040f + Z * 1.0570f; + + if (r > b && r > g && r > 1.0f) { + // red is too big + g = g / r; + b = b / r; + r = 1.0f; + } + else if (g > b && g > r && g > 1.0f) { + // green is too big + r = r / g; + b = b / g; + g = 1.0f; + } + else if (b > r && b > g && b > 1.0f) { + // blue is too big + r = r / b; + g = g / b; + b = 1.0f; + } + + // Apply gamma correction + r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f; + g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f; + b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f; + + if (r > b && r > g) { + // red is biggest + if (r > 1.0f) { + g = g / r; + b = b / r; + r = 1.0f; + } + } + else if (g > b && g > r) { + // green is biggest + if (g > 1.0f) { + r = r / g; + b = b / g; + g = 1.0f; + } + } + else if (b > r && b > g) { + // blue is biggest + if (b > 1.0f) { + r = r / b; + g = g / b; + b = 1.0f; + } + } + + r = r < 0 ? 0 : r; + g = g < 0 ? 0 : g; + b = b < 0 ? 0 : b; + + rgbw[0] = (int) (r * 255.0f); rgbw[1] = (int) (g * 255.0f); rgbw[2] = (int) (b * 255.0f); rgbw[3] = 0; +} + +void convert_ct() { + int hectemp = 10000 / ct; + int r, g, b; + if (hectemp <= 66) { + r = 255; + g = 99.4708025861 * log(hectemp) - 161.1195681661; + b = hectemp <= 19 ? 0 : (138.5177312231 * log(hectemp - 10) - 305.0447927307); + } else { + r = 329.698727446 * pow(hectemp - 60, -0.1332047592); + g = 288.1221695283 * pow(hectemp - 60, -0.0755148492); + b = 255; + } + r = r > 255 ? 255 : r; + g = g > 255 ? 255 : g; + b = b > 255 ? 255 : b; + rgbw[0] = r * (bri / 255.0f); rgbw[1] = g * (bri / 255.0f); rgbw[2] = b * (bri / 255.0f); rgbw[3] = bri; +} + +void handleNotFound() { + String message = "File Not Found\n\n"; + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + for (uint8_t i = 0; i < server.args(); i++) { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + server.send(404, "text/plain", message); +} + +void apply_scene(uint8_t new_scene) { + if ( new_scene == 0) { + bri = 144; ct = 447; color_mode = 2; convert_ct(); + } else if ( new_scene == 1) { + bri = 254; ct = 346; color_mode = 2; convert_ct(); + } else if ( new_scene == 2) { + bri = 254; ct = 233; color_mode = 2; convert_ct(); + } else if ( new_scene == 3) { + bri = 254; ct = 156; color_mode = 2; convert_ct(); + } else if ( new_scene == 4) { + bri = 77; ct = 367; color_mode = 2; convert_ct(); + } else if ( new_scene == 5) { + bri = 254; ct = 447; color_mode = 2; convert_ct(); + } else if ( new_scene == 6) { + bri = 1; x = 0.561; y = 0.4042; color_mode = 1; convert_xy(); + } else if ( new_scene == 7) { + bri = 203; x = 0.380328; y = 0.39986; color_mode = 1; convert_xy(); + } else if ( new_scene == 8) { + bri = 112; x = 0.359168; y = 0.28807; color_mode = 1; convert_xy(); + } else if ( new_scene == 9) { + bri = 142; x = 0.267102; y = 0.23755; color_mode = 1; convert_xy(); + } else if ( new_scene == 10) { + bri = 216; x = 0.393209; y = 0.29961; color_mode = 1; convert_xy(); + } +} + +void lightEngine() { + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + if (rgbw[color] != current_rgbw[color] ) { + in_transition = true; + current_rgbw[color] += step_level[color]; + if ((step_level[color] > 0.0f && current_rgbw[color] > rgbw[color]) || (step_level[color] < 0.0f && current_rgbw[color] < rgbw[color])) current_rgbw[color] = rgbw[color]; + _my92xx->setChannel(PWM_PINS[color], current_rgbw[color]); + _my92xx->update(); + } + } else { + if (current_rgbw[color] != 0) { + in_transition = true; + current_rgbw[color] -= step_level[color]; + if (current_rgbw[color] < 0.0f) current_rgbw[color] = 0; + _my92xx->setChannel(PWM_PINS[color], current_rgbw[color]); + _my92xx->update(); + } + } + } + if (in_transition) { + delay(6); + in_transition = false; + } +} + +void setup() { + EEPROM.begin(512); + + _my92xx = new my92xx(MY92XX_MODEL, MY92XX_CHIPS, MY92XX_DI_PIN, MY92XX_DCKI_PIN, MY92XX_COMMAND_DEFAULT); + _my92xx->setState(true); + + //WiFi.config(strip_ip, gateway_ip, subnet_mask); + + apply_scene(EEPROM.read(2)); + step_level[0] = rgbw[0] / 150.0; step_level[1] = rgbw[1] / 150.0; step_level[2] = rgbw[2] / 150.0; step_level[3] = rgbw[3] / 150.0; + + if (EEPROM.read(1) == 1 || (EEPROM.read(1) == 0 && EEPROM.read(0) == 1)) { + light_state = true; + for (uint8_t i = 0; i < 200; i++) { + lightEngine(); + } + } + WiFiManager wifiManager; + wifiManager.autoConnect("New Hue Light"); + /* if (! light_state) { + // Show that we are connected + pwm_set_duty(100, 1); + pwm_start(); + delay(500); + pwm_set_duty(0, 1); + pwm_start(); + } */ + WiFi.macAddress(mac); + + // Port defaults to 8266 + // ArduinoOTA.setPort(8266); + + // Hostname defaults to esp8266-[ChipID] + // ArduinoOTA.setHostname("myesp8266"); + + // No authentication by default + // ArduinoOTA.setPassword((const char *)"123"); + + ArduinoOTA.begin(); + + pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output + digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH + + server.on("/switch", []() { + server.send(200, "text/plain", "OK"); + int button; + for (uint8_t i = 0; i < server.args(); i++) { + if (server.argName(i) == "button") { + button = server.arg(i).toInt(); + } + } + if (button == 1000) { + if (light_state == false) { + light_state = true; + scene = 0; + } else { + apply_scene(scene); + scene++; + if (scene == 11) { + scene = 0; + } + } + } else if (button == 2000) { + if (light_state == false) { + bri = 30; + light_state = true; + } else { + bri += 30; + } + if (bri > 255) bri = 255; + if (color_mode == 1) convert_xy(); + else if (color_mode == 2) convert_ct(); + else if (color_mode == 3) convert_hue(); + } else if (button == 3000 && light_state == true) { + bri -= 30; + if (bri < 1) bri = 1; + else { + if (color_mode == 1) convert_xy(); + else if (color_mode == 2) convert_ct(); + else if (color_mode == 3) convert_hue(); + } + } else if (button == 4000) { + light_state = false; + } + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + step_level[color] = (rgbw[color] - current_rgbw[color]) / 54; + } else { + step_level[color] = current_rgbw[color] / 54; + } + } + }); + + + server.on("/set", []() { + light_state = true; + float transitiontime = 4; + for (uint8_t i = 0; i < server.args(); i++) { + if (server.argName(i) == "on") { + if (server.arg(i) == "True" || server.arg(i) == "true") { + if (EEPROM.read(1) == 0 && EEPROM.read(0) != 1) { + EEPROM.write(0, 1); + EEPROM.commit(); + } + light_state = true; + } + else { + if (EEPROM.read(1) == 0 && EEPROM.read(0) != 0) { + EEPROM.write(0, 0); + EEPROM.commit(); + } + light_state = false; + } + } + else if (server.argName(i) == "r") { + rgbw[0] = server.arg(i).toInt(); + color_mode = 0; + } + else if (server.argName(i) == "g") { + rgbw[1] = server.arg(i).toInt(); + color_mode = 0; + } + else if (server.argName(i) == "b") { + rgbw[2] = server.arg(i).toInt(); + color_mode = 0; + } + else if (server.argName(i) == "w") { + rgbw[3] = server.arg(i).toInt(); + color_mode = 0; + } + else if (server.argName(i) == "x") { + x = server.arg(i).toFloat(); + color_mode = 1; + } + else if (server.argName(i) == "y") { + y = server.arg(i).toFloat(); + color_mode = 1; + } + else if (server.argName(i) == "bri") { + if (server.arg(i).toInt() != 0) + bri = server.arg(i).toInt(); + } + else if (server.argName(i) == "bri_inc") { + bri += server.arg(i).toInt(); + if (bri > 255) bri = 255; + else if (bri < 0) bri = 0; + } + else if (server.argName(i) == "ct") { + ct = server.arg(i).toInt(); + color_mode = 2; + } + else if (server.argName(i) == "sat") { + sat = server.arg(i).toInt(); + color_mode = 3; + } + else if (server.argName(i) == "hue") { + hue = server.arg(i).toInt(); + color_mode = 3; + } + else if (server.argName(i) == "alert" && server.arg(i) == "select") { + if (light_state) { + current_rgbw[0] = 0; current_rgbw[1] = 0; current_rgbw[2] = 0; current_rgbw[3] = 0; + } else { + current_rgbw[0] = 255; current_rgbw[1] = 255; current_rgbw[2] = 255; current_rgbw[3] = 255; + } + } + else if (server.argName(i) == "transitiontime") { + transitiontime = server.arg(i).toInt(); + } + } + server.send(200, "text/plain", "OK, x: " + (String)x + ", y:" + (String)y + ", bri:" + (String)bri + ", ct:" + ct + ", colormode:" + color_mode + ", state:" + light_state); + if (color_mode == 1 && light_state == true) { + convert_xy(); + } else if (color_mode == 2 && light_state == true) { + convert_ct(); + } else if (color_mode == 3 && light_state == true) { + convert_hue(); + } + transitiontime *= 16; + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + step_level[color] = (rgbw[color] - current_rgbw[color]) / transitiontime; + } else { + step_level[color] = current_rgbw[color] / transitiontime; + } + } + }); + + server.on("/get", []() { + String colormode; + String power_status; + power_status = light_state ? "true" : "false"; + if (color_mode == 1) + colormode = "xy"; + else if (color_mode == 2) + colormode = "ct"; + else if (color_mode == 3) + colormode = "hs"; + server.send(200, "text/plain", "{\"on\": " + power_status + ", \"bri\": " + (String)bri + ", \"xy\": [" + (String)x + ", " + (String)y + "], \"ct\":" + (String)ct + ", \"sat\": " + (String)sat + ", \"hue\": " + (String)hue + ", \"colormode\": \"" + colormode + "\"}"); + }); + + server.on("/detect", []() { + server.send(200, "text/plain", "{\"hue\": \"bulb\",\"lights\": 1,\"modelid\": \"LCT001\",\"mac\": \"" + String(mac[5], HEX) + ":" + String(mac[4], HEX) + ":" + String(mac[3], HEX) + ":" + String(mac[2], HEX) + ":" + String(mac[1], HEX) + ":" + String(mac[0], HEX) + "\"}"); + }); + + server.on("/", []() { + float transitiontime = 100; + if (server.hasArg("startup")) { + if ( EEPROM.read(1) != server.arg("startup").toInt()) { + EEPROM.write(1, server.arg("startup").toInt()); + EEPROM.commit(); + } + } + + if (server.hasArg("scene")) { + if (server.arg("bri") == "" && server.arg("hue") == "" && server.arg("ct") == "" && server.arg("sat") == "") { + if ( EEPROM.read(2) != server.arg("scene").toInt() && EEPROM.read(1) < 2) { + EEPROM.write(2, server.arg("scene").toInt()); + EEPROM.commit(); + } + apply_scene(server.arg("scene").toInt()); + } else { + if (server.arg("bri") != "") { + bri = server.arg("bri").toInt(); + } + if (server.arg("hue") != "") { + hue = server.arg("hue").toInt(); + } + if (server.arg("sat") != "") { + sat = server.arg("sat").toInt(); + } + if (server.arg("ct") != "") { + ct = server.arg("ct").toInt(); + } + if (server.arg("colormode") == "1" && light_state == true) { + convert_xy(); + } else if (server.arg("colormode") == "2" && light_state == true) { + convert_ct(); + } else if (server.arg("colormode") == "3" && light_state == true) { + convert_hue(); + } + color_mode = server.arg("colormode").toInt(); + } + } else if (server.hasArg("on")) { + if (server.arg("on") == "true") { + light_state = true; { + if (EEPROM.read(1) == 0 && EEPROM.read(0) != 1) { + EEPROM.write(0, 1); + } + } + } else { + light_state = false; + if (EEPROM.read(1) == 0 && EEPROM.read(0) != 0) { + EEPROM.write(0, 0); + } + } + EEPROM.commit(); + } else if (server.hasArg("alert")) { + if (light_state) { + current_rgbw[0] = 0; current_rgbw[1] = 0; current_rgbw[2] = 0; current_rgbw[3] = 0; + } else { + current_rgbw[3] = 255; + } + } + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + step_level[color] = ((float)rgbw[color] - current_rgbw[color]) / transitiontime; + } else { + step_level[color] = current_rgbw[color] / transitiontime; + } + } + if (server.hasArg("reset")) { + ESP.reset(); + } + + + String http_content = ""; + http_content += ""; + http_content += ""; + http_content += ""; + http_content += ""; + http_content += "Light Setup"; + http_content += ""; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "

Light Setup

"; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += "ON"; + http_content += "OFF"; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += "alert or reset"; + http_content += ""; + http_content += ""; + http_content += "
"; + http_content += "
"; + http_content += ""; + http_content += ""; + http_content += ""; + + + server.send(200, "text/html", http_content); + + }); + + + server.onNotFound(handleNotFound); + + server.begin(); +} + +void loop() { + ArduinoOTA.handle(); + server.handleClient(); + lightEngine(); +} diff --git a/Lights/Arduino/MY92XX_RGBW_Light/my92xx.cpp b/Lights/Arduino/MY92XX_RGBW_Light/my92xx.cpp new file mode 100644 index 00000000..db00a0f5 --- /dev/null +++ b/Lights/Arduino/MY92XX_RGBW_Light/my92xx.cpp @@ -0,0 +1,221 @@ +/* + +MY92XX LED Driver Arduino library 3.0.0 +Based on the C driver by MaiKe Labs + +Copyright (c) 2016 - 2026 MaiKe Labs +Copyright (c) 2017 - Xose Pérez (for the library) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#include "my92xx.h" + +#if ARDUINO_ARCH_ESP8266 + + extern "C" { + void os_delay_us(unsigned int); + } + +#elif ARDUINO_ARCH_AVR + + #define os_delay_us delayMicroseconds + +#endif + +void my92xx::_di_pulse(unsigned int times) { + for (unsigned int i = 0; i < times; i++) { + digitalWrite(_pin_di, HIGH); + digitalWrite(_pin_di, LOW); + } +} + +void my92xx::_dcki_pulse(unsigned int times) { + for (unsigned int i = 0; i < times; i++) { + digitalWrite(_pin_dcki, HIGH); + digitalWrite(_pin_dcki, LOW); + } +} + +void my92xx::_write(unsigned int data, unsigned char bit_length) { + + unsigned int mask = (0x01 << (bit_length - 1)); + + for (unsigned int i = 0; i < bit_length / 2; i++) { + digitalWrite(_pin_dcki, LOW); + digitalWrite(_pin_di, (data & mask)); + digitalWrite(_pin_dcki, HIGH); + data = data << 1; + digitalWrite(_pin_di, (data & mask)); + digitalWrite(_pin_dcki, LOW); + digitalWrite(_pin_di, LOW); + data = data << 1; + } + +} + +void my92xx::_set_cmd(my92xx_cmd_t command) { + + // ets_intr_lock(); + + // TStop > 12us. + os_delay_us(12); + + // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 + // pulse's rising edge convert to command mode. + _di_pulse(12); + + // Delay >12us, begin send CMD data + os_delay_us(12); + + // Send CMD data + unsigned char command_data = *(unsigned char *) (&command); + for (unsigned char i=0; i<_chips; i++) { + _write(command_data, 8); + } + + // TStart > 12us. Delay 12 us. + os_delay_us(12); + + // Send 16 DI pulse,at 14 pulse's falling edge store CMD data, and + // at 16 pulse's falling edge convert to duty mode. + _di_pulse(16); + + // TStop > 12us. + os_delay_us(12); + + // ets_intr_unlock(); + +} + +void my92xx::_send() { + + #ifdef DEBUG_MY92XX + DEBUG_MSG_MY92XX("[MY92XX] Refresh: %s (", _state ? "ON" : "OFF"); + for (unsigned char channel = 0; channel < _channels; channel++) { + DEBUG_MSG_MY92XX(" %d", _value[channel]); + } + DEBUG_MSG_MY92XX(" )\n"); + #endif + + unsigned char bit_length = 8; + switch (_command.bit_width) { + case MY92XX_CMD_BIT_WIDTH_16: + bit_length = 16; + break; + case MY92XX_CMD_BIT_WIDTH_14: + bit_length = 14; + break; + case MY92XX_CMD_BIT_WIDTH_12: + bit_length = 12; + break; + case MY92XX_CMD_BIT_WIDTH_8: + bit_length = 8; + break; + default: + bit_length = 8; + break; + } + + // ets_intr_lock(); + + // TStop > 12us. + os_delay_us(12); + + // Send color data + for (unsigned char channel = 0; channel < _channels; channel++) { + _write(_state ? _value[channel] : 0, bit_length); + } + + // TStart > 12us. Ready for send DI pulse. + os_delay_us(12); + + // Send 8 DI pulse. After 8 pulse falling edge, store old data. + _di_pulse(8); + + // TStop > 12us. + os_delay_us(12); + + // ets_intr_unlock(); + +} + +// ----------------------------------------------------------------------------- + +unsigned char my92xx::getChannels() { + return _channels; +} + +void my92xx::setChannel(unsigned char channel, unsigned int value) { + if (0 <= channel && channel < _channels) { + _value[channel] = value; + } +} + +unsigned int my92xx::getChannel(unsigned char channel) { + if (0 <= channel && channel < _channels) { + return _value[channel]; + } + return 0; +} + +bool my92xx::getState() { + return _state; +} + +void my92xx::setState(bool state) { + _state = state; +} + +void my92xx::update() { + _send(); +} + +// ----------------------------------------------------------------------------- + +my92xx::my92xx(my92xx_model_t model, unsigned char chips, unsigned char di, unsigned char dcki, my92xx_cmd_t command) { + + _model = model; + _chips = chips; + _pin_di = di; + _pin_dcki = dcki; + _command = command; + + // Init channels + if (_model == MY92XX_MODEL_MY9291) { + _channels = 4 * _chips; + } else if (_model == MY92XX_MODEL_MY9231) { + _channels = 3 * _chips; + } + _value = new uint16_t(_channels); + for (unsigned char i=0; i<_channels; i++) { + _value[i] = 0; + } + + // Init GPIO + pinMode(_pin_di, OUTPUT); + pinMode(_pin_dcki, OUTPUT); + digitalWrite(_pin_di, LOW); + digitalWrite(_pin_dcki, LOW); + + // Clear all duty register + _dcki_pulse(32 * _chips); + + // Send init command + _set_cmd(command); + + DEBUG_MSG_MY92XX("[MY92XX] Initialized\n"); + +} diff --git a/Lights/Arduino/MY92XX_RGBW_Light/my92xx.h b/Lights/Arduino/MY92XX_RGBW_Light/my92xx.h new file mode 100644 index 00000000..444c82df --- /dev/null +++ b/Lights/Arduino/MY92XX_RGBW_Light/my92xx.h @@ -0,0 +1,122 @@ +/* + +MY92XX LED Driver Arduino library 3.0.0 + +Copyright (c) 2016 - 2026 MaiKe Labs +Copyright (C) 2017 - Xose Pérez + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*/ + +#ifndef _my92xx_h +#define _my92xx_h + +#include + +#ifdef DEBUG_MY92XX + #if ARDUINO_ARCH_ESP8266 + #define DEBUG_MSG_MY92XX(...) DEBUG_MY92XX.printf( __VA_ARGS__ ) + #elif ARDUINO_ARCH_AVR + #define DEBUG_MSG_MY92XX(...) { char buffer[80]; snprintf(buffer, sizeof(buffer), __VA_ARGS__ ); DEBUG_MY92XX.print(buffer); } + #endif +#else + #define DEBUG_MSG_MY92XX(...) +#endif + +typedef enum my92xx_model_t { + MY92XX_MODEL_MY9291 = 0X00, + MY92XX_MODEL_MY9231 = 0X01, +} my92xx_model_t; + +typedef enum my92xx_cmd_one_shot_t { + MY92XX_CMD_ONE_SHOT_DISABLE = 0X00, + MY92XX_CMD_ONE_SHOT_ENFORCE = 0X01, +} my92xx_cmd_one_shot_t; + +typedef enum my92xx_cmd_reaction_t { + MY92XX_CMD_REACTION_FAST = 0X00, + MY92XX_CMD_REACTION_SLOW = 0X01, +} my92xx_cmd_reaction_t; + +typedef enum my92xx_cmd_bit_width_t { + MY92XX_CMD_BIT_WIDTH_16 = 0X00, + MY92XX_CMD_BIT_WIDTH_14 = 0X01, + MY92XX_CMD_BIT_WIDTH_12 = 0X02, + MY92XX_CMD_BIT_WIDTH_8 = 0X03, +} my92xx_cmd_bit_width_t; + +typedef enum my92xx_cmd_frequency_t { + MY92XX_CMD_FREQUENCY_DIVIDE_1 = 0X00, + MY92XX_CMD_FREQUENCY_DIVIDE_4 = 0X01, + MY92XX_CMD_FREQUENCY_DIVIDE_16 = 0X02, + MY92XX_CMD_FREQUENCY_DIVIDE_64 = 0X03, +} my92xx_cmd_frequency_t; + +typedef enum my92xx_cmd_scatter_t { + MY92XX_CMD_SCATTER_APDM = 0X00, + MY92XX_CMD_SCATTER_PWM = 0X01, +} my92xx_cmd_scatter_t; + +typedef struct { + my92xx_cmd_scatter_t scatter:1; + my92xx_cmd_frequency_t frequency:2; + my92xx_cmd_bit_width_t bit_width:2; + my92xx_cmd_reaction_t reaction:1; + my92xx_cmd_one_shot_t one_shot:1; + unsigned char resv:1; +} __attribute__ ((aligned(1), packed)) my92xx_cmd_t; + +#define MY92XX_COMMAND_DEFAULT { \ + .scatter = MY92XX_CMD_SCATTER_APDM, \ + .frequency = MY92XX_CMD_FREQUENCY_DIVIDE_1, \ + .bit_width = MY92XX_CMD_BIT_WIDTH_8, \ + .reaction = MY92XX_CMD_REACTION_FAST, \ + .one_shot = MY92XX_CMD_ONE_SHOT_DISABLE, \ + .resv = 0 \ +} + +class my92xx { + + public: + + my92xx(my92xx_model_t model, unsigned char chips, unsigned char di, unsigned char dcki, my92xx_cmd_t command); + unsigned char getChannels(); + void setChannel(unsigned char channel, unsigned int value); + unsigned int getChannel(unsigned char channel); + void setState(bool state); + bool getState(); + void update(); + + private: + + void _di_pulse(unsigned int times); + void _dcki_pulse(unsigned int times); + void _set_cmd(my92xx_cmd_t command); + void _send(); + void _write(unsigned int data, unsigned char bit_length); + + my92xx_cmd_t _command; + my92xx_model_t _model = MY92XX_MODEL_MY9291; + unsigned char _chips = 1; + unsigned char _channels; + uint16_t * _value; + bool _state = false; + unsigned char _pin_di; + unsigned char _pin_dcki; + + +}; + +#endif From 45194095276fd52bd805345f705c821f7533436d Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 23 Nov 2017 22:30:50 +0200 Subject: [PATCH 09/28] Fix tradfri gateway pair bug --- BridgeEmulator/HueEmulator.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index f3dabd23..7fab913a 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -619,12 +619,12 @@ def longPressButton(sensor, buttonevent): def scanTradfri(): - if "tradfri_psk" in bridge_config: - tradri_devices = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["tradfri_psk"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001\"", shell=True).split("\n")[3]) + if "tradfri" in bridge_config: + tradri_devices = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["tradfri"]["psk"] + "\" \"coaps://" + bridge_config["tradfri"]["ip"] + ":5684/15001\"", shell=True).split("\n")[3]) pprint(tradri_devices) lights_found = 0 for device in tradri_devices: - device_parameters = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["tradfri_psk"] + "\" \"coaps://" + get_parameters["ip"][0] + ":5684/15001/" + str(device) +"\"", shell=True).split("\n")[3]) + device_parameters = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["tradfri"]["psk"] + "\" \"coaps://" + bridge_config["tradfri"]["ip"] + ":5684/15001/" + str(device) +"\"", shell=True).split("\n")[3]) if "3311" in device_parameters: new_light = True for light in bridge_config["lights_address"]: @@ -638,7 +638,7 @@ def scanTradfri(): new_light_id = nextFreeId("lights") bridge_config["lights"][new_light_id] = {"state": {"on": False, "bri": 200, "hue": 0, "sat": 0, "xy": [0.0, 0.0], "ct": 461, "alert": "none", "effect": "none", "colormode": "ct", "reachable": True}, "type": "Extended color light", "name": device_parameters["9001"], "uniqueid": "1234567" + str(device), "modelid": "LLM010", "swversion": "66009461"} new_lights.update({new_light_id: {"name": device_parameters["9001"]}}) - bridge_config["lights_address"][new_light_id] = {"device_id": device, "preshared_key": bridge_config["tradfri_psk"], "ip": get_parameters["ip"][0], "protocol": "ikea_tradfri"} + bridge_config["lights_address"][new_light_id] = {"device_id": device, "preshared_key": bridge_config["tradfri"]["psk"], "ip": bridge_config["tradfri"]["ip"], "protocol": "ikea_tradfri"} return lights_found else: return 0 @@ -997,7 +997,7 @@ def do_GET(self): if "code" in get_parameters: #register new identity registration = json.loads(check_output("./coap-client-linux -m post -u \"Client_identity\" -k \"" + get_parameters["code"][0] + "\" -e '{\"9090\":\"Hue-EMulator\"}' \"coaps://" + get_parameters["ip"][0] + ":5684/15011/9063\"", shell=True).split("\n")[3]) - bridge_config["tradfri_psk"] = registration["9091"] + bridge_config["tradfri"] = {"psk": registration["9091"], "ip": get_parameters["ip"][0]} lights_found = scanTradfri() if lights_found == 0: self.wfile.write(webformTradfri() + "
No lights where found") From 34f74a29742e37b6d62457c4b78164dd8d64a1d4 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 23 Nov 2017 23:14:44 +0200 Subject: [PATCH 10/28] improve xy color conversion for milight hub --- BridgeEmulator/HueEmulator.py | 61 ++++++++++++----------------------- 1 file changed, 21 insertions(+), 40 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 7fab913a..015f58c8 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -375,34 +375,15 @@ def sendRequest(url, method, data, time_out=2, delay=0): return response def convert_xy(x, y, bri): #needed for milight hub that don't work with xy values - Y = bri / 250.0 - z = 1.0 - x - y - - X = (Y / y) * x - Z = (Y / y) * z + X = x + Y = y + Z = 1.0 - x - y # sRGB D65 conversion - r = X * 1.656492 - Y * 0.354851 - Z * 0.255038 - g = -X * 0.707196 + Y * 1.655397 + Z * 0.036152 - b = X * 0.051713 - Y * 0.121364 + Z * 1.011530 - - if r > b and r > g and r > 1: - # red is too big - g = g / r - b = b / r - r = 1 - - elif g > b and g > r and g > 1: - #green is too big - r = r / g - b = b / g - g = 1 - - elif b > r and b > g and b > 1: - # blue is too big - r = r / b - g = g / b - b = 1 + r = X * 3.2406 - Y * 1.5372 - Z * 0.4986 + g = -X * 0.9689 + Y * 1.8758 + Z * 0.0415 + b = X * 0.0557 - Y * 0.2040 + Z * 1.0570 + r = 12.92 * r if r <= 0.0031308 else (1.0 + 0.055) * pow(r, (1.0 / 2.4)) - 0.055 g = 12.92 * g if g <= 0.0031308 else (1.0 + 0.055) * pow(g, (1.0 / 2.4)) - 0.055 @@ -414,25 +395,25 @@ def convert_xy(x, y, bri): #needed for milight hub that don't work with xy value g = g / r b = b / r r = 1 - elif g > b and g > r: - # green is biggest - if g > 1: - r = r / g - b = b / g - g = 1 - - elif b > r and b > g: - # blue is biggest - if b > 1: - r = r / b - g = g / b - b = 1 + elif g > b and g > r: + # green is biggest + if g > 1: + r = r / g + b = b / g + g = 1 + + elif b > r and b > g: + # blue is biggest + if b > 1: + r = r / b + g = g / b + b = 1 r = 0 if r < 0 else r g = 0 if g < 0 else g b = 0 if b < 0 else b - return [int(r * 255), int(g * 255), int(b * 255)] + return [int(r * bri), int(g * bri), int(b * bri)] def sendLightRequest(light, data): payload = {} From 4547fa48eef558bb3d4086b4c3c396b3663223a3 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Fri, 24 Nov 2017 14:00:08 +0200 Subject: [PATCH 11/28] Remove unused lines --- Lights/Arduino/MY92XX_RGBW_Light/MY92XX_RGBW_Light.ino | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Lights/Arduino/MY92XX_RGBW_Light/MY92XX_RGBW_Light.ino b/Lights/Arduino/MY92XX_RGBW_Light/MY92XX_RGBW_Light.ino index 8579d00a..15599b9a 100644 --- a/Lights/Arduino/MY92XX_RGBW_Light/MY92XX_RGBW_Light.ino +++ b/Lights/Arduino/MY92XX_RGBW_Light/MY92XX_RGBW_Light.ino @@ -16,11 +16,6 @@ uint8_t PWM_PINS[PWM_CHANNELS] = {4, 3, 5, 6}; //RGBW order -#define MY92XX_RED 4 -#define MY92XX_GREEN 3 -#define MY92XX_BLUE 5 - - my92xx * _my92xx; // if you want to setup static ip uncomment these 3 lines and line 72 From 4f12342d09fed73c7b8a15afb70a1bc55febf0a5 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Fri, 24 Nov 2017 20:57:42 +0200 Subject: [PATCH 12/28] add lights synchronization with milight hub --- BridgeEmulator/HueEmulator.py | 37 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 015f58c8..2bcb5642 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -555,24 +555,14 @@ def scanForLights(): #scan for ESP8266 lights and strips def syncWithLights(): #update Hue Bridge lights states for light in bridge_config["lights_address"]: - if bridge_config["lights_address"][light]["protocol"] == "native": - try: + try: + if bridge_config["lights_address"][light]["protocol"] == "native": light_data = json.loads(sendRequest("http://" + bridge_config["lights_address"][light]["ip"] + "/get?light=" + str(bridge_config["lights_address"][light]["light_nr"]), "GET", "{}", 0.5)) - except: - bridge_config["lights"][light]["state"]["reachable"] = False - bridge_config["lights"][light]["state"]["on"] = False - print("request error") - else: - bridge_config["lights"][light]["state"]["reachable"] = True bridge_config["lights"][light]["state"].update(light_data) - elif bridge_config["lights_address"][light]["protocol"] == "hue": - try: + elif bridge_config["lights_address"][light]["protocol"] == "hue": light_data = json.loads(sendRequest("http://" + bridge_config["lights_address"][light]["ip"] + "/api/" + bridge_config["lights_address"][light]["username"] + "/lights/" + bridge_config["lights_address"][light]["light_id"], "GET", "{}", 1)) bridge_config["lights"][light]["state"].update(light_data["state"]) - except: - bridge_config["lights"][light]["state"]["reachable"] = False - elif bridge_config["lights_address"][light]["protocol"] == "ikea_tradfri": - try: + elif bridge_config["lights_address"][light]["protocol"] == "ikea_tradfri": light_stats = json.loads(check_output("./coap-client-linux -m get -u \"Hue-EMulator\" -k \"" + bridge_config["lights_address"][light]["preshared_key"] + "\" \"coaps://" + bridge_config["lights_address"][light]["ip"] + ":5684/15001/" + str(bridge_config["lights_address"][light]["device_id"]) +"\"", shell=True).split("\n")[3]) bridge_config["lights"][light]["state"]["on"] = bool(light_stats["3311"][0]["5850"]) bridge_config["lights"][light]["state"]["bri"] = light_stats["3311"][0]["5851"] @@ -585,8 +575,23 @@ def syncWithLights(): #update Hue Bridge lights states bridge_config["lights"][light]["state"]["ct"] = 470 else: bridge_config["lights"][light]["state"]["ct"] = 470 - except: - bridge_config["lights"][light]["state"]["reachable"] = False + elif bridge_config["lights_address"][light]["protocol"] == "milight": + light_data = json.loads(sendRequest("http://" + bridge_config["lights_address"][light]["ip"] + "/gateways/" + bridge_config["lights_address"][light]["device_id"] + "/" + bridge_config["lights_address"][light]["mode"] + "/" + str(bridge_config["lights_address"][light]["group"]), "GET", "{}", 1)) + if light_data["state"] == "ON": + bridge_config["lights"][light]["state"]["on"] = True + else: + bridge_config["lights"][light]["state"]["on"] = True + if "brightness" in light_data: + bridge_config["lights"][light]["state"]["bri"] = light_data["brightness"] + if "color_temp" in light_data: + bridge_config["lights"][light]["state"]["colormode"] = "ct" + bridge_config["lights"][light]["state"]["ct"] = light_data["color_temp"] * 1.6 + except: + bridge_config["lights"][light]["state"]["reachable"] = False + bridge_config["lights"][light]["state"]["on"] = False + print("request error") + else: + bridge_config["lights"][light]["state"]["reachable"] = True def longPressButton(sensor, buttonevent): print("long press detected") From e59b3e7e630565a628fa1bcbe2d5c12c77d217b7 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Sat, 25 Nov 2017 12:47:01 +0200 Subject: [PATCH 13/28] Fix bug milight off state #100 --- BridgeEmulator/HueEmulator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 2bcb5642..741baef5 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -580,7 +580,7 @@ def syncWithLights(): #update Hue Bridge lights states if light_data["state"] == "ON": bridge_config["lights"][light]["state"]["on"] = True else: - bridge_config["lights"][light]["state"]["on"] = True + bridge_config["lights"][light]["state"]["on"] = False if "brightness" in light_data: bridge_config["lights"][light]["state"]["bri"] = light_data["brightness"] if "color_temp" in light_data: From 35cda6a0384379aea44ae8d40c8582e2c9b3089d Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Mon, 27 Nov 2017 11:55:09 +0200 Subject: [PATCH 14/28] Possible fix for HA lights status not updated --- BridgeEmulator/HueEmulator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 741baef5..7808fab9 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -1121,6 +1121,7 @@ def do_GET(self): bridge_config["config"]["UTC"] = datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S") bridge_config["config"]["localtime"] = datetime.now().strftime("%Y-%m-%dT%H:%M:%S") if len(url_pices) == 3 or (len(url_pices) == 4 and url_pices[3] == ""): #print entire config + syncWithLights() self.wfile.write(json.dumps({"lights": bridge_config["lights"], "groups": bridge_config["groups"], "config": bridge_config["config"], "scenes": bridge_config["scenes"], "schedules": bridge_config["schedules"], "rules": bridge_config["rules"], "sensors": bridge_config["sensors"], "resourcelinks": bridge_config["resourcelinks"]})) elif len(url_pices) == 4 or (len(url_pices) == 5 and url_pices[4] == ""): #print specified object config if url_pices[3] == "lights": #add changes from IKEA Tradfri gateway to bridge From 31c3ea411c49e5bf5df3ae22b3b27fb1fe579025 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Wed, 29 Nov 2017 12:30:16 +0200 Subject: [PATCH 15/28] move updateGroupStats function on PUT request --- BridgeEmulator/HueEmulator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index 7808fab9..f8d85c3f 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -1306,7 +1306,6 @@ def do_PUT(self): bridge_config["lights"][url_pices[4]]["state"]["colormode"] = key elif key in ["hue", "sat"]: bridge_config["lights"][url_pices[4]]["state"]["colormode"] = "hs" - updateGroupStats(url_pices[4]) if not url_pices[4] == "0": #group 0 is virtual, must not be saved in bridge configuration try: bridge_config[url_pices[3]][url_pices[4]][url_pices[5]].update(put_dictionary) @@ -1331,6 +1330,8 @@ def do_PUT(self): response_dictionary.append({"success":{response_location + key: value}}) self.wfile.write(json.dumps(response_dictionary,sort_keys=True, indent=4, separators=(',', ': '))) print(json.dumps(response_dictionary, sort_keys=True, indent=4, separators=(',', ': '))) + if url_pices[3] == "lights": + updateGroupStats(url_pices[4]) else: self.wfile.write(json.dumps([{"error": {"type": 1, "address": self.path, "description": "unauthorized user" }}],sort_keys=True, indent=4, separators=(',', ': '))) From 6ef0e5a88a8b303ad0f955364743cca96b82c665 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 30 Nov 2017 19:06:42 +0200 Subject: [PATCH 16/28] add control from gpio pins --- .../Generic_Dimmable_Light.ino | 93 +++++++++++++++---- 1 file changed, 74 insertions(+), 19 deletions(-) diff --git a/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino b/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino index ad9e187a..6a0d713e 100644 --- a/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino +++ b/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino @@ -7,23 +7,28 @@ #include #include "pwm.c" -#define lightsCount 3 +#define lightsCount 4 + +#define use_hardware_switch false // on/off state and brightness can be controlled with above gpio pins. Is mandatory to connect them to ground with 10K resistors. +#define button1_pin 4 // on and bri up +#define button2_pin 5 // off and bri down const uint32_t period = 1024; //define pins uint32 io_info[lightsCount][3] = { // MUX, FUNC, PIN - //{PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12, 12}, - //{PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15, 15}, - //{PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13, 13}, - //{PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14, 14}, - {PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4 , 4}, - {PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5 , 5}, + {PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12, 12}, + {PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15, 15}, + {PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13, 13}, + {PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14, 14}, + //{PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4 , 4}, + //{PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5 , 5}, }; // initial duty: all off -uint32 pwm_duty_init[lightsCount] = {0, 0}; +uint32 pwm_duty_init[lightsCount]; +//uint32 pwm_duty_init[lightsCount] = {512, 255}; this will set startup brightness to 50% on first light and 25% on second one // if you want to setup static ip uncomment these 3 lines and line 72 //IPAddress strip_ip ( 192, 168, 10, 95); @@ -64,6 +69,15 @@ void apply_scene(uint8_t new_scene, uint8_t light) { } } +void process_lightdata(uint8_t light, float transitiontime) { + transitiontime *= 16; + if (light_state[light]) { + step_level[light] = (bri[light] - current_bri[light]) / transitiontime; + } else { + step_level[light] = current_bri[light] / transitiontime; + } +} + void lightEngine() { for (int i = 0; i < lightsCount; i++) { @@ -88,6 +102,50 @@ void lightEngine() { if (in_transition) { delay(6); in_transition = false; + } else if (use_hardware_switch == true) { + if (digitalRead(button1_pin) == HIGH) { + int i = 0; + while (digitalRead(button1_pin) == HIGH && i < 30) { + delay(20); + i++; + } + for (int light = 0; light < lightsCount; light++) { + if (i < 30) { + // there was a short press + light_state[light] = true; + } + else { + // there was a long press + bri[light] += 56; + if (bri[light] > 254) { + // don't increase the brightness more then maximum value + bri[light] = 254; + } + } + process_lightdata(light, 4); + } + } else if (digitalRead(button2_pin) == HIGH) { + int i = 0; + while (digitalRead(button2_pin) == HIGH && i < 30) { + delay(20); + i++; + } + for (int light = 0; light < lightsCount; light++) { + if (i < 30) { + // there was a short press + light_state[light] = false; + } + else { + // there was a long press + bri[light] -= 56; + if (bri[light] < 1) { + // don't decrease the brightness less than minimum value. + bri[light] = 1; + } + } + process_lightdata(light, 4); + } + } } } @@ -142,6 +200,8 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH + pinMode(button1_pin, INPUT); + pinMode(button2_pin, INPUT); server.on("/switch", []() { @@ -179,11 +239,11 @@ void setup() { } else if (button == 4000) { light_state[i] = false; } - if (light_state[i]) { - step_level[i] = ((float)bri[i] - current_bri[i]) / transitiontime; - } else { - step_level[i] = current_bri[i] / transitiontime; - } + if (light_state[i]) { + step_level[i] = ((float)bri[i] - current_bri[i]) / transitiontime; + } else { + step_level[i] = current_bri[i] / transitiontime; + } } }); @@ -230,13 +290,8 @@ void setup() { transitiontime = server.arg(i).toInt(); } } + process_lightdata(light, transitiontime); server.send(200, "text/plain", "OK, bri:" + (String)bri[light] + ", state:" + light_state[light]); - transitiontime *= 16; - if (light_state[light]) { - step_level[light] = (bri[light] - current_bri[light]) / transitiontime; - } else { - step_level[light] = current_bri[light] / transitiontime; - } }); server.on("/get", []() { From 3c02e8a74b987ea286580e7b0d9c52b90d7516b7 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 30 Nov 2017 19:12:47 +0200 Subject: [PATCH 17/28] set input pins only if you use them. --- .../Generic_Dimmable_Light/Generic_Dimmable_Light.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino b/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino index 6a0d713e..ba64ae57 100644 --- a/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino +++ b/Lights/Arduino/Generic_Dimmable_Light/Generic_Dimmable_Light.ino @@ -200,8 +200,10 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH - pinMode(button1_pin, INPUT); - pinMode(button2_pin, INPUT); + if (use_hardware_switch == true) { + pinMode(button1_pin, INPUT); + pinMode(button2_pin, INPUT); + } server.on("/switch", []() { From 4bf05108646c010abbebe63c235797124e30610b Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 30 Nov 2017 19:19:38 +0200 Subject: [PATCH 18/28] add control from gpio pins --- .../WS2812BHueStrip/WS2812BHueStrip.ino | 105 +++++++++++++----- 1 file changed, 77 insertions(+), 28 deletions(-) diff --git a/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino b/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino index 44901046..5945845d 100644 --- a/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino +++ b/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino @@ -10,6 +10,10 @@ #define lightsCount 3 #define pixelCount 60 +#define use_hardware_switch false // on/off state and brightness can be controlled with above gpio pins. Is mandatory to connect them to ground with 10K resistors +#define button1_pin 4 // on and bri up +#define button2_pin 5 // off and bri down + // if you want to setup static ip uncomment these 3 lines and line 72 //IPAddress strip_ip ( 192, 168, 10, 95); //IPAddress gateway_ip ( 192, 168, 10, 1); @@ -92,41 +96,24 @@ void convert_hue(uint8_t light) void convert_xy(uint8_t light) { - float Y = bri[light] / 250.0f; - - float z = 1.0f - x[light] - y[light]; - - float X = (Y / y[light]) * x[light]; - float Z = (Y / y[light]) * z; + int optimal_bri = bri[light]; + if (optimal_bri < 5) { + optimal_bri = 5; + } + float Y = y[light]; + float X = x[light]; + float Z = 1.0f - x[light] - y[light]; // sRGB D65 conversion float r = X * 3.2406f - Y * 1.5372f - Z * 0.4986f; float g = -X * 0.9689f + Y * 1.8758f + Z * 0.0415f; float b = X * 0.0557f - Y * 0.2040f + Z * 1.0570f; - if (r > b && r > g && r > 1.0f) { - // red is too big - g = g / r; - b = b / r; - r = 1.0f; - } - else if (g > b && g > r && g > 1.0f) { - // green is too big - r = r / g; - b = b / g; - g = 1.0f; - } - else if (b > r && b > g && b > 1.0f) { - // blue is too big - r = r / b; - g = g / b; - b = 1.0f; - } // Apply gamma correction - r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f; - g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f; - b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f; + r = r <= 0.04045f ? r / 12.92f : pow((r + 0.055f) / (1.0f + 0.055f), 2.4f); + g = g <= 0.04045f ? g / 12.92f : pow((g + 0.055f) / (1.0f + 0.055f), 2.4f); + b = b <= 0.04045f ? b / 12.92f : pow((b + 0.055f) / (1.0f + 0.055f), 2.4f); if (r > b && r > g) { // red is biggest @@ -157,7 +144,7 @@ void convert_xy(uint8_t light) g = g < 0 ? 0 : g; b = b < 0 ? 0 : b; - rgb[light][0] = (int) (r * 255.0f); rgb[light][1] = (int) (g * 255.0f); rgb[light][2] = (int) (b * 255.0f); + rgb[light][0] = (int) (r * optimal_bri); rgb[light][1] = (int) (g * optimal_bri); rgb[light][2] = (int) (b * optimal_bri); } void convert_ct(uint8_t light) { @@ -232,6 +219,24 @@ void apply_scene(uint8_t new_scene, uint8_t light) { } } +void process_lightdata(uint8_t light,float transitiontime) { + transitiontime *= 16 - (pixelCount / 40); //every extra led add a small delay that need to be counted + if (color_mode[light] == 1 && light_state[light] == true) { + convert_xy(light); + } else if (color_mode[light] == 2 && light_state[light] == true) { + convert_ct(light); + } else if (color_mode[light] == 3 && light_state[light] == true) { + convert_hue(light); + } + for (uint8_t i = 0; i <= 3; i++) { + if (light_state[light]) { + step_level[light][i] = ((float)rgb[light][i] - current_rgb[light][i]) / transitiontime; + } else { + step_level[light][i] = current_rgb[light][i] / transitiontime; + } + } +} + void lightEngine() { for (int i = 0; i < lightsCount; i++) { if (light_state[i]) { @@ -265,6 +270,48 @@ void lightEngine() { if (in_transition) { delay(6); in_transition = false; + } else if (use_hardware_switch == true) { + if (digitalRead(button1_pin) == HIGH) { + int i = 0; + while (digitalRead(button1_pin) == HIGH && i < 30) { + delay(20); + i++; + } + for (int light = 0; light < lightsCount; light++) { + if (i < 30) { + // there was a short press + light_state[light] = true; + } + else { + // there was a long press + bri[light] += 56; + if (bri[light] > 255) { + // don't increase the brightness more then maximum value + bri[light] = 255; + } + } + } + } else if (digitalRead(button2_pin) == HIGH) { + int i = 0; + while (digitalRead(button2_pin) == HIGH && i < 30) { + delay(20); + i++; + } + for (int light = 0; light < lightsCount; light++) { + if (i < 30) { + // there was a short press + light_state[light] = false; + } + else { + // there was a long press + bri[light] -= 56; + if (bri[light] < 1) { + // don't decrease the brightness less than minimum value. + bri[light] = 1; + } + } + } + } } } @@ -320,6 +367,8 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH + pinMode(button1_pin, INPUT); + pinMode(button2_pin, INPUT); server.on("/switch", []() { From a14c969fa0f4460b03dd44c04a42ed1880fef902 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 30 Nov 2017 19:52:38 +0200 Subject: [PATCH 19/28] add control from gpio pins --- Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino b/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino index 5945845d..a62b2eae 100644 --- a/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino +++ b/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino @@ -228,7 +228,7 @@ void process_lightdata(uint8_t light,float transitiontime) { } else if (color_mode[light] == 3 && light_state[light] == true) { convert_hue(light); } - for (uint8_t i = 0; i <= 3; i++) { + for (uint8_t i = 0; i < 3; i++) { if (light_state[light]) { step_level[light][i] = ((float)rgb[light][i] - current_rgb[light][i]) / transitiontime; } else { From 0439caca4f1da1001a786c3e2a2ff55a16b87c96 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 30 Nov 2017 20:53:49 +0200 Subject: [PATCH 20/28] Update WS2812BHueStrip.ino --- .../WS2812BHueStrip/WS2812BHueStrip.ino | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino b/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino index a62b2eae..48780923 100644 --- a/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino +++ b/Lights/Arduino/WS2812BHueStrip/WS2812BHueStrip.ino @@ -220,7 +220,7 @@ void apply_scene(uint8_t new_scene, uint8_t light) { } void process_lightdata(uint8_t light,float transitiontime) { - transitiontime *= 16 - (pixelCount / 40); //every extra led add a small delay that need to be counted + transitiontime *= 17 - (pixelCount / 40); //every extra led add a small delay that need to be counted if (color_mode[light] == 1 && light_state[light] == true) { convert_xy(light); } else if (color_mode[light] == 2 && light_state[light] == true) { @@ -499,22 +499,8 @@ void setup() { transitiontime = server.arg(i).toInt(); } } - transitiontime *= 17 - (pixelCount / 40); //every extra led add a small delay that need to be counted server.send(200, "text/plain", "OK, x: " + (String)x[light] + ", y:" + (String)y[light] + ", bri:" + (String)bri[light] + ", ct:" + ct[light] + ", colormode:" + color_mode[light] + ", state:" + light_state[light]); - if (color_mode[light] == 1 && light_state[light] == true) { - convert_xy(light); - } else if (color_mode[light] == 2 && light_state[light] == true) { - convert_ct(light); - } else if (color_mode[light] == 3 && light_state[light] == true) { - convert_hue(light); - } - for (uint8_t j = 0; j < 3; j++) { - if (light_state[light]) { - step_level[light][j] = ((float)rgb[light][j] - current_rgb[light][j]) / transitiontime; - } else { - step_level[light][j] = current_rgb[light][j] / transitiontime; - } - } + process_lightdata(light, transitiontime); }); server.on("/get", []() { From 9ea3db6137b1997268dc8c4bc91aa745f4f536d0 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Thu, 30 Nov 2017 21:05:13 +0200 Subject: [PATCH 21/28] Delete .DS_Store --- Lights/Arduino/Generic_RGB_CCT_Light/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Lights/Arduino/Generic_RGB_CCT_Light/.DS_Store diff --git a/Lights/Arduino/Generic_RGB_CCT_Light/.DS_Store b/Lights/Arduino/Generic_RGB_CCT_Light/.DS_Store deleted file mode 100644 index ed1def276f50d2f28b3416024761c595b09718cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJxfDD5S-N%0h@GMUTGy*+Z-XHf}Mq}Bz^@#9*F5*=g-#J-BS{tT3W~~?9Sc3 zox8j#-ev*VbaQ_SOaP4Oj(GDhG=J_su)UTsBAsWvV2K5886OAL-zS`VhzmSmP2c7( zafuCc*F5bB&v?ZNS8H@vt8Ou0b#pTPXP?oJ-@~|)NdYM!1*Cu!kOIFe;JueNK1fuQ z0#ZN Date: Thu, 30 Nov 2017 21:05:44 +0200 Subject: [PATCH 22/28] add control from gpio pins --- .../Generic_RGB_CCT_Light.ino | 125 +++++++++++------- 1 file changed, 80 insertions(+), 45 deletions(-) diff --git a/Lights/Arduino/Generic_RGB_CCT_Light/Generic_RGB_CCT_Light.ino b/Lights/Arduino/Generic_RGB_CCT_Light/Generic_RGB_CCT_Light.ino index f8a4a6f7..608d4b64 100644 --- a/Lights/Arduino/Generic_RGB_CCT_Light/Generic_RGB_CCT_Light.ino +++ b/Lights/Arduino/Generic_RGB_CCT_Light/Generic_RGB_CCT_Light.ino @@ -15,11 +15,15 @@ #define PWM_CHANNELS 5 const uint32_t period = 1024; +#define use_hardware_switch false // on/off state and brightness can be controlled with above gpio pins. Is mandatory to connect them to ground with 10K resistors +#define button1_pin 1 // on and bri up +#define button2_pin 3 // off and bri down + //define pins uint32 io_info[PWM_CHANNELS][3] = { // MUX, FUNC, PIN - {PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13, 13}, {PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14, 14}, + {PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13, 13}, {PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12, 12}, {PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4 , 4}, {PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5 , 5}, @@ -105,37 +109,17 @@ void convert_hue() void convert_xy() { - float Y = bri / 250.0f; + int optimal_bri = int( 10 + bri / 1.04); - float z = 1.0f - x - y; - - float X = (Y / y) * x; - float Z = (Y / y) * z; + float Y = y; + float X = x; + float Z = 1.0f - x - y; // sRGB D65 conversion float r = X * 3.2406f - Y * 1.5372f - Z * 0.4986f; float g = -X * 0.9689f + Y * 1.8758f + Z * 0.0415f; float b = X * 0.0557f - Y * 0.2040f + Z * 1.0570f; - if (r > b && r > g && r > 1.0f) { - // red is too big - g = g / r; - b = b / r; - r = 1.0f; - } - else if (g > b && g > r && g > 1.0f) { - // green is too big - r = r / g; - b = b / g; - g = 1.0f; - } - else if (b > r && b > g && b > 1.0f) { - // blue is too big - r = r / b; - g = g / b; - b = 1.0f; - } - // Apply gamma correction r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f; g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f; @@ -170,18 +154,21 @@ void convert_xy() g = g < 0 ? 0 : g; b = b < 0 ? 0 : b; - rgb_cct[0] = (int) (r * 255.0f); rgb_cct[1] = (int) (g * 255.0f); rgb_cct[2] = (int) (b * 255.0f); rgb_cct[3] = 0; rgb_cct[4] = 0; + rgb_cct[0] = (int) (r * optimal_bri); rgb_cct[1] = (int) (g * optimal_bri); rgb_cct[2] = (int) (b * optimal_bri); rgb_cct[3] = 0; rgb_cct[4] = 0; } void convert_ct() { + + int optimal_bri = int( 10 + bri / 1.04); + rgb_cct[0] = 0; rgb_cct[1] = 0; rgb_cct[2] = 0; uint8 percent_warm = ((ct - 150) * 100) / 350; - rgb_cct[3] = (bri * percent_warm) / 100; - rgb_cct[4] = (bri * (100 - percent_warm)) / 100; + rgb_cct[3] = (optimal_bri * percent_warm) / 100; + rgb_cct[4] = (optimal_bri * (100 - percent_warm)) / 100; } @@ -226,6 +213,24 @@ void apply_scene(uint8_t new_scene) { } } +void process_lightdata(float transitiontime) { + if (color_mode == 1 && light_state == true) { + convert_xy(); + } else if (color_mode == 2 && light_state == true) { + convert_ct(); + } else if (color_mode == 3 && light_state == true) { + convert_hue(); + } + transitiontime *= 16; + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + step_level[color] = (rgb_cct[color] - current_rgb_cct[color]) / transitiontime; + } else { + step_level[color] = current_rgb_cct[color] / transitiontime; + } + } +} + void lightEngine() { for (uint8_t color = 0; color < PWM_CHANNELS; color++) { if (light_state) { @@ -249,6 +254,46 @@ void lightEngine() { if (in_transition) { delay(6); in_transition = false; + } else if (use_hardware_switch == true) { + if (digitalRead(button1_pin) == HIGH) { + int i = 0; + while (digitalRead(button1_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = true; + } + else { + // there was a long press + bri += 56; + if (bri > 254) { + // don't increase the brightness more then maximum value + bri = 254; + } + } + process_lightdata(4); + } else if (digitalRead(button2_pin) == HIGH) { + int i = 0; + while (digitalRead(button2_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = false; + } + else { + // there was a long press + bri -= 56; + if (bri < 1) { + // don't decrease the brightness less than minimum value. + bri = 1; + } + } + process_lightdata(4); + } } } @@ -298,6 +343,10 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH + if (use_hardware_switch == true) { + pinMode(button1_pin, INPUT); + pinMode(button2_pin, INPUT); + } server.on("/switch", []() { server.send(200, "text/plain", "OK"); @@ -352,7 +401,7 @@ void setup() { server.on("/set", []() { light_state = true; - float transitiontime = 4; + int transitiontime = 4; for (uint8_t i = 0; i < server.args(); i++) { if (server.argName(i) == "on") { if (server.arg(i) == "True" || server.arg(i) == "true") { @@ -426,22 +475,8 @@ void setup() { transitiontime = server.arg(i).toInt(); } } - server.send(200, "text/plain", "OK, x: " + (String)x + ", y:" + (String)y + ", bri:" + (String)bri + ", ct:" + ct + ", colormode:" + color_mode + ", state:" + light_state); - if (color_mode == 1 && light_state == true) { - convert_xy(); - } else if (color_mode == 2 && light_state == true) { - convert_ct(); - } else if (color_mode == 3 && light_state == true) { - convert_hue(); - } - transitiontime *= 16; - for (uint8_t color = 0; color < PWM_CHANNELS; color++) { - if (light_state) { - step_level[color] = (rgb_cct[color] - current_rgb_cct[color]) / transitiontime; - } else { - step_level[color] = current_rgb_cct[color] / transitiontime; - } - } + server.send(200, "text/plain", "OK, x: " + (String)x + ", y:" + (String)y + ", bri:" + (String)bri + ", ct:" + ct + ", colormode:" + color_mode + ", state:" + light_state + ", r:" + (String)rgb_cct[0] + ", g:" + (String)rgb_cct[1] + ", b:" + (String)rgb_cct[2]); + process_lightdata(transitiontime); }); server.on("/get", []() { From 7a24af7a814a12ee4370edf31a5dc4b1ccc90a9c Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Fri, 1 Dec 2017 12:11:46 +0200 Subject: [PATCH 23/28] revert bridge serial number to mac address --- BridgeEmulator/HueEmulator.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BridgeEmulator/HueEmulator.py b/BridgeEmulator/HueEmulator.py index f8d85c3f..ddbcb265 100755 --- a/BridgeEmulator/HueEmulator.py +++ b/BridgeEmulator/HueEmulator.py @@ -780,8 +780,8 @@ def description(): Philips hue bridge 2015 BSB002 http://www.meethue.com -00008800bbee -uuid:2f402f80-da50-11e1-9b23-00008800bbee +""" + mac.upper() + """ +uuid:2f402f80-da50-11e1-9b23-""" + mac + """ (null) From b33b6eb5c15bd0957deaadfb964a1b9028caed4f Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Fri, 1 Dec 2017 19:01:21 +0200 Subject: [PATCH 24/28] add external control with gpio pins --- .../Generic_CCT_Light/Generic_CCT_Light.ino | 76 ++++++++++++++++--- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/Lights/Arduino/Generic_CCT_Light/Generic_CCT_Light.ino b/Lights/Arduino/Generic_CCT_Light/Generic_CCT_Light.ino index 20b279a7..3534252c 100644 --- a/Lights/Arduino/Generic_CCT_Light/Generic_CCT_Light.ino +++ b/Lights/Arduino/Generic_CCT_Light/Generic_CCT_Light.ino @@ -1,5 +1,5 @@ /* - This can control bulbs with 5 pwm channels (red, gree, blue, warm white and could wihite). Is tested with MiLight RGB_CCT bulb. + This can control bulbs with 2 pwm channel */ @@ -15,6 +15,10 @@ #define PWM_CHANNELS 2 const uint32_t period = 1024; +#define use_hardware_switch false // on/off state and brightness can be controlled with above gpio pins. Is mandatory to connect them to ground with 10K resistors +#define button1_pin 1 // on and bri up +#define button2_pin 3 // off and bri down + //define pins uint32 io_info[PWM_CHANNELS][3] = { // MUX, FUNC, PIN @@ -82,6 +86,20 @@ void apply_scene(uint8_t new_scene) { } } +void process_lightdata(float transitiontime) { + if (light_state == true) { + convert_ct(); + } + transitiontime *= 16; + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + step_level[color] = (cct[color] - current_cct[color]) / transitiontime; + } else { + step_level[color] = current_cct[color] / transitiontime; + } + } +} + void lightEngine() { for (uint8_t color = 0; color < PWM_CHANNELS; color++) { if (light_state) { @@ -105,6 +123,46 @@ void lightEngine() { if (in_transition) { delay(6); in_transition = false; + } else if (use_hardware_switch == true) { + if (digitalRead(button1_pin) == HIGH) { + int i = 0; + while (digitalRead(button1_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = true; + } + else { + // there was a long press + bri += 56; + if (bri > 254) { + // don't increase the brightness more then maximum value + bri = 254; + } + } + process_lightdata(4); + } else if (digitalRead(button2_pin) == HIGH) { + int i = 0; + while (digitalRead(button2_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = false; + } + else { + // there was a long press + bri -= 56; + if (bri < 1) { + // don't decrease the brightness less than minimum value. + bri = 1; + } + } + process_lightdata(4); + } } } @@ -154,6 +212,10 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH + if (use_hardware_switch == true) { + pinMode(button1_pin, INPUT); + pinMode(button2_pin, INPUT); + } server.on("/switch", []() { server.send(200, "text/plain", "OK"); @@ -246,17 +308,7 @@ void setup() { } } server.send(200, "text/plain", "OK, bri:" + (String)bri + ", ct:" + ct + ", colormode: ct, state:" + light_state); - if (light_state == true) { - convert_ct(); - } - transitiontime *= 16; - for (uint8_t color = 0; color < PWM_CHANNELS; color++) { - if (light_state) { - step_level[color] = (cct[color] - current_cct[color]) / transitiontime; - } else { - step_level[color] = current_cct[color] / transitiontime; - } - } + process_lightdata(transitiontime); }); server.on("/get", []() { From 717fb2137ab363463a1c43138046eed55eec0f88 Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Fri, 1 Dec 2017 19:14:35 +0200 Subject: [PATCH 25/28] Delete .DS_Store --- Lights/Arduino/Generic_RGBW_Light/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Lights/Arduino/Generic_RGBW_Light/.DS_Store diff --git a/Lights/Arduino/Generic_RGBW_Light/.DS_Store b/Lights/Arduino/Generic_RGBW_Light/.DS_Store deleted file mode 100644 index ed1def276f50d2f28b3416024761c595b09718cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJxfDD5S-N%0h@GMUTGy*+Z-XHf}Mq}Bz^@#9*F5*=g-#J-BS{tT3W~~?9Sc3 zox8j#-ev*VbaQ_SOaP4Oj(GDhG=J_su)UTsBAsWvV2K5886OAL-zS`VhzmSmP2c7( zafuCc*F5bB&v?ZNS8H@vt8Ou0b#pTPXP?oJ-@~|)NdYM!1*Cu!kOIFe;JueNK1fuQ z0#ZN Date: Fri, 1 Dec 2017 19:15:31 +0200 Subject: [PATCH 26/28] add control from gpio pins --- .../Generic_RGBW_Light/Generic_RGBW_Light.ino | 83 +++++++++++++++---- 1 file changed, 68 insertions(+), 15 deletions(-) diff --git a/Lights/Arduino/Generic_RGBW_Light/Generic_RGBW_Light.ino b/Lights/Arduino/Generic_RGBW_Light/Generic_RGBW_Light.ino index 6519a164..ed79d3d8 100644 --- a/Lights/Arduino/Generic_RGBW_Light/Generic_RGBW_Light.ino +++ b/Lights/Arduino/Generic_RGBW_Light/Generic_RGBW_Light.ino @@ -10,6 +10,10 @@ #define PWM_CHANNELS 4 const uint32_t period = 1024; +#define use_hardware_switch false // on/off state and brightness can be controlled with above gpio pins. Is mandatory to connect them to ground with 10K resistors +#define button1_pin 1 // on and bri up +#define button2_pin 3 // off and bri down + //define pins uint32 io_info[PWM_CHANNELS][3] = { // MUX, FUNC, PIN @@ -225,6 +229,24 @@ void apply_scene(uint8_t new_scene) { } } +void process_lightdata(float transitiontime) { + if (color_mode == 1 && light_state == true) { + convert_xy(); + } else if (color_mode == 2 && light_state == true) { + convert_ct(); + } else if (color_mode == 3 && light_state == true) { + convert_hue(); + } + transitiontime *= 16; + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + step_level[color] = (rgbw[color] - current_rgbw[color]) / transitiontime; + } else { + step_level[color] = current_rgbw[color] / transitiontime; + } + } +} + void lightEngine() { for (uint8_t color = 0; color < PWM_CHANNELS; color++) { if (light_state) { @@ -248,6 +270,46 @@ void lightEngine() { if (in_transition) { delay(6); in_transition = false; + } else if (use_hardware_switch == true) { + if (digitalRead(button1_pin) == HIGH) { + int i = 0; + while (digitalRead(button1_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = true; + } + else { + // there was a long press + bri += 56; + if (bri > 254) { + // don't increase the brightness more then maximum value + bri = 254; + } + } + process_lightdata(4); + } else if (digitalRead(button2_pin) == HIGH) { + int i = 0; + while (digitalRead(button2_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = false; + } + else { + // there was a long press + bri -= 56; + if (bri < 1) { + // don't decrease the brightness less than minimum value. + bri = 1; + } + } + process_lightdata(4); + } } } @@ -297,6 +359,11 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH + if (use_hardware_switch == true) { + pinMode(button1_pin, INPUT); + pinMode(button2_pin, INPUT); + } + server.on("/switch", []() { server.send(200, "text/plain", "OK"); @@ -426,21 +493,7 @@ void setup() { } } server.send(200, "text/plain", "OK, x: " + (String)x + ", y:" + (String)y + ", bri:" + (String)bri + ", ct:" + ct + ", colormode:" + color_mode + ", state:" + light_state); - if (color_mode == 1 && light_state == true) { - convert_xy(); - } else if (color_mode == 2 && light_state == true) { - convert_ct(); - } else if (color_mode == 3 && light_state == true) { - convert_hue(); - } - transitiontime *= 16; - for (uint8_t color = 0; color < PWM_CHANNELS; color++) { - if (light_state) { - step_level[color] = (rgbw[color] - current_rgbw[color]) / transitiontime; - } else { - step_level[color] = current_rgbw[color] / transitiontime; - } - } + process_lightdata(transitiontime); }); server.on("/get", []() { From e835fa78ea84940d77e27333e2cd4a0ba20a970e Mon Sep 17 00:00:00 2001 From: Motea Marius Date: Fri, 1 Dec 2017 19:16:42 +0200 Subject: [PATCH 27/28] Delete .DS_Store --- Lights/Arduino/Generic_RGB_Light/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Lights/Arduino/Generic_RGB_Light/.DS_Store diff --git a/Lights/Arduino/Generic_RGB_Light/.DS_Store b/Lights/Arduino/Generic_RGB_Light/.DS_Store deleted file mode 100644 index ed1def276f50d2f28b3416024761c595b09718cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKJxfDD5S-N%0h@GMUTGy*+Z-XHf}Mq}Bz^@#9*F5*=g-#J-BS{tT3W~~?9Sc3 zox8j#-ev*VbaQ_SOaP4Oj(GDhG=J_su)UTsBAsWvV2K5886OAL-zS`VhzmSmP2c7( zafuCc*F5bB&v?ZNS8H@vt8Ou0b#pTPXP?oJ-@~|)NdYM!1*Cu!kOIFe;JueNK1fuQ z0#ZN Date: Fri, 1 Dec 2017 19:18:29 +0200 Subject: [PATCH 28/28] add control from gpio pins --- .../Generic_RGB_Light/Generic_RGB_Light.ino | 118 +++++++++++------- 1 file changed, 73 insertions(+), 45 deletions(-) diff --git a/Lights/Arduino/Generic_RGB_Light/Generic_RGB_Light.ino b/Lights/Arduino/Generic_RGB_Light/Generic_RGB_Light.ino index ae9e7b4b..2c86a480 100644 --- a/Lights/Arduino/Generic_RGB_Light/Generic_RGB_Light.ino +++ b/Lights/Arduino/Generic_RGB_Light/Generic_RGB_Light.ino @@ -10,6 +10,10 @@ #define PWM_CHANNELS 3 const uint32_t period = 1024; +#define use_hardware_switch false // on/off state and brightness can be controlled with above gpio pins. Is mandatory to connect them to ground with 10K resistors +#define button1_pin 1 // on and bri up +#define button2_pin 3 // off and bri down + //define pins uint32 io_info[PWM_CHANNELS][3] = { // MUX, FUNC, PIN @@ -97,36 +101,12 @@ void convert_hue() void convert_xy() { - float Y = bri / 250.0f; - float z = 1.0f - x - y; - float X = (Y / y) * x; - float Z = (Y / y) * z; - // sRGB D65 conversion - float r = X * 3.2406f - Y * 1.5372f - Z * 0.4986f; - float g = -X * 0.9689f + Y * 1.8758f + Z * 0.0415f; - float b = X * 0.0557f - Y * 0.2040f + Z * 1.0570f; - - if (r > b && r > g && r > 1.0f) { - // red is too big - g = g / r; - b = b / r; - r = 1.0f; - } - else if (g > b && g > r && g > 1.0f) { - // green is too big - r = r / g; - b = b / g; - g = 1.0f; - } - else if (b > r && b > g && b > 1.0f) { - // blue is too big - r = r / b; - g = g / b; - b = 1.0f; - } + float r = x * 3.2406f - y * 1.5372f - z * 0.4986f; + float g = -x * 0.9689f + y * 1.8758f + z * 0.0415f; + float b = x * 0.0557f - y * 0.2040f + z * 1.0570f; // Apply gamma correction r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f; @@ -162,7 +142,7 @@ void convert_xy() g = g < 0 ? 0 : g; b = b < 0 ? 0 : b; - rgb[0] = (int) (r * 255.0f); rgb[1] = (int) (g * 255.0f); rgb[2] = (int) (b * 255.0f); + rgb[0] = (int) (r * bri); rgb[1] = (int) (g * bri); rgb[2] = (int) (b * bri); } void convert_ct() { @@ -224,6 +204,24 @@ void apply_scene(uint8_t new_scene) { } } +void process_lightdata(float transitiontime) { + if (color_mode == 1 && light_state == true) { + convert_xy(); + } else if (color_mode == 2 && light_state == true) { + convert_ct(); + } else if (color_mode == 3 && light_state == true) { + convert_hue(); + } + transitiontime *= 16; + for (uint8_t color = 0; color < PWM_CHANNELS; color++) { + if (light_state) { + step_level[color] = (rgb[color] - current_rgb[color]) / transitiontime; + } else { + step_level[color] = current_rgb[color] / transitiontime; + } + } +} + void lightEngine() { for (uint8_t color = 0; color < PWM_CHANNELS; color++) { if (light_state) { @@ -247,6 +245,46 @@ void lightEngine() { if (in_transition) { delay(6); in_transition = false; + } else if (use_hardware_switch == true) { + if (digitalRead(button1_pin) == HIGH) { + int i = 0; + while (digitalRead(button1_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = true; + } + else { + // there was a long press + bri += 56; + if (bri > 254) { + // don't increase the brightness more then maximum value + bri = 254; + } + } + process_lightdata(4); + } else if (digitalRead(button2_pin) == HIGH) { + int i = 0; + while (digitalRead(button2_pin) == HIGH && i < 30) { + delay(20); + i++; + } + if (i < 30) { + // there was a short press + light_state = false; + } + else { + // there was a long press + bri -= 56; + if (bri < 1) { + // don't decrease the brightness less than minimum value. + bri = 1; + } + } + process_lightdata(4); + } } } @@ -296,6 +334,10 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH + if (use_hardware_switch == true) { + pinMode(button1_pin, INPUT); + pinMode(button2_pin, INPUT); + } server.on("/switch", []() { server.send(200, "text/plain", "OK"); @@ -350,7 +392,7 @@ void setup() { server.on("/set", []() { light_state = true; - float transitiontime = 4; + int transitiontime = 4; for (uint8_t i = 0; i < server.args(); i++) { if (server.argName(i) == "on") { if (server.arg(i) == "True" || server.arg(i) == "true") { @@ -425,21 +467,7 @@ void setup() { } } server.send(200, "text/plain", "OK, x: " + (String)x + ", y:" + (String)y + ", bri:" + (String)bri + ", ct:" + ct + ", colormode:" + color_mode + ", state:" + light_state); - if (color_mode == 1 && light_state == true) { - convert_xy(); - } else if (color_mode == 2 && light_state == true) { - convert_ct(); - } else if (color_mode == 3 && light_state == true) { - convert_hue(); - } - transitiontime *= 16; - for (uint8_t color = 0; color < PWM_CHANNELS; color++) { - if (light_state) { - step_level[color] = (rgb[color] - current_rgb[color]) / transitiontime; - } else { - step_level[color] = current_rgb[color] / transitiontime; - } - } + process_lightdata(transitiontime); }); server.on("/get", []() { @@ -456,7 +484,7 @@ void setup() { }); server.on("/detect", []() { - server.send(200, "text/plain", "{\"hue\": \"bulb\",\"lights\": 1,\"type\": \"rgb\",\"mac\": \"" + String(mac[5], HEX) + ":" + String(mac[4], HEX) + ":" + String(mac[3], HEX) + ":" + String(mac[2], HEX) + ":" + String(mac[1], HEX) + ":" + String(mac[0], HEX) + "\"}"); + server.send(200, "text/plain", "{\"hue\": \"bulb\",\"lights\": 1,\"modelid\": \"LCT001\",\"mac\": \"" + String(mac[5], HEX) + ":" + String(mac[4], HEX) + ":" + String(mac[3], HEX) + ":" + String(mac[2], HEX) + ":" + String(mac[1], HEX) + ":" + String(mac[0], HEX) + "\"}"); }); server.on("/", []() {