Setting up a test call?

We’re trying to setup Zabbix to monitor whether or not Asterisk/FreePBX is up and running I’ve already got several tests going which report the number of registered SIP and IAX2 trunks, number of active calls, whether or not the service itself is running, and even a test call out to a google voice number to make sure that our outgoing phone calls are working. But I’ve also been asked to make sure that we can monitor whether or not we’re able to receive calls and make sure that the call quality is good enough to get proper DTMF tones.

I wrote/put together 2 bash and 2 AGI scripts that seem to do what I need them to do seperately, but now comes the tough part of making them work togeter.

The first bash and agi together place an outgoing call from our main line and press 9638.

TestCallInDialer.sh

#!/bin/bash
DATE=`date +%d%m%Y-%H%M`
FILENAME=Incoming-"$DATE".call
echo "Channel: Local/4567890123@from-internal" >> /tmp/$FILENAME
echo "Application: AGI" >> /tmp/$FILENAME
echo "Data: TestCallDialer.agi" >> /tmp/$FILENAME
echo "MaxRetries: 2" >> /tmp/$FILENAME
echo "RetryTime: 30" >> /tmp/$FILENAME
echo "Priority: 1" >> /tmp/$FILENAME
echo "Archive: Yes" >> /tmp/$FILENAME
chmod 777 /tmp/$FILENAME
mv /tmp/$FILENAME /var/spool/asterisk/outgoing/
# Uncomment these once Receiver is called from the dial plan to send the data to the zabbix server
#
# sleep 30
# Sends Digits
# DIGITS=`cat /tmp/agitests.log|awk '{print $1}'`
# echo $DIGITS
# /etc/zabbix/./zabbix_sender -z [zabbix server ip] -p 10051 -s [hostname] -k asterisk.testcallindigits -o $DIGITS
# sleep 0.1
# Sends whether the call was successful
# SUCCESS=`cat /var/spool/asterisk/outgoing_done/$FILENAME |grep Status:|awk '{print $2}'`
# echo $SUCCESS
# /etc/zabbix/./zabbix_sender -z [zabbix server ip] -p 10051 -s [hostname] -k asterisk.testcallinsuccess -o $SUCCESS
rm /var/spool/asterisk/outgoing_done/$FILENAME

TestCallDialer.agi

<?php
ini_set('display_errors', 1);
set_time_limit(30);
require('phpagi.php');
error_reporting(E_ALL);

  $agi = new AGI();
  $agi->answer();

  $agi->verbose("before dtmf",3);
  $agi->exec("sendDTMF","w9638");
  $agi->verbose("after dtmf",3);

  // $agi->hangup();
?>

The second bash script and agi receive dtmf tones and write them to /tmp/agitests.log

TestCallInReceiver.sh

#!/bin/bash
# Once TestCallInReceiver is added to the dialplan don't use this batch script except for testing.
DATE=`date +%d%m%Y-%H%M`
FILENAME=Incoming-"$DATE".call
echo "Channel: Local/4567890123@from-internal" >> /tmp/$FILENAME
echo "Application: AGI" >> /tmp/$FILENAME
echo "Data: TestCallReceiver.agi" >> /tmp/$FILENAME
echo "MaxRetries: 2" >> /tmp/$FILENAME
echo "RetryTime: 30" >> /tmp/$FILENAME
echo "Priority: 1" >> /tmp/$FILENAME
echo "Archive: Yes" >> /tmp/$FILENAME
chmod 777 /tmp/$FILENAME
mv /tmp/$FILENAME /var/spool/asterisk/outgoing/
sleep 30
# Sends Digits
DIGITS=`cat /tmp/agitests.log|awk '{print $1}'`
/etc/zabbix/./zabbix_sender -z [zabbix server ip] -p 10051 -s [hostname] -k asterisk.testcallindigits -o $DIGITS
# Sends whether the call was successful
SUCCESS=`cat /var/spool/asterisk/outgoing_done/$FILENAME |grep Status:|awk '{print $2}'`
/etc/zabbix/./zabbix_sender -z [zabbix server ip] -p 10051 -s [hostname] -k asterisk.testcallinsuccess -o $SUCCESS
rm /var/spool/asterisk/outgoing_done/$FILENAME

TestCallReceiver.agi

#!/usr/bin/php
<?php
/*
This script answers the call and prompts for an extension, waits 5 seconds for your input and hangs up.
*/
$debug_mode = false; //debug mode writes extra data to the log file below whenever an AGI command is executed
$log_file = '/tmp/agitest.log'; //log file to use in debug mode
$allowed_ext = array('1234', '0'); //who's allowed to access this script

