Skip to content

Instantly share code, notes, and snippets.

@lgaetz
Last active December 7, 2021 21:18
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save lgaetz/8545099 to your computer and use it in GitHub Desktop.
Save lgaetz/8545099 to your computer and use it in GitHub Desktop.
Simple PHP script that checks the extension status at a remote PBX and updates a custom hint on the local pbx for proper BLF operation.
<?php
/**** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
* remotehintpoll.php
*
* Created by Lorne Gaetz lgaetz@sangoma.com
*
* Latest version: https://gist.github.com/lgaetz/8545099
*
* Licensed under GNU GPL version 2 or any later verison.
*
* Usage:
* This script is intended to be used on a local FreePBX system running version 2.9 or higher. When
* executed, the script polls a remote Asterisk server using remote Asterisk Manager Interface
* (AMI) credentials, checks the status of a specific extension number on the remote server, and
* then updates a local hint to the same value.
*
* Asterisk configuration:
* Define a dynamic hint on the local system of the same format as what is dialled to reach an
* extension on the remote system. If remote extensions are of the format 10XX and you use a dial
* prefix of 55 to dial remote extensions, the local dynamic hint is defined in extensions_custom.conf as:
*
* [from-internal-custom]
* exten => _5510XX,hint,Custom:Remote${EXTEN:2} // program BLF with e.g. 551001
*
* If you don't dial a prefix to reach the remote extensions from the local pbx, the hint looks like:
*
* [from-internal-custom]
* exten => _10XX,hint,Custom:Remote${EXTEN} // program BLF with e.g. 1001
*
* Version history:
* 2014-01-21 Initial commit for single extension
* 2017-06-22 Add support to poll a range of extensions and update a local dynamic hint
*
**** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****/
// set to true to echo debug
$debug=true;
// Set the local device prefix for the local hint, must match what is defined in extensions_custom.conf for the hint
// the $device_prefix will be used to prefix the remote extension number for the hint
$device_prefix = "Custom:Remote";
// Remote server host/IP, AMI credentials and
$remote_server = "hostname_placeholder";
$remote_name = "name";
$remote_secret = "password";
$remote_context = "from-internal";
// define range or remote extension numbers to poll, the fewer the better
// the range needs to match the dynamic hint noted above
$remote_extension_start='1000';
$remote_extension_end='1010';
// Connect to local machine with FreePBX bootstrap, requires FreePBX 2.9 or higher
if (!@include_once(getenv('FREEPBX_CONF') ? getenv('FREEPBX_CONF') : '/etc/freepbx.conf')) {
include_once('/etc/asterisk/freepbx.conf');
}
// connect to remote Asterisk machine using AMI credentials and get status of Extension 103
$remote = new AGI_AsteriskManager();
if ($remote->connect($remote_server, $remote_name, $remote_secret)) {
for ($remote_extension=$remote_extension_start; $remote_extension<=$remote_extension_end; $remote_extension++) {
$foo[$remote_extension] = $remote->ExtensionState($remote_extension, $remote_context);
}
$remote->disconnect();
}
else {
output("Can not connect to remote AGI");
}
// print_r($foo); //for debug
// Based on value of remote extension status, change local custom device state to match
// edit $device to reflect name of local custom device as defined in extensions_custom.conf
// in the [from-internal-custom] section add a line similar to:
// exten => 103,hint,Custom:Remote103
// Make sure that the number does not conflict with something else
if($astman->connected()) {
for ($remote_extension=$remote_extension_start; $remote_extension<=$remote_extension_end; $remote_extension++) {
switch ($foo[$remote_extension]['Status']) {
case -1:
output("$remote_extension Extension not found");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' UNKNOWN');
break;
case 0:
output("$remote_extension Idle");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' NOT_INUSE');
break;
case 1:
output("$remote_extension In Use");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' INUSE');
break;
case 2:
output("$remote_extension Busy");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' BUSY');
break;
case 4:
output("$remote_extension Unavailable");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' UNAVAILABLE');
break;
case 8:
output("$remote_extension Ringing");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' RINGING');
break;
case 9:
output("$remote_extension Ringing");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' RINGING');
break;
case 16:
output("$remote_extension On Hold");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' ONHOLD');
break;
default:
output("$remote_extension Extension not found");
$cmd = $astman->Command('devstate change '.$device_prefix.$remote_extension.' UNKNOWN');
}
}
} else {
output("Can not connect to local AGI");
}
function output($string){
global $debug;
if ($debug) {
echo $string."\n";
}
}
@lgaetz
Copy link
Author

