For our latest OpenDNS hackathon, I decided it would be a fun exercise to use an individually addressable digital LED strip to create a build light for our Jenkins instance. We work in a continuous development environment, and the light gives a quick heads-up display to see if it’s safe to merge. Plus, LEDs are just plain fun!
I followed this Adafruit article but used a Raspberry Pi 2 instead of Pi 1. The Pi 2 has more available pins, but the connecting pins will be the same. For power, I opted for a 5V/10Amp switching PSU, which provides more than double what my two-meter strip needed.
If you have some basic knowledge of Python, Linux, and soldering you should have no problem completing this in a few hours. If you’re anything like me, you’ll spend the majority of your time playing with different lighting patterns.
- Digital RGB LED strip – LPD8806
- 5V/10A switching power supply (must be 5v)
- JST 4-pin inline cables (plug and receptacle)
- DC power jack
- Female jumper wires (or ribbon cable)
- Raspberry Pi 2 (or 1)
- SDCard (Raspberry Pi boots off the SDCard)
- Soldering iron*, solder, and wire strippers
- Optional Raspberry Pi case
*You can get away with not soldering if you buy appropriate connectors to hold wires in the place. I also tried the ribbon cable used in the Adafruit tutorial and it provided a very tight connection.
Let’s wire it up!
Raspberry Pi 2 Pin-out diagram
Connect +5V and GND from the power supply to the +5V and GND pins on both the LED strip and the Raspberry Pi2 GPIO header. I simply soldered two wires into the positive jack and then two into the ground jack of the DC adapter. That way I could power both the Raspberry Pi and the LED strip off the same PSU.
Note: Do not attempt to power the LEDs off a micro USB cable connected to the Pi.
Connect the LED strip
The board’s SPI_MOSI pin connects to the DI input on the LED strip, and SPI_CLK pin connects to the CI input on the LED strip.
Be aware of polarity
I lucked out and Adafruit shipped my LEDs with a female JST 4-pin inline cable attached to the inputs of the LEDs. But Adafruit’s website says this is not always the case, and you might find your JST cable connected to the LED outputs! So be aware of which end you’re connecting to on the LED strip. If you look closely at your LED solder points you can see DI and CI for input, while DO and CO are your outputs respectively.
Once everything is connected it’s time to plug in the PSU.
OK, now I’ve got random LEDs lit
Initially, when I connected my LED strip there were no lights or random lights turning on until I ran my python script instructing the LEDs. Whew! But this could also be a sign that you’re not providing enough amperage to your LEDs. Adafruit has some troubleshooting tips to read over. If you’re using more than enough power then lets ignore the random LEDs and let’s move on.
Raspberry Pi setup
Rasberry Pi’s own site has very good instructions on how to do the following:
- Install an OS to Raspberry’s SDCard (I used NOOBS with Raspbian)
- Find the Raspberry’s IP address
- Be able to SSH to the device
- Enable SPI (serial port interface bus)
Here’s some of the software dependencies and updates that helped me. I used python 2.7.3 for this project, which was preinstalled on the Pi. I recommend using virtualenv to install your python dependencies. It’s a good habit to get into and keeps things tidy. You need to first ssh pi@ipaddress and install these from the command line of the Pi. Most of these will require sudo.
$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install python-pip $ sudo apt-get install python-dev $ sudo apt-get install git
Install Bibliopixel for LED bliss
Download and install the latest from github
$ git clone email@example.com:ManiacalLabs/BiblioPixel.git $ cd BiblioPixel $ sudo python setup.py install $ sudo pip install -r requirements.txt
Reboot once everything is installed
$ sudo reboot
Bibliopixel should’ve included multiple drivers to choose from. We’re using the LPD8806. Once it’s installed (and SPI is enabled) you should see the device in your dev directory on your Pi:
$ ls -la /dev/spidev* crw-rw---T 1 root spi 153, 0 Jan 1 1970 /dev/spidev0.0
Now for the fun part, playing with LEDs!
I wrote a simple python script that utilizes threads and a queue. Using a queue is one way to communicate between threads with the added bonus that it’s thread safe. The change of color can be thought of as an event and your event pool as a handler. When an event is emitted, the appropriate candidate responds with it’s particular color or animation.
The color changes I’m using in my script are very simplistic on/off color changes but Bibliopixel provides some very fun pre-written animations that you might try modifying.
Clone the latest copy of the jenkins status light script:
$ git clone https://github.com/opendns/jenkins-status-light $ cd jenkins_status_light $ sudo pip install -r requirements.txt
Manually running the script
Simply supply the jenkins host and job name as command line arguments to run:
$ sudo python jenkins_status_light.py --jenkins-url https://jenkins.example.com --job job-name
At this point if the script didn’t exit you should see LEDs come up for the current build status of Jenkins and change whenever Jenkins build status change from success, failure or aborted. But if the script did exit, you’ll need to read through your console to see what is failing and address that.
The colors I selected might not be what you want, but you can easily swap out predefined colors in the global section at the top of my script.
Once things are working then we should try wrapping our script with Supervisor. This provides us with monitoring and helps keep the script running. If our lighting script exits or crashes for any reason, Supervisor will restart it. As an added bonus, when you plugin the Raspberry Pi, the script will automatically run and the lights come right up!
As the root user, run the following command to install the Supervisor package:
apt-get install supervisor
Let’s add a configuration file to tell Supervisor where our jenkins_status_light.py file is and what to do with it. Save the file at /etc/supervisor/conf.d/jenkins_status_light.conf.
[program:jenkins_status_light] command=/usr/bin/env python /home/pi/jenkins_status_light.py --jenkins-url https://jenkins.server.com --job job-name autostart=true autorestart=true stderr_logfile=/var/log/jenkins_status_light.err.log stdout_logfile=/var/log/jenkins_status_light.out.log
Once you’ve saved that file then as the root user you can inform Supervisor of our new file:
Then update with those changes:
To control Supervisor you can use the following commands:
sudo service supervisor stop / start / restart
To monitor stdout of our py file output:
tail -f /var/log/jenkins_status_light.out.log
There’s also an interactive mode that is worth reading about.
Securing the Pi
The Raspberry Pi is a full fledged computer and it’s only as secure as you make it. Here’s a list of some things to do to increase the security of your device:
- The first thing you should absolutely do is change the default password. You can test the strength of your password with Steve Gibson’s password haystack. The higher the entropy the better.
- Make sure everything is up to date. We did this with apt-get update and apt-get upgrade above.
- Enabling unattended security updates which can help avoid “0-day exploits”.
- Change the default user account to something other than ‘pi’ (Note that root is disabled by default on Raspbian which is great)
- Close all services and ports you don’t use.
- Don’t let untrusted people near it. It’s simple to plug a malicious device into it to gain control.
- Don’t make the Pi publicly available on the internet unless you know what you’re doing. It’s best to sit behind your NAT router with DMZ disabled and behind a firewall if you have one (there’s one built into Linux, but it can be difficult to manage).
- Consider using IP tables to only allow specific IP addresses or IP ranges to connect to your device.
- Setup Fail2ban to block suspicious SSH connections who make too many failed attempts attempts against the device. This will provide a 10 minute ban for anyone who has 3 unsuccessful login attempts:
$ sudo apt-get install fail2ban
Note that some things such as “changing the ssh port” while not bad, will only get you so far. “Security through obscurity” won’t do much but slow down a determined hacker.
- Using a queue means lights don’t always update immediately, esp. if build times are very short
- Daemonizing threads and being able to cleanly exit the script would be great
- Sometimes the light will quickly flash a past build color before updating to the correct color
- Have the script automatically determine how many LED strips exist
- Try creating a moving ‘progress bar’ animation to display estimated build duration.
Since this was 24-hour hackathon project I’m sure there are plenty of code improvements to be made. Please feel free to fork and submit changes and improvements! We’d love to see your own projects and what you did with this! Happy hacking!