Filter API responses with Output Filters on your Arduino


Temboo can help you reduce the complexity of API responses with Output Filters.

Many APIs return complex JSON or XML data that can be difficult to parse, particularly on devices with limited memory like your Arduino board. But with Temboo, you can select which pieces of JSON or XML data you’d like to have returned. The key is specifying one or more Output Filters when you call a Choreo. We'll demonstrate this with the same Yahoo Weather Choreo used in our Arduino Getting Started tutorial.

Filtering API Responses

When you run the sketch from our getting started example, you see an XML response returned by Yahoo Weather printed to the Arduino serial monitor. Let's use Output Filters to extract just the date of the last weather report and the current temperature from this XML.

1Add the following lines of code to the Yahoo WeatherByAddress sketch, just before the call to the run() method:

// add an Output Filter to extract the current temperature
GetWeatherByAddressChoreo.addOutputFilter("temperature", "/rss/channel/item/yweather:condition/@temp", "Response");

// add an Output Filter to extract the date and time of the last report.
GetWeatherByAddressChoreo.addOutputFilter("date", "/rss/channel/item/yweather:condition/@date", "Response");

2Upload and run the sketch. Instead of seeing the XML returned by Yahoo Weather, you should now see individual values for "temperature" and "date" printed to the serial monitor in a format that can be easily read into individual variables for use in your sketch.

What Just Happened?

Output Filters provide a powerful mechanism for reducing the complexity of API responses. To understand how they work, we'll walk through the process of creating a new Output Filter from scratch.

As we saw above, each Output Filter is constructed with three parameters, in the format: Choreo.addOutputFilter(result_label, data_path, choreo_output).

Result label is how you’d like Temboo to label this piece of information when it’s returned to the Arduino. Labels can contain letters and numbers, and you can choose any label you’d like for an Output Filter.

Data path is used to identify the particular item within a JSON or XML-formatted API response that you’d like to have returned to the Arduino. The data path can either be an XPath statement, or a JSON path.

Choreo output is the name of the Choreo output that contains the JSON or XML data to be filtered.

Identifying the Data to Filter

To construct an Output Filter, you’ll need to create an XPath or JSON path statement that identifies the data within the API response you want returned.

For example, given the response XML:

<weather>
    <current>
        <temperature>68</temperature>
        <humidity>45</humidity>
    </current>
</weather>

To return only the value of the <temperature> element, your XPath statement would be:

/weather/current/temperature

If you’re not familiar with XPath, you can find a good general introduction here. There are also a number of useful online tools that can help with constructing XPath statements, like the this one.

The paths you use to specify JSON elements work much the same way (although they don’t support more advanced XPath features like attribute-value selectors). Given the JSON:

{
    “weather” : {
        “temperature”: “68”,
        “humidity”: “45”
    }
}

to retrieve the “temperature” value, you’d specify a data path of:

/weather/temperature

In cases where you need to get a JSON or XML element at a particular array index, you can use the square bracket syntax to specify which element in the array you want. Array indices start at 1 (rather than 0). So to retrieve the first element in the /weather/temperature array, you'd use:

/weather/temperature[1]

If you want to return all elements in a collection, you specify empty brackets, [], after the collection in question. So, to retrieve all elements in the /weather/temperature array, you'd use:

/weather/temperature[]

If you're targeting a collection that is at the top-level of the returned data, you can start your Output Filter specification with empty brackets e.g., /[]/var_name1/var_name2.

In this example, we'll define an additional Output Filter for the Yahoo Weather API to extract the forecast city from the response XML.

Assembling the Output Filter

When constructing an Output Filter, you’ll typically need to start with a sample of the JSON or XML returned by the Choreo. Running a Choreo from the Temboo Library is a convenient way to obtain this output.

To create the Output Filter, follow these steps:

1Run the Yahoo > Weather > WeatherByAddress Choreo using the Temboo Library website (using the same process explained in the first Getting Started tutorial). After the Choreo has run, you’ll see the XML returned in the Output section.

2Note the name of the Choreo output for which the XML data was returned. Some Choreos have more than one named output. In most cases, for Library Choreos, the relevant Choreo output name will be Response, like in the screenshot below.

Yahoo! Weather Response Output

A Choreo output named Response

3Identify the XPath or JSON path for the filtered information you want returned by Temboo.

