User Tools

Site Tools


processing:thermometer_example

This is an old revision of the document!


Thermometer example

The following examples will show you:

  • How to get data from the Internet.
  • How to scrape data.
  • How to draw fonts.
  • How to create a simple graphic meter.
  • How to invoke an action periodically.

You'll not find much description below. I may add some later, but my intent here is just to do a structured code dump.

The code here was written for Processing 1.5. It is currently undergoing revision to make it work in Processing 2.

Because applets have been removed in Processing 2 and because Processing.js doesn't allow downloading arbitrary files with its loadStrings implementation, linking to live examples that work in the browser from this page is not possible.

Getting files from the Internet

The built-in function loadStrings will load local files or URLs.

get_internet_page_simple.pde
/**
 * Gets a file from a URL and prints it out to the console.
 * 
 * Copyright (C) 2012 Mithat Konar
 */
 
final String THE_URL = "http://www.w3.org";
String[] lines;
 
void setup() {
  lines = loadStrings(THE_URL);
 
  if (lines != null)
  {
    println("there are " + lines.length + " lines");
    for (int i=0; i < lines.length; i++) {
      println(lines[i]);
    }
    println("There were " + lines.length + " lines.");
  }
  else
    println("Problem loading " + THE_URL);
}

This version adds exception handling and graphic feedback:

get_internet_page.pde
/**
 * Gets a file from a URL and prints it out to the console.
 * This version uses exceptions and adds graphic feedback.
 * 
 * Copyright (C) 2012 Mithat Konar
 */
 
// constants
final String THE_URL = "http://www.w3.org";
final int CANVAS_BORDER=10;
 
// global variables
String[] lines;
 
