diff --git a/src/bonescript.js b/src/bonescript.js index 5f25a27c..bc2e06a0 100644 --- a/src/bonescript.js +++ b/src/bonescript.js @@ -37,7 +37,13 @@ function _onSocketIOLoaded(host, port, socketio) { if (typeof host == 'undefined') host = '___INSERT_HOST___'; if (typeof port == 'undefined') port = 80; if (typeof socketio == 'undefined' && typeof io != 'undefined') socketio = io; - var socket = socketio.connect('http://' + host + ':' + port); + var socket; + if (typeof host == 'string') + socket = socketio('http://' + host + ':' + port); + else + socket = socketio('___INSERT_HOST___', { + port: port + }); socket.on('require', getRequireData); socket.on('bonescript', _seqcall); socket.on('connect', _bonescript.on.connect); @@ -83,6 +89,7 @@ function _onSocketIOLoaded(host, port, socketio) { ' if(callback) {\n' + ' _bonescript._callbacks[_bonescript._seqnum] = callback;\n' + ' calldata.seq = _bonescript._seqnum;\n' + + ' calldata.length = callback.length;\n' + ' _bonescript._seqnum++;\n' + ' }\n' + ' socket.emit("' + m.module + '$' + m.data[x].name + '", calldata);\n' + @@ -102,14 +109,17 @@ function _onSocketIOLoaded(host, port, socketio) { function _seqcall(data) { if ((typeof data.seq != 'number') || (typeof _bonescript._callbacks[data.seq] != 'function')) throw "Invalid callback message received: " + JSON.stringify(data); - _bonescript._callbacks[data.seq](data); + if (_bonescript._callbacks[data.seq].length == 1) + _bonescript._callbacks[data.seq](data); + else + _bonescript._callbacks[data.seq](data.err, data.resp); if (data.oneshot) delete _bonescript._callbacks[data.seq]; } // Require must be synchronous to be able to return data structures and // functions and therefore cannot call socket.io. All exported modules must // be exported ahead of time. -function myrequire(module) { +var myrequire = function (module) { if (typeof _bonescript == 'undefined') throw 'No BoneScript modules are not currently available'; if (typeof _bonescript.modules[module] == 'undefined') diff --git a/src/hw_mainline.js b/src/hw_mainline.js index 28f3ca8b..25544b01 100644 --- a/src/hw_mainline.js +++ b/src/hw_mainline.js @@ -62,17 +62,29 @@ var readPinMux = function (pin, mode, callback) { if (err) { mode.err = 'readPinctrl error: ' + err; if (debug) winston.debug(mode.err); - callback(mode); + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(mode); + } else + callback(mode.err, data); } mode = parse.modeFromPinctrl(data, muxRegOffset, 0x44e10800, mode); - callback(mode); + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(mode); + } else + callback(null, mode); }; var tryPinctrl = function (exists) { if (exists) { fs.readFile(pinctrlFile, 'utf8', readPinctrl); } else { if (debug) winston.debug('getPinMode(' + pin.key + '): no valid mux data'); - callback(mode); + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(mode); + } else + callback('readPinMux error: no valid mux data', mode); } }; if (callback) { @@ -223,7 +235,11 @@ var readGPIOValue = function (pin, resp, callback) { winston.error(resp.err); } resp.value = parseInt(data, 2); - callback(resp); + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else + callback(resp.err, resp.value); }; fs.readFile(gpioFile, readFile); return (true); @@ -259,7 +275,11 @@ var readAIN = function (pin, resp, callback) { winston.error(resp.err); } resp.value = parseInt(data, 10) / maxValue; - callback(resp); + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else + callback(resp.err, resp.value); }; fs.readFile(ainFile, readFile); return (resp); @@ -337,7 +357,7 @@ var writePWMFreqAndValue = function (pin, pwm, freq, value, resp, callback) { else tryAgain = false; callback(null); //async.until requires an err first format callback & - } else { //if there is an error iteration stops, so neglect the error if EACCES thrown + } else { //if there is an error iteration stops, so neglect the error if EACCES thrown tryAgain = false; callback(ex2); } diff --git a/src/hw_simulator.js b/src/hw_simulator.js index b74bd897..00328e82 100644 --- a/src/hw_simulator.js +++ b/src/hw_simulator.js @@ -29,7 +29,10 @@ var readGPIODirection = function (n, gpio) { var readPinMux = function (pin, mode, callback) { winston.info('readPinMux(' + [pin.key] + ')'); if (callback) { - callback(mode); + if (callback.length == 1) + callback(mode); + else + callback(null, mode); } return (mode); }; @@ -60,7 +63,11 @@ var writeGPIOValue = function (pin, value, callback) { var readGPIOValue = function (pin, resp, callback) { winston.info('readGPIOValue(' + [pin.key] + ')'); if (callback) { - callback(0); + resp.value = 0; + if (callback.length == 1) + callback(resp); + else + callback(null, resp.value); return (true); } resp.value = 0; @@ -76,7 +83,10 @@ var readAIN = function (pin, resp, callback) { winston.info('readAIN(' + [pin.key] + ')'); resp.value = 0; if (callback) { - callback(resp); + if (callback.length == 1) + callback(resp); + else + callback(null, resp.value); } return (resp); }; diff --git a/src/index.js b/src/index.js index 65eb54a7..91415583 100644 --- a/src/index.js +++ b/src/index.js @@ -148,10 +148,16 @@ f.pinMode = function (pin, direction, mux, pullup, slew, callback) { ) { var err = 'pinMode only supports ANALOG_OUTPUT for PWM pins: ' + pin.key; winston.info(err); - if (callback) callback({ - value: false, - err: err - }); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback({ + value: false, + err: err + }); + } else + callback(err, false); + } return (false); } direction = g.OUTPUT; @@ -182,7 +188,13 @@ f.pinMode = function (pin, direction, mux, pullup, slew, callback) { if (typeof resp.err == 'undefined') { gpio[n] = true; } - if (callback) callback(resp); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else + callback(resp.err, resp.value); + } return (resp.value); } @@ -200,7 +212,13 @@ f.pinMode = function (pin, direction, mux, pullup, slew, callback) { resp.value = false; winston.info(resp.err); delete gpio[n]; - if (callback) callback(resp); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else + callback(resp.err, resp.value); + } return (resp.value); } } @@ -220,7 +238,13 @@ f.pinMode = function (pin, direction, mux, pullup, slew, callback) { delete gpio[n]; } - if (callback) callback(resp); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else + callback(resp.err, resp.value); + } return (resp.value); }; f.pinMode.args = ['pin', 'direction', 'mux', 'pullup', 'slew', 'callback']; @@ -272,8 +296,11 @@ f.digitalRead = function (pin, callback) { } function analogCallback(x) { - x = analogValue(x); - callback(x); + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(analogValue(x)); + } else + callback(x.err, analogValue(x).value); } function analogValue(x) { @@ -283,6 +310,7 @@ f.digitalRead = function (pin, callback) { } else { x.value = g.LOW; } + return x; } return (resp.value); @@ -380,7 +408,16 @@ f.attachInterrupt = function (pin, handler, mode, callback) { if (!epoll.exists) { resp.err = 'attachInterrupt: requires Epoll module'; if (debug) winston.debug(resp.err); - if (callback) callback(resp); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else { + var err = resp.err; + delete resp.err; + callback(err, resp); + } + } return (resp.attached); } @@ -390,7 +427,16 @@ f.attachInterrupt = function (pin, handler, mode, callback) { if (debug) winston.debug(resp.err); resp.attached = false; resp.configured = false; - if (callback) callback(resp); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else { + var err = resp.err; + delete resp.err; + callback(err, resp); + } + } return (resp); } @@ -400,7 +446,16 @@ f.attachInterrupt = function (pin, handler, mode, callback) { if (debug) winston.debug(resp.err); resp.attached = false; resp.configured = true; - if (callback) callback(resp); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else { + var err = resp.err; + delete resp.err; + callback(err, resp); + } + } return (resp.attached); } @@ -418,7 +473,16 @@ f.attachInterrupt = function (pin, handler, mode, callback) { else m.output = { handler: handler }; - if (m.output && (typeof callback == 'function')) callback(m); + if (m.output && (typeof callback == 'function')) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(m); + } else { + var err = m.err; + delete m.err; + callback(err, m); + } + } }; try { @@ -431,7 +495,16 @@ f.attachInterrupt = function (pin, handler, mode, callback) { resp.err = 'attachInterrupt: GPIO input file not opened: ' + ex; if (debug) winston.debug(resp.err); } - if (callback) callback(resp); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(resp); + } else { + var err = resp.err; + delete resp.err; + callback(err, resp); + } + } return (resp.attached); }; f.attachInterrupt.args = ['pin', 'handler', 'mode', 'callback']; @@ -441,18 +514,36 @@ f.detachInterrupt = function (pin, callback) { if (debug) winston.debug('detachInterrupt(' + [pin.key] + ');'); var n = pin.gpio; if (typeof gpio[n] == 'undefined' || typeof gpioInt[n] == 'undefined') { - if (callback) callback({ - 'pin': pin, - 'detached': false - }); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback({ + 'pin': pin, + 'detached': false + }); + } else + callback(true, { + 'pin': pin, + 'detached': false + }); + } return (false); } gpioInt[n].epoll.remove(gpioInt[n].valuefd); delete gpioInt[n]; - if (callback) callback({ - 'pin': pin, - 'detached': true - }); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback({ + 'pin': pin, + 'detached': true + }); + } else + callback(null, { + 'pin': pin, + 'detached': true + }); + } return (true); }; f.detachInterrupt.args = ['pin', 'callback']; @@ -524,7 +615,13 @@ f.getEeproms = function (callback) { if (eeproms == {}) { if (debug) winston.debug('No valid EEPROM contents found'); } - if (callback) callback(eeproms); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(eeproms); + } else + callback(eeproms == {} ? 'No valid EEPROM contents found' : null, eeproms); + } return (eeproms); }; f.getEeproms.args = ['callback']; @@ -537,7 +634,11 @@ f.readTextFile = function (filename, callback) { 'data': data }); }; - fs.readFile(filename, 'ascii', cb); + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + fs.readFile(filename, 'ascii', cb); + } else + fs.readFile(filename, 'ascii', callback); } else { return fs.readFileSync(filename, 'ascii'); } @@ -580,16 +681,28 @@ f.getPlatform = function (callback) { platform.os.freemem = os.freemem(); platform.os.networkInterfaces = os.networkInterfaces(); platform = hw.readPlatform(platform); - if (callback) callback(platform); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback(platform); + } else + callback(null, platform); + } return (platform); }; f.getPlatform.args = ['callback']; f.echo = function (data, callback) { winston.info(data); - if (callback) callback({ - 'data': data - }); + if (callback) { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback({ + 'data': data + }); + } else + callback(null, data); + } return (data); }; f.echo.args = ['data', 'callback']; @@ -599,11 +712,20 @@ f.setDate = function (date, callback) { function dateResponse(error, stdout, stderr) { if (typeof callback != 'function') return; - else callback({ - 'error': error, - 'stdout': stdout, - 'stderr': stderr - }); + else { + if (callback.length == 1) { + winston.warning("single argument callbacks will be deprecated.please use node-style error-first callbacks: callback(err,response)"); + callback({ + 'error': error, + 'stdout': stdout, + 'stderr': stderr + }); + } else + callback({ + 'error': error, + 'stderr': stderr + }, stdout); + } } }; f.setDate.args = ['date', 'callback']; diff --git a/src/socket_handlers.js b/src/socket_handlers.js index 2c8f2439..82574c76 100644 --- a/src/socket_handlers.js +++ b/src/socket_handlers.js @@ -69,13 +69,28 @@ var addSocketListeners = function (server, serverEmitter) { if (debug) winston.debug('Sending message "bonescript": ' + JSON.stringify(resp)); socket.emit('bonescript', resp); }; + var myCallback_nodestyle = function (err, resp) { + if (debug) winston.debug(name + ' replied to ' + JSON.stringify(m) + ' with ' + JSON.stringify(resp)); + if (typeof m.seq == 'undefined') return; + // TODO: consider setting 'oneshot' + if (debug) winston.debug('Sending message "bonescript": ' + JSON.stringify(resp)); + socket.emit('bonescript', { + err: err, + resp: resp, + seq: m.seq + }); + }; try { var callargs = []; for (var arg in b[name].args) { var argname = b[name].args[arg]; if (argname == 'callback') { - if (typeof m.seq == 'number') callargs.push(myCallback); - else callargs.push(null); + if (typeof m.seq == 'number') { + if (m.length == 1) + callargs.push(myCallback); + else + callargs.push(myCallback_nodestyle); + } else callargs.push(null); } else if (typeof m[argname] != 'undefined') { callargs.push(m[argname]); } else { diff --git a/test/test-rpc.js b/test/test-rpc.js index 3474be39..6b8fd905 100644 --- a/test/test-rpc.js +++ b/test/test-rpc.js @@ -6,20 +6,223 @@ exports.setUp = function (callback) { server.serverStart(8000, process.cwd(), mycb); function mycb(emitter) { - serverEmitter = emitter; - bonescript.startClient('127.0.0.1', 8000, callback); + callback(); } }; -exports.testRPC1 = function (test) { - test.expect(1); - test.doesNotThrow(function () { - console.log(bonescript); +exports.testRPC_callbacks = function (test) { + test.expect(16); + + bonescript.startClient('127.0.0.1', 8000, getPlatformTest_oldstyle); + + function getPlatformTest_oldstyle() { var b = bonescript.require('bonescript'); b.getPlatform(function (platform) { + console.log("***getPlatformTest_oldstyle***"); + console.log(platform); console.log('Name: ' + platform.name); console.log('Version: ' + platform.bonescript); + getPlatformTest_nodestyle(platform); }); - }); - test.done(); -}; \ No newline at end of file + } + + function getPlatformTest_nodestyle(platform_) { + console.log('here'); + var b = bonescript.require('bonescript'); + b.getPlatform(function (err, platform) { + console.log("***getPlatformTest_nodestyle***"); + console.log(platform); + console.log('Name: ' + platform.name); + console.log('Version: ' + platform.bonescript); + test.equals(platform.name, platform_.name); + test.equals(platform.bonescript, platform_.bonescript); + pinModeTest_oldstyle(); + }); + } + + function pinModeTest_oldstyle() { + var b = bonescript.require('bonescript'); + b.pinMode("P8_13", b.OUTPUT, 7, 'pullup', 'fast', printStatus); + + function printStatus(x) { + console.log("***pinModeTest_oldstyle***"); + console.log('value = ' + x.value); + console.log('err = ' + x.err); + pinModeTest_nodestyle(x); + } + } + + function pinModeTest_nodestyle(x) { + var b = bonescript.require('bonescript'); + b.pinMode("P8_13", b.OUTPUT, 7, 'pullup', 'fast', printStatus); + + function printStatus(err, value) { + console.log("***pinModeTest_nodestyle***"); + console.log('value = ' + value); + console.log('err = ' + err); + test.equals(x.err, err); + test.equals(x.value, value); + getPinModeTest_oldstyle(); + } + } + + function getPinModeTest_oldstyle() { + var b = bonescript.require('bonescript'); + b.getPinMode("P8_13", printPinMux); + + function printPinMux(x) { + console.log("***getPinModeTest_oldstyle***"); + console.log('mux = ' + x.mux); + console.log('pullup = ' + x.pullup); + console.log('slew = ' + x.slew); + console.log('options = ' + x.options.join(',')); + console.log('err = ' + x.err); + getPinModeTest_nodestyle(x) + } + } + + function getPinModeTest_nodestyle(x) { + var b = bonescript.require('bonescript'); + b.getPinMode("P8_13", printPinMux); + + function printPinMux(err, resp) { + console.log("***getPinModeTest_nodestyle***"); + console.log('mux = ' + resp.mux); + console.log('pullup = ' + resp.pullup); + console.log('slew = ' + resp.slew); + console.log('options = ' + resp.options.join(',')); + console.log('err = ' + resp.err); + test.equals(x.mux, resp.mux); + test.equals(x.pullup, resp.pullup); + test.equals(x.slew, resp.slew); + test.equals(x.options.join(','), resp.options.join(',')); + digitalWriteTest(); + } + } + + function digitalWriteTest() { + var b = bonescript.require('bonescript'); + b.digitalWrite('USR0', b.HIGH, printErr); + + function printErr(x) { + console.log("***digitalWriteTest***"); + console.log('err = ' + x.err); + test.ok(true); + digitalReadTest_oldstyle(); + } + } + + function digitalReadTest_oldstyle() { + var b = bonescript.require('bonescript'); + b.digitalRead('P8_19', printStatus); + + function printStatus(x) { + console.log("***digitalReadTest_oldstyle***"); + console.log('x.value = ' + x.value); + console.log('x.err = ' + x.err); + digitalReadTest_nodestyle(x) + } + } + + function digitalReadTest_nodestyle(x) { + var b = bonescript.require('bonescript'); + b.digitalRead('P8_19', printStatus); + + function printStatus(err, value) { + console.log("***digitalReadTest_nodestyle***"); + console.log('x.value = ' + value); + console.log('x.err = ' + err); + test.equals(x.value, value); + analogWriteTest() + } + } + + + function analogWriteTest() { + var b = bonescript.require('bonescript'); + b.analogWrite('P9_14', 0.7, 2000, printJSON); + + function printJSON(x) { + console.log("***analogWriteTest***"); + console.log(JSON.stringify(x)); + test.ok(true); + analogReadTest_oldstyle(); + + } + } + + function analogReadTest_oldstyle() { + var b = bonescript.require('bonescript'); + b.analogRead('P9_36', printStatus); + + function printStatus(x) { + console.log("***analogReadTest_oldstyle***"); + console.log('x.value = ' + x.value); + console.log('x.err = ' + x.err); + analogReadTest_nodestyle(x); + } + } + + function analogReadTest_nodestyle(x) { + var b = bonescript.require('bonescript'); + b.analogRead('P9_36', printStatus); + + function printStatus(err, value) { + console.log("***analogReadTest_nodestyle***"); + console.log('x.value = ' + value); + console.log('x.err = ' + err); + test.equals(x.value, value); + attachInterruptTest_oldstyle() + } + } + + function attachInterruptTest_oldstyle() { + var b = bonescript.require('bonescript'); + b.attachInterrupt('P8_19', true, b.CHANGE, interruptCallback); + + function interruptCallback(x) { + console.log("***attachInterruptTest_oldstyle***"); + console.log(JSON.stringify(x)); + attachInterruptTest_nodestyle(x) + } + } + + function attachInterruptTest_nodestyle(x) { + var b = bonescript.require('bonescript'); + b.attachInterrupt('P8_19', true, b.CHANGE, interruptCallback); + + function interruptCallback(err, resp) { + console.log("***attachInterruptTest_nodestyle***"); + console.log(JSON.stringify(resp)); + test.equals(x.err, err); + test.equals(x.pin.name, resp.pin.name); + readTextFileTest_oldstyle(); + } + } + + function readTextFileTest_oldstyle() { + var b = bonescript.require('bonescript'); + b.readTextFile('/etc/fstab', printStatus); + + function printStatus(x) { + console.log("***readTextFileTest_oldstyle***"); + console.log('x.data = ' + x.data); + console.log('x.err = ' + x.err); + readTextFileTest_nodestyle(x); + } + } + + function readTextFileTest_nodestyle(x) { + var b = bonescript.require('bonescript'); + b.readTextFile('/etc/fstab', printStatus); + + function printStatus(err, data) { + console.log("***readTextFileTest_nodestyle***"); + console.log('x.data = ' + data); + console.log('x.err = ' + err); + test.equals(x.data, data); + test.equals(x.err, err); + test.done(); + } + } +} \ No newline at end of file