Asterisk and Nagios enthusiasts, professionals and consultants based in Kuala Lumpur, Malaysia. Astiostech Sdn Bhd. Asterisk Malaysia. Nagios Malaysia.
Thursday, March 22, 2012
Asterisk 10 (1.10) SMS (messaging or SIP Messaging) in action
[UPDATE: WORKS FLAWLESSLY WITH ASTERISK 11 TOO…On Asterisk 11, you can choose XMPP as well as the protocol, right now its just SIP:, imagine the possibilities. Also fixed the issue when failed message]
[ANOTHER UPDATE FOR Offline message - We all know when devices are offline, messages cannot be sent and it will be discarded by Asterisk. I've written another dialplan/solution to that here]
With Asterisk 10 comes a channel independent dialplan for handling SIP MESSAGING (and jabber if that’s configured) method. In other words, phones that support SIP Messaging can send and receive “SMSes” through Asterisk 10 without the need to dial a channel making it like a regular telco SMS. Older Asterisks requires you to dial and answer a channel before you can send messages (see here).
It worked for me well in Asterisk 10.2.1 and this guide takes you through the process of using SMSing with a dialplan in a four step setup below. Asterisk uses the Message/ast_msg_queue channel to do all SIP Method MESSAGE related processing.
I was using FreePBX 2.10 but I guess it doesn’t quite matter as I am using a custom context anyway.
1) You need to modify your SIP general settings in sip.conf [freepbx users use the SIP Settings in Web GUI and add inside “Other SIP Settings”] add these two lines.
Non FreePBX users, edit sip.conf, under general
accept_outofcall_message=yes
outofcall_message_context=astsms
Save and exit.
We will now create the dialplan inside context astsms [FreePBX users edit the extensions_custom.conf file and put these in]
2) Non freepbx users, edit your extensions.conf file add the following
[astsms]
exten => _.,1,NoOp(SMS receiving dialplan invoked)
exten => _.,n,NoOp(To ${MESSAGE(to)})
exten => _.,n,NoOp(From ${MESSAGE(from)})
exten => _.,n,NoOp(Body ${MESSAGE(body)})
exten => _.,n,Set(ACTUALTO=${CUT(MESSAGE(to),@,1)})
exten => _.,n,MessageSend(${ACTUALTO},${MESSAGE(from)})
exten => _.,n,NoOp(Send status is ${MESSAGE_SEND_STATUS})
exten => _.,n,GotoIf($["${MESSAGE_SEND_STATUS}" != "SUCCESS"]?sendfailedmsg)
exten => _.,n,Hangup()
;
; Handle failed messaging
exten => _.,n(sendfailedmsg),Set(MESSAGE(body)="[${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)}] Your message to ${EXTEN} has failed. Retry later.")
exten => _.,n,Set(ME_1=${CUT(MESSAGE(from),<,2)})
exten => _.,n,Set(ACTUALFROM=${CUT(ME_1,@,1)})
exten => _.,n,MessageSend(${ACTUALFROM},ServiceCenter)
exten => _.,n,Hangup()
exten => _.,n,Hangup()
The above dialplan also send a little error message if the SMS didn’t send out saying its from “ServiceCenter”…
3) Save and exit and reload asterisk. [FreePBX users do #amportal restart]. Send SMSes! Yeah! But make sure you use a phone that supports SIP SMS.
IMPORTANT: In the SMS message center settings in your phone, enter the IP address of your Asterisk Server. In my case, I was using Unidata WiFi phone. As usual, do let us know the outcome and using other phones.
Here’s a message I got using the phone
Confirmed working with:
1) Unidata phones
2) Yealink phones (with SMS capabilities)
3) CSIPSimple on Andriod
4) X-Lite softphone
5) Most phones that support SIP Messaging
Saturday, March 10, 2012
TechDay Asia - My Slides
And here's me presenting. And some pictures from TechDay which was a huge success. Spanning across three countries and cities.
Well done Astiostech boys!
Asterisk / FreePBX limit incoming calls based on DID (on ZAP/Dahdi/SIP) with FreePBX
Image Source: http://appcrawlr.com/android-apps/best-apps-restrict-access
So, we had this challenge by our customer to do this as they are using PRI and supporting multiple customers. Each customer needs to be limited to n number of channels on PRI. When they were using analog that was simply straightforward, its a physical line, so nothing much you can do about “limiting” it is limited by design!
The following guide allows you to limit calls based on
- A single DID
- A group of DIDs (in this guide the amount of DIDs per group is limited to 5, add more, improv as you wish)
- Group DIDs will be a union meaning, if you have DID1 and DID2 with limit of 3 calls, at any one time either calls coming to those DIDs are added up and if exceed 3, it will hangup.
Anyway, here’s a quick how-to to give you an idea how to go about it. Improv as you see fit :-)
Requirements: (my system)
1) FreePBX 2.10 or 2.11
2) Asterisk 1.8 or higher
3) Dahdi based PRI or SIP or just about anything with the use of proper declarations (variables)
4) Use MySQL
5) Debian Wheezy
6) Adminer to run a few MySQL tasks such as creating db/tables, editing values in them etc…
So here’s how:
- Create a database inside MySQL called LIMITER
- Use adminer and paste the following codes to using the “SQL Command” feature
USE ` LIMITER`;
CREATE TABLE `tbl_didlimiter` (
`group` int(255) NOT NULL AUTO_INCREMENT,
`data` varchar(100) DEFAULT NULL,
PRIMARY KEY (`group`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1; - Now, we will create a user superuser with password dbgod00, paste the following codes in SQL Command again
CREATE USER 'superuser'@'localhost' IDENTIFIED BY ‘dbgod00';
GRANT ALL PRIVILEGES ON LIMITER.* TO 'superuser'@'localhost';
FLUSH PRIVILEGES; -
Now, we edit the dialplan, the most important part! Since i use FreePBX, we use the _custom.conf to add new hacks. So that’s exactly what we are doing here, copy and paste the codes into extensions_custom.conf, like below
#nano /etc/assterisk/extensions_custom.conf
;; DIALPLAN START ;;
;; READ ME FIRST
;; copyleft sanjay@astiostech.com
;; 1. Set trunks to use from-pstn, from-dahdi, from-zaptel OR from-trunk contexts
;; 2. The bold highlights may need to be changed depending on what you see in the
;; channel variables, most cases we see either EXTEN or FROM_DID or even CALLERID(DNID)
;; 3. Be sure this value is available and matching each other, in my case, the value
;; ${EXTEN} eventually matches the value ${CALLERID(DNID)} and they must
;; 4. This only supports one unique DID entry in DB. IF there are multiple entries
;; by mistake or whatever, it will pickout the first result that returns only
;;
;; 5. Feel free to add more G numbers as shown below, right now its just 5
;; 6. Maxdefault is set for global when no DB definitions are found for that DID and its limit,
;; if you do not want blanket settings, simply set MAXDEFAULT to blank or “”, if you want to set a global
;; limit then set it with MAXDEFAULT which then applies to all DIDs not set in DB.
;; Only when there’s a value found in DB then that DB value’s limits overrides maxdefault
[from-pstn-custom]
exten => _X.,1,NoOp(Handling incoming to do cool stuff)
same => n,Set(GROUP()=${EXTEN})
same => n,Macro(didchoke)
[macro-didchoke]
exten => s,1,NoOp(Checking for incoming limits and applying if needed)
exten => s,n,Set(MAXDEFAULT=””)
exten => s,n,MYSQL(Connect connid localhost superuser dbgod00 LIMITER)
exten => s,n,MYSQL(Query resultid ${connid} SELECT data from tbl_didlimiter where data like '%${CALLERID(DNID)}%' LIMIT 1)
exten => s,n,MYSQL(Fetch fetchid ${resultid} DBRESULT)
exten => s,n,MYSQL(Clear ${resultid})
exten => s,n,MYSQL(Disconnect ${connid})
exten => s,n,ExecIf($["${DBRESULT}"=""]?Set(DBRESULT=${CALLERID(DNID)})
exten => s,n,GotoIf($["${DBRESULT}"=""]?exception)
;
exten => s,n,Set(GROUPLIMIT=${CUT(DBRESULT,:,2)})
exten => s,n,ExecIf($["${GROUPLIMIT}"=""]?Set(GROUPLIMIT=${MAXDEFAULT})
exten => s,n,GotoIf($["${GROUPLIMIT}"=""]?exception)
;
exten => s,n,Set(DIDS=${CUT(DBRESULT,:,1)})
exten => s,n,Set(DID1=${CUT(DIDS,\,,1)})
exten => s,n,Set(DID2=${CUT(DIDS,\,,2)})
exten => s,n,Set(DID3=${CUT(DIDS,\,,3)})
exten => s,n,Set(DID4=${CUT(DIDS,\,,4)})
exten => s,n,Set(DID5=${CUT(DIDS,\,,5)})
;
exten => s,n,ExecIf($["${DID1}"!=""]?Set(G1=${GROUP_COUNT(${DID1})}))
exten => s,n,ExecIf($["${DID2}"!=""]?Set(G2=${GROUP_COUNT(${DID2})}))
exten => s,n,ExecIf($["${DID3}"!=""]?Set(G3=${GROUP_COUNT(${DID3})}))
exten => s,n,ExecIf($["${DID4}"!=""]?Set(G4=${GROUP_COUNT(${DID4})}))
exten => s,n,ExecIf($["${DID5}"!=""]?Set(G5=${GROUP_COUNT(${DID5})}))
;
exten => s,n,ExecIf($["${DID1}"=""]?Set(G1=0)
exten => s,n,ExecIf($["${DID2}"=""]?Set(G2=0)
exten => s,n,ExecIf($["${DID3}"=""]?Set(G3=0)
exten => s,n,ExecIf($["${DID4}"=""]?Set(G4=0)
exten => s,n,ExecIf($["${DID5}"=""]?Set(G5=0)
;
exten => s,n,Set(TOTALGGROUPCHANS=$[${G1}+${G2}+${G3}+${G4}+${G5}])
exten => s,n,NoOp(So total channels here are ${TOTALGGROUPCHANS} of GROUPLIMIT of ${GROUPLIMIT})
exten => s,n,GotoIf($["${TOTALGGROUPCHANS}" > "${GROUPLIMIT}"]?overlimit)
exten => s,n,MacroExit()
;
exten => s,n(overlimit),Busy(20)
exten => s,n,Hangup(16)
exten => s,n,MacroExit()
;
exten => s,n(exception),MacroExit()
;; DIALPLAN END ;; - Now, reload asterisk dialplan, be sure to tail the log file to start troubleshooting if things don’t go right.
#asterisk -rx “dialplan reload” - Now, edit the DB values and add DIDs like show in example below, use adminer or similar for easy editing
E.g. 1 Format: DID1:3
Where DID1 is DID you wish to limit to 3 channels
E.g. 2 Format: DID1,DID2,DID3,DID4,DID5:3
Where DID1-5 are the DIDs you wish to limit to 3 channels combined
Here’s sample data from my own server!
Fire away, test it out…! As usual, appreciate the feedback and ideas to improve! Do let us know how it went for you!