Enable javascript in your browser for better experience. Need to know to enable it? Go here.
Blogs Banner

Monitoring a Build with Bias Lighting

Recently I got myself a RBG led strip with a remote control similar to this one for bias lighting on my computer, before I had just a regular lamp sitting behind my monitor. If you want to know more about bias lighting check this post on Coding Horror. Here’s how it looks now:

Turning the bias lighting into a build radiator

The fact that I could change the colors of the RGB strip with a remote control gave me the idea of making it a build radiator with Arduino. The first step was to make Arduino send the same IR (infrared) commands that my remote sends. Fortunately all reverse engineering of this common remote was already done. The receiver expects IR commands using the NEC protocol.

Getting Arduino to send the IR commands

Arduino has a wonderful library to send IR commands. You just need to know which protocol (of the most commonly used) and which commands the IR receiver expects. Below the IR receiver attached to the RGB strip:

Truth is, it was not as simple as it sounds, at least for me. Getting Arduino to send the proper commands took me into a journey of discovery of IR protocols, timer interrupts and prescalers on micro controllers and finally striping down an old DVD remote control we had to get the IR LED. After being able to send IR commands to the RGB receiver, I settled with this Arduino code (on github):


#include <IRremote.h>

int BUITIN_LED = 13; // Arduino's builtin led

// IR remote commands for RBG led strip which are IR NEC format
// format: 0x00ff[command][command ^ 0xff]
// see: http://blog.allgaiershops.com/2012/05/10/reversing-an-rgb-led-remote/
// see: http://www.instructables.com/id/Reverse-Engineering-RGB-LED-Bulb-with-IR-remote/?ALLSTEPS
// see: http://www.sbprojects.com/knowledge/ir/nec.php
unsigned long IR_RED    = 0x00ff1ae5; // command for red color
unsigned long IR_GREEN  = 0x00ff9a65; // command for green color
unsigned long IR_YELLOW = 0x00ff2ad5; // command for yellow color
// IR send interface, uses pin 3 on Arduino
// see: http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
IRsend irsend;

// hold the current state, arduino will keep issuing this
// command in a loop
unsigned long IR_CURRENT_STATE;

void setup()
{
    Serial.begin(9600);
    pinMode(BUITIN_LED, OUTPUT);
    IR_CURRENT_STATE = IR_GREEN; // start green
}
void blinkBuiltInLed() {
    digitalWrite(BUITIN_LED, HIGH);
    delay(100);
    digitalWrite(BUITIN_LED, LOW);
}
unsigned long readCurrentState(char command) {
    switch (command) {
        case 'r':
            return IR_RED;
            break;
        case 'g':
            return IR_GREEN;
            break;
        case 'y':
            return IR_YELLOW;
            break;
        default:
            return IR_CURRENT_STATE;
    }
}
void sendIRCommand(unsigned long ircommand) {
    irsend.sendNEC(ircommand, 32);
    blinkBuiltInLed();
}
void loop()
{
    // read commands from serial 'r', 'g' or 'y'
    if(Serial.available() > 0) {
        char command[1];
        Serial.readBytesUntil('n', command, 1);
        IR_CURRENT_STATE = readCurrentState(command[0]);
    }
    sendIRCommand(IR_CURRENT_STATE);
    delay(1000);
}

 

During the loop, Arduino will read from the serial, and if we write “r” , “g” or “y”, it will issue the IR command for Red, Green and Yellow like the remote would do, but it will keep issuing it every second. Below is how each of the bias lighting colors looks like (Red, Yellow and Green):

Monitoring a build on Snap-CI

Snap-CI provides access to build status using a cctray formatted XML. The next step was to make a script that can fetch the cctray, parse it and write to the serial interface where the Arduino is attached. Luckily again most of the heavy lifting is done already, using the ‘cctray’ and ‘serialport’ gems I just need to send the proper commands. Here’s the Ruby script which fetches the cctray information and sends the build statuses back to Arduino (code on github).


#!/usr/bin/env ruby
require 'serialport'
require 'cctray'
class BuildRadiator
  # find which serial your Arduino is using and set it here.
  ARDUINO_SERIAL_PORT = '/dev/tty.usbmodem14631'
  STATUS_COMMAND = {
    'Building' => 'y',
    'Failure'  => 'r',
    'Success'  => 'g'
  }
  def initialize
    @serial = SerialPort.new(ARDUINO_SERIAL_PORT, 9600, 8, 1, SerialPort::NONE)
  end
  def send(command)
    @serial.write command
  end
  def notify(status)
    send STATUS_COMMAND[status]
  end
end
buildradiator = BuildRadiator.new
cctray        = CCTray.new("https://snap-ci.com/mavcunha/misc/cctray.xml")
while true do
  puts "Fetching build status"
  p = cctray.fetch.first
  status = p.activity == 'Building' ? p.activity : p.last_build_status
  puts "Notifying build radiator of status: #{status}"
  buildradiator.notify status
  sleep 10
end

This script will loop every 10 seconds, fetch the cctray information and notify my Arduino. The Arduino then reads the command and issues the proper IR command to the RGB strip.

Notes

  • One thing that I couldn’t solve was that when the SerialPort initializes, it resets Arduino which in turn makes the light green until the next build status (if not green) is retrieved. I’m probably doing something wrong.
  • If you send anything into the serial port, the code will retrieve each byte and apply the readCurrentState routine, it will ignore invalid commands but could lead to a delay from Arduino part to issue the IR command.
  • I used embedXcode for this code, that’s why you might see more files than a regular Arduino IDE project if you check the github project.
  • If a group of developers sharing a table have the same strip attached to the back of their monitors one Arduino could potentially issue IR commands to change all bias lighting and it could be anything from build monitor to production issues and so on. Sounds like something I would like to see.

​Here is a video illustrating the process:

Have you tried bias lighting as a build status radiator? How do you monitor your build?

Disclaimer: The statements and opinions expressed in this article are those of the author(s) and do not necessarily reflect the positions of Thoughtworks.

Keep up to date with our latest insights