PIONEERS WP8 ZoiPer client - Push Notification ...

Is this topic useful / relevant for PIAF or Windows Phone 8 Smartphones ?

  • No

    Votes: 0 0.0%
  • Solutions already exist

    Votes: 0 0.0%

  • Total voters
    2

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:
  1. Asterisk: a rather old asterisk version (1.4.31) running as full VM on a PROXMOX server
  2. FreePBX version (2.9.x)
  3. 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.
BACKGROUND:
IMPLEMENTATION:
  1. 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"
  2. 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.​
  3. 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"​
  4. 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.
CONCLUSIONS:
  • 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.).
It has become quite a long post, and I don't know if anyone will actually get to read to this point. In any case I will welcome any feedback (good and bad), hoping that after all at least to some extend, it will be useful to the community.
 

Vaelntin

New Member
Joined
Oct 7, 2013
Messages
3
Reaction score
0
Thank you so much Manfred, this is exactly what many people need (and there is no up-to-date tutorials expect this one)

I did try that, my setup is:

1. PIAF-Green Amazon EC2 AMI (CentOS 6.3)
2. Asterisk 11.2.1 / FreePBX 2.11.0.39
3. Im using Google Motif as Trunk

I think it is almost working, however something went wrong i believe "ast_yyerror" , here is my CLI:

-- Executing [111@from-did-direct:32] Set("Motif/+17186461226-4350", "DIALSTATUS=CHANUNAVAIL") in new stack
-- Executing [111@from-did-direct:33] Goto("Motif/+17186461226-4350", "custom-WP8-PushNotification,111,1") in new stack
-- Goto (custom-WP8-PushNotification,111,1)
-- Executing [111@custom-WP8-PushNotification:1] NoOp("Motif/+17186461226-4350", "**WP8 Push Notification: ext: 111, callerID: 7186461226 **") in new stack
-- Executing [111@custom-WP8-PushNotification:2] Answer("Motif/+17186461226-4350", "") in new stack
-- Executing [111@custom-WP8-PushNotification:3] Set("Motif/+17186461226-4350", "location=108.12.158.72:3252:3600:111:sip:[email protected]:3252;rinstance=8c7e3e3cd5442ead") in new stack
-- Executing [111@custom-WP8-PushNotification:4] Set("Motif/+17186461226-4350", "regx="X-PUSH-URI=([0-9a-zA-Z\.\:\/\_\-]+)"") in new stack
[2014-10-30 22:01:19] WARNING[2041][C-00000000]: ast_expr2.fl:470 ast_yyerror: ast_yyerror(): syntax error: syntax error, unexpected '<token>', expecting $end; Input:
"108.12.158.72:3252:3600:111:sip:[email protected]:3252;rinstance=8c7e3e3cd5442ead"=~""X-PUSH-URI=([0-9a-zA-Z\.\:\/\_\-]+)""
^
[2014-10-30 22:01:19] WARNING[2041][C-00000000]: ast_expr2.fl:474 ast_yyerror: If you have questions, please refer to https://wiki.asterisk.org/wiki/display/AST/Channel Variables
-- Executing [111@custom-WP8-PushNotification:5] Set("Motif/+17186461226-4350", "push=0") in new stack
-- Executing [111@custom-WP8-PushNotification:6] System("Motif/+17186461226-4350", "/var/lib/asterisk/agi-bin/zoiperpush.sh 0") in new stack
-- Executing [111@custom-WP8-PushNotification:7] NoOp("Motif/+17186461226-4350", "**Sript Result: APPERROR **") in new stack
-- Executing [111@custom-WP8-PushNotification:8] GotoIf("Motif/+17186461226-4350", "0?skip") in new stack
-- Executing [111@custom-WP8-PushNotification:9] NoOp("Motif/+17186461226-4350", "** WP8 Push Notification: Script ERROR ext: 111 not available **") in new stack
-- Executing [111@custom-WP8-PushNotification:10] Goto("Motif/+17186461226-4350", "111,exit") in new stack
-- Goto (custom-WP8-PushNotification,111,14)
-- Executing [111@custom-WP8-PushNotification:14] NoOp("Motif/+17186461226-4350", "** WP8 Push Notification: Goodby **") in new stack
-- Auto fallthrough, channel 'Motif/+17186461226-4350' status is 'CHANUNAVAIL'

Do somebody know the approach to fix that ?
 

Allen Ford

New Member
Joined
Dec 25, 2014
Messages
5
Reaction score
2
I removed the lines with regx="X-PUSH-URI=([0-9a-zA-Z\.\:\/\_\-]+) " from my asterisk box, seems even when fixing the error it cut of some urls depending on some characters. i let asterisk send the full uri to the zoiper script then had the script use sed to structure the data. URL="$(echo $1 | sed -n -e 's/^.*X-PUSH-URI=//p')"

I am working on Expanding this example here www.cyfordtechnologies.com
 

Members online

Forum statistics

Threads
25,810
Messages
167,755
Members
19,240
Latest member
nikko
Get 3CX - Absolutely Free!

Link up your team and customers Phone System Live Chat Video Conferencing

Hosted or Self-managed. Up to 10 users free forever. No credit card. Try risk free.

3CX
A 3CX Account with that email already exists. You will be redirected to the Customer Portal to sign in or reset your password if you've forgotten it.
Top