Manfred Koroschetz
New Member
- Joined
- Oct 14, 2014
- Messages
- 1
- Reaction score
- 0
As I recently upgraded my smartphone to a Nokia Lumia 925 running Windows Phone 8 (T-Mobile), I decided to see if I could get it to work as a SIP extension on my personal PIAF system. While researching a possible solution, it became clear to me that there is not much information available on this topic (WP8 related). However as I am quite encouraged by the results, I decided to share my findings with the community to get feedback, improvement suggestions and possibly others to perfect the solution.
OPERATING ENVIRONMENT:
OPERATING ENVIRONMENT:
- Asterisk: a rather old asterisk version (1.4.31) running as full VM on a PROXMOX server
- FreePBX version (2.9.x)
- Zoiper, Windows Phone Edition (v.1.0.2.0) as SIP client. Configured for "Push Notification" as per "Help, Tutorial..." section in the settings page of the client itself.
- "Push Notifications" tutorial published by ZoiPer
- The somewhat modified / corrected shell script (see below) from the tutorial is used to send the push notification to Microsoft's MPNS servers, to notify the phone of the incoming call.
I decided to call it "zoiperpush.sh" and to place it in the "/var/lib/asterisk/agi-bin" folder, giving it permissions (+x) and user:group (asterisk:asterisk) so that asterisk can execute it.
Code:#!/bin/bash printResult() { echo "<root>" echo -e "\t<code>"$1"</code>" echo -e "\t<X_NotificationStatus>"$2"</X_NotificationStatus>" echo -e "\t<X_DeviceConnectionStatus>"$3"</X_DeviceConnectionStatus>" echo -e "\t<X_SubscriptionStatus>"$4"</X_SubscriptionStatus>" echo "</root>" } CURL=`which curl` if [ -z $CURL ]; then echo "Curl not found" exit 1 fi if [ -z $1 ]; then echo "Url is not set" exit 1 fi URL=$1 i=0 max_i=3 while [ 1 ] do if [ $i -ge $max_i ]; then echo "===> Device not available" printResult "$RETCODE" "$X_NotificationStatus" "$X_DeviceConnectionStatus" "$X_SubscriptionStatus" exit 1; fi let i++ headers=`$CURL -s --data '<?xml version=1.0 encoding=utf-8?><root><Value1>Zoiper</Value1><Value2>Incoming</Value2><Value3>Call</Value3></root>' -D - --header 'Content-Type: text/xml' --header 'X-NotificationClass: 4' $URL | tr -d '\r'` #echo "Command Result: " $headers RETCODE=`echo "$headers" | head -n 1 ` #echo "RETCODE: " $RETCODE X_NotificationStatus=`echo "$headers" | grep "X-NotificationStatus" | sed 's#X-NotificationStatus: ##' | sed -e 's/^\s*//g' -e 's/\s*$//g' ` X_DeviceConnectionStatus=`echo "$headers" | grep "X-DeviceConnectionStatus" | sed 's#X-DeviceConnectionStatus: ##' | sed -e 's/^\s*//g' -e 's/\s*$//g' ` X_SubscriptionStatus=`echo "$headers" | grep "X-SubscriptionStatus" | sed 's#X-SubscriptionStatus: ##' | sed -e 's/^\s*//g' -e 's/\s*$//g' ` if [ "$RETCODE" == "HTTP/1.1 200 OK" ]; then if [ "$X_SubscriptionStatus" == "Active" ]; then if [ "$X_NotificationStatus" == "Received" ]; then if [ "$X_DeviceConnectionStatus" == "Connected" ]; then break; fi fi if [ "$X_NotificationStatus" == "Suppressed" ]; then break; fi fi fi done #printResult "$RETCODE" "$X_NotificationStatus" "$X_DeviceConnectionStatus" "$X_SubscriptionStatus"
- For the Dial Plan, I decided to use a "Custom Destination" in FreePBX (see step 3. below), which would be tied to the SIP extension the Phone was registered with.
For this I included the following script (adapted from the ZoiPer tutorial) at the end of the "extensions_custom.conf" using FreePBX Config Edit.
Note: This code is quite basic. More functionality could and probably should be built into it. Error handling for things that could happen with the phone (unregistered, unavailable etc) need improvement.
Code:[custom-WP8-PushNotification] exten => _X.,1,NoOp(**WP8 Push Notification: ext: ${EXTEN}, callerID: ${CALLERID(num)} **) exten => _X.,n,Answer exten => _X.,n,Set(location=${DB(SIP/Registry/${EXTEN})}) exten => _X.,n,Set(regx="X-PUSH-URI=([0-9a-zA-Z\.\:\/\_\-]+)") exten => _X.,n,Set(push=$["${location}"=~"${regx}"]) exten => _X.,n,System(/var/lib/asterisk/agi-bin/zoiperpush.sh ${push}) exten => _X.,n,NoOp(**Sript Result: ${SYSTEMSTATUS} **) exten => _X.,n,Gotoif($["${SYSTEMSTATUS}" == "SUCCESS"]?skip) exten => _X.,n,NoOp(** WP8 Push Notification: Script ERROR ext: ${EXTEN} not available **) exten => _X.,n,Goto(${EXTEN},exit) exten => _X.,n(skip),NoOp(** WP8 Push Notification: Playing Progress Announcement **) ;exten => _X.,n,Playback(pls-wait-while-try,noanswer) exten => _X.,n,Wait(3) exten => _X.,n,Dial(SIP/${EXTEN},20) ;--== Could transfer to VM if needed ==--; ;--== a. For "No Answer" ==--; ;--== b. For "Ignore" ==--; ;--== c. For "Timeout " ==--; exten => _X.,n(exit),NoOp(** WP8 Push Notification: Goodby **)
Note: There might be a timing issue related to the external script call through the "System", and the additional delay included in the code with the "Wait" command, as well as any delay the MPNS might add for the response. Further testing is required to establish how sensitive the solution is related to this timing. If it does not happen in the right timing, the client will not present the call. - To invoke the script included above, I created a "Custom Destination" in FreePBX using the following settings:
"Custom Destination: custom-WP8-PushNotification,${EXTEN},1"
"Description: WP8-PushNotification"
"Notes: Push notification for Windows Phone 8 smartphones" - Putting it all together
- Created a standard SIP extension for the phone without voice mail (for my application I don't need/want one). In addition I chose to direct all "Optional Destinations" (No Answer, Busy, Not Reachable) for this extension to the "Custom Destination | WP8-PushNotification" created in step 3. above.
- Created "Follow Me" settings for this extension, specifying:
"Disabled: False"
"Initial Ring Time: 0"
"Ring Strategy: ringall"
"Ring Time: 1"
"Destination if no answer: Custom Destination | WP8-PushNotification" from step 3.
Hack: I needed to provide an entry for the "Follow-me List:", but for the code to work the"actual extension" had to be called ("ringall"). So I created and included a "dummy" extension in this field that would never be available.
Optional: In these settings we could also play an announcement to the caller "Please wait while ..." and some "Alert Info" that gets sent to the phone.
- The solution work quite well while the phone keeps its registration active.
I have tested with the client as the active application, suspended (background) application, with and without the lock screen activated and it works as expected.
The suggestion by ZoiPer is to set a "high registration timeout" for the extension.
I am not clear how to address/work around this issue as I don't know how to individually change the "max SIP registration timeout" in the Settings (as it is possible on other SIP devices). A possible solution is to increase the servers "max registration time" in "Asterisk SIP Settings"). I did some preliminary testing and I was able to set it to 64000 (aprox. 1 day), However I am not sure if that is a good idea, or what other implications it might have.. - The ZoiPer tutorial hints to the fact that push notification should be able to launch the application on the phone. Further testing with the slightly modified and corrected code is showing that it does indeed work!
I am now able to receive a call without the application having been launched. - There is an operational security issue implicit with the phone being on public networks (T-Mobile 4G/LTE and WiFi Hotspots). Since the PIAF server should be secure it would not allow registration from such a network. "Travelin' Man 4" by wardmundy, could be a solution for this, but definitely it would not work for a "permanent active" secure remote office extension. For now it should work fine in "allowed secure private" networks (home office, remote branch offices etc.).