User:Agx
From FreeSWITCH Wiki
Migrating from Asterisk
Actually i don't use FreeSwitch in production since there are a few missing pieces of the puzzle i need before i will able to switch the telephone system:
- G.729 licenses are not available (so not LEGAL transcoding is possible);
- there is no app Queue equivalente, but it looks trivial to write some other code in javascript using mod_limit;
- there seems no support for DevState and "hint,DS/customstate", so looks like i've to keep asterisk as "presence server" or write some code that handle special SUBSCRIBE with perl NET::SIP module;
This is an example of what i've to port:
in "extensions.conf" i've:
exten => 999,hint,DS/customstate
the i've a shell script:
#!/bin/sh asterisk -rx "device state 999 $1"
this script will change the LED on the phones as soon as i issue the command.
About PUBLISH / PRESENC
The Wiki documentation is totally wrong, i could actually change the status of a subscription. I registered X-Lite and was able to alter the status of subscribed items using command line stuffs:
- ON-THE-PHONE:
- presence in 18@DOMAIN on-the-phone "I am on the phone"
- BUSY:
- presence in 18@DOMAIN busy "I am Busy"
- RING:
- presence in 18@DOMAIN unknown hold
- OFFLINE:
- presence out 18@DOMAIN unknown
- ONLINE:
- presence in 18@DOMAIN online
- AWAY:
- presence in 18@DOMAIN away Away
- IDLE (PROPRIETARY):
- presence in 18@DOMAIN unknown Idle
However some stuff still remains:
- if i use presence out then a new presence in will not trigger any event
- when phone reboots it does not get notified of the status of the subscriptions
- when a user register or unregister i don't have events in/out
About me
A quick introduction to myself:
- i work for http://www.mercuriuspbx.it/
- i'm member of ILS: http://www.linux.it/~agx/
- personal homepage: http://www.badpenguin.org/
About VoIP:
- i mantain some code externally to asterisk 1.4.17: check sourceforge for agx-ast-addons
- i contributed some code and documentation to http://www.callweaver.org
- i'm contributing some documentation and patches/codes for FreeSwitch:
- the patch that can bind a keyboard's function key with a console command FSCORE-101
- i added shitloads of options to mod_fax, http://wiki.freeswitch.org/wiki/Mod_fax
Playing with FreeSwith
This is almost all the stuff i've tested with freeswitch since now.
Compiling Source
- do no forget to copy modules.conf template (cp build/modules.conf.in modules.conf) and to edit it before compiling
- "configure" script has no fancy options, just --prefix
- if you want to install additional modules you can use "make ${mod_name}" + "make ${mod_name}-install"
Basic FreeSwitch CLI command
The "real" CLI is available only when starting FS for debugging. If you want to connect to an already running instance you have to use another program, there are different way of doing it.
Anyway for debugging purpose you need first the mod_commands loaded and installed then you have access to this commands:
- reloadxml
- show calls - note that will only show bridged calls
- show channells
- status
- version
- sofia status profile PROFILENAME
To exit the console, and stop the daemon, you have to use:
- shutdown
Internal database
How can i show a single SIP phone status? How do i show values into a table when i've 200 phones??
- TIPS: i made a little shell script that does a SQL query upon the internal databases located in db/*.db using sqllite3
First Time Setup
- freeswitch.xml.conf is the main file it includes all the others
- if you change the config get a CLI and do the command "reloadxml"
- if this does not works just restart the daemon
- you don't need to edit the file but look at it for understand the basic config
- modules.conf.xml lists all the modules that are loaded at runtime, like modules.conf inside ast/cw
- lots of default modules has default password so strip down everything you don't need and check all password with a grep inside of every config file
- console.conf.xml enabled colorized output for the console if you like it:
<param name="colorize" value="true"/>
- syslog.conf.xml this logging module seems not working, i switched to logfile_conf.xml that also support automatically rotating the logfiles
- SIP server:
- make sure sofia's module is loaded in modules.conf.xml
- make sure sofia's config file is loaded in freeswitch.xml conf
- edit sofia.xml.conf and enable the cool feature of having more phones subscribing with the same user account:
<param name="multiple-registrations" value="true"/>
- edit sofia.xml.conf and enable this parameter if you want to disable SIP over TCP:
<param name="bind-params" value="transport=udp"/>
First Time Setup of NAT
If you're going to have SIP clients outside NAT and do a port-forwarding from the xDSL router to the SIP server you need some extra settings. FS handle domain into the authentication phase, so if you're addicted to broken asterisk SIP handling you should take care of this.
- edit sofia.xml.conf and enable this settings if you plan to use NAT doing a port forwarding of 5060 from the xDSL router:
<param name="force-register-domain" value="192.168.1.8"/>
- vars.xml contains some global values
- if you're behind NAT set a fixed domain
- at the end of the page don't forget to set your preferred STUN server
After i setup NAT i discovered it is working for external NATted client but no more for internal phones. So the trick is to create 2 sofia's profile: 1 for internal clients and 1 for natted clients. The two profiles have to use a different SIP ports, that's fine: use 5061 or 5062 for NAT so you also avoid bugged router to interferee with your SIP headers. The first profile, for local phones, should NOT contains the following lines that instead have to be used for the natted profile:
<param name="ext-rtp-ip" value="$${external_rtp_ip}"/>
<param name="ext-sip-ip" value="$${external_sip_ip}"/>
Multiple PBX behind NAT
If you have junkerix or any other SIP PBX behind NAT i found usefull forcing RTP port range and making a direct port forwarding of them to the local IP PBX to avoid any router interference with SIP/RTP dynamic connection tracking.
To restrict them edit switch.conf.xml:
<param name="rtp-start-port" value="21000"/> <param name="rtp-end-port" value="22000"/>
If you use junkerix edit also /etc/junkerix/rtp.conf and avoid overlap of the RTP UDP ports.
Adding a softphone
- directory.xml hold users credentials, edit it
- just add a new XML definitions
- restart the daemon
- you should be able to register your 1st softphone
- if you are behind NAT and want to act like a buggy asterisk implementations then add this to the user:
<variable name="force-contact" value="nat-connectile-dysfunction"/>
Codec Negotiation
If you try to make a call and it does not hit the dialplan you have a codec negotiation problem that its very easy to debug watching at the CLI messages. I've a lot of this issue since FS developers live in ULaw land while i strongly prefer ALaw.
- edit vars.xml.conf and set your preferred codec order, i uses for now:
<!--#set "global_codec_prefs=PCMA@20i,PCMU@20i,g729,GSM,speex,iLBC@30i"-->
Out Bound Calls
When you generate a call from your phone it hits the dialplan section of freeswitch.xml.conf this usually implies that the default_context.xml.conf is used
I'm tring to setup a catchall extension for invalid dialed numbers:
<extension name="ext_invalid">
<condition field="destination_number" expression=".*" continue="on-true">
<action application="playback" data="/opt/sounds/en/pbx-invalid.wav"/>
</condition>
</extension>
I also found usefull to set the phone's username the same as their main extension number and to automaticall catch all the registered phones using this extension XML:
<extension name="PBX Extension">
<condition field="destination_number" expression="^(1[0-9][0-9])$">
<action application="bridge" data="sofia/interni/$1%${domain}"/>
</condition>
</extension>
Setting multilanguage sound files
the problem
The default playback command does not understand a multilanguage structure like the PlayBack() application inside asterisk does. To do the trick you have just to use the phrase engine and create a macro that will transform just the filename inside a full patch including the directory where the file are installed, the language and the extension.
the solution
This is what i wrote myself:
- in your dialplan invoke the application/macro:
<action application="phrase" data="play,pbx-invalid"/>
- in freeswitch.xml into the phrase section (or inside your lang/*/*.xml files), after:
<language name="en" sound-path="/opt/sounds/en" tts_engine="cepstral" tts_voice="jean-pierre" >
insert:
<macros>
<macro name="play">
<input pattern="(.*)">
<match>
<action function="execute" data="sleep(1000)"/>
<action function="play-file" data="/opt/sounds/en/$1.wav"/>
</match>
</input>
</macro>
</macros>
testing in real field
Now in your directory.xml inside your user section you can insert into the variables section the default language for some of your foreign phones. I mean if your default is "en" and you want "it" for some phones just add:
<variable name="default_language" value="it"/>
I test this with my invalid extension catchup in dialplan.xml that changed from:
<extension name="ext_invalid">
<condition field="destination_number" expression=".*" continue="on-true">
<action application="playback" data="/opt/sounds/en/pbx-invalid.wav"/>
</condition>
</extension>
into:
<extension name="ext_invalid">
<condition field="destination_number" expression=".*" continue="on-true">
<action application="answer"/>
<action application="phrase" data="play,pbx-invalid"/>
<action application="hangup"/>
</condition>
</extension>
Setting some test extension
Echo test
<extension name="ext100">
<condition field="destination_number" expression="^100$" continue="on-true">
<action application="answer"/>
<action application="phrase" data="play,beep"/>
<action application="echo" data=""/>
<action application="hangup"/>
</condition>
</extension>
Milliwat
You need the mod_tone_stream enabled for this to work:
<extension name="test_milliwatt">
<condition field="destination_number" expression="^1002$">
<action application="answer"/>
<action application="playback" data="tone_stream://%(10000,0,1004);loops=-1"/>
<action application="hangup"/>
</condition>
</extension>
Play Tones
<extension name="test_tone_stream">
<condition field="destination_number" expression="^1003$">
<action application="answer"/>
<action application="playback" data="tone_stream://path=${base_dir}/conf/tones/tetris.ttml;loops=1"/>
<action application="sleep" data="500"/>
<action application="playback" data="tone_stream://path=${base_dir}/conf/tones/fur_elise.ttml;loops=1"/>
<action application="hangup"/>
</condition>
</extension>
-
I don't know how to create TTML files
-
Look here? http://wiki.freeswitch.org/wiki/TGML
Setting a music on hold stream
<extension name="ext105">
<condition field="destination_number" expression="^105$" continue="on-true">
<action application="answer"/>
<action application="playback" data="local_stream://moh-default"/>
<action application="hangup"/>
</condition>
</extension>
in mod_local_stream.xml.conf:
<configuration name="local_stream.conf" description="stream files from local dir">
<directory name="moh-default" path="/opt/moh">
<param name="rate" value="8000"/>
<param name="channels" value="1"/>
<param name="interval" value="2"/>
<param name="timer_name" value="soft"/>
</directory>
</configuration>
new parameter for mod_local_stream.xml.conf:
<param name="shuffle" value="true"/>
Blinking Field Lamp
The BFL is the feature that every customer wants and its ready to kill you if it is not going to work: so be carefull! Technically its based on SUBSCRIBE/NOTIFY sip messages. Most phones does not resend the SUBCRIBE stuff when they loose the registration and this make their BFL to stop working: you better reboot the phone.
To put it at work just add this in sofia.xml.conf to enable presence:
<param name="manage-presence" value="true"/>
X-Lite
- open "Contact" tab
- add a new friend
- edit it
- set "Type" as "Softphone"
- enter the username as "phone number" or like "<sip:username@PBXIP>"
- enable the mark on "Show this contact's Availability"
- TIP: Make sure you have "enable session timers" turned off in X-lite profile config or you will unable to dial out
Snom 320
It works with firmware 7.1.30. To configure it open the phone admin page:
- got to the "function keys" page
- configure your new button this way:
- account: choose the exact account
- type: choose "extension"
- as number: "<sip:131@192.168.1.8;user=phone>|**"
- change 131 with your SIP phones account name
- change 192.168.1.8 with your PBX domain
- the "|**" is a special new configuration parameter that will make the Snom call "**131" when a BFL blinking is pressed, avoiding fancy SIP messages, that's very nice since its the way GXP-2000 already work since many years;
GrandStream GXP 2000
- It works like in Asterisk, however it seems there is some delay before the LED becomes green when phones boot
Call Pickup
Call Pickup is implemented using the intercept application. Unluckly that application need a UUID to work (the channel unique identifier) so you need a fancy SET some DBvar during a call to keep track of all the UUIDs.
The 1st step is to have an extension that catch all your valid calls and set some internal DB values:
<extension name="set_variables_on_call" continue="true">
<condition field="destination_number" expression="^([1-9][0-9][0-9])$">
<action application="set" data="dialed_ext=$1"/>
<action application="set" data="call_timeout=30"/>
<action application="db" data="insert/last_dial_ext/${dialed_ext}/${uuid}"/>
</condition>
</extension>
The second step is to intercept the uuid of the latest call related to a given number:
<extension name="call-pickup-interno">
<condition field="destination_number" expression="^\*\*(\d+)$">
<action application="answer"/>
<action application="intercept" data="${db(select/last_dial_ext/$1)}"/>
<action application="sleep" data="2000"/>
</condition>
</extension>
-
This seems to have the drawback that only the latest callee can pickedup... if more people are ringing a phone (of course call waiting should be enabled) you can pick only the latest. So probably its better to use a queue or to implement some kind of dialplan locking.
-
There is no equivalent CLI command of "sip show subsriptions"
- well it looks you can just write a shell script that does an SQL query upon the SQLITE database that holds registration, subscriptions and stuffs.
-
If you stop freeswitch probably you have to reboot the phones too, in order to have the subscriptions working again
Call Parking
Parking is very easy and implies the use of mod_fifo. The concept is the one of a queue. If you park a call you put it in a waiting queue of type FIFO. So if you used to park a call to a slot and to pickup that call from another position i must warn you that you need to create a dedicated park slot for this since the following example create a global parking queue.
Park:
<extension name="park">
<condition field="destination_number" expression="^700$">
<action application="fifo" data="700@$${domain} in undef $${moh_uri}"/>
</condition>
</extension>
Unpark:
<extension name="unpark">
<condition field="destination_number" expression="^701$">
<action application="answer"/>
<action application="fifo" data="700@$${domain} out nowait"/>
</condition>
</extension>
Snom Park Orbit Button
On Asterisk i used to assign a DTMF key *2700 to do the parking trick. With Freeswitch it seems you can use the PARK+ORBIT button. I tried the following example and didn't worked well on Snom 320.
To configure it create a button of type "Park+Orbit" and as value set it to "park+700"; "park+" will be removed and "700" will be used by mod_fifo as your queue name:
<extension name="park">
<condition field="source" expression="mod_sofia"/>
<condition field="destination_number" expression="park\+(\d+)">
<action application="fifo" data="$1@$${domain} in undef $${moh_uri}"/>
</condition>
</extension>
<extension name="unpark">
<condition field="source" expression="mod_sofia"/>
<condition field="destination_number" expression="^parking$"/>
<condition field="${sip_to_params}" expression="fifo\=(\d+)">
<action application="answer"/>
<action application="fifo" data="$1@$${domain} out nowait"/>
</condition>
</extension>
Call Recording
- Its well supported
On Demand Recording
This is done using the Snom "Record" button. Just program a function key of type "Key_Event" and value "F_REC" and it will work. Check in sofia xml config the param "record-template" where the recorded call will be stored.
<param name="record-template" value="$${base_dir}/recordings/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
Other phones are not supported now:
[agx] what about other brands like GXP 2000 ? <bkw_> agx: well on those we have discussed something similar to res_features that can map dtmf to things.. but its not done yet. <bkw_> its on the list of stuff we want to do... just not sure when
Setting a ringback test extension
ringback will make a customized ring tone while trying to bridge to another phone
<extension name="ext101">
<condition field="destination_number" expression="^101$" continue="on-true">
<action application="set" data="ringback=%(1000, 4000, 425.0, 0.0)"/>
<action application="bridge" data="sofia/default/username%pbxip"/>
<action application="hangup"/>
</condition>
</extension>
You can also provide a MOH or a wave file:
<action application="set" data="ringback=local_stream://moh-default" /> <action application="set" data="/opt/sounds/en/waiting.wav" />
Ring Groups
I love pyramidal ring groups :) Adjust the timeout!
<extension name="ext150">
<condition field="destination_number" expression="^150$">
<action application="set" data="call_timeout=5"/>
<action application="bridge" data="sofia/interni/132%192.168.1.8"/>
<action application="bridge" data="sofia/interni/131%192.168.1.8",sofia/interni/132%192.168.1.8"/>
<action application="bridge" data="sofia/interni/130%192.168.1.8,sofia/interni/131%192.168.1.8",sofia/interni/132%192.168.1.8""/>
</condition>
</extension>
IVR Menues
The wiki has a really nice documentation about it at http://wiki.freeswitch.org/wiki/IVR_Menu
Question: How can i also accept more digits at the IVR prompt to bypass it and bridge to an internal phone? Answer: Try a javascript IVR, more example here: http://www.freeswitch.org/eg/js/
Asterisk F-AGI like
-
* event_socket.conf.xml provide something like a F-AGI but more powerfull, change the password inside this file first
- External control,
-
http://wiki.freeswitch.org/wiki/Event_socket_outbound
-
http://svn.freeswitch.org/svn/freeswitch/trunk/scripts/socket/socket2me/socket2me.c
Advanced Codec Negotiation
-
I want phones to use g729 when talkign each other and G711 when dialing outside or they are "On hold"
- this seems possible, if all the phones uses G.729 and i record all the audio files and event the MOH streaming in G.729 there'll be no transcoding and it will work!
-
check this post about codec negotiation to see if its possibile:
http://lists.freeswitch.org/pipermail/freeswitch-users/2007-April/000922.html
CAMP ON
[agx] bkw_, do you think it can be implemented in dialplan or it requires a dedicated mod_socket daemon doing the job? <bkw_> agx: hrm let me think about that.. I know a way.. but you'll need to write some lua/perl/javascript to keep it from looping <bkw_> or to control the looping I should say <bkw_> continue_on_fail = true.. then go into a script.. pause for like 30 seconds... play your camp on stuff.. with dtmf options to leave voicemail press 1 or continue to wait <bkw_> then issue a transfer back to the original extension <bkw_> rinse and repeat <bkw_> set transfer_ringback to the music on hold. [agx] bkw_, nice idea i will setup an example <bkw_> also might wanna count the loops in a var <bkw_> because the transfer will only go 70 times in a loop <bkw_> before it kills the call <bkw_> so you should be able to watch it.. and control it via that variable [agx] bkw_, Max-Forward issue? <bkw_> yes <bkw_> 70 forwards would be like 2100 seconds [agx] bkw_, that's ok for "camp on" <bkw_> camp on for that long @30 seconds each plus the ring out time.. would be an hour <bkw_> :P [agx] bkw_, my max camp time is 180 seconds and user can press "1" to go directly to voicemail <bkw_> hehe [agx] instead for an "inbound" call center? mod_socket is mandatory?
CALL CENTER INBOUND
[agx] instead for an "inbound" call center? mod_socket is mandatory? <bkw_> not really.. you could use offhook agents tied to a fifo <bkw_> so everyone connects to one end of the fifo.. ready for calls <bkw_> then you push calls into the fifo from the otherside [agx] bkw_, oh i didn't noticed something like that in mod_fifo i better reread the wiki about it
