Scripts designed for on access demand from an extension can be written to use the Asterisk Gateway Interface. They can be written in any supported scripting language.
Using the marvelous BBC Weather RSS Feed it is possible to generate an audible weather report available on the end of the phone.
This code is based on code taken from Asterisk: The Future of Telephony It has been modified to work (the original source would not work due to the lack of tcp wrappers for get_file_contents()). It has also been modified to work with the BBC News feed. This version requires lib_curl and a php with that included within.
/var/lib/asterisk/agi-bin/weather.agi
#!/usr/bin/php -q <?php #Location of Southampton's Weather feed $weatherURL="http://feeds.bbc.co.uk/weather/feeds/rss/obs/id/3471.xml"; #Where curl should output the feed to (alternative is it dumps it to STDOUT, which would screw with the AGI $feedRes = "/var/lib/asterisk/agi-bin/feed.xml"; # don't let this script run for more than 60 seconds set_time_limit(60); # turn off output buffering ob_implicit_flush(false); # turn off error reporting, as it will most likely interfere with # the AGI interface error_reporting(0); # create file handles if needed if (!defined('STDIN')) { define('STDIN', fopen('php://stdin', 'r')); } if (!defined('STDOUT')) { define('STDOUT', fopen('php://stdout', 'w')); } if (!defined('STDERR')) { define('STDERR', fopen('php://stderr', 'w')); } # retrieve all AGI variables from Asterisk - not nescessary in its current form, # however may want to add tommorows weather, or a 5 day forecast later while (!feof(STDIN)) { $temp = trim(fgets(STDIN,4096)); if (($temp == "") || ($temp == "\n")) { break; } $s = split(":",$temp); $name = str_replace("agi_","",$s[0]); $agi[$name] = trim($s[1]); } #retrieve the web page $ch = curl_init($weatherURL); $file = fopen($feedRes,'w'); curl_setopt($ch,CURLOPT_FILE,$file); $weatherPage = curl_exec($ch); curl_close($ch); fclose($file); $weatherPage = file_get_contents($feedRes); #grab temperature in Centigrade if (preg_match("/Temperature: ([\-]?[0-9]+)/i",$weatherPage,$matches)) { $currentTemp=$matches[1]; } #grab the wind direction if (preg_match("/Wind Direction: N,/i",$weatherPage)) { $currentWindDirection='northerly'; } elseif (preg_match("/Wind Direction: S,/i",$weatherPage)) { $currentWindDirection='southerly'; } elseif (preg_match("/Wind Direction: E,/i",$weatherPage)) { $currentWindDirection='easterly'; } elseif (preg_match("/Wind Direction: W,/i",$weatherPage)) { $currentWindDirection='westerly'; } elseif (preg_match("/Wind Direction: NW,/i",$weatherPage)) { $currentWindDirection='northwesterly'; } elseif (preg_match("/Wind Direction: NE,/i",$weatherPage)) { $currentWindDirection='northeasterly'; } elseif (preg_match("/Wind Direction: SW,/i",$weatherPage)) { $currentWindDirection='southwesterly'; } elseif (preg_match("/Wind Direction: SE,/i",$weatherPage)) { $currentWindDirection='southeasterly'; } #grab wind speed if (preg_match("/Wind Speed: ([0-9.]+) mph,/i",$weatherPage,$matches)) { $currentWindSpeed = $matches[1]; } # tell the caller the current conditions if ($currentTemp) { fwrite(STDOUT,"STREAM FILE temperature \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); fwrite(STDOUT,"SAY NUMBER $currentTemp \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); fwrite(STDOUT,"STREAM FILE centigrade \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); } if ($currentWindDirection && $currentWindSpeed) { fwrite(STDOUT,"STREAM FILE with \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); fwrite(STDOUT,"STREAM FILE $currentWindDirection \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); fwrite(STDOUT,"STREAM FILE winds \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); fwrite(STDOUT,"STREAM FILE at \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); fwrite(STDOUT,"SAY NUMBER $currentWindSpeed \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); fwrite(STDOUT,"STREAM FILE miles \"\"\n"); fflush(STDOUT); $result = trim(fgets(STDIN,4096)); checkresult($result); } function checkresult($res) { trim($res); if (preg_match('/^200/',$res)) { if (! preg_match('/result=(-?\d+)/',$res,$matches)) { fwrite(STDERR,"FAIL ($res)\n"); fflush(STDERR); return 0; } else { fwrite(STDERR,"PASS (".$matches[1].")\n"); fflush(STDERR); return $matches[1]; } } else { fwrite(STDERR,"FAIL (unexpected result '$res')\n"); fflush(STDERR); return -1; } } ?>
/etc/asterisk/extensions.conf
[internal] ... exten => 124,1,Answer() exten => 124,n,AGI(weather.agi) exten => 123,n,Hangup()
One proposed use of Asterisk would be to create a talking clock. This would be accurate to within 2s:
/var/lib/asterisk/agi-bin/time.agi
#!/usr/bin/php -q
#use php turning off html error codes
<?php
# don't let this script run for more than 60 seconds (its maximum runlength should be no more than 26s (depending on source wavs))
set_time_limit(60);
# turn off output buffering
ob_implicit_flush(false);
# turn off error reporting, as it will most likely interfere with
# the AGI interface
error_reporting(0);
# create file handles if needed
#Asterisk passes messages through on the STDIN channel, and the script should pass commands back on STDOUT
#And errors on STDERR
if (!defined('STDIN'))
{
define('STDIN', fopen('php://stdin', 'r'));
}
if (!defined('STDOUT'))
{
define('STDOUT', fopen('php://stdout', 'w'));
}
if (!defined('STDERR'))
{
define('STDERR', fopen('php://stderr', 'w'));
}
# retrieve all AGI variables from Asterisk
# not used in this script, but not unuseful
while (!feof(STDIN))
{
$temp = trim(fgets(STDIN,4096));
if (($temp == "") || ($temp == "\n"))
{
break;
}
$s = split(":",$temp);
$name = str_replace("agi_","",$s[0]);
$agi[$name] = trim($s[1]);
}
#get the date in a uniform format
$hour = date("H"); #hour in 12hr
$mins = date("i"); #minutes
$secs = date("s"); #seconds
#The original WAV files take 9s to completelly play from call start to end, including beeps.
#With announce every 15s, Call must commence at least 10s before beeps.
if($secs<4||$secs>=51) {
#taget is the number of seconds past the minute the beeps occur.
$target = 15;
#Delay brings the script right up to the end of the $secs%15 period. ie the beeps hit the quater minute.
if($secs<4)
$delay = $target-$secs-9;
else
$delay = 60-$secs+4-9;
} else if($secs<21&&$secs>=4) {
$target = 30;
$delay = $target-$secs-9;
} else if($secs<34&&$secs>=21) {
$target = 45;
$delay = $target-$secs-9;
} else if($secs<51&&$secs>=34) {
$target = 0;
$delay = 60-$secs-9;
#this is the following minute (16:59:60 == 17:00:00);
$mins=($mins+1)%60;
if($mins==0)
$hours=($hours+1)%24;
}
#return the stuff to Asterisk to output to the channel
fwrite(STDOUT,"STREAM FILE thirdbeep \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"SAY NUMBER $hour \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"SAY NUMBER $mins \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE and \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"SAY NUMBER $target \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE seconds \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
#wait until three beeps less than n*15s
sleep($delay);
fwrite(STDOUT,"STREAM FILE beep \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE beep \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
fwrite(STDOUT,"STREAM FILE beep \"\"\n");
fflush(STDOUT);
$result = trim(fgets(STDIN,4096));
checkresult($result);
#unnescessary Housekeeping.
unset($currentTemp);
unset($currentWindSpeed);
unset($delay);
unset($mins);
unset($hours);
unset($seconds);
unset($target);
#Check if the signal was sent correctly, output data to appropriate channel.
function checkresult($res)
{
trim($res);
if (preg_match('/^200/',$res))
{
if (! preg_match('/result=(-?\d+)/',$res,$matches))
{
fwrite(STDERR,"FAIL ($res)\n");
fflush(STDERR);
return 0;
}
else
{
fwrite(STDERR,"PASS (".$matches[1].")\n");
fflush(STDERR);
return $matches[1];
}
}
else
{
fwrite(STDERR,"FAIL (unexpected result '$res')\n");
fflush(STDERR);
return -1;
}
}
?>
/etc/asterisk/extensions.conf
[internal] ... exten => 123,1,Answer() exten => 123,2,AGI(time.agi) exten => 123,n,Goto(internal,123,2)