Skip to main content

If your fingers get tired from constantly clicking refresh to make sure you haven’t missed out on the latest awesome Agency Spy post then you’re in luck. I’m pleased to announce the Agency Spy Alertometer. Simply follow my easy to construct 94 step process and you’ll have this puppy glowing on your desk in no time. Ok, it’s not actually that difficult.

The Agency Spy Alertometer is pretty cool though. This simple lamp and desktop widget will keep you up to date on the latest agency news by alerting you to new stories by changing colors. Whenever a new article is posted the lamp will change colors based on which agency is mentioned. If an insider leaks breaking news on DDB the lamp will turn yellow, if someone defects at CP+B the lamp will glow orange. If that’s not enough for you it comes with a handy desktop widget that matches the color of the lamp and displays the article title.

The alertometer is a good project for creatives learning how to connect the digital and physical world. A combination of arduino and processing, you’ll dip your toe in the world of code, don’t worry it’s provided and at the same time connect a few simple wires to power your lamp.

This project is in response to the growing demand for hands on interactive art directors. I’m a strong believer that you can’t create truly innovative ideas unless you know what’s possible. The future of the internet will lie in the interaction of online data with physical devices and tinkering with projects such as this is as good a place to start as any.

What you’ll need:

You’ll also need to download the simpleML library for processing to work with XML data here.

Don’t get nervous it’s going to be ok. You can learn how to install a library here.

I’m not going to go super deep, you’ll want to check out the processing and arduino site’s to learn more or check out two helpful books. Getting Started with Arduino and Getting Started with Processing. They were really helpful in creating the alertometer.

So what is going on: Basically we’ve just written a program in processing that grabs the latest Agency Spy Article title. We have the program scan the title and search for words that match our list of agencies. If there is a match we update a color value that we have assigned to that agency title. That color is then passed to the arduino and changes the color of the lamp. This is a super stripped down explanation, but hopefully you get the point. Like I said I’m a creative, not a developer, or maybe a little of both, but I think everyone should be.

You’ll want to upload your arduino code first. Then run your processing sketch ( a sketch is what code is called in processing).

Here’s the Arduino code:

// Arduino Networked Lamp from Getting Started with Ardino
//
 
#define R_LED 11
#define G_LED 10
#define B_LED 9

int val = 0; // variable to store the value coming from the sensor

//int btn = LOW;
//int old_btn = LOW;
//int state = 1;
char buffer[7] ;
int pointer = 0;
byte inByte = 0;

byte r = 0;
byte g = 0;
byte b = 0;

void setup() {
  Serial.begin(9600);  // open the serial port
}

void loop() {

  if (Serial.available() >0) {

    // read the incoming byte:
    inByte = Serial.read();

    // If the marker's found, next 6 characters are the colour
    if (inByte == '#') {

      while (pointer < 6) { // accumulate 6 chars
        buffer[pointer] = Serial.read(); // store in the buffer
        pointer++; // move the pointer forward by 1
      }

      // now we have the 3 numbers stored as hex numbers
      // we need to decode them into 3 bytes r, g and b
      r = hex2dec(buffer[1]) + hex2dec(buffer[0]) * 16;
      g = hex2dec(buffer[3]) + hex2dec(buffer[2]) * 16;
      b = hex2dec(buffer[5]) + hex2dec(buffer[4]) * 16;
      
      pointer = 0; // reset the pointer so we can reuse the buffer
     
    }
  }   
  
    analogWrite(R_LED, r);  // turn the leds on
    analogWrite(G_LED, g);  // at the colour
    analogWrite(B_LED, b);  // sent by the computer
   
  delay(100);                // wait 100ms between each send
}

int hex2dec(byte c) { // converts one HEX character into a number
    if (c >= '0' && c <= '9') {
      return c - '0';
    } else if (c >= 'A' && c <= 'F') {
      return c - 'A' + 10;
    }
}


Here's the Processing code:

//Import libraries
import simpleML.*;
import processing.serial.*;


// Variables
String feed = "http://www.mediabistro.com/agencyspy/feed/rss";
int interval = 10;  // retrieve feed every 10 seconds;
int lastTime;       // the last time we fetched the content
color c = (105); //background color variable
String cs; //color sent to arduino
String oldcs; //check old color to see if updated
String headline = "Updating"; //Current headline from blog
//int light = 0;  // light level measured by the lamp
Serial port;
String buffer = ""; // Accumulates characters coming from Arduino
PImage b; //store logo image



XMLRequest xmlRequest;  //request to blog for title

void setup() {
  size(500, 200);
  frameRate(10);    // we don't need fast updates
  fill(255);
  // Creating and starting the request
  xmlRequest = new XMLRequest(this, feed);
  xmlRequest.makeRequest();

  lastTime = 0;

  String arduinoPort = Serial.list()[1];
  port = new Serial(this, arduinoPort, 9600); // connect to Arduino
}

