News:

On Tuesday September 6th the forum will be down for maintenance from 9:30 PM to 11:59 PM PDT

Main Menu

Speed dial to post to url. Part of my Google voice 2014 workaround.

Started by giqcass, November 07, 2013, 01:12:22 AM

Previous topic - Next topic

Roger

As my contribution to this effort I will post detailed instructions based on my experience setting this up:

How to Initiate a Google Callback from an Obi Device

Acknowledgements: This procedure uses php code by Aaronpk (https://github.com/aaronpk/Google-Voice-PHP-API). The Obi configuations were devised by giqcass and azroberts on the Obi forum. My role is solely documantary in nature.

Requirements: Besides needing an Obi device and a Google Voice Number, you will need access to a server where you can host php files on a webserver (herein called abc.org)

Step 1: Configure the Obi as follows

System Management > ITSP Provisioning

Method: System Start

ConfigURL: SET TPRM1 = $UDM0; @loop IF ( $UDM0 == 00 ) GOTO redial; SET TPRM2 = $UDM0; GOTO checkit; @redial SET TPRM2 = $TPRM1; @checkit IF ( $TPRM1 != $UDM0 ) SYNC http://www.abc.org/gv.php?dialnum=$TPRM2; SET TPRM1 = $UDM0; WAIT 5; GOTO loop;

System Management > User Defined Macro 0

Value: $SpeedDial.99

ExpandIn: ANY

Star Codes > Star Codes Profile A

Code30: *(1xxxxxxxxxx|xxxxxxxxxx|<212>xxxxxxx|00S0), Set Speed Dial, set($Spd[99],$code)

change <212> to whatever your area is if you want to use 7-digit dialing.

Step 2: Upload two PHP files to the root of your server

The first PHP file is a slimmed down version of the Google Voice API by Aaronpk that I will call gvcall.php. You may also use the original API file. You may call the file any name you like, but you have to include it in the second set of php code.

gvcall.php

<?php

class GoogleVoice {
    // Google account credentials.
    private $_login;
    private $_pass;

    // Special string that Google requires in our POST requests.
    private $_rnr_se;

    // File handle for PHP-Curl.
    private $_ch;

    // The location of our cookies.
    private $_cookieFile;

    // Are we logged in already?
    private $_loggedIn = FALSE;

    public function __construct($login, $pass) {
        $this->_login = $login;
        $this->_pass = $pass;
        $this->_cookieFile = '/tmp/gvCookies.txt';

        $this->_ch = curl_init();
        curl_setopt($this->_ch, CURLOPT_COOKIEJAR, $this->_cookieFile);
        curl_setopt($this->_ch, CURLOPT_FOLLOWLOCATION, TRUE);
        curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, TRUE);
                // Withtout the next line I get cURL errors
                curl_setopt($this->_ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($this->_ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
    }

    private function _logIn() {
        global $conf;

        if($this->_loggedIn)
            return TRUE;

        // Fetch the Google Voice login page.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://accounts.google.com/ServiceLogin?service=grandcentral&passive=1209600&continue=https://www.google.com/voice&followup=https://www.google.com/voice&ltmpl=open');
        $html = curl_exec($this->_ch);

        // Parse the returned webpage for the "GALX" token, needed for POST requests.
        if (preg_match('/name="GALX"\s*type="hidden"\s*value="([^"]+)"/', $html, $match))
            $GALX = $match[1];
        else
            throw new Exception('Could not parse for GALX token');

        // Send HTTP POST service login request.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://accounts.google.com/ServiceLoginAuth');
        curl_setopt($this->_ch, CURLOPT_POST, TRUE);
        curl_setopt($this->_ch, CURLOPT_POSTFIELDS, array(
            'Email' => $this->_login,
            'GALX' => $GALX,
            'Passwd' => $this->_pass,
                'continue' => 'https://www.google.com/voice',
            'followup' => 'https://www.google.com/voice',
            'service' => 'grandcentral',
            'signIn' => 'Sign in'));
        $html = curl_exec($this->_ch);

        // Test if the service login was successful.
        if(preg_match('/name="_rnr_se" (.*) value="(.*)"/', $html, $matches)) {
            $this->_rnr_se = $matches[2];
            $this->_loggedIn = TRUE;
        }
        else {
            throw new Exception("Could not log in to Google Voice with username: " . $this->_login);
        }
    }

    /**
     * Place a call to $number connecting first to $fromNumber.
     * @param $number The 10-digit phone number to call (formatted with parens and hyphens or none).
     * @param $fromNumber The 10-digit number on your account to connect the call (no hyphens or spaces).
     * @param $phoneType (mobile, work, home) The type of phone the $fromNumber is. The call will not be connected without this value.
     */
    public function callNumber($number, $from_number, $phone_type = 'mobile') {
        $types = array(
            'mobile' => 2,
            'work' => 3,
            'home' => 1
        );

        // Make sure phone type is set properly.
        if(!array_key_exists($phone_type, $types))
            throw new Exception('Phone type must be mobile, work, or home');

        // Login to the service if not already done.
        $this->_logIn();

        // Send HTTP POST request.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://www.google.com/voice/call/connect/');
        curl_setopt($this->_ch, CURLOPT_POST, TRUE);
        curl_setopt($this->_ch, CURLOPT_POSTFIELDS, array(
            '_rnr_se' => $this->_rnr_se,
            'forwardingNumber' => '+1'.$from_number,
            'outgoingNumber' => $number,
            'phoneType' => $types[$phone_type],
            'remember' => 0,
            'subscriberNumber' => 'undefined'
            ));
        curl_exec($this->_ch);
    }

    /**
     * Cancel a call to $number connecting first to $fromNumber.
     * @param $number The 10-digit phone number to call (formatted with parens and hyphens or none).
     * @param $fromNumber The 10-digit number on your account to connect the call (no hyphens or spaces).
     * @param $phoneType (mobile, work, home) The type of phone the $fromNumber is. The call will not be connected without this value.
     */
    public function cancelCall($number, $from_number, $phone_type = 'mobile') {
        $types = array(
            'mobile' => 2,
            'work' => 3,
            'home' => 1
        );

        // Make sure phone type is set properly.
        if(!array_key_exists($phone_type, $types))
            throw new Exception('Phone type must be mobile, work, or home');

        // Login to the service if not already done.
        $this->_logIn();

        // Send HTTP POST request.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://www.google.com/voice/call/cancel/');
        curl_setopt($this->_ch, CURLOPT_POST, TRUE);
        curl_setopt($this->_ch, CURLOPT_POSTFIELDS, array(
            '_rnr_se' => $this->_rnr_se,
            'forwardingNumber' => '+1'.$from_number,
            'outgoingNumber' => $number,
            'phoneType' => $types[$phone_type],
            'remember' => 0,
            'subscriberNumber' => 'undefined'
            ));
        curl_exec($this->_ch);
    }

}

?>
The second PHP file I will call gv.php. You can see that this was referred to in the ConfigURL above as http://www.abc.org/gv.php You will need to modify this code to contain your Google Voice credentials. You will also need to change 12223334444 to your callback number (the phone number in Google Voice settings that rings on your Obi device). I have added the line "ini_set('display_errors', 'On');" to provide valuable messages in case of errors. The messages could be removed after testing is complete. I have also added an email notification for each call. Again, this is primarily for testing purposes.

gv.php

<?php
ini_set('display_errors', 'On');
include('gvcall.php');
$dialnum = $_GET["dialnum"];
if ($dialnum != '') {
  $gv = new GoogleVoice('username@gmail.com', 'password');
  $gv->callNumber($dialnum, '12223334444', 'home');
  mail("webmaster@abc.org","gvcall made to $dialnum",$dialnum,"From:\n");
}
?>
As you can see the Google Voice username, password, and callback number are hard-coded into this second php file. You may wonder about the security of this, but my limited understanding–based on web searches–is that as long as the php files are being properly processed by the server, no one will be able to see your password. If, however, your server was not configured properly for php files, the code would be shown in plain text.

Step 3: Testing

Once the two php files have been uploaded to the server, try to access one of them from a browser by, for example, typing the following into your browser (replace abc.org with your server name): http://www.abc.org/gv.php If you get a blank screen that is a good sign because that means the server is processing the php code. If you are able to see the php code, that means the server is not processing the php code and instead just returning it. You need to have PHP5 and PHP5-Curl installed on the server and have it configured to process php code (left to other tutorials).

Testing the call using a browser

Once you believe the server is handling the php code properly you can test a call via the following URL: http://www.abc.org/gv.php?dialnum=12125551212 where 12125551212 is the number you want to call. If this works properly your phone should ring within a few seconds from enter this URL into your browser. If your phone does not ring, try entering just the first part and seeing if you get an error message: http://www.abc.org/gv.php

If you get a message that your Google Voice login failed, try clicking through the following link: https://accounts.google.com/ServiceLogin?passive=1209600&continue=https%3A%2F%2Faccounts.google.com%2FDisplayUnlockCaptcha&followup=https%3A%2F%2Faccounts.google.com%2FDisplayUnlockCaptcha That should re-enable your access. Try again until you are able to make a call with the URL.

Testing the call using the Obi

Now that you are able to make a call using the browser, you are ready to make a call using the Obi. Dial the number you want to call with a star in front of it. For example if you want to call 1-212-555-1212 dial *12125551212. You should hear a new dial tone, after which you can hang up and wait for the callback.

Step 4: Usage & Start-up

Once you get everything set up, usage is exactly the same as the final test. You place a call pre-pended with the * symbol and wait for the callback. There are, however, two caveats. You cannot dial the exact same number twice (study the ConfigURL to convince yourself why this is true). A redial has been built into the process, so dialing *00 will redial the last number, but it can only be used once, then you will have to dial the whole number again. Another workaround is to use 10 digit dialing one and and 11 digit dialing the second time, so you can call *2125551212 and then dial *12125551212 and both should work.

Under start-up, I will mention the following. When rebooting the Obi UDM0, TPRM1, and TPRM2 are all null and the Obi executes the configURL every 5 seconds (or whatever you set the WAIT interval to be). That is why I put the "if ($dialnum != '') " test in my gv.php file. Once I placed a callback request and then placed a redial the configURL behaves as intended and only executes the configURL when it sees a number number dialed. These two initial calls shouldn't be necessary, but for me they appeared to be.

pinchpenny

Quote from: Roger on April 30, 2014, 05:45:08 AM
As my contribution to this effort I will post detailed instructions based on my experience setting this up:

How to Initiate a Google Callback from an Obi Device

Acknowledgements: This procedure uses php code by Aaronpk (https://github.com/aaronpk/Google-Voice-PHP-API). The Obi configuations were devised by giqcass and azroberts on the Obi forum. My role is solely documantary in nature.

Requirements: Besides needing an Obi device and a Google Voice Number, you will need access to a server where you can host php files on a webserver (herein called abc.org)

Step 1: Configure the Obi as follows

System Management > ITSP Provisioning

Method: System Start

ConfigURL: SET TPRM1 = $UDM0; @loop IF ( $UDM0 == 00 ) GOTO redial; SET TPRM2 = $UDM0; GOTO checkit; @redial SET TPRM2 = $TPRM1; @checkit IF ( $TPRM1 != $UDM0 ) SYNC http://www.abc.org/gv.php?dialnum=$TPRM2; SET TPRM1 = $UDM0; WAIT 5; GOTO loop;

System Management > User Defined Macro 0

Value: $SpeedDial.99

ExpandIn: ANY

Star Codes > Star Codes Profile A

Code30: *(1xxxxxxxxxx|xxxxxxxxxx|<212>xxxxxxx|00S0), Set Speed Dial, set($Spd[99],$code)

change <212> to whatever your area is if you want to use 7-digit dialing.

Step 2: Upload two PHP files to the root of your server

The first PHP file is a slimmed down version of the Google Voice API by Aaronpk that I will call gvcall.php. You may also use the original API file. You may call the file any name you like, but you have to include it in the second set of php code.

gvcall.php

<?php

class GoogleVoice {
    // Google account credentials.
    private $_login;
    private $_pass;

    // Special string that Google requires in our POST requests.
    private $_rnr_se;

    // File handle for PHP-Curl.
    private $_ch;

    // The location of our cookies.
    private $_cookieFile;

    // Are we logged in already?
    private $_loggedIn = FALSE;

    public function __construct($login, $pass) {
        $this->_login = $login;
        $this->_pass = $pass;
        $this->_cookieFile = '/tmp/gvCookies.txt';

        $this->_ch = curl_init();
        curl_setopt($this->_ch, CURLOPT_COOKIEJAR, $this->_cookieFile);
        curl_setopt($this->_ch, CURLOPT_FOLLOWLOCATION, TRUE);
        curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, TRUE);
                // Withtout the next line I get cURL errors
                curl_setopt($this->_ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($this->_ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)");
    }

    private function _logIn() {
        global $conf;

        if($this->_loggedIn)
            return TRUE;

        // Fetch the Google Voice login page.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://accounts.google.com/ServiceLogin?service=grandcentral&passive=1209600&continue=https://www.google.com/voice&followup=https://www.google.com/voice&ltmpl=open');
        $html = curl_exec($this->_ch);

        // Parse the returned webpage for the "GALX" token, needed for POST requests.
        if (preg_match('/name="GALX"\s*type="hidden"\s*value="([^"]+)"/', $html, $match))
            $GALX = $match[1];
        else
            throw new Exception('Could not parse for GALX token');

        // Send HTTP POST service login request.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://accounts.google.com/ServiceLoginAuth');
        curl_setopt($this->_ch, CURLOPT_POST, TRUE);
        curl_setopt($this->_ch, CURLOPT_POSTFIELDS, array(
            'Email' => $this->_login,
            'GALX' => $GALX,
            'Passwd' => $this->_pass,
                'continue' => 'https://www.google.com/voice',
            'followup' => 'https://www.google.com/voice',
            'service' => 'grandcentral',
            'signIn' => 'Sign in'));
        $html = curl_exec($this->_ch);

        // Test if the service login was successful.
        if(preg_match('/name="_rnr_se" (.*) value="(.*)"/', $html, $matches)) {
            $this->_rnr_se = $matches[2];
            $this->_loggedIn = TRUE;
        }
        else {
            throw new Exception("Could not log in to Google Voice with username: " . $this->_login);
        }
    }

    /**
     * Place a call to $number connecting first to $fromNumber.
     * @param $number The 10-digit phone number to call (formatted with parens and hyphens or none).
     * @param $fromNumber The 10-digit number on your account to connect the call (no hyphens or spaces).
     * @param $phoneType (mobile, work, home) The type of phone the $fromNumber is. The call will not be connected without this value.
     */
    public function callNumber($number, $from_number, $phone_type = 'mobile') {
        $types = array(
            'mobile' => 2,
            'work' => 3,
            'home' => 1
        );

        // Make sure phone type is set properly.
        if(!array_key_exists($phone_type, $types))
            throw new Exception('Phone type must be mobile, work, or home');

        // Login to the service if not already done.
        $this->_logIn();

        // Send HTTP POST request.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://www.google.com/voice/call/connect/');
        curl_setopt($this->_ch, CURLOPT_POST, TRUE);
        curl_setopt($this->_ch, CURLOPT_POSTFIELDS, array(
            '_rnr_se' => $this->_rnr_se,
            'forwardingNumber' => '+1'.$from_number,
            'outgoingNumber' => $number,
            'phoneType' => $types[$phone_type],
            'remember' => 0,
            'subscriberNumber' => 'undefined'
            ));
        curl_exec($this->_ch);
    }

    /**
     * Cancel a call to $number connecting first to $fromNumber.
     * @param $number The 10-digit phone number to call (formatted with parens and hyphens or none).
     * @param $fromNumber The 10-digit number on your account to connect the call (no hyphens or spaces).
     * @param $phoneType (mobile, work, home) The type of phone the $fromNumber is. The call will not be connected without this value.
     */
    public function cancelCall($number, $from_number, $phone_type = 'mobile') {
        $types = array(
            'mobile' => 2,
            'work' => 3,
            'home' => 1
        );

        // Make sure phone type is set properly.
        if(!array_key_exists($phone_type, $types))
            throw new Exception('Phone type must be mobile, work, or home');

        // Login to the service if not already done.
        $this->_logIn();

        // Send HTTP POST request.
        curl_setopt($this->_ch, CURLOPT_URL, 'https://www.google.com/voice/call/cancel/');
        curl_setopt($this->_ch, CURLOPT_POST, TRUE);
        curl_setopt($this->_ch, CURLOPT_POSTFIELDS, array(
            '_rnr_se' => $this->_rnr_se,
            'forwardingNumber' => '+1'.$from_number,
            'outgoingNumber' => $number,
            'phoneType' => $types[$phone_type],
            'remember' => 0,
            'subscriberNumber' => 'undefined'
            ));
        curl_exec($this->_ch);
    }

}

?>
The second PHP file I will call gv.php. You can see that this was referred to in the ConfigURL above as http://www.abc.org/gv.php You will need to modify this code to contain your Google Voice credentials. You will also need to change 12223334444 to your callback number (the phone number in Google Voice settings that rings on your Obi device). I have added the line "ini_set('display_errors', 'On');" to provide valuable messages in case of errors. The messages could be removed after testing is complete. I have also added an email notification for each call. Again, this is primarily for testing purposes.

gv.php

<?php
ini_set('display_errors', 'On');
include('gvcall.php');
$dialnum = $_GET["dialnum"];
if ($dialnum != '') {
  $gv = new GoogleVoice('username@gmail.com', 'password');
  $gv->callNumber($dialnum, '12223334444', 'home');
  mail("webmaster@abc.org","gvcall made to $dialnum",$dialnum,"From:\n");
}
?>
As you can see the Google Voice username, password, and callback number are hard-coded into this second php file. You may wonder about the security of this, but my limited understanding–based on web searches–is that as long as the php files are being properly processed by the server, no one will be able to see your password. If, however, your server was not configured properly for php files, the code would be shown in plain text.

Step 3: Testing

Once the two php files have been uploaded to the server, try to access one of them from a browser by, for example, typing the following into your browser (replace abc.org with your server name): http://www.abc.org/gv.php If you get a blank screen that is a good sign because that means the server is processing the php code. If you are able to see the php code, that means the server is not processing the php code and instead just returning it. You need to have PHP5 and PHP5-Curl installed on the server and have it configured to process php code (left to other tutorials).

Testing the call using a browser

Once you believe the server is handling the php code properly you can test a call via the following URL: http://www.abc.org/gv.php?dialnum=12125551212 where 12125551212 is the number you want to call. If this works properly your phone should ring within a few seconds from enter this URL into your browser. If your phone does not ring, try entering just the first part and seeing if you get an error message: http://www.abc.org/gv.php

If you get a message that your Google Voice login failed, try clicking through the following link: https://accounts.google.com/ServiceLogin?passive=1209600&continue=https%3A%2F%2Faccounts.google.com%2FDisplayUnlockCaptcha&followup=https%3A%2F%2Faccounts.google.com%2FDisplayUnlockCaptcha That should re-enable your access. Try again until you are able to make a call with the URL.

Testing the call using the Obi

Now that you are able to make a call using the browser, you are ready to make a call using the Obi. Dial the number you want to call with a star in front of it. For example if you want to call 1-212-555-1212 dial *12125551212. You should hear a new dial tone, after which you can hang up and wait for the callback.

Step 4: Usage & Start-up

Once you get everything set up, usage is exactly the same as the final test. You place a call pre-pended with the * symbol and wait for the callback. There are, however, two caveats. You cannot dial the exact same number twice (study the ConfigURL to convince yourself why this is true). A redial has been built into the process, so dialing *00 will redial the last number, but it can only be used once, then you will have to dial the whole number again. Another workaround is to use 10 digit dialing one and and 11 digit dialing the second time, so you can call *2125551212 and then dial *12125551212 and both should work.

Under start-up, I will mention the following. When rebooting the Obi UDM0, TPRM1, and TPRM2 are all null and the Obi executes the configURL every 5 seconds (or whatever you set the WAIT interval to be). That is why I put the "if ($dialnum != '') " test in my gv.php file. Once I placed a callback request and then placed a redial the configURL behaves as intended and only executes the configURL when it sees a number number dialed. These two initial calls shouldn't be necessary, but for me they appeared to be.

In preparation for Doomsday on May 15th, I spotted this thread in giqcass' signature.

Ah, so in order for this to work you need 1)a webserver 2)dial * before the number you want to call and 3) wait for a callback to actually initiate the call.

