Using Websockets To Stream Real Time Accelerometer Data Between iPhone and a Web Page via NodeJS

Several months ago I worked on an in store retail project for a large international brand. The brief was to allow users of their iPhone app to control screens and interact with kiosks as they entered their stores. It also had to live alongside their existing IT and web infrastructure, and the app needed to be compatible with iOS6, so iBeacons (iO7) were out of the question.

After some experimenting it became clear that communicating via websockets would be a super easy way to stream data from the phone, and using NodeJS as the server would be a super easy way of setting up a simple prototype to demo it. This uncomplicated solution also had the benefits of easy portability between platforms, a simple framework new developers could extend and a base for the company’s partners to build upon. All things that were important to the client.

In this tutorial I’m going show you how to build a simple prototype that streams accelerometer data in real time from the iPhone and displays it on a web page using a NodeJS server and websockets. We’ll be using two iOS frameworks that take all the pain out of websocket connections for iOS: SocketRocket and socketIO. We’ll also be setting up a stock standard chat type app on a Node JS server to display the streaming data. I’ll be using NodeJitsu.com because they offer a free trial service and it’s easy to implement websockets on their servers. Go over there now and set up an account, if you don’t know how to set up an app on a NodeJS server, I’ve included everything you need with the project files here at gitHub, just deploy this to your NodeJitsu/NodeJS server and that side of things should work fine. There are a lot of great tutorials on creating NodeJS webapps and I suggest you take a look at them, but I’m not going to be focusing on that aspect in this tutorial. Here’s a great one that takes you through setting up a nodeJS server on your MAC.

So I’ve tried to keep this really simple: All you need to do is set up an account with NodeJitsu, and deploy the nodeJS app I’ve included in example project, change the name of the server in the Xcode project so it’s pointing at your server, shake your iPhone around a bit and it’s done!

Download the finished Xcode project from github here and have a play around, and I’ll go over the main concepts. Make sure you have SystemConfiguration.framework, MobileCoreServices.framwork, libicucore.A.dylib, Security.framework, and CFNetwork.framework all added to your project, and make sure that the class you’re working in conforms to the SocketIODelegate and UIAccelerometerDelegate protocols (see the finished example for more info).

Instantiate an instance SocketIO in the viewDidLoad method and pass your NodeJitsu URL in the connectToHost: method on port 80.

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.socketIO = [[SocketIO alloc] initWithDelegate:self];
    
    // socketIO.useSecure = NO;
    [self.socketIO connectToHost:@"MY_SERVER_NAME.nodejitsu.com" onPort:80];
    
    [self configureAccelerometer];
}

configure the accelerometer and related delegate methods and parse the x, y, and z data to socketIO:

-(void)configureAccelerometer
{
    self.accelerometer = [UIAccelerometer sharedAccelerometer];
    self.accelerometer.updateInterval = 1 / kAccelerometerFrequency;
    self.accelerometer.delegate = self;
}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
    UIAccelerationValue x, y, z;
    x = acceleration.x;
    y = acceleration.y;
    z = acceleration.z;
    
    [self.socketIO sendMessage:[NSString stringWithFormat:@"x:%f, y:%f, z:%f", x, y, z] withAcknowledge:nil];
}

Implement these SocketIO delegate methods, and disconnect in viewWillDisappear method:


- (void) socketIO:(SocketIO *)socket didReceiveEvent:(SocketIOPacket *)packet
{
    SocketIOCallback cb = ^(id argsData) {
        NSDictionary *response = argsData;
        // do something with response
        NSLog(@"packet arrived: %@", response);
    };
    [self.socketIO sendMessage:@"hello back!" withAcknowledge:cb];
}

- (void) socketIO:(SocketIO *)socket failedToConnectWithError:(NSError *)error
{
    NSLog(@"failedToConnectWithError() %@", error);
}


-(void)viewWillDisappear:(BOOL)animated
{
    self.socketIO.delegate = nil;
    [self.socketIO disconnect];
}

SocketIO combined with SocketRocket really take the pain out of communicating with websockets on iOS. Take a look at the SocketIO.h file, you’ll see it exposes several other useful methods: sendJSON and sendEvent. We could optimize this example more to speed up the comms, but the thing I like about it is the simplicity. The stream used in this tutorial was quick enough for instantaneous response from the in store screen to play games and create unique interactions with users.

One comment

Leave a Reply

Your email address will not be published. Required fields are marked *