Remote Control Using HTML5 WebSockets

Here´s a little sunday PoC I wanted to share with you: remote control a presentation using HTML5 web sockets.

Ingredients:

Client-side

The client (index.html) is just some vanilla JavaScript, setting up the Swipe component, wire up events, handle progress bar and setup the WebSocket. Here´s a go-thrue of the main function.

function init() {
    // Setting up the Swipe component
    slider = new Swipe(document.getElementById('slider'), {
        continuous: false,
        draggable: true,
        callback: swipeCallback
    });
    slider.setup();

    // Gets the progress element
    progress = document.getElementById('progress');

    // Wiring up events so we can navigate using left/right keyboard kyes
    wireKeyDownEvents();

    // Updates the progress bar
    handleProgress();

    // WebSocket support test
    if (tests.websocket) {
        // Setting up the WebSocket
        setupWebSocket();
    } else {
        console.log('Your browser doesn´t support WebSocket!');
        return;
    }
}

And the websocket is configured as follows:

function setupWebSocket() {
    // Instantiate a new WebSocket, passing in server url.
    // A handshake is made and a connection is established.
    ws = new WebSocket(url);

    // Captures errors
    ws.onerror = function (e) {
        // Set progress bar background to red to indicate an
        // connection error.
        progress.style.backgroundColor = '#FF2424';
        console.log('Problem with connection: ' + e.message);
    };
    // When connection opens
    ws.onopen = function () {
        console.log('Client connected');
    };
    // Captures messages from the server.
    // In this case the position of the slide.
    ws.onmessage = function (e) {
        // If current position isn´t equal to position sent 
        // from server, we update it.
        if (e.data != slider.getPos()) {
            slider.slide(e.data);
        }
    };
    // When connection closes
    ws.onclose = function () {
        console.log('Closed connection');
    };
}

When a slide change this will happen:

function swipeCallback(index, elem) {
    // Send position to server
    ws.send(index);
    // Update progress bar
    updateProgress();
}

Server-side

The socket server itself is a generic handler (SwipeSocketServer.ashx). It takes the http context and verifies if the incoming request is an socket request.

public void ProcessRequest(HttpContext context)
{
    // Is this a web socket request?
    if (context.IsWebSocketRequest)
    {
        // Yes, so accept this request and pass in our custom handler.
        context.AcceptWebSocketRequest(new SwipeWebSocketHandler());
    }
}

If so the request will be processed further to a custom web socket handler that inherits Microsoft.Web.Sockets.WebSocketHandler. It mimics a lot of the client-side implementation.

public class SwipeWebSocketHandler : WebSocketHandler
{
    ///<summary>
    /// Holds the connected clients.
    /// </summary>
    private static WebSocketCollection _clients = new WebSocketCollection();

    ///<summary>
    /// When a client connection opens.
    /// </summary>
    public override void OnOpen()
    {
        // Add client.
        _clients.Add(this);
    }

    ///<summary>
    /// When receiving a message from a client.
    /// </summary>
    /// <param name="message"></param>
    public override void OnMessage(string message)
    {
        // Broadcast message to all connected clients.
        _clients.Broadcast(message);
    }

    ///<summary>
    /// When a client connection closes.
    /// </summary>
    public override void OnClose()
    {
        // Remove client.
        _clients.Remove(this);
    }
}

Finally

Well that´s pretty much everything. Download the Visual Studio solution using the button below. To run this you´ll need a Windows 8 machine or higher. Windows 7 has some low level issues with http.sys (an update Microsoft, please). If you´re in the same position as me – running on Windows 7 – you can test it for example on Microsoft Azure. If the progressbar turns black everything is fine. If red there´s some issues with the socket connection. Now connect your computer, phone and tablet and slide forward and backwards to see it moves synchronously on all devices.

Working with sockets are fun and can be very useful in situations where you need: full-duplex, low latency, real-time communication etc. Next time holding a presentation, run this project on your computer and connect it to a projector. Open the application on your phone and use it as remote control. 🙂

Download