Dialing a * before a number my grandmother wanted to call would enrage her. Having to wait for a callback to initiate a call is simply untenable for my grandmother.

Pretty neat work around for me, perhaps, though not grandma friendly.

Why do grandmothers need landlines when they have cellphones?

giqcass

If Obihai would open up a few more options to us this project could be made completely seamless to the end user.

1) Give us a better way to pass a number as a variable.
2) Allow us to set an incoming call so it can join a call in process.  It would be nice to simulate ringing well waiting for the callback and then join the  incoming call.  That would give a natural experience.


It could be used with other services that do Callbacks like Localphone.  Many have an actual API.  I think we could even do basin text messaging.
Long live our new ObiLords!

Roger

What would be really cool is if the firmware for the Obi was open source, like tomato for routers.  Then anyone could create mods of it to do whatever they wanted.  Imagine the possibilities!

giqcass

Quote from: Roger on May 06, 2014, 12:04:36 PM
What would be really cool is if the firmware for the Obi was open source, like tomato for routers.  Then anyone could create mods of it to do whatever they wanted.  Imagine the possibilities!
I wish!
Long live our new ObiLords!

Roger

Quote from: azrobert on April 29, 2014, 09:07:28 PM
Roger,

What you describe shouldn't happen. The first command gets executed only on startup and sets TPRM1 to equal $UDM0, so the URL shouldn't be executed until you dial a new number. It also shouldn't matter if you set Method to Periodically instead of System Start. You would just execute the script additional times setting TPRM1 to $UDM0.

Even if there was a logic error on startup that I don't see, the script would only be executed once, because the next command sets TPRM1 to $UDM0. Maybe if Speed Dial #99 was set to a null value would cause a problem. I didn't test that condition.

As I mentioned before the callback works great, but sometimes the configURL script would execute every 5 seconds even though I didn't dial a number (and the dialnum would be blank).  Now I guess I see why.  I usually use the obitalk portal and I didn't see anything wrong there, but yesterday I logged into the device itself and noticed that the Obitalk provisioning script uses TPRM1 as one of its variables, so that was probably the cause of my problems.  I changed all the TPRMn to GPRMn in my configURL and hopefully that will resolve the problem.

sfcwtuOBI

"change 12223334444 to your callback number (the phone number in Google Voice settings that rings on your Obi device"

What number is this? Is it the GV number? I tried it with my GV number, but obi device did not ring. It only works when I use my mobile number. Can someone help pls?

giqcass

You must set up an incoming phone number for your Obi by getting a free DID from Callcentric, IPkall, or anyone else that provides them.  You must then verify that number with Google Voice and set it up as a forwarding phone.  Then Use that number as the Callback number.
Long live our new ObiLords!