<repo_name>nidhhoggr/GPRS-googleVoice<file_sep>/classes/GPRS_SMS_API.php
<?php

/**
 * GPRS_SMS_API 
 * 
 * This class has some loose coupling with PhpSerial, a class for interfacing 
 * a device connected to a computer. the purpose of this class is to interface
 * SMS functionality of the connected GPRS shield.
 *  
 * @abstract
 * @package 
 * @version $id$
 * @copyright 
 * @author <NAME> <<EMAIL>> 
 * @license 
 */
abstract class GPRS_SMS_API
{
    protected $sms_ids = array(1,2,3,4,5);

    protected $sms_last_index = 1;

    /**
     * __construct
     * 
     * @param PhpSerial $serial 
     * @param mixed $device 
     * @param int $baud 
     * @access protected
     * @return void
     */
    function __construct(PhpSerial $serial, $device, $baud = 9600)
    {
        $serial->deviceSet($device);

        $serial->confBaudRate($baud);

        $serial->deviceOpen();

        $this->serial = $serial;

        $this->init();
    }

    /**
     * boot_load
     * 
     * @access public
     * @return void
     */
    function boot_load()
    {
        $this->serial->sendMessage("AT\r",1);
    }

    /**
     * setSmsLastIndex
     * 
     * @param mixed $sms_last_index 
     * @access public
     * @return void
     */
    public function setSmsLastIndex($sms_last_index)
    {
        $this->sms_last_index = $sms_last_index;
    }

    /**
     * setSmsIds
     * 
     * @param array $sms_ids 
     * @access public
     * @return void
     */
    public function setSmsIds($sms_ids = array())
    {
        $this->sms_ids = $sms_ids; 
    }

    /**
     * getSerial
     * 
     * @access public
     * @return PhpSerial $serial
     */
    public function getSerial()
    {
        return $this->serial;
    }

    /**
     * _getSmsIds
     * 
     * @access protected
     * @return array $sms_ids
     */
    protected function _getSmsIds()
    {
        return $this->sms_ids;
    }   

    /**
     * _getSmsLastIndex
     * 
     * @access protected
     * @return int $sms_last_index
     */
    protected function _getSmsLastIndex()
    {
        return $this->sms_last_index;
    }

    /**
     * listAllIncomingSMSBySmsIds
     * 
     * @access public
     * @return void
     */
    public function listAllIncomingSMSBySmsIds()
    {
        $this->serial->sendMessage("AT+CMGF=1\r",1);

        $sms_ids = $this->_getSmsIds();

        foreach($sms_ids as $sms_id)
        {
            $this->lastCmd = "AT+CMGR=$sms_id\r";
            $this->setial->readPort(); 
            $this->serial->sendMessage($this->lastCmd,1);
            $this->_readSms($this->serial->readPort());
        }
    }

    /**
     * listAllIncomingSMSFromLastIndex
     * 
     * @param mixed $sms_processor 
     * @access public
     * @return void
     */
    public function listAllIncomingSMSFromLastIndex($sms_processor)
    {
        $this->serial->sendMessage("AT+CMGF=1\r",1);

        $sms_id = $this->_getSmsLastIndex();

        do
        {
            $this->lastCmd = "AT+CMGR=$sms_id\r";
            $this->serial->sendMessage($this->lastCmd,1);
            $sms = $this->_readSms($sms_id, $this->serial->readPort());

            if($sms)
            {
                $this->_saveSms($sms);
            }

            $sms_processor($sms); 

            $sms_id++;
        }
        while($sms);
    }

    /**
     * _saveSms
     * 
     * @param mixed array $sms 
     * @abstract
     * @access protected
     * @return void
     */
    abstract protected function _saveSms($sms);

