Make disconnect detection more robust

@DubbyTT's addition of error handling addressed a major reason why it was hard to handle disconnections. These changes address some of the situations that I discovered come up when working on my own similar changes:

* It's easy to get duplicate intervals firing, depending on what triggered the error. Make sure we clear the interval timer before setting up another.
* A spurious error is thrown in roomRegister when we close an existing WebSocket. This should be ignored since we're about to reconnect.
* Sometimes it takes an extraordinarily long time for the WebSocket to notice there's a problem. Provide a failsafe 2 minute timeout.

What follows is a very simple automatic reconnect example that doesn't require a watchdog.

    var Bot    = require('ttapi');
    var AUTH   = 'xxxxxxxxxxxxxxxxxxxxxxxx';
    var USERID = 'xxxxxxxxxxxxxxxxxxxxxxxx';
    var ROOMID = 'xxxxxxxxxxxxxxxxxxxxxxxx';
    var bot    = new Bot(AUTH, USERID);
    var error  = false;
    
    var connect = function (roomid) {
      error = false;
      console.log('connect');
      bot.roomRegister(roomid, function (data) {
        console.log('registered = ' + (data.success ? 'true' : 'false'));
      });
    };
    
    var onError = function () {
      if (!error) {
        error = true;
        console.log('onError');
        setTimeout(function () {
          connect(ROOMID);
        }, 5000);
      }
    };
    
    bot
      .on('ready', function (data) {
        console.log('ready');
        connect(ROOMID);
      })
      .on('roomChanged', function (data) {
        console.log('roomChanged', data.room ? data.room.name : 'unknown');
      })
      .on('error', function (data) {
        console.log('error', data);
        onError();
      })
      .on('speak', function (data) {
        if (data.text.match(/^\/hello$/)) {
          bot.speak('Hey! How are you @' + data.name + '?');
        }
      });