├── .gitignore ├── .travis.yml ├── LICENSE.md ├── Makefile ├── README.md ├── _config.yml ├── coap-broker-server.js ├── libs ├── coap-broker.js ├── coap-proxy-websocket.js ├── index.js ├── thing.js └── websocket-broker.js ├── package-lock.json ├── package.json ├── templates ├── 101-air-quality-sensor-console-print │ ├── README.md │ ├── esp8266 │ │ └── coap-air-quality.lua │ ├── package.json │ └── server.js ├── 101-air-quality-sensor-text-messaging-twilio │ ├── README.md │ ├── config.json.example │ ├── esp8266 │ │ └── coap-air-quality.lua │ ├── package.json │ └── server.js ├── 102-air-quality-sensor-dropbox │ ├── README.md │ ├── config.access_token.json.example │ ├── config.app.json.example │ ├── esp8266 │ │ └── coap-air-quality.lua │ ├── package.json │ └── server.js ├── 102-air-quality-sensor-email │ ├── README.md │ ├── config.json.example │ ├── esp8266 │ │ └── coap-air-quality.lua │ ├── package-lock.json │ ├── package.json │ ├── server.js │ └── utilities │ │ └── email.js ├── 201-web-of-things-dashboard │ ├── README.md │ ├── esp8266 │ │ └── coap-temperature.lua │ ├── package.json │ ├── server.js │ └── server.proxy.js └── README.md ├── test ├── run ├── test.coap.send.js ├── test.websocket.send.js └── test.websocket.viewer.js └── websocket-broker-server.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | *.swp 11 | *.DS_Store 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # node-waf configuration 23 | .lock-wscript 24 | 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | 28 | # Dependency directory 29 | node_modules 30 | 31 | # Optional npm cache directory 32 | .npm 33 | 34 | # Optional REPL history 35 | .node_repl_history 36 | 37 | # Configuration files 38 | components/configs/*/*.conf 39 | 40 | # Config files 41 | config.*.json 42 | config.json 43 | config*json 44 | 45 | # Templates 46 | templates/*/.git 47 | templates/*/.gitignore 48 | templates/*/iisnode.yml 49 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '4' 4 | after_success: ./node_modules/.bin/codecov 5 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 devify-server contributors 4 | Copyright (c) 2016 Devify, Inc. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TESTS = $(shell find test/test.*.js) 2 | 3 | test: 4 | @./test/run $(TESTS) 5 | 6 | .PHONY: test -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](http://res.cloudinary.com/jollen/image/upload/h_110/v1455862763/devify-logo_rh63vl.png) 2 | 3 | A fast and simple way to write isomorphic Web of Things application servers in the Iot. 4 | 5 | # devify-server 6 | 7 | [![Build Status](https://travis-ci.org/flowchain/devify-server.svg?branch=master)](https://travis-ci.org/flowchain/devify-server) 8 | 9 | **devify-server**, or [*Devify*](https://github.com/DevifyPlatform/devify-server), is a set of IoT device server boilerplate. 10 | 11 | *Devify* is written in 100% JavaScript and designed to be light-weight. It aims to help developers to create IoT application servers, faster. 12 | 13 | ## What's a Devify ? 14 | 15 | Devify is a sub-project of [WoT.City](https://wotcity.com/WoTCity-WhitePaper.pdf) software framework that it proposes a new design software architecture for the development of interoperable Internet of Things (IoT) application server on IoT devices. To begin creating and developing customized such IoT application servers, the Devify provides several boilerplates (project templates) that can be used instantly. 16 | 17 | ## Introduction 18 | 19 | Devify is an open source project to develop a set of boilerplates for getting started with interoperable IoT device servers. It aims to help you developing device server running on IoT devices and using emerging web technologies. 20 | 21 | ## Technology 22 | 23 | Devify itself is a broker server that implements REST-style RPC operations. Moreover, the code size of the Devify is extremely light weight; thus, it can run on laptops, mobile devices, and even resource-constrained devices. 24 | 25 | ## Quickstart 26 | 27 | A cli tool [devify-cli](https://github.com/DevifyPlatform/devify-cli) is available for getting started with *devify*. 28 | 29 | ``` 30 | $ npm install -g devify-cli 31 | $ devify new 32 | $ cd && npm install 33 | $ node coap-broker-server-events.js 34 | ``` 35 | 36 | ## Tutorial 37 | 38 | This section introduces the steps to write a CoAP device server to collaborate with an ESP8266 (NodeMCU) IoT device that the device server will receive data from the ESP8266 device. 39 | 40 | The following instructions show how to connect NodeMCU to your localhost (PC/Notebook) and send ADC data to localhost over CoAP. 41 | 42 | ### Step 1. Get *devify-cli* 43 | 44 | ``` 45 | $ npm install -g devify-cli 46 | ``` 47 | 48 | *devify-cli* a cli app aimed to get you speed up. 49 | 50 | ### Step 2. Create a new project 51 | 52 | ``` 53 | $ devify esp_air_iot 54 | ``` 55 | Create a new *Devify* project by *devify-cli*. *Devify-cli* will automatically create a new folder and download the project template at this folder. The folder name is *esp_air_iot* at this example. 56 | 57 | Please make sure that *git* was installed at your host. 58 | 59 | ### Step 3. Install dependencies 60 | 61 | ``` 62 | $ cd esp_air_iot && npm install 63 | ``` 64 | 65 | *Devify* project template is an isomorphic JavaScript app using Node.js. Please run ```npm install``` to get Node.js modules installed. 66 | 67 | ### Step 4. Start the server 68 | 69 | You need to export the host IP through ```HOST``` environment variable before starting the CoAP server. 70 | 71 | ``` 72 | $ export HOST=192.168.0.100 73 | $ node coap-broker-server-events.js 74 | WoT/CoAP server is listening at coap://192.168.0.100:8000 75 | ``` 76 | The message shows that the server is listening at ```coap://192.168.0.100:8000```. 77 | 78 | ### Step 5. Programing IoT device 79 | 80 | The simplest way to send sensor data to IoT server via CoAP is using NodeMCU and Lua programming language. 81 | 82 | ``` 83 | -- Configure the ESP as a station (client) 84 | wifi.setmode(wifi.STATION) 85 | wifi.sta.config("", "") 86 | wifi.sta.autoconnect(1) 87 | 88 | -- Create a CoAP client 89 | cc = coap.Client() 90 | 91 | -- Make a POST request 92 | uri="coap://192.168.0.100:8000/object/12345678/send" 93 | 94 | -- Setup a timer to send ADC data 95 | tmr.alarm(0, 1000, 1, function() 96 | buf = 97 | "{" .. 98 | "\"quality\":" .. 99 | adc.read(0) .. 100 | "}" 101 | 102 | cc:post(uri, buf) 103 | print(buf) 104 | end) 105 | ``` 106 | 107 | The sample ```coap-broker-server-events.js``` will print messages from IoT devices on the console. Please read [101-air-quality-sensor-console-print](https://github.com/DevifyPlatform/devify-server/tree/master/templates/101-air-quality-sensor-console-print) for getting started. 108 | 109 | ### Step 6. Deploy 110 | 111 | A Devify application server might be installed and run on a cloud-based server, an application processor-based high-performance device or a microcontroller device. The following section introduces how to install a Devify application server on Azure, the cloud-based server. 112 | 113 | ## Deploy: Cloud-Based Server 114 | 115 | [![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://deploy.azure.com/?repository=https://github.com/DevifyPlatform/devify-server) 116 | 117 | Before starting to develop your own IoT server. You may want to have a try. By click the **Deploy to Azure** button, it takes couple minutes to have *devify-server* deployed at Microsoftt Azure web service. The following instructions show how to deploy devify-server, and have a try by using test scripts. 118 | 119 | * Please click above button to deploy this project. 120 | 121 | * Be sure to [Enable Web Sockets](https://azure.microsoft.com/zh-tw/blog/introduction-to-websockets-on-windows-azure-web-sites/) after deploy.azure.com has finished deploying this project. 122 | 123 | * Go to the [Windows Azure Management Console](https://portal.azure.com/) 124 | * Select **App Services** 125 | * Select your web site, and go to the **All settings** page 126 | * Scroll down and select **Application settings** in the GENERAL label 127 | * Scroll down and switch the button of **Web sockets** to **On** 128 | * Click the **Save** icon 129 | 130 | * Use your web site URL to access Devify server. 131 | 132 | * Go to the [Windows Azure Management Console](https://portal.azure.com/) 133 | * Select **App Services** 134 | * Select your web site 135 | * Find **URL** here, for example ```devify-server88de.azurewebsites.net``` 136 | 137 | * Use WebSocket broker server. 138 | 139 | * Open *test/test.websocket.send.js* file 140 | * Modify this line: ```client.connect('ws://localhost:8000/object/5550937980d51931b3000009/send', '');``` to meet your web site URL. For the example above ```client.connect('ws://devify-server88de.azurewebsites.net/object/5550937980d51931b3000009/send', '');``` 141 | * The Devify framework will generate a URI for sending the received messages, use ```ws://devify-server88de.azurewebsites.net/object/5550937980d51931b3000009/viewer``` to receive real-time messages from the server. Please open *test/test.websocket.viewer.js*, and modify the URL string. 142 | * The string ```5550937980d51931b3000009``` is the device ID. You can modify it and give a favor string. 143 | 144 | ## Biolerplates 145 | 146 | 147 | Currently, the Devify provices 5 templates to introduce the usage of *devify-server* open source project. 148 | 149 | * Chapter 1 - [101-air-quality-sensor-console-print](templates/101-air-quality-sensor-console-print): Connected an air quality sensor to NodeMCU and send data to an IoT server locally (in local area network). 150 | * Chapter 2 -[101-air-quality-sensor-text-messaging-twilio](templates/101-air-quality-sensor-text-messaging-twilio): Send an alert message by SMS when the air quality is not good 151 | * Chapter 3 -[102-air-quality-sensor-dropbox](templates/102-air-quality-sensor-dropbox): Save hardware data to Dropbox files 152 | * Chapter 4 -[102-air-quality-sensor-email](templates/102-air-quality-sensor-email): Send an alert message by email when the air quality is not good 153 | * Chapter 5 -[201-web-of-things-dashboard](templates/201-web-of-things-dashboard): An advanced chapter. Build a real-time sensor information dashboard. Get understood of WebSockets, CoAP and Web of Things (WoT). 154 | 155 | ## License 156 | 157 | devify-server is released under the [MIT License](http://www.opensource.org/licenses/MIT). See [LICENSE.md](LICENSE.md). 158 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /coap-broker-server.js: -------------------------------------------------------------------------------- 1 | var server = require('./libs/coap-broker'); 2 | 3 | var onmessage = function(payload) { 4 | var obj = JSON.parse(payload.data); 5 | var paths = payload.pathname.split('/'); 6 | var deviceId = paths[2]; 7 | 8 | console.log('[', deviceId, ']', payload.data); 9 | }; 10 | 11 | var onnewthing = function(thing) { 12 | var data = JSON.stringify(thing); 13 | 14 | console.log(' ' + data); 15 | }; 16 | 17 | server.start({ 18 | onmessage: onmessage, 19 | onnewthing: onnewthing 20 | }); 21 | -------------------------------------------------------------------------------- /libs/coap-broker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * The MIT License (MIT) 4 | * 5 | * Devify Platform 6 | * 7 | * Copyright (c) 2016 Devify, Inc. 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | * 27 | */ 28 | 29 | 'use strict'; 30 | 31 | /** 32 | * Main WoT Framework 33 | */ 34 | var WoT = require('wotcity.io'); 35 | 36 | /** 37 | * WoT Modules 38 | */ 39 | var Framework = WoT.Framework 40 | , CoapBroker = WoT.CoapBroker 41 | , Router = WoT.CoapRouter 42 | , RequestHandlers = WoT.CoapRequestHandlers 43 | , Runtime = WoT.Runtime; 44 | 45 | /** 46 | * Util Modules 47 | */ 48 | var merge = require('utils-merge'); 49 | 50 | /** 51 | * CoAP URL Router 52 | */ 53 | var coapHandlers = { 54 | "/object/([A-Za-z0-9-]+)/send": RequestHandlers.send, 55 | "/object/([A-Za-z0-9-]+)/viewer": RequestHandlers.viewer, 56 | "/object/([A-Za-z0-9-]+)/status": RequestHandlers.status 57 | }; 58 | 59 | /* 60 | * Prototype and Class 61 | */ 62 | var Server = function () { 63 | this.server = null; 64 | this.callbacks = { 65 | ondata: function() { return 0; }, 66 | onnewthing: function() { return 0; }, 67 | onstart: function() { return 0; } 68 | }; 69 | }; 70 | 71 | /** 72 | * Event callback factory 73 | */ 74 | Server.prototype.onNewThing = function(thing) { 75 | // at this server, the thing description is included via a local file 76 | // or it can be accessed by invoking HTTP api from remote device 77 | var def = require('./thing'); 78 | var thing = merge(def, thing); 79 | 80 | // register a new thing to WoT framework 81 | this.registerThing(thing); 82 | this.callbacks['onnewthing'](thing); 83 | }; 84 | 85 | /** 86 | * Event callback factory 87 | */ 88 | Server.prototype.onData = function(payload) { 89 | this.callbacks['ondata'](payload); 90 | 91 | // Send hardware data to FBP network. 92 | var data = { 93 | upproc: 'devify-device', 94 | upport: 'out', 95 | payload: payload 96 | }; 97 | this._network.send(data); 98 | }; 99 | 100 | /** 101 | * Event callback factory 102 | */ 103 | Server.prototype.onStart = function(payload) { 104 | this.callbacks['onstart'](payload); 105 | }; 106 | 107 | /** 108 | * Create an WoT server. 109 | * 110 | * @return {Object} 111 | * @api public 112 | */ 113 | function createServer(options) { 114 | var instance = new Server(); 115 | 116 | // Create FBP Runtime 117 | var network = new Runtime(); 118 | instance._network = network; 119 | 120 | return merge(instance, options); 121 | } 122 | 123 | /** 124 | * Start a CoAP server. 125 | * 126 | * @return {None} 127 | * @api public 128 | */ 129 | Server.prototype.start = function(options) { 130 | var port = process.env.PORT || 8000; 131 | var host = process.env.HOST || 'localhost'; 132 | var options = options || {}; 133 | 134 | if (options && options.ondata && typeof options.ondata === 'function') 135 | this.callbacks['ondata'] = options.ondata; 136 | 137 | if (options && options.onnewthing && typeof options.onnewthing === 'function') 138 | this.callbacks['onnewthing'] = options.onnewthing; 139 | 140 | if (options && options.onstart && typeof options.onstart === 'function') 141 | this.callbacks['onstart'] = options.onstart; 142 | 143 | // Load components 144 | this._network.load(this._options.components || {}); 145 | 146 | // Start FBP Network Runtime 147 | this._network.runtime(this._options.graph || {}); 148 | 149 | var server = new CoapBroker({ 150 | port: port, 151 | host: host 152 | }); 153 | var router = new Router(); 154 | 155 | // Events callback factory 156 | server.on('newThing', this.onNewThing.bind(this)); 157 | server.on('data', this.onData.bind(this)); 158 | server.on('start', this.onStart.bind(this)); 159 | 160 | server.start(router.route, coapHandlers); 161 | 162 | this.server = server; 163 | }; 164 | 165 | /** 166 | * Shutdown the CoAP server. 167 | * 168 | * @param cb {Function} The complete callback 169 | * @return {} 170 | * @api public 171 | */ 172 | Server.prototype.shutdown = function(cb) { 173 | if (this.server) 174 | this.server.shutdown(cb); 175 | } 176 | 177 | /** 178 | * Create the server instance. 179 | */ 180 | var coapBrokerImpl = createServer({}); 181 | 182 | /** 183 | * Combined server with framework instance. 184 | */ 185 | var coapServer = new Framework({ 186 | server: coapBrokerImpl 187 | }); 188 | 189 | /** 190 | * Export the server. 191 | */ 192 | module.exports = coapServer; 193 | -------------------------------------------------------------------------------- /libs/coap-proxy-websocket.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * The MIT License (MIT) 4 | * 5 | * Devify Platform 6 | * 7 | * Copyright (c) 2016 Devify, Inc. 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | * 27 | */ 28 | 29 | 'use strict'; 30 | 31 | /** 32 | * Main WoT Framework 33 | */ 34 | var WoT = require('wotcity.io'); 35 | 36 | /** 37 | * WoT Modules 38 | */ 39 | var Framework = WoT.Framework 40 | , CoapBroker = WoT.CoapBroker 41 | , Router = WoT.CoapRouter 42 | , RequestHandlers = WoT.CoapRequestHandlers 43 | , Runtime = WoT.Runtime; 44 | 45 | /** 46 | * Util Modules 47 | */ 48 | var merge = require('utils-merge'); 49 | 50 | /** 51 | * CoAP URL Router 52 | */ 53 | var coapHandlers = { 54 | "/object/([A-Za-z0-9-]+)/send": RequestHandlers.proxyingWebSocket, 55 | "/object/([A-Za-z0-9-]+)/viewer": RequestHandlers.viewer, 56 | "/object/([A-Za-z0-9-]+)/status": RequestHandlers.status 57 | }; 58 | 59 | /* 60 | * Prototype and Class 61 | */ 62 | var Server = function () { 63 | this.server = null; 64 | this.callbacks = { 65 | ondata: function() { return 0; }, 66 | onnewthing: function() { return 0; }, 67 | onstart: function() { return 0; } 68 | }; 69 | }; 70 | 71 | /** 72 | * Event callback factory 73 | */ 74 | Server.prototype.onNewThing = function(thing) { 75 | // at this server, the thing description is included via a local file 76 | // or it can be accessed by invoking HTTP api from remote device 77 | var def = require('./thing'); 78 | var thing = merge(def, thing); 79 | 80 | // register a new thing to WoT framework 81 | this.registerThing(thing); 82 | 83 | this.callbacks['onnewthing'](thing); 84 | }; 85 | 86 | /** 87 | * Event callback factory 88 | */ 89 | Server.prototype.onData = function(payload) { 90 | this.callbacks['ondata'](payload); 91 | 92 | // Send hardware data to FBP network. 93 | var data = { 94 | upproc: 'devify-device', 95 | upport: 'out', 96 | payload: payload 97 | }; 98 | this._network.send(data); 99 | }; 100 | 101 | /** 102 | * Event callback factory 103 | */ 104 | Server.prototype.onStart = function(payload) { 105 | this.callbacks['onstart'](payload); 106 | }; 107 | 108 | /** 109 | * Create an WoT server. 110 | * 111 | * @return {Object} 112 | * @api public 113 | */ 114 | function createServer(options) { 115 | var instance = new Server(); 116 | 117 | // Create FBP Runtime 118 | var network = new Runtime(); 119 | instance._network = network; 120 | 121 | return merge(instance, options); 122 | } 123 | 124 | /** 125 | * Start a CoAP server. 126 | * 127 | * @return {None} 128 | * @api public 129 | */ 130 | Server.prototype.start = function(options) { 131 | var port = process.env.PORT || 8000; 132 | var host = process.env.HOST || 'localhost'; 133 | var endpoint = process.env.ENDPOINT || 'wot.city'; 134 | var options = options || {}; 135 | 136 | if (options && options.ondata && typeof options.ondata === 'function') 137 | this.callbacks['ondata'] = options.ondata; 138 | 139 | if (options && options.onnewthing && typeof options.onnewthing === 'function') 140 | this.callbacks['onnewthing'] = options.onnewthing; 141 | 142 | if (options && options.onstart && typeof options.onstart === 'function') 143 | this.callbacks['onstart'] = options.onstart; 144 | 145 | // Load components 146 | this._network.load(this._options.components || {}); 147 | 148 | // Start FBP Network Runtime 149 | this._network.runtime(this._options.graph || {}); 150 | 151 | var server = new CoapBroker({ 152 | port: port, 153 | host: host, 154 | endpoint: [ 155 | 'localhost:8000' 156 | ] 157 | }); 158 | var router = new Router(); 159 | 160 | // Events callback factory 161 | server.on('newThing', this.onNewThing.bind(this)); 162 | server.on('data', this.onData.bind(this)); 163 | server.on('start', this.onStart.bind(this)); 164 | 165 | server.start(router.route, coapHandlers); 166 | 167 | this.server = server; 168 | }; 169 | 170 | /** 171 | * Shutdown the Websocket server. 172 | * 173 | * @param cb {Function} The complete callback 174 | * @return {} 175 | * @api public 176 | */ 177 | Server.prototype.shutdown = function(cb) { 178 | if (this.server) 179 | this.server.shutdown(cb); 180 | } 181 | 182 | /** 183 | * Create the server instance. 184 | */ 185 | var coapBrokerImpl = createServer({}); 186 | 187 | /** 188 | * Combined server with framework instance. 189 | */ 190 | var coapServer = new Framework({ 191 | server: coapBrokerImpl 192 | }); 193 | 194 | /** 195 | * Export the server. 196 | */ 197 | module.exports = coapServer; 198 | -------------------------------------------------------------------------------- /libs/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * The MIT License (MIT) 4 | * 5 | * Devify Platform 6 | * 7 | * Copyright (c) 2016 Devify, Inc. 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | * 27 | */ 28 | 29 | var CoapBroker = require('./coap-broker') 30 | , WebsocketBroker = require("./websocket-broker") 31 | , CoapToWebsocketProxy = require("./coap-proxy-websocket"); 32 | 33 | module.exports = { 34 | CoapBroker: CoapBroker, 35 | WebsocketBroker: WebsocketBroker, 36 | CoapToWebsocketProxy: CoapToWebsocketProxy 37 | }; -------------------------------------------------------------------------------- /libs/thing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The thing definition which includes 3 | * - name 4 | * - model 5 | * - implementation 6 | */ 7 | module.exports = { 8 | "name": "esp8266", 9 | "model": { 10 | "events": { 11 | "ac_power": function () { 12 | } 13 | }, 14 | "properties": { 15 | "battery": function() { 16 | } 17 | }, 18 | "actions": { 19 | "unlock": function () { 20 | }, 21 | "lock": function () { 22 | } 23 | } 24 | }, 25 | "implementation": { 26 | notify: function (thing) { 27 | }, 28 | } 29 | }; -------------------------------------------------------------------------------- /libs/websocket-broker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * The MIT License (MIT) 4 | * 5 | * Devify Platform 6 | * 7 | * Copyright (c) 2016 Devify, Inc. 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | * 27 | */ 28 | 29 | 'use strict'; 30 | 31 | /** 32 | * Main WoT Framework 33 | */ 34 | var WoT = require('wotcity.io'); 35 | 36 | /** 37 | * WoT Modules 38 | */ 39 | var Framework = WoT.Framework 40 | , WebsocketBroker = WoT.WebsocketBroker 41 | , WebsocketRouter = WoT.WebsocketRouter 42 | , RequestHandlers = WoT.WebsocketRequestHandlers 43 | , Runtime = WoT.Runtime; 44 | 45 | /** 46 | * Util Modules 47 | */ 48 | var merge = require('utils-merge'); 49 | 50 | /** 51 | * Websocket URL Router 52 | */ 53 | var wsHandlers = { 54 | "/object/([A-Za-z0-9-]+)/send": RequestHandlers.send, 55 | "/object/([A-Za-z0-9-]+)/viewer": RequestHandlers.viewer, 56 | "/object/([A-Za-z0-9-]+)/status": RequestHandlers.status 57 | }; 58 | 59 | /* 60 | * Prototype and Class 61 | */ 62 | var Server = function () { 63 | this.server = null; 64 | this.callbacks = { 65 | ondata: function() { return 0; }, 66 | onnewthing: function() { return 0; }, 67 | onstart: function() { return 0; } 68 | }; 69 | }; 70 | 71 | /** 72 | * Event callback factory 73 | */ 74 | Server.prototype.onNewThing = function(thing) { 75 | // at this server, the thing description is included via a local file 76 | // or it can be accessed by invoking HTTP api from remote device 77 | var def = require('./thing'); 78 | var thing = merge(def, thing); 79 | 80 | // register a new thing to WoT framework 81 | this.registerThing(thing); 82 | 83 | this.callbacks['onnewthing'](thing); 84 | }; 85 | 86 | /** 87 | * Event callback factory 88 | */ 89 | Server.prototype.onData = function(payload) { 90 | this.callbacks['ondata'](payload); 91 | 92 | // Send hardware data to FBP network. 93 | var data = { 94 | upproc: 'devify-device', 95 | upport: 'out', 96 | payload: payload 97 | }; 98 | this._network.send(data); 99 | }; 100 | 101 | /** 102 | * Event callback factory 103 | */ 104 | Server.prototype.onStart = function(payload) { 105 | this.callbacks['onstart'](payload); 106 | }; 107 | 108 | /** 109 | * Create an WoT server. 110 | * 111 | * @return {Object} 112 | * @api public 113 | */ 114 | function createServer(options) { 115 | var instance = new Server(); 116 | 117 | // Create FBP Runtime 118 | var network = new Runtime(); 119 | instance._network = network; 120 | 121 | return merge(instance, options); 122 | } 123 | 124 | /** 125 | * Start a Websocket server. 126 | * 127 | * @return {None} 128 | * @api public 129 | */ 130 | Server.prototype.start = function(options) { 131 | var port = process.env.PORT || 8000; 132 | var host = process.env.HOST || 'localhost'; 133 | var options = options || {}; 134 | 135 | if (options && options.ondata && typeof options.ondata === 'function') 136 | this.callbacks['ondata'] = options.ondata; 137 | 138 | if (options && options.onnewthing && typeof options.onnewthing === 'function') 139 | this.callbacks['onnewthing'] = options.onnewthing; 140 | 141 | if (options && options.onstart && typeof options.onstart === 'function') 142 | this.callbacks['onstart'] = options.onstart; 143 | 144 | // Load components 145 | this._network.load(this._options.components || {}); 146 | 147 | // Start FBP Network Runtime 148 | this._network.runtime(this._options.graph || {}); 149 | 150 | var server = new WebsocketBroker({ 151 | port: port, 152 | host: host 153 | }); 154 | var router = new WebsocketRouter(); 155 | 156 | // Events callback factory 157 | server.on('newThing', this.onNewThing.bind(this)); 158 | server.on('data', this.onData.bind(this)); 159 | server.on('start', this.onStart.bind(this)); 160 | 161 | server.start(router.route, wsHandlers); 162 | 163 | this.server = server; 164 | }; 165 | 166 | Server.prototype.shutdown = function(cb) { 167 | if (this.server) 168 | this.server.shutdown(cb); 169 | } 170 | 171 | /** 172 | * Create the server instance. 173 | */ 174 | var wsBrokerImpl = createServer({}); 175 | 176 | /** 177 | * Combined server with framework instance. 178 | */ 179 | var wsServer = new Framework({ 180 | server: wsBrokerImpl 181 | }); 182 | 183 | /** 184 | * Export the server. 185 | */ 186 | module.exports = wsServer; 187 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devify-server", 3 | "version": "3.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@tootallnate/once": { 8 | "version": "1.1.2", 9 | "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", 10 | "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", 11 | "dev": true 12 | }, 13 | "@ungap/promise-all-settled": { 14 | "version": "1.1.2", 15 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 16 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 17 | "dev": true 18 | }, 19 | "agent-base": { 20 | "version": "6.0.2", 21 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 22 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 23 | "dev": true, 24 | "requires": { 25 | "debug": "4" 26 | }, 27 | "dependencies": { 28 | "debug": { 29 | "version": "4.3.1", 30 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 31 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 32 | "dev": true, 33 | "requires": { 34 | "ms": "2.1.2" 35 | } 36 | }, 37 | "ms": { 38 | "version": "2.1.2", 39 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 40 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 41 | "dev": true 42 | } 43 | } 44 | }, 45 | "ansi-colors": { 46 | "version": "4.1.1", 47 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 48 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 49 | "dev": true 50 | }, 51 | "ansi-regex": { 52 | "version": "3.0.0", 53 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 54 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 55 | "dev": true 56 | }, 57 | "ansi-styles": { 58 | "version": "4.3.0", 59 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 60 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 61 | "dev": true, 62 | "requires": { 63 | "color-convert": "^2.0.1" 64 | } 65 | }, 66 | "anymatch": { 67 | "version": "3.1.2", 68 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 69 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 70 | "dev": true, 71 | "requires": { 72 | "normalize-path": "^3.0.0", 73 | "picomatch": "^2.0.4" 74 | } 75 | }, 76 | "argparse": { 77 | "version": "2.0.1", 78 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 79 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 80 | "dev": true 81 | }, 82 | "argv": { 83 | "version": "0.0.2", 84 | "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", 85 | "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", 86 | "dev": true 87 | }, 88 | "asap": { 89 | "version": "2.0.6", 90 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 91 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", 92 | "dev": true 93 | }, 94 | "axios": { 95 | "version": "0.21.1", 96 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", 97 | "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", 98 | "dev": true, 99 | "requires": { 100 | "follow-redirects": "^1.10.0" 101 | } 102 | }, 103 | "backbone": { 104 | "version": "1.4.0", 105 | "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz", 106 | "integrity": "sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==", 107 | "requires": { 108 | "underscore": ">=1.8.3" 109 | } 110 | }, 111 | "balanced-match": { 112 | "version": "1.0.2", 113 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 114 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 115 | "dev": true 116 | }, 117 | "base64-js": { 118 | "version": "1.5.1", 119 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 120 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 121 | }, 122 | "binary-extensions": { 123 | "version": "2.2.0", 124 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 125 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 126 | "dev": true 127 | }, 128 | "bl": { 129 | "version": "5.0.0", 130 | "resolved": "https://registry.npmjs.org/bl/-/bl-5.0.0.tgz", 131 | "integrity": "sha512-8vxFNZ0pflFfi0WXA3WQXlj6CaMEwsmh63I1CNp0q+wWv8sD0ARx1KovSQd0l2GkwrMIOyedq0EF1FxI+RCZLQ==", 132 | "requires": { 133 | "buffer": "^6.0.3", 134 | "inherits": "^2.0.4", 135 | "readable-stream": "^3.4.0" 136 | }, 137 | "dependencies": { 138 | "buffer": { 139 | "version": "6.0.3", 140 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", 141 | "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", 142 | "requires": { 143 | "base64-js": "^1.3.1", 144 | "ieee754": "^1.2.1" 145 | } 146 | }, 147 | "readable-stream": { 148 | "version": "3.6.0", 149 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 150 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 151 | "requires": { 152 | "inherits": "^2.0.3", 153 | "string_decoder": "^1.1.1", 154 | "util-deprecate": "^1.0.1" 155 | } 156 | }, 157 | "string_decoder": { 158 | "version": "1.3.0", 159 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 160 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 161 | "requires": { 162 | "safe-buffer": "~5.2.0" 163 | } 164 | } 165 | } 166 | }, 167 | "bluebird": { 168 | "version": "3.7.2", 169 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 170 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 171 | }, 172 | "brace-expansion": { 173 | "version": "1.1.11", 174 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 175 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 176 | "dev": true, 177 | "requires": { 178 | "balanced-match": "^1.0.0", 179 | "concat-map": "0.0.1" 180 | } 181 | }, 182 | "braces": { 183 | "version": "3.0.2", 184 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 185 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 186 | "dev": true, 187 | "requires": { 188 | "fill-range": "^7.0.1" 189 | } 190 | }, 191 | "browser-stdout": { 192 | "version": "1.3.1", 193 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 194 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 195 | "dev": true 196 | }, 197 | "bson": { 198 | "version": "4.4.0", 199 | "resolved": "https://registry.npmjs.org/bson/-/bson-4.4.0.tgz", 200 | "integrity": "sha512-uX9Zqzv2DpFXJgQOWKD8nbf0dTQV57WM8eiXDXVWeJYgiu/zIRz61OGLJKwbfSEEjZJ+AgS+7TUT7Y8EloTaqQ==", 201 | "requires": { 202 | "buffer": "^5.6.0" 203 | } 204 | }, 205 | "buffer": { 206 | "version": "5.7.1", 207 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 208 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 209 | "requires": { 210 | "base64-js": "^1.3.1", 211 | "ieee754": "^1.1.13" 212 | } 213 | }, 214 | "buffer-equal-constant-time": { 215 | "version": "1.0.1", 216 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 217 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", 218 | "dev": true 219 | }, 220 | "bufferutil": { 221 | "version": "4.0.3", 222 | "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz", 223 | "integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==", 224 | "requires": { 225 | "node-gyp-build": "^4.2.0" 226 | } 227 | }, 228 | "call-bind": { 229 | "version": "1.0.2", 230 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 231 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 232 | "dev": true, 233 | "requires": { 234 | "function-bind": "^1.1.1", 235 | "get-intrinsic": "^1.0.2" 236 | } 237 | }, 238 | "camelcase": { 239 | "version": "6.2.0", 240 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 241 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", 242 | "dev": true 243 | }, 244 | "capitalize": { 245 | "version": "2.0.3", 246 | "resolved": "https://registry.npmjs.org/capitalize/-/capitalize-2.0.3.tgz", 247 | "integrity": "sha512-Qc5ksT1/zEJBbFYD05h99hCNEW0cgyD0zzE5WvkgisNnppJ+16zfaSk34evF0j6pGW8hejkRUeygJ5uN5k22SQ==" 248 | }, 249 | "chalk": { 250 | "version": "4.1.1", 251 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", 252 | "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", 253 | "dev": true, 254 | "requires": { 255 | "ansi-styles": "^4.1.0", 256 | "supports-color": "^7.1.0" 257 | }, 258 | "dependencies": { 259 | "supports-color": { 260 | "version": "7.2.0", 261 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 262 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 263 | "dev": true, 264 | "requires": { 265 | "has-flag": "^4.0.0" 266 | } 267 | } 268 | } 269 | }, 270 | "chokidar": { 271 | "version": "3.5.1", 272 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", 273 | "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", 274 | "dev": true, 275 | "requires": { 276 | "anymatch": "~3.1.1", 277 | "braces": "~3.0.2", 278 | "fsevents": "~2.3.1", 279 | "glob-parent": "~5.1.0", 280 | "is-binary-path": "~2.1.0", 281 | "is-glob": "~4.0.1", 282 | "normalize-path": "~3.0.0", 283 | "readdirp": "~3.5.0" 284 | } 285 | }, 286 | "cliui": { 287 | "version": "7.0.4", 288 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 289 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 290 | "dev": true, 291 | "requires": { 292 | "string-width": "^4.2.0", 293 | "strip-ansi": "^6.0.0", 294 | "wrap-ansi": "^7.0.0" 295 | }, 296 | "dependencies": { 297 | "ansi-regex": { 298 | "version": "5.0.0", 299 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 300 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 301 | "dev": true 302 | }, 303 | "is-fullwidth-code-point": { 304 | "version": "3.0.0", 305 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 306 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 307 | "dev": true 308 | }, 309 | "string-width": { 310 | "version": "4.2.2", 311 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 312 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 313 | "dev": true, 314 | "requires": { 315 | "emoji-regex": "^8.0.0", 316 | "is-fullwidth-code-point": "^3.0.0", 317 | "strip-ansi": "^6.0.0" 318 | } 319 | }, 320 | "strip-ansi": { 321 | "version": "6.0.0", 322 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 323 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 324 | "dev": true, 325 | "requires": { 326 | "ansi-regex": "^5.0.0" 327 | } 328 | } 329 | } 330 | }, 331 | "cluster": { 332 | "version": "0.7.7", 333 | "resolved": "https://registry.npmjs.org/cluster/-/cluster-0.7.7.tgz", 334 | "integrity": "sha1-5JfiZ8yVa9CwUTrbSqOTNX0Ahe8=", 335 | "requires": { 336 | "log": ">= 1.2.0", 337 | "mkdirp": ">= 0.0.1" 338 | } 339 | }, 340 | "coap": { 341 | "version": "0.24.0", 342 | "resolved": "https://registry.npmjs.org/coap/-/coap-0.24.0.tgz", 343 | "integrity": "sha512-8qn5JMHrbM8sX9PWIWsjZ4/WLJE3g/uvGMdS5v4rggL92+Cp5CReT81ohmF8US7CRD3KIAlWYrnJ3ghlu1WyXA==", 344 | "requires": { 345 | "bl": "^4.0.2", 346 | "capitalize": "^2.0.3", 347 | "coap-packet": "^0.1.14", 348 | "debug": "^4.1.1", 349 | "fastseries": "^2.0.0", 350 | "lru-cache": "^5.1.1", 351 | "readable-stream": "^3.6.0" 352 | }, 353 | "dependencies": { 354 | "bl": { 355 | "version": "4.1.0", 356 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 357 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 358 | "requires": { 359 | "buffer": "^5.5.0", 360 | "inherits": "^2.0.4", 361 | "readable-stream": "^3.4.0" 362 | } 363 | }, 364 | "debug": { 365 | "version": "4.3.1", 366 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 367 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 368 | "requires": { 369 | "ms": "2.1.2" 370 | } 371 | }, 372 | "lru-cache": { 373 | "version": "5.1.1", 374 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", 375 | "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", 376 | "requires": { 377 | "yallist": "^3.0.2" 378 | } 379 | }, 380 | "ms": { 381 | "version": "2.1.2", 382 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 383 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 384 | }, 385 | "readable-stream": { 386 | "version": "3.6.0", 387 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 388 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 389 | "requires": { 390 | "inherits": "^2.0.3", 391 | "string_decoder": "^1.1.1", 392 | "util-deprecate": "^1.0.1" 393 | } 394 | }, 395 | "string_decoder": { 396 | "version": "1.3.0", 397 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 398 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 399 | "requires": { 400 | "safe-buffer": "~5.2.0" 401 | } 402 | } 403 | } 404 | }, 405 | "coap-packet": { 406 | "version": "0.1.14", 407 | "resolved": "https://registry.npmjs.org/coap-packet/-/coap-packet-0.1.14.tgz", 408 | "integrity": "sha1-OEgitnBau/MaDLxEnvejpkxPPlI=" 409 | }, 410 | "codecov": { 411 | "version": "3.7.1", 412 | "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.7.1.tgz", 413 | "integrity": "sha512-JHWxyPTkMLLJn9SmKJnwAnvY09kg2Os2+Ux+GG7LwZ9g8gzDDISpIN5wAsH1UBaafA/yGcd3KofMaorE8qd6Lw==", 414 | "dev": true, 415 | "requires": { 416 | "argv": "0.0.2", 417 | "ignore-walk": "3.0.3", 418 | "js-yaml": "3.13.1", 419 | "teeny-request": "6.0.1", 420 | "urlgrey": "0.4.4" 421 | }, 422 | "dependencies": { 423 | "argparse": { 424 | "version": "1.0.10", 425 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 426 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 427 | "dev": true, 428 | "requires": { 429 | "sprintf-js": "~1.0.2" 430 | } 431 | }, 432 | "js-yaml": { 433 | "version": "3.13.1", 434 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 435 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 436 | "dev": true, 437 | "requires": { 438 | "argparse": "^1.0.7", 439 | "esprima": "^4.0.0" 440 | } 441 | } 442 | } 443 | }, 444 | "color-convert": { 445 | "version": "2.0.1", 446 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 447 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 448 | "dev": true, 449 | "requires": { 450 | "color-name": "~1.1.4" 451 | } 452 | }, 453 | "color-name": { 454 | "version": "1.1.4", 455 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 456 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 457 | "dev": true 458 | }, 459 | "concat-map": { 460 | "version": "0.0.1", 461 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 462 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 463 | "dev": true 464 | }, 465 | "core-util-is": { 466 | "version": "1.0.2", 467 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 468 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 469 | }, 470 | "d": { 471 | "version": "1.0.1", 472 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 473 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 474 | "requires": { 475 | "es5-ext": "^0.10.50", 476 | "type": "^1.0.1" 477 | } 478 | }, 479 | "dayjs": { 480 | "version": "1.10.5", 481 | "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.5.tgz", 482 | "integrity": "sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==", 483 | "dev": true 484 | }, 485 | "debug": { 486 | "version": "2.6.9", 487 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 488 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 489 | "requires": { 490 | "ms": "2.0.0" 491 | } 492 | }, 493 | "decamelize": { 494 | "version": "4.0.0", 495 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 496 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 497 | "dev": true 498 | }, 499 | "diff": { 500 | "version": "5.0.0", 501 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 502 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 503 | "dev": true 504 | }, 505 | "duration": { 506 | "version": "0.2.2", 507 | "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", 508 | "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", 509 | "requires": { 510 | "d": "1", 511 | "es5-ext": "~0.10.46" 512 | } 513 | }, 514 | "ecdsa-sig-formatter": { 515 | "version": "1.0.11", 516 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 517 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 518 | "dev": true, 519 | "requires": { 520 | "safe-buffer": "^5.0.1" 521 | } 522 | }, 523 | "emoji-regex": { 524 | "version": "8.0.0", 525 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 526 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 527 | "dev": true 528 | }, 529 | "es5-ext": { 530 | "version": "0.10.53", 531 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 532 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 533 | "requires": { 534 | "es6-iterator": "~2.0.3", 535 | "es6-symbol": "~3.1.3", 536 | "next-tick": "~1.0.0" 537 | } 538 | }, 539 | "es6-iterator": { 540 | "version": "2.0.3", 541 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 542 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 543 | "requires": { 544 | "d": "1", 545 | "es5-ext": "^0.10.35", 546 | "es6-symbol": "^3.1.1" 547 | } 548 | }, 549 | "es6-symbol": { 550 | "version": "3.1.3", 551 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 552 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 553 | "requires": { 554 | "d": "^1.0.1", 555 | "ext": "^1.1.2" 556 | } 557 | }, 558 | "escalade": { 559 | "version": "3.1.1", 560 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 561 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 562 | "dev": true 563 | }, 564 | "escape-string-regexp": { 565 | "version": "4.0.0", 566 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 567 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 568 | "dev": true 569 | }, 570 | "esprima": { 571 | "version": "4.0.1", 572 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 573 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 574 | "dev": true 575 | }, 576 | "event-emitter": { 577 | "version": "0.3.5", 578 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 579 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 580 | "requires": { 581 | "d": "1", 582 | "es5-ext": "~0.10.14" 583 | } 584 | }, 585 | "ext": { 586 | "version": "1.4.0", 587 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 588 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 589 | "requires": { 590 | "type": "^2.0.0" 591 | }, 592 | "dependencies": { 593 | "type": { 594 | "version": "2.5.0", 595 | "resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz", 596 | "integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw==" 597 | } 598 | } 599 | }, 600 | "fastseries": { 601 | "version": "2.0.0", 602 | "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-2.0.0.tgz", 603 | "integrity": "sha512-XBU9RXeoYc2/VnvMhplAxEmZLfIk7cvTBu+xwoBuTI8pL19E03cmca17QQycKIdxgwCeFA/a4u27gv1h3ya5LQ==" 604 | }, 605 | "fill-range": { 606 | "version": "7.0.1", 607 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 608 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 609 | "dev": true, 610 | "requires": { 611 | "to-regex-range": "^5.0.1" 612 | } 613 | }, 614 | "find-up": { 615 | "version": "5.0.0", 616 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 617 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 618 | "dev": true, 619 | "requires": { 620 | "locate-path": "^6.0.0", 621 | "path-exists": "^4.0.0" 622 | } 623 | }, 624 | "flat": { 625 | "version": "5.0.2", 626 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 627 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 628 | "dev": true 629 | }, 630 | "follow-redirects": { 631 | "version": "1.14.1", 632 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", 633 | "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", 634 | "dev": true 635 | }, 636 | "fs.realpath": { 637 | "version": "1.0.0", 638 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 639 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 640 | "dev": true 641 | }, 642 | "fsevents": { 643 | "version": "2.3.2", 644 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 645 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 646 | "dev": true, 647 | "optional": true 648 | }, 649 | "function-bind": { 650 | "version": "1.1.1", 651 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 652 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 653 | "dev": true 654 | }, 655 | "get-caller-file": { 656 | "version": "2.0.5", 657 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 658 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 659 | "dev": true 660 | }, 661 | "get-intrinsic": { 662 | "version": "1.1.1", 663 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 664 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 665 | "dev": true, 666 | "requires": { 667 | "function-bind": "^1.1.1", 668 | "has": "^1.0.3", 669 | "has-symbols": "^1.0.1" 670 | } 671 | }, 672 | "glob": { 673 | "version": "7.1.6", 674 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 675 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 676 | "dev": true, 677 | "requires": { 678 | "fs.realpath": "^1.0.0", 679 | "inflight": "^1.0.4", 680 | "inherits": "2", 681 | "minimatch": "^3.0.4", 682 | "once": "^1.3.0", 683 | "path-is-absolute": "^1.0.0" 684 | } 685 | }, 686 | "glob-parent": { 687 | "version": "5.1.2", 688 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 689 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 690 | "dev": true, 691 | "requires": { 692 | "is-glob": "^4.0.1" 693 | } 694 | }, 695 | "growl": { 696 | "version": "1.10.5", 697 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 698 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 699 | "dev": true 700 | }, 701 | "has": { 702 | "version": "1.0.3", 703 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 704 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 705 | "dev": true, 706 | "requires": { 707 | "function-bind": "^1.1.1" 708 | } 709 | }, 710 | "has-flag": { 711 | "version": "4.0.0", 712 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 713 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 714 | "dev": true 715 | }, 716 | "has-symbols": { 717 | "version": "1.0.2", 718 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 719 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", 720 | "dev": true 721 | }, 722 | "he": { 723 | "version": "1.2.0", 724 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 725 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 726 | "dev": true 727 | }, 728 | "http-proxy-agent": { 729 | "version": "4.0.1", 730 | "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", 731 | "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", 732 | "dev": true, 733 | "requires": { 734 | "@tootallnate/once": "1", 735 | "agent-base": "6", 736 | "debug": "4" 737 | }, 738 | "dependencies": { 739 | "debug": { 740 | "version": "4.3.1", 741 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 742 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 743 | "dev": true, 744 | "requires": { 745 | "ms": "2.1.2" 746 | } 747 | }, 748 | "ms": { 749 | "version": "2.1.2", 750 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 751 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 752 | "dev": true 753 | } 754 | } 755 | }, 756 | "https-proxy-agent": { 757 | "version": "5.0.0", 758 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 759 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 760 | "dev": true, 761 | "requires": { 762 | "agent-base": "6", 763 | "debug": "4" 764 | }, 765 | "dependencies": { 766 | "debug": { 767 | "version": "4.3.1", 768 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 769 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 770 | "dev": true, 771 | "requires": { 772 | "ms": "2.1.2" 773 | } 774 | }, 775 | "ms": { 776 | "version": "2.1.2", 777 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 778 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 779 | "dev": true 780 | } 781 | } 782 | }, 783 | "ieee754": { 784 | "version": "1.2.1", 785 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 786 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 787 | }, 788 | "ignore-walk": { 789 | "version": "3.0.3", 790 | "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", 791 | "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", 792 | "dev": true, 793 | "requires": { 794 | "minimatch": "^3.0.4" 795 | } 796 | }, 797 | "inflight": { 798 | "version": "1.0.6", 799 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 800 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 801 | "dev": true, 802 | "requires": { 803 | "once": "^1.3.0", 804 | "wrappy": "1" 805 | } 806 | }, 807 | "inherits": { 808 | "version": "2.0.4", 809 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 810 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 811 | }, 812 | "is-binary-path": { 813 | "version": "2.1.0", 814 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 815 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 816 | "dev": true, 817 | "requires": { 818 | "binary-extensions": "^2.0.0" 819 | } 820 | }, 821 | "is-extglob": { 822 | "version": "2.1.1", 823 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 824 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 825 | "dev": true 826 | }, 827 | "is-fullwidth-code-point": { 828 | "version": "2.0.0", 829 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 830 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 831 | "dev": true 832 | }, 833 | "is-glob": { 834 | "version": "4.0.1", 835 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 836 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 837 | "dev": true, 838 | "requires": { 839 | "is-extglob": "^2.1.1" 840 | } 841 | }, 842 | "is-number": { 843 | "version": "7.0.0", 844 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 845 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 846 | "dev": true 847 | }, 848 | "is-plain-obj": { 849 | "version": "2.1.0", 850 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 851 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 852 | "dev": true 853 | }, 854 | "is-typedarray": { 855 | "version": "1.0.0", 856 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 857 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 858 | }, 859 | "isarray": { 860 | "version": "0.0.1", 861 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 862 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 863 | }, 864 | "isexe": { 865 | "version": "2.0.0", 866 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 867 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 868 | "dev": true 869 | }, 870 | "js-yaml": { 871 | "version": "4.0.0", 872 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", 873 | "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", 874 | "dev": true, 875 | "requires": { 876 | "argparse": "^2.0.1" 877 | } 878 | }, 879 | "jsonwebtoken": { 880 | "version": "8.5.1", 881 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", 882 | "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", 883 | "dev": true, 884 | "requires": { 885 | "jws": "^3.2.2", 886 | "lodash.includes": "^4.3.0", 887 | "lodash.isboolean": "^3.0.3", 888 | "lodash.isinteger": "^4.0.4", 889 | "lodash.isnumber": "^3.0.3", 890 | "lodash.isplainobject": "^4.0.6", 891 | "lodash.isstring": "^4.0.1", 892 | "lodash.once": "^4.0.0", 893 | "ms": "^2.1.1", 894 | "semver": "^5.6.0" 895 | }, 896 | "dependencies": { 897 | "ms": { 898 | "version": "2.1.3", 899 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 900 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 901 | "dev": true 902 | } 903 | } 904 | }, 905 | "jwa": { 906 | "version": "1.4.1", 907 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 908 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 909 | "dev": true, 910 | "requires": { 911 | "buffer-equal-constant-time": "1.0.1", 912 | "ecdsa-sig-formatter": "1.0.11", 913 | "safe-buffer": "^5.0.1" 914 | } 915 | }, 916 | "jws": { 917 | "version": "3.2.2", 918 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 919 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 920 | "dev": true, 921 | "requires": { 922 | "jwa": "^1.4.1", 923 | "safe-buffer": "^5.0.1" 924 | } 925 | }, 926 | "locate-path": { 927 | "version": "6.0.0", 928 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 929 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 930 | "dev": true, 931 | "requires": { 932 | "p-locate": "^5.0.0" 933 | } 934 | }, 935 | "lodash": { 936 | "version": "4.17.21", 937 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 938 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 939 | "dev": true 940 | }, 941 | "lodash.includes": { 942 | "version": "4.3.0", 943 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 944 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=", 945 | "dev": true 946 | }, 947 | "lodash.isboolean": { 948 | "version": "3.0.3", 949 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 950 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=", 951 | "dev": true 952 | }, 953 | "lodash.isinteger": { 954 | "version": "4.0.4", 955 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 956 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=", 957 | "dev": true 958 | }, 959 | "lodash.isnumber": { 960 | "version": "3.0.3", 961 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 962 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=", 963 | "dev": true 964 | }, 965 | "lodash.isplainobject": { 966 | "version": "4.0.6", 967 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 968 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", 969 | "dev": true 970 | }, 971 | "lodash.isstring": { 972 | "version": "4.0.1", 973 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 974 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", 975 | "dev": true 976 | }, 977 | "lodash.once": { 978 | "version": "4.1.1", 979 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 980 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", 981 | "dev": true 982 | }, 983 | "log": { 984 | "version": "6.0.0", 985 | "resolved": "https://registry.npmjs.org/log/-/log-6.0.0.tgz", 986 | "integrity": "sha512-sxChESNYJ/EcQv8C7xpmxhtTOngoXuMEqGDAkhXBEmt3MAzM3SM/TmIBOqnMEVdrOv1+VgZoYbo6U2GemQiU4g==", 987 | "requires": { 988 | "d": "^1.0.0", 989 | "duration": "^0.2.2", 990 | "es5-ext": "^0.10.49", 991 | "event-emitter": "^0.3.5", 992 | "sprintf-kit": "^2.0.0", 993 | "type": "^1.0.1" 994 | } 995 | }, 996 | "log-symbols": { 997 | "version": "4.0.0", 998 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 999 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 1000 | "dev": true, 1001 | "requires": { 1002 | "chalk": "^4.0.0" 1003 | } 1004 | }, 1005 | "lru-cache": { 1006 | "version": "2.5.2", 1007 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.2.tgz", 1008 | "integrity": "sha1-H92tk4quEmPOE4aAvhs/WRwKtBw=" 1009 | }, 1010 | "lwm2m-node-lib": { 1011 | "version": "0.4.2", 1012 | "resolved": "https://registry.npmjs.org/lwm2m-node-lib/-/lwm2m-node-lib-0.4.2.tgz", 1013 | "integrity": "sha1-MhDJKENi0bewiobZiNATsYdjVrM=", 1014 | "requires": { 1015 | "async": "1.5.2", 1016 | "coap": "0.13.1", 1017 | "coap-cli": "0.4.0", 1018 | "command-node": "0.1.1", 1019 | "logops": "0.5.0", 1020 | "mongodb": "2.1.7", 1021 | "mongoose": "4.4.3", 1022 | "mongoose-auto-increment": "5.0.1", 1023 | "underscore": "1.7.0" 1024 | }, 1025 | "dependencies": { 1026 | "async": { 1027 | "version": "1.5.2", 1028 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 1029 | "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" 1030 | }, 1031 | "coap": { 1032 | "version": "0.13.1", 1033 | "resolved": "https://registry.npmjs.org/coap/-/coap-0.13.1.tgz", 1034 | "integrity": "sha512-QHRIoJfraW5eqZAfkcXIBJqJsvREuC4EUfiEJBg6NLgPXBTUKRuXyYdb/gRQmIIcbAWtfLSwxLq1WMllYw2mrg==", 1035 | "requires": { 1036 | "bl": "~1.0.0", 1037 | "capitalize": "^1.0.0", 1038 | "coap-packet": "~0.1.12", 1039 | "debug": "^2.2.0", 1040 | "fastseries": "^1.7.0", 1041 | "lru-cache": "~4.0.0", 1042 | "readable-stream": "~2.0.5" 1043 | }, 1044 | "dependencies": { 1045 | "bl": { 1046 | "version": "1.0.2", 1047 | "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.2.tgz", 1048 | "integrity": "sha512-Gqno6lkTlQIyqOxtI8NuaRAGjz6HGVKEIzVLchY1+eUSQ9gYIY4hyiRqqE22wUgMBetHyqRaMlS6X9H3hEJ8Vw==", 1049 | "requires": { 1050 | "readable-stream": "~2.0.5" 1051 | } 1052 | }, 1053 | "capitalize": { 1054 | "version": "1.0.0", 1055 | "resolved": "https://registry.npmjs.org/capitalize/-/capitalize-1.0.0.tgz", 1056 | "integrity": "sha512-ZvPF27zRh4ZiRbWYfSktO+t7xi4RPfqL9w6gfPAWGT5pT9TjB0rlP8cKHmKWHYYCR8QHKDDebX3HVHcfw6K3GQ==" 1057 | }, 1058 | "coap-packet": { 1059 | "version": "0.1.13", 1060 | "resolved": "https://registry.npmjs.org/coap-packet/-/coap-packet-0.1.13.tgz", 1061 | "integrity": "sha512-jwCumbIDSSNx5Tufth31LWgiNU9trEF1OcgE0xOOlUe29l3+2yNPN128Ig0YEBln4tEW9zEwJECapeGPOdCeqg==" 1062 | }, 1063 | "debug": { 1064 | "version": "2.2.0", 1065 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 1066 | "integrity": "sha512-X0rGvJcskG1c3TgSCPqHJ0XJgwlcvOC7elJ5Y0hYuKBZoVqWpAMfLOeIh2UI/DCQ5ruodIjvsugZtjUYUw2pUw==", 1067 | "requires": { 1068 | "ms": "0.7.1" 1069 | }, 1070 | "dependencies": { 1071 | "ms": { 1072 | "version": "0.7.1", 1073 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 1074 | "integrity": "sha512-lRLiIR9fSNpnP6TC4v8+4OU7oStC01esuNowdQ34L+Gk8e5Puoc88IqJ+XAY/B3Mn2ZKis8l8HX90oU8ivzUHg==" 1075 | } 1076 | } 1077 | }, 1078 | "fastseries": { 1079 | "version": "1.7.2", 1080 | "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz", 1081 | "integrity": "sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==", 1082 | "requires": { 1083 | "reusify": "^1.0.0", 1084 | "xtend": "^4.0.0" 1085 | }, 1086 | "dependencies": { 1087 | "reusify": { 1088 | "version": "1.0.1", 1089 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.1.tgz", 1090 | "integrity": "sha512-QwCssfLPwXehhwODORcqQRdJu+wenkV9zafWRGODbJOIAsiXouQNVbWNWhILRWrnWmigxBn4YK1CbmRLr56Ozg==" 1091 | }, 1092 | "xtend": { 1093 | "version": "4.0.1", 1094 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 1095 | "integrity": "sha512-iTwvhNBRetXWe81+VcIw5YeadVSWyze7uA7nVnpP13ulrpnJ3UfQm5ApGnrkmxDJFdrblRdZs0EvaTCIfei5oQ==" 1096 | } 1097 | } 1098 | }, 1099 | "lru-cache": { 1100 | "version": "4.0.0", 1101 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.0.tgz", 1102 | "integrity": "sha512-WKhDkjlLwzE8jAQdQlsxLUQTPXLCKX/4cJk6s5AlRtJkDBk0IKH5O51bVDH61K9N4bhbbyvLM6EiOuE8ovApPA==", 1103 | "requires": { 1104 | "pseudomap": "^1.0.1", 1105 | "yallist": "^2.0.0" 1106 | }, 1107 | "dependencies": { 1108 | "pseudomap": { 1109 | "version": "1.0.2", 1110 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 1111 | "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==" 1112 | }, 1113 | "yallist": { 1114 | "version": "2.0.0", 1115 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz", 1116 | "integrity": "sha512-l446SSVnGyIspyBekF2U4g2cUMLwBJLu3IvXvqDSwmJFWtAgQ9B8CtHArNluFgI7nPm5+EEbH12fwPIwSXPQyg==" 1117 | } 1118 | } 1119 | }, 1120 | "readable-stream": { 1121 | "version": "2.0.5", 1122 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.5.tgz", 1123 | "integrity": "sha512-a2vWwaZC9d3kKrNKzEEETumWJxa18TgQiEB/A7fTDuHj6+GUa4RwMj8II9yogc/bbN/WO0/XlOLNYPbI8JpIsQ==", 1124 | "requires": { 1125 | "core-util-is": "~1.0.0", 1126 | "inherits": "~2.0.1", 1127 | "isarray": "0.0.1", 1128 | "process-nextick-args": "~1.0.6", 1129 | "string_decoder": "~0.10.x", 1130 | "util-deprecate": "~1.0.1" 1131 | }, 1132 | "dependencies": { 1133 | "core-util-is": { 1134 | "version": "1.0.2", 1135 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1136 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" 1137 | }, 1138 | "inherits": { 1139 | "version": "2.0.1", 1140 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 1141 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 1142 | }, 1143 | "isarray": { 1144 | "version": "0.0.1", 1145 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1146 | "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" 1147 | }, 1148 | "process-nextick-args": { 1149 | "version": "1.0.6", 1150 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz", 1151 | "integrity": "sha512-94OochEFu6/hLhOK4cpk2+CU5xVLmdimAnwrjPbb5VLct879euAq+I3mHUfP8u3abmdl2BLRX3oqEUvg5PBsag==" 1152 | }, 1153 | "string_decoder": { 1154 | "version": "0.10.31", 1155 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1156 | "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" 1157 | }, 1158 | "util-deprecate": { 1159 | "version": "1.0.2", 1160 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1161 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1162 | } 1163 | } 1164 | } 1165 | } 1166 | }, 1167 | "coap-cli": { 1168 | "version": "0.4.0", 1169 | "resolved": "https://registry.npmjs.org/coap-cli/-/coap-cli-0.4.0.tgz", 1170 | "integrity": "sha512-Y3Shntab+WIatXZkZafRh5LGbVvNAH8Ib1yHsBX7NJRAAAiPOwhyQVQ23lNh8Gi8mBRL/MfZhGyONoEKTlJcXg==", 1171 | "requires": { 1172 | "coap": "~0.12.0", 1173 | "commander": "~2.9.0", 1174 | "through2": "~2.0.0" 1175 | }, 1176 | "dependencies": { 1177 | "coap": { 1178 | "version": "0.12.1", 1179 | "resolved": "https://registry.npmjs.org/coap/-/coap-0.12.1.tgz", 1180 | "integrity": "sha512-BNLJqy0D9u+EqjuEO0JVdI/jJ2Dli34U9QtZ3Sfy9gupd6l6AjnNkeh9xNVLHGvhGjLf/xMk52AHSwqLN3Y0cQ==", 1181 | "requires": { 1182 | "bl": "~0.9.0", 1183 | "capitalize": "^1.0.0", 1184 | "coap-packet": "~0.1.12", 1185 | "fastseries": "^1.1.0", 1186 | "lru-cache": "~2.5.0", 1187 | "readable-stream": "~1.0.33" 1188 | }, 1189 | "dependencies": { 1190 | "bl": { 1191 | "version": "0.9.5", 1192 | "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", 1193 | "integrity": "sha512-njlCs8XLBIK7LCChTWfzWuIAxkpmmLXcL7/igCofFT1B039Sz0IPnAmosN5QaO22lU4qr8LcUz2ojUlE6pLkRQ==", 1194 | "requires": { 1195 | "readable-stream": "~1.0.26" 1196 | } 1197 | }, 1198 | "capitalize": { 1199 | "version": "1.0.0", 1200 | "resolved": "https://registry.npmjs.org/capitalize/-/capitalize-1.0.0.tgz", 1201 | "integrity": "sha512-ZvPF27zRh4ZiRbWYfSktO+t7xi4RPfqL9w6gfPAWGT5pT9TjB0rlP8cKHmKWHYYCR8QHKDDebX3HVHcfw6K3GQ==" 1202 | }, 1203 | "coap-packet": { 1204 | "version": "0.1.13", 1205 | "resolved": "https://registry.npmjs.org/coap-packet/-/coap-packet-0.1.13.tgz", 1206 | "integrity": "sha512-jwCumbIDSSNx5Tufth31LWgiNU9trEF1OcgE0xOOlUe29l3+2yNPN128Ig0YEBln4tEW9zEwJECapeGPOdCeqg==" 1207 | }, 1208 | "fastseries": { 1209 | "version": "1.7.2", 1210 | "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz", 1211 | "integrity": "sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==", 1212 | "requires": { 1213 | "reusify": "^1.0.0", 1214 | "xtend": "^4.0.0" 1215 | }, 1216 | "dependencies": { 1217 | "reusify": { 1218 | "version": "1.0.1", 1219 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.1.tgz", 1220 | "integrity": "sha512-QwCssfLPwXehhwODORcqQRdJu+wenkV9zafWRGODbJOIAsiXouQNVbWNWhILRWrnWmigxBn4YK1CbmRLr56Ozg==" 1221 | }, 1222 | "xtend": { 1223 | "version": "4.0.1", 1224 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 1225 | "integrity": "sha512-iTwvhNBRetXWe81+VcIw5YeadVSWyze7uA7nVnpP13ulrpnJ3UfQm5ApGnrkmxDJFdrblRdZs0EvaTCIfei5oQ==" 1226 | } 1227 | } 1228 | }, 1229 | "lru-cache": { 1230 | "version": "2.5.2", 1231 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.2.tgz", 1232 | "integrity": "sha512-wyqfj+623mgqv+bpjTdivSoC/LtY9oOrmKz2Cke0NZcgYW9Kce/qWjd9e5PDYf8wuiKfVeo8VnyOSSyeRiUsLw==" 1233 | }, 1234 | "readable-stream": { 1235 | "version": "1.0.33", 1236 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", 1237 | "integrity": "sha512-72KxhcKi8bAvHP/cyyWSP+ODS5ef0DIRs0OzrhGXw31q41f19aoELCbvd42FjhpyEDxQMRiiC5rq9rfE5PzTqg==", 1238 | "requires": { 1239 | "core-util-is": "~1.0.0", 1240 | "inherits": "~2.0.1", 1241 | "isarray": "0.0.1", 1242 | "string_decoder": "~0.10.x" 1243 | }, 1244 | "dependencies": { 1245 | "core-util-is": { 1246 | "version": "1.0.2", 1247 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1248 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" 1249 | }, 1250 | "inherits": { 1251 | "version": "2.0.1", 1252 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 1253 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 1254 | }, 1255 | "isarray": { 1256 | "version": "0.0.1", 1257 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1258 | "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" 1259 | }, 1260 | "string_decoder": { 1261 | "version": "0.10.31", 1262 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1263 | "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" 1264 | } 1265 | } 1266 | } 1267 | } 1268 | }, 1269 | "commander": { 1270 | "version": "2.9.0", 1271 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 1272 | "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", 1273 | "requires": { 1274 | "graceful-readlink": ">= 1.0.0" 1275 | }, 1276 | "dependencies": { 1277 | "graceful-readlink": { 1278 | "version": "1.0.1", 1279 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 1280 | "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==" 1281 | } 1282 | } 1283 | }, 1284 | "through2": { 1285 | "version": "2.0.1", 1286 | "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", 1287 | "integrity": "sha512-/vp02SIbpmVHapNMjox4hDBzykPdAOmH5y3INcKaxGfpEPSCMqzdWXyGfqPYyxoBLo1JpxBrlh3Z9esv0vWUYw==", 1288 | "requires": { 1289 | "readable-stream": "~2.0.0", 1290 | "xtend": "~4.0.0" 1291 | }, 1292 | "dependencies": { 1293 | "readable-stream": { 1294 | "version": "2.0.5", 1295 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.5.tgz", 1296 | "integrity": "sha512-a2vWwaZC9d3kKrNKzEEETumWJxa18TgQiEB/A7fTDuHj6+GUa4RwMj8II9yogc/bbN/WO0/XlOLNYPbI8JpIsQ==", 1297 | "requires": { 1298 | "core-util-is": "~1.0.0", 1299 | "inherits": "~2.0.1", 1300 | "isarray": "0.0.1", 1301 | "process-nextick-args": "~1.0.6", 1302 | "string_decoder": "~0.10.x", 1303 | "util-deprecate": "~1.0.1" 1304 | }, 1305 | "dependencies": { 1306 | "core-util-is": { 1307 | "version": "1.0.2", 1308 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1309 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" 1310 | }, 1311 | "inherits": { 1312 | "version": "2.0.1", 1313 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 1314 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 1315 | }, 1316 | "isarray": { 1317 | "version": "0.0.1", 1318 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1319 | "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" 1320 | }, 1321 | "process-nextick-args": { 1322 | "version": "1.0.6", 1323 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz", 1324 | "integrity": "sha512-94OochEFu6/hLhOK4cpk2+CU5xVLmdimAnwrjPbb5VLct879euAq+I3mHUfP8u3abmdl2BLRX3oqEUvg5PBsag==" 1325 | }, 1326 | "string_decoder": { 1327 | "version": "0.10.31", 1328 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1329 | "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" 1330 | }, 1331 | "util-deprecate": { 1332 | "version": "1.0.2", 1333 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1334 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1335 | } 1336 | } 1337 | }, 1338 | "xtend": { 1339 | "version": "4.0.1", 1340 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 1341 | "integrity": "sha512-iTwvhNBRetXWe81+VcIw5YeadVSWyze7uA7nVnpP13ulrpnJ3UfQm5ApGnrkmxDJFdrblRdZs0EvaTCIfei5oQ==" 1342 | } 1343 | } 1344 | } 1345 | } 1346 | }, 1347 | "command-node": { 1348 | "version": "0.1.1", 1349 | "resolved": "https://registry.npmjs.org/command-node/-/command-node-0.1.1.tgz", 1350 | "integrity": "sha1-YILnEHkDoUMaYODoCOld4L+eLTk=" 1351 | }, 1352 | "logops": { 1353 | "version": "0.5.0", 1354 | "resolved": "https://registry.npmjs.org/logops/-/logops-0.5.0.tgz", 1355 | "integrity": "sha512-8zwUTMlEE91GCSHnnSwLg3qwMEJlhx6SxuL5OjRKIIAa93PYg5nPAVCPY70mMWSAEVvclVCM5po0vDDLaqSQIg==", 1356 | "requires": { 1357 | "colors": "^1.1.2" 1358 | }, 1359 | "dependencies": { 1360 | "colors": { 1361 | "version": "1.1.2", 1362 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", 1363 | "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==" 1364 | } 1365 | } 1366 | }, 1367 | "mongodb": { 1368 | "version": "2.1.7", 1369 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.7.tgz", 1370 | "integrity": "sha512-jI96LkyWX2RlXfcd1RCxWTRm53v63f/RqdSjdFIlB+2oHAGUtVVUNjMCzhsod+CC2k/5LKvuwX218jz0ohwMYg==", 1371 | "requires": { 1372 | "es6-promise": "3.0.2", 1373 | "mongodb-core": "1.3.1", 1374 | "readable-stream": "1.0.31" 1375 | }, 1376 | "dependencies": { 1377 | "es6-promise": { 1378 | "version": "3.0.2", 1379 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", 1380 | "integrity": "sha512-CUD62/uqeE0L+EJeypOKuFfM56CFaH4vo+++J76bff0NkeQ2bBmWVCTNxL2hj9HeCYPkof6Gqea0BSeK17gBzA==" 1381 | }, 1382 | "mongodb-core": { 1383 | "version": "1.3.1", 1384 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.1.tgz", 1385 | "integrity": "sha512-CwKCEQ94PxRDGDihsx+QOp8yLKIdptni8W4OLtLj57c0lFWaewBarXXmbH7rvoHsgSu200PAYnLNI38q/72OCQ==", 1386 | "requires": { 1387 | "bson": "~0.4.21", 1388 | "require_optional": "~1.0.0" 1389 | }, 1390 | "dependencies": { 1391 | "bson": { 1392 | "version": "0.4.21", 1393 | "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.21.tgz", 1394 | "integrity": "sha512-D3IBqK2y4eOHGnAkUj+jUVbmvw0KcnEpA6rFiOsr5Km0t8LXc9mPu3cXUusBhXMFhE4cxPN3Tjh8WJ21OUj3bw==" 1395 | }, 1396 | "require_optional": { 1397 | "version": "1.0.0", 1398 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", 1399 | "integrity": "sha512-FWWx5HT9LXaoGlPBqkcL+7PzQ03ZaFlech34dxypnhQnen53qO2pDpf8ys594y0yjnsqgU9473CX0ZWFQr7XXQ==", 1400 | "requires": { 1401 | "resolve-from": "^2.0.0", 1402 | "semver": "^5.1.0" 1403 | }, 1404 | "dependencies": { 1405 | "resolve-from": { 1406 | "version": "2.0.0", 1407 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 1408 | "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" 1409 | }, 1410 | "semver": { 1411 | "version": "5.1.0", 1412 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz", 1413 | "integrity": "sha512-sfKXKhcz5XVyfUZa2V4RbjK0xjOJCMLNF9H4p4v0UCo9wNHM/lH9RDuyDbGEtxWLMDlPBc8xI7AbbVLKXty+rQ==" 1414 | } 1415 | } 1416 | } 1417 | } 1418 | }, 1419 | "readable-stream": { 1420 | "version": "1.0.31", 1421 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz", 1422 | "integrity": "sha512-tco/Dwv1f/sgIgN6CWdj/restacPKNskK6yps1981ivH2ZmLYcs5o5rVzL3qaO/cSkhN8hYOMWs7+glzOLSgRg==", 1423 | "requires": { 1424 | "core-util-is": "~1.0.0", 1425 | "inherits": "~2.0.1", 1426 | "isarray": "0.0.1", 1427 | "string_decoder": "~0.10.x" 1428 | }, 1429 | "dependencies": { 1430 | "core-util-is": { 1431 | "version": "1.0.2", 1432 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1433 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" 1434 | }, 1435 | "inherits": { 1436 | "version": "2.0.1", 1437 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 1438 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 1439 | }, 1440 | "isarray": { 1441 | "version": "0.0.1", 1442 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1443 | "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" 1444 | }, 1445 | "string_decoder": { 1446 | "version": "0.10.31", 1447 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1448 | "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" 1449 | } 1450 | } 1451 | } 1452 | } 1453 | }, 1454 | "mongoose": { 1455 | "version": "4.4.3", 1456 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-4.4.3.tgz", 1457 | "integrity": "sha512-wmHQElFInZfjWha5O+Xh9jCtWCigNoEXuf+sOMSG1ecdFFOZXkm0ZtoHXF7eiUgwZeT7L4XEC5aorFCAHDhi3w==", 1458 | "requires": { 1459 | "async": "1.5.2", 1460 | "bson": "0.4.21", 1461 | "hooks-fixed": "1.1.0", 1462 | "kareem": "1.0.1", 1463 | "mongodb": "2.1.6", 1464 | "mpath": "0.2.1", 1465 | "mpromise": "0.5.5", 1466 | "mquery": "1.6.3", 1467 | "ms": "0.7.1", 1468 | "muri": "1.1.0", 1469 | "regexp-clone": "0.0.1", 1470 | "sliced": "1.0.1" 1471 | }, 1472 | "dependencies": { 1473 | "bson": { 1474 | "version": "0.4.21", 1475 | "resolved": "https://registry.npmjs.org/bson/-/bson-0.4.21.tgz", 1476 | "integrity": "sha512-D3IBqK2y4eOHGnAkUj+jUVbmvw0KcnEpA6rFiOsr5Km0t8LXc9mPu3cXUusBhXMFhE4cxPN3Tjh8WJ21OUj3bw==" 1477 | }, 1478 | "hooks-fixed": { 1479 | "version": "1.1.0", 1480 | "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-1.1.0.tgz", 1481 | "integrity": "sha512-G6wwrJomxWd/zCaKYa5dMrhMahd3cTD2W5vBGZ/IRO/p6J/VykgrNLYe5/RV1JLBoq4NERWdohT/w8LSWIZjqA==" 1482 | }, 1483 | "kareem": { 1484 | "version": "1.0.1", 1485 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-1.0.1.tgz", 1486 | "integrity": "sha512-FWVjp1u+YDXpxfEZAyGAwulQsjwgqnNkbvju4PivaRHAeR1sOXe4Di4p9NkJlBVL+U1Xd8xBsX4lvtSVo690TA==" 1487 | }, 1488 | "mongodb": { 1489 | "version": "2.1.6", 1490 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.1.6.tgz", 1491 | "integrity": "sha512-3QMfEE3pXszHAXTRXd193wAr9otD+PKucbt7pjZKp4bch7v/VyZYRUJISzxwh4jDO3B1DAxHRgTKIcnwJYwQhw==", 1492 | "requires": { 1493 | "es6-promise": "3.0.2", 1494 | "mongodb-core": "1.3.1", 1495 | "readable-stream": "1.0.31" 1496 | }, 1497 | "dependencies": { 1498 | "es6-promise": { 1499 | "version": "3.0.2", 1500 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", 1501 | "integrity": "sha512-CUD62/uqeE0L+EJeypOKuFfM56CFaH4vo+++J76bff0NkeQ2bBmWVCTNxL2hj9HeCYPkof6Gqea0BSeK17gBzA==" 1502 | }, 1503 | "mongodb-core": { 1504 | "version": "1.3.1", 1505 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-1.3.1.tgz", 1506 | "integrity": "sha512-CwKCEQ94PxRDGDihsx+QOp8yLKIdptni8W4OLtLj57c0lFWaewBarXXmbH7rvoHsgSu200PAYnLNI38q/72OCQ==", 1507 | "requires": { 1508 | "bson": "~0.4.21", 1509 | "require_optional": "~1.0.0" 1510 | }, 1511 | "dependencies": { 1512 | "require_optional": { 1513 | "version": "1.0.0", 1514 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.0.tgz", 1515 | "integrity": "sha512-FWWx5HT9LXaoGlPBqkcL+7PzQ03ZaFlech34dxypnhQnen53qO2pDpf8ys594y0yjnsqgU9473CX0ZWFQr7XXQ==", 1516 | "requires": { 1517 | "resolve-from": "^2.0.0", 1518 | "semver": "^5.1.0" 1519 | }, 1520 | "dependencies": { 1521 | "resolve-from": { 1522 | "version": "2.0.0", 1523 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 1524 | "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" 1525 | }, 1526 | "semver": { 1527 | "version": "5.1.0", 1528 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz", 1529 | "integrity": "sha512-sfKXKhcz5XVyfUZa2V4RbjK0xjOJCMLNF9H4p4v0UCo9wNHM/lH9RDuyDbGEtxWLMDlPBc8xI7AbbVLKXty+rQ==" 1530 | } 1531 | } 1532 | } 1533 | } 1534 | }, 1535 | "readable-stream": { 1536 | "version": "1.0.31", 1537 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz", 1538 | "integrity": "sha512-tco/Dwv1f/sgIgN6CWdj/restacPKNskK6yps1981ivH2ZmLYcs5o5rVzL3qaO/cSkhN8hYOMWs7+glzOLSgRg==", 1539 | "requires": { 1540 | "core-util-is": "~1.0.0", 1541 | "inherits": "~2.0.1", 1542 | "isarray": "0.0.1", 1543 | "string_decoder": "~0.10.x" 1544 | }, 1545 | "dependencies": { 1546 | "core-util-is": { 1547 | "version": "1.0.2", 1548 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1549 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" 1550 | }, 1551 | "inherits": { 1552 | "version": "2.0.1", 1553 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", 1554 | "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" 1555 | }, 1556 | "isarray": { 1557 | "version": "0.0.1", 1558 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1559 | "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" 1560 | }, 1561 | "string_decoder": { 1562 | "version": "0.10.31", 1563 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1564 | "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" 1565 | } 1566 | } 1567 | } 1568 | } 1569 | }, 1570 | "mpath": { 1571 | "version": "0.2.1", 1572 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.2.1.tgz", 1573 | "integrity": "sha512-+wsZfFqAjtiVkt5LTIUdsiB7zxWKvcCL4WJhnB/+r1GwrLZAV/eX5OCwPD5jy4fbo2JNfjBlCsRcjF6Mk/htug==" 1574 | }, 1575 | "mpromise": { 1576 | "version": "0.5.5", 1577 | "resolved": "https://registry.npmjs.org/mpromise/-/mpromise-0.5.5.tgz", 1578 | "integrity": "sha512-b/IJDqWlRXIW3ZouxIkUYLZFrr4qK/oUEgfVAywuvm77nTdDmY6y57lHxA8kfLnOSM+SbAUN/VvU1RxsGBLkQw==" 1579 | }, 1580 | "mquery": { 1581 | "version": "1.6.3", 1582 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-1.6.3.tgz", 1583 | "integrity": "sha512-pHgPD0+8w5YsOui7Gri+lnHMO245LvvrigUGRiZPefflqMXKo86CX/zZ/iEzdm5PBmIjzci1FaxjBiZzslKKiw==", 1584 | "requires": { 1585 | "bluebird": "2.9.26", 1586 | "debug": "2.2.0", 1587 | "regexp-clone": "0.0.1", 1588 | "sliced": "0.0.5" 1589 | }, 1590 | "dependencies": { 1591 | "bluebird": { 1592 | "version": "2.9.26", 1593 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.26.tgz", 1594 | "integrity": "sha512-rCR4rqoI1uXUObTgSd7M0Jhp4CXxqPdfmp7NDJ5zmxtwWTNeL6mGkPTL5ehuKK62//S1W/cY1vDjuIXwa6wm5A==" 1595 | }, 1596 | "debug": { 1597 | "version": "2.2.0", 1598 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", 1599 | "integrity": "sha512-X0rGvJcskG1c3TgSCPqHJ0XJgwlcvOC7elJ5Y0hYuKBZoVqWpAMfLOeIh2UI/DCQ5ruodIjvsugZtjUYUw2pUw==", 1600 | "requires": { 1601 | "ms": "0.7.1" 1602 | } 1603 | }, 1604 | "sliced": { 1605 | "version": "0.0.5", 1606 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-0.0.5.tgz", 1607 | "integrity": "sha512-9bYT917D6H3+q8GlQBJmLVz3bc4OeVGfZ2BB12wvLnluTGfG6/8UdOUbKJDW1EEx9SZMDbjnatkau5/XcUeyOw==" 1608 | } 1609 | } 1610 | }, 1611 | "ms": { 1612 | "version": "0.7.1", 1613 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", 1614 | "integrity": "sha512-lRLiIR9fSNpnP6TC4v8+4OU7oStC01esuNowdQ34L+Gk8e5Puoc88IqJ+XAY/B3Mn2ZKis8l8HX90oU8ivzUHg==" 1615 | }, 1616 | "muri": { 1617 | "version": "1.1.0", 1618 | "resolved": "https://registry.npmjs.org/muri/-/muri-1.1.0.tgz", 1619 | "integrity": "sha512-Kr34tn9s0Ej2dJgTkfUerxgikZ/7MOp0ALDCltDi/pncI3VdQzQFnxEjtZbt3wSlZR4n7xXTIMJRoKio269aMg==" 1620 | }, 1621 | "regexp-clone": { 1622 | "version": "0.0.1", 1623 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-0.0.1.tgz", 1624 | "integrity": "sha512-tfYXF0HXEYh3AtgdjqNLQ8+tmZSAKIS7KtOjmB1laJgfbsi+Lf2RVNwLZVOE3U27yBXikzQuIXglLlakvb8Thw==" 1625 | }, 1626 | "sliced": { 1627 | "version": "1.0.1", 1628 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 1629 | "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" 1630 | } 1631 | } 1632 | }, 1633 | "mongoose-auto-increment": { 1634 | "version": "5.0.1", 1635 | "resolved": "https://registry.npmjs.org/mongoose-auto-increment/-/mongoose-auto-increment-5.0.1.tgz", 1636 | "integrity": "sha512-fuSw0np0ZZXYjNBBrD6Wg0y70N0i5NhBuH3AIETTXCchaq45FeHpISoQ3fFbbdSFhfVEDRtg+hVxEDpFjdI2lw==", 1637 | "requires": { 1638 | "extend": "^3.0.0" 1639 | }, 1640 | "dependencies": { 1641 | "extend": { 1642 | "version": "3.0.0", 1643 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", 1644 | "integrity": "sha512-5mYyg57hpD+sFaJmgNL9BidQ5C7dmJE3U5vzlRWbuqG+8dytvYEoxvKs6Tj5cm3LpMsFvRt20qz1ckezmsOUgQ==" 1645 | } 1646 | } 1647 | }, 1648 | "underscore": { 1649 | "version": "1.7.0", 1650 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", 1651 | "integrity": "sha512-cp0oQQyZhUM1kpJDLdGO1jPZHgS/MpzoWYfe9+CM2h/QGDZlqwT2T3YGukuBdaNJ/CAPoeyAZRRHz8JFo176vA==" 1652 | } 1653 | } 1654 | }, 1655 | "minimatch": { 1656 | "version": "3.0.4", 1657 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1658 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1659 | "dev": true, 1660 | "requires": { 1661 | "brace-expansion": "^1.1.7" 1662 | } 1663 | }, 1664 | "mkdirp": { 1665 | "version": "1.0.4", 1666 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 1667 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" 1668 | }, 1669 | "mocha": { 1670 | "version": "8.4.0", 1671 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", 1672 | "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", 1673 | "dev": true, 1674 | "requires": { 1675 | "@ungap/promise-all-settled": "1.1.2", 1676 | "ansi-colors": "4.1.1", 1677 | "browser-stdout": "1.3.1", 1678 | "chokidar": "3.5.1", 1679 | "debug": "4.3.1", 1680 | "diff": "5.0.0", 1681 | "escape-string-regexp": "4.0.0", 1682 | "find-up": "5.0.0", 1683 | "glob": "7.1.6", 1684 | "growl": "1.10.5", 1685 | "he": "1.2.0", 1686 | "js-yaml": "4.0.0", 1687 | "log-symbols": "4.0.0", 1688 | "minimatch": "3.0.4", 1689 | "ms": "2.1.3", 1690 | "nanoid": "3.1.20", 1691 | "serialize-javascript": "5.0.1", 1692 | "strip-json-comments": "3.1.1", 1693 | "supports-color": "8.1.1", 1694 | "which": "2.0.2", 1695 | "wide-align": "1.1.3", 1696 | "workerpool": "6.1.0", 1697 | "yargs": "16.2.0", 1698 | "yargs-parser": "20.2.4", 1699 | "yargs-unparser": "2.0.0" 1700 | }, 1701 | "dependencies": { 1702 | "debug": { 1703 | "version": "4.3.1", 1704 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1705 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1706 | "dev": true, 1707 | "requires": { 1708 | "ms": "2.1.2" 1709 | }, 1710 | "dependencies": { 1711 | "ms": { 1712 | "version": "2.1.2", 1713 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1714 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1715 | "dev": true 1716 | } 1717 | } 1718 | }, 1719 | "ms": { 1720 | "version": "2.1.3", 1721 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1722 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1723 | "dev": true 1724 | } 1725 | } 1726 | }, 1727 | "ms": { 1728 | "version": "2.0.0", 1729 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1730 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1731 | }, 1732 | "nanoid": { 1733 | "version": "3.1.20", 1734 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", 1735 | "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", 1736 | "dev": true 1737 | }, 1738 | "next-tick": { 1739 | "version": "1.0.0", 1740 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 1741 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 1742 | }, 1743 | "node-fetch": { 1744 | "version": "2.6.1", 1745 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 1746 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", 1747 | "dev": true 1748 | }, 1749 | "node-gyp-build": { 1750 | "version": "4.2.3", 1751 | "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", 1752 | "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==" 1753 | }, 1754 | "nodemailer": { 1755 | "version": "6.6.1", 1756 | "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.1.tgz", 1757 | "integrity": "sha512-1xzFN3gqv+/qJ6YRyxBxfTYstLNt0FCtZaFRvf4Sg9wxNGWbwFmGXVpfSi6ThGK6aRxAo+KjHtYSW8NvCsNSAg==" 1758 | }, 1759 | "normalize-path": { 1760 | "version": "3.0.0", 1761 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1762 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1763 | "dev": true 1764 | }, 1765 | "object-inspect": { 1766 | "version": "1.10.3", 1767 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", 1768 | "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", 1769 | "dev": true 1770 | }, 1771 | "once": { 1772 | "version": "1.4.0", 1773 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1774 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1775 | "dev": true, 1776 | "requires": { 1777 | "wrappy": "1" 1778 | } 1779 | }, 1780 | "p-limit": { 1781 | "version": "3.1.0", 1782 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1783 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1784 | "dev": true, 1785 | "requires": { 1786 | "yocto-queue": "^0.1.0" 1787 | } 1788 | }, 1789 | "p-locate": { 1790 | "version": "5.0.0", 1791 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1792 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1793 | "dev": true, 1794 | "requires": { 1795 | "p-limit": "^3.0.2" 1796 | } 1797 | }, 1798 | "path-exists": { 1799 | "version": "4.0.0", 1800 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1801 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1802 | "dev": true 1803 | }, 1804 | "path-is-absolute": { 1805 | "version": "1.0.1", 1806 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1807 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1808 | "dev": true 1809 | }, 1810 | "picomatch": { 1811 | "version": "2.3.0", 1812 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 1813 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 1814 | "dev": true 1815 | }, 1816 | "pop-iterate": { 1817 | "version": "1.0.1", 1818 | "resolved": "https://registry.npmjs.org/pop-iterate/-/pop-iterate-1.0.1.tgz", 1819 | "integrity": "sha1-zqz9q0q/NT16DyqqLB/Hs/lBO6M=", 1820 | "dev": true 1821 | }, 1822 | "q": { 1823 | "version": "2.0.3", 1824 | "resolved": "https://registry.npmjs.org/q/-/q-2.0.3.tgz", 1825 | "integrity": "sha1-dbjbAlWhpa+C9Yw/Oqoe/sfQ0TQ=", 1826 | "dev": true, 1827 | "requires": { 1828 | "asap": "^2.0.0", 1829 | "pop-iterate": "^1.0.1", 1830 | "weak-map": "^1.0.5" 1831 | } 1832 | }, 1833 | "querystringify": { 1834 | "version": "2.2.0", 1835 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", 1836 | "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", 1837 | "dev": true 1838 | }, 1839 | "randombytes": { 1840 | "version": "2.1.0", 1841 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1842 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1843 | "dev": true, 1844 | "requires": { 1845 | "safe-buffer": "^5.1.0" 1846 | } 1847 | }, 1848 | "readable-stream": { 1849 | "version": "1.0.34", 1850 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 1851 | "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", 1852 | "requires": { 1853 | "core-util-is": "~1.0.0", 1854 | "inherits": "~2.0.1", 1855 | "isarray": "0.0.1", 1856 | "string_decoder": "~0.10.x" 1857 | } 1858 | }, 1859 | "readdirp": { 1860 | "version": "3.5.0", 1861 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 1862 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 1863 | "dev": true, 1864 | "requires": { 1865 | "picomatch": "^2.2.1" 1866 | } 1867 | }, 1868 | "require-directory": { 1869 | "version": "2.1.1", 1870 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1871 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1872 | "dev": true 1873 | }, 1874 | "requires-port": { 1875 | "version": "1.0.0", 1876 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 1877 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", 1878 | "dev": true 1879 | }, 1880 | "reusify": { 1881 | "version": "1.0.4", 1882 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1883 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" 1884 | }, 1885 | "rootpath": { 1886 | "version": "0.1.2", 1887 | "resolved": "https://registry.npmjs.org/rootpath/-/rootpath-0.1.2.tgz", 1888 | "integrity": "sha1-Wzeah9ypBum5HWkKWZQ5vvJn6ms=", 1889 | "dev": true 1890 | }, 1891 | "safe-buffer": { 1892 | "version": "5.2.1", 1893 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1894 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1895 | }, 1896 | "scmp": { 1897 | "version": "2.1.0", 1898 | "resolved": "https://registry.npmjs.org/scmp/-/scmp-2.1.0.tgz", 1899 | "integrity": "sha512-o/mRQGk9Rcer/jEEw/yw4mwo3EU/NvYvp577/Btqrym9Qy5/MdWGBqipbALgd2lrdWTJ5/gqDusxfnQBxOxT2Q==", 1900 | "dev": true 1901 | }, 1902 | "semver": { 1903 | "version": "5.7.1", 1904 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1905 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1906 | "dev": true 1907 | }, 1908 | "serialize-javascript": { 1909 | "version": "5.0.1", 1910 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", 1911 | "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", 1912 | "dev": true, 1913 | "requires": { 1914 | "randombytes": "^2.1.0" 1915 | } 1916 | }, 1917 | "side-channel": { 1918 | "version": "1.0.4", 1919 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1920 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1921 | "dev": true, 1922 | "requires": { 1923 | "call-bind": "^1.0.0", 1924 | "get-intrinsic": "^1.0.2", 1925 | "object-inspect": "^1.9.0" 1926 | } 1927 | }, 1928 | "sprintf-js": { 1929 | "version": "1.0.3", 1930 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1931 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1932 | "dev": true 1933 | }, 1934 | "sprintf-kit": { 1935 | "version": "2.0.0", 1936 | "resolved": "https://registry.npmjs.org/sprintf-kit/-/sprintf-kit-2.0.0.tgz", 1937 | "integrity": "sha512-/0d2YTn8ZFVpIPAU230S9ZLF8WDkSSRWvh/UOLM7zzvkCchum1TtouRgyV8OfgOaYilSGU4lSSqzwBXJVlAwUw==", 1938 | "requires": { 1939 | "es5-ext": "^0.10.46" 1940 | } 1941 | }, 1942 | "stream-events": { 1943 | "version": "1.0.5", 1944 | "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", 1945 | "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", 1946 | "dev": true, 1947 | "requires": { 1948 | "stubs": "^3.0.0" 1949 | } 1950 | }, 1951 | "string-width": { 1952 | "version": "2.1.1", 1953 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1954 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1955 | "dev": true, 1956 | "requires": { 1957 | "is-fullwidth-code-point": "^2.0.0", 1958 | "strip-ansi": "^4.0.0" 1959 | } 1960 | }, 1961 | "string_decoder": { 1962 | "version": "0.10.31", 1963 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1964 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 1965 | }, 1966 | "strip-ansi": { 1967 | "version": "4.0.0", 1968 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1969 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1970 | "dev": true, 1971 | "requires": { 1972 | "ansi-regex": "^3.0.0" 1973 | } 1974 | }, 1975 | "strip-json-comments": { 1976 | "version": "3.1.1", 1977 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1978 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1979 | "dev": true 1980 | }, 1981 | "stubs": { 1982 | "version": "3.0.0", 1983 | "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", 1984 | "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", 1985 | "dev": true 1986 | }, 1987 | "supports-color": { 1988 | "version": "8.1.1", 1989 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1990 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1991 | "dev": true, 1992 | "requires": { 1993 | "has-flag": "^4.0.0" 1994 | } 1995 | }, 1996 | "teeny-request": { 1997 | "version": "6.0.1", 1998 | "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", 1999 | "integrity": "sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g==", 2000 | "dev": true, 2001 | "requires": { 2002 | "http-proxy-agent": "^4.0.0", 2003 | "https-proxy-agent": "^4.0.0", 2004 | "node-fetch": "^2.2.0", 2005 | "stream-events": "^1.0.5", 2006 | "uuid": "^3.3.2" 2007 | }, 2008 | "dependencies": { 2009 | "agent-base": { 2010 | "version": "5.1.1", 2011 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", 2012 | "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", 2013 | "dev": true 2014 | }, 2015 | "debug": { 2016 | "version": "4.3.1", 2017 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 2018 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 2019 | "dev": true, 2020 | "requires": { 2021 | "ms": "2.1.2" 2022 | } 2023 | }, 2024 | "https-proxy-agent": { 2025 | "version": "4.0.0", 2026 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", 2027 | "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", 2028 | "dev": true, 2029 | "requires": { 2030 | "agent-base": "5", 2031 | "debug": "4" 2032 | } 2033 | }, 2034 | "ms": { 2035 | "version": "2.1.2", 2036 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2037 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 2038 | "dev": true 2039 | } 2040 | } 2041 | }, 2042 | "to-regex-range": { 2043 | "version": "5.0.1", 2044 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2045 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2046 | "dev": true, 2047 | "requires": { 2048 | "is-number": "^7.0.0" 2049 | } 2050 | }, 2051 | "twilio": { 2052 | "version": "3.63.1", 2053 | "resolved": "https://registry.npmjs.org/twilio/-/twilio-3.63.1.tgz", 2054 | "integrity": "sha512-xwtOM78sO2jGxKg1AW+7XlJdrhTMW9dzr6665O+IB/VtNVQB7JQS48pLCZFnBaTvZOILVO0Q6t63wv24hIbr/A==", 2055 | "dev": true, 2056 | "requires": { 2057 | "axios": "^0.21.1", 2058 | "dayjs": "^1.8.29", 2059 | "https-proxy-agent": "^5.0.0", 2060 | "jsonwebtoken": "^8.5.1", 2061 | "lodash": "^4.17.19", 2062 | "q": "2.0.x", 2063 | "qs": "^6.9.4", 2064 | "rootpath": "^0.1.2", 2065 | "scmp": "^2.1.0", 2066 | "url-parse": "^1.5.0", 2067 | "xmlbuilder": "^13.0.2" 2068 | }, 2069 | "dependencies": { 2070 | "qs": { 2071 | "version": "6.10.1", 2072 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", 2073 | "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", 2074 | "dev": true, 2075 | "requires": { 2076 | "side-channel": "^1.0.4" 2077 | } 2078 | } 2079 | } 2080 | }, 2081 | "type": { 2082 | "version": "1.2.0", 2083 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 2084 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 2085 | }, 2086 | "typedarray-to-buffer": { 2087 | "version": "3.1.5", 2088 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 2089 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 2090 | "requires": { 2091 | "is-typedarray": "^1.0.0" 2092 | } 2093 | }, 2094 | "underscore": { 2095 | "version": "1.13.1", 2096 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz", 2097 | "integrity": "sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==" 2098 | }, 2099 | "url-parse": { 2100 | "version": "1.5.1", 2101 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", 2102 | "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", 2103 | "dev": true, 2104 | "requires": { 2105 | "querystringify": "^2.1.1", 2106 | "requires-port": "^1.0.0" 2107 | } 2108 | }, 2109 | "urlgrey": { 2110 | "version": "0.4.4", 2111 | "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", 2112 | "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=", 2113 | "dev": true 2114 | }, 2115 | "utf-8-validate": { 2116 | "version": "5.0.5", 2117 | "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz", 2118 | "integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==", 2119 | "requires": { 2120 | "node-gyp-build": "^4.2.0" 2121 | } 2122 | }, 2123 | "util": { 2124 | "version": "0.10.4", 2125 | "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", 2126 | "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", 2127 | "requires": { 2128 | "inherits": "2.0.3" 2129 | }, 2130 | "dependencies": { 2131 | "inherits": { 2132 | "version": "2.0.3", 2133 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 2134 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 2135 | } 2136 | } 2137 | }, 2138 | "util-deprecate": { 2139 | "version": "1.0.2", 2140 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2141 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2142 | }, 2143 | "utils-merge": { 2144 | "version": "1.0.1", 2145 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 2146 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 2147 | }, 2148 | "uuid": { 2149 | "version": "3.4.0", 2150 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 2151 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 2152 | "dev": true 2153 | }, 2154 | "weak-map": { 2155 | "version": "1.0.5", 2156 | "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.5.tgz", 2157 | "integrity": "sha1-eWkVhNmGB/UHC9O3CkDmuyLkAes=", 2158 | "dev": true 2159 | }, 2160 | "websocket": { 2161 | "version": "1.0.34", 2162 | "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", 2163 | "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", 2164 | "requires": { 2165 | "bufferutil": "^4.0.1", 2166 | "debug": "^2.2.0", 2167 | "es5-ext": "^0.10.50", 2168 | "typedarray-to-buffer": "^3.1.5", 2169 | "utf-8-validate": "^5.0.2", 2170 | "yaeti": "^0.0.6" 2171 | } 2172 | }, 2173 | "which": { 2174 | "version": "2.0.2", 2175 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2176 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2177 | "dev": true, 2178 | "requires": { 2179 | "isexe": "^2.0.0" 2180 | } 2181 | }, 2182 | "wide-align": { 2183 | "version": "1.1.3", 2184 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 2185 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 2186 | "dev": true, 2187 | "requires": { 2188 | "string-width": "^1.0.2 || 2" 2189 | } 2190 | }, 2191 | "workerpool": { 2192 | "version": "6.1.0", 2193 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", 2194 | "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", 2195 | "dev": true 2196 | }, 2197 | "wotcity.io": { 2198 | "version": "0.9.8", 2199 | "resolved": "https://registry.npmjs.org/wotcity.io/-/wotcity.io-0.9.8.tgz", 2200 | "integrity": "sha1-xXGCThmx3/RMmWKTmt+C+HPFl/Q=", 2201 | "requires": { 2202 | "backbone": "^1.2.0", 2203 | "bl": "^0.9.4", 2204 | "bluebird": "^3.3.3", 2205 | "cluster": "^0.7.7", 2206 | "coap": "^0.10.3", 2207 | "lwm2m-node-lib": "^0.4.1", 2208 | "underscore": "^1.8.3", 2209 | "utils-merge": "^1.0.0", 2210 | "websocket": "^1.0.17" 2211 | }, 2212 | "dependencies": { 2213 | "bl": { 2214 | "version": "0.9.5", 2215 | "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", 2216 | "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", 2217 | "requires": { 2218 | "readable-stream": "~1.0.26" 2219 | } 2220 | }, 2221 | "coap": { 2222 | "version": "0.10.5", 2223 | "resolved": "https://registry.npmjs.org/coap/-/coap-0.10.5.tgz", 2224 | "integrity": "sha1-BeA3PLf987v06n5trEzsefraQSI=", 2225 | "requires": { 2226 | "bl": "~0.9.0", 2227 | "coap-packet": "~0.1.12", 2228 | "fastseries": "^1.1.0", 2229 | "lru-cache": "~2.5.0", 2230 | "readable-stream": "~1.0.33" 2231 | } 2232 | }, 2233 | "fastseries": { 2234 | "version": "1.7.2", 2235 | "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz", 2236 | "integrity": "sha1-0izhO5Qz3/M4jZHb1ri9qbIaD0s=", 2237 | "requires": { 2238 | "reusify": "^1.0.0", 2239 | "xtend": "^4.0.0" 2240 | } 2241 | } 2242 | } 2243 | }, 2244 | "wrap-ansi": { 2245 | "version": "7.0.0", 2246 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2247 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2248 | "dev": true, 2249 | "requires": { 2250 | "ansi-styles": "^4.0.0", 2251 | "string-width": "^4.1.0", 2252 | "strip-ansi": "^6.0.0" 2253 | }, 2254 | "dependencies": { 2255 | "ansi-regex": { 2256 | "version": "5.0.0", 2257 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2258 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2259 | "dev": true 2260 | }, 2261 | "is-fullwidth-code-point": { 2262 | "version": "3.0.0", 2263 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2264 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2265 | "dev": true 2266 | }, 2267 | "string-width": { 2268 | "version": "4.2.2", 2269 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 2270 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 2271 | "dev": true, 2272 | "requires": { 2273 | "emoji-regex": "^8.0.0", 2274 | "is-fullwidth-code-point": "^3.0.0", 2275 | "strip-ansi": "^6.0.0" 2276 | } 2277 | }, 2278 | "strip-ansi": { 2279 | "version": "6.0.0", 2280 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2281 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2282 | "dev": true, 2283 | "requires": { 2284 | "ansi-regex": "^5.0.0" 2285 | } 2286 | } 2287 | } 2288 | }, 2289 | "wrappy": { 2290 | "version": "1.0.2", 2291 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2292 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2293 | "dev": true 2294 | }, 2295 | "xmlbuilder": { 2296 | "version": "13.0.2", 2297 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", 2298 | "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", 2299 | "dev": true 2300 | }, 2301 | "xtend": { 2302 | "version": "4.0.2", 2303 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 2304 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 2305 | }, 2306 | "y18n": { 2307 | "version": "5.0.8", 2308 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 2309 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 2310 | "dev": true 2311 | }, 2312 | "yaeti": { 2313 | "version": "0.0.6", 2314 | "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", 2315 | "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" 2316 | }, 2317 | "yallist": { 2318 | "version": "3.1.1", 2319 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", 2320 | "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" 2321 | }, 2322 | "yargs": { 2323 | "version": "16.2.0", 2324 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 2325 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 2326 | "dev": true, 2327 | "requires": { 2328 | "cliui": "^7.0.2", 2329 | "escalade": "^3.1.1", 2330 | "get-caller-file": "^2.0.5", 2331 | "require-directory": "^2.1.1", 2332 | "string-width": "^4.2.0", 2333 | "y18n": "^5.0.5", 2334 | "yargs-parser": "^20.2.2" 2335 | }, 2336 | "dependencies": { 2337 | "ansi-regex": { 2338 | "version": "5.0.0", 2339 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 2340 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 2341 | "dev": true 2342 | }, 2343 | "is-fullwidth-code-point": { 2344 | "version": "3.0.0", 2345 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2346 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2347 | "dev": true 2348 | }, 2349 | "string-width": { 2350 | "version": "4.2.2", 2351 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 2352 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 2353 | "dev": true, 2354 | "requires": { 2355 | "emoji-regex": "^8.0.0", 2356 | "is-fullwidth-code-point": "^3.0.0", 2357 | "strip-ansi": "^6.0.0" 2358 | } 2359 | }, 2360 | "strip-ansi": { 2361 | "version": "6.0.0", 2362 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2363 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2364 | "dev": true, 2365 | "requires": { 2366 | "ansi-regex": "^5.0.0" 2367 | } 2368 | } 2369 | } 2370 | }, 2371 | "yargs-parser": { 2372 | "version": "20.2.4", 2373 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 2374 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 2375 | "dev": true 2376 | }, 2377 | "yargs-unparser": { 2378 | "version": "2.0.0", 2379 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 2380 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 2381 | "dev": true, 2382 | "requires": { 2383 | "camelcase": "^6.0.0", 2384 | "decamelize": "^4.0.0", 2385 | "flat": "^5.0.2", 2386 | "is-plain-obj": "^2.1.0" 2387 | } 2388 | }, 2389 | "yocto-queue": { 2390 | "version": "0.1.0", 2391 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2392 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2393 | "dev": true 2394 | } 2395 | } 2396 | } 2397 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "devify-server", 3 | "version": "3.0.0", 4 | "description": "Boilerplates for IoT cloud servers", 5 | "keywords": [ 6 | "iot" 7 | ], 8 | "author": "jollen (http://jollen.org/)", 9 | "main": "libs/index.js", 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/DevifyPlatform/devify-server.git" 13 | }, 14 | "homepage": "https://github.com/DevifyPlatform/devify-server.git", 15 | "dependencies": { 16 | "bl": "^5.0.0", 17 | "bluebird": "^3.7.2", 18 | "bson": "^4.4.0", 19 | "coap": "^0.24.0", 20 | "nodemailer": "^6.6.1", 21 | "util": "^0.10.3", 22 | "utils-merge": "^1.0.0", 23 | "websocket": "^1.0.34", 24 | "wotcity.io": "^0.9.3" 25 | }, 26 | "scripts": { 27 | "test": "make test", 28 | "start": "node ./websocket-broker-server.js" 29 | }, 30 | "devDependencies": { 31 | "codecov": "^3.7.1", 32 | "mocha": "^8.4.0", 33 | "twilio": "^3.63.1" 34 | }, 35 | "license": "MIT License" 36 | } 37 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-console-print/README.md: -------------------------------------------------------------------------------- 1 | ![](http://res.cloudinary.com/jollen/image/upload/h_110/v1455862763/devify-logo_rh63vl.png) 2 | 3 | ESP8266 over the Web: Getting started with IoT System Architecture 4 | 5 | ## Project Goal 6 | 7 | The use scenario of this project. 8 | 9 | * Connect an Air Quality sensor with ESP8266 10 | * Programming ESP8266 in Lua programming language 11 | * Setup a CoAP server at your host PC 12 | * Print the data on the screen when CoAP server receives the data from ESP8266 13 | 14 | ## Prerequisites 15 | 16 | 1. [Node.js](https://nodejs.org). Note: Node should be with a version above 4.3 17 | 2. ESP8266 or NodeMCU development kit 18 | 3. An air quality sensor or any other sensor which is the type of analog in 19 | 20 | ![](https://cloud.githubusercontent.com/assets/1126021/13700095/beb9fa90-e7b9-11e5-8f61-a729ce3e1016.JPG) 21 | 22 | Figure-1: Connect an air quality sensor to a NodeMCU development kit. 23 | 24 | ## Quickstart 25 | 26 | ![The use cases that we're going to achieve in the next two lessons](https://cloud.githubusercontent.com/assets/1126021/13699804/b9498212-e7b7-11e5-99e3-734ac6bf91da.png) 27 | 28 | Figure-2: The use cases that we're going to achieve in the next two lessons. 29 | 30 | ### Device Side 31 | 32 | * Connect your ESP8266 to WiFi AP 33 | * Run [coap-air-quality.lua](esp8266/coap-air-quality.lua) in this project 34 | 35 | ### Server Side 36 | 37 | * Run *server.js* in this project at your host PC 38 | 39 | ``` 40 | $ npm install 41 | $ export HOST= 42 | $ export PORT= 43 | $ npm start 44 | ``` 45 | 46 | ## Getting Started 47 | 48 | For IoT developers, *Devify* is a software framework which makes it easy to build IoT server using CoAP and WebSocket. It minimizes the time to write a **Hello, World** IoT server. The following explains how ```esp8266-coap-server.js``` works. 49 | 50 | First, it requires ```devify-server``` library and get a CoAP server instance. 51 | 52 | ``` 53 | var server = require('devify-server').coapBroker; 54 | ``` 55 | Then, it invokes ```start()``` method to start the server. 56 | 57 | ``` 58 | server.start(); 59 | ``` 60 | 61 | ## Use *onmessage* callback 62 | 63 | The ```server.js``` demo doesn't print any thing on the screen. To print data received from NodeMCU at the terminal console, you need to implement the ```onmessage``` callback function. 64 | 65 | To print the data sent from NodeMCU, give a ```onmessage``` function callback to ```start()```. 66 | 67 | ``` 68 | var onmessage = function(message) { 69 | // Parse strings to JSON object. 70 | var obj = JSON.parse(message.data); 71 | // Print strings. 72 | console.log(' ' + message.data); 73 | }; 74 | 75 | server.start({ 76 | onmessage: onmessage, 77 | }); 78 | ``` 79 | Once there is an incoming message from NodeMCU, the ```onmessage``` function will be called with one parameter of *Object* type. The data from ESP8266 is stored at the ```data``` property. The data from ESP8266 is in JSON string format. To read this data, it should be parsed into *Object* type. 80 | 81 | ``` 82 | var obj = JSON.parse(message.data); 83 | ``` 84 | 85 | This demo is simple. However, it's not the best practice to get data from NodeMCU. The best practice is explained at [Understanding Resource-Oriented](README.md#understanding-resource-oriented). 86 | 87 | ## NodeMCU 88 | 89 | The full source list is as the following. 90 | 91 | ``` 92 | -- Configure the ESP as a station (client) 93 | wifi.setmode(wifi.STATION) 94 | wifi.sta.config("", "") 95 | wifi.sta.autoconnect(1) 96 | 97 | -- Create a CoAP client 98 | cc = coap.Client() 99 | 100 | -- Make a POST request 101 | uri="coap://192.168.0.100:8000/object/12345678/send" 102 | 103 | -- Setup a timer to send ADC data 104 | tmr.alarm(0, 8000, 1, function() 105 | buf = 106 | "{" .. 107 | "\"quality\":" .. 108 | adc.read(0) .. 109 | "}" 110 | 111 | cc:post(uri, buf) 112 | print(buf) 113 | end) 114 | ``` 115 | 116 | Please modify the ```uri``` variable to the real CoAP server URI. Basically, the IP address and the listening port need to be fixed. 117 | 118 | The ```buf``` variable stores the JSON string (aka JSON document) which includes the air quality data. Finally, the JSON string will be sent to your server over the web via COAP. 119 | 120 | ## Understanding Resource-Oriented 121 | 122 | The best practice to achieve the purpose of getting data from NodeMCU is to use ```coap://192.168.0.100:8000/object/12345678/viewer```. 123 | 124 | Devify framework will automatically generate this URI for your NodeMCU device. The URI is the resource name of *NodeMCU data*. 125 | 126 | Write Node.js code to read the resource of this URI ```coap://192.168.0.100:8000/object/12345678/viewer``` is easy. 127 | 128 | ``` 129 | var coap = require('coap'); 130 | 131 | var clientWriable = coap.request('coap://192.168.0.100:8000/object/12345678/viewer'); 132 | 133 | clientWriable.on('response', function(res) { 134 | res.pipe(process.stdout) 135 | }); 136 | 137 | clientWriable.end(); 138 | ``` 139 | 140 | Please save the code under your project folder (*esp_air_iot/* at this tutorial) as the file name *coap-view-data.js*. Then, execute *coap-view-data.js* by running ```node coap-view-data.js```. 141 | 142 | ## Understanding the URI Design 143 | 144 | Devify has a simplified design of WoT framework. 145 | 146 | * Take advantage of broker pattern architecture 147 | * Thing modeling (thing description in JSON) 148 | * URI based communications (supoprt CoAP/WebSocket) 149 | 150 | The URI style is as the following. 151 | 152 | ``` 153 | coap://127.0.0.1:8000/object//send 154 | ``` 155 | 156 | * **object** is the resource name 157 | * **<ObjectID>** is the unique ID of the resource. Please assign a string for your device. 158 | * **send** or **viewer** is the property of this resource. Use **send** to *send data to CoAP server*, and **viewer** to *view data from CoAP server* 159 | 160 | This URI style is defined in the underlying of Devify framework. 161 | 162 | ## Better IoT Programming 163 | 164 | Flowchain open source project for flow-based IoT programming is available at [Flowchain](https://github.com/flowchain/flowchain). 165 | 166 | This chapter explains two different programming models. 167 | 168 | * One is the monolithic application (aka single process) with conventional *if..else...* programming model. 169 | * The other is the concept of resource-oriented using URI model. 170 | 171 | Flowchain opensource project brings the vision of **A new way to write IoT application server code**. For better IoT programming with flow-based paradigm, please read [Flowchain](https://github.com/flowchain/flowchain). 172 | 173 | ## Next Chapter 174 | 175 | * [101-air-quality-sensor-text-messaging-twilio](../101-air-quality-sensor-text-messaging-twilio) 176 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-console-print/esp8266/coap-air-quality.lua: -------------------------------------------------------------------------------- 1 | -- Configure the ESP as a station (client) 2 | wifi.setmode(wifi.STATION) 3 | wifi.sta.config("", "") 4 | wifi.sta.autoconnect(1) 5 | 6 | -- Print IP address 7 | ip = wifi.sta.getip() 8 | print(ip) 9 | 10 | -- Create a CoAP client 11 | cc = coap.Client() 12 | 13 | -- Make a POST request 14 | uri="coap://192.168.1.44:8000/object/5550937980d51931b3000009/send" 15 | 16 | tmr.alarm(0, 3000, 1, function() 17 | buf = 18 | "{" .. 19 | "\"quality\":" .. 20 | adc.read(0) .. 21 | "}" 22 | 23 | cc:post(uri, buf) 24 | print(buf) 25 | end) 26 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-console-print/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "101-air-quality-sensor-console-print", 3 | "version": "1.0.0", 4 | "description": "Boilerplate for IoT cloud servers", 5 | "keywords": [ 6 | "iot" 7 | ], 8 | "author": "jollen (http://jollen.org/)", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/DevifyPlatform/devify-server.git" 12 | }, 13 | "homepage": "https://github.com/DevifyPlatform/devify-server.git", 14 | "dependencies": { 15 | "devify-server": "*" 16 | }, 17 | "scripts": { 18 | "test": "make test", 19 | "start": "node ./server.js" 20 | }, 21 | "devDependencies": { 22 | }, 23 | "license": "MIT License" 24 | } 25 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-console-print/server.js: -------------------------------------------------------------------------------- 1 | var server = require('devify-server').CoapBroker; 2 | 3 | var onmessage = function(message) { 4 | // Parse strings to JSON object. 5 | var obj = JSON.parse(message.data); 6 | // Print strings. 7 | console.log(' ' + message.data); 8 | }; 9 | 10 | server.start({ 11 | onmessage: onmessage, 12 | }); 13 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-text-messaging-twilio/README.md: -------------------------------------------------------------------------------- 1 | ![](http://res.cloudinary.com/jollen/image/upload/h_110/v1455862763/devify-logo_rh63vl.png) 2 | 3 | ESP8266 over the Web: Getting started with IoT System Architecture 4 | 5 | # Project Goal 6 | 7 | ![](https://cloud.githubusercontent.com/assets/1126021/13699804/b9498212-e7b7-11e5-99e3-734ac6bf91da.png) 8 | 9 | The use scenario of this project. 10 | 11 | * Send an alert message by SMS when the air quality is not good 12 | * Understanding Devify 13 | 14 | This project shows how to extend devify-server biolerplate to send an alert SMS. Please read [Devify](https://github.com/DevifyPlatform/devify-server/blob/master/README.md) to understand Devify in a bit before continue to this project. 15 | 16 | ## Prerequisites 17 | 18 | 0. Understanding [101-air-quality-sensor-console-print](../101-air-quality-sensor-console-print) 19 | 20 | 1. This project uses twilio APIs for text messaging. Please signup and get your own credentials at [twilio](https://www.twilio.com). 21 | 22 | 2. This project uses [twilio](https://www.npmjs.com/package/twilio) npm module to invoke twilio REST APIs. Please run `$ npm install twilio` to install the latest version. 23 | 24 | 3. Please copy ```config.json.example``` to ```config.json```. 25 | 26 | ## Getting Started 27 | 28 | Twilio credentials consists of Sid and Token. Please open ```config.json``` and put on your credentials. 29 | 30 | ``` 31 | var server = require('devify-server').coapBroker; 32 | 33 | // Twilio Credentials 34 | // Sendgrid credentials. 35 | var fs = require('fs'); 36 | var app = JSON.parse(fs.readFileSync(__dirname + '/config.json')); 37 | 38 | //require the Twilio module and create a REST client 39 | var client = require('twilio')(app.accountSid, app.authToken); 40 | 41 | var sms = 0; 42 | 43 | // override '.onData()' event handler 44 | var sms = function(message) { 45 | var obj = JSON.parse(message.data); 46 | 47 | if (obj.quality >= 350) { 48 | client.messages.create({ 49 | to: "", 50 | from: "", 51 | body: "The air is too bad: " + obj.quality, 52 | }, function(err, result) { 53 | console.log(result.sid); 54 | }); 55 | } 56 | } 57 | 58 | server.start({ 59 | onmessage: sms 60 | }); 61 | ``` 62 | 63 | ## NodeMCU 64 | 65 | The full source list is as the following. 66 | 67 | ``` 68 | -- Configure the ESP as a station (client) 69 | wifi.setmode(wifi.STATION) 70 | wifi.sta.config("", "") 71 | wifi.sta.autoconnect(1) 72 | 73 | -- Create a CoAP client 74 | cc = coap.Client() 75 | 76 | -- Make a POST request 77 | uri="coap://192.168.0.100:8000/object/12345678/send" 78 | 79 | -- Setup a timer to send ADC data 80 | tmr.alarm(0, 8000, 1, function() 81 | buf = 82 | "{" .. 83 | "\"quality\":" .. 84 | adc.read(0) .. 85 | "}" 86 | 87 | cc:post(uri, buf) 88 | print(buf) 89 | end) 90 | ``` 91 | 92 | The work of modifying the code is just the same with the chapter [101-air-quality-sensor-console-print](../101-air-quality-sensor-console-print#nodemcu). 93 | 94 | Please read [Quickstart](../101-air-quality-sensor-console-print#quickstart) to run this project. 95 | 96 | ## Next 97 | 98 | * [102-air-quality-sensor-email](../102-air-quality-sensor-email) 99 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-text-messaging-twilio/config.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "accountSid": "95482ced3bf09f85c", 3 | "authToken": "972c5ebe5758e0a95482ced3bf09f85c" 4 | } -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-text-messaging-twilio/esp8266/coap-air-quality.lua: -------------------------------------------------------------------------------- 1 | -- Configure the ESP as a station (client) 2 | wifi.setmode(wifi.STATION) 3 | wifi.sta.config("", "") 4 | wifi.sta.autoconnect(1) 5 | 6 | -- Print IP address 7 | ip = wifi.sta.getip() 8 | print(ip) 9 | 10 | -- Create a CoAP client 11 | cc = coap.Client() 12 | 13 | -- Make a POST request 14 | uri="coap://192.168.1.44:8000/object/5550937980d51931b3000009/send" 15 | 16 | tmr.alarm(0, 3000, 1, function() 17 | buf = 18 | "{" .. 19 | "\"quality\":" .. 20 | adc.read(0) .. 21 | "}" 22 | 23 | cc:post(uri, buf) 24 | print(buf) 25 | end) 26 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-text-messaging-twilio/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "101-air-quality-sensor-text-messaging-twilio", 3 | "version": "1.0.0", 4 | "description": "Boilerplate for IoT cloud servers", 5 | "keywords": [ 6 | "iot" 7 | ], 8 | "author": "jollen (http://jollen.org/)", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/DevifyPlatform/devify-server.git" 12 | }, 13 | "homepage": "https://github.com/DevifyPlatform/devify-server.git", 14 | "dependencies": { 15 | "devify-server": "*", 16 | "twilio": "^2.9.0" 17 | }, 18 | "scripts": { 19 | "test": "make test", 20 | "start": "node ./server.js" 21 | }, 22 | "devDependencies": {}, 23 | "license": "MIT License" 24 | } 25 | -------------------------------------------------------------------------------- /templates/101-air-quality-sensor-text-messaging-twilio/server.js: -------------------------------------------------------------------------------- 1 | var server = require('devify-server').CoapBroker; 2 | 3 | // Twilio Credentials 4 | // Sendgrid credentials. 5 | var fs = require('fs'); 6 | var app = JSON.parse(fs.readFileSync(__dirname + '/config.json')); 7 | 8 | //require the Twilio module and create a REST client 9 | var client = require('twilio')(app.accountSid, app.authToken); 10 | 11 | var sms = 0; 12 | 13 | // override '.onData()' event handler 14 | var sms = function(message) { 15 | var obj = JSON.parse(message.data); 16 | 17 | if (obj.quality >= 350) { 18 | client.messages.create({ 19 | to: "", 20 | from: "", 21 | body: "The air is too bad: " + obj.quality, 22 | }, function(err, result) { 23 | console.log(result.sid); 24 | }); 25 | } 26 | } 27 | 28 | server.start({ 29 | onmessage: sms 30 | }); -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-dropbox/README.md: -------------------------------------------------------------------------------- 1 | ![](http://res.cloudinary.com/jollen/image/upload/h_110/v1455862763/devify-logo_rh63vl.png) 2 | 3 | ESP8266 over the Web: Getting started with IoT System Architecture 4 | 5 | # Project Goal 6 | 7 | ![](https://cloud.githubusercontent.com/assets/1126021/13699804/b9498212-e7b7-11e5-99e3-734ac6bf91da.png) 8 | 9 | The use scenario of this project. 10 | 11 | * Save hardware data to Dropbox files 12 | * The name of each file is according to the current timestamp 13 | 14 | This project shows how to extend devify-server biolerplate to save data to Dropbox files. Please read [Devify](https://github.com/DevifyPlatform/devify-server/blob/master/README.md) to understand Devify in a bit before continue to this project. 15 | 16 | ## Prerequisites 17 | 18 | The guidelines are the same with the previous lessons. Therefore, this lesson will be explained in a short. Please read the previous 3 lessons before starting the project of this lesson. 19 | 20 | * [101-air-quality-sensor-console-print](../101-air-quality-sensor-console-print) 21 | * [101-air-quality-sensor-text-messaging-twilio](../101-air-quality-sensor-text-messaging-twilio) 22 | * [102-air-quality-sensor-email](../102-air-quality-sensor-email) 23 | 24 | ## Quickstart 25 | 26 | 1. This project uses Dropbox APIs. Please signup and get your own application key at [Dropbox](https://dropbox.com/). 27 | 28 | 2. Please copy ```config.app.json.example``` to ```config.app.json```. 29 | 30 | 3. Please copy ```config.access_token.json.example``` to ```config.access_token.json```. 31 | 32 | 4. Please modify ```config.app.json``` and ```config.access_token.json``` to fill with your Dropbox token and secret key. 33 | 34 | ## Next 35 | 36 | * [201: Building Real-Time Dahsboard](../201-web-of-things-dashboard/) 37 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-dropbox/config.access_token.json.example: -------------------------------------------------------------------------------- 1 | { "oauth_token_secret": "", 2 | "oauth_token": "", 3 | "uid": "" } 4 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-dropbox/config.app.json.example: -------------------------------------------------------------------------------- 1 | { "app_key": "", 2 | "app_secret": "", 3 | "root": "dropbox" 4 | } 5 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-dropbox/esp8266/coap-air-quality.lua: -------------------------------------------------------------------------------- 1 | -- Configure the ESP as a station (client) 2 | wifi.setmode(wifi.STATION) 3 | wifi.sta.config("", "") 4 | wifi.sta.autoconnect(1) 5 | 6 | -- Print IP address 7 | ip = wifi.sta.getip() 8 | print(ip) 9 | 10 | -- Create a CoAP client 11 | cc = coap.Client() 12 | 13 | -- Make a POST request 14 | uri="coap://192.168.1.44:8000/object/5550937980d51931b3000009/send" 15 | 16 | tmr.alarm(0, 3000, 1, function() 17 | buf = 18 | "{" .. 19 | "\"quality\":" .. 20 | adc.read(0) .. 21 | "}" 22 | 23 | cc:post(uri, buf) 24 | print(buf) 25 | end) 26 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-dropbox/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "101-air-quality-sensor-dropbox", 3 | "version": "1.0.0", 4 | "description": "Boilerplate for IoT cloud servers", 5 | "keywords": [ 6 | "iot" 7 | ], 8 | "author": "jollen (http://jollen.org/)", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/DevifyPlatform/devify-server.git" 12 | }, 13 | "homepage": "https://github.com/DevifyPlatform/devify-server.git", 14 | "dependencies": { 15 | "dbox": "^0.6.4", 16 | "devify-server": "*" 17 | }, 18 | "scripts": { 19 | "test": "make test", 20 | "start": "node ./server.js" 21 | }, 22 | "devDependencies": {}, 23 | "license": "MIT License" 24 | } 25 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-dropbox/server.js: -------------------------------------------------------------------------------- 1 | var server = require('devify-server').CoapBroker; 2 | 3 | 4 | /** 5 | * DropBox API 6 | */ 7 | var fs = require("fs"); 8 | var dbox = require("dbox"); 9 | 10 | var app_cfg = JSON.parse(fs.readFileSync(__dirname + "/config.app.json")); 11 | var access_token = JSON.parse(fs.readFileSync(__dirname +"/config.access_token.json")); 12 | 13 | var app = dbox.app(app_cfg); 14 | var client = app.client(access_token); 15 | 16 | /** 17 | * Internal Variables 18 | */ 19 | var data = []; 20 | 21 | var onmessage = function(message) { 22 | // Parse strings to JSON object. 23 | var obj = JSON.parse(message.data); 24 | 25 | // Put a timestamp in the message 26 | var now = Math.floor(Date.now() / 1000); 27 | obj.timestamp = now; 28 | 29 | // Put to array 30 | data.push(obj); 31 | 32 | // Put to DropBox 33 | var filename = new Date() + '.json'; 34 | 35 | if (data.length >= 10) { 36 | client.put(filename, JSON.stringify(data), function(status, reply) { 37 | console.log('DBOX Status: ' + status); 38 | data = []; 39 | }); 40 | } 41 | }; 42 | 43 | server.start({ 44 | onmessage: onmessage, 45 | }); 46 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-email/README.md: -------------------------------------------------------------------------------- 1 | ![](http://res.cloudinary.com/jollen/image/upload/h_110/v1455862763/devify-logo_rh63vl.png) 2 | 3 | ESP8266 over the Web: Getting started with IoT System Architecture 4 | 5 | # Project Goal 6 | 7 | ![](https://cloud.githubusercontent.com/assets/1126021/13699804/b9498212-e7b7-11e5-99e3-734ac6bf91da.png) 8 | 9 | The use scenario of this project. 10 | 11 | * Send an alert message by email when the air quality is not good 12 | * Lean how to invoke SendGrid APIs 13 | 14 | This project shows how to extend devify-server biolerplate to send an email. Please read [Devify](https://github.com/DevifyPlatform/devify-server/blob/master/README.md) to understand Devify in a bit before continue to this project. 15 | 16 | ## Prerequisites 17 | 18 | 0. Understanding [101-air-quality-sensor-console-print](../101-air-quality-sensor-console-print) 19 | 20 | 1. This project uses SendGrid APIs for sending emails. Please signup and get your own credentials at [SendGrid](https://sendgrid.com/). 21 | 22 | 2. Please copy ```config.json.example``` to ```config.json```. 23 | 24 | ## Getting Started 25 | 26 | Please open ```config.json``` and put on your username and password of SendGrid. 27 | 28 | ``` 29 | var server = require('devify-server').coapBroker; 30 | 31 | // The email utility 32 | var email = require('./utilities/email'); 33 | 34 | // Sendgrid credentials. 35 | var fs = require('fs'); 36 | var credentials = JSON.parse(fs.readFileSync(__dirname + '/config.json')); 37 | 38 | // Last time we have sent an email. 39 | var last = 0; 40 | 41 | var onmessage = function(message) { 42 | // Parse strings to JSON object. 43 | var obj = JSON.parse(message.data); 44 | 45 | // Put a timestamp in the message 46 | var now = Math.floor(Date.now() / 1000); 47 | obj.timestamp = now; 48 | 49 | // Don't send too many emails. 50 | if (now - last < 60) 51 | // We have sent an email in 60 seconds. 52 | return; 53 | 54 | email({ 55 | credentials: credentials, 56 | 57 | from: 'jollen ', 58 | to: 'jollen ', 59 | replyTo: 'jollen ', 60 | subject: 'ESP8266 Air Quality', 61 | text: JSON.stringify(message.data), 62 | 63 | success: function(message) { 64 | last = now; 65 | console.log('Email sent: ' + last); 66 | }, 67 | error: function(err) { 68 | console.log('Email failed: ' + err); 69 | } 70 | }); 71 | }; 72 | 73 | server.start({ 74 | onmessage: onmessage, 75 | }); 76 | 77 | ``` 78 | 79 | Please replace ```from```, ```to```, ```replyTo```, ```subject```, and ```text``` with yours. The ```text``` property is the text context of this email. 80 | 81 | ## NodeMCU 82 | 83 | The full source list is as the following. 84 | 85 | ``` 86 | -- Configure the ESP as a station (client) 87 | wifi.setmode(wifi.STATION) 88 | wifi.sta.config("", "") 89 | wifi.sta.autoconnect(1) 90 | 91 | -- Create a CoAP client 92 | cc = coap.Client() 93 | 94 | -- Make a POST request 95 | uri="coap://192.168.0.100:8000/object/12345678/send" 96 | 97 | -- Setup a timer to send ADC data 98 | tmr.alarm(0, 8000, 1, function() 99 | buf = 100 | "{" .. 101 | "\"quality\":" .. 102 | adc.read(0) .. 103 | "}" 104 | 105 | cc:post(uri, buf) 106 | print(buf) 107 | end) 108 | ``` 109 | 110 | The work of modifying the code is just the same with the chapter [101-air-quality-sensor-console-print](../101-air-quality-sensor-console-print). 111 | 112 | Please read [Quickstart](101-air-quality-sensor-console-print#quickstart) to run this project. 113 | 114 | ## Next 115 | 116 | * [102-air-quality-sensor-dropbox](../102-air-quality-sensor-dropbox) 117 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-email/config.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "user": "jollen", 3 | "password": "972c5ebe5758e0a95482ced3bf09f85c", 4 | "host": "smtp.sendgrid.net", 5 | "ssl": true 6 | } -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-email/esp8266/coap-air-quality.lua: -------------------------------------------------------------------------------- 1 | -- Configure the ESP as a station (client) 2 | wifi.setmode(wifi.STATION) 3 | wifi.sta.config("", "") 4 | wifi.sta.autoconnect(1) 5 | 6 | -- Print IP address 7 | ip = wifi.sta.getip() 8 | print(ip) 9 | 10 | -- Create a CoAP client 11 | cc = coap.Client() 12 | 13 | -- Make a POST request 14 | uri="coap://192.168.1.44:8000/object/5550937980d51931b3000009/send" 15 | 16 | tmr.alarm(0, 3000, 1, function() 17 | buf = 18 | "{" .. 19 | "\"quality\":" .. 20 | adc.read(0) .. 21 | "}" 22 | 23 | cc:post(uri, buf) 24 | print(buf) 25 | end) 26 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-email/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "101-air-quality-sensor-email", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "nodemailer": { 8 | "version": "6.6.1", 9 | "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.1.tgz", 10 | "integrity": "sha512-1xzFN3gqv+/qJ6YRyxBxfTYstLNt0FCtZaFRvf4Sg9wxNGWbwFmGXVpfSi6ThGK6aRxAo+KjHtYSW8NvCsNSAg==" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-email/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "101-air-quality-sensor-email", 3 | "version": "1.0.0", 4 | "description": "Boilerplate for IoT cloud servers", 5 | "keywords": [ 6 | "iot" 7 | ], 8 | "author": "jollen (http://jollen.org/)", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/DevifyPlatform/devify-server.git" 12 | }, 13 | "homepage": "https://github.com/DevifyPlatform/devify-server.git", 14 | "dependencies": { 15 | "devify-server": "*", 16 | "nodemailer": "^6.6.1", 17 | "smtpapi": "^1.2.0" 18 | }, 19 | "scripts": { 20 | "test": "make test", 21 | "start": "node ./server.js" 22 | }, 23 | "devDependencies": {}, 24 | "license": "MIT License" 25 | } 26 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-email/server.js: -------------------------------------------------------------------------------- 1 | var server = require('devify-server').CoapBroker; 2 | 3 | // The email utility 4 | var email = require('./utilities/email'); 5 | 6 | // Sendgrid credentials. 7 | var fs = require('fs'); 8 | var credentials = JSON.parse(fs.readFileSync(__dirname + '/config.json')); 9 | 10 | // Last time we have sent an email. 11 | var last = 0; 12 | 13 | var onmessage = function(message) { 14 | // Parse strings to JSON object. 15 | var obj = JSON.parse(message.data); 16 | 17 | // Put a timestamp in the message 18 | var now = Math.floor(Date.now() / 1000); 19 | obj.timestamp = now; 20 | 21 | // Don't send too many emails. 22 | if (now - last < 60) 23 | // We have sent an email in 60 seconds. 24 | return; 25 | 26 | email({ 27 | credentials: credentials, 28 | 29 | from: 'jollen ', 30 | to: 'jollen ', 31 | replyTo: 'jollen ', 32 | subject: 'ESP8266 Air Quality', 33 | text: JSON.stringify(message.data), 34 | 35 | success: function(message) { 36 | last = now; 37 | console.log('Email sent: ' + last); 38 | }, 39 | error: function(err) { 40 | console.log('Email failed: ' + err); 41 | } 42 | }); 43 | }; 44 | 45 | server.start({ 46 | onmessage: onmessage, 47 | }); 48 | -------------------------------------------------------------------------------- /templates/102-air-quality-sensor-email/utilities/email.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports = module.exports = function(options) { 4 | var nodemailer = require('nodemailer'); 5 | var smtpapi = require('smtpapi'); 6 | 7 | // Build the smtpapi header 8 | var header = new smtpapi(); 9 | 10 | if (options.to === 'object') { 11 | header.setTos(options.to); 12 | } else { 13 | header.addTo(options.to); 14 | } 15 | 16 | // Add the smtpapi header to the general headers 17 | var headers = { 'x-smtpapi': header.jsonString() }; 18 | 19 | // Use nodemailer to send the email 20 | var settings = { 21 | host: options.credentials.host, 22 | port: parseInt(587, 10), 23 | requiresAuth: true, 24 | auth: { 25 | user: options.credentials.user, 26 | pass: options.credentials.password 27 | } 28 | }; 29 | 30 | var smtpTransport = nodemailer.createTransport(settings); 31 | 32 | var mailOptions = { 33 | from: options.from, 34 | to: options.to, 35 | subject: options.subject, 36 | text: options.text, 37 | headers: headers 38 | }; 39 | 40 | smtpTransport.sendMail(mailOptions, function(error, response) { 41 | smtpTransport.close(); 42 | 43 | if (error) { 44 | options.error('Email failed to send. ' + error); 45 | return; 46 | } else { 47 | options.success(response); 48 | return; 49 | } 50 | }); 51 | }; 52 | -------------------------------------------------------------------------------- /templates/201-web-of-things-dashboard/README.md: -------------------------------------------------------------------------------- 1 | ![](http://res.cloudinary.com/jollen/image/upload/h_110/v1455862763/devify-logo_rh63vl.png) 2 | 3 | The simplest tutorial to build the Web of Things architecture - with ESP8266 and Microsoft Azure 4 | 5 | ## Project Goal 6 | 7 | Real-time Sensor Dashboard: Get Started with WebSockets, CoAP and Web of Things 8 | 9 | The Web of Things (WoT) provides an Application Layer that simplifies the creation of Internet of Things applications[1]. WoT reuses existing web technologies, such as REST, HTTP, Websockets, CoAP and etc. [1]. 10 | 11 | This project aims to architect the Web of Things for wireless sensor networks. 12 | 13 | ![](https://cloud.githubusercontent.com/assets/1126021/13872864/54542382-ed28-11e5-8d11-5c4d1c62f239.gif) 14 | 15 | ## Abstraction 16 | 17 | The wireless sensor network is built from "nodes"[2]. A node in a sensor network is capable of gathering information and communicating with other nodes. 18 | 19 | ![](https://upload.wikimedia.org/wikipedia/commons/2/21/WSN.svg) 20 | 21 | Figure-1: Wireless Sensor Network (Source: https://en.wikipedia.org/wiki/Wireless_sensor_network. License: Public Domain) 22 | 23 | One of the simple topologies of the wireless network network is Star Network[3]. 24 | 25 | ![](https://upload.wikimedia.org/wikipedia/commons/8/84/Star_Topology.png) 26 | 27 | Figure-2: Star Network (Source: https://en.wikipedia.org/wiki/Star_network. License: CC BY-SA 3.0) 28 | 29 | In a star network, every node is connected to Gateway Sensor Node. A node in a star network will gather sensory information and send it to Gateway Sensor Node. We will use star network to architect the Web of Things in this project. 30 | 31 | ## Goal and Architecture 32 | 33 | ![](https://cloud.githubusercontent.com/assets/1126021/13871103/b0f09960-ed1c-11e5-810b-33f4aa8f0e70.png) 34 | 35 | Figure-3: Goal of 201-web-of-things-dashboard 36 | 37 | Figure-3 is a simple Web of Things architecture. In the figure: 38 | 39 | * We will call Gateway Sensor Node as "Proxy" 40 | * We will take advantge of ESP8266 as "Temperature Node", marked as "Node" in Figure-3 41 | * Temperature Node will gather temperature information and send it to Proxy over "CoAP" 42 | * We will connect Proxy to an IoT cloud server, the IoT cloud server is called "Endpoint" 43 | * We will deploy "Endpoint" at Microsoft Azure through App Service 44 | * We will build a web frontend "Dashboard" and connect "Dashboard" to "Endpoint" for viewing temperature information 45 | 46 | Some technical details: 47 | 48 | * "Temperature Node" sends temperature information to "Proxy" over CoAP 49 | * "Proxy" is real-time pushing temperature information to "Endpoint" over Websockets 50 | * "Endpoint" is real-time pushing temperature information to "Dashboard" over Websockets 51 | 52 | We will implement "Endpoint", "Proxy", "Node" and "Dashboard" in sequence. 53 | 54 | ## Setup "Endpoint" 55 | 56 | The following steps show that how to deploy "Endpoint" to Azure web service. 57 | 58 | Please change your working directory to this project. 59 | 60 | ``` 61 | $ cd /devify-server/templates/201-web-of-things-dashboard 62 | ``` 63 | 64 | The project structre is as the following. 65 | 66 | ``` 67 | . 68 | ├── README.md 69 | ├── esp8266 70 | │   └── coap-temperature.lua The sample code of "Temperature Node" 71 | ├── package.json 72 | ├── server.js The sample code of "Endpoint" 73 | └── server.proxy.js The sample code of "Proxy" 74 | ``` 75 | 76 | We will deploy this project to Azure App Service. Azure App Service will run ```server.js``` automatically after we finish deploying our project. 77 | 78 | You may need to visit [Microsoft Azure](https://azure.microsoft.com/) if you want to know more about Microsoft Azure, or you have to sign up a new Azure account. 79 | 80 | It's suggested that you read [App Service](https://azure.microsoft.com/en-us/services/app-service/) if it's the first time to use App Service of Microsoft Azure. 81 | 82 | ### Step 1: Install azure-cli 83 | 84 | ``` 85 | $ npm install azure-cli -g 86 | ``` 87 | 88 | ### Step 2: Create Azure Site 89 | 90 | You must login to Azure in advance: 91 | 92 | ``` 93 | azure config mode asm 94 | azure login 95 | ``` 96 | 97 | Then use the command line to create an Aure site: 98 | 99 | ``` 100 | azure site create --git 101 | ``` 102 | Input your site information at the prompt mode. This is an example: 103 | 104 | ``` 105 | $ azure site create --git 106 | info: Executing command site create 107 | help: Need a site name 108 | Name: devify-temperature 109 | + Getting locations 110 | + Getting sites 111 | + Getting locations 112 | help: Choose a location 113 | 1) East Asia 114 | 2) North Europe 115 | 3) West Europe 116 | 4) Southeast Asia 117 | 5) West US 118 | 6) East US 119 | 7) Japan West 120 | 8) Japan East 121 | 9) South Central US 122 | 10) East US 2 123 | 11) North Central US 124 | 12) Central US 125 | 13) Brazil South 126 | : 7 127 | info: Creating a new web site at devify-temperature.azurewebsites.net 128 | -info: Created website at devify-temperature.azurewebsites.net 129 | + 130 | info: Executing `git init` 131 | info: Creating default iisnode.yml file 132 | info: Initializing remote Azure repository 133 | + Updating site information 134 | info: Remote azure repository initialized 135 | + Getting site information 136 | + Getting user information 137 | info: Executing `git remote add azure https://jollen@devify-temperature.scm.azurewebsites.net/devify-temperature.git` 138 | info: A new remote, 'azure', has been added to your local git repository 139 | info: Use git locally to make changes to your site, commit, and then use 'git push azure master' to deploy to Azure 140 | info: site create command OK 141 | 142 | ``` 143 | 144 | Please append ```--git``` option to the command line. This option could make Azure CLI to add the remote git of our new created site to local project. We will use ```git``` to deploy our site. 145 | 146 | ### Step 3: Get Endpoint 147 | 148 | After finishing creating site, remember the name of your site. Please looking for the ```Created website at``` message line to get your endpoint name. 149 | 150 | The endpoint name is ```devify-temperature.azurewebsites.net``` in this example. 151 | 152 | ### Step 4: Create Site Credentials 153 | 154 | Run the command line to create credentials (the username and password): 155 | 156 | ``` 157 | azure site deployment user set 158 | ``` 159 | 160 | This is an example: 161 | 162 | ``` 163 | $ azure site deployment user set 164 | info: Executing command site deployment user set 165 | Git username: jollen 166 | Git password: ********* 167 | Confirm password: ********* 168 | + Setting user credentials 169 | info: site deployment user set command OK 170 | ``` 171 | 172 | ### Step 5: Deploy Site 173 | 174 | Use ```git``` to commit and push your project files to web site: 175 | 176 | ``` 177 | $ git add --all 178 | $ git commit -m 'deploy to azure' 179 | $ git push azure master 180 | ``` 181 | 182 | The is an example: 183 | 184 | ``` 185 | $ git add --all 186 | $ git commit -m 'deploy to azure' 187 | $ git push azure master 188 | Password for 'https://jollen@devify-temperature.scm.azurewebsites.net': 189 | fatal: Authentication failed for 'https://jollen@devify-temperature.scm.azurewebsites.net/devify-temperature.git/' 190 | Moko365de-iMac:201-web-of-things-dashboard apple$ git push azure master 191 | Password for 'https://jollen@devify-temperature.scm.azurewebsites.net': 192 | Counting objects: 10, done. 193 | Delta compression using up to 2 threads. 194 | Compressing objects: 100% (8/8), done. 195 | Writing objects: 100% (10/10), 5.16 KiB | 0 bytes/s, done. 196 | Total 10 (delta 1), reused 0 (delta 0) 197 | remote: Updating branch 'master'. 198 | remote: Updating submodules. 199 | remote: Preparing deployment for commit id '0f244b55bf'. 200 | remote: Generating deployment script. 201 | remote: Generating deployment script for node.js Web Site 202 | remote: Generated deployment script files 203 | remote: Running deployment command... 204 | remote: Handling node.js deployment. 205 | remote: KuduSync.NET from: 'D:\home\site\repository' to: 'D:\home\site\wwwroot' 206 | remote: Deleting file: 'hostingstart.html' 207 | remote: Copying file: '.gitignore' 208 | remote: Copying file: 'iisnode.yml' 209 | remote: Copying file: 'package.json' 210 | remote: Copying file: 'README.md' 211 | remote: Copying file: 'server.js' 212 | remote: Copying file: 'server.proxy.js' 213 | remote: Copying file: 'esp8266\coap-temperature.lua' 214 | remote: Using start-up script server.js from package.json. 215 | remote: Generated web.config. 216 | remote: The package.json file does not specify node.js engine version constraints. 217 | remote: The node.js application will run with the default node.js version 4.2.3. 218 | remote: Selected npm version 3.5.1 219 | remote: .... 220 | . 221 | . 222 | remote: Finished successfully. 223 | remote: Running post deployment command(s)... 224 | remote: Deployment successful. 225 | To https://jollen@devify-temperature.scm.azurewebsites.net/devify-temperature.git 226 | * [new branch] master -> master 227 | ``` 228 | 229 | ### Step 5: Enable Websockets 230 | 231 | To enable web sockets: 232 | 233 | ``` 234 | azure site set -w 235 | ``` 236 | 237 | This is an example: 238 | 239 | ``` 240 | $ azure site set -w 241 | info: Executing command site set 242 | Web site name: devify-temperature 243 | Web site slot [enter for none]: 244 | \ Updating site config information 245 | ``` 246 | 247 | ## Setup "Proxy" 248 | 249 | The simplest way to run "Proxy" is to use the laptop. 250 | 251 | ``` 252 | $ cd /devify-server/templates/201-web-of-things-dashboard 253 | $ npm install 254 | $ export ENDPOINT=devify-temperature.azurewebsites.net 255 | $ export HOST=192.168.1.100 256 | $ export PORT=8000 257 | $ node server.proxy.js 258 | ``` 259 | 260 | There are three variables for configuration options. 261 | 262 | * **ENDPOINT** is the endpoint name of "Endpoint" server 263 | * **HOST** is the IP address of the laptop 264 | * **PORT** is the listening port 265 | 266 | ## Setup "Node" 267 | 268 | Open [coap-temperature.lua](esp8266/coap-temperature.lua) file. Fill in with the WiFi hotspot name and password. 269 | 270 | ``` 271 | wifi.sta.config("", "") 272 | ``` 273 | 274 | Then, please find this line, fix the IP address and listening port. 275 | 276 | ``` 277 | uri="coap://192.168.1.100:8000/object/5550937980d51931b3000009/send" 278 | ``` 279 | 280 | The "Proxy" and "Node" should be connected to the same WiFi station. 281 | 282 | ## Setup "Dashboard" 283 | 284 | Please install Devify CLI to speed up setup "Dahsboard". 285 | 286 | ``` 287 | $ npm install devify-cli 288 | ``` 289 | 290 | Download a sample dashboard. 291 | 292 | ``` 293 | $ devify ui ui-moving-line 294 | ``` 295 | 296 | It will download [ui-moving-line](https://github.com/wotcity/ui-moving-line) repo, a simple web frontend of moving line chart. 297 | 298 | Change directory to ```ui-moving-line```, and start a web server to serve *ui-moving-line*. 299 | 300 | ``` 301 | $ cd ui-moving-line 302 | $ devify serve ./ 303 | ``` 304 | Open your browser with ```http://localhost:3000/index.html#testman/wot.city/temperature```. You will immediately see a demo. 305 | 306 | The URL format is as ```index.html#//```. 307 | 308 | * **<DeviceID>** is the device ID, please check it out with the URI in [coap-temperature.lua](esp8266/coap-temperature.lua) 309 | * **<Endpoint>** is the "Endpoint" 310 | * **<Y-Axis-Key>** is the key of the display value, please check it out with JSON output in [coap-temperature.lua](esp8266/coap-temperature.lua) 311 | 312 | This is an example: 313 | 314 | ``` 315 | index.html#5550937980d51931b3000009/devify-temperature.azurewebsites.net/temperature 316 | ``` 317 | 318 | [1]: https://en.wikipedia.org/wiki/Web_of_Things 319 | [2]: https://en.wikipedia.org/wiki/Wireless_sensor_network 320 | [3]: https://en.wikipedia.org/wiki/Star_network 321 | -------------------------------------------------------------------------------- /templates/201-web-of-things-dashboard/esp8266/coap-temperature.lua: -------------------------------------------------------------------------------- 1 | -- Configure the ESP as a station (client) 2 | wifi.setmode(wifi.STATION) 3 | wifi.sta.config("", "") 4 | wifi.sta.autoconnect(1) 5 | 6 | -- Print IP address 7 | ip = wifi.sta.getip() 8 | print(ip) 9 | 10 | -- Create a CoAP client 11 | cc = coap.Client() 12 | 13 | -- Make a POST request 14 | uri="coap://192.168.1.100:8000/object/5550937980d51931b3000009/send" 15 | 16 | tmr.alarm(0, 3000, 1, function() 17 | buf = 18 | "{" .. 19 | "\"temperature\":" .. 20 | adc.read(0) .. 21 | "}" 22 | 23 | cc:post(uri, buf) 24 | print(buf) 25 | end) 26 | -------------------------------------------------------------------------------- /templates/201-web-of-things-dashboard/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "201-web-of-things-dashboard", 3 | "version": "1.0.0", 4 | "description": "Boilerplate for IoT cloud servers", 5 | "keywords": [ 6 | "iot" 7 | ], 8 | "author": "jollen (http://jollen.org/)", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/DevifyPlatform/devify-server.git" 12 | }, 13 | "homepage": "https://github.com/DevifyPlatform/devify-server.git", 14 | "dependencies": { 15 | "devify-server": "*" 16 | }, 17 | "scripts": { 18 | "test": "make test", 19 | "start": "node ./server.js" 20 | }, 21 | "devDependencies": { 22 | }, 23 | "license": "MIT License" 24 | } 25 | -------------------------------------------------------------------------------- /templates/201-web-of-things-dashboard/server.js: -------------------------------------------------------------------------------- 1 | var server = require('devify-server').WebsocketBroker; 2 | 3 | var onmessage = function(message) { 4 | // Parse strings to JSON object. 5 | var obj = JSON.parse(message.data); 6 | }; 7 | 8 | server.start({ 9 | onmessage: onmessage, 10 | }); 11 | -------------------------------------------------------------------------------- /templates/201-web-of-things-dashboard/server.proxy.js: -------------------------------------------------------------------------------- 1 | var server = require('devify-server').CoapToWebsocketProxy; 2 | 3 | var onmessage = function(message) { 4 | // Parse strings to JSON object. 5 | var obj = JSON.parse(message.data); 6 | }; 7 | 8 | server.start({ 9 | onmessage: onmessage, 10 | }); 11 | -------------------------------------------------------------------------------- /templates/README.md: -------------------------------------------------------------------------------- 1 | ![](http://res.cloudinary.com/jollen/image/upload/h_110/v1455862763/devify-logo_rh63vl.png) 2 | 3 | # NodeMCU over the web 4 | 5 | [![Join the chat at https://gitter.im/DevifyPlatform/devify-server](https://badges.gitter.im/DevifyPlatform/devify-server.svg)](https://gitter.im/DevifyPlatform/devify-server?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | [![Build Status](https://travis-ci.org/DevifyPlatform/devify-server.svg?branch=master)](https://travis-ci.org/DevifyPlatform/devify-server) 7 | [![GitHub license](https://img.shields.io/github/license/DevifyPlatform/devify-server.svg)](https://github.com/DevifyPlatform/devify-server) 8 | 9 | A little book for beginners to get started with IoT cloud servers. This little book is a side project of [*devify-server*](https://github.com/DevifyPlatform/devify-server) which is a simple IoT server boilerplate. 10 | 11 | **Devify** is extremely light weight, and is very easy to use. It aims to help developers to create IoT application servers, faster. 12 | 13 | There are five templates (with one chapter for each template) developed by this book to introduce the usage of *devify-server* open source project. 14 | 15 | ## Who should read 16 | 17 | * People who are interested in using ESP8266 for developing IoT devices, and 18 | * Want to develop IoT cloud servers to connect their devices over the web. 19 | 20 | ## Ebook 21 | 22 | The **NodeMCU over the Web** little book. A guide to setup **Devify Server** for getting started with NodeMCU over the web. 23 | 24 | * Chapter 1 - [101-air-quality-sensor-console-print](101-air-quality-sensor-console-print): Connected an air quality sensor to NodeMCU and send data to an IoT server locally (in local area network). 25 | * Chapter 2 -[101-air-quality-sensor-text-messaging-twilio](101-air-quality-sensor-text-messaging-twilio): Send an alert message by SMS when the air quality is not good 26 | * Chapter 3 -[102-air-quality-sensor-dropbox](102-air-quality-sensor-dropbox): Save hardware data to Dropbox files 27 | * Chapter 4 -[102-air-quality-sensor-email](102-air-quality-sensor-email): Send an alert message by email when the air quality is not good 28 | * Chapter 5 -[201-web-of-things-dashboard](201-web-of-things-dashboard): An advanced chapter. Build a real-time sensor information dashboard. Get understood of WebSockets, CoAP and Web of Things (WoT). 29 | 30 | ## License 31 | 32 | CC BY 4.0 33 | -------------------------------------------------------------------------------- /test/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export NODE_ENV=test 4 | 5 | echo 6 | for file in $@; do 7 | printf "\033[90m ${file#test/}\033[0m " 8 | node $file 2> /tmp/stderr && echo "\033[36m✓\033[0m" 9 | code=$? 10 | if test $code -ne 0; then 11 | echo "\033[31m✖\033[0m" 12 | cat /tmp/stderr >&2 13 | exit $code 14 | fi 15 | done 16 | echo -------------------------------------------------------------------------------- /test/test.coap.send.js: -------------------------------------------------------------------------------- 1 | var coap = require('coap'); 2 | 3 | var sendNumber = function() { 4 | // 20 to 27 5 | var number = Math.round(Math.random() * 27 + 1); 6 | var obj = {temperature: number, temp: number}; 7 | var data = JSON.stringify(obj); 8 | var clientWriable = coap.request('coap://localhost:8000/object/5550937980d51931b3000009/send'); 9 | 10 | console.log('Pushing: ' + data); 11 | clientWriable.end(new Buffer(data)); 12 | 13 | process.exit(0); 14 | }; 15 | 16 | sendNumber(); 17 | -------------------------------------------------------------------------------- /test/test.websocket.send.js: -------------------------------------------------------------------------------- 1 | var WebSocketClient = require('websocket').client; 2 | 3 | var client = new WebSocketClient(); 4 | 5 | client.on('connectFailed', function(error) { 6 | console.log('Connect Error: ' + error.toString()); 7 | }); 8 | 9 | client.on('connect', function(connection) { 10 | console.log('WebSocket client connected'); 11 | connection.on('error', function(error) { 12 | console.log("Connection Error: " + error.toString()); 13 | }); 14 | connection.on('close', function() { 15 | console.log('echo-protocol Connection Closed'); 16 | }); 17 | connection.on('message', function(message) { 18 | if (message.type === 'utf8') { 19 | console.log("Received: '" + message.utf8Data + "'"); 20 | } 21 | }); 22 | 23 | function sendNumber() { 24 | if (connection.connected) { 25 | var lucky = Math.round(Math.random() * 100 + 1); 26 | var obj = {temperature: lucky}; 27 | 28 | console.log('Pushing: ' + JSON.stringify(obj)); 29 | 30 | connection.sendUTF(JSON.stringify(obj)); 31 | } 32 | } 33 | sendNumber(); 34 | process.exit(0); 35 | }); 36 | 37 | client.connect('ws://localhost:8000/object/5550937980d51931b3000009/send', ''); 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /test/test.websocket.viewer.js: -------------------------------------------------------------------------------- 1 | var WebSocketClient = require('websocket').client; 2 | 3 | var client = new WebSocketClient(); 4 | 5 | client.on('connectFailed', function(error) { 6 | console.log('Connect Error: ' + error.toString()); 7 | process.exit(0); 8 | }); 9 | 10 | client.on('connect', function(connection) { 11 | console.log('WebSocket client connected'); 12 | process.exit(0); 13 | }); 14 | 15 | client.connect('ws://localhost:8000/object/5550937980d51931b3000009/viewer', ''); 16 | -------------------------------------------------------------------------------- /websocket-broker-server.js: -------------------------------------------------------------------------------- 1 | var server = require('./libs/websocket-broker'); 2 | 3 | var onmessage = function(payload) { 4 | var obj = JSON.parse(payload.data); 5 | var paths = payload.pathname.split('/'); 6 | var deviceId = paths[2]; 7 | 8 | console.log('[', deviceId, ']', payload.data); 9 | }; 10 | 11 | var onnewthing = function(thing) { 12 | var data = JSON.stringify(thing); 13 | 14 | console.log(' ' + data); 15 | }; 16 | 17 | server.start({ 18 | onmessage: onmessage, 19 | onnewthing: onnewthing 20 | }); 21 | --------------------------------------------------------------------------------