Script Shelly scripts
Control a Philips Hue room from a wall switch
Turns a wall switch wired to a Shelly into a switch for one Hue room. It talks to your Hue Bridge directly over Wi-Fi, with no Home Assistant and no cloud.
- Gen2
- Gen3
- Gen4
- Pro
// Hue wall switch: a switch on a Shelly input controls a Philips Hue room// through the Hue Bridge on your Wi-Fi. No Home Assistant, no cloud. let CONFIG = { bridgeIp: "192.168.1.20", roomName: "Living room", inputId: 0, appKey: "",}; // The bridge only hands out a key in the 30 seconds after its button is// pressed. Ask every 3 seconds for a minute, which covers walking to it.let PAIR_EVERY_SEC = 3;let PAIR_FOR_SEC = 60;let KVS_KEY = "hue-app-key"; let key = CONFIG.appKey;let roomLight = null;let roomLabel = CONFIG.roomName;let homeLight = null;let busy = false;let pairTimer = null;let pairUntil = 0;let bridgeAnswered = false; function hue(method, path, body, callback) { let req = { method: method, url: "https://" + CONFIG.bridgeIp + path, headers: { "hue-application-key": key }, // The bridge's certificate is self-signed, so it can't be checked against // the Shelly's built-in list. The request never leaves your network. ssl_ca: "*", timeout: 10, }; if (body !== null) req.body = JSON.stringify(body); Shelly.call("HTTP.Request", req, callback);} function failed(res, err, what) { if (err !== 0) { print("Couldn't reach the Hue Bridge at " + CONFIG.bridgeIp + " to " + what + "."); return true; } if (res.code === 403) { print("The bridge refused the key. Set appKey to \"\" and restart to pair again."); Shelly.call("KVS.Delete", { key: KVS_KEY }); return true; } if (res.code !== 200) { print("The bridge answered " + res.code + " when asked to " + what + "."); return true; } return false;} function onSet(res, err) { busy = false; failed(res, err, "switch the lights");} function setLight(id, state) { hue("PUT", "/clip/v2/resource/grouped_light/" + id, state, onSet);} function onRoomState(res, err) { if (failed(res, err, "read the room")) { busy = false; return; } let on = JSON.parse(res.body).data[0].on.on; print(roomLabel + (on ? " off." : " on.")); setLight(roomLight, { on: { on: !on } });} function press(kind) { if (roomLight === null) { print("Still looking for the room. Try again in a moment."); return; } if (busy) return; busy = true; if (kind === "toggle") { hue("GET", "/clip/v2/resource/grouped_light/" + roomLight, null, onRoomState); } else if (kind === "bright") { print(roomLabel + " to full brightness."); setLight(roomLight, { on: { on: true }, dimming: { brightness: 100 } }); } else { print("Every Hue light off."); setLight(homeLight, { on: { on: false } }); }} function onEvent(ev) { if (ev.info.component !== "input:" + CONFIG.inputId) return; let e = ev.info.event; if (e === "single_push") press("toggle"); else if (e === "double_push") press("bright"); else if (e === "long_push") press("all-off");} // A rocker (input type Switch) has no pushes: every flip toggles the room.function onStatus(st) { if (st.component !== "input:" + CONFIG.inputId) return; if (typeof st.delta.state === "boolean") press("toggle");} function groupedLight(item) { for (let i = 0; i < item.services.length; i++) { if (item.services[i].rtype === "grouped_light") return item.services[i].rid; } return null;} function onHome(res, err) { if (failed(res, err, "find the whole-home group")) return; homeLight = groupedLight(JSON.parse(res.body).data[0]); print("Ready. Use the switch.");} function onRooms(res, err) { if (failed(res, err, "list the rooms")) return; let rooms = JSON.parse(res.body).data; let names = []; let want = CONFIG.roomName.toLowerCase(); for (let i = 0; i < rooms.length; i++) { let name = rooms[i].metadata.name; names.push(name); if (name.toLowerCase() === want) { roomLight = groupedLight(rooms[i]); roomLabel = name; } } if (roomLight === null) { print("No room called " + CONFIG.roomName + ". The bridge has: " + names.join(", ") + "."); return; } hue("GET", "/clip/v2/resource/bridge_home", null, onHome);} function findRoom() { hue("GET", "/clip/v2/resource/room", null, onRooms);} function stopPairing() { Timer.clear(pairTimer); pairTimer = null;} function onPair(res, err) { if (pairTimer === null || err !== 0) return; bridgeAnswered = true; let reply = JSON.parse(res.body)[0]; if (reply.success) { stopPairing(); key = reply.success.username; Shelly.call("KVS.Set", { key: KVS_KEY, value: key }); print("Paired with the Hue Bridge. The key is saved on this Shelly."); findRoom(); }} function askForKey() { if (Shelly.getUptimeMs() > pairUntil) { stopPairing(); if (bridgeAnswered) print("No button press seen. Restart the script to try again."); else print("Couldn't reach a Hue Bridge at " + CONFIG.bridgeIp + ". Check bridgeIp."); return; } Shelly.call("HTTP.Request", { method: "POST", url: "https://" + CONFIG.bridgeIp + "/api", body: JSON.stringify({ devicetype: "shelly#hue-wall-switch" }), ssl_ca: "*", timeout: 5, }, onPair);} function onSavedKey(res, err) { if (err === 0 && res && typeof res.value === "string") { key = res.value; findRoom(); return; } print("Press the round button on your Hue Bridge now. Waiting " + PAIR_FOR_SEC + " seconds."); pairUntil = Shelly.getUptimeMs() + PAIR_FOR_SEC * 1000; pairTimer = Timer.set(PAIR_EVERY_SEC * 1000, true, askForKey);} Shelly.addEventHandler(onEvent);Shelly.addStatusHandler(onStatus);print("Hue wall switch started.");if (key !== "") findRoom();else Shelly.call("KVS.Get", { key: KVS_KEY }, onSavedKey); What it does
With a push button, one press switches the room on or off, two presses set it to full brightness, and a long press turns off every Hue light in the house. With a rocker, every flip switches the room. The script finds the room by its name in the Hue app, so lights you add to the room later answer to the switch without any change to the script.
The first time it runs, the script pairs with the bridge itself: press the button on the bridge within a minute and it saves its key on the Shelly. Everything stays on your network, so the switch keeps working when the internet is down. If the bridge doesn't answer, the console says so and the press is dropped, so the lights never change long after you've pressed.
Install it on your Shelly
Before you install
- Set the input type
In the Shelly app, set the input to Button for a push button or Switch for an ordinary rocker. On a relay, also set the input mode to Detached so the switch no longer works the relay.
Install the script
Have the Hue Bridge within reach. Once the script runs, you have a minute to press its button.
Shelly Smart Control
- Open the device and tap Scripts
In Shelly Smart Control, open the room, then the device. Tap Scripts, the { } icon in the menu down the left.
- Tap Create new script
If the device has no scripts yet, the screen says No scripts created.
- Name it, paste the code, then tap Save
Name it hue-wall-switch. Tap in the code area, paste the script you copied above, then tap Save (the disk icon at the top right).
- Tap the play button
The play button lights up once the script is saved. Tap it and a message says the script has been started.
- Close the editor and turn on Run on startup
Back on the Scripts screen, turn on Run on startup next to your script, so it starts again after a power cut or a firmware update.
Direct access via IP
- Open the device's web page and click Scripts
Find the IP address in the Shelly app under Device settings, then Device information, and type it into a browser on the same Wi-Fi. Click Scripts in the menu on the left.
- Click Create script
If the device has no scripts yet, the list says so.
- Name it, paste the code, then click Save
Name it hue-wall-switch. Click in the code area, paste the script you copied above, then click Save (the disk icon above the code).
- Click Run and check the console
Run appears once the script is saved. The console under the code then prints what the script is doing.
- Turn on Run on startup
Click Scripts again and turn on Run on startup next to your script, so it starts again after a power cut or a firmware update.
After you install
- Pair with the bridge
Within a minute of starting the script, press the round button on top of the Hue Bridge. On the device's web page, the console prints Paired with the Hue Bridge, then Ready.
- Test it
Press the button once to switch the room on or off, twice for full brightness, or hold it to turn off every Hue light. With a rocker, each flip switches the room.
Changelog
v1.0 First release. Still need a hand?
We answer most messages within one business day. If your question is about an existing order, have your order number ready. It speeds things up.
Contact us