web socket fun part 1

So I’ve been playing with websockets (because I’m a geek). I made this demo using socket.io to link an iPad’s movements to your desktop. It shows only the beginning of what’s possible with websockets. If anyone wants more of an explanation, feel free to contact me. I don’t think its worth putting up on github, but I’ll post the code below. Just visit the demo below on your phone and your desktop and watch the magic. Or better yet, call your friend in China and have him visit with his iphone and watch in real time as he moves his phone!

Demo

If you don’t know how to set up a server to run websockets – follow this tutorial.

Now that you have an environment set up with nodeJS and socket.io installed (npm install socket.io). Let’s make a server:

Create a new file called server.js in the www or public web directory and place the following code inside:

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on('connection', function (socket) {

  socket.on('mobile', function(data) {
  	io.sockets.emit('desktop', { accelerometer: data });
  });

});

It loads in some libraries. Routes you to the correct index file. Then listens for an event called “mobile” and upon receipt of the data it just fires it straight back out to all the other socket connections.

Now we need a client script to handle all the events. Let’s create the index file where we will serve our js file to control websockets to the client.

Copy and paste:

<html>
	<head>
		<title>Accelerometer</title>
		<meta content="width=device-width,user-scalable=yes" name="viewport">
		<style>
			body {
				font-family: helvetica, arial, sans serif;
				background-color: black;
			}

			#content {
				width: 250px;
				margin: 0 auto;
				margin-top: 200px;
				position: relative;
				left: -75px;
			}
			/*#sphere {
				position: absolute;
				width: 50px;
				height: 50px;
				border-radius: 50px;
				-webkit-radius: 50px;
				background-color: blue;
			}*/

			img {
				/*-webkit-transition: -moz-transform 0.3s ease;
		        -moz-transition: -webkit-transform 0.3s ease;
		        -o-transition: -o-transform 0.3s ease;
		        transition: transform 0.3s ease;*/

		        -webkit-transition: all 0.2s ease;
		        -moz-transition: all 0.2s ease;
		        -o-transition: all 0.2s ease;
		        transition: all 0.2s ease;
			}

			/*
			-moz-transform: rotate(720deg);
	        -webkit-transform: rotate(720deg);
	        -o-transform: rotate(720deg);
	        -ms-transform: rotate(720deg);
	        transform: rotate(720deg);
			*/
		</style>
		<script type=text/javascript src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
	</head>
	<body>
		<div id="content">
			<h1>Accelerometer Javascript Test</h1>
			<div id="imageHolder"></div>
		<div id="sphere" style="top: 0px; left: 0px;"></div>
		<script src="/socket.io/socket.io.js"></script>
        <script>
			// the bay citizen - map data
			// google data blog -
			socket = io.connect('http://107.20.254.40');
			/*socket.on('news', function (data) {
				console.log(data);
				socket.emit('my other event', { my: 'data' });
			});*/
        </script>
        <script>

			var appName = navigator.appCodeName;

			var isiPad = navigator.userAgent.match(/iPad/i) != null;
			var isiPhone = navigator.userAgent.match(/iPhone/i) != null;

			var x,
				y,
				agent = navigator.userAgent;

			var tilt = function(dataArr) {
				x = dataArr[0];
				y = dataArr[1];
			}

			if(isiPad || isiPhone) {
				if (window.DeviceOrientationEvent) {
				    window.addEventListener("deviceorientation", function () {
				        tilt([event.beta, event.gamma]);
				    }, true);
				} else if (window.DeviceMotionEvent) {
				    window.addEventListener('devicemotion', function () {
				        tilt([event.acceleration.x * 2, event.acceleration.y * 2]);
				    }, true);
				} else {
				    window.addEventListener("MozOrientation", function () {
				        tilt([orientation.x * 50, orientation.y * 50]);
				    }, true);
				}

				setInterval(function() {
					socket.emit('mobile', { x: x, y: y, agent: agent });
				}, 100);
			} else {
				console.debug(appName);

				$('#imageHolder').html('<img src="http://futurejesus.com/mobile-accelerometer/ipad.png" />');

				socket.on('desktop', function (data) {

					var xData = Math.round( parseFloat( data.accelerometer.x ) );

					// console.debug(xData);

					/*$('img').css({
						'-moz-transform': 'rotate(' + Math.round( parseFloat( data.accelerometer.x ) ) + 'deg)',
						'-webkit-transform': 'rotate(' + Math.round( parseFloat( data.accelerometer.x ) ) + 'deg)',
						'-o-transform': 'rotate(' + Math.round( parseFloat( data.accelerometer.x ) ) + 'deg)',
						'transform': 'rotate(' + Math.round( parseFloat( data.accelerometer.x ) ) + 'deg)'
					});*/

					$('img').css({
						'-moz-transform': 'rotate(' + xData + 'deg)',
						'-webkit-transform': 'rotate(' + xData + 'deg)',
						'-o-transform': 'rotate(' + xData + 'deg)',
						'transform': 'rotate(' + xData + 'deg)'
					});

				});

			}
		</script>
	</body>
</html>

This script detects if you’re on an iphone or ipad. If you are it sets you up to emit accelerometer data to the node server. If not, it sets you up to receive accelerometer data from the server.

The rest is just interpreting data and moving the ipad image according to tilt angle.

Have fun!

Leave a Reply

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