GPS Event [17] – Coral8 [5]

Last time we detected when a device stops streaming data, however the message remained within Coral8. Today, I would like to attach an output adapter to send the message out. Coral8 comes with several output adapters, including XML over HTTP. This one seems appropriate for any kind of server based application. Just for fun, I decided to transfer data to an application running on Google App Engine.

Note:
Starting with Google App Engine is fairly easy; detailed instructions are available, so I will not describe it here.

The to-do list:

  1. Add a XML over HTTP output adapter to the Coral8 example;
  2. Write an application on Google App Engine to receive, store and display Coral8 messages;
  3. Test.

1. The Output Adapter


--Adapter for GoogleAppEngine
ATTACH OUTPUT ADAPTER WriteXMLOverHTTP 
    TYPE WriteXmlOverHttpAdapterType
TO STREAM sAlarm
PROPERTIES
 URL = "//192.168.xxx.76:8080",
 XSLTEMPLATE = 
[[<xsl:stylesheet xmlns:xsl="//www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" />
<xsl:template match="/">
<xsl:text>{</xsl:text>
<xsl:for-each select="*">
<xsl:for-each select="*">
<xsl:text>'</xsl:text>
<xsl:value-of select="@Name" />
<xsl:text>':'</xsl:text>
<xsl:value-of select="." />
<xsl:text>',</xsl:text>
</xsl:for-each>
</xsl:for-each>
<xsl:text>}</xsl:text>
</xsl:template>
</xsl:stylesheet>
]]
;

 

The adapter has two properties:

  • URL of the server, including the port number;
  • XSLTEMPLATE for an optional XSL transformation.

If the XSLTEMPLATE is not specified, Coral8 sends a raw XML string like this one:


<tuple xmlns="//www.coral8.com/cpx/2004/03/" timestamp="1232757671788000">
	<field name="Entity">DS_1</field>
	<field name="Msg">Stream stopped</field>
	<field name="AlmTime">2009-01-23 19:41:09.788000</field>
</tuple>

 

The template in the adapter transforms the XML to a dictionary-like string:
{'Entity':'DS_1','Msg':'Stream stopped','AlmTime':'2009-01-23 19:41:09.788000',}.
Using the XSL I have simply avoided parsing the XML on the server side.

2. The Application

"""
Capture Coral8 messages to DB.
Display last 10 messages.
"""
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util \
     import run_wsgi_app
from google.appengine.ext import db
 
class Dta(db.Model):
  content = db.StringProperty(multiline=True)
  date = db.DateTimeProperty(auto_now_add=True)
  
class MainPage(webapp.RequestHandler):
  def get(self):
    self.response.headers \
      ['Content-Type'] = 'text/plain'
    dt = db.GqlQuery \
      ("SELECT * FROM Dta ORDER BY date DESC LIMIT 10")
    for d in dt:
      try:
        dic = eval(d.content)
        self.response.out.write('\n%s' % ('-' * 40))
        for k in dic.keys():
          self.response.out.write \
            ('\n%s = %s' % (k, dic[k]))
      except:
        pass
 
  def post(self):
    rec = Dta()
    doc = str(self.request.body)
    rec.content = ' '.join(doc.split())
    rec.put()
     
application = webapp.WSGIApplication \
              ([('/', MainPage)], debug=True)
 
def main():
  run_wsgi_app(application)
 
if __name__ == "__main__":
  main()

May seem complicated, but here is the basics:

class Dta(db.Model) defines a “database table” with two columns:

  • content – a string column for Coral8 data;
  • date – a timestamp column;

post(self) method is activated when Coral8 sends data to the application’s web page;

get(self) method is activated when a browser visits the web page.

3. Test

For testing, I have used the same example as in the previous post — send several messages to Coral 8 and then stop. Here is the result in a browser window: