Processing CDR from the PBX
From Pbxnsip Wiki
Purpose
Keeping CDR on the PBX primarily serves the purpose of reviewing the recent call history and use functions like redial and click to dial. A history of a few days on the PBX is usually long enough for most applications. However, for billing purposes you usually need longer contexts.
The PBX may post call data records (CDR) to an external application server. By running an external database, you may store a potentially large number of records without affecting the performance of the PBX.
Format
The data interchange is done by using the HTTP/SOAP protocol. The CDR is encoded in a XML format and looks like this. The real file will not have indentation; here it is only for illustration purposes.
POST /cdr.xml HTTP/1.1
Host: pbx.com
SOAPAction: CDR
Content-Type: text/xml
Content-Length: 123
<env:Envelope
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sns="http://www.pbxnsip.com/soap/pbx">
<env:Body>
<sns:CDR>
<From>Fred Feuerstein <sip:ff@test.com></From>
<To>Tom Test <sip:tt@test.com></To>
<Type>extcall</Type>
<TimeStart>464645649</TimeStart>
<TimeConnected>464645655</TimeConnected>
<TimeEnd>464645676</TimeEnd>
<CallID>8c72b11bcd4@192.168.2.44</CallID>
<Domain>test.com</Domain>
</sns:CDR>
</env:Body>
</env:Envelope>
The XML schema for the CDR is defined in cdr.xsd file
The format follows the SOAP specification. In the pbxnsip namespace, the record CDR indicates that a CDR shall be transmitted. The CDR may have the following attributes:
- CallID: The Call-ID for the call. This makes it easier to match the call (like a session-cookie).
- Type: The PBX reports the last type of the call. This way, it is for example possible to tell if the call went to the voicemail box.
- Domain: The domain in which the call was being run.
- Language: If a specific language was selected, this tag will indicate the language.
- From: The value of the From header as it appeared in the call.
- To: Similar to the From but for the To header.
- FromUser: If the call was coming from a known extension, the extension name is reported here.
- ToUser: If the call was going to a known extension, the extension name is reported here.
- FromUser: If the call was coming from a known trunk, the trunk name is reported here.
- ToUser: If the call was going to a known trunk, the trunk name is reported here.
- ChargeAccount and ChargeNumber: If the call was redirected to an external number, the charged account and the destination number are reported here.
- TimeStart: The time when the call started. All timestamps are in number of seconds since 1970 (UNIX timestamp).
- TimeConnected: If the call was connected, this stamp indicates the connection time.
- TimeEnd: The time when the call was disconnected or cancelled.
Example PHP File
This code example shows how to process the CDR on an Apache web server using the PHP extension. This example just extracts the data and writes it into a plain file.
<?php
$elem="";
$callid="";
$type="";
$domain="";
$language="";
$from="";
$to="";
$fromUser="";
$toUser="";
$chargeAccount="";
$chargeNumber="";
$timeStart="";
$timeConnected="";
$timeEnd="";
$duration="";
function start_element($parser, $name, $attrs)
{
global $elem;
$elem=$name;
}
function end_element($parser, $name)
{}
function xml_data($parser, $data)
{
global $elem,
$callid,
$type,
$domain,
$from,
$to,
$fromUser,
$toUser,
$chargeAccount,
$chargeNumber,
$timeStart,
$timeConnected,
$timeEnd;
if($elem=="CALLID") $callid .= $data;
else if($elem=="TYPE") $type .= $data;
else if($elem=="DOMAIN") $domain .= $data;
else if($elem=="LANGUAGE") $language .= $data;
else if($elem=="FROM") $from .= $data;
else if($elem=="TO") $to .= $data;
else if($elem=="FROMUSER") $fromUser .= $data;
else if($elem=="TOUSER") $toUser .= $data;
else if($elem=="CHARGEACCOUNT") $chargeAccount .= $data;
else if($elem=="CHARGENUMBER") $chargeNumber .= $data;
else if($elem=="TIMESTART") $timeStart .= $data;
else if($elem=="TIMECONNECTED") $timeConnected .= $data;
else if($elem=="TIMEEND") $timeEnd .= $data;
}
$content = $HTTP_RAW_POST_DATA;
$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "start_element", "end_element");
xml_set_character_data_handler($xml_parser, "xml_data");
if(!xml_parse($xml_parser, $content, true))
{
die(sprintf("Get XML error parsing %s: %s at line %d",
htmlspecialchars($content),
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
xml_parser_free($xml_parser);
$fd = fopen("C:/Temp/cdr.txt", "a");
if( $fd )
{
fwrite( $fd, "callid = $callid, \r\n
type = $type, \r\n
language = $language, \r\n
domain = $domain, \r\n
from = $from, \r\n
to = $to, \r\n
fromUser = $fromUser, \r\n
toUser = $toUser, \r\n
chargeAccount = $chargeAccount, \r\n
chargeNumber = $chargeNumber, \r\n
timeStart = $timeStart, \r\n
timeConnected = $timeConnected, \r\n
timeEnd = $timeEnd, \r\n ";
fclose( $fd );
echo "ok";
}
?>
Applicable Table names and Column names can be found in the section [applicaiton table names and column names]