    /**
     * _readSms
     * 
     * @param mixed $sms_id 
     * @param mixed $deviceBuffer 
     * @access private
     * @return void
     */
    private function _readSms($sms_id, $deviceBuffer)
    {
        //the SMS query should be the last command
        if(!strstr($deviceBuffer, $this->lastCmd))
        {
            return FALSE;
        }

        $replacable = array(
            $this->lastCmd, 
            "+CMGR: ",
            "OK"
        );

        foreach($replacable as $to_replace)
        {
            $deviceBuffer = str_replace($to_replace,'',$deviceBuffer);

        }
        
        $trimmed_message = trim($deviceBuffer);

        if(empty($trimmed_message))
        {   
            return FALSE;
        }
        else
        {

            $contents = explode("\r\n", $trimmed_message);

            $info = explode(',', $contents[0]);

            $sms_info_keys = $this->_getSmsInfoKeys();

            foreach($info as $info_key=>$info_val)
            {
                $key_name = $sms_info_keys[$info_key];

                if($key_name !== "omit")
                {
                    $info[$key_name] = str_replace('"','',$info_val);
                }

                unset($info[$info_key]);
            }

            $info['index'] = $sms_id;

            $sms['info'] = $info; 

            if(empty($contents[1]))
            {
                return FALSE;
            }

            $sms['msg'] = $contents[1];
            

            return $sms;
        }
    }

    /**
     * _getSmsInfoKeys
     * 
     * @access protected
     * @return array $sms_info_keys
     */
    protected function _getSmsInfoKeys()
    {

        /**

        array(5) {
            [0]=>
                string(10) ""REC READ""
                [1]=>
                string(14) ""+13214277445""
                [2]=>
                string(2) """"
                [3]=>
                string(9) ""14/12/06"
                [4]=>
                string(12) "16:46:18-20""
                **/

        return array(
            'status',
            'recipient_phone_number',
            'omit',
            'date',
            'time'
        );
    }
}
<file_sep>/classes/SMSForwarder.php
<?php

/**
 * SMSForwarder 
 *
 * This class is not only a concrete implementation of an SMSProcessor
 * but it also acts to decouple database persietnce from abstracted functionality
 * in the GPRS_SMS_API. The main purpose of this class is to play Google Tranlsate
 * MP3's of the lastest text message recieved and them as processed.
 *
 * @uses GPRS_SMS_API
 * @uses SMSProcessor
 * @package 
 * @version $id$
 * @copyright 
 * @author <NAME> <<EMAIL>> 
 * @license 
 */
class SMSForwarder extends GPRS_SMS_API implements SMSProcessor
{
    const AUDIO_DIR = 'audio';

    const GOOGLE_TRANSLATE_API_CALL = 'http://translate.google.com/translate_tts?ie=UTF-8&tl=en&q=';

    /**
     * init
     * 
     * @access public
     * @return void
     */
    public function init()
    {   
        R::setup('mysql:host=localhost;dbname=gprs','root','');
    }

    /**
     * _saveSms
     * 
     * @param array $sms 
     * @access protected
     * @return void
     */
    protected function _saveSms($sms = array())
    {
        $sms_bean = R::dispense('sms');

        $sms_info = $sms['info'];

        $sms_bean->index = $sms_info['index'];
        $sms_bean->status = $sms_info['status'];
        $sms_bean->recipient_phone_number = $sms_info['recipient_phone_number'];
        $sms_bean->date = $sms_info['date'];
        $sms_bean->time = $sms_info['time'];
        $sms_bean->msg = $sms['msg'];
        $sms_bean->is_sent = FALSE;

        $id = R::store($sms_bean); 
    }

    /**
     * processIncomingSMS
     * 
     * @access public
     * @return void
     */
    public function processIncomingSMS()
    {
        $sendableSms = R::find('sms', ' is_sent = 0');

        foreach($sendableSms as $sms_to_send)
        {
            $message = urlencode($sms_to_send->msg);

            $audio_file = self::AUDIO_DIR . "/output-{$sms_to_send->id}.mp3";

            shell_exec("wget -q -U Mozilla -O {$audio_file} '".self::GOOGLE_TRANSLATE_API_CALL."{$message}'");

            if(file_exists($audio_file))
            {
                exec("mplayer " . $audio_file);

                exec("rm -rf $audio_file");

                $sms_to_send->is_sent = TRUE;

                R::store($sms_to_send);
            }
        }
    }

    /**
     * setSmsLastIndex
     * 
     * @access public
     * @return void
     */
    public function setSmsLastIndex()
    {
        $lastSms = R::findOne('sms', ' ORDER BY id DESC LIMIT 1');

        $smsLastIndex = $lastSms->index + 1;

        parent::setSmsLastIndex($smsLastIndex);
    }
}
<file_sep>/autoload.php
<?php

