Archive

Archive for May, 2009

Connecting to Apple Push Notification Services using Python & Twisted

May 11th, 2009 7 comments

One of the exciting features of the upcoming iPhone 3.0 operating system is the ability for a device to receive a notification message from your own application that is relayed by Apple’s network cloud. This feature allows the iPhone to channel all out-of-band communication into a narrow channel that is low impact on the device from a power, security and usability point-of-view.

As an application developer, you are responsible for two pieces to make this new notification service work: the actual application that runs on the iPhone OS, and a provider service that both communicates with the device and directly to Apple’s cloud.

In a typical flow, the application on an iPhone device issues an API call to request notifications for the identifier that the developer has assigned to the application. In response to that API call, Apple’s servers provide the device with a binary token value that uniquely identifies the device & installation combination (for security reasons, the device token is reset if the device is reset, so it is not a one-to-one mapping to the actual hardware). Next, the application must connect to the developer’s provider servers and provide it with the device token it has received from apple. The provider can now use the device token when communicating back to the Apple Push Notification Service (APNS) cloud.

A provider implementation has very little work to do to inform APNS of a device update. Most of the effort in a provider will be in the actual framework of the application itself, and managing what information should be sent to a device. A common implementation will be for a provider to both communicate with the APNS server cloud and also to the application’s own network services and effectively become a protocol translator. Such a heavily network based application like that is a perfect match for the Python language and the Twisted framework.

A provider to APNS link is very simple: a secure-socket connection (SSL) is made to a APNS server and then simple messages are sent by the provider whenever a notification needs to be sent to the device. The APNS server does not respond or acknowledge the message. Every so often (Apple recommends once an hour), the provider server should connect to a web server that will dump a list of device tokens that are no longer valid (as in the device has uninstalled the application). This is the provider’s only feedback mechanism outside of communicating directly with a device.

The first step is to setup an SSL connection to the APNS servers. By following the directions on Apple’s developer portal, you can create a certificate and private key that are assigned to your application identifier. This certificate & private key must then be used when connecting to the APNS servers as an authentication mechanism.

One caveat  - the Mac OS X Keychain Access application does not directly export certificates and private keys in Private Enhanced Mail (.pem)  format, which is what the OpenSSL implementation we use with Twisted will want, but luckily there’s an easy mechanism to convert if you export the files as Personal Information Exchange (.p12) format. The following two commands can be used to convert the .p12 files into .pem files using the built-in openssl command on Mac OS X or most Linux distributions:

openssl pkcs12 -in cred.p12 -out certkey.pem -nodes -clcerts
openssl pkcs12 -in pkey.p12 -out pkey.pem -nodes -clcerts

Now that we have our SSL files in the proper format, we can build our ClientContextFactory object that will be used by Twisted to initiate a connection to the APNS servers:

class APNSClientContextFactory(ClientContextFactory):
    def __init__(self):
        self.ctx = SSL.Context(SSL.SSLv3_METHOD)
        self.ctx.use_certificate_file(APNS_SSL_CERTIFICATE_FILE)
        self.ctx.use_privatekey_file(APNS_SSL_PRIVATE_KEY_FILE)
 
def getContext(self):
    return self.ctx

We’ll also need a ClientFactory object that will be used to build the Protocol object whenever a connection is established to a server:

class APNSClientFactory(ClientFactory):
    def buildProtocol(self, addr):
        print "Connected to APNS Server %s:%u" % (addr.host, addr.port)
        return APNSProtocol()
 
    def clientConnectionLost(self, connector, reason):
        print "Lost connection. Reason: %s" % reason
 
    def clientConnectionFailed(self, connector, reason):
        print "Connection failed. Reason: %s" % reason

Next, we’ll need the actual Protocol object that will format messages and queue them to the server. For APNS, we don’t receive any responses so that half of the protocol goes unused.

class APNSProtocol(Protocol):
    def sendMessage(self, deviceToken, payload):
        # notification messages are binary messages in network order
        # using the following format:
        # <1 byte command> <2 bytes length> <2 bytes length>
 
        fmt = "!cH32sH%ds" % len(payload)
        command = '\x00'
        msg = struct.pack(fmt, command, 32, deviceToken,
                          len(payload), payload)
        self.transport.write(msg)

And finally, we’ll need the main code to kick everything off for the test:

if __name__ == '__main__':
    reactor.connectSSL(APNS_SERVER_HOSTNAME,
                       APNS_SERVER_PORT,
                       APNSClientFactory(),
                       APNSClientContextFactory())
    reactor.run()

From here, the Python and Twisted combination can be easily extended to handle multiple protocols and convert between them as needed. For example, one of the commonly expected use cases of the new push feature will be instant messaging (IM) clients that will need to provide a proxy between the device and the IM servers and the APNS servers in order to notify a device of outstanding messages.

The full Python script containing the above excerpts can be downloaded here:

test-apns-blog

Share and Enjoy:
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google Bookmarks
  • Facebook

iPod installation in the car

May 3rd, 2009 1 comment

Due to recent negative events with XM Radio’s customer service, I no longer have an XM subscription in any of my vehicles. In the truck there is an auxiliary input jack, so feeding music from an iPod is a no-brainer. But in the Corvette, there was no such option. GM never really provided a great solution for it, but luckily the aftermarket came to the rescue.

One of the better options is a device called the Lockpick that intelligently interfaces with the various radio interfaces in GM vehicles. The Corvette Lockpick they provide interfaces directly with the navigation radio in all 6th generation Corvettes so I ordered it to try it out.

Installation turned out to be incredibly simple. The unit ties into the wiring harness that feeds the XM Radio brain. In the convertible model, the brain is hidden behind the waterfall, located between the seats. Removing the waterfall is straight-forward, and then you are left with a simple wire routing problem.

In the end, I decided to locate the Lockpick unit itself on the carpeted area behind the waterfall. I used sticky-tape velcro to keep the unit attached to the carpet, and then ran the wiring harness to the XM Radio unit in order to attach the Y-connector that feeds into the Lockpick itself. The wiring harness that connects to the iPod also has to be routed, and I decided in the end to locate the iPod in the glove box rather than the center console. Access to the center console would require some cutting for a clean installtion look, and plus it tends to get rather hot inside so I was worried about shortening the life of the iPod a bit too much to locate it there.

Luckily the glove box had a space for a switch that wasn’t installed with my option packages, so it made a perfect place to feed the wiring harness. From there, I routed the wiring harness into the dash and then underneath the center console and feed it directly to the waterfall area. The final result is a perfectly clean and hidden installation with no permanent modifications needed to the car.

The Lockpick unit itself works great, although the control system is a quirky. The lower right-hand button in the XM Radio menu activates the iPod. Once activated, the Category up and down buttons control your playlist selection, and then seek forward and back buttons control the current song playing within the playlist. The info button displays the song information as you would expect. It’s quirky, but works extremely well.

Share and Enjoy:
  • Digg
  • StumbleUpon
  • del.icio.us
  • Google Bookmarks
  • Facebook
Categories: Cars, Technology Tags: , ,