How I made a light that turns on when streaming
Tags: showdev, electronics, christmas
Published: 2020-12-24 02:32:57

I asked my friend Ben what I could get him for Christmas this year and he said that I should surprise him and make something. When I was looking at my list of projects thinking what I could make him it hit me: I had an idea of making an indicator light for our apartment so my partner could see if I was in a meeting when getting home from work[^ideasource]. I could do something similar for Ben and make him an "On Air" sign that turns on when he starts streaming!

[^ideasource]: I got my idea from Christine on the [Twilio Remote Participants](https://www.twitch.tv/twilio) stream when she talked about the [light to indicate of she is in a meeting](https://www.youtube.com/watch?v=8_FdR-L7qrs) she made. This stream has been something I look forward to while I haven't been able to travel and see friends and I still think [Phil](https://dev.to/philnash) should consider the pull request I made to the video chat application he made on his stream and add the "CRIME" reaction to it.

# Electronics

The first thing I needed to figure out was the electronics. I had a couple of NodeMCU boards that have been sitting in my box of random things for years that I had yet to play around with. I could use one to act as a webserver and turn LEDs on and off using some webhooks. I pulled one of them out of the box, opened it and started looking at the documentation for them.

A lot of what I did to get the board set up is outlined in the [tutorial I followed](https://tutorials-raspberrypi.com/introduction-programming-esp8266-nodemcu-board/). Getting started with the code was straight forward and got me really far really quickly. At the start I needed to:

- Connect the board to my computer
- Flash it with some default firmware
- Connect to it using the ESPlorer software
- Write some basic code to connect it to my Wifi
- Write some code so it could handle web requests

That got me to this point with the code:
{% gist https://gist.github.com/mpomery/1d1bf485c097aaf8129bc1a3f25f2ee6 file=NodeMCUBasics.lua %}

After I had it connected to my WiFi and acting as a webserver I started running into problems. I couldn't get the [HTTP Server Module](https://nodemcu.readthedocs.io/en/release/lua-modules/httpserver/) to load, so didn't have access to nice functions for understanding the requests and responding to them.  I decided I would keep it simple and do basic string manipulation to understand the requests and some basic error handling.

I also tried to use [Pulse Width Modulation](https://nodemcu.readthedocs.io/en/release/modules/pwm/) to control the RGB LEDs and had some difficulty understanding the documentation. Once the LEDs were lighting up and controllable I noticed that they were flickering. I stopped using pulse width modulation to control them and used a binary on/off instead. I would have liked to have more control over the colour of the LEDs, but the strip I had bought was fairly dull and didn't look that great even at full brightness.

The end result is some functional code.

{% gist https://gist.github.com/mpomery/1d1bf485c097aaf8129bc1a3f25f2ee6 file=OnAirLight.lua %}

I don't think I will come back to this code (or my other NodeMCU boards) any time soon for other projects.

# Getting OBS to trigger webhooks

I found getting OBS to trigger webhooks was easier than I initially expected. I searched for "OBS Trigger Webhook" and came across an [OBS plugin for sending webhooks to discord](https://gist.github.com/Parik27/3fca8328812c28375dbc3d05a982fc49) that made me aware of OBS Scripts. I used Parik27's code to figure out the minimum code I needed.

{% gist https://gist.github.com/mpomery/1d1bf485c097aaf8129bc1a3f25f2ee6 file=TestingObsScript.py %}

This was a good starting point, but the script wasn't outputting anything or running. Time to look at the [OBS Scripting documentation](https://obsproject.com/docs/scripting.html). Reading this I saw what was causing my problems listed as a note.

> NOTE: On windows, currently only Python 3.6 is supported.

After installing Python 3.6 and setting the Python install directory to point to it, my script was working!

Now that I had it logging out on events, triggering webhooks was next. Adding in a urllib request on the events hardcoded to the IP Address of the NodeMCU board was going to be more than sufficient for this project.

{% gist https://gist.github.com/mpomery/1d1bf485c097aaf8129bc1a3f25f2ee6 file=OnAirWebhookHandler.py %}

I want to come back to this code in the future, parameterize it and add in more events that you can trigger webhooks from.

# The Housing

A spaghetti of electronics isn't exactly a nice sign that you could proudly have sitting on your desk, so I needed to create a housing for it. Fortunately for me I have a Cricut that I can use to cut text out of vinyl with, and my local makerspace has a laser cutter I could use to make the housing.

Cutting the text on the Cricut was simple. My partner had already pulled it out of the cupboard so I just needed to plug it in, put the text into a project in Cricut Design Space, load my material and then press cut. The machine had been in the cupboard for almost a year, and if it was still there I probably would have painted on the text or engraved it instead.

![Text "On Air" cut out of vinyl](https://dev-to-uploads.s3.amazonaws.com/i/fhgpc3iswsf3sonvx6pd.jpg)

It took me two attempts to cut the housing out with the laser cutter. The first attempt failed because I had the speed too high and the laser didn't cut all the way through, and I moved the origin so I couldn't do another pass[^lasersettings]. Attempt number two was better and I had a housing!

[^lasersettings]: I found out on my next makerspace visit that the lens and the mirrors had a light coating of smoke and were absorbing some of the lasers power, making it cut less. I now know how to check and clean these to help maintain the laser cutter.

![All the pieces on the workbench being glued together and prepared for assembly](https://dev-to-uploads.s3.amazonaws.com/i/4f17ftz0a329h618ip9x.jpg)

![Assembled with the last part of the glue drying](https://dev-to-uploads.s3.amazonaws.com/i/5bdvobwsn9repm13jisw.jpg)

# Future Improvements

It's always good to look back on a project and think about what could be done differently next time.

Things I have thought about:
- **Putting the source code into version control.** It would make it harder for me to hard code values because they would be publicly visible. It would also make it easier to go back when I made a mistake and revert to code I knew worked, instead of needing to fix forward.
- **Using a different board.** The NodeMCU Boards are really nice for playing around with, but I'm giving this to someone else. I don't want to have to reprogram the sign when he moves house so I can connect it to his Wifi.
- **Not needing direct network access.** This would make it easier to set up and would allow me to make it go into a party mode remotely.
- **Better LEDs.** The ones I used where the cheapest 5V LED strip I could find. They aren't individually addressable so you can't do cool patterns like rolling colours. Either the NodeMCU board or the LEDs themselves didn't like PWM, which limits the range of colours and patterns I could do. At full brightness you can also see the distinct red, green, and blue, and they aren't as bright as I would have liked.
- **A better housing.** The housing I made works, but having to open it up to access the board is annoying. Plus having the board and excess wiring inside it gets in the way of the LEDs and casts shadows, though better LEDs could make this a non-issue. I also didn't have access to any frosted acrylic, so did what I could with some non-laser safe acrylic I had, cutting it to size on the bandsaw and leaving the plastic protecting sheets on the backside to act as an opaque layer.

I had a different development board arrive right after I finished this, which is a better platform to work from. I have made version two, which I will give to Ben and write a follow up guide if you want to make one yourself.

# Delivery

Getting this to Ben and setting up OBS on his machine to use it wasn't as straight forward as I would have liked. I had to talk to his dad to get permission to add it to the network. His dad gave me permission to add it to their guest Wifi, but I need direct access to be able to call the webhooks. After talking to his dad some more and explaining what it is and how it works, he gave me the details for the main network so I could program it in. If I didn't need to upload the program to change the network it connected to, I could have given it to Ben without the details programmed in and gotten him to do that himself.

Delays caused by unexpected car trouble and an outbreak of Covid19 in Sydney mean that I didn't get to give this to Ben when we had initially planned to catch up, so instead he got the improved version two that I haven't written about yet[^version2], and he loves it! Version two is easier to reprogram to connect it to wifi, but we encountered issues when doing that. The new board I started using doesn't like connecting to Channel 12 or 13 which it appears Ben's home network was on (it was set to auto). It took around 40 minutes of me and his dad going back and forth trying some different settings to get it to work. Ben also uses Streamlabs OBS, which is different to OBS Studio and doesn't have the scripts menu or something similar. Instead of automating it, I set it up so that he has a simple UI that he can use to control it.

[^version2]: I am planning on writing about the version two build as a guide that you could follow, with a different trigger for the lighting (I'm thinking something data driven).

![Version two sitting on top of Ben's PC lit up as a rainbow](https://dev-to-uploads.s3.amazonaws.com/i/wps1a7dp1mxqn2hb5fhd.jpg)

![Version one next to an in progress version two.](https://dev-to-uploads.s3.amazonaws.com/i/kmwem7d0vepxbfarlscl.jpg)