Knowledge Base

Setting Up your UCP

The UCP or user control panel is an integral part of freePBX, It lets users have control over their telephone experience.

Below is a short video for setting up the key components of the UCP including voicemail and the WebRTC softphone.

The UCP Phone or WebRTC Phone is an in-browser phone. The Administrator can enable the “WebRTC phone” and that is “attached” to a user’s extension, this phone will then receive phone calls at the same time as the users extension .

The UCP allows users to add multiple dashboards and resizable widgets, This functionality allows users to completely customize the look and feel of their User Control Panel.

The Voicemail widget allows you to view, listen and manage your voicemail settings. The voicemail widget also allows you to monitor and listen to other peoples mailboxes, This feature is invaluable for receptionists and PA’s as it allows them to monitor their Managers or teh main company mailbox. To monitor additional mailboxes contact your system administrator.

 The FreePBX User Management Module controls which mailboxes a user will be able to add as a widget in UCP as it is not just limited to the extensions own mailbox, This is useful for department managers or Receptionists.

The UCP also has a chat function built-in that allows remote users to chat between each other similar to any other webchat but with the added security of it being ‘siloed’ in your company.

For full details and instructions of all options please see the WIKI at

Asterisk Support FreePBX Knowledge Base Support Technical

Backing up files in FreePBX 15

The first time you come to restore your FREEpbx 15 system you may find that not everything that you expected is there !

The new backup module backs up on a module by module base and not like before where is was DBs and Files.

Linked here is a repository that has the files to create a module that can be edited to backup directories.

The file you need to edit is Backup.php


namespace FreePBX\modules\Filebackup;
use FreePBX\modules\Backup as Base;

