Pushing the boundaries of free technology

Main menu

Monthly Archives: 2011-1

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.

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.

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?”

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.

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