Here the AsteriskClient.php script (/var/www/vtigercrm/cron/modules/PBXManager/) that works with Asterisk 1.4 and vTiger 5.1.0.
This scripts fixe the problem of a phone logged-in into a queue -> vTiger could
not pop-up the caller information.
This will fix it.
Cheers
Daniel
#!/usr/bin/php
/*+**********************************************************************************
* The contents of this file are subject to the vtiger CRM Public License Version 1.0
* ("License"); You may not use this file except in compliance with the License
* The Original Code is: vtiger CRM Open Source
* The Initial Developer of the Original Code is vtiger.
* Portions created by vtiger are Copyright (C) vtiger.
* All Rights Reserved.
************************************************************************************/
/**
* this file will be run as a shell script (in linux) or a batch file (under windows).
* the purpose of the file is to create a master socket which will be connecting to the asterisk server
* and to keep it (the socket) alive all the time.
*/
ini_set("include_path", "../../../");
require_once('modules/PBXManager/utils/AsteriskClass.php');
require_once('config.php');
require_once('include/utils/utils.php');
require_once('include/language/en_us.lang.php');
require_once('modules/PBXManager/AsteriskUtils.php');
$calls = array();
asteriskClient();
/**
* this function defines the asterisk client
*/
function asteriskClient(){
global $app_strings, $current_user;
global $adb, $log;
$data = getAsteriskInfo($adb);
$server = $data['server'];
$port = $data['port'];
$username = $data['username'];
$password = $data['password'];
$version = $data['version'];
$errno = $errstr = NULL;
$sock = @fsockopen($server, $port, $errno, $errstr, 3);
if( $sock === false ) {
$errno = $errstr = NULL;
$sock = @fsockopen($server, $port, $errno, $errstr, 1);
}
stream_set_blocking($sock, false);
if( $sock === false ) {
echo "Socket cannot be created due to error: $errno: $errstr\n";
$log->debug("Socket cannot be created due to error: $errno: $errstr\n");
exit(0);
}else{
echo "Date: ".date("d-m-Y")."\n";
echo "Connecting to asterisk server.....\n";
$log->debug("Connecting to asterisk server.....\n");
}
echo "Connected successfully\n\n\n";
$asterisk = new Asterisk($sock, $server, $port);
authorizeUser($username, $password, $asterisk);
//keep looping continuosly to check if there are any calls
while (true) {
//check for incoming calls and insert in the database
// sleep(1);
$incoming = handleIncomingCalls($asterisk, $adb);
}
fclose($sock);
unset($sock);
}
/**
* this function checks if there are any incoming calls for the current user
* if any call is found, it just inserts the values into the vtiger_asteriskincomingcalls table
*
* @param $asterisk - the asterisk object
* @param $adb - the peardatabase type object
* @return incoming call information if successful
* false if unsuccessful
*/
function handleIncomingCalls($asterisk, $adb){
global $calls;
$response = $asterisk->getAsteriskResponse(false);
if(empty($response)) {
return false;
}
$tmp = array();
$tmp = explode(".", $response['Uniqueid']);
$unique_id = $tmp[0];
if(($response['Event'] == 'Newstate') && ($response['State'] == 'Ring')) {
if(!array_key_exists($unique_id, $calls)) {
$calls = array($unique_id => array('CallerID' => $response['CallerID'],
'CallerIDName' => $response['CallerIDName'],
'UniqueTime' => time()));
echo date("H:i:s") . ' - UniqueId: ' . $unique_id . ' ==> New Call' . "\n\r";
echo ' ' . ' - CallerId: ' . $calls[$unique_id]['CallerID'] . "\n\r";
echo ' ' . ' - CallerName: ' . $calls[$unique_id]['CallerIDName'] . "\n\r";
}
return true;
}
if($response['Event'] == 'Newcallerid') {
if(array_key_exists($unique_id, $calls)) {
$calls[$unique_id]['CallerID'] = $response['CallerID'];
$calls[$unique_id]['CallerIDName'] = $response['CallerIDName'];
echo date("H:i:s") . ' - UniqueId: ' . $unique_id . ' ==> CallerId Change' . "\n\r";
echo ' ' . ' - CallerId: ' . $calls[$unique_id]['CallerID'] . "\n\r";
echo ' ' . ' - CallerName: ' . $calls[$unique_id]['CallerIDName'] . "\n\r";
}
return true;
}
if(($response['Event'] == 'Newexten') && (strstr($response['AppData'],"EXTTOCALL"))){
if(array_key_exists($unique_id, $calls)) {
$temp = array();
$temp = explode("/",$response['Channel']);
$calls[$unique_id]['CallerType'] = $temp[0];
$temp = explode("=",$response['AppData']);
$calls[$unique_id]['Extension'] = $temp[1];
if(checkExtension($calls[$unique_id]['Extension'], $adb)){
$sql = "insert into vtiger_asteriskincomingcalls values (?,?,?,?,?,?)";
$flag= 0;
$timer = time();
$params = array($calls[$unique_id]['CallerID'],
$calls[$unique_id]['CallerIDName'],
$calls[$unique_id]['Extension'],
$calls[$unique_id]['CallerType'],
$flag, $timer);
$adb->pquery($sql, $params);
addToCallHistory($calls[$unique_id]['Extension'],
$calls[$unique_id]['CallerType'] . ":" . $calls[$unique_id]['CallerID'],
$calls[$unique_id]['Extension'],
"incoming", $adb);
echo date("H:i:s") . ' - UniqueId: ' . $unique_id . ' ==> Internal Call vTiger DB' . "\n\r";
echo ' ' . ' - CallerId: ' . $calls[$unique_id]['CallerID'] . "\n\r";
echo ' ' . ' - CallerName: ' . $calls[$unique_id]['CallerIDName'] . "\n\r";
echo ' ' . ' - Extension: ' . $calls[$unique_id]['Extension'] . "\n\r";
}
}
return true;
}
if($response['Event'] == 'Hangup'){
if(array_key_exists($unique_id, $calls)) {
unset($calls[$unique_id]);
echo date("H:i:s") . ' - HangUpId: ' . $unique_id . ' ==> Call End' . "\n\r";
}
return true;
}
if(($response['Event'] == 'Newchannel') && ($response['State'] == 'Ring')){
if(array_key_exists($unique_id, $calls)) {
$temp = array();
$temp = explode("/", $response['Channel']);
$temp1 = array();
$temp1 = explode("@", $temp[1]);
$calls[$unique_id]['CallerType'] = 'SIP';
$calls[$unique_id]['Extension'] = $temp1[0];
echo date("H:i:s") . ' - UniqueId: ' . $unique_id . ' ==> New Channel: ' . $calls[$unique_id]['Extension'] . "\n\r";
if(checkExtension($calls[$unique_id]['Extension'], $adb)){
$sql = "insert into vtiger_asteriskincomingcalls values (?,?,?,?,?,?)";
$flag= 0;
$timer = time();
$params = array($calls[$unique_id]['CallerID'],
$calls[$unique_id]['CallerIDName'],
$calls[$unique_id]['Extension'],
$calls[$unique_id]['CallerType'],
$flag, $timer);
$adb->pquery($sql, $params);
addToCallHistory($calls[$unique_id]['Extension'],
$calls[$unique_id]['CallerType'] . ":" . $calls[$unique_id]['CallerID'],
$calls[$unique_id]['Extension'],
"incoming", $adb);
echo date("H:i:s") . ' - UniqueId: ' . $unique_id . ' ==> External Call vTiger DB' . "\n\r";
echo ' ' . ' - CallerId: ' . $calls[$unique_id]['CallerID'] . "\n\r";
echo ' ' . ' - CallerName: ' . $calls[$unique_id]['CallerIDName'] . "\n\r";
echo ' ' . ' - Extension: ' . $calls[$unique_id]['Extension'] . "\n\r";
}
}
return true;
}
return true;
}
/**
* this function takes a XML response and converts it to an array format
* @param string $response - the xml response
* @return the xml formatted into an array
*/
function getArray($xml){
$lines = explode("\r\n", $xml);
$response = array();
foreach($lines as $line){
list($key, $value) = explode(":", $line);
$response[$key] = $value;
}
return $response;
}
/**
* this function checks if the given extension is a valid vtiger extension or not
* if yes it returns true
* if not it returns false
*
* @param string $ext - the extension to be checked
* @param object $adb - the peardatabase object
*/
function checkExtension($ext, $adb){
$sql = "select * from vtiger_asteriskextensions where asterisk_extension='$ext'";
$result = $adb->pquery($sql, array());
if($adb->num_rows($result)>0){
return true;
}else{
return false;
}
}
?>
Hi Asterisk Friends
The local telco here in Malasyia is sending the area code for local to local calls with the CID.
Sample:
If someone from Kuala Lumpur land line calls a other land line (connected to Asterisk) we receive a 10 digit number as CID like: 03 2288 4400 (where 03 is the area code). Unfortunately if we re-dial this number
the carrier will not accept 10 digits number, we can not use the area code to call someone in the same area..
So we need to do a couple of things on the incoming CID before we "ring" the phone and display the CID:
- detect if the call is a local call (area code equals "03")
- remove the area code if it's a local call
- add a 9 in front of the CID to allow us to re-dial the number and give us access to our outbound route
Here the simple context [from-pst-custom] inside extensions_custom.conf:
[from-pstn-custom]
exten => _X.,1,GotoIf($["${CALLERID(num):0:2}" = "03"]?2:3)
exten => _X.,2,Set(CALLERID(num)=${CALLERID(num):2:10})
exten => _X.,3,Set(CALLERID(num)=9${CALLERID(num)})
Hi Asterisk Friends
I have a client which runs a travel agency call center here in Malaysia on Asterisk 1.4.
We are using the GXP-2000 phone for all it's agents. The client requested a feature that the Agents can simply press the GXP-2000 programmable buttons to log-in / log out of queues (one button for log-in and log-out per queue). If the agent is not logged in he will see a "red" light on the phone. As soon he press the button, he will hear the message "Agent logged-in) as well the lamp change from "red" to "green".
Attention: The following will only work with FreePBX 2.5 installed.
As you know Asterik 1.4 is not "natively" supporting the DEVSTATE function from Asterisk 1.6.
As first step you need to use Russell's devstate backport for Asterisk 1.4. Please download
the function from here and copy it into your Asterisk funcs directory.
In my case "/usr/src/asterisk-1.4.21.1/funcs"
After that change into your asterisk source directory.
In my case: /usr/src/asterisk-1.4.21.1/
Run a: make clean
make all
make install
This will add the devstate funtion to your Asterisk 1.4
Attention: I did that a couple of times on my productive machines and never had any problems.
But no guarantee from my side.... smile!
Don't install the config-samples!!
Before we restart Asterisk we tell FreePBX to use the new DEVSTATE function.
Open /etc/amportal.conf and add the following line at the end of the file:
USEDEVSTATE=true
No restart Asterisk: amportal restart
To check if you have the new function available use following command in the Asterisk CLI:
Access CLI with: asterisk -rvvv
show function DEVSTATE
You should see the following output:
-= Info about function 'DEVSTATE' =-
[Syntax]
DEVSTATE(device)
[Synopsis]
Get or Set a device state
[Description]
The DEVSTATE function can be used to retrieve the device state from any
device state provider. For example:
NoOp(SIP/mypeer has state ${DEVSTATE(SIP/mypeer)})
NoOp(Conference number 1234 has state ${DEVSTATE(MeetMe:1234)})
The DEVSTATE function can also be used to set custom device state from
the dialplan. The "Custom:" prefix must be used. For example:
Set(DEVSTATE(Custom:lamp1)=BUSY)
Set(DEVSTATE(Custom:lamp2)=NOT_INUSE)
You can subscribe to the status of a custom device state using a hint in
the dialplan:
exten => 1234,hint,Custom:lamp1
The possible values for both uses of this function are:
UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING
RINGINUSE | ONHOLD
Know we need to add some dial-plan stuff into extensions_custom.conf:
[from-internal-custom]
include => hintsforqueue
include => macro-queuemgmt
[hintsforqueue]
exten => 40407000,hint,Custom:phone7000
exten => _4040XXXX,1,Macro(queuemgmt,4040)
[macro-queuemgmt]
exten => s,1,Macro(user-callerid,SKIPTTL)
exten = s,n,NoOp(Macro queuemgmt called for extension ${CALLERID(num)})
exten = s,n,NoCDR()
exten = s,n,Set(CID=${CALLERID(num)})
exten = s,n,Set(QUEUENAME=${ARG1})
#exten = s,n,Set(PEERCHANNELNAME=SIP/${CID})
exten = s,n,Set(PEERCHANNELNAME=Local/${CID}@from-internal/n)
exten = s,n,Set(QUEUEHINTNAME=qm-${QUEUENAME}-${CALLERID(num)})
exten = s,n,Set(QUEUEMEMBERS=${QUEUE_MEMBER_LIST(${QUEUENAME})})
exten = s,n,Set(MEMBERCOUNTER=1)
exten = s,n(begin),Set(CURRENTPEER=${CUT(QUEUEMEMBERS,\,,${MEMBERCOUNTER})})
exten = s,n,GotoIf($["${CURRENTPEER}"=""]?add)
exten = s,n,GotoIf($["${CURRENTPEER}"="${PEERCHANNELNAME}"]?remove)
exten = s,n,Set(MEMBERCOUNTER=${MATH(${MEMBERCOUNTER}+1)})
exten = s,n,Goto(begin)
exten = s,n(add),AddQueueMember(${QUEUENAME},${PEERCHANNELNAME})
exten = s,n,Set(DEVSTATE(Custom:phone${CALLERID(num)})=NOT_INUSE)
exten = s,n,Playback(agent-loginok)
exten = s,n,Goto(end)
exten = s,n(remove),RemoveQueueMember(${QUEUENAME},${PEERCHANNELNAME})
exten = s,n,Set(DEVSTATE(Custom:phone${CALLERID(num)})=INUSE)
exten = s,n,Playback(agent-loggedoff)
exten = s,n,Goto(end)
exten = s,n(end),Answer()
exten = s,n,Wait(1)
exten = s,n,Hangup()
I assume you know a little bit about dial plans, so i will not explain all the steps except the ones related to the new DEVSTATE function.
Here we go:
Firts we use a "normal" hint to "light-up" the lamp on the GXP phone.
exten => 40407000,hint,Custom:phone7000
Attention: You need to add 40407000 into your GXP BLF field.
For me that means 4040 is the queue i want to login and 7000 the device (i use device and
user)
We also use the new syntax Custom which we can refer to in the dial plan. I name it Custom:phone7000
(easier to identify).
Here we set the lamp status to green,for logged-in:
exten = s,n,Set(DEVSTATE(Custom:phone${CALLERID(num)})=NOT_INUSE)
and
exten = s,n,Set(DEVSTATE(Custom:phone${CALLERID(num)})=INUSE)
to the change the lamp to red.
You can dowmload the extensions_custom.conf from here.
Works like a charm for me. Let me know if you have any issues.
Cheers
Daniel
Good Morning
Last week i conducted a 5 day Asterisk bootcamp training and one of the students ask me why X-Lite (counterpath free softyphone) has problems with the video support via Asterisk. Until then i did not even think about to use video with Asterisk and X-Lite.. So we tried it out and had the problem that if you clicked on to the "Start Video" function in the X-Lite phone nothing happen. Meaning no video signal was sent or received.
After a while of adjusting sip_custmom.conf (We use FreePBX..) it worked like a charm.
Here a print screen of Marco and me (the one with the green wall in the his kitchen...) using X-Lite with video.

Here the sip_custom.conf:
videosupport=yes
allow=h263
allow=h263+
allow=h264
allow=h264+
Im not sure if its always a good thing to see my biz partners and staff on the phone..... ha ha
Cheers and have a great weekend!
Daniel
Here a short description on how you can dial into a low-cost PRI gateway. You can find many description on hos to use SIP/IAX2 gateways but not so many about how to trunk to a PRI gateway and wait for a dial tone before you actually send the number you like to reach.
To prefix (add a certain dial string in front of every call) we can use the “Dial-Rules” feature inside the specific Trunk settings. In our case we have only one trunk which is ZAP/g0, which is reachable via outbound route 9. That means when we press 9 and any number the call will be routed from Outbound-Route “0 9_outside” to Trunk ZAP/g0.
On the Trunk we add the following content to the dial-rules:
XXXXXXX
XXXXXXXX
1800877957ww+.
What happens is that we allow that 7 and 8 digit numbers are allowed to use this trunk. So if someone keys in a local number 7 or 8 digits the call will be passed through this trunk without any prefix. Because we don’t have low cost rate on local calls.
For any other number with more than 8 digits the system will add 1800877957ww+. in front of the dialed number. If you dial 90122680619 the system will cut the 9 of the number first (that happens in the outbound route) then pass the call to the Trunk/g0 which will apply the defined dial-rules and create the following dialing string 1800877957ww0122680619. The “ww” are wait statements. Each “w” adds 250 ms delay.
The system dials 1800877957 first, wait 500 ms to get a dial tone from P1, then dials the number you actually like to reach.

Cheers
Daniel