I host a simple website titled ‘Say Hi’. If you press the switch displayed in that website, you will turn on a physical light-bulb in my bedroom. I thought it would be fun to explain how I set it up in this post.

A little bit of backstory

One fine evening, I had a crazy little idea. I get quite a lot of visitors to my blog. What if there was some way for these visitors to ‘Say Hi!’ to me over the internet?

The initial plan was simple. Add a basic input box and a button. Let a visitor type something in the box and submit it using the button. I would log the message somewhere in a database and go through it once in a while. Kinda like e-mail, but dumber.

Then I remembered something that inspired me to do something a bit more fun. I watch a lot of Twitch streams and one of my favourite streamers is Ellajaz. Twitch has a system where you can spend channel points that you accumulate by watching a stream to get channel rewards. These rewards could be unlocking a few emotes, showing an emote on the stream, making the streamer do something funny, reminding a streamer to take a sip of water or something else. The streamer can add any kind of channel reward to his stream.

Ellajaz has a channel reward where a viewer can spend channel points to switch on a smart light bulb in his room. I’m not sure if he was the first streamer to set something like this up, but I found the concept really interesting. I decided to spend my points to activate the reward and it worked! I could see the lightbulb in his room turn on to the color I specified in his stream. I thought it was amazing that I controlled something thousand of miles away with a simple click! Sure, you could say that about anything that you do on the Internet. But seeing something physical like a light bulb change on my command felt different.

Since I already have a Home Assistant setup controlling a few different smart devices in my room, I decided that I could setup something like this too on my website. I use a Wipro Smart Light Bulb that connects to my Wi-Fi network.

The plan

I understood the steps I had to take to set something like this up on a high-level:

  • Host a website somewhere. The website should contain a button, and some way to let the viewer know they’ve turned on a light-bulb in my room.
  • When a user presses the button in the website, I need to send an API request to Home Assistant to turn on my lightbulb.
  • Since the website will be hosted publicly, I need to make sure that the system is secure. I don’t want anyone frying my light-bulb or worse, gaining access to my Home Assistant instance.

With these steps in mind, I started building the website.

You can find the source code for the entire project in my Github repository

Creating the website

Initially I had an SVG image of a light-bulb and a button below it. The user would press it and the light-bulb would light up to show the user that they’ve turned it on. This worked okay but I knew I could do better.

I use a floorplan image to visualize and control smart devices in my Home Assistant instance. Basically, you just create a 3-D render of your room in a tool like Blender or Sweet Home 3D. You then render multiple images with different light switches turned on/off and overlay them over each other depending on which devices are turned on. This creates a nice visualization similar to a top-down view of your room.

I decided to use the same concept in my website. I used the renders of my room with all the lights switched off and one with the light bulb turned on. I would then overlay the second image over the first when the users clicks the button.

The effect shown in the video is a result of simply changing the opacity of an image using CSS transitions.

Now all I needed to do was to add a button and send a REST API request back to Home Assistant when the user presses it.

Sending the request back to Home Assistant

I decided to use Node for running the web-server. There wasn’t any particular reason behind my choice, except that I was familiar with Node and Javascript. You can find the source code for the server in the server.ts file in the Github repo I mentioned above. The code basically does the following things:

  • Use Express to host a server.

  • Serve the index.html file for the frontend.

  • Expose an REST API endpoint called /lightbulb/turn_on to handle requests to turn on the light bulb.

  • When a light-bulb turn on request is received, we do the following:

    • Log the IP address, user-agent and referer so that we know who (at least the country) turned on the light-bulb.
    • Send an HTTP request to Home Assistant to turn on the light-bulb.
  • I also use Express Rate Limit to rate limit light-bulb turn on request. Knowing the Internet, it’s almost certain that someone will try to mess around with my light-bulb. With Express Rate Limit, I’ve limited each IP address to 5 light-bulb turn on requests per minute.

And that’s it. Now all I needed to do was host the website somewhere and it should be working! I already host my blog using Nginx Proxy Manager so this part was easy. I just create a new proxy host in NPM and point it to my nodejs server port and my work is done.

Here is a diagram showing the entire system:

smart-light-hello-arc

Analytics

I use Grafana to log and monitor users who turn on my light switch. I send the data to an InfluxDB2 instance and Grafana visualizes this data.

smart-light-hello-grafana

Possible improvements

The smart light bulb that I use supports RGB lighting. This means I could potentially let users decide the colour that the light bulb turns on to. I really wanted to implement this, but I couldn’t come up with a way to show all the different combinations of colours in the room render.