//Get the AGI variables; I modified the script not to check caller ID of the tester and shouldn't be necessary, but I had problems when I removed it, so I'll leave it in.
$agivars = array();
while (!feof(STDIN)) {
        $agivar = trim(fgets(STDIN));
        if ($agivar === '') {
                break;
        }
        else {
                $agivar = explode(':', $agivar);
                $agivars[$agivar[0]] = trim($agivar[1]);
        }
}
foreach($agivars as $k=>$v) {
        log_agi("Got $k=$v");
}
extract($agivars);

//Prompt for 4 digits
$ext = '';
$result = execute_agi('STREAM FILE please-enter-the "0123456789"');
if ($result['result'] == 0) {
        $result = execute_agi('STREAM FILE users "0123456789"');
        if ($result['result'] == 0) {
                //they haven't entered anything yet
                $result = execute_agi("GET DATA extension 5000 4");
                if ($result['result'] > 0) {
                        $ext = $result['result'];
                }
        }
        else {
                $ext = chr($result['result']);
        }
}
else {
        $ext = chr($result['result']);
}

//we haven't got 4 digits yet
if (strlen($ext) < 4) {
        //still no input after GET DATA timeout
        if (empty($ext)) {
                execute_agi('STREAM FILE please-enter-the ""');
                execute_agi('STREAM FILE users ""');
                execute_agi('STREAM FILE extension ""');
        }
        //we got a single digit during playback of 'please enter the' or 'users'
        while (strlen($ext) < 4) {
                $result = execute_agi('WAIT FOR DIGIT -1');
                //look for digits only
                if ($result['result'] >= 48 && $result['result'] <= 57) {
                        $ext .= chr($result['result']);
                }
                //ignore * or # (or a, b, c, d)
                else {
                        continue;
                }
        }
}
//log_agi("Got extension $ext");

//Writing the digits to /tmp/agitests.log shouldn't be necessary.
$fp = fopen('/tmp/agitests.log', 'w');
fwrite($fp, $ext);
fclose($fp);

//Say back the extension; not neccesary for our testing, but might come in handy for troubleshooting..
//execute_agi('STREAM FILE you-entered ""');
//execute_agi("SAY DIGITS $ext \"\"");
//execute_agi('STREAM FILE goodbye ""');

//Hangs up the Calls
execute_agi('HANGUP');

exit;


//Executes the AGI Commands
function execute_agi($command) {
        global $debug_mode, $log_file;

        fwrite(STDOUT, "$command\n");
        fflush(STDOUT);
        $result = trim(fgets(STDIN));
        $ret = array('code'=> -1, 'result'=> -1, 'timeout'=> false, 'data'=> '');
        if (preg_match("/^([0-9]{1,3}) (.*)/", $result, $matches)) {
                $ret['code'] = $matches[1];
                $ret['result'] = 0;
                if (preg_match('/^result=([0-9a-zA-Z]*)\s?(?:\(?(.*?)\)?)?$/', $matches[2], $match))  {
                        $ret['result'] = $match[1];
                        $ret['timeout'] = ($match[2] === 'timeout') ? true : false;
                        $ret['data'] = $match[2];
                }
        }
        if ($debug_mode && !empty($logfile)) {
                $fh = fopen($logfile, 'a');                if ($fh !== false) {
                        $res = $ret['result'] . (empty($ret['data']) ? '' : " / $ret[data]");
                        fwrite($fh, "-------\n>> $command\n<< $result\n<<     parsed $res\n");
                        fclose($fh);
                }
        }
        return $ret;
}

//AGI Debugger
function log_agi($entry, $level = 1) {
        if (!is_numeric($level)) {
                $level = 1;
        }
        $result = execute_agi("VERBOSE \"$entry\" $level");
}
?>

From what I’ve been reading I believe that I should be able to just call the TestCallReceiver.agi from the dialplan and eliminate the batch script. Unfortunately I’m not very familiar with the dialplan and am a bit hesitant to touch it because this is a production server. Right now I haven’t tested to make sure that they’ll work together, but I’ve tested them with my cell phone and it appears that they both work. The dialer will call me and enter DTMF tones, the Receiver will call me, ask for DTMF tones, and record them to the log file which we will be monitoring with Zabbix. If anyone has some insight on how to make these scipts work together or an idea of where I should be looking I’d greatly appreciate it.

Can you please share your Zabbix Template? I just started on this a few hours ago but it would be helpful to not have to do the work someone else has done. I plan on packaging everything up in a template and releasing it to the Zabbix Community. I am at the first beginning of all of this though. Some things I have done which you may find interest too are monitoring asterisk (I am sure you have this already) and grabbing the FreePBX version from the database.

The freepbx version I just created an item called freepbx.version and then run this to add the settings into the Zabbix Agent Config

echo -e ‘UserParameter=freepbx.version,mysql -u root -e "use asterisk;SELECT value FROM admin WHERE variable = ‘’‘version’’’;" |grep . |grep -v value’ >> /etc/zabbix/zabbix_agentd.conf
and then obviously restarting the agent. This is working well for me. Anything you would be willing to share would be extremely appreciated.