From 3ac761817b1ddb0ec354d51d79db4c01bd318368 Mon Sep 17 00:00:00 2001 From: glarue-ol Date: Tue, 11 Jul 2017 11:38:23 +0200 Subject: [PATCH 1/2] Added current monitor --- .gitignore => sensorlab-cli/.gitignore | 0 Gruntfile.js => sensorlab-cli/Gruntfile.js | 0 LICENSE.txt => sensorlab-cli/LICENSE.txt | 0 README.md => sensorlab-cli/README.md | 0 .../THIRD_PARTIES.txt | 0 {bin => sensorlab-cli/bin}/sensorlab-cli | 0 package.json => sensorlab-cli/package.json | 0 .../sensorlab-cli.js | 48 +- sensorlab-collector/.npmignore | 37 + sensorlab-collector/LICENSE.txt | 373 +++++++++ sensorlab-collector/README.md | 24 + sensorlab-collector/package.json | 92 +++ sensorlab-collector/sensorlab-collector.js | 250 ++++++ sensorlab-commands/.eslintrc | 2 + sensorlab-commands/.npmignore | 37 + sensorlab-commands/Gruntfile.js | 25 + sensorlab-commands/LICENSE.txt | 373 +++++++++ sensorlab-commands/README.md | 50 ++ sensorlab-commands/THIRD_PARTIES.txt | 14 + sensorlab-commands/package.json | 95 +++ sensorlab-commands/sensorlab-commands.js | 748 ++++++++++++++++++ 21 files changed, 2167 insertions(+), 1 deletion(-) rename .gitignore => sensorlab-cli/.gitignore (100%) rename Gruntfile.js => sensorlab-cli/Gruntfile.js (100%) rename LICENSE.txt => sensorlab-cli/LICENSE.txt (100%) rename README.md => sensorlab-cli/README.md (100%) rename THIRD_PARTIES.txt => sensorlab-cli/THIRD_PARTIES.txt (100%) rename {bin => sensorlab-cli/bin}/sensorlab-cli (100%) mode change 100755 => 100644 rename package.json => sensorlab-cli/package.json (100%) rename sensorlab-cli.js => sensorlab-cli/sensorlab-cli.js (93%) create mode 100644 sensorlab-collector/.npmignore create mode 100644 sensorlab-collector/LICENSE.txt create mode 100644 sensorlab-collector/README.md create mode 100644 sensorlab-collector/package.json create mode 100644 sensorlab-collector/sensorlab-collector.js create mode 100644 sensorlab-commands/.eslintrc create mode 100644 sensorlab-commands/.npmignore create mode 100644 sensorlab-commands/Gruntfile.js create mode 100644 sensorlab-commands/LICENSE.txt create mode 100644 sensorlab-commands/README.md create mode 100644 sensorlab-commands/THIRD_PARTIES.txt create mode 100644 sensorlab-commands/package.json create mode 100644 sensorlab-commands/sensorlab-commands.js diff --git a/.gitignore b/sensorlab-cli/.gitignore similarity index 100% rename from .gitignore rename to sensorlab-cli/.gitignore diff --git a/Gruntfile.js b/sensorlab-cli/Gruntfile.js similarity index 100% rename from Gruntfile.js rename to sensorlab-cli/Gruntfile.js diff --git a/LICENSE.txt b/sensorlab-cli/LICENSE.txt similarity index 100% rename from LICENSE.txt rename to sensorlab-cli/LICENSE.txt diff --git a/README.md b/sensorlab-cli/README.md similarity index 100% rename from README.md rename to sensorlab-cli/README.md diff --git a/THIRD_PARTIES.txt b/sensorlab-cli/THIRD_PARTIES.txt similarity index 100% rename from THIRD_PARTIES.txt rename to sensorlab-cli/THIRD_PARTIES.txt diff --git a/bin/sensorlab-cli b/sensorlab-cli/bin/sensorlab-cli old mode 100755 new mode 100644 similarity index 100% rename from bin/sensorlab-cli rename to sensorlab-cli/bin/sensorlab-cli diff --git a/package.json b/sensorlab-cli/package.json similarity index 100% rename from package.json rename to sensorlab-cli/package.json diff --git a/sensorlab-cli.js b/sensorlab-cli/sensorlab-cli.js similarity index 93% rename from sensorlab-cli.js rename to sensorlab-cli/sensorlab-cli.js index 1b06df5..a2b5f55 100644 --- a/sensorlab-cli.js +++ b/sensorlab-cli/sensorlab-cli.js @@ -247,6 +247,20 @@ helpers.format.location.status = function(uid, status){ return format; }; +helpers.format.current_monitor = {}; +helpers.format.current_monitor.status = function(uid, status){ + var format; + + format = vorpal.chalk.yellow('observer ' + uid) + + ' State: ' + helpers.format.state(status.state) + + ' Calibre [A]: ' + helpers.format.property(status.calibre) + + ' Sampling Period [s]: ' + helpers.format.property(status.sampling_period) + + ' Mode: ' + helpers.format.property(status.mode) + + ' Measurement channel: ' + helpers.format.property(status.measurement_channel) + + return format; +}; + helpers.format.system = {}; helpers.format.system.status = function(uid, status){ var format; @@ -345,6 +359,13 @@ helpers.output.location.status = function(uids, statuses){ }); }; +helpers.output.current_monitor = {}; +helpers.output.current_monitor.status = function(uids, statuses){ + statuses.forEach(function(status, index){ + vorpal.log(helpers.format.current_monitor.status(uids[index], status)); + }); +}; + helpers.output.system = {}; helpers.output.system.status = function(uids, statuses){ statuses.forEach(function(status, index){ @@ -754,7 +775,7 @@ vorpal .autocomplete({data:helpers.observers.autocomplete}) .action(helpers.vorpal.action.bind(this,'location','start',[])); vorpal - .command('location stop [observers...]', 'stop experiment of supplied list of observers', {}) + .command('location stop [observers...]', 'stop location module of supplied list of observers', {}) .alias('lstop') .autocomplete({data:helpers.observers.autocomplete}) .action(helpers.vorpal.action.bind(this,'location','stop',[])); @@ -765,6 +786,31 @@ vorpal .action(function (args, callback) { helpers.vorpal.action.bind(this,'location','setup',[args.latitude, args.longitude])(args, callback); }); + +/* current monitor commands */ +vorpal + .command('current_monitor status [observers...]', 'require current_monitor status of supplied list of observers', {}) + .alias('cmstatus') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'current_monitor','status',[])); +vorpal + .command('current_monitor start [observers...]', 'start current_monitor module of supplied list of observers', {}) + .alias('cmstart') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'current_monitor','start',[])); +vorpal + .command('current_monitor stop [observers...]', 'stop current_monitor module of supplied list of observers', {}) + .alias('cmstop') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'current_monitor','stop',[])); +vorpal + .command('current_monitor setup [observers...]', 'configure current_monitor modules of supplied list of observers', {}) + .alias('cmsetup') + .autocomplete({data:helpers.observers.autocomplete}) + .action(function (args, callback) { + helpers.vorpal.action.bind(this,'current_monitor','setup',[args.mode, args.calibre, args.measurement_channel])(args, callback); + }); + vorpal .command('system status [observers...]', 'require system status, i.e. version and sync status of supplied list of observers', {}) .alias('sstatus') diff --git a/sensorlab-collector/.npmignore b/sensorlab-collector/.npmignore new file mode 100644 index 0000000..5148e52 --- /dev/null +++ b/sensorlab-collector/.npmignore @@ -0,0 +1,37 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history diff --git a/sensorlab-collector/LICENSE.txt b/sensorlab-collector/LICENSE.txt new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/sensorlab-collector/LICENSE.txt @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/sensorlab-collector/README.md b/sensorlab-collector/README.md new file mode 100644 index 0000000..37c3cf0 --- /dev/null +++ b/sensorlab-collector/README.md @@ -0,0 +1,24 @@ +# sensorlab-collector + +SensorLab2 collector + + +## Brief + +This node module collects logs on a MQTT server and consolidates it + either in a JSON or PCAP file. + +## Installation + +sensorlab-commands is available via NPM: + +```bash + npm install sensorlab-collector --save +``` + +## Usage + + +## License & Copyrights +Mozilla Public License Version 2.0 (MPL-2.0). +Copyright 2016 Orange diff --git a/sensorlab-collector/package.json b/sensorlab-collector/package.json new file mode 100644 index 0000000..72b5d7c --- /dev/null +++ b/sensorlab-collector/package.json @@ -0,0 +1,92 @@ +{ + "_args": [ + [ + { + "raw": "sensorlab-collector@^1.0.0", + "scope": null, + "escapedName": "sensorlab-collector", + "name": "sensorlab-collector", + "rawSpec": "^1.0.0", + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "C:\\Users\\guill\\node_modules\\sensorlab-cli" + ] + ], + "_from": "sensorlab-collector@>=1.0.0 <2.0.0", + "_id": "sensorlab-collector@1.0.0", + "_inCache": true, + "_location": "/sensorlab-collector", + "_nodeVersion": "5.7.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/sensorlab-collector-1.0.0.tgz_1472816676969_0.47111955960281193" + }, + "_npmUser": { + "name": "quentin-ol", + "email": "quentin.lampin@orange.com" + }, + "_npmVersion": "3.7.3", + "_phantomChildren": {}, + "_requested": { + "raw": "sensorlab-collector@^1.0.0", + "scope": null, + "escapedName": "sensorlab-collector", + "name": "sensorlab-collector", + "rawSpec": "^1.0.0", + "spec": ">=1.0.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/sensorlab-cli" + ], + "_resolved": "https://registry.npmjs.org/sensorlab-collector/-/sensorlab-collector-1.0.0.tgz", + "_shasum": "59cc412062ee293a9be3646e03ac709f2731b9d4", + "_shrinkwrap": null, + "_spec": "sensorlab-collector@^1.0.0", + "_where": "C:\\Users\\guill\\node_modules\\sensorlab-cli", + "author": { + "name": "Quentin Lampin", + "email": "quentin.lampin@orange.com" + }, + "dependencies": { + "binary": "^0.3.0", + "debug": "^2.2.0", + "mqtt-q": "^1.1.0", + "q": "^1.4.1", + "sanitize-filename": "^1.6.0" + }, + "description": "collect logs of a sensorlab experiment", + "devDependencies": { + "grunt": "^1.0.1", + "grunt-eslint": "^18.1.0", + "grunt-jsdoc": "^2.1.0" + }, + "directories": {}, + "dist": { + "shasum": "59cc412062ee293a9be3646e03ac709f2731b9d4", + "tarball": "https://registry.npmjs.org/sensorlab-collector/-/sensorlab-collector-1.0.0.tgz" + }, + "gitHead": "14734d68df6ab078123eb8b67d0239f183800679", + "keywords": [ + "sensorlab", + "experiment", + "collector", + "mqtt" + ], + "license": "MPL-2.0", + "main": "sensorlab-collector", + "maintainers": [ + { + "name": "quentin-ol", + "email": "quentin.lampin@orange.com" + } + ], + "name": "sensorlab-collector", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.0.0" +} diff --git a/sensorlab-collector/sensorlab-collector.js b/sensorlab-collector/sensorlab-collector.js new file mode 100644 index 0000000..1d84f5e --- /dev/null +++ b/sensorlab-collector/sensorlab-collector.js @@ -0,0 +1,250 @@ +/** + * + * Sensorlab2 MQTT experiment logs collection module. + * `author` : Quentin Lampin + * `license` : MPL + * `date` : 2016/06/15 + * Copyright 2016 Orange + * + * This module gathers logs pertaining to a Sensorlab experiment. + * Logs are retained in a chronologically sorted buffer + * + */ + +require('events').EventEmitter.prototype._maxListeners = 100; + + +const DEFAULT_RETENTION = 5000; // 5s + +var log = require('debug')('sensorlab-collector'), + mqtt = require('mqtt-q'), + Q = require('q'), + fs = require('fs'), + os = require('os'), + sanitize = require('sanitize-filename'), + binary = require('binary'); + + +/** + * + * @param event + * @param date + * @constructor + */ +function Record(event, date){ + this.event = event; + this.timeout = date; +} +Record.prototype.postpone = function(date){ + this.timeout = date; +}; +Record.prototype.timestamp = function() { + return this.event.timestamp; +}; + +/** + * + * @param {String} address - broker address + * @param {String|Number} port - port on which the MQTT server listens to + * @param {String} experiment - ID of the experiment, i.e. name of the sub-topic in which the JSON feeds from observers is + * made available. + * @param {String} type - type of the log to collect (pcap or json) + * @param {stream.Writable} outputStream - output stream + * @param {Number} retention - retention time in the buffer (milliseconds) + * @constructor + */ +function Collector(address, port, experiment, type, outputStream, retention){ + this.address = address; + this.port = port; + this.experiment = experiment; + this.type = type; + this.retention = retention? retention: DEFAULT_RETENTION; + this.buffer = []; + this.mqttClient = new mqtt.Client(os.hostname+':'+experiment+':'+type, address, port, {clean:false}); + this.outputStream = outputStream ? outputStream : fs.createWriteStream('experiment-' + sanitize(experiment)+'.'+type); + this.outputTimer = undefined; +} + +Collector.prototype.submitPCAP = function(event){ + var now, + fields, + timestamp, + record, + rIndex, + delay, + i; + + // register current date + now = Date.now(); + + /* retrieve timestamp from the PCAP record header */ + fields = binary.parse(event) + .word32lu('timeS') + .word32lu('timeUs') + .word32lu('inclLength') + .word32lu('origLength') + .vars; + + timestamp = fields['timeS'] + Math.pow(10,-6) * fields['timeUs'] + + // create a new record + record = new Record({timestamp: timestamp, pcap: event}, now + this.retention); + log('record input: '+ JSON.stringify(record.event)); + + this.buffer.push(record); + // decreasing order sort: the last element is the oldest + this.buffer.sort(function(record1, record2){return record2.timestamp() - record1.timestamp()}); + // postpone output of records more recent than this: + // find the index of the new record + rIndex = this.buffer.indexOf(record); + // iterate records in decreasing timestamp order + for(i=0; i.js'] + }, + jsdoc: { + dist: { + src: '<%= pkg.name %>.js', + options: { + destination: 'doc' + } + } + }, + }); + + grunt.loadNpmTasks('grunt-eslint'); + grunt.loadNpmTasks('grunt-jsdoc'); + + + grunt.registerTask('test', ['eslint']); + grunt.registerTask('doc', ['jsdoc']); + grunt.registerTask('default', ['eslint']); +}; diff --git a/sensorlab-commands/LICENSE.txt b/sensorlab-commands/LICENSE.txt new file mode 100644 index 0000000..14e2f77 --- /dev/null +++ b/sensorlab-commands/LICENSE.txt @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/sensorlab-commands/README.md b/sensorlab-commands/README.md new file mode 100644 index 0000000..b1c5ed7 --- /dev/null +++ b/sensorlab-commands/README.md @@ -0,0 +1,50 @@ +# sensorlab-nexus + +SensorLab2 commands module + + +## Brief + +This node module builds a set of commands to control a SensorLab observer given its REST API port and host. + +## Installation + +sensorlab-commands is available via NPM: + +```bash + npm install sensorlab-commands --save +``` + +## Usage + +### Using callbacks + +```javascript + var commands; + + commands = require('sensorlab-commands')('observer-X.local', 5555, false); + function onSuccess(status){ + console.log('status: ', status); + } + function onError(error, response, body){ + console.log('error: ', error, ' response: ', response, ' body: ', body); + } + commands.node.status(onSuccess, onError); +``` + +### Using **Q** promises + +```javascript + var commands, + promise; + + commands = require('sensorlab-commands')('observer-X.local', 5555, true); + + promise = commands.node.status(); + promise.then( function(status){ console.log('status: ', status) }); + +``` + +## License & Copyrights +Mozilla Public License Version 2.0 (MPL-2.0). +Copyright 2016 Orange diff --git a/sensorlab-commands/THIRD_PARTIES.txt b/sensorlab-commands/THIRD_PARTIES.txt new file mode 100644 index 0000000..5b6df39 --- /dev/null +++ b/sensorlab-commands/THIRD_PARTIES.txt @@ -0,0 +1,14 @@ +Legal Information +This node module depends on third parties, listed below: + +request +Copyright: Mikeal Rogers +License: Apache License Version 2.0 + +debug +Copyright (c) 2014 TJ Holowaychuk +License: MIT + +Q +Copyright 2009–2015 Kristopher Michael Kowal and contributors +License: MIT diff --git a/sensorlab-commands/package.json b/sensorlab-commands/package.json new file mode 100644 index 0000000..830dca6 --- /dev/null +++ b/sensorlab-commands/package.json @@ -0,0 +1,95 @@ +{ + "_args": [ + [ + { + "raw": "sensorlab-commands@^1.3.0", + "scope": null, + "escapedName": "sensorlab-commands", + "name": "sensorlab-commands", + "rawSpec": "^1.3.0", + "spec": ">=1.3.0 <2.0.0", + "type": "range" + }, + "C:\\Users\\guill\\node_modules\\sensorlab-cli" + ] + ], + "_from": "sensorlab-commands@>=1.3.0 <2.0.0", + "_id": "sensorlab-commands@1.3.0", + "_inCache": true, + "_location": "/sensorlab-commands", + "_nodeVersion": "6.8.1", + "_npmOperationalInternal": { + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/sensorlab-commands-1.3.0.tgz_1481897857153_0.2377455118112266" + }, + "_npmUser": { + "name": "quentin-ol", + "email": "quentin.lampin@orange.com" + }, + "_npmVersion": "3.10.8", + "_phantomChildren": {}, + "_requested": { + "raw": "sensorlab-commands@^1.3.0", + "scope": null, + "escapedName": "sensorlab-commands", + "name": "sensorlab-commands", + "rawSpec": "^1.3.0", + "spec": ">=1.3.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/sensorlab-cli" + ], + "_resolved": "https://registry.npmjs.org/sensorlab-commands/-/sensorlab-commands-1.3.0.tgz", + "_shasum": "7f1b7c9f3e2cfc2346a052fbdd5f0a5bac919a5a", + "_shrinkwrap": null, + "_spec": "sensorlab-commands@^1.3.0", + "_where": "C:\\Users\\guill\\node_modules\\sensorlab-cli", + "author": { + "name": "Quentin Lampin", + "email": "quentin.lampin@orange.com" + }, + "bugs": { + "url": "https://github.com/Orange-OpenSource/sensorlab-commands/issues" + }, + "dependencies": { + "debug": "^2.2.0", + "q": "^1.4.1", + "request": "^2.69.0" + }, + "description": "Sensorlab2 observers command module.", + "devDependencies": { + "grunt": "^0.4.5", + "grunt-eslint": "^18.0.0", + "grunt-jsdoc": "^1.1.0" + }, + "directories": {}, + "dist": { + "shasum": "7f1b7c9f3e2cfc2346a052fbdd5f0a5bac919a5a", + "tarball": "https://registry.npmjs.org/sensorlab-commands/-/sensorlab-commands-1.3.0.tgz" + }, + "gitHead": "9555f37657d37b4f645235f02f1ce021eb318407", + "homepage": "https://github.com/Orange-OpenSource/sensorlab-commands#readme", + "keywords": [ + "sensorlab2", + "command", + "observer" + ], + "license": "MPL-2.0", + "main": "sensorlab-commands.js", + "maintainers": [ + { + "name": "quentin-ol", + "email": "quentin.lampin@orange.com" + } + ], + "name": "sensorlab-commands", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/Orange-OpenSource/sensorlab-commands.git" + }, + "scripts": {}, + "version": "1.3.0" +} diff --git a/sensorlab-commands/sensorlab-commands.js b/sensorlab-commands/sensorlab-commands.js new file mode 100644 index 0000000..2f92af0 --- /dev/null +++ b/sensorlab-commands/sensorlab-commands.js @@ -0,0 +1,748 @@ +/** + * + * Sensorlab2 commands service. + * `author` : Quentin Lampin + * `license` : MPL + * `date` : 2016/03/17 + * Copyright 2016 Orange + * + * returns a commands set to pilot an observer, provided its host and port. + * If the third argument (promise) is set to `true` then commands return `Q` promises. + * Otherwise, commands call supplied callbacks on completion or error (onSuccess, onError) + */ + +/** + * + * @param {String} host - the observer's API host + * @param {(String|Number)}port - the observer's API port + * @param {Boolean} promise - using Q promises + * @returns {*} + */ +var factory = function(host, port, promise){ + 'use strict'; + + /* node modules dependencies */ + var log = require('debug')('sensorlab-commands'), + request = require('request'), + Q = require('q'); + + var partials, + commands, + commandsWithPromises; + + function generic(target, command, onSuccess, onError, parameters) { + var req, + callback; + + req = {}; + + req.url = 'http://' + host + ':' + port + '/'; + if (typeof target === 'string' && target !== '') { + req.url += target + '/'; + } + if (typeof command === 'string') { + req.url += command; + } + + req.method = !parameters ? 'GET' : 'POST'; + + req.formData = parameters ? parameters : undefined; + + callback = function (error, response, body) { + log('command ', req, ' callback with (error: ', error, ' response: ', response, ' body: ', body); + if (!error && response.statusCode == 200) { + onSuccess(JSON.parse(body)); + } else { + onError(error, response, body); + } + }; + log('command: ', req); + request(req, callback); + } + + partials = { + root: generic.bind(null, ''), + node: generic.bind(null, 'node'), + experiment: generic.bind(null, 'experiment'), + location: generic.bind(null, 'location'), + current_monitor: generic.bind(null, 'current_monitor'), + io: generic.bind(null, 'io'), + system: generic.bind(null, 'system') + }; + + commands = { + root: { + /** + * request the observer's status + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + status: function (onSuccess, onError) { + partials.root('status', onSuccess, onError); + } + }, + node: { + /** + * setup the observer's node module + * @param {File} profile + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + setup: function (profile, onSuccess, onError) { + partials.node('setup', onSuccess, onError, {'profile': profile}) + }, + /** + * init the observer's node module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + init: function (onSuccess, onError) { + partials.node('init', onSuccess, onError) + }, + /** + * load a firmware in the observer's node + * @param {String} firmwareId + * @param {File} firmware + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + load: function (firmwareId, firmware, onSuccess, onError) { + partials.node('load', onSuccess, onError, {'firmware_id': firmwareId, 'firmware': firmware}) + }, + /** + * start the observer's node module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + start: function (onSuccess, onError) { + partials.node('start', onSuccess, onError) + }, + /** + * stop the observer's node module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + stop: function (onSuccess, onError) { + partials.node('stop', onSuccess, onError) + }, + /** + * reset the observer's node module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + reset: function (onSuccess, onError) { + partials.node('reset', onSuccess, onError) + }, + /** + * send a message to the observer's node + * @param {(String|Buffer)} message + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + send: function (message, onSuccess, onError) { + partials.node('send', onSuccess, onError, {'message': message}) + }, + /** + * request the observer's node module status + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + status: function (onSuccess, onError) { + partials.node('status', onSuccess, onError) + } + }, + experiment: { + /** + * setup the observer's experiment module + * @param {String} experimentId + * @param {File} behavior + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + setup: function (experimentId, behavior, onSuccess, onError) { + partials.experiment('setup', onSuccess, onError, {'experiment_id': experimentId, 'behavior': behavior}); + }, + /** + * start the observer's experiment module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + start: function (onSuccess, onError) { + partials.experiment('start', onSuccess, onError); + }, + /** + * stop the observer's experiment module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + stop: function (onSuccess, onError) { + partials.experiment('stop', onSuccess, onError); + }, + /** + * reset the observer's experiment module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + reset: function (onSuccess, onError) { + partials.experiment('reset', onSuccess, onError); + }, + /** + * request the observer's experiment module status + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + status: function (onSuccess, onError) { + partials.experiment('status', onSuccess, onError); + } + }, + location: { + /** + * setup the observer's experiment module + * @param {(number|String)} latitude + * @param {(number|String)} longitude + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + setup: function (latitude, longitude, onSuccess, onError) { + partials.location('setup', onSuccess, onError, {'latitude': latitude, 'longitude': longitude}); + }, + /** + * request the observer's location module status + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + status: function (onSuccess, onError) { + partials.location('status', onSuccess, onError); + } + }, + current_monitor: { + /** + * setup the observer's current monitor module + * @param {(number|String)} mode + * @param {(number|String)} calibre + * @param {(number|String)} measurement_channel + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + setup: function (mode, calibre, measurement_channel, onSuccess, onError) { + partials.current_monitor('setup', onSuccess, onError, {'mode': mode, 'calibre': calibre, 'measurement_channel': measurement_channel}); + }, + /** + * request the observer's current monitor module status + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + status: function (onSuccess, onError) { + partials.current_monitor('status', onSuccess, onError); + } + }, + io: { + /** + * setup the observer's experiment module + * @param {(String)} address + * @param {(number|String)} port + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + setup: function (address, port, onSuccess, onError) { + partials.io('setup', onSuccess, onError, { + 'address': address, + 'port': port, + }, onSuccess, onError); + }, + /** + * start the observer's IO module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + start: function (onSuccess, onError) { + partials.io('start', onSuccess, onError); + }, + /** + * stop the observer's IO module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + stop: function (onSuccess, onError) { + partials.io('stop', onSuccess, onError); + }, + /** + * request the observer's IO module status + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + status: function (onSuccess, onError) { + partials.io('status', onSuccess, onError); + } + }, + system: { + /** + * request the observer's system version + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + version: function (onSuccess, onError) { + partials.system('version', onSuccess, onError); + }, + /** + * request the observer's system synchronization details + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + synchronization: function (onSuccess, onError) { + partials.system('synchronization', onSuccess, onError); + }, + /** + * request the observer's system logs + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + log: function (since, onSuccess, onError) { + partials.system('log', onSuccess, onError, {'since': since}); + }, + /** + * request the observer's system status + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + status: function (onSuccess, onError) { + partials.system('status', onSuccess, onError); + } + } + }; + + function onSuccessWithPromise(deferred, status){ + deferred.resolve(status); + } + + function onErrorWithPromise(deferred, error, response, body){ + deferred.reject({error: error, response: response, body: body}); + } + + commandsWithPromises = { + root:{ + /** + * request the observer's status + * @returns {Promise} the request's promise + */ + status: function () { + var deferred; + + deferred = Q.defer(); + commands.root.status( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + } + }, + node: { + /** + * setup the observer's node module + * @param {File} profile + */ + setup: function (profile) { + var deferred; + + deferred = Q.defer(); + commands.node.setup( + profile, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * init the observer's node module + * @returns {Promise} the request's promise + */ + init: function () { + var deferred; + + deferred = Q.defer(); + commands.node.init( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * load a firmware in the observer's node + * @parma {String} firmwareId + * @param {File} firmware + * @returns {Promise} the request's promise + */ + load: function (firmwareId, firmware) { + var deferred; + + deferred = Q.defer(); + commands.node.load( + firmwareId, + firmware, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * start the observer's node module + * @returns {Promise} the request's promise + */ + start: function () { + var deferred; + + deferred = Q.defer(); + commands.node.start( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * stop the observer's node module + * @returns {Promise} the request's promise + */ + stop: function () { + var deferred; + + deferred = Q.defer(); + commands.node.stop( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * reset the observer's node module + * @returns {Promise} the request's promise + */ + reset: function () { + var deferred; + + deferred = Q.defer(); + commands.node.reset( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * send a message to the observer's node + * @param {(String|Buffer)} message + * @returns {Promise} the request's promise + */ + send: function (message) { + var deferred; + + deferred = Q.defer(); + commands.node.send( + message, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's node module status + * @returns {Promise} the request's promise + */ + status: function () { + var deferred; + + deferred = Q.defer(); + commands.node.status( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + } + }, + experiment: { + /** + * setup the observer's experiment module + * @param {String} experimentId + * @param {File} behavior + * @returns {Promise} the request's promise + */ + setup: function (experimentId, behavior) { + var deferred; + + deferred = Q.defer(); + commands.experiment.setup( + experimentId, + behavior, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * start the observer's experiment module + * @returns {Promise} the request's promise + */ + start: function () { + var deferred; + + deferred = Q.defer(); + commands.experiment.start( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * stop the observer's experiment module + * @returns {Promise} the request's promise + */ + stop: function () { + var deferred; + + deferred = Q.defer(); + commands.experiment.stop( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * reset the observer's experiment module + * @returns {Promise} the request's promise + */ + reset: function () { + var deferred; + + deferred = Q.defer(); + commands.experiment.reset( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's experiment module status + * @returns {Promise} the request's promise + */ + status: function () { + var deferred; + + deferred = Q.defer(); + commands.experiment.status( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + } + }, + location: { + /** + * setup the observer's location module + * @param {(number|String)} latitude + * @param {(number|String)} longitude + * @returns {Promise} the request's promise + */ + setup: function (latitude, longitude) { + var deferred; + + deferred = Q.defer(); + commands.location.setup( + latitude, + longitude, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's location module status + * @returns {Promise} the request's promise + */ + status: function () { + var deferred; + + deferred = Q.defer(); + commands.location.status( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + } + }, + current_monitor: { + /** + * setup the observer's current monitor module + * @param {(number|String)} mode + * @param {(number|String)} calibre + * @param {(number|String)} measurement_channel + * @returns {Promise} the request's promise + */ + setup: function (mode, calibre, measurement_channel) { + var deferred; + + deferred = Q.defer(); + commands.current_monitor.setup( + mode, + calibre, + measurement_channel, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's current monitor module status + * @returns {Promise} the request's promise + */ + status: function () { + var deferred; + + deferred = Q.defer(); + commands.current_monitor.status( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + } + }, + io: { + /** + * setup the observer's experiment module + * @param {(String)} address + * @param {(number|String)} port + * @returns {Promise} the request's promise + */ + setup: function (address, port) { + var deferred; + + deferred = Q.defer(); + commands.io.setup( + address, + port, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * start the observer's IO module + * @returns {Promise} the request's promise + */ + start: function () { + var deferred; + + deferred = Q.defer(); + commands.io.start( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * stop the observer's IO module + * @returns {Promise} the request's promise + */ + stop: function () { + var deferred; + + deferred = Q.defer(); + commands.io.stop( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's IO module status + * @returns {Promise} the request's promise + */ + status: function () { + var deferred; + + deferred = Q.defer(); + commands.io.status( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + } + }, + system: { + /** + * request the observer's IO module status + * @returns {Promise} the request's promise + */ + version: function () { + var deferred; + + deferred = Q.defer(); + commands.system.version( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's IO module status + * @returns {Promise} the request's promise + */ + synchronization: function () { + var deferred; + + deferred = Q.defer(); + commands.system.synchronization( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's IO module status + * @param {String} the since string, as in journalctl format + * @returns {Promise} the request's promise + */ + log: function (since) { + var deferred; + + deferred = Q.defer(); + commands.system.log( + since, + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * request the observer's IO module status + * @returns {Promise} the request's promise + */ + status: function () { + var deferred; + + deferred = Q.defer(); + commands.system.status( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + } + } + }; + if(promise){ + return commandsWithPromises; + } else { + return commands; + } + + /** + * @callback onSuccessCallback + * @param {Object} status - status update of the configured module + */ + + /** + * @callback onErrorCallback + * @param {Error} error - request error + * @param {http.IncomingMessage} response - server's response, if any + * @param {(Buffer|String)} body - response body, if any + */ +}; + +module.exports = factory; From 8c71ba3f9cbea3ac0542b5c167dbca6764f98020 Mon Sep 17 00:00:00 2001 From: glarue-ol Date: Fri, 6 Oct 2017 11:23:11 +0200 Subject: [PATCH 2/2] Updated Help for current monitor --- sensorlab-cli/nucleo-lora-profile.tar.gz | Bin 0 -> 2865 bytes sensorlab-cli/package.json | 110 +++- sensorlab-cli/sensorlab-cli - Backup.js | 800 +++++++++++++++++++++++ sensorlab-cli/sensorlab-cli.js | 11 +- sensorlab-commands/sensorlab-commands.js | 48 ++ 5 files changed, 945 insertions(+), 24 deletions(-) create mode 100644 sensorlab-cli/nucleo-lora-profile.tar.gz create mode 100644 sensorlab-cli/sensorlab-cli - Backup.js diff --git a/sensorlab-cli/nucleo-lora-profile.tar.gz b/sensorlab-cli/nucleo-lora-profile.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..dc7c297932511a96d55929178e40f24fbf93bf02 GIT binary patch literal 2865 zcmV-13(oW(iwFP+n8jBB1MOUEZyUK4mD4R6t6%b|=tr)DRyNjF=KTKR+CN*S~s*(Q~BFeOqzVMvYl!s z<(fD)kGcOJF}_%TRh0SRw4zO3PR24XME&#ZiT7TA&vCuDTmP%D*7}Q6!KV#nKij&` z?EU#41&-IP|5ex}{2z{o5BJCWO<9Q#A4B001;Og|cjIOLdyW_Oi1YKMx!OMS_3!=q zcfaXf>-GLjIeE5Ez9-i7wce(BdFu68z4ZH2-C^G1#;TC_4i28%;_0kcXP>5B#{d7G z{g?4yJ?uHb693)EbvyoFk!{?cW^T{W`Fan&_lJv{UbnAvcC8(+w^|xH>#VcRI_s>n zPscXkuK)IzoknM!b@mCG)(2w!UF+Y#Z`k^4)_>9JbHjRK{ax$dz;D=g*R21-`s>!; zu%1|d*ZMc`RY|M7!;H#)d?pOD*RyT7^Voa)qeiF4|@Nvgf)yPo#Gmon{x$P2U&W149n zg?^-c95A_SA|yOW^p!N@uJ%-hRC^{eUwcj?u6@QtsJ%#Ip}kCGj0moin4XR*n6drT z^z=N}L<%EndIqs)BE=z#&0GRsAVSKynSGK4CL1O*GkYpRlTAj2nLTHb$wsD9nzWJEEp%5ct3)WEmpREI{6zo7pEK1THc&*$EaQZz{~} zc@hJcRECJ)y9x4k923d)QsAO0%-AtS-jQb_g#iODq0bS4WgL0)z+{t(47kY9WFwhC z-ZV1VWQhbWX&fLz;5o?4Pq5yui@crG^mJ4MGq;dpzr;Rpix@)$E&}8wIo3N1kvGrG z?2{w{E~&tNVKH!{(no~QOOTiEV7=WGc{{F&^7ay}w~{b}i<_FrUg#n3fMUO>4rXpKOA$fH0C@|J z_2waP$ug52O(W!;2<#Uc0~aP;M2P(ad3z4l+ev|o>zYV@NRfBoVZTHSxTubZASFlM zBEWj{47g;W$%dr@c_$I}3zfiy#g1in08XYMI7(x1l11Ps_rS@_2S89YQ$G}OSf}?=|CqoI2Mp+ExxwHzC2GFJ?gjTT_+C(F0RpvpPxDTz8E<@IiZ`ti8 z&?YB^R{0FtuMGRTvgRn`i*7N+W1f5<{z`4{Z`2v?_BLaB+Rh zZa;-Kc?q=2rO+maL91d3ZHff6D&!KlWU*Bk9)Xit433HroRk4LnmFKO>Vl)x_ko+o zEV}~=PKFE|jZ$zjPQX!zgOhFsj(Rc%ZbDjx$s%YIkD*mEgf@u)T9rD`ro@F-F`of9 z&$sLjDYPkI(5g6vHbn`v%H_}|Cxce`QUW&-TZIuZI4L7=ln3Bs7J{SH1t*yUjwYTD zTzqEP9Wih+rr>ChfRkYgj(Qn5>2q+@QA3)!Nof^E#?U4aL94O=+QdU>6?36Y)PYu| z9s@4EZ`mC)Xj4R?Rbc{c3Q}m5pFx{E4y|&91TJdm-TqGhn}^>%7(f2@-q++UyKT1d zqIUdf|G~ZQ9z9&thPD*qsJ}TF3=|-lkaSu!M0Y2$qDO*MriH58TV<+l(Y_|Ktd3|y@|sZnrYOo2 z6@PQ{pX8M+=;14(3N*_qQP-x-%cCPY$xJz;4Sn@uI2^tt`YmR_Ukm;tsfB)=<-)YH zflSyDW-*!-)|Ah`y`W-*utYDzBRvgWQjfo6R{s9`S$R=o-)d7gp}bi@z6jJ;ac#0h zCr}$$_VjLhOh%++>frK|sDR_VDo|AwJ+W8qLaFuBYemN6e3Ccg@pdf=xufIh!jMg+ zRDo_2cGd`5RrG9oXI3Yws;r9gFrQ@NRBs3yNM!K5KFFN%C}NSfDz*r}EiyWKP}Du^g9ANk93 zBOmK6eUqF}wE$`x650w%nsVjv>jre!rD_MvB{>n~P&BG-slryRad*u)ifoNaQmDBp zUJzcCwVnbR=qP3iwO9+_iuJg2n*{47Sx%edX>)EjY>JxGW09$f$5aiiFY$^K+uw?d zzN(=#vGWOOjr_tL?YS?_5PDujrA}rs&rJssh6%NYKB%Sw*Ywx6^ND?@;;jtT7Svfl zB}7-+$B{f&1un^Fz9y=AU!eN{Kr_IV}P`D$yZj>%iQgA+E` zxggB&q{W4+u zd1)j?>91X(V|rGUR4?E^2F=;A7>oupSsv^T^bQr1W-!w8sBKWif|oo0T3+f40x1!H zhZvP;rqzVl{{8ul`Y#%NeWSiu_AekVn&NH@Syy-GnjS*fZF#JxF*caKh3~AXYNM9e=zjlsCH9(D*$J)0NS(g6o=$loO7d;_oNo0OzYHAp z_1Vmx#%jFNrf<3<6z}xO3e%5MCC|uSF)I$$1J26kdy;JB>aJf&%Ehg^QHPHo_kQyB z+##2TTWhm}uUo)naLn=dGuhqM zbn;Hvw7@BkKbM_zIkA^^j_LN9?3~NN`2hO0{v(o6-`;!9{WM+G^zr2d+>rF&u19Z0 z9o)*qPq&bCQC4(d+A%uKR2;Er>$;)mI0!s|9fkMM^C=~=0LYG^;J{zb^t=8`2a+hPRq$@Ddp&*x+Xso z>ImGbbB12%keljJc`_}EUBc;P(3mNj&(Q!6IV!Vhfe", - "license": "MPL-2.0", + "_resolved": "https://registry.npmjs.org/sensorlab-cli/-/sensorlab-cli-1.3.3.tgz", + "_shasum": "3e38b0cba1ad11c12e2558af48944ef26ba35f66", + "_shrinkwrap": null, + "_spec": "sensorlab-cli", + "_where": "C:\\Users\\guill", + "author": { + "name": "Quentin Lampin", + "email": "quentin.lampin@orange.com" + }, + "bin": { + "sensorlab-cli": "bin/sensorlab-cli" + }, + "bugs": { + "url": "https://github.com/Orange-OpenSource/sensorlab-cli/issues" + }, "dependencies": { "debug": "^2.2.0", "mdns-spawn": "^1.5.0", @@ -30,9 +64,45 @@ "vorpal": "^1.10.10", "vorpal-autocomplete-fs": "0.0.3" }, + "description": "Sensorlab2 observers command line interface.", "devDependencies": { "grunt": "^0.4.5", "grunt-eslint": "^18.0.0", "grunt-jsdoc": "^1.1.0" - } + }, + "directories": { + "bin": "./bin" + }, + "dist": { + "shasum": "3e38b0cba1ad11c12e2558af48944ef26ba35f66", + "tarball": "https://registry.npmjs.org/sensorlab-cli/-/sensorlab-cli-1.3.3.tgz" + }, + "gitHead": "59446f89c9ae2267870d68f1998ecb4b225e3892", + "homepage": "https://github.com/Orange-OpenSource/sensorlab-cli#readme", + "keywords": [ + "sensorlab2", + "cli", + "command", + "line", + "interface", + "observer" + ], + "license": "MPL-2.0", + "main": "sensorlab-cli.js", + "maintainers": [ + { + "name": "quentin-ol", + "email": "quentin.lampin@orange.com" + } + ], + "name": "sensorlab-cli", + "optionalDependencies": {}, + "preferGlobal": true, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/Orange-OpenSource/sensorlab-cli.git" + }, + "scripts": {}, + "version": "1.3.3" } diff --git a/sensorlab-cli/sensorlab-cli - Backup.js b/sensorlab-cli/sensorlab-cli - Backup.js new file mode 100644 index 0000000..1b06df5 --- /dev/null +++ b/sensorlab-cli/sensorlab-cli - Backup.js @@ -0,0 +1,800 @@ +/** + * + * Sensorlab2 Command Line Interface. + * `author` : Quentin Lampin + * `license` : MPL + * `date` : 2016/04/11 + * Copyright 2016 Orange + * + * Interactive command line interface to pilot SensorLab observers + */ + + +var mdns = require('mdns-spawn'), + vorpal = require('vorpal')(), + vorpalAutocompleteFs = require('vorpal-autocomplete-fs'), + commands = require('sensorlab-commands'), + Collector = require('sensorlab-collector'), + fs = require('fs'), + Q = require('q'), + version = require('./package.json').version; + +var observers, + collectors, + browser, + helpers; + + +helpers = {}; +helpers.services = {}; +helpers.services.register = function(observers, service){ + var match, uid; + + if ( !!(match = /observer-(\d+)/.exec(service.service_name)) ) { + uid = match[1]; + observers[uid] = { 'uid': uid, 'commands': commands(service.service_name+'.local', '5555', true) }; + } +}; +helpers.services.deregister = function(observers, service){ + var match, uid; + + if ( !!(match = /observer-(\d+)/.exec(service.service_name)) ) { + uid = match[1]; + delete observers[uid]; + } +}; + +helpers.observers = {}; +helpers.observers.autocomplete = function(){ + return Object.keys(observers).map(String); +}; + +helpers.comprehension = {}; +helpers.comprehension.included = function(lowerBound, upperBound, value){ + return (Number(value) >= Number(lowerBound) && Number(value) <= Number(upperBound)); +}; + + +helpers.format = {}; +helpers.format.error = {}; +helpers.format.error.comprehension = function(passed){ + return vorpal.chalk.red('error: comprehension must be of form .., received ' + passed); +}; +helpers.format.error.observerNotFound = function(passed){ + return vorpal.chalk.red('error: unknown observer id: ' + passed); +}; +helpers.format.error.observerNotSupplied = function(){ + return vorpal.chalk.red('error: no observer ID supplied'); +}; + +helpers.format.error.unknownExperimentCollector = function(experiment_id, collectors){ + var collectorsList; + + collectorsList = Object.keys(collectors).sort(); + return vorpal.chalk.red('error: unknown experiment collector: '+experiment_id+'. list of known collectors: ' + + collectorsList.join(', ')); +}; + +helpers.format.error.commandError = function(errorSummary){ + if(errorSummary.body){ + return vorpal.chalk.red(errorSummary.body); + } else { + return vorpal.chalk.red(errorSummary.error); + } +}; + +helpers.format.uids = function (uids) { + return uids.join(', '); +}; + +helpers.format.collectors = function(collectors){ + return collectors.join(', '); +}; + +helpers.format.state = function(state){ + switch (state) { + case 'ready': + case 'connected': + case 'online': + return vorpal.chalk.blue(state); + break; + case 'running': + return vorpal.chalk.green(state); + break; + case 'halted': + return vorpal.chalk.red(state); + break; + default: + return vorpal.chalk.grey(state); + break; + } +}; + +helpers.format.property = function(property){ + switch(property){ + case 'none': + case 'undefined': + return vorpal.chalk.grey(property); + break; + default: + return vorpal.chalk.blue(property); + break; + } +}; + +helpers.format.observer = {}; +helpers.format.observer.status = function(status){ + var output = vorpal.chalk.yellow('observer ' + status.node.id); + output += ' :: node: '; + if(status.node.hardware.id !== 'undefined'){ + output += vorpal.chalk.green(status.node.hardware.id); + }else{ + output += vorpal.chalk.red('not configured'); + } + output += ' :: experiment: '; + + if(status.node.experiment == undefined){ + output += vorpal.chalk.red('not configured'); + }else{ + switch (status.node.experiment.state){ + case 'ready': + output += vorpal.chalk.blue(status.node.experiment.id); + break; + case 'running': + output += vorpal.chalk.green(status.node.experiment.id); + output += ' remaining: ' + helpers.format.property(status.node.experiment.remaining); + break; + case 'halted': + output += vorpal.chalk.red(status.node.experiment.id); + break; + default: + output += vorpal.chalk.grey(status.node.experiment.id); + break; + } + } + output += ' :: I/Os: '; + if(status.io.address == 'undefined'){ + output += vorpal.chalk.red('not configured'); + } else { + switch(status.io.state){ + case 'disconnected': + output += ' '+ vorpal.chalk.red(status.io.address+':'+status.io.port + '(not connected)'); + break; + case 'ready': + output += ' ' + vorpal.chalk.yellow(status.io.address+':'+status.io.port + '(ready)'); + break; + case 'connecting': + output += ' ' + vorpal.chalk.blue(status.io.address+':'+status.io.port + '(connecting)'); + break; + case 'connected': + output += ' ' + vorpal.chalk.green(status.io.address+':'+status.io.port + '(connected)'); + break; + } + } + return output; +}; + +helpers.format.node = {}; +helpers.format.node.status = function(status){ + return vorpal.chalk.yellow('observer ' + status.id)+ + ' (' + vorpal.chalk.green(status.hardware.id) + ') ' + + 'state: ' + helpers.format.state(status.hardware.state) + + ' firmware: ' + helpers.format.property(status.hardware.firmware) + + ' checksum: ' + helpers.format.property(status.hardware.checksum); +}; + +helpers.format.experiment = {}; +helpers.format.experiment.behavior = +helpers.format.experiment.remaining = +helpers.format.experiment.duration = function(behavior){ + switch(behavior){ + case 'none': + case 'undefined': + return vorpal.chalk.grey(behavior); + break; + default: + return vorpal.chalk.blue(behavior); + break; + } +}; +helpers.format.experiment.status = function(uid, status){ + var format; + + format = vorpal.chalk.yellow('observer ' + uid); + if(status.experiment){ + format += ' id: ' + helpers.format.experiment.behavior(status.experiment.id) + + ' state: ' + helpers.format.state(status.experiment.state); + if(status.experiment.state === 'running'){ + format += ' remaining: ' + helpers.format.property(status.experiment.remaining); + } + format += ' duration: ' + helpers.format.property(status.experiment.duration); + }else{ + format += ' experiment: ' + helpers.format.state('undefined'); + } + return format; +}; + +helpers.format.io = {}; +helpers.format.io.status = function(uid, status){ + var format; + format = vorpal.chalk.yellow('observer ' + uid)+ + ' address: ' + helpers.format.property(status.address) + ':' + helpers.format.property(status.port) + + ' state: ' + helpers.format.state(status.state); + return format; +}; + +helpers.format.location = {}; +helpers.format.location.uncertainty = function(value){ + if(value < 2){ + return vorpal.chalk.green(value); + }else if(value < 10){ + return vorpal.chalk.yellow(value); + }else if(value < 50){ + return vorpal.chalk.red(value); + }else{ + return vorpal.chalk.black(value); + } +}; +helpers.format.location.status = function(uid, status){ + var format; + + format = vorpal.chalk.yellow('observer ' + uid) + + ' state: ' + helpers.format.state(status.state) + + ' position: (' + helpers.format.property(status.latitude) + ',' + helpers.format.property(status.longitude) + ')[' + helpers.format.property(status.altitude) + ']' + + ' uncertainty: (' + helpers.format.location.uncertainty(status.error_estimate_latitude) + ', ' + + helpers.format.location.uncertainty(status.error_estimate_longitude) + ', ' + + helpers.format.location.uncertainty(status.error_estimate_altitude) + ')'; + return format; +}; + +helpers.format.system = {}; +helpers.format.system.status = function(uid, status){ + var format; + + format = vorpal.chalk.yellow('observer ' + uid) + + ' (' + helpers.format.property('v'+status.version) + ') ::' + + ' clock source: ' + helpers.format.property(status.synchronization.source) + + ' clock offset: ' + helpers.format.property(status.synchronization.offset) + + ' (standard deviation: ' + helpers.format.property(status.synchronization.offset_std) + ')'; + return format; +}; + +helpers.format.system.log = function(uid, log){ + var format; + format = ''; + log.log.split('\n').forEach(function(line){ + if(/ERROR/.exec(line)){ + format += vorpal.chalk.red(line) +'\n'; + }else if(/WARNING/.exec(line)){ + format += vorpal.chalk.yellow(line) +'\n'; + }else if(/INFO/.exec(line)){ + format += vorpal.chalk.yellow(line) +'\n'; + }else if(/DEBUG/.exec(line)){ + format += vorpal.chalk.white(line) +'\n'; + }else{ + format += line +'\n'; + } + }); + return format; +}; + +helpers.format.system.synchronization = function(uid, synchronization){ + var format; + format = vorpal.chalk.yellow('observer ' + uid) + + ' clock: ' + helpers.format.property(synchronization['date']) + + ' clock source: ' + helpers.format.property(synchronization['sync_source']) + + ' clock offset: ' + helpers.format.property(synchronization['offset']) + + ' (standard deviation: ' + helpers.format.property(synchronization.offset_std) + ')'; + return format; +}; + +helpers.format.system.version = function(uid, version){ + var format; + format = vorpal.chalk.yellow('observer ' + uid) + + ' version: ' + helpers.format.property(version.version); + return format; +}; + +helpers.output = {}; + +helpers.output.observer = {}; +helpers.output.observer.status = function(uids, statuses){ + statuses.forEach(function(status){ + vorpal.log(helpers.format.observer.status(status)); + }); +}; +helpers.output.root = helpers.output.observer; + +helpers.output.node = {}; +helpers.output.node.status = +helpers.output.node.setup = +helpers.output.node.start = +helpers.output.node.stop = +helpers.output.node.reset = function(uids, statuses){ + statuses.forEach(function(status){ + vorpal.log(helpers.format.node.status(status)); + }); +}; + +helpers.output.experiment = {}; +helpers.output.experiment.status = +helpers.output.experiment.setup = +helpers.output.experiment.start = +helpers.output.experiment.stop = +helpers.output.experiment.reset = function(uids, statuses){ + statuses.forEach(function(status, index){ + vorpal.log(helpers.format.experiment.status(uids[index], status)); + }); +}; + +helpers.output.io = {}; +helpers.output.io.status = +helpers.output.io.setup = +helpers.output.io.start = +helpers.output.io.stop = + function(uids, statuses){ + statuses.forEach(function(status, index){ + vorpal.log(helpers.format.io.status(uids[index], status)); + }); +}; + +helpers.output.location = {}; +helpers.output.location.status = function(uids, statuses){ + statuses.forEach(function(status, index){ + vorpal.log(helpers.format.location.status(uids[index], status)); + }); +}; + +helpers.output.system = {}; +helpers.output.system.status = function(uids, statuses){ + statuses.forEach(function(status, index){ + vorpal.log(helpers.format.system.status(uids[index], status)); + }); +}; + +helpers.output.system.log = function(uids, logs){ + logs.forEach(function(log, index){ + vorpal.log(helpers.format.system.log(uids[index], log)); + }); +}; + +helpers.output.system.version = function(uids, versions){ + versions.forEach(function(version, index){ + vorpal.log(helpers.format.system.version(uids[index], version)); + }); +}; + + +helpers.output.system.synchronization = function(uids, synchronizations){ + synchronizations.forEach(function(synchronization, index){ + vorpal.log(helpers.format.system.synchronization(uids[index], synchronization)); + }); +}; + + +helpers.output.error = {}; +helpers.output.error.commandError = function(errorSummary){ + vorpal.log(helpers.format.error.commandError(errorSummary)); +}; + + +helpers.vorpal = {}; +helpers.vorpal.action = function(target, command, params, args, callback){ + var promises, + uids, + match; + + promises = []; + uids = []; + if(!!args.observers && typeof(args.observers[0]) == 'string' && args.observers[0] === 'all'){ + uids = Object.keys(observers); + }else{ + if(!args.observers){ + vorpal.log(helpers.format.error.observerNotSupplied()); + callback(); + return; + } + args.observers.forEach(function(uid){ + if( typeof(uid) == 'string' && uid.includes('..') ){ + if ( !!(match = /(\d+)\.\.(\d+)/.exec(uid)) ) { + Object.keys(observers) + .filter(helpers.comprehension.included.bind(null, match[1], match[2])) + .reduce(function(_prev, uid){ + uids.push(uid); + }, 0); + } else { + vorpal.log(helpers.format.error.comprehension(uid)); + callback(); + } + } else { + if( uid in observers ){ + uids.push(uid); + } else { + vorpal.log(helpers.format.error.observerNotFound(uid)); + callback(); + } + } + }); + } + uids.forEach(function(uid){ + promises.push( observers[uid].commands[target][command].apply(this, params) ); + }); + Q.all(promises) + .then(helpers.output[target][command].bind(null, uids), helpers.output.error.commandError) + .then(callback); +}; + +helpers.collectors = {}; +helpers.collectors.create = function(broker_address, broker_port, experiment_id, type,callback){ + + collectors[experiment_id] = new Collector(broker_address, broker_port, experiment_id, type); + collectors[experiment_id].start(); + callback(); +}; +helpers.collectors.destroy = function(experiment_id, callback){ + if(collectors[experiment_id]){ + collectors[experiment_id].end(); + delete collectors[experiment_id]; + callback(); + }else{ + vorpal.log(helpers.format.error.unknownExperimentCollector(experiment_id, collectors)); + callback(); + } +}; + +helpers.collectors.autocomplete = function(){ + return Object.keys(collectors).map(String); +}; + +observers = {}; +collectors = {}; + +browser = new mdns(); +browser.addEvent('serviceUp', helpers.services.register.bind(null, observers)); +browser.addEvent('serviceDown', helpers.services.deregister.bind(null, observers)); +browser.start(); + +/* store history */ +vorpal.history('sensorlab-cli'); + +/* usage memo */ +vorpal + .command('memo', 'workflow reminder', {}) + .alias('workflow') + .action(function(args, callback){ + vorpal.log( + vorpal.chalk.yellow( + vorpal.chalk.bold( + " # 0. Prerequisites \n" + ) + )+ + " ------------------------------------------------------------------------- \n"+ + " - query the observers state: \n"+ + " > "+vorpal.chalk.cyan("observer status ")+" \n"+ + " \n"+ + " - if an experiment is already running, contact the owner. \n"+ + " DO NOT STOP a RUNNING EXPERIMENT UNLESS IT'S YOURS! \n"+ + " \n"+ + " - stop any existing experiment and reset the experiment handler: \n"+ + " > "+vorpal.chalk.cyan("experiment stop ")+" \n"+ + " > "+vorpal.chalk.cyan("experiment reset ")+" \n"+ + " \n"+ + " - query the I/Os state: \n"+ + " > "+vorpal.chalk.cyan("io status ")+" \n"+ + " \n"+ + " - if the MQTT broker address and port are not defined, provide them: \n"+ + " > "+vorpal.chalk.cyan("io setup ")+" \n"+ + " \n"+ + " - query the I/Os state: \n"+ + " > "+vorpal.chalk.cyan("io status ")+" \n"+ + " \n"+ + " - if the I/O handler is connected jump to section "+vorpal.chalk.yellow("#1")+" \n"+ + " - otherwise initiate the connection: \n"+ + " > "+vorpal.chalk.cyan("io start ")+" \n"+ + " \n"+ + " - verify that the change is in effect: \n"+ + " > "+vorpal.chalk.cyan("io status ")+" \n"+ + " \n"+ + vorpal.chalk.yellow( + vorpal.chalk.bold( + " # 1. interfacing the observer with the device \n" + ) + )+ + " ------------------------------------------------------------------------- \n"+ + " - query the current device interface: \n"+ + " > "+vorpal.chalk.cyan("node status ")+" \n"+ + " \n"+ + " - if the interface matches the current device, jump to section "+vorpal.chalk.yellow("#2")+" \n"+ + " - otherwise upload the interface: \n"+ + " > "+vorpal.chalk.cyan("node setup ")+" \n"+ + " \n"+ + " - verify that the change is in effect: \n"+ + " > "+vorpal.chalk.cyan("node status ")+" \n"+ + " \n"+ + vorpal.chalk.yellow( + vorpal.chalk.bold(" # 2. upload the experiment \n" + ) + )+ + " ------------------------------------------------------------------------- \n"+ + " - upload the experiment profile: \n"+ + " > "+vorpal.chalk.cyan("experiment setup ")+" \n"+ + " \n"+ + " - query the experiment handler status: \n"+ + " > "+vorpal.chalk.cyan("experiment status ")+" \n"+ + " \n"+ + vorpal.chalk.yellow( + vorpal.chalk.bold(" # 3. setup an experiment collector (optional) \n" + ) + )+ + " ------------------------------------------------------------------------- \n"+ + " - setup a collector for the log trace you're interested in (json,pcap): \n"+ + " > "+vorpal.chalk.cyan("collector setup
")+" \n"+ + " \n"+ + vorpal.chalk.yellow( + vorpal.chalk.bold(" # 4. start the experiment \n" + ) + )+ + " ------------------------------------------------------------------------- \n"+ + " - start the experiment scheduler: \n"+ + " > "+vorpal.chalk.cyan("experiment start ")+" \n"+ + " \n"+ + " - query the experiment handler status \n"+ + " > "+vorpal.chalk.cyan("experiment status ")+" \n"+ + " \n"+ + vorpal.chalk.yellow( + vorpal.chalk.bold(" # 5. clean-up \n" + ) + )+ + " ------------------------------------------------------------------------- \n"+ + " - at the end of the experiment, discard collectors: \n"+ + " > "+vorpal.chalk.cyan("collector stop ")+" \n"+ + " \n"+ + " ------------------------------------------------------------------------- \n"+ + + vorpal.chalk.yellow( + vorpal.chalk.bold(" # 6. submitting an issue \n" + ) + )+ + " \n"+ + " ------------------------------------------------------------------------- \n"+ + " - collect the version numbers of the observers and your CLI client: \n"+ + " > "+vorpal.chalk.cyan("system version ")+" \n"+ + " > "+vorpal.chalk.cyan("version")+" \n"+ + " \n"+ + " - query the observer system logs: \n"+ + " > "+vorpal.chalk.cyan("system log ")+" \n"+ + " \n"+ + " - if system logs reports any connectivity issue related \n"+ + " report to the network administrator \n"+ + " \n"+ + " - if system logs reports a runtime exception, report with a github issue \n"+ + " "+vorpal.chalk.cyan("TRIM ANY NON-LOCAL ADDRESS FROM LOGS BEFORE REPORTING")+" \n"+ + " \n"+ + " - else send your description of the issue along with logs to your local \n"+ + " Sensorlab admin \n"+ + " ------------------------------------------------------------------------- \n"+ + vorpal.chalk.yellow( + vorpal.chalk.bold(" # 42. friendly reminder \n" + ) + )+ + " ------------------------------------------------------------------------- \n"+ + " - this is a PoC, not some kind of Apollo-grade software \n"+ + " - even Apollo-grade mission can go wrong, Apollo 13 anyone? \n"+ + " - Nobody has voodoo powers, provide detailed analysis of your \n"+ + " issues in a github issue. \n"+ + " - Refrain from sending mails containing exclamation marks, urgent sign \n"+ + " superlative, etc. It's offensive. \n"+ + " \n"+ + " ------------------------------------------------------------------------- \n" + + ); + callback(); + }); + +vorpal + .command('observers', 'list of observers', {}) + .alias('list') + .action(function (args, callback) { + var uids; + uids = Object.keys(observers).sort(); + vorpal.log(helpers.format.uids(uids)); + callback(); + }); + +vorpal + .command('collectors', 'list of collectors', {}) + .alias('clist') + .action(function (args, callback) { + var cols; + cols = Object.keys(collectors).sort(); + vorpal.log(helpers.format.collectors(cols)); + callback(); + }); + +vorpal + .command('observer status [observers...]', 'require status of supplied list of observers', {}) + .alias('ostatus') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'root','status',[])); + +/* node commands */ +vorpal + .command('node status [observers...]', 'require node status of supplied list of observers', {}) + .alias('nstatus') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'node','status',[])); +vorpal + .command('node init [observers...]', 'init devices of supplied list of observers', {}) + .alias('ninit') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'node','init',[])); +vorpal + .command('node start [observers...]', 'start devices of supplied list of observers', {}) + .alias('nstart') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'node','start',[])); +vorpal + .command('node stop [observers...]', 'stop devices of supplied list of observers', {}) + .alias('nstop') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'node','stop',[])); +vorpal + .command('node load [observers...]', 'load firmware to devices of supplied list of observers', {}) + .alias('nload') + .autocomplete(vorpalAutocompleteFs()) + .action(function (args, callback) { + try { + helpers.vorpal.action.bind(this,'node','load',[args.firmware_id, fs.createReadStream(args.firmware)])(args, callback); + } catch (exception) { + vorpal.log(vorpal.chalk.red('cannot read firmware ['+args.firmware+']\n. Error: '+exception)); + callback(); + } + }); +vorpal + .command('node setup [observers...]', 'configure node modules of supplied list of observers', {}) + .alias('nsetup') + .autocomplete(vorpalAutocompleteFs()) + .action(function (args, callback) { + try { + helpers.vorpal.action.bind(this,'node','setup',[fs.createReadStream(args.profile)])(args, callback); + } catch (exception) { + vorpal.log(vorpal.chalk.red('cannot read profile ['+args.profile+']\n. Error: '+exception)); + callback(); + } + }); + +vorpal + .command('node reset [observers...]', 'reset node modules of supplied list of observers', {}) + .alias('nreset') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'node','reset',[])); + +/* experiment commands */ +vorpal + .command('experiment status [observers...]', 'require experiment status of supplied list of observers', {}) + .alias('estatus') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'experiment','status',[])); +vorpal + .command('experiment reset [observers...]', 'reset experiment of supplied list of observers', {}) + .alias('ereset') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'experiment','reset',[])); +vorpal + .command('experiment start [observers...]', 'start experiments of supplied list of observers', {}) + .alias('estart') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'experiment','start',[])); +vorpal + .command('experiment stop [observers...]', 'stop experiment of supplied list of observers', {}) + .alias('estop') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'experiment','stop',[])); +vorpal + .command('experiment setup [observers...]', 'configure experiment modules of supplied list of observers', {}) + .alias('esetup') + .autocomplete(vorpalAutocompleteFs()) + .action(function (args, callback) { + try{ + helpers.vorpal.action.bind(this,'experiment','setup',[args.experiment_id, fs.createReadStream(args.behavior)])(args, callback); + } catch (exception) { + vorpal.log(vorpal.chalk.red('cannot read behavior ['+args.behavior+']\n. Error: '+exception)); + callback(); + } + }); + +/* I/O commands */ +vorpal + .command('io status [observers...]', 'require io status of supplied list of observers', {}) + .alias('iostatus') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'io','status',[])); +vorpal + .command('io start [observers...]', 'start experiments of supplied list of observers', {}) + .alias('iostart') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'io','start',[])); +vorpal + .command('io stop [observers...]', 'stop experiment of supplied list of observers', {}) + .alias('iostop') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'io','stop',[])); +vorpal + .command('io setup
[observers...]', 'configure io modules of supplied list of observers', {}) + .alias('iosetup') + .autocomplete({data:helpers.observers.autocomplete}) + .action(function (args, callback) { + helpers.vorpal.action.bind(this,'io','setup',[args.address, args.port])(args, callback); + }); +/* Collector commands */ +vorpal + .command('collector setup
', 'setup log collection', {}) + .alias('csetup') + .help(function(args){}) + .action(function (args, callback){ + helpers.collectors.create(args.address, args.port, args.experiment_id, args.type, callback); + }); +vorpal + .command('collector stop ', 'stop log collection', {}) + .alias('cstop') + .autocomplete({data:helpers.collectors.autocomplete}) + .action(function (args, callback){ + helpers.collectors.destroy(args.experiment_id, callback); + }); + +/* location commands */ +vorpal + .command('location status [observers...]', 'require location status of supplied list of observers', {}) + .alias('lstatus') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'location','status',[])); +vorpal + .command('location start [observers...]', 'start location module of supplied list of observers', {}) + .alias('lstart') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'location','start',[])); +vorpal + .command('location stop [observers...]', 'stop experiment of supplied list of observers', {}) + .alias('lstop') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'location','stop',[])); +vorpal + .command('location setup [observers...]', 'configure io modules of supplied list of observers', {}) + .alias('lsetup') + .autocomplete({data:helpers.observers.autocomplete}) + .action(function (args, callback) { + helpers.vorpal.action.bind(this,'location','setup',[args.latitude, args.longitude])(args, callback); + }); +vorpal + .command('system status [observers...]', 'require system status, i.e. version and sync status of supplied list of observers', {}) + .alias('sstatus') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'system','status',[])); +vorpal + .command(' system version [observers...]', 'require system version of supplied list of observers', {}) + .alias('sversion') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'system','version',[])); +vorpal + .command('system synchronization [observers...]', 'require synchronization status of supplied list of observers', {}) + .alias('ssync') + .autocomplete({data:helpers.observers.autocomplete}) + .action(helpers.vorpal.action.bind(this,'system','synchronization',[])); +vorpal + .command('system log [observers...]', 'require logs of supplied list of observers', {}) + .alias('slog') + .autocomplete({data:helpers.observers.autocomplete}) + .action(function (args, callback) { + helpers.vorpal.action.bind(this,'system','log',[args.since])(args, callback); + }); +vorpal + .command('version', 'returns sensorlab-cli version',{}) + .action(function (args, callback) { + vorpal.log('version: ' + version); + callback(); + }); + + +vorpal + .delimiter(vorpal.chalk.green('>')) + .show(); diff --git a/sensorlab-cli/sensorlab-cli.js b/sensorlab-cli/sensorlab-cli.js index a2b5f55..d3e6008 100644 --- a/sensorlab-cli/sensorlab-cli.js +++ b/sensorlab-cli/sensorlab-cli.js @@ -360,6 +360,9 @@ helpers.output.location.status = function(uids, statuses){ }; helpers.output.current_monitor = {}; +helpers.output.current_monitor.setup = +helpers.output.current_monitor.start = +helpers.output.current_monitor.stop = helpers.output.current_monitor.status = function(uids, statuses){ statuses.forEach(function(status, index){ vorpal.log(helpers.format.current_monitor.status(uids[index], status)); @@ -789,22 +792,22 @@ vorpal /* current monitor commands */ vorpal - .command('current_monitor status [observers...]', 'require current_monitor status of supplied list of observers', {}) + .command('current_monitor status [observers...]', 'require current_monitor status of supplied list of observers\n', {}) .alias('cmstatus') .autocomplete({data:helpers.observers.autocomplete}) .action(helpers.vorpal.action.bind(this,'current_monitor','status',[])); vorpal - .command('current_monitor start [observers...]', 'start current_monitor module of supplied list of observers', {}) + .command('current_monitor start [observers...]', 'start current_monitor module of supplied list of observers\n', {}) .alias('cmstart') .autocomplete({data:helpers.observers.autocomplete}) .action(helpers.vorpal.action.bind(this,'current_monitor','start',[])); vorpal - .command('current_monitor stop [observers...]', 'stop current_monitor module of supplied list of observers', {}) + .command('current_monitor stop [observers...]', 'stop current_monitor module of supplied list of observers\n', {}) .alias('cmstop') .autocomplete({data:helpers.observers.autocomplete}) .action(helpers.vorpal.action.bind(this,'current_monitor','stop',[])); vorpal - .command('current_monitor setup [observers...]', 'configure current_monitor modules of supplied list of observers', {}) + .command('current_monitor setup [observers...]', 'configure current monitor modules of supplied list of observers\nArguments:\n *mode:\n - 0 : Oscilloscope 1,7kHz - current\n - 1 : Low frequency 0,9 Hz - Current\n - 2 : Oscilloscope 0,9 kHz - current, shunt voltage, bus voltage\n *calibre: \n Two calibres available on "terminal channel" (0.05 and 0.1 [A]) and three calibres available on "USB channel" (0.05, 0.1 and 0.2 [A]). Change in calibre must also be done on the board by soldering the appropriate solder-jumps\n *measurement_channel:\n 0 : Terminal\n 1 : USB ', {}) .alias('cmsetup') .autocomplete({data:helpers.observers.autocomplete}) .action(function (args, callback) { diff --git a/sensorlab-commands/sensorlab-commands.js b/sensorlab-commands/sensorlab-commands.js index 2f92af0..479ec27 100644 --- a/sensorlab-commands/sensorlab-commands.js +++ b/sensorlab-commands/sensorlab-commands.js @@ -234,6 +234,22 @@ var factory = function(host, port, promise){ */ status: function (onSuccess, onError) { partials.current_monitor('status', onSuccess, onError); + }, + /** + * start the observer's current monitor module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + start: function (onSuccess, onError) { + partials.current_monitor('start', onSuccess, onError); + }, + /** + * stop the observer's current monitor module + * @param {onSuccessCallback} onSuccess + * @param {onErrorCallback} onError + */ + stop: function (onSuccess, onError) { + partials.current_monitor('stop', onSuccess, onError); } }, io: { @@ -588,10 +604,12 @@ var factory = function(host, port, promise){ ); return deferred.promise; }, + /** * request the observer's current monitor module status * @returns {Promise} the request's promise */ + status: function () { var deferred; @@ -601,6 +619,36 @@ var factory = function(host, port, promise){ onErrorWithPromise.bind(null, deferred) ); return deferred.promise; + }, + + /** + * start the observer's current monitor module + * @returns {Promise} the request's promise + */ + + start: function () { + var deferred; + + deferred = Q.defer(); + commands.current_monitor.start( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; + }, + /** + * stop the observer's current monitor module + * @returns {Promise} the request's promise + */ + stop: function () { + var deferred; + + deferred = Q.defer(); + commands.current_monitor.stop( + onSuccessWithPromise.bind(null, deferred), + onErrorWithPromise.bind(null, deferred) + ); + return deferred.promise; } }, io: {