void draw() {
  background(c);

  //background image
  b = loadImage("AlertometerUI.png");
  image(b, 0, 0);

  int n = (interval - ((millis()-lastTime)/1000));

  fill(0); //sets text color

  cs = "#" + hex(c, 6); // Prepare a string to be sent to Arduino

  text("Sending:", 15, 188);
  text(cs, 78, 188);
  text("Next update in "+ n + " seconds", 310, 188);
  text( headline, 38, 135);

  if (n <= 0) {
    fetchData();  //checks for new article post
    lastTime = millis();

    if (oldcs != cs) {
      updateBlink();
    }
  }

  port.write(cs); // send data to Arduino

  if (port.available() > 0) { // check if there is data waiting
    int inByte = port.read(); // read one byte
    if (inByte != 10) { // if byte is not newline
      buffer = buffer + char(inByte); // just add it to the buffer
    }
    else {

      // newline reached, let's process the data
      if (buffer.length() > 1) { // make sure there is enough data

        // chop off the last character, it's a carriage return
        // (a carriage return is the character at the end of a
        // line of text)
        buffer = buffer.substring(0, buffer.length() -1);

        // turn the buffer from string into an integer number
        //light = int(buffer);

        // clean the buffer for the next read cycle
        buffer = "";

        // We're likely falling behind in taking readings
        // from Arduino. So let's clear the backlog of
        // incoming sensor readings so the next reading is
        // up-to-date.
        port.clear();
      }
    }
  }
}

// When the request is complete, prints title to 
String netEvent(XMLRequest ml) {
  // Retrieving an array of all XML elements inside "" tags
  String[] headlines = ml.getElementArray("title");
  for (int i = 0; i < 1; i++) {
    // println(headlines[1]);
    headline = (headlines[1]);
  }
  return headline;
}

void fetchData() {

  //make call again to site
  xmlRequest.makeRequest();
  try {
    URL url = new URL(feed);  // An object to represent the URL
    // prepare a connection   
    URLConnection conn = url.openConnection(); 
    conn.connect();
    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
  } 
  catch (Exception ex) { // If there was an error, stop the sketch
    ex.printStackTrace();
    System.out.println("ERROR: "+ex.getMessage());
  }

  // Look for names of agencies or keywords in title
  String[] m1 = match(headline, "Odds");
  String[] m2 = match(headline, "Euro");
  String[] m3 = match(headline, "DDB");
  String[] m4 = match(headline, "BBDO");
  String[] m5 = match(headline, "Leo");
  String[] m6 = match(headline, "Mithun");
  String[] m7 = match(headline, "CP+B");
  String[] m8 = match(headline, "Chiat");
  String[] m9 = match(headline, "Grey");
  String[] m10 = match(headline, "Razorfish");
  String[] m11 = match(headline, "72andSunny");
  String[] m12 = match(headline, "Draft");
  String[] m13 = match(headline, "Digitas");
  String[] m14 = match(headline, "Ogilvy");
 String[] m15 = match(headline, "AKQA");

  // if agency name found, set to appropriate color
  if (m1 != null) {
    c = color(89, 133, 39);
  } 
  else {
    c = color(255, 60, 0);  //Set to standard orange if no matching agency in title
  }
  if (m2 != null) {
    c = color(0, 155, 135);
  } 
  if (m3 != null) {
    c = color(255, 255, 0);
  } 
  if (m4 != null) {
    c = color(255, 72, 0);
  } 
  if (m5 != null) {
    c = color(255, 255, 255);
  } 
  if (m6 != null) {
    c = color(255, 222, 0);
  } 
  if (m7 != null) {
    c = color(255, 66, 0);
  } 
  if (m8 != null) {
    c = color(255, 255, 0);
  }
  if (m9 != null) {
    c = color(105, 105, 105);
  }
  if (m10 != null) {
    c = color(230, 255, 0);
  }
  if (m11 != null) {
    c = color(255, 150, 0);
  }
  if (m12 != null) {
    c = color(255, 150, 0);
  }
  if (m13 != null) {
    c = color(255, 255, 255);
  } 
  if (m14 != null) {
    c = color(255, 0, 0);
  }
   if (m15 != null) {
    c = color(105, 105, 200);
  }  

  println(headline);
  println(cs);
  oldcs = cs;
}

//simple function for setting a delay. Not that important.
void myDelay(int ms) {
  int time = millis();
  while (millis ()-time < ms);
}

//Blink light when new article found. Not working yet.
void updateBlink() {
  for (int i = 0; i < 10; i++) { 
    c = color(255); 
    myDelay(500);
    c = color(0);
    myDelay(500);
  }
}


It's time to wire this bad boy up. It's pretty simple. Pin 11 is Red, Pin 10 is Green, Pin 9 is Blue. Check out the photos.
Make sure you're grounded and try not to set anything on fire.

Once your light is shining grab the Agency Spy lamp shade to cover the arduino and enjoy.

About Me:

I'm an interactive creative working in Chicago, with experience at shops such as Euro RSCG, Leo Burnett and Draft FCB. I have a passion for all things advertising and especially how it will be shaped by digital in the future. If you have a second feel free to take a look through the rest of my book.