The XML returned by the Yahoo > Weather > GetWeatherByAddress looks like:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rss xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0">
<channel>
    <title>Yahoo! Weather - Portland, OR</title>
    <link>http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/USWA0468_f.html</link>
    <description>Yahoo! Weather for Portland, OR</description>
    <language>en-us</language>
    <lastBuildDate>Mon, 24 Jun 2013 11:53 am PDT</lastBuildDate>
    <ttl>60</ttl>
    <yweather:location city="Portland" region="OR" country="United States"/>
    <yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
    <yweather:wind chill="60" direction="170" speed="5"/>
    <yweather:atmosphere humidity="80" visibility="10" pressure="29.72" rising="0"/>
    <yweather:astronomy sunrise="5:21 am" sunset="9:01 pm"/>
    <image>
        <title>Yahoo! Weather</title>
        <width>142</width>
        <height>18</height>
        <link>http://weather.yahoo.com</link>
        <url>http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif</url>
    </image>
    <item>
        <title>Conditions for Portland, OR at 11:53 am PDT</title>
        <geo:lat>45.58</geo:lat>
        <geo:long>-122.69</geo:long>
        <link>http://us.rd.yahoo.com/dailynews/rss/weather/Portland__OR/*http://weather.yahoo.com/forecast/USWA0468_f.html</link>
        <pubDate>Mon, 24 Jun 2013 11:53 am PDT</pubDate>
        <yweather:condition text="Light Rain" code="11" temp="60" date="Mon, 24 Jun 2013 11:53 am PDT"/>

(The full XML response has been shortened here for clarity)

We’ll want to retrieve the value of the city attribute within the <yweather:location> element. The XPath statement for this value will be:

/rss/channel/yweather:location/@city

That is, the city attribute (specified by the "@" symbol) within the XML element located at /rss/channel/yweather:location. Note that you could also specify this element using:

//yweather:location/@city

(The // means "regardless of the parent XML element’s location.")

4Finally, decide how Temboo will label the filtered data when it’s returned to the Arduino. In this case, we’ll use city as the label.

We now have all the pieces to assemble the Output Filter:

Using Output Filters

After defining the components of your Output Filter, you can specify it as a parameter argument in your Arduino sketch using the addOutputFilter(label, path, output) method. For this Output Filter, the code will look like:

GetWeatherByAddressChoreo.addOutputFilter("city", "/rss/channel/yweather:location/@city", "Response");

The complete loop() method for your sketch should now look like:


/**
* Imports and setup code go here. 
* This code will vary depending on which internet shield you're using
*/

void loop()
{
  // while we haven't reached the max number of runs...
  if (numRuns <= maxRuns) {
      
    // print status
    Serial.println("Running GetWeatherByAddress - Run #" + String(numRuns++) + "...");

    // create a TembooChoreo object to send a Choreo request to Temboo
    TembooChoreo GetWeatherByAddressChoreo(client);
    
    // invoke the Temboo client
    GetWeatherByAddressChoreo.begin();

    // add your temboo account info
    GetWeatherByAddressChoreo.setAccountName(TEMBOO_ACCOUNT);
    GetWeatherByAddressChoreo.setAppKeyName(TEMBOO_APP_KEY_NAME);
    GetWeatherByAddressChoreo.setAppKey(TEMBOO_APP_KEY);
    
    // set the name of the choreo we want to run
    GetWeatherByAddressChoreo.setChoreo("/Library/Yahoo/Weather/GetWeatherByAddress");
    
    // set choreo inputs; in this case, the address for which to retrieve weather data
    // the Temboo client provides standardized calls to 100+ cloud APIs
    GetWeatherByAddressChoreo.addInput("Address", ADDRESS_FOR_FORECAST);

    // add an Output Filter to extract the name of the city.
    GetWeatherByAddressChoreo.addOutputFilter("city", "/rss/channel/yweather:location/@city", "Response");
    
    // add an Output Filter to extract the current temperature
    GetWeatherByAddressChoreo.addOutputFilter("temperature", "/rss/channel/item/yweather:condition/@temp", "Response");

    // add an Output Filter to extract the date and time of the last report.
    GetWeatherByAddressChoreo.addOutputFilter("date", "/rss/channel/item/yweather:condition/@date", "Response");

    // run the choreo 
    GetWeatherByAddressChoreo.run();
        
    // when the choreo results are available, print them to the serial monitor
    while(GetWeatherByAddressChoreo.available()) {
      char c = GetWeatherByAddressChoreo.read();    
      Serial.print(c);
    }
    GetWeatherByAddressChoreo.close();
  }

  Serial.println("Waiting...");
  Serial.println("");
  delay(30000); // wait 30 seconds between GetWeatherByAddress calls
}

You can specify as many Output Filters as you need for each Choreo, although each filter must have a unique label.

Save and upload your sketch. You should now see individual outputs for "city," "temperature," and "date" printed to the serial monitor.

Need Help?

We're always happy to help. Just email us at support@temboo.com, and we'll answer your questions.


Back