Apple push notifications (APN) with Python

We have created a middleware service which inputs RSS feeds and outputs Apple Push Notification. This allows integrate push notification support for your existing content management system easily. This blog post should give you some ideas if you are planning to create similar services.

To have the über-experience of customer engagement with mobile push notifications you need

  • A mobile application (iOS, Android 2.2)
  • RSS feed to notifications middleware server (our solution)
  • RSS feeds themselves
  • Windows/UNIX server running the middleware

1. How it is put together

Tornado web server is used to handle incoming HTTP requests in scalable manner.

feedparser library fetches RSS feeds and processes them to client notifications.

BitReader (post, source) library is used to create messages to interact with Apple push notification service (APNs). The protocol is bit based protocol running directly over TCP/IP. Apple service has been designed to handle high volumes of traffic – it does not use anything like stateless HTTP to waste bandwidth.

Django models are used to store the state of each individual subscriber. Django’s ORM abstraction allows us to use the same middleware for small distributions (< 1000 clients, SQLite database) or big ones (millions of clients, MySQL database). The stored state information includes the subscriber id and the current badge number – the red circle on the app icon showing the count unread posts. When the application is launched, it can decrease its badge number by doing a HTTP call to the server.

Django settings are used to put together required certificates and whether the application is run in sandbox mode.

2. Walkthrough

There is a core IO loop, running in a separate process, called stream observer. This loops updates fetches RSS feeds’ status and passes updates to Tornado server over HTTP.  With this arrangement, any HTTP capable client can send push notifications.

Tornado handles incoming updates, updates the related subscribe status – how many unread notifications, etc. through exposed Django views. The notification is formatted according to the variables available on the subscriber mobile platform. In Apple’s case, the notification message gets title, badge, sound and a launch image. Payload is checked against hard 256 byte limit.

Then the payload is pushed to Apple servers over TCP/IP protocol. SSL certificaties needed.

A subscriber is registered  when the mobile application is launched. The application asks a subscriber id from Apple servers. Then, this subscriber id is delivered to our middleware over normal HTTP call.

The middleware also handles feedback service which gives you list of devices which have unsubscribed from your service. This way you can cut off notifications from unsubscribed clients. This is also done using BitReader and TCP/IP.

3. Future

The architecture is built so that different push backends can be included in the service. Android support is on the roadmap and we probably will have Blackberry and Meego support (when/if Nokia announces such a service).

We have currently tested this solution with RSS streams from WordPress and Plone.

We may release source code when it’s ready.

4. More info

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

Finding an application download link for App Store or Android Market

For App Store, search your application in itunes.apple.com and copy-paste View in iTunes link.

For Android, search for your application in Android Pit and copy-paste Android Market Link. Android Pit also provides QR code (2D barcode) for your application.

Note that URL shorteners (bit.ly) do not like market:// protocol, so you might need to use alternative http://market.android.com notation. This, however, prompts a dialog in the device “Would you like to open this URL in a browser or in Market Place?”

More info

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

Importing Apache log file with performance information into OpenOffice / Excel using Python script

You can enhance Apache log files to include performance information, like read/sent bytes and HTTP request processing time. Compared to load tool (JMeter) generated data this information is usually easier to acquire and reflects the actual production server usage patterns. I think there even exist tools to replay the log data to rerun the load in simulation mode. This, however, works only on systems whose state can be reseted to the original situation (like with ZODB transactional database).

Below is an example Python script snippet which reads this custom Apache log file and creates Excel export out of it. After this, you can easily open this file in OpenOffice Calc or Microsoft Excel and draw nice diagrames out of it to see where the performance bottlenecks are.

The script splits duration column for the output file. You can easily add your own splits or use Calc’s Text to Columns editor.

The script:

#!/bin/python

import shlex
from pyExcelerator.Workbook import Workbook

FILE = "/var/log/apache2/yourlogfile.log"

def get_parts(line):
	""" Extract the parts of a line"""

	parts = shlex.split(line) # Split reserving parts inside quotation marks
	# 'duration:0/42327', 'io:643/4507', 'balancer:http://127.0.0.1:13003/']

	return parts

def get_duration(duration):
	""" Extract duration in ms from log line """

	keyword, args = duration.split(":")
	seconds, microseconds = args.split("/")

	mseconds = int(microseconds) 

	return mseconds

wb = Workbook()
sheet = wb.add_sheet('0')

print "Reading log"
i = 0

for line in open(FILE, "rt"):
	parts = get_parts(line)
	j = 0

	for part in parts:
		sheet.write(i,j,part)
		j += 1
         	sheet.write(i,len(parts)+1,get_duration(parts[-3]))
	i += 1

wb.save('output.xls')

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

Plone vs. Drupal – Welcome to Legoland

This is the most insightful IRC comment for a while and pretty much summarizes it all.

<lloydpearsoniv> i just appreciate the help. Plone is by the
  far the most sophisticated CMS  i have ever dealt with. I thought
  drupal was tough...lol But i need the sophistication for the project that I am attempting
<lloydpearsoniv> seriously, this makes drupal seem like lego

So this my new classification on popular CMS systems

  • Joomla!, WordPress: Lego Dublo
  • Drupal: Lego
  • Plone: Lego Technic

\"\" Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+