TL;DR: If you have lights controlled by Shelly dimmers and/or via a Philips Hue bridge, Turtles might possibly be a useful project for you. It’s reasonably simple to set up and the code is small and straight-forward so it would be easy to hack at if you like that sort of thing, but it is very limited in functionality compared to something like Home Assistant.

The itch

My wife and I recently completed a renovation project of a big part of our house. Almost all of the new lights were controlled by Shelly dimmers, which are Wi-Fi attached and have some simple APIs for programmability. A couple of lights needed more power than the Shelly dimmers could handle, and the electricians used some no-name Zigbee dimmers for this.

Of course this caused an immediate itch to want to be able to control all the lights at once from my smartphone, create scenes and so on.

I poked a bit at the Shelly APIs, they’re very simple to use as long as you’re on the same Wi-Fi, and I ordered an off-brand Wi-Fi/Zigbee bridge via Aliexpress, figuring it might arrive before the holiday break and this could be a nice project during the holiday break.

I also took a look at Home Assistant and some other existing home automation platforms. Rationally, I might have been better off going with Home Assistant, which has ready-made integrations with Shelly, Zigbee dimmers, and probably thousands of other device types, but I wanted complete control and hackability, and I preferred to spend time building my own system rather than learning and customizing Home Assistant and maybe never getting it to work like I want it to.

Scratching it

The AliExpress shipment arrived just before the holidays! Sadly, the order did not contain a Zigbee bridge but rather a Bluetooth Low Energy (BLE) bridge. The AliExpress folks brushed me off when I sent them a photo showing the packaging of the wrong device… oh well, that’s something like $20 down the drain ($8 for the thing itself with shipping, and the rest to Icelandic customs and postal authorities… don’t get me started).

Lucky for me, my wife had bought a Philips Hue starter set for our son as a Christmas present, and it comes with a bridge which very quickly and easily discovered the other Zigbee lights! The Hue is very hackable, too, with simple APIs and a bunch of unofficial documentation around the Internet. The only tricky bit was that it seems that the Hue bridge will change its MAC address from time to time, so assigning it a static IP in our home router did not work - a couple of days later it presented as a new MAC address and therefore got a different IP. In the end it was simple to implement SSDP discovery.

My programming language of choice these days is Elixir (along with Erlang and JavaScript) and that’s what I implemented Turtles in. The de facto standard web framework for Elixir is called Phoenix. It’s really good, but the default generator for a new project does create a veritable ton of all kinds of files and configuration, much of which I don’t need in a simple project like this… but which I haven’t gotten around to removing.

To use Turtles, go get the source code, install asdf, create a file named tconfig.secret.exs in the config directory, set static IPs for all your Shelly lights in your home router, and document all the lights you want to control in the tconfig.secret.exs file similar to the below:

config :turtles,
  zones: [
  dimmers: [
      %{name: "Forstofa inngangur", type: :shelly, zone: "Foyer", ip: ""}},
      # Hue device unique IDs can be found at
      # http://{ip address of bridge}/api/{Hue bridge username}/lights
      %{name: "Foyer indirect LEDs", type: :hue, zone: "Foyer", bridge: :hue1, unique_id: "04:11:84:ff:13:43:75:a3-01"}},

      %{name: "Kitchen worktops", type: :shelly, zone: "Kitchen", ip: ""}},
      %{name: "Kitchen island", type: :hue, zone: "Kitchen", bridge: :hue1, unique_id: "03:11:84:ff:13:12:75:a1-03"}},
  bridges: %{
    # For details on getting the username, see
    # The unique_id can be found at http://{ip address of bridge}/description.xml
    # under the <serialNumber> key.
    hue1: %{type: :hue, unique_id: "abcdef01234", username: "HUEBRIDGEUSERNAME"}

You can get fancy with how you run Elixir, building an Erlang release and/or putting everything into a Docker container, but from my perspective for a local-WiFi system like this you can simply run it in development mode as follows:

cd ~/turtles   # assuming that's where you retrieved the code to
iex -S mix phx.server

Maybe run it in a screen session that you can detach from and reattach to later, on an always-on old Linux laptop in a closet, connected to the same Wi-Fi as the lights and bridge, of course.

Obligatory screenshots

I’ll end with some obligatory screenshots showing the UI.

Let me know if you try it! It was just to scratch my own itch, but still would be fun if it’s useful for someone.

Main screen - control lights, choose scenes

Main screen - control lights, choose scenes

Create a scene; give it a name and choose which lights it will affect, and it will later apply the same state to lights as they currently have

Create a scene; give it a name and choose which lights it will affect, and it will later apply the same state to lights as they currently have

Manage scenes; so far all you can do is delete but I want to add reordering and renaming.

Manage scenes; so far all you can do is delete but I want to add reordering and renaming.