Perl Script to put Weather on your Polycom Microbrowser
Posted: January 5th, 2009 | Author: Fred | Filed under: VoIP, tech | Tags: asterisk, internet, Perl, telephone, VoIP | 6 Comments »
VoIP Geeks Rock
Note: This is one of VoIP Tech Chat’s more technical articles. If you’re not a techie (or a trekkie), you may want to skip this one. In fact, we’d love it if you instead read our What is a VoIP? article instead.
Here’s a quick little perl script to create a static html/xml file that can be displayed on your Polycom’s microbrowser. The script uses the Google weather API to check the weather based on a given zip code. The script, of course, is just an example and can be customized as needed.
For PHP coders, the same script can be modified to PHP and save yourself a step. For those of us that really like Perl, this script will create a static page. Using a cron job, you can easily make the page update every 10 minutes or so, and keep weather information current.
You can download the zipped file (weather.pl), or view the code and geeky discussion below…
First, let’s look at an example of the rendered code needed to display “nicely” on a Polycom’s microbrowser. The following would be appropriate for a larger screened phone, such as a SoundPoint IP 650:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head>Fort Lauderdale, FL</head> <body> It is 70 F (21 C), Clear. High 79, Low 63, Mostly Sunny. Humidity: 87%. Wind: E at 0 mph. Tomorrow: Mostly Sunny. </body> </html>
The above will display a bold title of “Fort Lauderdale, FL” and then start with the weather conditions on the following line. For those with a smaller screen (such as the 450) you might want to kill the title and some of the weather info — something like:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head></head> <body> It is 70 F (21 C), Clear. High 79, Low 63, Mostly Sunny. </body> </html>
Now, for the perl script. First, if you don’t have the XML::TreePP module, you’ll need to install it. Which is as easy as:
# perl -MCPAN -e shell cpan> install XML::TreePP
That’s it… the install should be pretty quick. Ok, next for the perl script (weather.pl):
#!/usr/bin/perl -w
use strict;
use XML::TreePP;
my $ZipCode = $ARGV[0];
if ($ZipCode =~ /^(\d{5})$/) {
$ZipCode = $1;
}
else {
print qq(ERROR: invalid zipcode format\n);
open (MYFILE, '>/var/www/html/polyweather.html');
print MYFILE qq(ERROR: invalid zipcode format\n);
close MYFILE;
exit(0);
}
my $url = "http://www.google.com/ig/api?weather=" . $ZipCode ;
my $tpp = XML::TreePP->new();
my $tree = $tpp->parsehttp( GET => $url );
my $city = $tree->{xml_api_reply}->{weather}->{forecast_information}->{city}->{"-data"};
if (length($city) < 1) {
print "Unable to get info -- most likely a bad zip code. \n";
open (MYFILE, '>/var/www/html/polyweather.html');
print MYFILE qq(Unable to get info -- most likely a bad zip code.\n);
close MYFILE;
exit(0);
}
my $currtempf = $tree->{xml_api_reply}->{weather}->{current_conditions}->{temp_f}->{"-data"};
my $currtempc = $tree->{xml_api_reply}->{weather}->{current_conditions}->{temp_c}->{"-data"};
my $currhumidity = $tree->{xml_api_reply}->{weather}->{current_conditions}->{humidity}->{"-data"};
my $currcondition = $tree->{xml_api_reply}->{weather}->{current_conditions}->{condition}->{"-data"};
my $currwind = $tree->{xml_api_reply}->{weather}->{current_conditions}->{wind_condition}->{"-data"};
my $todayhigh = $tree->{xml_api_reply}->{weather}->{forecast_conditions}->[0]->{high}->{"-data"};
my $todaylow = $tree->{xml_api_reply}->{weather}->{forecast_conditions}->[0]->{low}->{"-data"};
my $todaycond = $tree->{xml_api_reply}->{weather}->{forecast_conditions}->[0]->{condition}->{"-data"};
my $tomorrowcond = $tree->{xml_api_reply}->{weather}->{forecast_conditions}->[1]->{condition}->{"-data"};
my $polyhtml = qq(<?xml version="1.0" encoding="utf-8"?>\n);
$polyhtml = $polyhtml . qq(<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">\n);
$polyhtml = $polyhtml . qq(<html xmlns="http://www.w3.org/1999/xhtml">\n);
$polyhtml = $polyhtml . qq(<head>$city</head>\n);
$polyhtml = $polyhtml . qq(<body>\n);
$polyhtml = $polyhtml . qq-It is $currtempf F ($currtempc C), $currcondition. High $todayhigh, Low $todaylow, $todaycond. $currhumidity. $currwind. Tomorrow: $tomorrowcond. \n-;
$polyhtml = $polyhtml . qq(</body>\n);
$polyhtml = $polyhtml . qq(</html>\n);
open (MYFILE, '>/var/www/html/polyweather.html');
print MYFILE $polyhtml;
close MYFILE;
print $polyhtml;
How does it work?
Google has a nice little weather API which will provide a weather forecast for a given zip code via xml. A sample output looks like:
<?xml version="1.0"?> <xml_api_reply version="1"> <weather module_id="0" tab_id="0"> <forecast_information> <city data="Fort Lauderdale, FL"/> <postal_code data="33325"/> <latitude_e6 data=""/> <longitude_e6 data=""/> <forecast_date data="2009-01-05"/> <current_date_time data="2009-01-05 20:19:00 +0000"/> <unit_system data="US"/> </forecast_information> <current_conditions> <condition data="Clear"/> <temp_f data="77"/> <temp_c data="25"/> <humidity data="Humidity: 68%"/> <icon data="/images/weather/sunny.gif"/> <wind_condition data="Wind: E at 5 mph"/> </current_conditions> <forecast_conditions> <day_of_week data="Today"/> <low data="65"/> <high data="79"/> <icon data="/images/weather/mostly_sunny.gif"/> <condition data="Mostly Sunny"/> </forecast_conditions> <forecast_conditions> <day_of_week data="Tue"/> <low data="67"/> <high data="81"/> <icon data="/images/weather/mostly_sunny.gif"/> <condition data="Mostly Sunny"/> </forecast_conditions> <forecast_conditions> <day_of_week data="Wed"/> <low data="56"/> <high data="81"/> <icon data="/images/weather/chance_of_rain.gif"/> <condition data="Chance of Showers"/> </forecast_conditions><forecast_conditions> <day_of_week data="Thu"/> <low data="52"/> <high data="74"/> <icon data="/images/weather/sunny.gif"/> <condition data="Clear"/> </forecast_conditions> </weather> </xml_api_reply>
A sample output for a bad zip code looks like:
<?xml version="1.0"?> <xml_api_reply version="1"> <weather module_id="0" tab_id="0"> <problem_cause data=""/> </weather> </xml_api_reply>
The perl script scrolls through the xml, parsing for the requested data and making a little webpage. To call the script, you would run something such as:
perl weather.pl 90210
The above would create the web page giving the weather for Brenda, Dylan, and the rest of the Beverly Hills crowd.
Now, for those that love the Mason Perl website engine (like Fred), you can code this in one quick dynamic file, this one is called weatherbyzip.html and is optimized for a smaller screen:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<% $message %>
</body>
</html>
<%init>
use XML::TreePP;
my $message = "";
if ($ZipCode =~ /^(\d{5})$/) {
$ZipCode = $1;
my $url = "http://www.google.com/ig/api?weather=" . $ZipCode ;
my $tpp = XML::TreePP->new();
my $tree = $tpp->parsehttp( GET => $url );
my $city = $tree->{xml_api_reply}->{weather}->{forecast_information}->{city}->{"-data"};
if (length($city) > 0) {
my $currtempf = $tree->{xml_api_reply}->{weather}->{current_conditions}->{temp_f}->{"-data"};
my $currtempc = $tree->{xml_api_reply}->{weather}->{current_conditions}->{temp_c}->{"-data"};
my $currcondition = $tree->{xml_api_reply}->{weather}->{current_conditions}->{condition}->{"-data"};
my $todayhigh = $tree->{xml_api_reply}->{weather}->{forecast_conditions}->[0]->{high}->{"-data"};
my $todaylow = $tree->{xml_api_reply}->{weather}->{forecast_conditions}->[0]->{low}->{"-data"};
my $todaycond = $tree->{xml_api_reply}->{weather}->{forecast_conditions}->[0]->{condition}->{"-data"};
$message = "It is $currtempf F ($currtempc C), $currcondition. High $todayhigh, Low $todaylow, $todaycond.";
}
else {
$message = "Unable to get info -- most likely a bad zip code.";
}
}
else {
$message = "Invalid Zip Code." ;
}
</%init>
<%args>
$ZipCode => ''
</%args>
You would then call the page with weatherbyzip.html?ZipCode=90210
Ok… this was one of our more technical posts… we’ll be back to normal tomorrow. We promise.
Download the files:














This could easily be adapted to work with Aastra phone displays too.
Fred's Weather
[...] Tech Chat posted a nice little script for putting a quick, no frills weather report directly onto your Polycom [...]
[...] Cepstral. Since the parking spots wouldn’t change, maybe the weather would. So, using another script to check the weather, you can modify the results and create a sound file using Cepstral (and swift), such [...]
<?php
//god
//syn
//original idea: http://www.voiptechchat.com/voip/208/perl-script-to-put-weather-on-your-polycom-microbrowser/
//Requires PHP 5 or greater
//config:
$zip = 33325; //default zipcode
$showhead = 1; //show header
$urlzip = 1; //allow URL defined zipcode
$cache = 0; //cache
$cachepath = "/var/www/mysite.com/cache"; //cache path (not used if cache == 0);
//end config
//credit where credit is due (class only)
/*
* Grabs weather data from Google.com's weather API and return a nicely formatted array
* @author Ashwin Surajbali
* @package Redink Design
* @version 0.9.1
* @url http://www.redinkdesign.net/google_weather_api_class
*/
class googleWeather{
public $zip;
public $enable_cache = 0;
public $cache_path = '';
public $cache_time = 3600; // 1 hour
private $cache_file;
private $gweather_api_url = 'http://www.google.com/ig/api?weather=';
private $raw_data;
public function get_weather_data($zip = 0){
if ($zip == 0 || strlen($zip) zip = $zip;
}
if ($this->enable_cache && !empty($this->cache_path)){
$this->cache_file = $this->cache_path . '/' . $this->zip;
return $this->load_from_cache();
}
// build the url
$this->gweather_api_url = $this->gweather_api_url . $this->zip;
if ($this->make_request()){
$xml = new SimpleXMLElement($this->raw_data);
$return_array = array();
$return_array['forecast_info']['city'] = $xml->weather->forecast_information->city['data'];
$return_array['forecast_info']['zip'] = $xml->weather->forecast_information->postal_code['data'];
$return_array['forecast_info']['date'] = $xml->weather->forecast_information->forecast_date['data'];
$return_array['forecast_info']['date_time'] = $xml->weather->forecast_information->current_date_time['data'];
$return_array['current_conditions']['condition'] = $xml->weather->current_conditions->condition['data'];
$return_array['current_conditions']['temp_f'] = $xml->weather->current_conditions->temp_f['data'];
$return_array['current_conditions']['temp_c'] = $xml->weather->current_conditions->temp_c['data'];
$return_array['current_conditions']['humidity'] = $xml->weather->current_conditions->humidity['data'];
$return_array['current_conditions']['icon'] = 'http://www.google.com' . $xml->weather->current_conditions->icon['data'];
$return_array['current_conditions']['wind'] = $xml->weather->current_conditions->wind_condition['data'];
for ($i = 0; $i weather->forecast_conditions); $i++){
$data = $xml->weather->forecast_conditions[$i];
$return_array['forecast'][$i]['day_of_week'] = $data->day_of_week['data'];
$return_array['forecast'][$i]['low'] = $data->low['data'];
$return_array['forecast'][$i]['high'] = $data->high['data'];
$return_array['forecast'][$i]['icon'] = 'http://www.google.com' . $data->icon['data'];
$return_array['forecast'][$i]['condition'] = $data->condition['data'];
}
}
if ($this->enable_cache && !empty($this->cache_path)){
$this->write_to_cache();
}
return $return_array;
}
private function load_from_cache(){
if (file_exists($this->cache_file)){
$file_time = filectime($this->cache_file);
$now = time();
$diff = ($now-$file_time);
if ($diff cache_file));
}
}
}
private function write_to_cache(){
if (!file_exists($this->cache_path)){
// attempt to make the dir
mkdir($this->cache_path, 0777);
}
if (!file_put_contents($this->cache_file, serialize($return_array))){
echo "Could not save data to cache. Please make sure your cache directory exists and is writable.";
}
}
private function make_request(){
$ch = curl_init();
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_URL, $this->gweather_api_url);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt ($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$this->raw_data = curl_exec ($ch);
curl_close ($ch);
if (empty($this->raw_data)){
return false;
}else{
return true;
}
}
}
//end class
if (isset($_GET['z']) && $urlzip == 1){
$zip = preg_replace("[^0-9]", "", $_GET['z']);
}
$w = new googleWeather();
$w->enable_cache = 0;
if ($usecache == 1){
$w->enable_cache = 1;
$w->cache_path = $cachepath;
}
$ar_data = $w->get_weather_data($zip);
$currtempf = $ar_data['current_conditions']['temp_f'];
$currtempc = $ar_data['current_conditions']['temp_c'];
$currcondition = $ar_data['current_conditions']['condition'];
$todayhigh = $ar_data['forecast'][0]['high'];
$todaylow = $ar_data['forecast'][0]['low'];
$todaycond = $ar_data['forecast'][0]['condition'];
$currhumidity = $ar_data['current_conditions']['humidity'];
$currwind = $ar_data['current_conditions']['wind'];
$tomorrowcond = $ar_data['forecast'][1]['condition'];
if ($showhead == 1){
$city = "\n".$ar_data['forecast_info']['city']."\n\n";
} else {
$city = "\n\n\n";
}
echo "\n\n".$city."\n\n";
echo "It is ".$currtempf."°F (".$currtempc."°C), ".$currcondition.". High ".$todayhigh.", Low ".$todaylow.", ".$todaycond.". ".$currhumidity.". ".$currwind.". Tomorrow: ".$tomorrowcond.".";
echo "\n\n";
?>
Php5 version. Doesn’t require a cron entry.
please change
$urlzip = 1; //allow URL defined zipcode
to
$urlzip = 1; //allow URL defined zipcode (?z=zipcode)
and delete this comment.
Thank you very much for this great piece of code, but you failed to mention a small fact about the need to execute this perl script with su (sudo) privileges and have the html folder created under /var/www/ prior to running it for the first time if using apache2 web server, because that’s where the resulting polyweather.html file is to be created.
The only thing I haven’t figured out yet is how to get the weatherbyzip.html to work because all it shows on my web browser is the code that’s in it, nothing gets created worthy of looking at. Also, this php file isn’t working for me either even though I have the php5 installed (I’m using Ubuntu Intrepid).
Thanks in advance!