class Backup extends Base\BackupBase
    public function runBackup($id, $transaction)
        $files = glob("/etc/asterisk/*conf");
        foreach ($files as $file) {
            $path = pathinfo($file, PATHINFO_DIRNAME);
            $this->addFile(basename($file), $path, '', "conf");
    $files = glob("/tftpboot/*xml");
        foreach ($files as $file) {
            $path = pathinfo($file, PATHINFO_DIRNAME);
            $this->addFile(basename($file), $path, '', "conf");
        return $this;

As you see we are backing up /etc/asterisk and /tftpboot , But only *.conf files in /etc/asterisk and only *.xml files in /tftpboot

Details on the new backup system are here

Thanks to James Finstrom for the original version of this, This version is not to replace his work but only to give an example of working with Multiple directories

The downloaded zip file needs to be added as a Local module via Module Admin and enabled, It will obviously give a signing error but this can be disabled in Advanced settings or ignored ;-)

Enjoy but don’t blame me if it doesn’t work. Ive tested it on my systems and all seems good by your experience may be different

Blog Knowledge Base

SSL, FOP2 and All that..

There are a few common questions and gotchas when using fop2 on a FreePBX server using ssl.

The symptom is simple you cant connect and at the bottom left if tels you that it cant connect over websockets to port 4445 and will finally time out saying Flash is required.. None of this is awfully helpful to be honest.

But the fix is simple and its a shame by default its not this .

In your fop2.cfg file local the lines below and edit them so they match .

It maybe that your certificate names aren’t as below, In that case substitute webserver.XXX with the correct file names.

; If you access fop2 via https, browsers will try to use wss (Secure 
; web sockets) and for that it requires a certificate file and key file,
; the same ones you have in your web server configuration. Be sure to
; specify the correct certificates, the defaults are the ones for a 
; regular Centos installation:


Thats its. Fop2 will now work over HTTPS

Blog Knowledge Base

Recording Announcements in FreePBX 13 and later

This was recorded a while ago as an aid to a customer, Its a short video on recording prompts and then adding them to an announcment so they can be used in call flow.

FreePBX Knowledge Base

FreePBX EPM Whoopsing

We have seen on some installations of FreePBX with EPM that when you upload a photo it Whoops when trying to rebulid the config.

The clue to whats happening is that it cant call function imagecreatefromjpeg or imagecreatefrompng depending on your file format

The most common cause of this is php-gd isnt installed. To Check this is simple, create a simple PHP file in the web root called phpcheck.php add the following to it:


if (extension_loaded('gd') && function_exists('gd_info')) {
    echo "PHP GD library is installed on your web server";
else {
    echo "PHP GD library is NOT installed on your web server";
<?php phpinfo(); ?>

Now browse in your favourite browser to this and it will show at the top if gd is installed or not.

If its not and php was installed via yum then :

yum search php-gd
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
 * base:
 * extras:
 * updates:
=============================================================== N/S Matched: php-gd ================================================================
php-gd.x86_64 : A module for PHP applications for using the gd graphics library

Will show if its avalible. (your version of PHP may mean this is different for you) then to install yum install php-gd and restart the httpd service

You should now be able to go to phpcheck.php again and it should show as installed. if it does you are good to go installing screen images for phones

Asterisk Support FreePBX Knowledge Base Support Technical

Resetting root password on FreePBX 14 and other Centos 7 servers

Boot your system and wait until the GRUB menu appears. On some systems you may need to press the “Escape” key to access the GRUB menu. FreePBX should show this for a few seconds on Boot

Highlight your Operating System and then press “e” to edit. You have to be quick here simpler to just press e when the menu appears and you will see similar to below.

Find the line beginning with linux. In this example the line begins linux16.

Manually delete the entries quiet and rhgb from the line. then append the following statement to the end of the line init=/bin/sh Don’t worry if your command is spread across more than one line. A continuation character “\ will be inserted automatically.

Now reboot your system now using the options specified by pressing the keys Ctrl +X

Once the system has re-booted, you will be presented with a shell prompt without having to enter any user name or password.

At this command prompt you will need to enter the following commands:

Remount the “/” root filesystem in Read/Write mode: mount -o remount,rw /

Issue the passwd command to reset the root account password: passwd

Then enter the new password as prompted twice

Then remount the “/” root filesystem in Read Only mode: mount -o remount,ro /

You can now restart the system and login with your new password.

FIrmware releases Knowledge Base

Sangoma Phone Firmware

This firmware version fixes a problem with the S400 and low audio level when making calls.

Blog Knowledge Base

Transcribing Voicemail with Google Speech api

This is part 2 and rather long awaited description of how to transcribe voicemails to email and deliver them with text and an attached MP3

You will need to install the files from here and also have a Google Developers account.

Also create a directory:-


Lets begin.

  • Script to create the mp3 and the file for transcription
FILENUM=$(/bin/ls ${PATH}${origmailbox}/INBOX |/bin/grep txt | /usr/bin/wc -l)

##Added to allow 999 messages
if  (( $FILENUM <= 9 ));
elif (( $FILENUM <= 99 ));

IN=$(/bin/grep "${origmailbox} =>" /etc/asterisk/voicemail.conf)
set -- "$IN"
IFS=","; declare -a Array=($*)

/bin/echo "[message]" >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo origmailbox=${origmailbox} >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "context=demo" >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "macrocontext=" >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "exten=s" >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "priority=11" >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo callerchan=${callerchan} >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo callerid=${callerid} >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo origdate=${origdate} >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo origtime=${origtime} >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "category=" >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "duration=${duration}" >> ${PATH}${origmailbox}/INBOX/${FILENAME}.txt

/bin/nice /usr/bin/sox /var/lib/asterisk/sounds/catline/${origdir}.wav ${PATH}${origmailbox}/INBOX/${FILENAME}.flac   silence -l 1 0.1 1% -1 0.3 1% 

/bin/nice /usr/bin/lame -b 16 -m m -q 9-resample /var/lib/asterisk/sounds/catline/${origdir}.wav  ${PATH}${origmailbox}/INBOX/${FILENAME}.mp3

voicemailbody=$(/usr/bin/perl -w /usr/src/asterisk-speech-recog-cloud_api/cli/ -k $apikey -o detailed -r 8000 -n 1  /var/spool/asterisk/voicemail/default/${origmailbox}/INBOX/${FILENAME}.flac)

/bin/cp /var/lib/asterisk/sounds/catline/${origdir}.wav ${PATH}${origmailbox}/INBOX/${FILENAME}.wav

echo "You have a new voicemail from ${callerid} it was left on ${origdate} and is ${duration} seconds long ${voicemailbody}" | /bin/mail -s "A new voicemail has arrived from ${callerid}" -a "${PATH}${origmailbox}/INBOX/${FILENAME}.mp3" "$email"

/bin/rm -f ${PATH}${origmailbox}/INBOX/${FILENAME}.flac
/bin/rm -f ${PATH}${origmailbox}/INBOX/${FILENAME}.mp3
  • Asterisk Dialplan to pass the call to the above script
exten => _XXXX,1,Set(__EXTTOCALL=${EXTEN})
exten => _XXXX,n,Noop(${EXTTOCALL})
exten => _XXXX,n,Goto(s,1)

exten => s,1,Answer()  ; Listen to ringing for 1 seconds
exten => s,n,Noop(${EXTTOCALL} , ${DIALSTATUS} , ${SV_DIALSTATUS})
exten => s,n,GotoIf($["${DIALSTATUS}"="BUSY"]?busy:bnext)
exten => s,n(busy),Set(greeting=busy)
exten => s,n,Goto(carryon)
exten => s,n(bnext),GotoIf($["${DIALSTATUS}"="NOANSWER"]?unavail:unext)
exten => s,n(unavail),Set(greeting=unavail)
exten => s,n,Goto(carryon)
exten => s,n(unext),Set(greeting=unavail)
exten => s,n,Goto(carryon)
exten => s,n(carryon),Set(origmailbox=${EXTTOCALL})
exten => s,n,Set(msg=${STAT(e,${ASTSPOOLDIR}/voicemail/default/${origmailbox}/${greeting}.wav)})
exten => s,n,Set(__start=0)
exten => s,n,Set(__end=0)
exten => s,n,NoOp(${UNIQUEID})
exten => s,n,Set(origdate=${STRFTIME(${EPOCH},,%a %b %d %r %Z %G)})
exten => s,n,Set(origtime=${EPOCH})
exten => s,n,Set(callerchan=${CHANNEL})
exten => s,n,Set(callerid=${CALLERID(num)})
exten => s,n,Set(origmailbox=${origmailbox})
exten => s,n,Answer()
exten => s,n,GotoIf($["${msg}"="1"]?msgy:msgn)
exten => s,n(msgy),Playback(${ASTSPOOLDIR}/voicemail/default/${origmailbox}/${greeting});(local/catreq/how_did)
exten => s,n,Goto(beep)
exten => s,n(msgn),Playback(vm-intro)
exten => s,n(beep),System(/bin/touch /var/lib/asterisk/sounds/catline/${UNIQUEID}.wav)
exten => s,n,Playback(beep)
exten => s,n,Set(__start=${EPOCH})
exten => s,n,Record(catline/${UNIQUEID}.wav,3,60,kaq)
exten => s,n,Playback(beep)
exten => s,n,Hangup()
exten => h,1,Noop(${start} ${end})
exten => h,n,GotoIf($["${start}"!="0"]?ok:end)
exten => h,n(ok),Set(end=${EPOCH})
exten => h,n,Set(duration=${MATH(${end}-${start},int)})
exten => h,n,System(/usr/local/sbin/ "${callerchan}" ${callerid} "${origdate}" ${origtime} ${origmailbox} ${UNIQUEID} ${duration})
exten => h,n(end),Noop(finished)
  • Modified api script, Note the language and enhanced mode setting
    • For these to work you need “datalogging ” enabled in the dialogflow api settings
#!/usr/bin/env perl

# Render speech to text using Google's Cloud Speech API.
# Copyright (C) 2011 - 2016, Lefteris Zafiris <>
# This program is free software, distributed under the terms of
# the GNU General Public License Version 2. See the COPYING file
# at the top of the source tree.
# This has been altered to work with Googles new Speech models

use strict;
use warnings;
use File::Temp qw(tempfile);
use Getopt::Std;
use File::Basename;
use LWP::UserAgent;
use LWP::ConnCache;
use JSON;
use MIME::Base64;

my %options;
my $flac;
my $key;
my $url        = "";
my $samplerate = 16000;
my $language   = "en-US";
my $output     = "detailed";
my $results    = 1;
my $pro_filter = "false";
my $error      = 0;
my $thetext = ".";
my $score = ".";
getopts('k:l:o:r:n:fhq', \%options);

VERSION_MESSAGE() if (defined $options{h} || !@ARGV);


my %config = (
        "encoding"         => "FLAC",
        "sampleRateHertz"      => $samplerate,
        "languageCode"    => $language,
        "profanityFilter" => $pro_filter,
        "maxAlternatives" => $results,
        "model" => "phone_call",
        "useEnhanced" => 'true' 

my $ua = LWP::UserAgent->new(ssl_opts => {verify_hostname => 1});
$ua->agent("CLI speech recognition script");

# send each sound file to Google and get the recognition results #
foreach my $file (@ARGV) {
        my ($filename, $dir, $ext) = fileparse($file, qr/\.[^.]*/);
        if ($ext ne ".flac" && $ext ne ".wav") {
                say_msg("Unsupported file-type: $ext");
        if ($ext eq ".wav") {
                if (($file = encode_flac($file)) eq '-1') {
#       print("File $filename\n") if (!defined $options{q});
        my $audio;
        if (open(my $fh, "<", "$file")) {
                $audio = do { local $/; <$fh> };
        } else {
                say_msg("Cant read file $file");
        my %audio = ( "content" => encode_base64($audio, "") );
        my %json = (
                "config" => \%config,
                "audio"  => \%audio,
        my $response = $ua->post(
                Content_Type => "application/json",
                Content      => encode_json(\%json),
        if (!$response->is_success) {
                say_msg("Failed to get data for file: $file");
        if ($output eq "raw") {
                print $response->content;
        my $jdata = decode_json($response->content);
        if ($output eq "detailed") {
                foreach (@{$jdata->{"results"}[0]->{"alternatives"}}) {
                        $score = $_->{"confidence"};
                        $thetext = $_->{"transcript"};
        } elsif ($output eq "compact") {
                print $_->{"transcript"}."\n" foreach (@{$jdata->{"results"}[0]->{"alternatives"}});

print "\n\nThe transcription of message is below:\n\n$thetext\n\nWe are $score out of 1 sure its correct\n\nTranscribed using Googles Cloud Speech API ";

exit(($error) ? 1 : 0);

sub parse_options {
# Command line options parsing #
        if (defined $options{k}) {
        # check API key #
                $key = $options{k};
        } else {
                say_msg("Invalid or missing API key.\n");
                exit 1;
        if (defined $options{l}) {
        # check if language setting is valid #
                if ($options{l} =~ /^[a-z]{2}(-[a-zA-Z]{2,6})?$/) {
                        $language = $options{l};
                } else {
                        say_msg("Invalid language setting. Using default.\n");
        if (defined $options{o}) {
        # check if output setting is valid #
                if ($options{o} =~ /^(detailed|compact|raw)$/) {
                        $output = $options{o};
                } else {
                        say_msg("Invalid output formatting setting. Using default.\n");
        if (defined $options{n}) {
        # set number or results #
                $results = $options{n} if ($options{n} =~ /\d+/);
        if (defined $options{r}) {
        # set audio sampling rate #
                $samplerate = $options{r} if ($options{r} =~ /\d+/);
        # set profanity filter #
        $pro_filter = "true" if (defined $options{f});


sub say_msg {
# Print messages to user if 'quiet' flag is not set #
        my @message = @_;
        warn @message if (!defined $options{q});

# Help message #
        print "Speech recognition using Google Cloud Speech API.\n\n",
                "Usage: $0 [options] [file(s)]\n\n",
                "Supported options:\n",
                " -k <key>       specify the Speech API key\n",
                " -l <lang>      specify the language to use (default 'en-US')\n",
                " -o <type>      specify the type of output formatting\n",
                "    detailed    print detailed output with info like confidence (default)\n",
                "    compact     print only the transcripted string\n",
                "    raw         raw JSON output\n",
                " -r <rate>      specify the audio sample rate in Hz (default 16000)\n",
                " -n <number>    specify the maximum number of results (default 1)\n",
                " -f             filter out profanities\n",
                " -q             don't print any error messages or warnings\n",
                " -h             this help message\n\n";
  • In Freepbx create a Custom Destination as    “vmail2text,s,1”  and if you require certain queues to go to specific mailboxes one like “vmail2text,2000,1” so calls will be sent to mailbox 2000
  • Then in extensions that want to use transcription set the “Optional Destinations” to the custom destination.

And thats it. Enjoy.

Knowledge Base

Connecting to Serial console ports with Macs

Many devices and servers still require connection to them with console cables. Sangoma IPPBX and SBCs for example.
I will cover here how to connect to then with a Mac as they do not have a serial port.

First you will need a USB serial console cable. These can be purchased cheaply from Amazon or ebay.
For example the “KUMEED FTDI RS232 USB to RJ45 Serial for Cisco Console Rollover Cable for Cisco Routers” costs £10.99 inc delivery and works with Windows and Macs

To connect to a console port you need a few bits of information, The port speed, in the case of Sangoma SBCs the is 115200. also you need the device address.

To get teh device address open a terminal window and type:

ls /dev/*usb*

you will be returned something like:

/dev/cu.usbserial-DN01YED6 /dev/tty.usbserial-DN01YED6

so now to connect to the console port you need to enter:

screen /dev/tty.usbserial-DN01YED6  115200

you should now be connected, and can interact as if on a ssh session.

to disconnect is not as simple as just closing the terminal window, as a screen session will still be running. to exit a screen session enter the following key combination.

ctrl a \ 

If you do close a terminal you can see if any sessions are active by opening a new terminal and entering:

screen -list

Something like below will be returned if a session is active.

There is a screen on:

5177.ttys000.Ians-MacBook-2 (Detached)

1 Socket in /var/folders/bl/7k0f_2695njbsqwx762kr_380000gn/T/.screen.

to reconnect type

screen -r

and you should reconnect.

then exit as normal with ctrl a \

Blog Knowledge Base Security Uncategorized

GDPR and Call recordings

The effects of the GDPR on call recording will be to further strengthen the rights of individuals when it comes to businesses collecting, recording and using their personal data, placing greater onus the business to demonstrate compliance & increasing the penalties for not doing so.

All of this will have a direct impact on how you manage call recording. We will ask try to explain what the changes will be, what you need to know, and what you can do to get ready.

The Law As it Was

Previously, call recording was classified as a form of data processing. The Data Protection Act states that individuals must be informed and aware that they are being recorded and why they are being recorded.

This is because recorded calls have the ability to capture:

  • Personally identifiable information such as, names and addresses
  • Sensitive information such as, banking, financial, health, family, religious etc. detailsThe Data Protection Act also, sets outs rules for the correct handling of data, which requires any calls recorded to be stored securely with steps to be taken to avoid breaches.

So the main principles behind the GDPR are quite similar to those that were in place within UK legislation. With regards to call recording, the key principles are the expectation to protect privacy, notification and consent, and the requirement to adequately protect stored data from misuse.

The main difference with the GDPR will be that it strengthens the rights of the individual over the rights of an organisation. The DPA focuses on balancing the interests of individuals and businesses – as long as steps to protect privacy are followed, collecting and recording personal data is generally assumed to be justified.

Not so under the GDPR. Businesses wishing to record calls will be required to actively justify legality, by demonstrating the purpose fulfils any of six conditions:

  1. The people involved in the call have given consent to be recorded.
  2. A recording of a call is necessary for the fulfilment of a contract.
  3. Recording is necessary for fulfilling a legal requirement.
  4. The call recording is necessary to protect the interests of one or more participants
  5. The call recording is in the public interest or necessary for the exercise of official authority.
  6. Recording is in the legitimate interests of the recorder, unless those interests are overridden by the interests of the participant in the call.

Some of these conditions will apply specifically to certain uses of call recording in certain sectors. Number three, for example, could be used by firms in the financial services sector, which are required by the FCA to record all calls leading up to transactions. Number five will apply to the emergency and security services, who use call recording for investigatory purposes and in the interests of public protection.

But for general call recording, for example to monitor service levels or for staff training in a contact centre, the options left to businesses will be numbers one or six. And as the ‘legitimate interests’ of a business to evaluate customer service are not likely to outweigh the interests of personal privacy under the new regulations, so that only leaves gaining consent.

So unlike the previous law, assumed consent will not be satisfactory. With the GDPR strengthened rights of individuals to know what is happening with their personal information and to restrict and object to what happens to it, explicit consent to record calls will be required.


Along with the new GDPR comes a new ‘Principle of Accountability’ which puts a requirement on organisations to demonstrate their compliance. Data protection policies will soon become a statutory compliance document, rather than a recommended option. Therefore, businesses wishing to record calls will be required by law to draw up a specific call recording policy.

Next Step

So what to do, carry out a thorough audit of call recording practices, from the notifications given to how recordings are stored, is the first step to take. This should be done in the context of a wider evaluation of data protection, taking into account factors like how data breaches are identified, impact assessments and training and awareness within the business. From there, policies and protocols can begin to be drawn up, giving you plenty of time to make sure you hit the ground running come May 2018.

ICO Views on file retention and encryption

Data controllers must consider the security of lawful recordings and whether this can be achieved through the use of full-disk or file encryption products. However, some types of audio recording devices such as a dictation machines may not routinely offer encryption. The data controller must consider whether an alternative device is more appropriate or consider additional technical and organisational safeguards such as deleting the data as soon as practicable and locking the device away when not in use.

In the event that an unencrypted version of the recording should be retained (eg for playback in a Court of Law) then a range of other compensatory measures must be considered. These can include storage within a secure facility, limited and authorised access and an audit trail of ownership and usage.

The data controller must also consider the security of recordings once transferred from the device for long-term storage and be aware of other requirements which may prohibit audio recording of certain types of data.