lgaetz commented Oct 21, 2014

Future feature:
The $remote_extension variable should accept a comma separated list of remote extensions which would be exploded (and trimmed!) into an array. Then using for_each, $foo becomes an array of values of remote extensions' statuses.

@juesor
Copy link

juesor commented Aug 9, 2017

Have you thought of adding the ability for multiple ranges?

1100-1150

2100-2150

@Ferbla
Copy link

Ferbla commented Aug 9, 2017

@juesor
Copy link

juesor commented Aug 10, 2017

OMG Ferbla that is awesome. All i had to do was create a data.csv with two column's.

Layout was as follows.

1100,1120
1122
1124,1150
2100,2150

Now i am watching 1100-1150 omitting 1121 and 1123 and 2100-2150

Thanks @Ferbla for thinking of this setup.

@geforce28
Copy link

geforce28 commented Aug 16, 2017

I've 2 Asterisk 13 Servers, i want so sync with your script.

But if i run it there are many errors...:
PHP Warning: include_once(/etc/asterisk/freepbx.conf): failed to open stream: No such file or directory in /root/hintpoll/new/remotehintpoll.php on line 55 PHP Warning: include_once(): Failed opening '/etc/asterisk/freepbx.conf' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /root/hintpoll/new/remotehintpoll.php on line 55 PHP Fatal error: Class 'AGI_AsteriskManager' not found in /root/hintpoll/new/remotehintpoll.php on line 59

Can you help me ?

EDIT:
Okay, I've included the Class phpagi now.
Now my errors are:

PHP Warning: include_once(/etc/asterisk/freepbx.conf): failed to open stream: No such file or directory in /root/hintpoll/remotehintpoll.php on line 69 PHP Warning: include_once(): Failed opening '/etc/asterisk/freepbx.conf' for inclusion (include_path='.:/usr/share/php:/usr/share/pear') in /root/hintpoll/remotehintpoll.php on line 69 Wed, 16 Aug 2017 18:40:14 +0200 - Got event.. fullybooted Wed, 16 Aug 2017 18:40:14 +0200 - No event handler for event 'fullybooted' PHP Notice: Undefined variable: astman in /root/hintpoll/remotehintpoll.php on line 92 PHP Fatal error: Call to a member function connected() on null in /root/hintpoll/remotehintpoll.php on line 92

@juesor
Copy link

juesor commented Aug 23, 2017

Did you create the user manage the remote systems?

Settings > Asterisk Manager Settings.

Add manager and set permit to the IP of the other server on both sides.

Add that servers IP to the $remote_server
Add that manager to the $remote_name.
Add that managers password as $remote_secret

$remote_server = "hostname_placeholder";
$remote_name = "name";
$remote_secret = "password";

From there you need to create customer extensions context
vim /etc/asterisk/extensions_custom.conf and make sure all of your remote extensions are created and look like the following.

exten => _4000,hint,Custom:Remote${EXTEN}
exten => _4001,hint,Custom:Remote${EXTEN}
...
exten => _4009,hint,Custom:Remote${EXTEN}
exten => _4010,hint,Custom:Remote${EXTEN}

I also needed to toggle hints.

In FreePBX Web GUI Go to Settings > Advanced Settings

Dynamically Generate Hints
Toggle Yes/No and toggle it back. Apply in between.

Then all my phones now toggle ringing and talking. Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment