Glintech integrates Asterisk, Jabber for open source UC platform
A week or so ago, my boss came to me asking if I could write something on what’d I’d done internally with XMPP and Asterisk for someone he knew at Computerworld. I was only too happy to have someone listen to my ramblings, so I wrote up some replies to some of the questions his friend had asked.
Last night my boss sent me a link to the article. Unfortunately, the article makes it look like he was the one who replied to the questions instead of me, but it’s nice to get some of my work out there anyway.
Here’s the full article: Glintech integrates Asterisk, Jabber for open source UC platform.
For those who actually understand what the article is about, you’ll probably realise that what I did here wasn’t anything particularly difficult or out of the ordinary. But hopefully for those who don’t, it might open a few eyes to some of the things that can be done with open source software.
Asterisk Bootcamp
Just a quick post to mention that I’m heading to Melbourne next month for the Asterisk Bootcamp (care of work). Should be a good opportunity to learn a lot of info about Asterisk and VoIP in general.
SPA942 Personal Directory with LDAP
A while ago, I posted a blog about the SPA942 Personal Directory. Well I’ve built on it a bit now and managed to get it populated from the information taken out of our LDAP server (Microsoft Active Directory).
When we allocate a phone to someone, we fill in the ipphone field with their extension. We then also add two other ipphone entries, the first being the MAC address of the phone, the second being the phone’s IP.
I’m also managing calling groups (queues) in LDAP by creating security groups and using the Notes field to enter the information that I then use to build Asterisk’s queues.conf file (I might post more on that later if people are interested). An example of one of these entries for the groups is:
fullname = {groupname}
strategy = ringall
timeout = 15
wrapuptime = 0
autofill = yes
autopause = no
maxlen = 0
joinempty = yes
leavewhenempty = yes
reportholdtime = yes
musicclass = default
From this information in LDAP, I have a PHP script that is run as a cron job each night to update the phones with the new Personal Directory.
I’ll post the PHP as one big chunk, and explain it a bit further below.
set_time_limit(300);
//Include a list of all the extensions - this is page that lists the id's for the pdir. $extensions=array('25454','25390','25582', etc...
include('voip_ext.php');
//Doing LDAP connection stuff
$ldap_host = "ldapserver";
$base_dn = "DC=domain,DC=com";
$filter = "(|(ipphone=*)(info=[*))";
$ldap_user = "CN=Admin User,CN=Users,DC=domain,DC=com";
$ldap_pass = "fullysecretpassword";
$connect = ldap_connect($ldap_host,$ldap_port)
or exit(">>Could not connect to LDAP server<<");
ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);
$bind = ldap_bind($connect, $ldap_user, $ldap_pass)
or exit(">>Could not bind to $ldap_host<<");
$read = ldap_search($connect, $base_dn, $filter)
or exit(">>Unable to search ldap server<<");
$info = ldap_get_entries($connect, $read);
//start doing things
ldapPhoneIPs($info);
//close the ldap connection
ldap_close($connect);
//FUNCTIONS
function ldapPhoneIPs($info){
$pDir = ldapUsers($info);
for ($i=0; $i<$info["count"]; $i++) {
if ($info[$i]["otheripphone"][0] <> "") {
echo "<br />".$info[$i]["samaccountname"][0]."<br />";
$phoneIP = $info[$i]["otheripphone"][0];
$phoneMAC .= $info[$i]["otheripphone"][1];
$ringtone = getRingTone($phoneIP);
$pDir2 = str_replace("r%3D0",$ringtone,$pDir);
updatePhonePDir($phoneIP,$pDir2);
}
}
}
//This just makes sure we don't overwrite somone's customised ringtone
function getRingTone($phoneIP){
$xmlstr = file_get_contents("http://$phoneIP/admin/spacfg.xml");
if (strlen($xmlstr) < 1){
$ringtone = "0";
} else {
$xml = new SimpleXMLElement($xmlstr);
$ringtone = $xml->Default_Ring_1_;
if ($ringtone == "User 1") {
$ringtone = "11";
} elseif ($ringtone == "User 2") {
$ringtone = "12";
}
}
return "r%3D".$ringtone;
}
function updatePhonePDir($phoneIP,$pDir){
$command = "wget --post-data '".$pDir."' http://".$phoneIP."/pdir.spa";
runCommand($command); // or die("update to $phoneIP failed");
}
function ldapUsers($info){
//get the list of users
global $extensions;
$extID = 99;
for ($i=0; $i<$info["count"]; $i++) {
if ($info[$i]["ipphone"][0] <> "") {
//individual users
if ($info[$i]["otheripphone"][0] <> "") {
$extensionstring .= "$extensions[$extID]=n%3D".str_replace(" ","%20",$info[$i]["displayname"][0]).";";
$extensionstring .= "p%3D".$info[$i]["ipphone"][0].";r%3D0&";
$extID--;
}
} elseif (ereg("[[6][0-9]{3}]",substr($info[$i]["info"][0],0,6))){
//calling groups
echo substr($info[$i]["info"][0],0,6);
$extensionstring .= "$extensions[$extID]=n%3D".strtoupper(str_replace(" ","%20",$info[$i]["name"][0])).";";
$extensionstring .= "p%3D".substr($info[$i]["info"][0],1,4).";r%3D0&";
$extID--;
}
}
$extensionstring = substr($extensionstring,0,(strlen($extensionstring)-1));
return $extensionstring;
}
function runCommand($command){
system($command,$returned);
echo $command ."<br />";
return $returned;
}
?>
Ok, so firstly we include another file. There’s nothing flash about this file, in fact all it contains is a list of all the id’s in the Personal Directory page
Next it’s a matter of setting up the LDAP connection and filters. I’m filtering for either an entry in the ipphone field (for individual users) OR the notes(info) field (for the groups).
Then we get into actually doing things.
The first bit parses the info from LDAP and extracts the fields I care about. I’ve added in filtering for custom ringtones, so that if someone has set a custom ringtone for a particular entry, it doesn’t get overwritten.
From there, we go through and construct the wget strings (see my previous post for an explanation on this). It puts regular users in CamelCase and groups in UPPERCASE so that users can distinguish the difference.
Once all that is done, we run the wget command and push out the updates.
SPA942 Personal Directory
I’ve been setting up Asterisk at work recently, as our old PABX has reached it’s limits.
We picked up half a dozen SPA942′s for some initial testing.
I have to say that while the phones are nice as an end user, however some of the administration functions seem to come up a bit short.
One of the big issues for us was that the personal directory on the phones doesn’t actually have to option to be populated from Asterisk (or any other PBX other than SPA9000). I have to admit though, I’m not really one to accept that something can’t be done.
After trying a number of things, I upgraded to the latest firmware (5.1.5 at time of writing) and after some more stuffing around, I was finally able to get the following line to populate the Personal Directory:
A few things about the command.
Firstly, the command will enter in two contacts in the Directory. These will be under entry #5 (24686) and entry #2 (25390). A complete list of all the codes here can be seen in the source of the Personal Directory page in the phone’s web interface.
So taking the first of the two entries (24686), what we’re posting is:
n=Geoff; (we need to escape the ‘=’ signs so that wget will actually pass the info on correctly)
n is the Display Name that will appear in the Directory
p=6004;
p is the extension number (or phone number). My extension is 6004.
r=1
r is the ring to use. 0 is no sound, just flashing. Play around with the other numbers to find the ringtone you want to use.
To add more than one entry at a time, simply separate the strings with ‘&’.
From here I’m going to look into LDAP integration, so that I can autorun the command, pulling the users and extensions out of Active Directory.
GLiNTECH #19 in BRW Fast 100
Dave already blogged about this a while back, but I thought I’d post it as well.
The company I work for (GLiNTECH) recently made the BRW Fast 100 which is a list of Australia’s definitive fastest growing small and medium businesses. Not only did we make it in, we came in at #19. Yay!
Good to see Atlassian (the people behind Jira and Confluence) coming in at #10.
