From 79913334bb51dd7d0ee9992ff8f4bf248cccee05 Mon Sep 17 00:00:00 2001 From: Erick Hitter <services@ethitter.com> Date: Sat, 27 Aug 2016 17:19:59 -0700 Subject: [PATCH] Rewrite as single API endoint, ensuring lock is always disconnected before request completes Resolves issue where lock would remain connected, blocking subsequent requests (and those from the official apps) until the node server was restarted. --- server.js | 255 ++++++++++++++++++++++++------------------------------ 1 file changed, 113 insertions(+), 142 deletions(-) diff --git a/server.js b/server.js index 0f0ea19..b8de4e8 100755 --- a/server.js +++ b/server.js @@ -1,153 +1,124 @@ 'use strict'; -var augustctl = require('./index'); -var express = require('express'); -var morgan = require('morgan'); -var await = require('asyncawait/await'); -var async = require('asyncawait/async'); -var config = require(process.env.AUGUSTCTL_CONFIG || './config.json'); -var serverConfig = require(process.env.AUGUSTCTL_SERVER_CONFIG || './server-config.json'); - -var DEBUG = process.env.NODE_ENV !== 'production'; -var address = serverConfig.address || 'localhost'; -var port = serverConfig.port || 3000; - -var app = express(); -app.use(morgan(DEBUG ? 'dev' : 'combined')); - -var ret = {'status': -1, 'ret': '', 'msg': ''}; - -app.get('/api/unlock/:lock_name', function(req, res) { - var lock = app.get('lock' + req.params.lock_name); - if (!lock) { - res.sendStatus(503); - return; - } - - -var execStatus = async(function() { - - var status = await(lock.status()); - - if(status == 'locked') - { - - var cmd = await(lock.forceUnlock()); - ret['msg'] = 'Command completed. Disconnected.'; - ret['status'] = 0; - ret['ret'] = 'unlocked'; - console.log('Released unlock request'); - - } - else - { - ret['status'] = 1; - ret['msg'] = 'Lock is already unlocked'; - res.json(ret); - - } - - lock.disconnect(); - res.json(ret); -}); - - lock.connect().then(function(){ - - var exec = execStatus(); - - }).finally(function(){ - console.log('Finally'); - }); - -}); - - -app.get('/api/lock/:lock_name', function(req, res) { - var lock = app.get('lock' + req.params.lock_name); - if (!lock) { - res.sendStatus(503); - return; - } - - - var execLock = async(function() { - var status = await(lock.status()); - - if(status == 'unlocked') - { +var augustctl = require( './index' ); +var express = require( 'express' ); +var morgan = require( 'morgan' ); +var await = require( 'asyncawait/await' ); +var async = require( 'asyncawait/async' ); - var cmd = await(lock.forceLock()); - ret['msg'] = 'Command completed. Disconnected.'; - ret['status'] = 0; - ret['ret'] = 'locked'; - console.log('Released lock request'); +var config = require( process.env.AUGUSTCTL_CONFIG || './config.json' ); +var serverConfig = require( process.env.AUGUSTCTL_SERVER_CONFIG || './server-config.json' ); - } - else - { - ret['status'] = 1; - ret['msg'] = 'Lock is already locked'; - - } - - res.json(ret); - lock.disconnect(); -}); - - lock.connect().then(function(){ - - var status = execLock(); - - }).finally(function(){ - console.log('Finally'); - }); - -}); - - -app.get('/api/status/:lock_name', function(req, res){ - var lock = app.get('lock' + req.params.lock_name); - if(!lock) { - res.sendStatus(503); - return; - } - - var execStatus = async(function() { - var status = await(lock.status()); - ret['ret'] = status; - ret['status'] = 0; - ret['msg'] = 'Command completed.'; - - console.log('Disconnecting'); - lock.disconnect(); - - console.log('Returning'); - res.json(ret); - }); - - - lock.connect().then(function() { - var status = execStatus(); - - }).finally(function() { - console.log('Finally'); - }); - - -}); - -Object.keys(config).forEach( function( lockName ) { - var lockConfig = config[lockName]; +var DEBUG = process.env.NODE_ENV !== 'production'; +var address = serverConfig.address || 'localhost'; +var port = serverConfig.port || 3000; - augustctl.scan(lockConfig.lockUuid).then(function (peripheral) { +var app = express(); +app.use( morgan( DEBUG ? 'dev' : 'combined' ) ); + +// Default return arguments +var ret = { + 'status': -1, + 'ret': '', + 'msg': '' +}; + +// Endpoint to perform all lock actions +app.get( '/api/:lock_action/:lock_name', function( req, res ) { + // Parse allowed request arguments + var action = req.params.lock_action, + allowedActions = [ 'unlock', 'lock', 'status' ]; + if ( -1 === allowedActions.indexOf( action ) ) { + res.sendStatus( 400 ); + return; + } + + var lock = app.get( 'lock' + req.params.lock_name ); + if ( ! lock ) { + res.sendStatus( 400 ); + return; + } + + // Suspendable functions to interact with lock based on requested action + if ( 'status' === action ) { + // Checks lock's state and returns it + var actionFunction = async( function() { + var status = await( lock.status() ), + statusInt = -1; + + if ( 'locked' === status ) { + statusInt = 0; + } else if ( 'unlocked' === status ) { + statusInt = 1; + } + + ret.ret = status; + ret.status = statusInt; + ret.msg = "Status checked successfully."; + + lock.disconnect(); + res.json( ret ); + } ); + } else { + // Locks or unlocks a requested lock, if not already in that state + var actionFunction = async( function() { + var status = await( lock.status() ); + + if ( 'lock' === action && 'unlocked' === status ) { + var cmd = await( lock.forceLock() ); + + ret.ret = 'locked'; + ret.status = 0; + ret.msg = 'Locked as requested.'; + } else if ( 'unlock' === action && 'locked' === status ) { + var cmd = await( lock.forceUnlock() ); + + ret.ret = 'unlocked'; + ret.status = 1; + ret.msg = 'Unlocked as requested.'; + } else { + var statusInt = -1; + + if ( 'locked' === status ) { + statusInt = 0; + } else if ( 'unlocked' === status ) { + statusInt = 1; + } + + ret.ret = status; + ret.status = statusInt; + ret.msg = "No change made. Lock was already '" + status + "'."; + } + + lock.disconnect(); + res.json( ret ); + } ); + } + + // Perform requested action + lock.connect().then( actionFunction ).catch( function( err ) { + console.error( err ); + lock.disconnect(); + res.sendStatus( 500 ); + } ); +} ); + +// Parse lock configurations +Object.keys( config ).forEach( function( lockName ) { + var lockConfig = config[ lockName ]; + + augustctl.scan( lockConfig.lockUuid ).then( function( peripheral ) { var lock = new augustctl.Lock( peripheral, lockConfig.offlineKey, lockConfig.offlineKeyOffset ); + app.set('lock' + lockName, lock); - }); -}); -var server = app.listen(port, address, function() { - console.log('Listening at %j', server.address()); -}); + } ); +} ); + +// Start Express server +var server = app.listen( port, address, function() { + console.log( 'Listening at %j', server.address() ); +} ); -- GitLab