Wednesday, June 2, 2010

Asterisk Events with Timestamp 1.4

The below events is the incoming call to asterisk and Plays a prompt and does a Echo after that.

Event: Newchannel
Privilege: call,all
Timestamp: 1261277764.070399
Channel: SIP/broadvox-0a7bde90
State: Down
CallerIDNum:
CallerIDName:
Uniqueid: 1261277764.44

Event: Newcallerid
Privilege: call,all
Timestamp: 1261277764.070456
Channel: SIP/broadvox-0a7bde90
CallerID:
CallerIDName:
Uniqueid: 1261277764.44
CID-CallingPres: 0 (Presentation Allowed, Not Screened)

Event: Newstate
Privilege: call,all
Timestamp: 1261277765.729062
Channel: SIP/broadvox-0a7bde90
State: Up
CallerID:
CallerIDName:
Uniqueid: 1261277764.44

Event: OriginateResponse
Privilege: call,all
Timestamp: 1261277765.729085
Response: Success
Channel: SIP/broadvox-0a7bde90
Context: broadvoxcontext
Exten: 13038598130
Reason: 4
Uniqueid: 1261277764.44
CallerID:
CallerIDNum:
CallerIDName:

Event: Newexten
Privilege: call,all
Timestamp: 1261277765.729144
Channel: SIP/broadvox-0a7bde90
Context: broadvoxcontext
Extension: 13038598130
Priority: 1
Application: Answer
AppData: 4
Uniqueid: 1261277764.44

Event: Newexten
Privilege: call,all
Timestamp: 1261277765.729187
Channel: SIP/broadvox-0a7bde90
Context: broadvoxcontext
Extension: 13038598130
Priority: 2
Application: Read
AppData: DESTNO|vm-enter-num-to-call
Uniqueid: 1261277764.44

Event: Newexten
Privilege: call,all
Timestamp: 1261277778.705334
Channel: SIP/broadvox-0a7bde90
Context: broadvoxcontext
Extension: 13038598130
Priority: 3
Application: SayDigits
AppData: 12345
Uniqueid: 1261277764.44

Event: Newexten
Privilege: call,all
Timestamp: 1261277781.847347
Channel: SIP/broadvox-0a7bde90
Context: broadvoxcontext
Extension: 13038598130
Priority: 4
Application: Echo
AppData:
Uniqueid: 1261277764.44

Event: Hangup
Privilege: call,all
Timestamp: 1261277785.813339
Channel: SIP/broadvox-0a7bde90
Uniqueid: 1261277764.44
Cause: 16
Cause-txt: Normal Clearing

Saturday, May 1, 2010

Unusable Google App Engine - Time wasting efforts with Google App Engine

ok. I tried to inserted the data somehow each record with a new request and that worked fine. Now I tried to delete the data.

Tried to delete all at once. Did not work. Tried 100 at a time, Did not work.
Tried even 10 at a time, did not work. Deleting one by one that worked. Stupid Stuff !



 javax.jdo.Query q = pm.newQuery(Agent.class);

        Collection results = (Collection) q.execute();

        int deletecount =0;

        Iterator iter = results.iterator();

           while (iter.hasNext()) {

               if( deletecount > 1 )

                   break;

               pm.deletePersistent(iter.next());             

               deletecount++;

           }


If I try to delete one by one, then my quota got over. :)  I used to delete millions of records at a time with the existing Databases. Google Datastore or Big Table (I would say funny table) it is a total crap here and totally unusable for enterprise.

I use Microsoft Windows just for browsing and playing games. (Sometimes it is not even worth to play games). Same here too. So far felt comfortable with Google technologies, the app engine is a total crap and the datastore is too crappy. So if you want to use cloud computing and don't deal with huge data at the same time, just like writing personal home based applications, then I would say, opt for Google Appengine. Otherwise keey away and don't waste your time.


More over from the above graph I have still lot of CPU hours left in Datastore CPU Time, I don't know what is the fun of limitation out there. So Daily quota is not Daily Quote, it is per second Quota. Just for marketing purposes they come with the big numbers above.

With the above facts, it becomes unusable for me to work with except to host static files and funny websites. Not yet ready for enterprise and not so reliable though.

