Combining Tele-communications and E-commerce (Asterisk, Java, and Python - Oh My!)This very gentle introduction to development with Asterisk will demonstrate how to use the AGI. Along the way you'll learn about Python and Java as well. I'll assume you're able to set up and configure Asterisk. The Asterisk Gateway Interface (AGI) allows an application you write (in whatever language you choose) to communicate directly with Asterisk using simple descriptive text commands. Normally you place your application in /var/lib/asterisk/agi-bin and Asterisk will execute it when it is encountered in the dial plan. Most of the commands are explained here. They are fairly straight forward, so I'll only demonstrate a few. There are three other AGIs you should be aware of. There is the dead AGI which allows you to run an application after a call ends. There is the fast AGI which lets your application communicate with Asterisk over TCP. And there is the extended AGI which is supposed to let your application view the audio stream on file descriptor three. But I don't know the state of this last AGI. Now here is your task. M&M wants to add a new color to their current selection. The choices are pink, emerald green, and mahogany. You will be responsible for developing the phone based voting system that will allow customers to vote for these new delicious sounding candies. In addition, you will need to make the results available to the public on a website in a graphical format. First take a look at the code below. You can find agi.py in the resources section (along with a link to the explanation). You'll also want the connection code. | ||
#!/usr/bin/env python #resources #http://home.cogeco.ca/~camstuff/agi.html #http://sourceforge.net/projects/mysql-python import agi from connect import get_mysql_connection OPTIONS = "123" interface = agi.AGI() select_map = {1: "pink", 2: "green", 3: "mahogany"} select_stmt = 'SELECT votes FROM colors WHERE color="%s"' update_stmt = 'UPDATE colors SET votes=%d WHERE color="%s"' try: (res,int_res)=interface.Cmd('STREAM FILE voteprompt "%s"' % OPTIONS) db = get_mysql_connection() color = select_map[int(chr(int_res))] db.query(select_stmt % color) rs = db.store_result() val = rs.fetch_row()[0][0]#returns a tuple of tuples db.query(update_stmt % (val+1,color)) db.close() except: pass | ||
This is our interface to asterisk. Every time a caller dials in, this script will be run. The first line of the try block executes the STREAM FILE command. The first argument is the name of the file to play, and the second argument are the keys the caller can press. In this example, the caller can press one, two, or three for the three colors. The next line connects to the database. The number is mapped to a color and the corresponding row is selected from the database. The number of votes is incremented and put back. That's all. Now let's take a look at the code for generating a plot of the results. In order to do this, we'll use Jython for its graphics libraries. I won't go much into the graphics libraries, but you can have a look at the references below. | ||
#!/usr/bin/env jython #resources #http://www.aion-needlecrafts.co.uk/info/dmcval2.htm #http://www.geocities.com/marcoschmidt.geo/java-save-jpeg-thumbnail.html #http://www-106.ibm.com/developerworks/library/j-begjava/ #http://java.sun.com/docs/books/tutorial/2d/TOC.html#display import time import connect from com.sun.image.codec.jpeg import JPEGImageEncoder,JPEGEncodeParam,JPEGCodec from java.awt import Graphics2D, Color from java.awt.image import BufferedImage from java.io import BufferedOutputStream,FileOutputStream from java.awt.geom import Rectangle2D MAX_X = 300 MAX_Y = 200 def write_image(votes,name):m = max(votes.values()) if m==0: return for k in votes: votes[k] = MAX_Y-int(votes[k]*float(MAX_Y)/m) #create the image image = BufferedImage(MAX_X,200,BufferedImage.TYPE_INT_RGB) g2d = image.createGraphics()g2d.setPaint(Color.white) g2d.fill(Rectangle2D.Double(0,0,MAX_X,MAX_Y)) g2d.setPaint(Color(243,71,139)) #Cyclamen Pink g2d.fill(Rectangle2D.Double(0,votes["pink"],100,MAX_Y)) g2d.setPaint(Color.black) g2d.drawString("Pink", 35,190) g2d.setPaint(Color(49,128,97)) #Emerald Green - MED g2d.fill(Rectangle2D.Double(100,votes["green"],200,MAX_Y)) g2d.setPaint(Color.black) g2d.drawString("Emerald Green", 105,190) g2d.setPaint(Color(209,102,84)) #Mahogany - MED g2d.fill(Rectangle2D.Double(200,votes["mahogany"],300,MAX_Y)) g2d.setPaint(Color.black) g2d.drawString("Mahogany", 220,190) #write to file as a JPEG bos = BufferedOutputStream(FileOutputStream(name+".jpeg")) encoder = JPEGCodec.createJPEGEncoder(bos) param = encoder.getDefaultJPEGEncodeParam(image) param.setQuality(1.0, False) encoder.setJPEGEncodeParam(param) encoder.encode(image) bos.close() while True: time.sleep(60) db = connect.get_jdbc_connection() stmt = db.createStatement() rs = stmt.executeQuery("SELECT * FROM colors") results = {} while rs.next(): md = rs.getMetaData() results[rs.getObject(1)] = rs.getObject(2) db.close() write_image(results,"votes") | ||
First we go into a loop that executes every 60 seconds (making this effectively an image server). Then we select the total votes for each of the colors from the database. Last the image generation routine is called with the votes. The numbers are normalized. A new image is created, and the background is set to white. Each of the three colors is painted on the background as a vertical bar with the height corresponding to the number of votes. Some identifying text is placed beneath each bar. Then the image is written out as a jpeg. The last bit of code is for handling database connections in Python and Jython and is not discussed here. If you have a decent understanding of Python, you should be able to follow the code.
Exercises (Warning - I haven't tried these.) |