Simple ruby wrapper for Delcom build lights on Linux

This isn’t particularly new – I wrote this code a while ago, but it never got “finished” so I never wrote it up…

Many agile dev teams use Delcom USB build lights:
http://delcomproducts.com/productdetails.asp?productnum=804005

Coding for these is apparently quite complex… unless you are on a recent-ish Linux machine, in which case it’s amazingly trivial.

When you plug the light in, if you have the right modules loaded, you’ll get a set of magic files in a directory somewhere under:
/sys/bus/usb/drivers/usbled – on my PC with my light they show up under /sys/bus/usb/drivers/usbled/7-2:1.0, and you only need to care about 3 little virtual files:

-rw-rw-rw- 1 root root 4096 2010-02-12 16:26 blue
-rw-rw-rw- 1 root root 4096 2010-02-12 16:26 green
-rw-rw-rw- 1 root root 4096 2010-02-12 16:26 red

Those 3 files control the 3 components of the light. You can set or get the colour trivially from the shell, once you know the name:

$ cat /sys/bus/usb/drivers/usbled/7-2:1.0/blue
0
$ echo "1" > /sys/bus/usb/drivers/usbled/7-2:1.0/blue
# Blam!  The light goes blue!
$ cat /sys/bus/usb/drivers/usbled/7-2:1.0/blue
1
$ echo "1" > /sys/bus/usb/drivers/usbled/7-2:1.0/red
# and now the light goes purple - red + blue!

That’s really all you need to know – you can read, and write, the red/green/blue elements of the light. A little ruby wrapper I wrote makes for nicer colour names, and automatically works out the path to the light (ok, it just finds the first directory that looks right in the usbled path…):

#!/usr/bin/env ruby
class UsbLight
  COLOURNAMES = {
      :black => [0,0,0],
      :red => [1,0,0],
      :green => [0,1,0],
      :blue => [0,0,1],
      :cyan => [0,1,1],
      :magenta => [1,0,1],
      :yellow => [1,1,0],
      :white => [1,1,1]
    }

  def initialize
    @usbledpath = '/sys/bus/usb/drivers/usbled'
    @usbleddev = Dir.new(@usbledpath).find { |f| f =~ /^\d-\d.*/ }
    raise "Can't find device in #{@usbledpath}" unless @usbleddev
    @usbled = File.join(@usbledpath,@usbleddev)
    @lights = {}
    %w(red green blue).each do |light|
      @lights[light] = File.join(@usbled,light)
      raise "can't read #{light} light" unless File.readable?(@lights[light])
      raise "can't write #{light} light" unless File.writable?(@lights[light])
    end
  end
  def colour
    lights = [read_light("red"),read_light("green"),read_light("blue")]
    colour_pattern = COLOURNAMES.detect { |colour, pattern| pattern == lights }
    raise "bad colour combo: #{lights.inspect}" if colour_pattern.nil?
    colour_pattern[0]
  end
  def colour=(name)
    lights = COLOURNAMES[name.to_sym]
    raise "unknown lamp colour: #{name}" unless lights
    write_light("red",lights[0])
    write_light("green",lights[1])
    write_light("blue",lights[2])
  end
  def off
    self.colour = :black
  end

  private
  def read_light(name)
    File.new(@lights[name]).read.to_i
  end
  def write_light(name,value)
    open(@lights[name],"w") do |f|
      f.puts(value.to_s)
    end
  end
end

I have a Hudson watcher that uses this to set the light colour – but that’s a subject for another post!



One Response to “Simple ruby wrapper for Delcom build lights on Linux”

  1.   korny Says:

    Just a note – if using a recent Delcom light, you should check out the ruby driver at http://github.com/ileitch/delcom_904008_driver – apparently the linux kernel doesn’t support new lights (yet!)

Leave a Reply

*