Experience with Google App Engine Data Store

Tried the Google's cloud platform with a simple example to store data.



package com.musugundan;

import java.io.IOException;
import java.util.Date;

import javax.jdo.PersistenceManager;
import javax.servlet.http.*;

@SuppressWarnings("serial")
public class MusugundanServlet extends HttpServlet {
 public void doGet(HttpServletRequest req, HttpServletResponse resp)
   throws IOException {
  resp.setContentType("text/plain");
  resp.addHeader("Refresh", "0; URL=/musugundan");
  resp.getWriter().println("Adding 100 records, Starting time " + new Date());
  PersistenceManager pm = PMF.get().getPersistenceManager();
  resp.flushBuffer();
        // 
                int maxrecords = 1000;
  for(long i=1;i<1000; i++)
  {
   Agent ag = new Agent("firstname" + i ,"lastname" + i,new Date());
   resp.getWriter().println("Writing Record :" + i );
   resp.flushBuffer();
            pm.makePersistent(ag);
  }    
        resp.getWriter().println("Added 100  records, Ending time " + new Date());
        resp.flushBuffer();
 }
}



When I set the maxrecords to 1000. It is error always. Means I cannot create 1000 records at a stretch.

I changed to 100. The timing went to 12 seconds to 25 seconds.

Change it to 1 and open multiple browsers with the instance of 100. It went on smoothly. Creating single record in a single request is pretty fast.

In Cloud computing make big things in a simpler way. That way it can work fast for its distributed nature of resources.

Wednesday, July 15, 2009

Asterisk Manager Interface to Python

I was thinking bit strange about python String Handling and doing advanced operations. It is very hunger for strings and handle things in a neat way.

Eventhough there are python libraries available for Asterisk. Handling it in our code natively gives us more comfort.

Below is the code connects to AMI (Asterisk Manager Interface) and prints all the events which it receives from asterisk.

#!/usr/bin/env python

import socket
import sys


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1",5038))
s.settimeout(.5)
file = s.makefile("rw",8096)
file.write("Action: Login\r\nUsername: username\r\nSecret: secret\r\nEvents: On\r\n\r\n")
file.flush()
print "Starting to Receive ...\n"
AVDict = {}

while 1:
try:
data = file.readline()
results = data.strip().split(": ")

try:
AVDict[results[0]].append(results[1])
except KeyError:
AVDict[results[0]] = results[1];
except AttributeError:
continue;
except:
print "[1001] ", sys.exc_info()[0]

except IndexError:
try:
print "AVDict is:", AVDict
AVDict.clear()
continue
except:
try:
del AVDict[:]
except TypeError:
continue;
except:
print "[1003] ", sys.exc_info()[0]
continue;
except:
#print "[1004] ", sys.exc_info()[0]
continue;

file.close()




Enjoy !

Wednesday, June 24, 2009

Getting the result of Netborder Call Progress Analyzer to an Asterisk variable

/* Parse contact header for continued conversation */
/* When we get 200 OK, we know which device (and IP) to contact for this call */
/* This is important when we have a SIP proxy between us and the phone */
if (outgoing) {
int cpdstart=0;
const char *cpdresult = __get_header(req,"CPD-Result",&cpdstart);

if (!ast_strlen_zero(cpdresult))
pbx_builtin_setvar_helper(p->owner, "CPDRESULT", cpdresult);
update_call_counter(p, DEC_CALL_RINGING);

Add the above bold code in chan_sip.c and you will get the Call Progress Detection result in asterisk Dial plan.

If you originate a call through AMI, with the dialplan,

exten => _8.,1,Answer
exten => _8.,2,Noop(${CPDRESULT})
exten => _8.,3,Echo


You will see in the asterisk console similar to this,


-- Executing [8dfgdfgdfgdfgdgdgdfgd@something:1] Answer("SIP/963258-10058d50", "") in new stack
-- Executing [8dfgdfgdfgdfgdgdgdfgd@something:2] NoOp("SIP/963258-10058d50", "Answering-Machine") in new stack
-- Executing [8dfgdfgdfgdfgdgdgdfgd@something:3] Echo("SIP/963258-10058d50", "") in new stack


In this case it is Answering-Machine.

Asterisk How to Capture Events and Handle it with PHP easily, works with all 1.2, 1.4 & 1.6

PHP makes the life easily when it comes to string parsing. Just enjoy to handle the events from asterisk.

#!/usr/bin/php -q

ob_implicit_flush(false);

$socket = fsockopen("hostname or ip","port", $errornum, $errorstr);
if(!$socket) {
print "Couldn't open socket. Error #" . $errornum . ": " . $errorstr;
} else {
fputs($socket, "Action: Login\r\n");
fputs($socket, "UserName: username\r\n");
fputs($socket, "Secret: password\r\n\r\n");
fputs($socket, "Action: Events\r\n");
fputs($socket, "EventMask: on\r\n\r\n");

fgets($socket); // Ignore the welcome message

$change = false;
$agentid = NULL;
$agentchannel = NULL;
$login = NULL;

while(true)
{
while(!feof($socket) )
{

$readbuf = "";
$resp = fread($socket,8192);
$readbuf .= $resp;
$allevents = split("\r\n\r\n",$readbuf);
foreach($allevents as $event)
{
$eventdetails = split("\r\n",$event);
$event_assoc = "";
foreach($eventdetails as $value ) {
$namevalue = split(": ",$value);
$event_assoc[$namevalue[0]] = $namevalue[1];
}
switch( $event_assoc['Event'] )
{
case 'Link': // Calls getting bridged
break;

default:
if( !empty($event_assoc['Event']) )
print_r($event_assoc);
}
}
fputs($socket, "Action: Ping\r\n\r\n");
usleep(1000000);
}

}

}

?>

Tuesday, April 21, 2009

Asterisk 1.2 , 1.4 & 1.6 Mp3 Voicemail using lame

Google Code checkout:
svn co http://codeoftheday.googlecode.com/svn/trunk/21April2009

Uncomment the following line in voicemail.conf

externnotify=/var/lib/asterisk/agi-bin/sendvoicemail.php

#!/usr/bin/php

<?php
/*
Released under Public Domain. Feel Free to modify and use it.
*/
mb_language('uni');
mb_internal_encoding('UTF-8');
require("class.phpmailer.php");

@mysql_connect("localhost","sqlusername","sqlpassword");
$dbselect = @mysql_select_db("asterisktable");

$voicemaildir = "/var/spool/asterisk/voicemail/" . $argv[1] . "/";

$sfilename = sprintf($voicemaildir .
"%s/INBOX/msg%04d.wav",$argv[2],$argv[3]-1);

$dfilename = sprintf($voicemaildir .
"%s/INBOX/msg%04d.mp3",$argv[2],$argv[3]-1);

$infofilename = sprintf($voicemaildir .
"%s/INBOX/msg%04d.txt",$argv[2],$argv[3]-1);

system("lame -V2 $sfilename $dfilename");



$stmt = sprintf("Select * from voicemail_users where mailbox='%s' and
context='%s'",$argv[2],$argv[1]);
$result = mysql_query($stmt);
if( mysql_num_rows($result) == 0 )
{
exit;
}

$row = mysql_fetch_assoc($result);
$rcptemail = $row['email'];
$rcptname = $row['fullname'];

$msginfo = parse_ini_file($infofilename);
$mail = new PHPMailer();
$mail->From = "noreply@voicetoemail.com";
$mail->FromName = "VoicetoEmail";
$mail->AddAddress($rcptemail, $rcptname);
$mail->AddReplyTo("noreply@voicetoemail.com", "VoicetoEmail");
$mail->WordWrap = 50; // set word wrap to 50 characters
$mail->AddAttachment($dfilename); // add attachments
$mail->IsHTML(true); // set email format to HTML

$mail->Subject = "Voicemail from " . $msginfo['callerid'];
$mail->Body = "Dear " . $rcptname . ",\n<br><br>Attached is the voice received
from " . $msginfo['callerid'] . "\n<br>Date & Time:" . $msginfo['origdate'] .
"\n\n<br><br>Support,<br>\nhttp://www.CalltoEmail.com";
$mail->AltBody = $mail->Body;
$mail->Send();

system("rm -rf $sfilename");
system("rm -rf $dfilename");
system("rm -rf $infofilename");

?>