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:
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.
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.