include('vendor/autoload.php'); 

function myload($class) 
{
    $libClass = 'libs/'.$class.'.php';
    $classClass = 'classes/'.$class.'.php';
 
    if (is_file($libClass))
    {
        require_once ($libClass);
    }
    else if(is_file($classClass))
    {
        require_once ($classClass);
    }
}

spl_autoload_register("myload");
<file_sep>/README.md
# GPRS-Google Voice

 >Author: <NAME> | Version: 0.1

The purpose of the repository is to house multiple libraries and useful scripts related to interfacing a GPRS shield and Google voice.

###SMSForwarder

this is a script that connects to a GRPS shield through USB serial port. The script checks for any new SMS text messages and saves them to a database. to process the SMS records the script utilizes the google translate API to download an MP3 containing the message in the SMS record and plays the record using Mplayer. After the record is played the record is updated as is_sent(boolean).

#####TODO

* add functionality to store phone number and keep a record of a name associated to the phone number
* In the MP3 for the text message the voice will provide who texted you what such as "Bob said [contents of sms message]" when the phone number is associated to a user name bob
* When a SMS message is recieved an SMS message will be sent asking for a name if the number doesn't already have an associated name

##### Installation

* Create a database named GPRS and configure the database username and password. Thats it!

```sh
mysql> CREATE DATABASE gprs;
```

* You need to install mapler to play the MP3's

```sh
$ sudo apt-get install mplayey
```

##### Usage

Plugin in your device with USB serial. The default baud rate is 9600.If another baud rate is desired you will have to explicity configure in the SMSForwarder instantion with a thrid parameter on the gprs script.

1) Send a text message to your Device

2) probe the shield for the new SMS message

```sh
$ ./gprs -d /dev/ttyACMO
```

3) probe the shield again. This time an MP3 will be played containing the latest SMS text message

```sh
$ ./gprs -d /dev/ttyACMO
```

###GoogleVoice

##### Usage

```sh
$ ./googleVoice
```

#####LINKS
* GPRS Shield Documentation
http://www.seeedstudio.com/wiki/GPRS_Shield_V1.0
* SIM900  AT Commands Manual
http://www.seeedstudio.com/wiki/images/a/a8/SIM900_AT_Command_Manual_V1.03.pdf
* Youtube videos coming soon

<file_sep>/googleVoice
#!/usr/bin/php
<?php

$options = getopt('u:p:n:m:f:h::');

extract($options);

//$p = "<PASSWORD>"; 

if(isset($h) || !isset($u) || !isset($p) || !isset($n) || (!isset($m) && !isset($f)))
{
    echo "usage: ./googleVoice -u [google voice email] -p [google voice password] -n [recipient phone number or from phone number for calls] -m [message] -f [to phone number for calls only]"; 
}
else
{
  include('autoload.php');

  $gv = new GoogleVoice($u, $p);
  
  if(isset($m)) { 
    $gv->sendSMS($n, $m);
  } else if(isset($f)) {
    $gv->callNumber($n, $f);
  }
}
<file_sep>/gprs
#!/usr/bin/php
<?php
$options = getopt('d:');

if(!isset($options['d']))
{
    Throw new Exception('Must specify a device'); 
}
else if(!file_exists($options['d']))
{
    Throw new Exception('No such device: ' . $options['d']); 
}

require_once('autoload.php');

$serial = new PhpSerial;

$smsF = new SMSForwarder($serial, $options['d']);

$smsF->processIncomingSMS();

$smsF->boot_load();

$smsF->setSmsLastIndex();

$smsF->listAllIncomingSMSFromLastIndex(function($sms) { 
    var_dump($sms);
}); 


<file_sep>/classes/SMSProcessor.php
<?php

/**
 * SMSProcessor 
 * 
 * @package 
 * @version $id$
 * @author <NAME> <<EMAIL>> 
 * @license 
 */
interface SMSProcessor
{

    /**
     * init
     * 
     * this funtion is called in the constructor of the super class
     *
     * @access public
     * @return void
     */
    function init();


    /**
     * processIncomingSMS
     * 
     * This is why the child class is implementing me.
     *
     * @access public
     * @return void
     */
    function processIncomingSMS();
}