void setup() {
  size(160, 90);
  smooth();
  try {
    lines = loadStrings(THE_URL);
 
    for (int i=0; i < lines.length; i++) {
      println(lines[i]);
    }
    println("There were " + lines.length + " lines.");
 
    // Turn the canvas green to show that all went well.
    background(#00cc00);
  }
  catch (Exception e) {
    // In case there is an error, print out the error to the console and
    // turn the canvas red with a big 'X' in it.
    println("Problem loading " + THE_URL);
    println(e);
 
    // Turn the canvas red with a big 'X' in it to indicate error.
    background(#ff0000);
    strokeWeight(5);
    line(CANVAS_BORDER, CANVAS_BORDER, width-CANVAS_BORDER, height-CANVAS_BORDER);
    line(CANVAS_BORDER, height-CANVAS_BORDER, width-CANVAS_BORDER, CANVAS_BORDER);
  }
  println("Exiting app.");
}

Scraping XML for data

Grabbing selected data from an XML source is easy with the XML class. In this example, we load an RSS feed (which is XML) and parse it for some data.

get_xml_page.pde
/**
 * Gets data from Yahoo RSS weather feed, picks off some information,
 * and prints it to the console.
 * 
 * Copyright (C) 2012-2013 Mithat Konar
 */
 
// Constants:
// change the URL to get the desired location and units
// (see http://developer.yahoo.com/weather/).
final String URL = "http://weather.yahooapis.com/forecastrss?w=12781882&u=f";
 
// path in XML data to current conditions:
final String ELEMENT_CONDITION="channel/item/yweather:condition";
 
// attribute name in element above for current temperature:
final String ATTRIBUTE_CONDITION_TEMPERATURE = "temp";
 
// path in XML data to element that holds units of measurement:
final String ELEMENT_UNITS = "channel/yweather:units";
 
// attribute name in element above that holds units for temperature:
final String ATTRIBUTE_UNIT_TEMPERATURE = "temperature";
 
// misc.
final int CANVAS_BORDER=10;
 
// Functions:
void setup() {
  size(160, 90);
  smooth(); 
 
  try {
    XML weather = loadXML(URL);  // instantiate an XML object from URL.
    XML condition = weather.getChild(ELEMENT_CONDITION);  // pull current cond.
    XML units = weather.getChild(ELEMENT_UNITS);  // pull units data
 
    // Turn the canvas green to show that all went well.
    background(#00cc00);
 
    // "\u00b0" is the degree symbol
    println("The content:");
    println(condition.getInt(ATTRIBUTE_CONDITION_TEMPERATURE) + "\u00b0 "
            + units.getString(ATTRIBUTE_UNIT_TEMPERATURE));
    println("End content.");
  }
  catch (Exception e) {
    println("Problem loading " + URL);
    println(e);
 
    // Turn the canvas red with a big 'X' in it to indicate error.
    background(#ff0000);
    strokeWeight(5);
    line(CANVAS_BORDER, CANVAS_BORDER, width-CANVAS_BORDER, height-CANVAS_BORDER);
    line(CANVAS_BORDER, height-CANVAS_BORDER, width-CANVAS_BORDER, CANVAS_BORDER);
  }
 
  println("Exiting app.");
}

A digital thermometer

Fonts are graphics in Processing. To get the following to work, you'll need to create the *.vlw file using the Tools > Create Font… menu item.

thermometer_digital.pde
/*
 * Gets temperature data from Yahoo RSS feed and displays it numerically
 * on the canvas.
 * 
 * Copyright (C) 2012-2013 Mithat Konar
 */
 
// Constants:
// change the URL to get the desired location and units
// (see http://developer.yahoo.com/weather/).
final String URL = "http://weather.yahooapis.com/forecastrss?w=12781882&u=f";
 
// path in XML data to current conditions:
final String ELEMENT_CONDITION="channel/item/yweather:condition";
 
// attribute name in element above for current temperature:
final String ATTRIBUTE_CONDITION_TEMPERATURE = "temp";
 
// path in XML data to element that holds units of measurement:
final String ELEMENT_UNITS = "channel/yweather:units";
 
// attribute name in element above that holds units for temperature:
final String ATTRIBUTE_UNIT_TEMPERATURE = "temperature";
 
// misc.
final int CANVAS_BORDER=10;
 
// Functions:
void setup() {
  size(250, 140);
  smooth(); 
 
  try {
    XML weather = loadXML(URL);  // instantiate an XML object from URL
    XML condition = weather.getChild(ELEMENT_CONDITION);  // pull current cond.
    XML units = weather.getChild(ELEMENT_UNITS);  // pull units data
 
    background(#296783);
 
    PFont font;  // we'll use this to hold font data
    font = loadFont("Monospaced.bold-48.vlw"); 
    textFont(font, 48);
    textAlign(CENTER, CENTER);
    fill(#ffffff);
    text(condition.getInt(ATTRIBUTE_CONDITION_TEMPERATURE) + "\u00b0" + units.getString(ATTRIBUTE_UNIT_TEMPERATURE), width/2, height/2);
  }
  catch (Exception e) {
    println("Problem loading " + URL);
    println(e);
 
    // Turn the canvas red with a big 'X' in it to indicate error.
    background(#ff0000);
    strokeWeight(5);
    line(CANVAS_BORDER, CANVAS_BORDER, width-CANVAS_BORDER, height-CANVAS_BORDER);
    line(CANVAS_BORDER, height-CANVAS_BORDER, width-CANVAS_BORDER, CANVAS_BORDER);
  }
 
  println("Exiting app.");
}

Abstracting the drawing with a function:

thermometer_digital_func.pde
/**
 * Gets temperature data from Yahoo RSS feed and displays it numerically
 * on the canvas. This version uses a function to abstract the drawing.
 *
 * Copyright (C) 2012-2013 Mithat Konar
 */
 
// Constants:
// change the URL to get the desired location and units
// (see http://developer.yahoo.com/weather/).
final String URL = "http://weather.yahooapis.com/forecastrss?w=12781882&u=f";
 
// path in XML data to current conditions:
final String ELEMENT_CONDITION="channel/item/yweather:condition";
 
// attribute name in element above for current temperature:
final String ATTRIBUTE_CONDITION_TEMPERATURE = "temp";
 
// path in XML data to element that holds units of measurement:
final String ELEMENT_UNITS = "channel/yweather:units";
 
// attribute name in element above that holds units for temperature:
final String ATTRIBUTE_UNIT_TEMPERATURE = "temperature";
 
// misc.
final int CANVAS_BORDER=10;
 
// Functions:
void setup() {
  size(250, 140);
  smooth(); 
 
  try {
    XML weather = loadXML(URL);  // instantiate an XML object from URL
    XML condition = weather.getChild(ELEMENT_CONDITION);  // pull current cond.
    XML units = weather.getChild(ELEMENT_UNITS);  // pull units data
 
    background(#296783);
    drawDigitalTemp(condition.getInt(ATTRIBUTE_CONDITION_TEMPERATURE), 
        units.getString(ATTRIBUTE_UNIT_TEMPERATURE), width/2, height/2);
  }
  catch (Exception e) {
    println("Problem loading " + URL);
    println(e);
 
    // Turn the canvas red with a big 'X' in it to indicate error.
    background(#ff0000);
    strokeWeight(5);
    line(CANVAS_BORDER, CANVAS_BORDER, width-CANVAS_BORDER, height-CANVAS_BORDER);
    line(CANVAS_BORDER, height-CANVAS_BORDER, width-CANVAS_BORDER, CANVAS_BORDER);
  }
 
  println("Exiting app.");
}
 
/**
 * Render the temperature numerically at a given canvas location.
 */
void drawDigitalTemp(int temperature, String units, int x, int y)
{
  PFont font;
  font = loadFont("Monospaced.bold-48.vlw"); 
  textFont(font, 48);
  textAlign(CENTER, CENTER);
  fill(#ffffff);
  text(temperature + "\u00b0" + units, x, y);
}

Adding a graphic meter

Representing quantities graphically. Note also the use of Javadoc/Doxygen documentation comments for the functions.

thermometer_meter.pde
/**
 * Gets temperature data from Yahoo RSS feed and displays it in a meter
 * as well as numerically.
 *
 * Copyright (C) 2012-2013 Mithat Konar
 */
 
// Constants:
// change the URL to get the desired location and units
// (see http://developer.yahoo.com/weather/).
final String URL = "http://weather.yahooapis.com/forecastrss?w=12781882&u=f";
 
// path in XML data to current conditions:
final String ELEMENT_CONDITION="channel/item/yweather:condition";
 
// attribute name in element above for current temperature:
final String ATTRIBUTE_CONDITION_TEMPERATURE = "temp";
 
// path in XML data to element that holds units of measurement:
final String ELEMENT_UNITS = "channel/yweather:units";
 
// attribute name in element above that holds units for temperature:
final String ATTRIBUTE_UNIT_TEMPERATURE = "temperature";
 
// misc.
final int BORDER=10;
 
// Functions:
void setup() {
  size(200, 100);
  smooth(); 
 
  try {
    XML weather = loadXML(URL);  // instantiate an XML object from URL
    XML condition = weather.getChild(ELEMENT_CONDITION);  // pull current cond.
    XML units = weather.getChild(ELEMENT_UNITS);  // pull units data
 
    background(#296783);
    drawDigitalTemp(condition.getInt(ATTRIBUTE_CONDITION_TEMPERATURE),
        units.getString(ATTRIBUTE_UNIT_TEMPERATURE), width/2, height/2);
    drawMeter(70, -40, 120, 10, height-2*BORDER, width-10-BORDER, BORDER);
  }
  catch (Exception e) {
    println("Problem loading " + URL);
    println(e);
 
    // Turn the canvas red with a big 'X' in it to indicate error.
    background(#ff0000);
    strokeWeight(5);
    line(BORDER, BORDER, width-BORDER, height-BORDER);
    line(BORDER, height-BORDER, width-BORDER, BORDER);
  }
 
  println("Exiting app.");
}
 
/**
 * Render the temperature numerically at a given canvas location.
 *
 * @param temperature the temperature to be drawn (int)
 * @param units       the units of measure used for temperatre (String)
 * @param x           the horizontal location of the display (int)
 * @param y           the vertical location of the display (int)
 *
 * @return void
 */
void drawDigitalTemp(int temperature, String units, int x, int y)
{
  PFont font;
  font = loadFont("Monospaced.bold-48.vlw"); 
  textFont(font, 48);
  textAlign(CENTER, CENTER);
  fill(#ffffff);
  text(temperature + "\u00b0" + units, x, y);
}
 
/**
 * Render the temperature graphically.
 *
 * @param val      the value to be drawn (float)
 * @param minimum  val's value that corresponds to no deflection (float)
 * @param minimum  val's value that corresponds to maximum deflection (float)
 * @param w        the width of the meter (int)
 * @param h        the height of the meter (int)
 * @param x        the horizontal location of the meter (int)
 * @param y        the vertical location of the meter (int)
 *
 * @return void
 */
void drawMeter(float val, float minimum, float maximum, int w, int h, int x, int y)
{
  // calculate height of indicator in pixels
  float barHeight=map(val, minimum, maximum, 0, h);
  println("barHeight = " + barHeight);
  // draw the indicator
  strokeWeight(1);
  stroke(#ff0000);
  fill(#e00000);
  rect(x, y+(h-barHeight), w, barHeight);
  // draw the frame
  noFill();
  stroke(#1F4D62);
  rect(x, y, w, h);
}

Updating the data

Don't sleep. Poll instead.

thermometer_update.pde
/**
 * Gets temperature data from Yahoo RSS feed and displays it in a meter
 * as well as numerically; updates periodically.
 * 
 * Copyright (C) 2012 Mithat Konar
 */
 
// Change the following to get the desired location and scale.
// See http://developer.yahoo.com/weather/
final String URL = "http://weather.yahooapis.com/forecastrss?w=12781882&u=f";
 
// These should only need changing if Yahoo! changes the RSS feed structure.
final String CHILD_CONDITION="channel/item/yweather:condition";
final String ATTRIBUTE_CONDITION_TEMPERATURE = "temp";
final String CHILD_UNITS = "channel/yweather:units";
final String ATTRIBUTE_UNIT_TEMPERATURE = "temperature";
 
final int BORDER=10;
 
int oldMinute;
 
void setup() {
  size(200, 100);
  smooth(); 
  oldMinute = minute();
  background(#296783);
  updateTemp();
}
 
void draw() {
  // updateTemp every minute.
  int currentMinute = minute();
  if (oldMinute != currentMinute)
  {
    updateTemp();
    oldMinute = currentMinute;
  }
}
 
void updateTemp() {
  try {
    println("updateTemp() called at "+ hour()+":"+minute()+":"+second());
    background(#ffff00);
    XMLElement weather = new XMLElement(this, URL);
    XMLElement condition = weather.getChild(CHILD_CONDITION);
    XMLElement units = weather.getChild(CHILD_UNITS);
    background(#296783);
    drawDigitalTemp(condition.getInt(ATTRIBUTE_CONDITION_TEMPERATURE), 
        units.getString(ATTRIBUTE_UNIT_TEMPERATURE), width/2, height/2);
    drawMeter(70, -40, 120, 10, height-2*BORDER, width-10-BORDER, BORDER);
  }
  catch (Exception e) {
    println("Problem loading " + URL);
    println(e);
 
    // Turn the canvas red with a big 'X' in it to indicate error.
    background(#ff0000);
    strokeWeight(5);
    line(BORDER, BORDER, width-BORDER, height-BORDER);
    line(BORDER, height-BORDER, width-BORDER, BORDER);
  }
}
 
void drawDigitalTemp(int temperature, String units, int x, int y)
/*
 * Print the temperature and units to the canvas centered around (x,y).
 */
{
  PFont font;
  font = loadFont("Monospaced.bold-48.vlw"); 
  fill(#ffffff);
  textFont(font, 48);
  textAlign(CENTER, CENTER);
  text(temperature + "\u00b0" + units, x, y);
}
 
void drawMeter(float val, float minimum, float maximum, int w, int h, int x, int y)
/* 
 * Represent a value in a vertical meter. Parameters:
 *   val: the value to be represented
 *   minimum: val's value that corresponds to no deflection.
 *   minimum: val's value that corresponds to maximum deflection.
 *   w: the width of the meter
 *   h: the height of the meter
 *   x, y: the location of the meter
 */
{
  // calculate height of indicator in pixels
  float barHeight=map(val, minimum, maximum, 0, h);
 
  // draw the indicator
  strokeWeight(1);
  stroke(#ff0000);
  fill(#e00000);
  rect(x, y+(h-barHeight), w, barHeight);
 
  // draw the frame
  noFill();
  stroke(#1F4D62);
  rect(x, y, w, h);
}
processing/thermometer_example.1375581431.txt.gz · Last modified: 2013/08/04 01:57 (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki