├── .editorconfig ├── .gitignore ├── bindings.md ├── data ├── db.js └── dbs │ ├── file │ └── db.js │ └── remote_demo │ └── db.js ├── documents ├── abstract-msgs.md ├── app-platforms.md ├── json-td.md ├── layers.png ├── p2p │ ├── decentralized_iot.md │ └── protocol.md ├── things.md └── types.md ├── examples ├── coap_demo │ ├── config.js │ ├── demo.js │ ├── readme.md │ └── simulator.js ├── demo │ ├── config.js │ ├── demo.js │ ├── readme.md │ └── simulator.js ├── http_demo │ ├── api.js │ ├── config.js │ ├── demo.js │ ├── readme.md │ └── simulator.js ├── http_express_demo │ ├── api.js │ ├── config.js │ ├── demo.js │ ├── readme.md │ └── simulator.js ├── mqtt_demo │ ├── config.js │ └── readme.md ├── p2p_demo │ ├── config.js │ ├── crypto_demo.js │ ├── demo.js │ ├── kaddht_demo.js │ ├── peer_demo.js │ ├── readme.md │ └── simulator.js ├── raspberrypi_demo │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── account.js │ ├── appdefs.js │ ├── bootclient.js │ ├── config.json │ ├── contactlist.js │ ├── contacts.js │ ├── db │ │ └── readme.md │ ├── device │ │ └── ds18b20.js │ ├── device_handler.js │ ├── message.js │ ├── package.json │ ├── peernet.js │ ├── peertransport.js │ ├── readme_ds18b20.md │ ├── streembit.js │ ├── streembitdb.js │ └── utilities.js └── remote_demo │ ├── config.js │ ├── demo.js │ ├── readme.md │ └── simulator.js ├── framework.js ├── libs ├── adapters │ ├── coap.js │ ├── http.js │ └── mqtt.js ├── crypto │ ├── crypto_handler.js │ └── ecc │ │ ├── ECCSign.js │ │ ├── EccDsa.js │ │ ├── EccKey.js │ │ ├── EccVerify.js │ │ ├── ecurve │ │ ├── curve.js │ │ ├── curves.json │ │ ├── index.js │ │ ├── names.js │ │ └── point.js │ │ ├── readme.md │ │ └── util.js ├── events │ └── thingevents.js ├── lists │ └── registry.js ├── message │ ├── jwe.js │ ├── jwt.js │ └── wotmsg.js ├── thing │ ├── thing.js │ └── thing_handler.js └── transport │ └── p2p │ └── wotkad │ ├── discoverysrvc.js │ ├── kaddht.js │ ├── lib │ ├── bucket.js │ ├── constants.js │ ├── contact.js │ ├── item.js │ ├── message.js │ ├── node.js │ ├── router.js │ ├── rpc.js │ ├── storages │ │ └── localstorage.js │ ├── transports │ │ ├── address-port-contact.js │ │ ├── index.js │ │ ├── tcp.js │ │ └── udp.js │ └── utils.js │ ├── peer_comm.js │ ├── peer_network.js │ ├── pm2start.js │ ├── readme.md │ ├── seed.js │ └── websocketsrv.js ├── logger.js ├── notes.txt ├── package.json ├── readme.md ├── roadmap.md ├── security.md ├── streams.md ├── test ├── closure-loop-repro.js └── mocha.opts └── transports ├── coap ├── handler.js └── readme.md ├── http ├── handler.js └── readme.md ├── mqtt ├── handler.js └── readme.md ├── p2p ├── handler.js └── readme.md ├── restapi ├── handler.js └── readme.md ├── server_handler.js ├── web ├── handler.js ├── httpd.js ├── public │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ ├── font-awesome-animation.css │ │ ├── font-awesome-animation.min.css │ │ ├── font-awesome │ │ │ ├── HELP-US-OUT.txt │ │ │ ├── css │ │ │ │ ├── font-awesome.css │ │ │ │ └── font-awesome.min.css │ │ │ ├── fonts │ │ │ │ ├── FontAwesome.otf │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ ├── fontawesome-webfont.woff │ │ │ │ └── fontawesome-webfont.woff2 │ │ │ ├── less │ │ │ │ ├── animated.less │ │ │ │ ├── bordered-pulled.less │ │ │ │ ├── core.less │ │ │ │ ├── fixed-width.less │ │ │ │ ├── font-awesome.less │ │ │ │ ├── icons.less │ │ │ │ ├── larger.less │ │ │ │ ├── list.less │ │ │ │ ├── mixins.less │ │ │ │ ├── path.less │ │ │ │ ├── rotated-flipped.less │ │ │ │ ├── stacked.less │ │ │ │ └── variables.less │ │ │ └── scss │ │ │ │ ├── _animated.scss │ │ │ │ ├── _bordered-pulled.scss │ │ │ │ ├── _core.scss │ │ │ │ ├── _fixed-width.scss │ │ │ │ ├── _icons.scss │ │ │ │ ├── _larger.scss │ │ │ │ ├── _list.scss │ │ │ │ ├── _mixins.scss │ │ │ │ ├── _path.scss │ │ │ │ ├── _rotated-flipped.scss │ │ │ │ ├── _stacked.scss │ │ │ │ ├── _variables.scss │ │ │ │ └── font-awesome.scss │ │ ├── jquery.gritter.css │ │ └── wotstyles.css │ ├── favicon.ico │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── images │ │ ├── gritter-light.png │ │ ├── gritter-long.png │ │ ├── gritter.png │ │ ├── ie-spacer.gif │ │ └── trees.jpg │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── bower_components │ │ ├── knockout-postbox │ │ │ ├── .bower.json │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── bower.json │ │ │ └── build │ │ │ │ ├── knockout-postbox.js │ │ │ │ └── knockout-postbox.min.js │ │ └── knockout │ │ │ ├── .bower.json │ │ │ ├── Gruntfile.js │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── bower.json │ │ │ ├── build │ │ │ ├── fragments │ │ │ │ ├── amd-post.js │ │ │ │ ├── amd-pre.js │ │ │ │ ├── extern-post.js │ │ │ │ ├── extern-pre.js │ │ │ │ └── source-references.js │ │ │ └── knockout-raw.js │ │ │ ├── dist │ │ │ ├── knockout.debug.js │ │ │ └── knockout.js │ │ │ ├── package.json │ │ │ └── src │ │ │ ├── binding │ │ │ ├── bindingAttributeSyntax.js │ │ │ ├── bindingProvider.js │ │ │ ├── defaultBindings │ │ │ │ ├── attr.js │ │ │ │ ├── checked.js │ │ │ │ ├── click.js │ │ │ │ ├── css.js │ │ │ │ ├── enableDisable.js │ │ │ │ ├── event.js │ │ │ │ ├── foreach.js │ │ │ │ ├── hasfocus.js │ │ │ │ ├── html.js │ │ │ │ ├── ifIfnotWith.js │ │ │ │ ├── options.js │ │ │ │ ├── selectedOptions.js │ │ │ │ ├── style.js │ │ │ │ ├── submit.js │ │ │ │ ├── text.js │ │ │ │ ├── textInput.js │ │ │ │ ├── uniqueName.js │ │ │ │ ├── value.js │ │ │ │ └── visible.js │ │ │ ├── editDetection │ │ │ │ ├── arrayToDomNodeChildren.js │ │ │ │ └── compareArrays.js │ │ │ ├── expressionRewriting.js │ │ │ └── selectExtensions.js │ │ │ ├── components │ │ │ ├── componentBinding.js │ │ │ ├── customElements.js │ │ │ ├── defaultLoader.js │ │ │ └── loaderRegistry.js │ │ │ ├── google-closure-compiler-utils.js │ │ │ ├── memoization.js │ │ │ ├── namespace.js │ │ │ ├── subscribables │ │ │ ├── dependencyDetection.js │ │ │ ├── dependentObservable.js │ │ │ ├── extenders.js │ │ │ ├── mappingHelpers.js │ │ │ ├── observable.js │ │ │ ├── observableArray.changeTracking.js │ │ │ ├── observableArray.js │ │ │ └── subscribable.js │ │ │ ├── templating │ │ │ ├── jquery.tmpl │ │ │ │ └── jqueryTmplTemplateEngine.js │ │ │ ├── native │ │ │ │ └── nativeTemplateEngine.js │ │ │ ├── templateEngine.js │ │ │ ├── templateRewriting.js │ │ │ ├── templateSources.js │ │ │ └── templating.js │ │ │ ├── utils.domData.js │ │ │ ├── utils.domManipulation.js │ │ │ ├── utils.domNodeDisposal.js │ │ │ ├── utils.js │ │ │ ├── version.js │ │ │ └── virtualElements.js │ │ ├── jquery-1.11.3.min.js │ │ ├── jquery.gritter.min.js │ │ ├── knockout-postbox.min.js │ │ ├── knockout.js │ │ ├── knockout.mapping-latest.js │ │ └── wot │ │ ├── viewmodels │ │ ├── thing.js │ │ └── things.js │ │ └── wotapp.js ├── readme.md ├── routes │ ├── api.js │ └── main.js └── views │ ├── docs.handlebars │ ├── error.handlebars │ ├── index.handlebars │ ├── layouts │ └── main.handlebars │ ├── partials │ ├── door.html │ └── light.html │ ├── things.handlebars │ └── tutorials.handlebars └── ws └── handler.js /.editorconfig: -------------------------------------------------------------------------------- 1 | ; top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.js] 13 | ; CodePainter extended properties 14 | quote_type = auto 15 | spaces_around_operators = true 16 | space_after_control_statements = true 17 | space_after_anonymous_functions = false 18 | spaces_in_brackets = false 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # don't sync node modules that this project pulls in 2 | 3 | node_modules/ 4 | .DS_Store 5 | design.txt 6 | readme 7 | notes 8 | 9 | # don't sync Visual Studio files 10 | .ntvs_analysis.dat 11 | .ntvs_analysis.dat.tmp 12 | bin/ 13 | obj/ 14 | *.njsproj 15 | *.suo 16 | *.sln 17 | logs/*.log 18 | 19 | -------------------------------------------------------------------------------- /data/db.js: -------------------------------------------------------------------------------- 1 | var config = global.appconfig; 2 | 3 | module.exports = function () { 4 | var appdb = null; 5 | 6 | // get from the config what database needs to be wired up 7 | var dbtype = config.db.type; 8 | if (!dbtype) { 9 | throw new Error('The application data database tyepe does not exists in the configuration file'); 10 | } 11 | 12 | appdb = require('./dbs/' + dbtype + '/db'); 13 | return appdb; 14 | }; 15 | 16 | -------------------------------------------------------------------------------- /data/dbs/remote_demo/db.js: -------------------------------------------------------------------------------- 1 |  2 | // The main things definition for the server 3 | // The WoT server will manage these things 4 | var definitions = []; 5 | 6 | definitions.push( 7 | { 8 | "name": "door33", 9 | "model": { 10 | "@events": { 11 | "bell": { 12 | fields: [ 13 | "timestamp" 14 | ] 15 | }, 16 | }, 17 | "@properties": { 18 | "is_open": { 19 | "type": "boolean" 20 | }, 21 | "on": { 22 | "type": "boolean", 23 | "writeable": true 24 | }, 25 | "temperature": { 26 | "type": "numeric" 27 | } 28 | }, 29 | "@actions": { 30 | "unlock": null, 31 | "lock": null 32 | } 33 | } 34 | } 35 | ); 36 | 37 | 38 | exports.find_thing = function find_thing(name, callback) { 39 | var thing = null; 40 | for (i = 0; i < definitions.length; i++) { 41 | if (definitions[i].name == name) { 42 | thing = definitions[i]; 43 | break; 44 | } 45 | } 46 | 47 | if (!thing) { 48 | return callback("thing " + name + " definition doesn't exists in the database"); 49 | } 50 | 51 | // return the name, protocol and model 52 | callback(null, thing); 53 | } 54 | 55 | 56 | // the "things" list is for the clients, typically this will be rendered to the client UI 57 | var things = []; 58 | 59 | things.push({ name: 'door33', id: 3 }); 60 | 61 | 62 | // all databases returns the data asynchronously so return from this local file asynchronously as well 63 | // to keep the implementation consistent 64 | exports.things_list = function things_list( callback) { 65 | callback(null, things); 66 | } 67 | 68 | 69 | var endpoints = {}; 70 | 71 | exports.register_endpoint = function register_endpoint(thing, endpoint, callback) { 72 | if (endpoints[thing] == undefined) { 73 | endpoints[thing] = []; 74 | } 75 | 76 | var endpointlist = endpoints[thing]; 77 | 78 | // check if the endpoint for the thing is registered already 79 | for (i = 0; i < endpointlist.length; i++) { 80 | if (endpointlist[i] == endpoint) { 81 | // this endpoint already registered 82 | return callback(null, true); 83 | } 84 | } 85 | 86 | endpointlist.push(endpoint); 87 | 88 | callback(null, true); 89 | } 90 | 91 | 92 | exports.endpoint_list = function register_endpoint(thing, callback) { 93 | callback(null, endpoints[thing]); 94 | } -------------------------------------------------------------------------------- /documents/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/documents/layers.png -------------------------------------------------------------------------------- /documents/p2p/decentralized_iot.md: -------------------------------------------------------------------------------- 1 | # Decentralised peer-to-peer Internet of Things. 2 | 3 | A decentralised, peer-to-peer (P2P) system is a collection of applications run on several local computers, which connect remotely to each other to complete a function or a task. A decentralised peer to peer overlay network manages connections between human and Internet of Things peers. The participants in the network are the peer nodes. The peer to peer network is scalable and an unlimited number of nodes can participate in the network. 4 | 5 | Centralized corporate owned cloud is certainly an easier way to build out IoT platforms; however, the owners, application service providers, cloud service providers and authorities of these topologies have an influence upon the network and can exploit it. They can ban devices, spy on devices, report the activities of devices and compromise the data integrity of the devices. In fact, the government can order the cloud service operators and centralised application providers to do all of these things. 6 | 7 | In the near future, the doors, air condition units, and security system of homes will be fully internet connected. The users will be able to control their home automation system from a mobile phone device. It is essential that only the end user has full control over the IoT devices. Decentralised P2P Internet of Things aims to provide users with such exclusive control. 8 | 9 | ### Protocol design 10 | The [protocol readme document](protocol.md) describes the decentralized, peer-to-peer overlay network. 11 | 12 | -------------------------------------------------------------------------------- /documents/p2p/protocol.md: -------------------------------------------------------------------------------- 1 | 1. Introduction 2 | + 1.1. Architecture 3 | + 1.2 System components 4 | 5 | 2. Requirements Language 6 | 7 | 3. Terminology 8 | 9 | 4. The overlay network 10 | + 4.1 Network topology 11 | + 4.1.1 Nodes 12 | + 4.1.2 Transport layer 13 | + 4.1.3 Storage 14 | + 4.1.4 Blockchain 15 | + 4.2 System functions 16 | + 4.2.1 Contact discovery 17 | + 4.2.2 Service discovery 18 | + 4.2.3 Content delivery 19 | + 4.3 Security 20 | + 4.3.1 Public/private key infrastructure 21 | + 4.3.2 Identification 22 | + 4.3.3 Authentication 23 | + 4.3.4 Access control 24 | 25 | 5. Network protocol 26 | + 5.1 Message routing 27 | + 5.2 Messages 28 | + 5.2.1 PING 29 | + 5.2.2 STORE 30 | + 5.2.3 FIND_NODE 31 | + 5.2.4 FIND_VALUE 32 | + 5.2.5 FIND_RANGE 33 | + 5.2.6 DELETE 34 | + 5.2.7 ADD_BLOCK 35 | 36 | 6. Blockchain protocol 37 | + 6.1 Merkle tree 38 | + 6.2 Blockchain operations 39 | 40 | 7. Decentralized application (DAP) management 41 | + 7.1 Support for DAP 42 | + 7.2 Validate a DAP 43 | + 7.3 Enable a DAP 44 | 45 | 8. Acknowledgments 46 | 9. References 47 | -------------------------------------------------------------------------------- /examples/coap_demo/config.js: -------------------------------------------------------------------------------- 1 | /* config.js - JSON server configuration file */ 2 | 3 | var config = { 4 | framework: { 5 | // framework related settings 6 | action_timeout: 30000, // default action call timeout in milliseconds 7 | property_timeout: 30000 // default property set timeout in milliseconds 8 | }, 9 | /* 10 | Log levels are 11 | error 12 | info 13 | debug 14 | 15 | Use debug to log all levels and get detailed logs in the log file 16 | */ 17 | log: { 18 | level: "debug" 19 | }, 20 | // Server settings 21 | // These are really protocols but since the web server settings is included here as well the setting name is "server". 22 | // These servers/protocols will be exposed to the clients i.e. the clients connect to WoT via these servers/protocols 23 | servers: { 24 | web: { 25 | port: 8888, // http web server port to listen reqests from browsers 26 | }, 27 | ws: { 28 | port: 8080 // web socket port 29 | }, 30 | http: { 31 | // to provide end point for inter server communication 32 | // pass the fqdn to other wot servers as this is the end point listener 33 | fqdn: "http://localhost:8889", 34 | // end point port that listen for messages from other WoT servers 35 | port: 8889 36 | }, 37 | coap: { 38 | port: 5683 // default CoAP port 39 | } 40 | }, 41 | // The application database configuration. The ./data/dbs directory includes the database implementations 42 | // where the db.js file implements the database functions 43 | db: { 44 | type: 'file' 45 | } 46 | }; 47 | 48 | module.exports = config; -------------------------------------------------------------------------------- /examples/coap_demo/readme.md: -------------------------------------------------------------------------------- 1 | ## WoT Framework Demo 2 | 3 | Run this demo with "node demo.js" to create a WoT server to communicate with the simulator objects via the CoAP protocols. 4 | 5 | Make sure executing "npm install" to install dependencies such as the node-coap library. 6 | 7 | This demo wires up the door12 and switch12 devices. 8 | 9 | Once the Wot server is running open a browser session at http://localhost:8888 and then click on the "Things" menu item to view and manage the demo things. 10 | 11 | The web server port is configured in the config file that is in the same directory as the demo.js file. 12 | 13 | The door12 battery level changes in every 10 seconds, the door beel event is signalled every 30 seconds and if the systems works properly then the user interface is notified about the changes. By unlocking and locking the door the device simulator changes the "is_open" property and the UI receives notification about the change. 14 | 15 | Once the "on" property of the switch12 device is selected, the UI should be notified with the power consumption property level in every 10 seconds. 16 | 17 | To run the remote proxy device "door33" with the CoAP demo the remote WoT instance must be operational (see the remote_demo example) as well as the global.is_door33_defined variable must be set to "true" at the top of demo.js file. 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /examples/demo/config.js: -------------------------------------------------------------------------------- 1 | /* config.js - JSON server configuration file */ 2 | 3 | var config = { 4 | framework: { 5 | // framework related settings 6 | action_timeout: 30000, // default action call timeout in milliseconds 7 | property_timeout: 30000 // default property set timeout in milliseconds 8 | }, 9 | /* 10 | Log levels are 11 | error 12 | info 13 | debug 14 | 15 | Use debug to log all levels and get detailed logs in the log file 16 | */ 17 | log: { 18 | level: "debug" 19 | }, 20 | // Server settings 21 | // These are really protocols but since the web server settings is included here as well the setting name is "server". 22 | // These servers/protocols will be exposed to the clients i.e. the clients connect to WoT via these servers/protocols 23 | servers: { 24 | web: { 25 | port: 8888, // http web server port to listen reqests from browsers 26 | }, 27 | ws: { 28 | port: 8080 // web socket port 29 | }, 30 | http: { 31 | // to provide end point for inter server communication 32 | // pass the fqdn to other wot servers as this is the end point listener 33 | fqdn: "http://localhost:8889", 34 | // end point port that listen for messages from other WoT servers 35 | port: 8889 36 | }, 37 | restapi: { 38 | }, 39 | coap: { 40 | port: 5683 // default CoAP port 41 | }, 42 | mqtt: { 43 | } 44 | }, 45 | // The application database configuration. The ./data/dbs directory includes the database implementations 46 | // where the db.js file implements the database functions 47 | db: { 48 | type: 'file' 49 | } 50 | }; 51 | 52 | module.exports = config; -------------------------------------------------------------------------------- /examples/demo/readme.md: -------------------------------------------------------------------------------- 1 | ## WoT Framework Demo 2 | 3 | Run this demo with "node demo.js" to create a WoT server. 4 | 5 | Once the Wot server is running open a browser session at http://localhost:8888 and then click on the "Things" menu item to view and manage the demo things. 6 | Please note the web server port is configured in the config file that is in the same directory as the demo.js file. 7 | 8 | The door12 battery level changes in every 2 seconds, the door beel event is signalled in every 30 seconds and if the systems works properly then the user interface is notified about the changes. By unlocking and locking the door the device simulator changes the "is_open" property and the UI receives notification about the change. 9 | 10 | Once the "on" property of the switch12 device is selected, the UI should be notified with the power consumption property level in every 2 seconds. 11 | 12 | In order to receive notifications for door door33 the remote WoT instance must be operational (see the remote_demo example). 13 | 14 | Open a second, third, etc. browser session at http://localhost:8888 and then click on the "Things" menu item. The web socket transport should notify all broswer session upon property changes and events. 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/http_demo/api.js: -------------------------------------------------------------------------------- 1 | var logger = require('../../logger'); 2 | 3 | /** URL Router */ 4 | var express = require('express'), 5 | router = express.Router(); 6 | 7 | var create = function(req, res, next) { 8 | var data = req.params; 9 | var thing = req.app.thing; 10 | var model = thing.model; 11 | 12 | if (!data || !data.name || !data.type) { 13 | return next(new Error('Device HTTP listener error: invalid parameters')); 14 | } 15 | 16 | try { 17 | if (!data.type || !data.name || data.name != thing.name) { 18 | return; 19 | } 20 | 21 | logger.debug('HTTP device simulator received: ' + data.type + ' from ' + data.name); 22 | 23 | //console.log(req.params); 24 | switch (data.type) { 25 | case 'action': 26 | // handle the action 27 | var action = data.action; 28 | if (model.actions[action]) { 29 | model.actions[action](); 30 | } 31 | res.json({ result: true }); 32 | return next(); 33 | break; 34 | 35 | case 'patch': 36 | // set property 37 | var property = data.property; 38 | var value = data.value; 39 | if (model.properties[property]) { 40 | model.properties[property](value); 41 | } 42 | res.json({ result: true }); 43 | return next(); 44 | break; 45 | 46 | case 'property_get': 47 | // get property 48 | var property = data.property; 49 | var value = model.properties.get(property); 50 | res.json({ thing: thing.name, property: property, value: value }); 51 | return next(); 52 | break; 53 | 54 | default: 55 | next(new Error('HTTP device listener error: invalid action type')); 56 | break; 57 | } 58 | } 59 | catch (e) { 60 | logger.error(e); 61 | next(new Error('property get error: ' + e.message)); 62 | } 63 | 64 | } 65 | 66 | router.post('/:name/:type', create); 67 | 68 | module.exports = router; 69 | -------------------------------------------------------------------------------- /examples/http_demo/config.js: -------------------------------------------------------------------------------- 1 | /* config.js - JSON server configuration file */ 2 | 3 | var config = { 4 | framework: { 5 | // framework related settings 6 | action_timeout: 30000, // default action call timeout in milliseconds 7 | property_timeout: 30000 // default property set timeout in milliseconds 8 | }, 9 | /* 10 | Log levels are 11 | error 12 | info 13 | debug 14 | 15 | Use debug to log all levels and get detailed logs in the log file 16 | */ 17 | log: { 18 | level: "debug" 19 | }, 20 | // Server settings 21 | // These are really protocols but since the web server settings is included here as well the setting name is "server". 22 | // These servers/protocols will be exposed to the clients i.e. the clients connect to WoT via these servers/protocols 23 | servers: { 24 | web: { 25 | port: 8888, // http web server port to listen reqests from browsers 26 | }, 27 | ws: { 28 | port: 8080 // web socket port 29 | }, 30 | http: { 31 | // to provide end point for inter server communication 32 | // pass the fqdn to other wot servers as this is the end point listener 33 | fqdn: "http://localhost:8889", 34 | // end point port that listen for messages from other WoT servers and from IoT devices that communicate via the HTTP protocol 35 | port: 8889 36 | } 37 | }, 38 | // The application database configuration. The ./data/dbs directory includes the database implementations 39 | // where the db.js file implements the database functions 40 | db: { 41 | type: 'file' 42 | } 43 | }; 44 | 45 | module.exports = config; -------------------------------------------------------------------------------- /examples/http_demo/readme.md: -------------------------------------------------------------------------------- 1 | ## WoT Framework Demo 2 | 3 | Run this demo with "node demo.js" to create a WoT server to communicate with the simulator objects via the HTTP protocols. Real IoT devices would use this system similarly via the HTTP protocol as the simulator objects. The simulator and device objects communicates with the default HTTP end point of WoT server. The simulator and device objects expose an HTTP listener to receive messages from the WoT system. The WoT system uses an adapter object at /libs/adapters/http.js to send messages to the simulators/devices. 4 | 5 | This demo wires up the door12 and switch12 simulator devices. 6 | 7 | Once the Wot server is running open a browser session at http://localhost:8888 and then click on the "Things" menu item to view and manage the demo things. 8 | Please note the web server port is configured in the config file that is in the same directory as the demo.js file. 9 | 10 | The door12 battery level changes in every 10 seconds, the door beel event is signalled in every 30 seconds and if the systems works properly then the user interface is notified about the changes. By unlocking and locking the door the device simulator changes the "is_open" property and the UI receives notification about the change. 11 | 12 | Once the "on" property of the switch12 device is selected, the UI should be notified with the power consumption property level in every 10 seconds. 13 | 14 | To run the remote proxy device "door33" with this HTTP demo the remote WoT instance must be operational (see the remote_demo example) as well as the global.is_door33_defined variable must be set to "true" at the top of demo.js file. 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/http_express_demo/api.js: -------------------------------------------------------------------------------- 1 | var logger = require('../../logger'); 2 | 3 | /** URL Router */ 4 | var express = require('express'), 5 | router = express.Router(); 6 | 7 | var create = function(req, res, next) { 8 | var data = req.params; 9 | var thing = req.app.thing; 10 | var model = thing.model; 11 | 12 | if (!data || !data.name || !data.type) { 13 | return next(new Error('Device HTTP listener error: invalid parameters')); 14 | } 15 | 16 | try { 17 | if (!data.type || !data.name || data.name != thing.name) { 18 | return; 19 | } 20 | 21 | logger.debug('HTTP device simulator received: ' + data.type + ' from ' + data.name); 22 | 23 | //console.log(req.params); 24 | switch (data.type) { 25 | case 'action': 26 | // handle the action 27 | var action = data.action; 28 | if (model.actions[action]) { 29 | model.actions[action](); 30 | } 31 | res.json({ result: true }); 32 | return next(); 33 | break; 34 | 35 | case 'patch': 36 | // set property 37 | var property = data.property; 38 | var value = data.value; 39 | if (model.properties[property]) { 40 | model.properties[property](value); 41 | } 42 | res.json({ result: true }); 43 | return next(); 44 | break; 45 | 46 | case 'property_get': 47 | // get property 48 | var property = data.property; 49 | var value = model.properties.get(property); 50 | res.json({ thing: thing.name, property: property, value: value }); 51 | return next(); 52 | break; 53 | 54 | default: 55 | next(new Error('HTTP device listener error: invalid action type')); 56 | break; 57 | } 58 | } 59 | catch (e) { 60 | logger.error(e); 61 | next(new Error('property get error: ' + e.message)); 62 | } 63 | 64 | } 65 | 66 | router.post('/:name/:type', create); 67 | 68 | module.exports = router; 69 | -------------------------------------------------------------------------------- /examples/http_express_demo/config.js: -------------------------------------------------------------------------------- 1 | /* config.js - JSON server configuration file */ 2 | 3 | var config = { 4 | framework: { 5 | // framework related settings 6 | action_timeout: 30000, // default action call timeout in milliseconds 7 | property_timeout: 30000 // default property set timeout in milliseconds 8 | }, 9 | /* 10 | Log levels are 11 | error 12 | info 13 | debug 14 | 15 | Use debug to log all levels and get detailed logs in the log file 16 | */ 17 | log: { 18 | level: "debug" 19 | }, 20 | // Server settings 21 | // These are really protocols but since the web server settings is included here as well the setting name is "server". 22 | // These servers/protocols will be exposed to the clients i.e. the clients connect to WoT via these servers/protocols 23 | servers: { 24 | web: { 25 | port: 8888, // http web server port to listen reqests from browsers 26 | }, 27 | ws: { 28 | port: 8080 // web socket port 29 | }, 30 | http: { 31 | // to provide end point for inter server communication 32 | // pass the fqdn to other wot servers as this is the end point listener 33 | fqdn: "http://localhost:8889", 34 | // end point port that listen for messages from other WoT servers and from IoT devices that communicate via the HTTP protocol 35 | port: 8889 36 | } 37 | }, 38 | // The application database configuration. The ./data/dbs directory includes the database implementations 39 | // where the db.js file implements the database functions 40 | db: { 41 | type: 'file' 42 | } 43 | }; 44 | 45 | module.exports = config; -------------------------------------------------------------------------------- /examples/http_express_demo/readme.md: -------------------------------------------------------------------------------- 1 | ## WoT Framework Demo 2 | 3 | Run this demo with "node demo.js" to create a WoT server to communicate with the simulator objects via the HTTP protocols. Real IoT devices would use this system similarly via the HTTP protocol as the simulator objects. The simulator and device objects communicates with the default HTTP end point of WoT server. The simulator and device objects expose an HTTP listener to receive messages from the WoT system. The WoT system uses an adapter object at /libs/adapters/http.js to send messages to the simulators/devices. 4 | 5 | This demo wires up the door12 and switch12 simulator devices. 6 | 7 | Once the Wot server is running open a browser session at http://localhost:8888 and then click on the "Things" menu item to view and manage the demo things. 8 | Please note the web server port is configured in the config file that is in the same directory as the demo.js file. 9 | 10 | The door12 battery level changes in every 10 seconds, the door beel event is signalled in every 30 seconds and if the systems works properly then the user interface is notified about the changes. By unlocking and locking the door the device simulator changes the "is_open" property and the UI receives notification about the change. 11 | 12 | Once the "on" property of the switch12 device is selected, the UI should be notified with the power consumption property level in every 10 seconds. 13 | 14 | To run the remote proxy device "door33" with this HTTP demo the remote WoT instance must be operational (see the remote_demo example) as well as the global.is_door33_defined variable must be set to "true" at the top of demo.js file. 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /examples/mqtt_demo/config.js: -------------------------------------------------------------------------------- 1 | /* config.js - JSON server configuration file */ 2 | 3 | var config = { 4 | framework: { 5 | // framework related settings 6 | action_timeout: 30000, // default action call timeout in milliseconds 7 | property_timeout: 30000 // default property set timeout in milliseconds 8 | }, 9 | /* 10 | Log levels are 11 | error 12 | info 13 | debug 14 | 15 | Use debug to log all levels and get detailed logs in the log file 16 | */ 17 | log: { 18 | level: "debug" 19 | }, 20 | // Server settings 21 | // These are really protocols but since the web server settings is included here as well the setting name is "server". 22 | // These servers/protocols will be exposed to the clients i.e. the clients connect to WoT via these servers/protocols 23 | servers: { 24 | web: { 25 | port: 8888, // http web server port to listen reqests from browsers 26 | }, 27 | ws: { 28 | port: 8080 // web socket port 29 | }, 30 | http: { 31 | // to provide end point for inter server communication 32 | // pass the fqdn to other wot servers as this is the end point listener 33 | fqdn: "http://localhost:8889", 34 | // end point port that listen for messages from other WoT servers 35 | port: 8889 36 | }, 37 | mqtt: { 38 | } 39 | }, 40 | // The application database configuration. The ./data/dbs directory includes the database implementations 41 | // where the db.js file implements the database functions 42 | db: { 43 | type: 'file' 44 | } 45 | }; 46 | 47 | module.exports = config; -------------------------------------------------------------------------------- /examples/mqtt_demo/readme.md: -------------------------------------------------------------------------------- 1 | ## WoT Framework MQTT Demo 2 | 3 | TODO 4 | 5 | -------------------------------------------------------------------------------- /examples/p2p_demo/config.js: -------------------------------------------------------------------------------- 1 | /* config.js - JSON server configuration file */ 2 | 3 | var config = { 4 | framework: { 5 | // framework related settings 6 | action_timeout: 30000, // default action call timeout in milliseconds 7 | property_timeout: 30000 // default property set timeout in milliseconds 8 | }, 9 | /* 10 | Log levels are 11 | error 12 | info 13 | debug 14 | 15 | Use debug to log all levels and get detailed logs in the log file 16 | */ 17 | log: { 18 | level: "debug" 19 | }, 20 | servers: { 21 | p2p: { 22 | nodes: [ 23 | { 24 | address: 'localhost', 25 | port: 31300, 26 | nick: "wotseed01", 27 | seeds: [] 28 | }, 29 | { 30 | address: 'localhost', 31 | port: 31301, 32 | nick: "wotseed02", 33 | seeds: [{ address: 'localhost', port: 31300 }] 34 | } 35 | ] 36 | } 37 | }, 38 | // The application database configuration. The ./data/dbs directory includes the database implementations 39 | // where the db.js file implements the database functions` 40 | db: { 41 | type: 'file' 42 | } 43 | }; 44 | 45 | module.exports = config; -------------------------------------------------------------------------------- /examples/p2p_demo/crypto_demo.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto') 2 | var secrand = require('secure-random'); 3 | var EccKey = require('../../libs/crypto/ecc/EccKey'); 4 | var ecdsa = require('../../libs/crypto/ecc/EccDsa'); 5 | var eccsign = require('../../libs/crypto/ecc/EccSign'); 6 | var eccverify = require('../../libs/crypto/ecc/EccVerify'); 7 | var jwt = require('../../libs/message/jwt'); 8 | var WoTMessage = require('../../libs/message/wotmsg'); 9 | 10 | var random_bytes = secrand.randomBuffer(32); 11 | var pwd = crypto.createHash('sha1').update(random_bytes).digest().toString('hex'); 12 | var key = new EccKey(pwd); 13 | 14 | var wotmsg = new WoTMessage(); 15 | var token = wotmsg.create(key.privateKey, { foo: "bar" }, null, 1800, "door12", "some message" ); 16 | var decoded = wotmsg.decode(token, key.publicKeyStr); 17 | console.log(decoded.data.foo == "bar"); 18 | 19 | token = jwt.encode({ data: { foo: "bar" } }, key.privateKey, {expiresIn: 1800, issuer: "door12", subject :"some message"}); 20 | decoded = jwt.decode(token, key.publicKeyStr); 21 | console.log(decoded.data.foo == "bar"); 22 | 23 | var obj = { foo: "bar" }; 24 | var signature = eccsign(key.privateKey, obj); 25 | var is_valid = eccverify(key.publicKeyStr, obj, signature); 26 | 27 | var msg = new Buffer("hello", 'utf8'); 28 | var shaMsg = crypto.createHash('sha256').update(msg).digest(); 29 | var signature = ecdsa.sign(shaMsg, key.privateKey); 30 | is_valid = ecdsa.verify(shaMsg, signature, key.publicKey); 31 | console.log(isValid) //true 32 | 33 | msg = new Buffer("test", 'utf8'); 34 | shaMsg = crypto.createHash('sha256').update(msg).digest(); 35 | signature = ecdsa.sign(shaMsg, key.privateKey); 36 | is_valid = ecdsa.verify(shaMsg, signature, key.publicKey); 37 | console.log(isValid); -------------------------------------------------------------------------------- /examples/p2p_demo/peer_demo.js: -------------------------------------------------------------------------------- 1 | var PeerNetwork = require('../../libs/transport/p2p/wotkad/peer_network'); 2 | var logger = require('../../logger'); 3 | 4 | var peernet = new PeerNetwork(); 5 | 6 | // create the overlay network with node1 7 | var options = { 8 | address: '127.0.0.1', 9 | port: 65529, 10 | nick: 'seed1' 11 | }; 12 | var seed1 = peernet.create_peer(options); 13 | 14 | options = { 15 | address: '127.0.0.1', 16 | port: 65530, 17 | nick: 'seed2', 18 | seeds: [{ address: '127.0.0.1', port: 65529 }] 19 | }; 20 | var seed2 = peernet.create_peer(options); 21 | 22 | // connect to the overlay network 23 | options = { 24 | address: '127.0.0.1', 25 | port: 65531, 26 | nick: 'node2', 27 | seeds: [{ address: '127.0.0.1', port: 65529 }] 28 | }; 29 | var peer2 = peernet.create_peer(options); 30 | 31 | options = { 32 | address: '127.0.0.1', 33 | port: 65532, 34 | nick: 'node3', 35 | seeds: [{ address: '127.0.0.1', port: 65530 }] 36 | }; 37 | var peer3 = peernet.create_peer(options); 38 | 39 | peer2.on('connect', function (err, value) { 40 | if (err) { 41 | return logger.error("peer connect error %j", err, {}); 42 | } 43 | 44 | logger.debug("peer peer2 %j connected to overlay network", value, {}); 45 | 46 | peer2.put('door12/events/bell', 'beep1 from peer2', function (err) { 47 | if (err) { 48 | return logger.error("onPut error %j", err, {}); 49 | } 50 | 51 | }); 52 | 53 | }); 54 | 55 | peer3.on('connect', function (err, value) { 56 | if (err) { 57 | return logger.error("peer connect error %j", err, {}); 58 | } 59 | 60 | logger.debug("peer peer3 %j connected to overlay network", value, {}); 61 | 62 | peernet.on('data', function (key) { 63 | if (key == 'door12/events/bell') { 64 | peer3.get('door12/events/bell', function (err, value) { 65 | if (err) { 66 | return logger.error("peer get error %j", err, {}); 67 | } 68 | logger.debug('--------------------------------------------------------------------------------------------------------'); 69 | logger.debug('peer3 received door12/events/bell value is : ' + value); 70 | logger.debug('--------------------------------------------------------------------------------------------------------'); 71 | }); 72 | } 73 | }); 74 | 75 | }); -------------------------------------------------------------------------------- /examples/p2p_demo/readme.md: -------------------------------------------------------------------------------- 1 | ## WoT Framework P2P (peer to peer) Demo 2 | 3 | Run the P2P demo by executing "node demo.js" from the \examples\p2pdemo directory. 4 | 5 | The P2P architecture implements a decentralized Kademlia distributed hash table (DHT) and peer to peer network via the UDP transport layer. 6 | 7 | The P2P design aims to utilize the scalability and high availability features of the decentralized network concept. Having no central server theoretically means no central point of failure. The solution is scalable – in fact more devices on the network should result in more optimal data propagation and increased security. 8 | 9 | The main purpose of the DHT is to provide device discovery service, decentralized data storage for device data, particularly for devices that are source of big-data, to provide publishing of device schemas and accessibility information as well as facilitate communication between devices and public/private networks. The P2P paradigm is also suitable for networks with small number of devices if users prefer peer to peer networking over the conventional client/server topology. 10 | 11 | This is a hybrid design as direct communication is possible with the devices via UDP peer to peer messaging. In case of direct peer to peer communication the device data is not stored in the DHT. 12 | 13 | The message handling uses JSON Web Token (JWT). Currently it supports ECC based cryptography, ES256, ES384, ES512 algorithms. The message signature aims to comply with the JSON Web Signature (JWS) standard. 14 | Devices, things and human users can send messages directly to each other via UDP instead of publishing the data to the public DHT. Such direct messages are encrypted with shared symmetric cryptography keys. The cryptography keys are shared between devices/users using Diffie-Hellman key exchange. The system uses the EC Diffie-Hellman key exchanges mehods (ECDH) of the NodeJs crypto library to perform the symmetric key exchange. This implementation aims to comply witht he JSON Web Encryption (JWE) sandards. (TODO: perhaps need to add standard key wrapping methods). 15 | 16 | This particular demo demonstrates two smart cars, a Toyota and a Ford. The vehicles update a public traffic information database with their speed and location data, so once there are a large number of cars participate in the network, big-data applications could provide end users with traffic info with regards to a particular location, road, motorway, etc. 17 | 18 | The demo vehicles raise events upon exceeding a predefined speed limit as well signal an event when the door is opened or the vehicle is closed. Designated users, security companies, etc. can receive the events. Such events aren’t exposed to the public network and encrypted with the shared symmetric cryptography key of authorized users and the device. More events will be added to the demo to demonstrate engine, diagnostic and security related events. Currently the demo sends an encrypted peer message from P2P node "ToyotaClient01" to P2P node "Toyota" (which reprsents the car manufacturer) in every 15 seconds to send some demo timestamp information. In real life scenario the information would be for exmaple speed, location or diganostic data. 19 | -------------------------------------------------------------------------------- /examples/raspberrypi_demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | *.log 3 | 4 | # Runtime data 5 | pids 6 | *.pid 7 | *.seed 8 | 9 | # Directory for instrumented libs generated by jscoverage/JSCover 10 | lib-cov 11 | 12 | # Coverage directory used by tools like istanbul 13 | coverage 14 | 15 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 16 | .grunt 17 | 18 | # node-waf configuration 19 | .lock-wscript 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Dependency directory 25 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 26 | node_modules 27 | 28 | .DS_Store 29 | design.txt 30 | readme 31 | notes 32 | 33 | # don't sync Visual Studio files 34 | .ntvs_analysis.dat 35 | .ntvs_analysis.dat.tmp 36 | bin/ 37 | obj/ 38 | *.njsproj 39 | *.suo 40 | *.sln 41 | logs/*.log 42 | 43 | *.ldb 44 | *.dat 45 | /db/maindb 46 | /db/localdb 47 | build/buildtools 48 | build/win64 49 | build/linux64 50 | build/macosx64 51 | *.nw 52 | /.vs/config/applicationhost.config 53 | /data 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional REPL history 59 | .node_repl_history 60 | 61 | *.zip 62 | -------------------------------------------------------------------------------- /examples/raspberrypi_demo/appdefs.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of Streembit application. 4 | Streembit is an open source project to create a real time communication system for humans and machines. 5 | 6 | Streembit is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation, either version 3.0 of the License, or (at your option) any later version. 8 | 9 | Streembit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with Streembit software. 13 | If not, see http://www.gnu.org/licenses/. 14 | 15 | ------------------------------------------------------------------------------------------------------------------------- 16 | Author: Tibor Zsolt Pardi 17 | Copyright (C) 2016 The Streembit software development team 18 | ------------------------------------------------------------------------------------------------------------------------- 19 | 20 | */ 21 | 22 | 23 | 'use strict'; 24 | 25 | var streembit = streembit || {}; 26 | 27 | streembit.DEFS = (function (module) { 28 | return { 29 | APP_PORT: 8905, // Appliction port 30 | BOOT_PORT: 32319, // Discovery port for the Streembit network 31 | WS_PORT: 32318, // Default Web Socket port 32 | 33 | TRANSPORT_TCP: "tcp", // TCP/IP 34 | TRANSPORT_WS: "ws", // websocket 35 | 36 | PRIVATE_NETWORK: "private", 37 | PUBLIC_NETWORK: "public", 38 | 39 | USER_TYPE_HUMAN: "human", 40 | USER_TYPE_DEVICE: "device", 41 | USER_TYPE_SERVICE: "service", 42 | 43 | ERR_CODE_SYSTEMERR: 0x1000, 44 | ERR_CODE_INVALID_CONTACT: 0x1001, 45 | 46 | PEERMSG_CALL_WEBRTC: "CALL_WEBRTC", 47 | PEERMSG_CALL_WEBRTCSS: "CALL_WEBRTCSS", // offer share screen 48 | PEERMSG_CALL_WEBRTCAA: "CALL_WEBRTCAA", // auto audio call (audio call with screen sharing without prompting the user) 49 | PEERMSG_FILE_WEBRTC: "FILE_WEBRTC", 50 | PEERMSG_TXTMSG: "TXTMSG", 51 | PEERMSG_FSEND: "FSEND", 52 | PEERMSG_FRECV: "FRECV", 53 | PEERMSG_FEXIT: "FEXIT", 54 | PEERMSG_DEVDESC_REQ: "DEVDESCREQ", 55 | PEERMSG_DEVDESC: "DEVDESC", 56 | PEERMSG_DEVREAD_PROP: "DEVREADPROP", 57 | PEERMSG_DEVREAD_PROP_REPLY: "DEVREADPROP_REPLY", 58 | PEERMSG_DEVSUBSC: "DEVSUBSC", 59 | PEERMSG_DEVSUBSC_REPLY: "DEVSUBSC_REPLY", 60 | PEERMSG_DEV_EVENT: "DEV_EVENT", 61 | 62 | MSG_TEXT: "text", 63 | MSG_ADDCONTACT: "addcontact", 64 | MSG_ACCEPTCONTACT: "acceptcontact", 65 | MSG_DECLINECONTACT: "declinecontact" 66 | } 67 | 68 | }(streembit.DEFS || {})) 69 | 70 | module.exports = streembit.DEFS; -------------------------------------------------------------------------------- /examples/raspberrypi_demo/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "node": { 3 | "account": "", 4 | "address": "", 5 | "port": 32320, 6 | "seeds": [ 7 | { "address": "seed.streemio.org", "port": 32320, "public_key": "033b726f5ff2fc02a009ab2ef0844b807372af4b13d1236c2df9752de1ee93f5fa" }, 8 | { "address": "seed.streemio.net", "port": 32320, "public_key": "033d92278f9440c8b4061dddf862f5e224d0ff312e642edfa2c93c86671442609f" }, 9 | { "address": "seed.streemio.biz", "port": 32320, "public_key": "026f2303d7932ed86bf21b7150bcd45024f3926d37b615798855994b6b53e8b81b" }, 10 | { "address": "seed.streemo.uk", "port": 32320, "public_key": "035f4881a0c7d50af6fcf7cc40c3eab60c382bf7f8cd83cd2a3ff5064afd893c70" } 11 | ] 12 | }, 13 | "log": { 14 | "level": "debug" 15 | }, 16 | "transport": "tcp", 17 | "private_network": false, 18 | "private_network_accounts": [ ], 19 | "devices": [ ], 20 | "contactsonly": true, 21 | "contacts": [ 22 | ] 23 | 24 | } -------------------------------------------------------------------------------- /examples/raspberrypi_demo/db/readme.md: -------------------------------------------------------------------------------- 1 | # Levalelup Database directory 2 | 3 | The db directory must exists when the app is deployed. 4 | -------------------------------------------------------------------------------- /examples/raspberrypi_demo/message.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of Streembit application. 4 | Streembit is an open source project to create a real time communication system for humans and machines. 5 | 6 | Streembit is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation, either version 3.0 of the License, or (at your option) any later version. 8 | 9 | Streembit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 10 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with Streembit software. 13 | If not, see http://www.gnu.org/licenses/. 14 | 15 | ------------------------------------------------------------------------------------------------------------------------- 16 | Author: Tibor Zsolt Pardi 17 | Copyright (C) 2016 The Streembit software development team 18 | ------------------------------------------------------------------------------------------------------------------------- 19 | 20 | */ 21 | 22 | 23 | 'use strict'; 24 | 25 | var streembit = streembit || {}; 26 | 27 | var nodecrypto = require(global.cryptolib); 28 | var wotmsg = require("streembitlib/message/wotmsg"); 29 | var uuid = require("uuid"); 30 | 31 | streembit.Message = (function (msgobj, logger, events) { 32 | 33 | msgobj.getvalue = function (val) { 34 | return wotmsg.base64decode(val); 35 | } 36 | 37 | msgobj.decode = function (payload, public_key) { 38 | return wotmsg.decode(payload, public_key); 39 | } 40 | 41 | msgobj.aes256decrypt = function (symmetric_key, cipher_text) { 42 | return wotmsg.aes256decrypt(symmetric_key, cipher_text); 43 | } 44 | 45 | msgobj.aes256encrypt = function (symmetric_key, data) { 46 | return wotmsg.aes256encrypt(symmetric_key, data); 47 | } 48 | 49 | msgobj.decrypt_ecdh = function (rcpt_private_key, rcpt_public_key, sender_public_key, jwe_input) { 50 | return wotmsg.decrypt_ecdh(rcpt_private_key, rcpt_public_key, sender_public_key, jwe_input); 51 | } 52 | 53 | msgobj.getpayload = function (msg) { 54 | return wotmsg.getpayload(msg); 55 | } 56 | 57 | msgobj.create_peermsg = function (data, notbuffer) { 58 | var message = { 59 | type: "PEERMSG", 60 | data: data 61 | }; 62 | var strobj = JSON.stringify(message); 63 | if (notbuffer) { 64 | return strobj; 65 | } 66 | 67 | var buffer = new Buffer(strobj); 68 | return buffer; 69 | } 70 | 71 | msgobj.create_id = function () { 72 | var temp = uuid.v4().toString(); 73 | var id = temp.replace(/-/g, ''); 74 | return id; 75 | } 76 | 77 | msgobj.create_hash_id = function (data) { 78 | var hashid = nodecrypto.createHash('sha1').update(data).digest().toString('hex'); 79 | return hashid; 80 | } 81 | 82 | return msgobj; 83 | 84 | }(streembit.Message || {}, global.applogger, global.appevents)); 85 | 86 | 87 | module.exports = streembit.Message; -------------------------------------------------------------------------------- /examples/raspberrypi_demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "streembit-pi", 3 | "version": "1.0.1", 4 | "description": "streembit-pi", 5 | "main": "streembit.js", 6 | "author": { 7 | "name": "TZ Pardi", 8 | "email": "tzpardi@streembit.com" 9 | }, 10 | "dependencies": { 11 | "collections": "^3.0.0", 12 | "ds18x20": "^0.2.0", 13 | "leveldown": "^1.4.3", 14 | "levelup": "^1.3.1", 15 | "pm2": "^1.0.0", 16 | "secure-random": "^1.1.1", 17 | "socket.io": "^1.4.3", 18 | "streembitlib": "git+https://github.com/streembit/streembitlib.git", 19 | "uuid": "^2.0.1" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/raspberrypi_demo/readme_ds18b20.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | http://www.reuk.co.uk/DS18B20-Temperature-Sensor-with-Raspberry-Pi.htm 4 | 5 | Configure the 1-Wire interface 6 | ------------------------------ 7 | 8 | The tutorials suggest to enable the 1-wire interface from the terminal, but on the new Raspberry Pi use the Advanced options of raspi-config to enable 1-wire. 9 | 10 | ```bash 11 | $ raspi-config 12 | ``` 13 | 14 | Select option 9, "Advanced options" and then select "1-Wire" to enable the interface. 15 | 16 | Load the drivers 17 | ---------------- 18 | 19 | (Please note, it seems the DS18B20 temperature sensor and 1-Wire interface works with the new Raspberry Pi 3 devices without loading the drivers. If not, performs the steps below.) 20 | 21 | In order to probe the sensors, the temperature driver needs to be loaded. To load the drivers enter in the terminal before starting Streembit. 22 | 23 | ```bash 24 | $ sudo modprobe w1-gpio && sudo modprobe w1-therm 25 | ``` 26 | 27 | Alternatively, create a shell script to load the driver by executing the above command when booting the device. 28 | 29 | The device description follows the recommendations of the [WoT standardization initiative](https://www.w3.org/WoT/IG/). 30 | 31 | ```json 32 | { 33 | "@context": "http://schema.org/", 34 | "metadata": { "name": "Temperature Sensor"}, 35 | "encodings": ["JSON"], 36 | "interactions": [ 37 | { 38 | "@type": "Property", 39 | "name": "temperature", 40 | "outputData": "xsd:float", 41 | "writable": false 42 | }, 43 | { 44 | "@type": "Event", 45 | "outputData": "xsd:float", 46 | "name": "highTemperature" 47 | } 48 | ] 49 | }; 50 | ``` 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /examples/raspberrypi_demo/utilities.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of Streembit application. 4 | Streembit is an open source project to create a real time communication system for humans and machines. 5 | 6 | Streembit is a free software: you can redistribute it and/or modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation, either version 3.0 of the License, or (at your option) any later version. 8 | 9 | Streembit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with Streembit software. 13 | If not, see http://www.gnu.org/licenses/. 14 | 15 | ------------------------------------------------------------------------------------------------------------------------- 16 | Author: Tibor Zsolt Pardi 17 | Copyright (C) 2016 The Streembit software development team 18 | ------------------------------------------------------------------------------------------------------------------------- 19 | 20 | */ 21 | 22 | 23 | var path = require('path'); 24 | var fs = require('fs'); 25 | 26 | exports.ensure_dbdir_exists = function (dbdir, callback) { 27 | 28 | var dbpath = path.join(__dirname, 'db', dbdir); 29 | 30 | fs.open(dbpath, 'r', function (err, fd) { 31 | if (err && err.code == 'ENOENT') { 32 | // not exists 33 | try { 34 | fs.mkdirSync(dbpath); 35 | } 36 | catch (e) { 37 | logger.error("creating " + dbpath + " directory error: " + e.message); 38 | } 39 | 40 | fs.open(dbpath, 'r', function (err, fd) { 41 | callback(err) 42 | }); 43 | } 44 | else { 45 | // directory exists 46 | callback(); 47 | } 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /examples/remote_demo/config.js: -------------------------------------------------------------------------------- 1 | /* config.js - JSON server configuration file */ 2 | 3 | var config = { 4 | framework: { 5 | // framework related settings 6 | action_timeout: 30000, // default action call timeout in milliseconds 7 | property_timeout: 30000 // default property set timeout in milliseconds 8 | }, 9 | /* 10 | Log levels are 11 | error 12 | info 13 | debug 14 | 15 | Use debug to log all levels and get detailed logs in the log file 16 | */ 17 | log: { 18 | level: "debug" 19 | }, 20 | // Server settings 21 | // These are really protocols but since the web server settings is included here as well the setting name is "server". 22 | // These servers/protocols will be exposed to the clients i.e. the clients connect to WoT via these servers/protocols 23 | servers: { 24 | http: { 25 | // to provide end point for inter server communication 26 | // pass the fqdn to other wot servers as this is the end point listener 27 | fqdn: "http://localhost:8890", 28 | // end point port that listen for messages from other WoT servers 29 | port: 8890 30 | } 31 | }, 32 | // The application database configuration. The ./data/dbs directory includes the database implementations 33 | // where the db.js file implements the database functions 34 | db: { 35 | type: 'remote_demo' 36 | } 37 | }; 38 | 39 | module.exports = config; -------------------------------------------------------------------------------- /examples/remote_demo/readme.md: -------------------------------------------------------------------------------- 1 | # WoT Framework Demo 2 | 3 | Run this file with "node demo.js" from this directory to create a new instance of WoT server on the local machine (or on a remote server) to test the communication between two WoT server instances. 4 | 5 | Go to the examples directory and start the remote server: 6 | 7 | cd examples 8 | 9 | node remote_demo/demo.js 10 | 11 | Once the remote_demo/demo.js is started run "node demo.js" from the /examples/demo directory. 12 | 13 | node demo/demo.js 14 | 15 | The demo/demo.js WoT will send the property get/set, actions and patch to the remote_demo/demo.js WoT with regards to the door33 thing. The remote_demo/demo.js will send property updates and events of door33 to the HTTP endpoint of demo/demo.js. 16 | 17 | Open a browser session at http://localhost:8888 and then click on the "Things" menu item to view and manage the demo things. The door33 temperature changes every 2 second, the door's bell event is signalled every 30 seconds and if the systems work properly then the user interface is notified about the changes. When the actions and patch are invoked from the UI then the console should print debug messages. 18 | 19 | Open a second, third, etc. browser session at http://localhost:8888 and then click on the "Things" menu item. The web socket transport should notify all broswer session upon property changes and events. 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /framework.js: -------------------------------------------------------------------------------- 1 | // wot-framework.js 2 | var logger = require('./logger'); 3 | 4 | var server_handler = require('./transports/server_handler'); 5 | var thing_handler = require('./libs/thing/thing_handler'); 6 | 7 | exports.init = function init(things) { 8 | // call the thing handler to start handling the things 9 | thing_handler.init(things); 10 | 11 | // start the servers 12 | server_handler.init(); 13 | 14 | logger.debug("WoT Framework is initialised"); 15 | 16 | } 17 | 18 | exports.things_init = function things_init(things) { 19 | // call the thing handler to start handling the things 20 | thing_handler.init(things); 21 | 22 | logger.debug("WoT Framework things are initialised"); 23 | } 24 | 25 | 26 | exports.transport_init = function transport_init() { 27 | // start the servers 28 | server_handler.init(); 29 | 30 | logger.debug("WoT Framework transport is initialised"); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /libs/adapters/coap.js: -------------------------------------------------------------------------------- 1 | var logger = require('../../logger'); 2 | var coap = require('coap'); 3 | 4 | exports.init = function init(adapter, callback) { 5 | logger.info('CoAP adapter init'); 6 | 7 | if (!adapter || !adapter.device || adapter.protocol != "coap" || !adapter.host) { 8 | return callback("Invalid CoAP adapter configuration parameters"); 9 | } 10 | 11 | // TODO more initialisation, loging, audit here 12 | 13 | callback(null); 14 | } 15 | 16 | 17 | exports.unbind = function unbind(callback) { 18 | logger.info('CoAP adapter unbind'); 19 | 20 | callback(null); 21 | } 22 | 23 | 24 | exports.send = function action(url, msg, callback) { 25 | try { 26 | logger.info('CoAP adapter send message'); 27 | 28 | var req = coap.request(url) 29 | 30 | req.write(JSON.stringify(msg)); 31 | 32 | req.on('response', function (res) { 33 | try { 34 | // return only the payload 35 | var payload = res && res.payload && res.payload.length ? JSON.parse(res.payload.toString()) : null; 36 | if (payload) { 37 | callback(null, payload); 38 | } 39 | else { 40 | callback("Invaid COAP pyalod in response"); 41 | } 42 | } 43 | catch (err) { 44 | logger.info('CoAP adapter response handler error: ' + err.message); 45 | } 46 | }) 47 | 48 | req.end(); 49 | } 50 | catch (e) { 51 | logger.info('CoAP adapter send error: ' + e.message); 52 | } 53 | } 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /libs/adapters/http.js: -------------------------------------------------------------------------------- 1 | var restify = require('restify'); 2 | var logger = require('../../logger'); 3 | 4 | 5 | exports.init = function init(adapter, callback) { 6 | logger.info('HTTP adapter init'); 7 | 8 | if (!adapter || !adapter.device || adapter.protocol != "http" || !adapter.host) { 9 | return callback("Invalid CoAP adapter configuration parameters"); 10 | } 11 | 12 | // TODO more initialisation, loging, audit here 13 | 14 | callback(null); 15 | } 16 | 17 | 18 | exports.unbind = function unbind(callback) { 19 | logger.info('CoAP adapter unbind'); 20 | 21 | callback(null); 22 | } 23 | 24 | 25 | exports.send = function action(url, path, msg, callback) { 26 | try { 27 | logger.info('HTTP adapter send message'); 28 | 29 | var client = restify.createJsonClient({ 30 | url: url, 31 | version: '*', 32 | agent: false 33 | }); 34 | 35 | 36 | client.post(path, msg, function (err, req, res, data) { 37 | if (err) { 38 | callback("HTTP adapter " + path + " error: " + err); 39 | } 40 | else if (!data) { 41 | callback("HTTP adapter " + path + " invalid result"); 42 | } 43 | else { 44 | callback(null, data); 45 | } 46 | 47 | client.close(); 48 | }); 49 | 50 | } 51 | catch (e) { 52 | logger.info('HTTP adapter send error: ' + e.message); 53 | } 54 | } 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /libs/adapters/mqtt.js: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /libs/crypto/crypto_handler.js: -------------------------------------------------------------------------------- 1 |  2 | function CryptoHandler(alg, initstr) { 3 | if (!(this instanceof CryptoHandler)) { 4 | return new CryptoHandler(); 5 | } 6 | 7 | this.alg = alg; 8 | } 9 | 10 | CryptoHandler.prototype.sign = function () { 11 | var self = this; 12 | 13 | } 14 | 15 | 16 | CryptoHandler.prototype.verify = function () { 17 | 18 | } 19 | 20 | 21 | module.exports = CryptoHandler; -------------------------------------------------------------------------------- /libs/crypto/ecc/ECCSign.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | var crypto = require('crypto'); 21 | var ecdsa = require('./EccDsa'); 22 | 23 | function EccSign(privateKey, input) { 24 | if (!privateKey || input == undefined) { 25 | throw new Error("Invalid EccSign parameters"); 26 | return; 27 | } 28 | 29 | var text = null; 30 | try { 31 | if (typeof input != 'string') { 32 | if (typeof input == 'object') { 33 | try { 34 | text = JSON.stringify(input); 35 | } 36 | catch (e) { 37 | text = input.toString(); 38 | } 39 | } 40 | else { 41 | text = input.toString(); 42 | } 43 | } 44 | else { 45 | text = input; 46 | } 47 | } 48 | catch (err) { 49 | throw new Error("Invalid EccSign input parameter"); 50 | } 51 | 52 | if (!text) { 53 | throw new Error("Invalid EccSign input parameter"); 54 | } 55 | 56 | var buffer = new Buffer(text, "utf-8"); 57 | var hash = crypto.createHash('sha256').update(buffer).digest(); 58 | 59 | var signbuffer = ecdsa.sign(hash, privateKey); 60 | var ser1 = ecdsa.serializeSig(signbuffer); 61 | var ser2 = new Buffer(ser1); 62 | 63 | var signatureb64 = ser2.toString('base64'); 64 | 65 | return signatureb64; 66 | } 67 | 68 | module.exports = EccSign; 69 | 70 | -------------------------------------------------------------------------------- /libs/crypto/ecc/EccVerify.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | var crypto = require('crypto'); 21 | var ecdsa = require('./EccDsa'); 22 | 23 | 24 | /* 25 | * The public_key parameter must be in hex string format 26 | */ 27 | 28 | function EccVerify(public_key, input, signature) { 29 | if (!public_key) { 30 | throw new Error("Invalid EccVerify public key parameter"); 31 | } 32 | if (input == undefined) { 33 | throw new Error("Invalid EccVerify input parameter"); 34 | } 35 | if (!signature) { 36 | throw new Error("Invalid EccVerify signature parameter"); 37 | } 38 | 39 | var pkbuffer; 40 | try { 41 | pkbuffer = new Buffer(public_key, 'hex'); 42 | } 43 | catch (e) { 44 | } 45 | 46 | if (!pkbuffer) { 47 | throw new Error('Encoding public key failed'); 48 | } 49 | 50 | var text = null; 51 | try { 52 | if (typeof input != 'string') { 53 | if (typeof input == 'object') { 54 | try { 55 | text = JSON.stringify(input); 56 | } 57 | catch (e) { 58 | text = input.toString(); 59 | } 60 | } 61 | else { 62 | text = input.toString(); 63 | } 64 | } 65 | else { 66 | text = input; 67 | } 68 | } 69 | catch (err) { 70 | throw new Error("Invalid EccSign input parameter"); 71 | } 72 | 73 | if (!text) { 74 | throw new Error("Invalid EccSign input parameter"); 75 | } 76 | 77 | var buffer = new Buffer(text, "utf-8"); 78 | var hash = crypto.createHash('sha256').update(buffer).digest(); 79 | 80 | var signBuffer = null; 81 | try { 82 | signBuffer = new Buffer(signature, 'base64'); 83 | } 84 | catch (e) { 85 | signBuffer = null; 86 | } 87 | if (!signBuffer) { 88 | throw new Error("Invalid signature buffer."); 89 | } 90 | 91 | var signature = ecdsa.parseSig(signBuffer); 92 | var valid = ecdsa.verify(hash, signature, pkbuffer); 93 | 94 | return valid; 95 | } 96 | 97 | module.exports = EccVerify; 98 | 99 | -------------------------------------------------------------------------------- /libs/crypto/ecc/ecurve/curve.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | var BigInteger = require('bigi') 3 | 4 | var Point = require('./point') 5 | 6 | function Curve (p, a, b, Gx, Gy, n, h) { 7 | this.p = p 8 | this.a = a 9 | this.b = b 10 | this.G = Point.fromAffine(this, Gx, Gy) 11 | this.n = n 12 | this.h = h 13 | 14 | this.infinity = new Point(this, null, null, BigInteger.ZERO) 15 | 16 | // result caching 17 | this.pOverFour = p.add(BigInteger.ONE).shiftRight(2) 18 | } 19 | 20 | Curve.prototype.pointFromX = function (isOdd, x) { 21 | var alpha = x.pow(3).add(this.a.multiply(x)).add(this.b).mod(this.p) 22 | var beta = alpha.modPow(this.pOverFour, this.p) // XXX: not compatible with all curves 23 | 24 | var y = beta 25 | if (beta.isEven() ^ !isOdd) { 26 | y = this.p.subtract(y) // -y % p 27 | } 28 | 29 | return Point.fromAffine(this, x, y) 30 | } 31 | 32 | Curve.prototype.isInfinity = function (Q) { 33 | if (Q === this.infinity) return true 34 | 35 | return Q.z.signum() === 0 && Q.y.signum() !== 0 36 | } 37 | 38 | Curve.prototype.isOnCurve = function (Q) { 39 | if (this.isInfinity(Q)) return true 40 | 41 | var x = Q.affineX 42 | var y = Q.affineY 43 | var a = this.a 44 | var b = this.b 45 | var p = this.p 46 | 47 | // Check that xQ and yQ are integers in the interval [0, p - 1] 48 | if (x.signum() < 0 || x.compareTo(p) >= 0) return false 49 | if (y.signum() < 0 || y.compareTo(p) >= 0) return false 50 | 51 | // and check that y^2 = x^3 + ax + b (mod p) 52 | var lhs = y.square().mod(p) 53 | var rhs = x.pow(3).add(a.multiply(x)).add(b).mod(p) 54 | return lhs.equals(rhs) 55 | } 56 | 57 | /** 58 | * Validate an elliptic curve point. 59 | * 60 | * See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive 61 | */ 62 | Curve.prototype.validate = function (Q) { 63 | // Check Q != O 64 | assert(!this.isInfinity(Q), 'Point is at infinity') 65 | assert(this.isOnCurve(Q), 'Point is not on the curve') 66 | 67 | // Check nQ = O (where Q is a scalar multiple of G) 68 | var nQ = Q.multiply(this.n) 69 | assert(this.isInfinity(nQ), 'Point is not a scalar multiple of G') 70 | 71 | return true 72 | } 73 | 74 | module.exports = Curve 75 | -------------------------------------------------------------------------------- /libs/crypto/ecc/ecurve/curves.json: -------------------------------------------------------------------------------- 1 | { 2 | "secp128r1": { 3 | "p": "fffffffdffffffffffffffffffffffff", 4 | "a": "fffffffdfffffffffffffffffffffffc", 5 | "b": "e87579c11079f43dd824993c2cee5ed3", 6 | "n": "fffffffe0000000075a30d1b9038a115", 7 | "h": "01", 8 | "Gx": "161ff7528b899b2d0c28607ca52c5b86", 9 | "Gy": "cf5ac8395bafeb13c02da292dded7a83" 10 | }, 11 | "secp160k1": { 12 | "p": "fffffffffffffffffffffffffffffffeffffac73", 13 | "a": "00", 14 | "b": "07", 15 | "n": "0100000000000000000001b8fa16dfab9aca16b6b3", 16 | "h": "01", 17 | "Gx": "3b4c382ce37aa192a4019e763036f4f5dd4d7ebb", 18 | "Gy": "938cf935318fdced6bc28286531733c3f03c4fee" 19 | }, 20 | "secp160r1": { 21 | "p": "ffffffffffffffffffffffffffffffff7fffffff", 22 | "a": "ffffffffffffffffffffffffffffffff7ffffffc", 23 | "b": "1c97befc54bd7a8b65acf89f81d4d4adc565fa45", 24 | "n": "0100000000000000000001f4c8f927aed3ca752257", 25 | "h": "01", 26 | "Gx": "4a96b5688ef573284664698968c38bb913cbfc82", 27 | "Gy": "23a628553168947d59dcc912042351377ac5fb32" 28 | }, 29 | "secp192k1": { 30 | "p": "fffffffffffffffffffffffffffffffffffffffeffffee37", 31 | "a": "00", 32 | "b": "03", 33 | "n": "fffffffffffffffffffffffe26f2fc170f69466a74defd8d", 34 | "h": "01", 35 | "Gx": "db4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d", 36 | "Gy": "9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d" 37 | }, 38 | "secp192r1": { 39 | "p": "fffffffffffffffffffffffffffffffeffffffffffffffff", 40 | "a": "fffffffffffffffffffffffffffffffefffffffffffffffc", 41 | "b": "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 42 | "n": "ffffffffffffffffffffffff99def836146bc9b1b4d22831", 43 | "h": "01", 44 | "Gx": "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 45 | "Gy": "07192b95ffc8da78631011ed6b24cdd573f977a11e794811" 46 | }, 47 | "secp256k1": { 48 | "p": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 49 | "a": "00", 50 | "b": "07", 51 | "n": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 52 | "h": "01", 53 | "Gx": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 54 | "Gy": "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" 55 | }, 56 | "secp256r1": { 57 | "p": "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", 58 | "a": "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 59 | "b": "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 60 | "n": "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 61 | "h": "01", 62 | "Gx": "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 63 | "Gy": "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /libs/crypto/ecc/ecurve/index.js: -------------------------------------------------------------------------------- 1 | var Point = require('./point') 2 | var Curve = require('./curve') 3 | 4 | var getCurveByName = require('./names') 5 | 6 | module.exports = { 7 | Curve: Curve, 8 | Point: Point, 9 | getCurveByName: getCurveByName 10 | } 11 | -------------------------------------------------------------------------------- /libs/crypto/ecc/ecurve/names.js: -------------------------------------------------------------------------------- 1 | var BigInteger = require('bigi') 2 | 3 | var curves = require('./curves') 4 | var Curve = require('./curve') 5 | 6 | function getCurveByName (name) { 7 | var curve = curves[name] 8 | if (!curve) return null 9 | 10 | var p = new BigInteger(curve.p, 16) 11 | var a = new BigInteger(curve.a, 16) 12 | var b = new BigInteger(curve.b, 16) 13 | var n = new BigInteger(curve.n, 16) 14 | var h = new BigInteger(curve.h, 16) 15 | var Gx = new BigInteger(curve.Gx, 16) 16 | var Gy = new BigInteger(curve.Gy, 16) 17 | 18 | return new Curve(p, a, b, Gx, Gy, n, h) 19 | } 20 | 21 | module.exports = getCurveByName 22 | -------------------------------------------------------------------------------- /libs/crypto/ecc/readme.md: -------------------------------------------------------------------------------- 1 | # WoT ECC crypto implementation. 2 | 3 | Based on source files from https://github.com/cryptocoinjs 4 | 5 | -------------------------------------------------------------------------------- /libs/crypto/ecc/util.js: -------------------------------------------------------------------------------- 1 | var crypto = require('crypto') 2 | 3 | module.exports = { 4 | hmacSHA256: hmacSHA256 5 | } 6 | 7 | function hmacSHA256(v, k) { 8 | return crypto.createHmac('sha256', k).update(v).digest() 9 | } -------------------------------------------------------------------------------- /libs/events/thingevents.js: -------------------------------------------------------------------------------- 1 | var events = require("events"); 2 | 3 | var eventEmitter = new events.EventEmitter(); 4 | 5 | exports.onProperty = function (thing, patch, data) { 6 | var payload = { 7 | thing: thing, 8 | patch: patch, 9 | data: data 10 | }; 11 | eventEmitter.emit("thingevent", "propertychange", payload); 12 | } 13 | 14 | exports.onEventSignalled = function (thing, event, data) { 15 | var payload = { 16 | thing: thing, 17 | event: event, 18 | data: data 19 | }; 20 | eventEmitter.emit("thingevent", "eventsignall", payload); 21 | } 22 | 23 | exports.onDeviceMessage = function (data) { 24 | eventEmitter.emit("device_msg", data); 25 | } 26 | 27 | exports.onDevicePropertyChanged = function (data) { 28 | eventEmitter.emit("device_property_changed", data); 29 | } 30 | 31 | exports.onDeviceEventSignalled = function (data) { 32 | eventEmitter.emit("device_event_signalled", data); 33 | } 34 | 35 | 36 | exports.emitter = eventEmitter; -------------------------------------------------------------------------------- /libs/lists/registry.js: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | Use this object to maintain the eregisteres things list. This object is accessible from all decoupled components such as the routers 4 | and can be extended into a persistent store on a load balanced implementation that will address high availability requirements 5 | */ 6 | 7 | var registry; 8 | var _regarray; 9 | 10 | if (!registry) { 11 | _regarray = {}; 12 | registry = _regarray; 13 | } 14 | 15 | module.exports = registry; -------------------------------------------------------------------------------- /libs/thing/thing_handler.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var util = require('util'); 4 | var url = require('url'); 5 | //var logger = require('../../logger'); 6 | var Thing = require('./thing').Thing; 7 | var list_of_things = require('../lists/registry.js'); 8 | 9 | 10 | var ThingHandler = (function (config, logger) { 11 | 12 | function get_thing(name) { 13 | if (list_of_things.hasOwnProperty(name)) { 14 | return list_of_things[name]; 15 | } 16 | 17 | return undefined; 18 | } 19 | 20 | function get_thing_async(name, callback) { 21 | var thing = get_thing(name); 22 | if (thing == undefined) { 23 | return callback('The thing is not registered'); 24 | } 25 | 26 | callback(null, thing); 27 | } 28 | 29 | 30 | function register_thing(name, thing) { 31 | if (!name || !thing) { 32 | throw ('Error in register_thing(). The name and thing cannot be null'); 33 | } 34 | 35 | var isexists = get_thing(name); 36 | if (isexists) { 37 | throw ('Error in register_thing(). The thing already exists. name: ' + name); 38 | } 39 | 40 | list_of_things[name] = thing; 41 | } 42 | 43 | 44 | function get_thing_model(name, callback) { 45 | var thing = get_thing(name); 46 | if (thing == undefined) { 47 | return callback('The thing is not registered'); 48 | } 49 | 50 | var model = thing.model; 51 | if (!model) { 52 | return callback('The thing model is null'); 53 | } 54 | 55 | callback(null, model); 56 | } 57 | 58 | 59 | function init(things) { 60 | try { 61 | if (!things || !util.isArray(things)) { 62 | return logger.error("Error in parsing things configuration file. Invalid data."); 63 | } 64 | 65 | for (var i = 0; i < things.length; i++) { 66 | var thing_def = things[i]; 67 | thing_def.thing(function (err, thing) { 68 | var name, model, implementation, remote; 69 | name = thing.name; 70 | if (!name) { 71 | return logger.error("Error in register_from_config. The thing name is required"); 72 | } 73 | 74 | model = thing.model; 75 | if (!model) { 76 | return logger.error("Error in register_from_config. The thing model is required"); 77 | } 78 | 79 | // The implementation where the start and stop methods callbacks reside is defined on the local file 80 | implementation = thing_def.implementation; 81 | if (!implementation) { 82 | return logger.error("Error in register_from_config. The thing implementation is required"); 83 | } 84 | 85 | remote = thing.remote; 86 | 87 | var isexists = get_thing(name); 88 | if (isexists) { 89 | return logger.error('The thing already exists: ' + name); 90 | } 91 | 92 | var thingobj = new Thing(name, model, implementation, remote); 93 | register_thing(name, thingobj); 94 | }); 95 | } 96 | } 97 | catch (e) { 98 | logger.error("Error in initializing things from local js file. " + e.message); 99 | } 100 | } 101 | 102 | return { 103 | init: init, 104 | get_model: get_thing_model, 105 | get_thing: get_thing, 106 | get_thing_async: get_thing_async 107 | }; 108 | 109 | }(global.appconfig, global.applogger)); 110 | 111 | module.exports = ThingHandler; 112 | 113 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/discoverysrvc.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Streemo - Real time communication system for humans and machines 4 | 5 | Copyright (C) 2016 T. Z. Pardi 6 | 7 | This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as 8 | published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 11 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | */ 14 | 15 | var config = require('config'); 16 | var restify = require('restify'); 17 | 18 | var logger = global.applogger; 19 | 20 | function completeRequest(err, data, res, next) { 21 | try { 22 | if (err) { 23 | res.send(200, { error: err }); 24 | } 25 | else if (!data) { 26 | res.send(200, { error: 'no data is available' }); 27 | } 28 | else { 29 | res.send(200, { result: data }); 30 | } 31 | return next(); 32 | } 33 | catch (e) { 34 | res.send(200, { error: e.message }); 35 | return next(); 36 | } 37 | } 38 | 39 | 40 | 41 | var server = restify.createServer(); 42 | server 43 | .use(restify.fullResponse()) 44 | .use(restify.bodyParser()); 45 | 46 | 47 | server.post('/seeds', function create(req, res, next) { 48 | try { 49 | // return the known seeds of the network 50 | var error = null, data = null; 51 | 52 | var list_of_seeds = config.get('list_of_seeds'); 53 | if (!list_of_seeds.length) { 54 | error = "invalid list of seeds data"; 55 | } 56 | else { 57 | data = list_of_seeds; 58 | } 59 | 60 | completeRequest(error, data, res, next); 61 | } 62 | catch (e) { 63 | try { 64 | completeRequest(e, null, res, next); 65 | logger.error(e); 66 | } 67 | catch (e) { 68 | console.log("fatal error in 'server.post('/seeds')' error: %j", e); 69 | } 70 | } 71 | }); 72 | 73 | 74 | function start_server(callback) { 75 | // 32319 is the generic Streemo discovery port 76 | server.listen(32319, function () { 77 | logger.debug('%s listening at %s', server.name, server.url); 78 | 79 | callback(); 80 | }); 81 | } 82 | 83 | exports.start = start_server; -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/kaddht.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Source is based on https://github.com/gordonwritescode 17 | 18 | Copyright (C) 2015 The W3C WoT Team 19 | 20 | */ 21 | 22 | 'use strict'; 23 | 24 | var assert = require('assert'); 25 | var async = require('async'); 26 | var Node = require('./lib/node'); 27 | 28 | /** 29 | * Creates a new K-Node and returns it 30 | * #createNode 31 | * @param {object} options 32 | * @param {function} onConnect 33 | */ 34 | module.exports = function createNode(options) { 35 | return new Node(options); 36 | }; 37 | 38 | module.exports.Bucket = require('./lib/bucket'); 39 | module.exports.Contact = require('./lib/contact'); 40 | module.exports.Message = require('./lib/message'); 41 | module.exports.Node = require('./lib/node'); 42 | module.exports.Router = require('./lib/router'); 43 | module.exports.transports = require('./lib/transports'); 44 | module.exports.utils = require('./lib/utils'); 45 | module.exports.constants = require('./lib/constants'); 46 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/bucket.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 21 | 'use strict'; 22 | 23 | var _ = require('lodash'); 24 | var assert = require('assert'); 25 | var constants = require('./constants'); 26 | var Contact = require('./contact'); 27 | 28 | /** 29 | * Represents a contact bucket 30 | * @constructor 31 | */ 32 | function Bucket() { 33 | if (!(this instanceof Bucket)) { 34 | return new Bucket(); 35 | } 36 | 37 | this._contacts = []; 38 | } 39 | 40 | /** 41 | * Return the number of contacts in this bucket 42 | * #getSize 43 | */ 44 | Bucket.prototype.getSize = function() { 45 | return this._contacts.length; 46 | }; 47 | 48 | /** 49 | * Return the list of contacts in this bucket 50 | * #getContactList 51 | */ 52 | Bucket.prototype.getContactList = function() { 53 | return _.clone(this._contacts); 54 | }; 55 | 56 | /** 57 | * Return the contact at the given index 58 | * #getContact 59 | * @param {number} index 60 | */ 61 | Bucket.prototype.getContact = function(index) { 62 | assert(index >= 0, 'Contact index cannot be negative'); 63 | assert(index < constants.B, 'Contact index cannot be greater than `B`'); 64 | 65 | return this._contacts[index] || null; 66 | }; 67 | 68 | /** 69 | * Adds the contact to the bucket 70 | * #addContact 71 | * @param {object} contact 72 | */ 73 | Bucket.prototype.addContact = function(contact) { 74 | assert(contact instanceof Contact, 'Invalid contact supplied'); 75 | 76 | if (!this.hasContact(contact.nodeID)) { 77 | var index = _.sortedIndex(this._contacts, contact, function(contact) { 78 | return contact.lastSeen; 79 | }); 80 | 81 | this._contacts.splice(index, 0, contact); 82 | } 83 | 84 | return this; 85 | }; 86 | 87 | /** 88 | * Removes the contact from the bucket 89 | * #removeContact 90 | * @param {object} contact 91 | */ 92 | Bucket.prototype.removeContact = function(contact) { 93 | var index = this.indexOf(contact); 94 | 95 | if (index >= 0) { 96 | this._contacts.splice(index, 1); 97 | } 98 | 99 | return this; 100 | }; 101 | 102 | /** 103 | * Returns boolean indicating that the nodeID is contained in the bucket 104 | * #hasContact 105 | * @param {string} nodeID 106 | */ 107 | Bucket.prototype.hasContact = function(nodeID) { 108 | for (var i = 0; i < this.getSize(); i++) { 109 | if (this._contacts[i].nodeID === nodeID) { 110 | return true; 111 | } 112 | } 113 | 114 | return false; 115 | }; 116 | 117 | /** 118 | * Returns the index of the given contact 119 | * #indexOf 120 | * @param {object} contact 121 | */ 122 | Bucket.prototype.indexOf = function(contact) { 123 | assert(contact instanceof Contact, 'Invalid contact supplied'); 124 | 125 | for (var i = 0; i < this.getSize(); i++) { 126 | if (this.getContact(i).nodeID === contact.nodeID) { 127 | return i; 128 | } 129 | } 130 | 131 | return -1; 132 | }; 133 | 134 | module.exports = Bucket; 135 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/constants.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 'use strict'; 21 | 22 | var ms = require('ms'); 23 | 24 | /** 25 | * Protocol constants 26 | * #exports 27 | * @see http://xlattice.sourceforge.net/components/protocol/kademlia/specs.html#constants 28 | */ 29 | module.exports = { 30 | 31 | ALPHA: 3, 32 | B: 160, 33 | K: 20, 34 | 35 | // TODO make these configurable 36 | T_REFRESH: ms('3600s'), 37 | T_REPLICATE: ms('3600s'), 38 | T_REPUBLISH: ms('86400s'), 39 | T_EXPIRE: ms('3660s'), // must be bigger than the replicate so the deleted keys can be replicated 40 | 41 | T_OFFLMSGREP: 5000, 42 | 43 | // TODO make this configurable 44 | T_MSG_EXPIRE: ms('259200s'), // 72 hours of message expiry 45 | 46 | // TODO make this configurable 47 | T_ITEM_EXPIRE: ms('86460s'), // 24 hours of item expiry 48 | 49 | T_RESPONSETIMEOUT: ms('5s'), 50 | 51 | T_MAINTAIN_INTERVAL: 60000, 52 | 53 | 54 | MESSAGE_TYPES: [ 55 | 'PING', 56 | 'PONG', 57 | 'STORE', 58 | 'STORE_REPLY', 59 | 'FIND_NODE', 60 | 'FIND_NODE_REPLY', 61 | 'FIND_VALUE', 62 | 'FIND_VALUE_REPLY', 63 | 'PEERMSG' 64 | ] 65 | 66 | }; 67 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/contact.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 'use strict'; 21 | 22 | var assert = require('assert'); 23 | var utils = require('./utils'); 24 | 25 | /** 26 | * Represent a contact (or peer) 27 | * @constructor 28 | * @param {object} options 29 | */ 30 | function Contact(options) { 31 | 32 | assert(this instanceof Contact, 'Invalid instance was supplied'); 33 | assert(typeof options == "object", 'Invalid options were supplied'); 34 | 35 | Object.defineProperty( 36 | this, 37 | 'nodeID', { 38 | value: options.nodeID || this._createNodeID(), 39 | configurable: false, 40 | enumerable: true 41 | } 42 | ); 43 | 44 | assert(utils.isValidKey(this.nodeID), 'Invalid nodeID was supplied'); 45 | 46 | this.seen(); 47 | } 48 | 49 | /** 50 | * Updates the lastSeen property to right now 51 | * #seen 52 | */ 53 | Contact.prototype.seen = function() { 54 | this.lastSeen = Date.now(); 55 | }; 56 | 57 | /* istanbul ignore next */ 58 | /** 59 | * Unimplemented stub, called when no nodeID is passed to constructor. 60 | * #_createNodeID 61 | */ 62 | Contact.prototype._createNodeID = function() { 63 | throw new Error('Method not implemented'); 64 | }; 65 | 66 | module.exports = Contact; 67 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/item.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 'use strict'; 21 | 22 | var assert = require('assert'); 23 | var constants = require('./constants'); 24 | var utils = require('./utils'); 25 | var crypto = require('crypto'); 26 | 27 | /** 28 | * Represents an item to store 29 | * @constructor 30 | * @param {string} key 31 | * @param {object} value 32 | * @param {string} publisher - nodeID 33 | * @param {number} timestamp - optional 34 | */ 35 | function Item(key, value, publisher, timestamp, recipient) { 36 | if (!(this instanceof Item)) { 37 | return new Item(key, value, publisher, timestamp, recipient); 38 | } 39 | 40 | assert.ok(typeof key === 'string', 'Invalid key supplied'); 41 | assert.ok(value, 'Invalid value supplied'); 42 | assert(utils.isValidKey(publisher), 'Invalid publisher nodeID supplied'); 43 | 44 | if (timestamp) { 45 | assert(typeof timestamp === 'number', 'Invalid timestamp supplied'); 46 | assert(Date.now() >= timestamp, 'Timestamp cannot be in the future'); 47 | } 48 | 49 | var obj = [key, value]; 50 | var str = JSON.stringify(obj); 51 | var buffer = new Buffer(str); 52 | var hashval = crypto.createHash('sha1').update(buffer).digest(); 53 | this.hash = hashval.toString('hex'); 54 | 55 | this.key = key; 56 | this.value = value; 57 | this.publisher = publisher; 58 | this.timestamp = timestamp || Date.now(); 59 | this.recipient = recipient || ""; 60 | } 61 | 62 | module.exports = Item; 63 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/message.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 'use strict'; 21 | 22 | var assert = require('assert'); 23 | var constants = require('./constants'); 24 | var merge = require('merge'); 25 | var Contact = require('./contact'); 26 | 27 | /** 28 | * Represents a message to be sent over RPC 29 | * @constructor 30 | * @param {string} type 31 | * @param {object} params 32 | * @param {object} fromContact 33 | */ 34 | function Message(type, params, fromContact) { 35 | if (!(this instanceof Message)) { 36 | return new Message(type, params, fromContact); 37 | } 38 | 39 | assert(constants.MESSAGE_TYPES.indexOf(type) !== -1, 'Invalid message type'); 40 | assert(fromContact instanceof Contact, 'Invalid contact supplied'); 41 | 42 | this.type = type; 43 | this.params = merge(params, fromContact); 44 | } 45 | 46 | /** 47 | * Serialize message to a Buffer 48 | * #serialize 49 | */ 50 | Message.prototype.serialize = function() { 51 | return new Buffer(JSON.stringify(this), 'utf8'); 52 | }; 53 | 54 | module.exports = Message; 55 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/storages/localstorage.js: -------------------------------------------------------------------------------- 1 |  2 | 'use strict' 3 | 4 | var Map = require("collections/map"); 5 | 6 | module.exports = KadLocalStorage 7 | 8 | var EventEmitter = require('events').EventEmitter 9 | var map = new Map(); 10 | 11 | function KadLocalStorage(namespace) { 12 | if (namespace.indexOf('_') >= 0) throw new Error('Invalid namespace, character "_" in the namespace and account name is not allowed') 13 | this._prefix = namespace + '_' 14 | } 15 | 16 | KadLocalStorage.prototype.get = function (key, cb) { 17 | var val = map.get(this._prefix + key); 18 | if (!val) return cb(new Error('not found')); 19 | try { 20 | val = JSON.parse(val) 21 | } catch (err) { 22 | return cb(err) 23 | } 24 | cb(null, val) 25 | } 26 | 27 | KadLocalStorage.prototype.put = function (key, val, cb) { 28 | key = this._prefix + key; 29 | map.set(key, JSON.stringify(val)); 30 | var inserted_val = map.get(key); 31 | cb(null, inserted_val) 32 | } 33 | 34 | KadLocalStorage.prototype.del = function (key, cb) { 35 | key = this._prefix + key; 36 | map.delete(key); 37 | cb(null) 38 | } 39 | 40 | KadLocalStorage.prototype.createReadStream = function () { 41 | var storage = this 42 | var stream = new EventEmitter() 43 | setTimeout(function () { 44 | var len = localStorage.length 45 | for (var i = 0; i < len; i++) { 46 | var unprefixedKey = localStorage.key(i) 47 | var isOwnKey = unprefixedKey.indexOf(storage._prefix) === 0 48 | if (!isOwnKey) continue 49 | var key = unprefixedKey.substring(storage._prefix.length) 50 | storage.get(key, onGet.bind(null, key)) 51 | } 52 | stream.emit('end') 53 | }) 54 | return stream 55 | 56 | function onGet(key, err, val) { 57 | if (err) return stream.emit('error', err) 58 | stream.emit('data', { key: key, value: val }) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/transports/address-port-contact.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 'use strict'; 21 | 22 | var assert = require('assert'); 23 | var Contact = require('../contact'); 24 | var inherits = require('util').inherits; 25 | var utils = require('../utils'); 26 | 27 | inherits(AddressPortContact, Contact); 28 | 29 | /** 30 | * Represent a contact (or peer) 31 | * @constructor 32 | * @param {object} options 33 | */ 34 | function AddressPortContact(options) { 35 | 36 | if (!(this instanceof AddressPortContact)) { 37 | return new AddressPortContact(options); 38 | } 39 | 40 | assert(typeof options == "object", 'Invalid options were supplied'); 41 | assert(typeof options.address === 'string', 'Invalid address was supplied'); 42 | assert(typeof options.port === 'number', 'Invalid port was supplied'); 43 | assert(typeof options.account === 'string', 'Invalid account was supplied'); 44 | 45 | this.address = options.address; 46 | this.port = options.port; 47 | this.account = options.account; 48 | 49 | Contact.call(this, options) 50 | } 51 | 52 | 53 | /** 54 | * Generate a NodeID by taking the SHA1 hash of the address and port 55 | * #_createNodeID 56 | */ 57 | AddressPortContact.prototype._createNodeID = function() { 58 | return utils.createID(this.account); //this.toString()); 59 | }; 60 | 61 | /** 62 | * Generate a user-friendly string for the contact 63 | * #_toString 64 | */ 65 | AddressPortContact.prototype.toString = function() { 66 | return this.address + ':' + this.port; 67 | }; 68 | 69 | module.exports = AddressPortContact; 70 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/transports/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 'use strict'; 21 | 22 | module.exports = { 23 | UDP: require('./udp'), 24 | TCP: require('./tcp') 25 | }; 26 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/lib/transports/udp.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of W3C Web-of-Things-Framework. 4 | 5 | W3C Web-of-Things-Framework is an open source project to create an Internet of Things framework. 6 | This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | 9 | W3C Web-of-Things-Framework is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License along with W3C Web-of-Things-Framework. If not, see . 13 | 14 | File created by Tibor Zsolt Pardi 15 | 16 | Copyright (C) 2015 The W3C WoT Team 17 | 18 | */ 19 | 20 | 'use strict'; 21 | 22 | var AddressPortContact = require('./address-port-contact'); 23 | var inherits = require('util').inherits; 24 | var dgram = require('dgram'); 25 | var RPC = require('../rpc'); 26 | 27 | inherits(UDPTransport, RPC); 28 | 29 | /** 30 | * Represents an UDP transport for RPC 31 | * @constructor 32 | * @param {object} options 33 | */ 34 | function UDPTransport(options) { 35 | if (!(this instanceof UDPTransport)) { 36 | return new UDPTransport(options); 37 | } 38 | 39 | var self = this; 40 | var socketOptions = { type: 'udp4', reuseAddr: true }; 41 | var socketMessageHandler = this._handleMessage.bind(this); 42 | 43 | RPC.call(this, options); 44 | 45 | this._socket = dgram.createSocket(socketOptions, socketMessageHandler); 46 | 47 | this._socket.on('error', function(err) { 48 | var contact = self._contact; 49 | self._log.error('failed to bind to supplied address %s', contact.address); 50 | self._log.info('binding to all interfaces as a fallback'); 51 | self._socket.close(); 52 | 53 | self._socket = dgram.createSocket(socketOptions, socketMessageHandler); 54 | 55 | self._socket.bind(contact.port); 56 | }); 57 | 58 | this._socket.on('listening', function() { 59 | self.emit('ready'); 60 | }); 61 | 62 | this._socket.bind(this._contact.port, this._contact.address ); 63 | } 64 | 65 | /** 66 | * Create a UDP Contact 67 | * #_createContact 68 | * @param {object} options 69 | */ 70 | UDPTransport.prototype._createContact = function(options) { 71 | return new AddressPortContact(options); 72 | } 73 | 74 | /** 75 | * Send a RPC to the given contact 76 | * #_send 77 | * @param {buffer} data 78 | * @param {Contact} contact 79 | */ 80 | UDPTransport.prototype._send = function(data, contact) { 81 | this._socket.send(data, 0, data.length, contact.port, contact.address); 82 | }; 83 | 84 | /** 85 | * Close the underlying socket 86 | * #_close 87 | */ 88 | UDPTransport.prototype._close = function() { 89 | this._socket.close(); 90 | }; 91 | 92 | module.exports = UDPTransport; 93 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/peer_comm.js: -------------------------------------------------------------------------------- 1 | var dgram = require('dgram'); 2 | 3 | 4 | function send_msg(data, port, address) { 5 | var socketOptions = { type: 'udp4', reuseAddr: true }; 6 | var socketMessageHandler = function (buffer, info) { 7 | var b = buffer; 8 | }; 9 | 10 | var socket = dgram.createSocket(socketOptions, socketMessageHandler); 11 | socket.send(data, 0, data.length, port, address); 12 | } 13 | 14 | 15 | module.exports = { 16 | sendmsg: send_msg 17 | } 18 | 19 | -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/pm2start.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Streemo - Real time communication system for humans and machines 4 | 5 | Copyright (C) 2016 T. Z. Pardi 6 | 7 | This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as 8 | published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 11 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | 13 | */ 14 | 15 | 16 | var async = require("async"); 17 | var pm2 = require('pm2'); 18 | 19 | pm2.connect(function (err) { 20 | if (err) { 21 | console.error(err); 22 | process.exit(2); 23 | } 24 | 25 | async.waterfall( 26 | [ 27 | function (callback) { 28 | pm2.start({ 29 | name : "streemo seed #1", 30 | script : 'seed.js', 31 | cwd : "/home/zsoltp/apps/streemoseed", 32 | env: { 33 | "NODE_CONFIG_DIR": "/home/zsoltp/apps/streemoseed/config" 34 | } 35 | }, 36 | function (err, apps) { 37 | callback(err); 38 | }); 39 | }, 40 | function (callback) { 41 | setTimeout( 42 | function () { 43 | pm2.start({ 44 | name : "streemo seed #2", 45 | script : 'seed.js', 46 | cwd : "/home/zsoltp/apps/seed2", 47 | env: { 48 | "NODE_CONFIG_DIR": "/home/zsoltp/apps/seed2/config" 49 | } 50 | }, 51 | function (err, apps) { 52 | callback(err); 53 | }); 54 | }, 55 | 5000 56 | ); 57 | }, 58 | function (callback) { 59 | setTimeout( 60 | function () { 61 | pm2.start({ 62 | name : "streemo seed #3", 63 | script : 'seed.js', 64 | cwd : "/home/zsoltp/apps/seed3", 65 | env: { 66 | "NODE_CONFIG_DIR": "/home/zsoltp/apps/seed3/config" 67 | } 68 | }, 69 | function (err, apps) { 70 | callback(err); 71 | }); 72 | }, 73 | 5000 74 | ); 75 | } 76 | ], 77 | function (err) { 78 | if (err) { 79 | return console.log("pm2.start error: %j", err); 80 | } 81 | 82 | console.log("pm2.start complete"); 83 | process.exit(0); 84 | } 85 | ); 86 | 87 | }); -------------------------------------------------------------------------------- /libs/transport/p2p/wotkad/readme.md: -------------------------------------------------------------------------------- 1 | ## WoT P2P Kademlia DHT (distributed hash table) library 2 | 3 | Based on https://github.com/gordonwritescode/kad. 4 | 5 | Credit to Gordon Hall at https://github.com/gordonwritescode to publish the orginal kad solution. 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /logger.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | var winston = require('winston'); 4 | 5 | var config = global.appconfig; 6 | 7 | var logDir = path.join(__dirname, '/logs'); 8 | 9 | fs.open(logDir, 'r', function (err, fd) { 10 | if (err && err.code == 'ENOENT') { 11 | /* the directory doesn't exist */ 12 | console.log("Creating logs directory ..."); 13 | fs.mkdir(logDir, function (err) { 14 | if (err) { 15 | // failed to create the log directory, most likely due to insufficient permission 16 | console.log("Error in creating logs directory: " + err.message ? err.message : err); 17 | } 18 | else { 19 | console.log("Logs directory created"); 20 | } 21 | }); 22 | } 23 | }); 24 | 25 | var logfilePath = path.join(__dirname, '/logs/application.log'); 26 | var exceptionFileLog = path.join(__dirname, '/logs/exception.log'); 27 | 28 | var level = config && config.log && config.log.level ? config.log.level : "error"; 29 | 30 | var logger = new (winston.Logger)({ 31 | exitOnError: false, 32 | transports: [ 33 | new winston.transports.Console({ 34 | level: 'debug', 35 | json: false, 36 | colorize: true 37 | }), 38 | new (winston.transports.File)({ 39 | filename: logfilePath, 40 | level: level, 41 | json: true, 42 | maxsize: 5242880, //5MB 43 | maxFiles: 5, 44 | colorize: false 45 | }) 46 | ], 47 | exceptionHandlers: [ 48 | new winston.transports.File({ 49 | filename: exceptionFileLog, 50 | json: true 51 | }), 52 | new winston.transports.Console({ 53 | level: 'debug', 54 | json: false, 55 | colorize: true 56 | }) 57 | ] 58 | }); 59 | 60 | function log_log(level, msg, val1, val2, val3, val4) { 61 | try { 62 | if (msg) { 63 | // most of js exceptions have a "message" field 64 | // try to use that to get a friendly error message 65 | if (msg.message) { 66 | logger.log(level, msg.message); 67 | } 68 | else { 69 | if (val1 && val2 && val3 && val4) { 70 | logger.log(level, msg, val1, val2, val3, val4); 71 | } 72 | else if (val1 && val2 && val3) { 73 | logger.log(level, msg, val1, val2, val3); 74 | } 75 | else if (val1 && val2) { 76 | logger.log(level, msg, val1, val2); 77 | } 78 | else if (val1) { 79 | logger.log(level, msg, val1); 80 | } 81 | else { 82 | logger.log(level, msg); 83 | } 84 | } 85 | } 86 | } 87 | catch (e) { 88 | if (msg) { 89 | // still log to the console 90 | console.log(msg.message ? msg.message : msg); 91 | } 92 | } 93 | } 94 | 95 | function log_error(msg, val1, val2, val3, val4) { 96 | log_log('error', msg, val1, val2, val3, val4); 97 | } 98 | 99 | function log_info(msg, val1, val2, val3, val4) { 100 | log_log('info', msg, val1, val2, val3, val4); 101 | } 102 | 103 | function log_debug(msg, val1, val2, val3, val4) { 104 | log_log('debug', msg, val1, val2, val3, val4); 105 | } 106 | 107 | // write stream object 108 | var log_stream = { 109 | write: function(message, encoding){ 110 | log_info(message); 111 | } 112 | }; 113 | 114 | exports.error = log_error; 115 | exports.info = log_info; 116 | exports.debug = log_debug; 117 | exports.stream = log_stream; 118 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webofthings", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "start": "node demo.js", 6 | "test": "./node_modules/.bin/mocha" 7 | }, 8 | "dependencies": { 9 | "async": "^1.5.0", 10 | "bigi": "^1.4.1", 11 | "body-parser": "^1.15.0", 12 | "clarinet": "^0.11.0", 13 | "coap": "^0.12.0", 14 | "collections": "^1.2.4", 15 | "cookie-parser": "^1.3.5", 16 | "crypto-hashing": "^0.3.1", 17 | "express": "^4.13.4", 18 | "express-handlebars": "^2.0.1", 19 | "hat": "0.0.3", 20 | "leveldown": "^1.4.2", 21 | "levelup": "^1.2.1", 22 | "lodash": "^3.10.1", 23 | "merge": "^1.2.0", 24 | "morgan": "^1.6.1", 25 | "mqtt": "^1.5.0", 26 | "ms": "^0.7.1", 27 | "restify": "^4.0.0", 28 | "secure-random": "^1.1.1", 29 | "serve-favicon": "^2.3.0", 30 | "underscore": "^1.8.3", 31 | "underscore.string": "^3.2.2", 32 | "uuid": "^2.0.1", 33 | "winston": "^1.0.1", 34 | "ws": "latest" 35 | }, 36 | "devDependencies": { 37 | "mocha": "latest", 38 | "should": "latest" 39 | }, 40 | "engine": "node >= 0.1.0" 41 | } 42 | -------------------------------------------------------------------------------- /streams.md: -------------------------------------------------------------------------------- 1 | # Object Models for Data Streams 2 | 3 | *Note: this has yet to be implemented in the server code* 4 | 5 | Some sensors produces streams of data as a function of time. Data streams can carry one or more data channels where each channel is a single number or a vector. 6 | 7 | An example would be an electrocardiography (ECG) sensor which is used to produce a waveform of the heart's activity over a time period of a few seconds. In a hospital the sensor and display are connected together with electrical leads. 8 | 9 | In the Web of Things, the sensor and the display are both modelled as "things". In place of leads, we set the sensor's output property to the display. The display could be an object in a web page script that displays the waveform using the HTML CANVAS element, or it could be a remote service, e.g. a device that acts as an oscilloscope. The display could have properties that control its behaviour, e.g. how many seconds of data to show. It could also have actions, e.g. to freeze the display to allow a waveform to be studied in more detail. 10 | 11 | Script developers ony need to know the object model for the sensor and display. The details of the underlying protocols are dealt with automatically by the server platform. For this to work, we need a standard way to describe data streams as part of the data model for "things". 12 | 13 | For a simple thing property, e.g. the state of a light switch, setting the value of the property on the proxy results in the server sending a message to update the physical state of the switch. For streams, the semantics is slightly different. Setting the value of the proxy's' output directs the data stream to the designated object. 14 | 15 | This model assumes that a stream can only be sent to a single data sink. If you want to have multiple sinks, you will need to use a "thing" that acts as splitter. In principle, the thing acting as the sensor could do this, e.g. providing one output for a data logger, and another for a display. -------------------------------------------------------------------------------- /test/closure-loop-repro.js: -------------------------------------------------------------------------------- 1 | var wot = require('../framework.js'); // launch the servers 2 | var assert = require("assert"); 3 | 4 | describe('Thing with multiple properties should initialize correctly', function() { 5 | describe('setting values', function() { 6 | it('should have properly set values', function() { 7 | // define the thing with multiple properties 8 | wot.thing("twoprops", { 9 | "@properties": { 10 | "property1": "string", 11 | "property2": "string" 12 | } 13 | }, { 14 | start: function(thing) { 15 | console.log("setting property 1"); 16 | thing.property1 = "property 1"; 17 | 18 | console.log("setting property 2"); 19 | thing.property2 = "property 2"; 20 | }, 21 | stop: function(thing) {}, 22 | }); 23 | 24 | 25 | 26 | }) 27 | }) 28 | }); -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require should 2 | --reporter spec 3 | --ui bdd 4 | --recursive 5 | -------------------------------------------------------------------------------- /transports/coap/readme.md: -------------------------------------------------------------------------------- 1 | # CoAP server implementation -------------------------------------------------------------------------------- /transports/http/readme.md: -------------------------------------------------------------------------------- 1 | # HTTP server implementation to provide HTTP end port for inter server communication -------------------------------------------------------------------------------- /transports/mqtt/handler.js: -------------------------------------------------------------------------------- 1 | var logger = require('../../logger'); 2 | 3 | exports.start = function start(settings) { 4 | logger.info('The MQTT server initialisation is not yet implemented'); 5 | } -------------------------------------------------------------------------------- /transports/mqtt/readme.md: -------------------------------------------------------------------------------- 1 | # MQTT server implementation -------------------------------------------------------------------------------- /transports/p2p/readme.md: -------------------------------------------------------------------------------- 1 | # P2P implementation -------------------------------------------------------------------------------- /transports/restapi/handler.js: -------------------------------------------------------------------------------- 1 | var logger = require('../../logger'); 2 | 3 | exports.start = function start(settings) { 4 | logger.info('The REST API server initialisation is not yet implemented'); 5 | } -------------------------------------------------------------------------------- /transports/restapi/readme.md: -------------------------------------------------------------------------------- 1 | # REST API server implementation to provide HTTP end port for WoT inter server communication -------------------------------------------------------------------------------- /transports/server_handler.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | var logger = require('../logger'); 3 | 4 | var config = global.appconfig; 5 | 6 | function initialize_server(server, settings) { 7 | try { 8 | logger.debug(server + " server configuration exists. Start " + server + " server"); 9 | var path = './' + server + '/handler.js'; 10 | var server_handler = require(path); 11 | server_handler.start(settings); 12 | } 13 | catch (e) { 14 | logger.error("Error in starting " + server + " server. " + e.message); 15 | } 16 | } 17 | 18 | function initialize_servers() { 19 | try { 20 | var server_config = config.servers; 21 | if (!server_config) { 22 | throw new Error("Error in populating servers config settings. The servers config settings does not exists"); 23 | } 24 | 25 | // Call the servers start method 26 | // The servers must implement the start method 27 | for (server in server_config) { 28 | var settings = server_config[server]; 29 | initialize_server(server, settings); 30 | } 31 | } 32 | catch (e) { 33 | logger.error("Error in initialize_servers(), " + e.message); 34 | } 35 | } 36 | 37 | module.exports = { 38 | init: initialize_servers 39 | }; 40 | -------------------------------------------------------------------------------- /transports/web/handler.js: -------------------------------------------------------------------------------- 1 | var logger = require('../../logger'); 2 | var httpd = require('./httpd.js'); 3 | 4 | exports.start = function start(settings) { 5 | // the web server is tarted by including the module declaration above 6 | logger.info('Initialising web server'); 7 | } -------------------------------------------------------------------------------- /transports/web/httpd.js: -------------------------------------------------------------------------------- 1 | var applog = require('../../logger'); // the logger name is used by express internally so call here the log obj "applog" 2 | var path = require('path'); 3 | var express = require('express'); 4 | var bodyParser = require('body-parser'); 5 | var cookieParser = require('cookie-parser'); 6 | var exphbs = require('express-handlebars'); 7 | var main_routes = require('./routes/main'); 8 | var api_routes = require('./routes/api'); 9 | var favicon = require('serve-favicon'); 10 | 11 | var config = global.appconfig; 12 | 13 | applog.info("WoT Express server start"); 14 | 15 | // init the express app 16 | var app = express(); 17 | 18 | // view engine setup 19 | app.set('views', path.join(__dirname, 'views')); 20 | 21 | app.engine('handlebars', exphbs({ 22 | // the server runs in a sub directory instead of in the root (which is the default implementation) 23 | // and the layouts directory must be specified here 24 | layoutsDir: path.join(__dirname, 'views/layouts'), 25 | defaultLayout: 'main', 26 | helpers: { 27 | section: function (name, options) { 28 | if (!this._sections) this._sections = {}; 29 | this._sections[name] = options.fn(this); 30 | return null; 31 | } 32 | } 33 | })); 34 | 35 | app.set('view engine', 'handlebars'); 36 | 37 | // uncomment after placing your favicon in /public 38 | app.use(favicon(__dirname + '/public/favicon.ico')); 39 | app.use(bodyParser.json()); 40 | app.use(bodyParser.urlencoded({ extended: false })); 41 | app.use(cookieParser()); 42 | app.use(express.static(path.join(__dirname, 'public'))); 43 | 44 | app.use('/', main_routes); 45 | app.use('/api', api_routes); 46 | 47 | // catch 404 and forward to error handler 48 | app.use(function (req, res, next) { 49 | var err = new Error('Not Found'); 50 | err.status = 404; 51 | next(err); 52 | }); 53 | 54 | // error handlers 55 | 56 | // development error handler 57 | // will print stacktrace 58 | if (app.get('env') === 'development') { 59 | app.use(function (err, req, res, next) { 60 | res.status(err.status || 500); 61 | res.render('error', { 62 | message: err.message, 63 | error: err 64 | }); 65 | }); 66 | } 67 | 68 | // production error handler 69 | // no stacktraces leaked to user 70 | app.use(function (err, req, res, next) { 71 | res.status(err.status || 500); 72 | res.render('error', { 73 | message: err.message, 74 | error: {} 75 | }); 76 | }); 77 | 78 | module.exports = app; 79 | 80 | var port = config.servers.web.port; 81 | app.set('port', port); 82 | 83 | var server = app.listen(app.get('port'), function () { 84 | applog.info('WoT Express server listening on port ' + server.address().port); 85 | }); 86 | 87 | 88 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/HELP-US-OUT.txt: -------------------------------------------------------------------------------- 1 | I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, 2 | Fonticons (https://fonticons.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, 3 | comprehensive icon sets or copy and paste your own. 4 | 5 | Please. Check it out. 6 | 7 | -Dave Gandy 8 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/css/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/css/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/css/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/css/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/css/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | .fa-icon-rotate(@degrees, @rotation) { 15 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); 16 | -webkit-transform: rotate(@degrees); 17 | -ms-transform: rotate(@degrees); 18 | transform: rotate(@degrees); 19 | } 20 | 21 | .fa-icon-flip(@horiz, @vert, @rotation) { 22 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); 23 | -webkit-transform: scale(@horiz, @vert); 24 | -ms-transform: scale(@horiz, @vert); 25 | transform: scale(@horiz, @vert); 26 | } 27 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 16 | -webkit-transform: rotate($degrees); 17 | -ms-transform: rotate($degrees); 18 | transform: rotate($degrees); 19 | } 20 | 21 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 22 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}); 23 | -webkit-transform: scale($horiz, $vert); 24 | -ms-transform: scale($horiz, $vert); 25 | transform: scale($horiz, $vert); 26 | } 27 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /transports/web/public/css/font-awesome/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | -------------------------------------------------------------------------------- /transports/web/public/css/jquery.gritter.css: -------------------------------------------------------------------------------- 1 | /* the norm */ 2 | #gritter-notice-wrapper { 3 | position:fixed; 4 | top:20px; 5 | right:20px; 6 | width:301px; 7 | z-index:9999; 8 | } 9 | #gritter-notice-wrapper.top-left { 10 | left: 20px; 11 | right: auto; 12 | } 13 | #gritter-notice-wrapper.bottom-right { 14 | top: auto; 15 | left: auto; 16 | bottom: 20px; 17 | right: 20px; 18 | } 19 | #gritter-notice-wrapper.bottom-left { 20 | top: auto; 21 | right: auto; 22 | bottom: 20px; 23 | left: 20px; 24 | } 25 | .gritter-item-wrapper { 26 | position:relative; 27 | margin:0 0 10px 0; 28 | background:url('../images/ie-spacer.gif'); /* ie7/8 fix */ 29 | } 30 | .gritter-top { 31 | background:url(../images/gritter.png) no-repeat left -30px; 32 | height:10px; 33 | } 34 | .hover .gritter-top { 35 | background-position:right -30px; 36 | } 37 | .gritter-bottom { 38 | background:url(../images/gritter.png) no-repeat left bottom; 39 | height:8px; 40 | margin:0; 41 | } 42 | .hover .gritter-bottom { 43 | background-position: bottom right; 44 | } 45 | .gritter-item { 46 | display:block; 47 | background:url(../images/gritter.png) no-repeat left -40px; 48 | color:#eee; 49 | padding:2px 11px 8px 11px; 50 | font-size: 11px; 51 | font-family:verdana; 52 | } 53 | .hover .gritter-item { 54 | background-position:right -40px; 55 | } 56 | .gritter-item p { 57 | padding:0; 58 | margin:0; 59 | word-wrap:break-word; 60 | } 61 | .gritter-close { 62 | display:none; 63 | position:absolute; 64 | top:5px; 65 | left:3px; 66 | background:url(../images/gritter.png) no-repeat left top; 67 | cursor:pointer; 68 | width:30px; 69 | height:30px; 70 | text-indent:-9999em; 71 | } 72 | .gritter-title { 73 | font-size:14px; 74 | font-weight:bold; 75 | padding:0 0 7px 0; 76 | display:block; 77 | text-shadow:1px 1px 0 #000; /* Not supported by IE :( */ 78 | } 79 | .gritter-image { 80 | width:48px; 81 | height:48px; 82 | float:left; 83 | } 84 | .gritter-with-image, 85 | .gritter-without-image { 86 | padding:0; 87 | } 88 | .gritter-with-image { 89 | width:220px; 90 | float:right; 91 | } 92 | /* for the light (white) version of the gritter notice */ 93 | .gritter-light .gritter-item, 94 | .gritter-light .gritter-bottom, 95 | .gritter-light .gritter-top, 96 | .gritter-light .gritter-close { 97 | background-image: url(../images/gritter-light.png); 98 | color: #222; 99 | } 100 | .gritter-light .gritter-title { 101 | text-shadow: none; 102 | } 103 | -------------------------------------------------------------------------------- /transports/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/favicon.ico -------------------------------------------------------------------------------- /transports/web/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /transports/web/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /transports/web/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /transports/web/public/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /transports/web/public/images/gritter-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/images/gritter-light.png -------------------------------------------------------------------------------- /transports/web/public/images/gritter-long.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/images/gritter-long.png -------------------------------------------------------------------------------- /transports/web/public/images/gritter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/images/gritter.png -------------------------------------------------------------------------------- /transports/web/public/images/ie-spacer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/images/ie-spacer.gif -------------------------------------------------------------------------------- /transports/web/public/images/trees.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w3c/web-of-things-framework/f82fd056e8c9a928960dbe8906a9034a2ae96f19/transports/web/public/images/trees.jpg -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout-postbox/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "knockout-postbox", 3 | "version": "0.5.2", 4 | "main": "build/knockout-postbox.min.js", 5 | "dependencies": { 6 | "knockout": ">= 2.0" 7 | }, 8 | "publishConfig": { 9 | "registry": "https://registry.npmjs.org" 10 | }, 11 | "ignore": [ 12 | "examples", 13 | "ext", 14 | "reports", 15 | "spec", 16 | "src", 17 | "Gruntfile.js", 18 | "package.json", 19 | ".gitignore" 20 | ], 21 | "homepage": "https://github.com/rniemeyer/knockout-postbox", 22 | "_release": "0.5.2", 23 | "_resolution": { 24 | "type": "version", 25 | "tag": "v0.5.2", 26 | "commit": "c64c3d3753fe009835b35d01bb5b3534405dd34a" 27 | }, 28 | "_source": "git://github.com/rniemeyer/knockout-postbox.git", 29 | "_target": "~0.5.2", 30 | "_originalSource": "knockout-postbox", 31 | "_direct": true 32 | } -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout-postbox/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ryan Niemeyer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout-postbox/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "knockout-postbox", 3 | "version": "0.5.2", 4 | "main": "build/knockout-postbox.min.js", 5 | "dependencies": { 6 | "knockout": ">= 2.0" 7 | }, 8 | "publishConfig": { 9 | "registry": "https://registry.npmjs.org" 10 | }, 11 | "ignore": [ 12 | "examples", 13 | "ext", 14 | "reports", 15 | "spec", 16 | "src", 17 | "Gruntfile.js", 18 | "package.json", 19 | ".gitignore" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout-postbox/build/knockout-postbox.min.js: -------------------------------------------------------------------------------- 1 | // knockout-postbox 0.5.2 | (c) 2015 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license 2 | !function(a){"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?a(require("knockout"),exports):"function"==typeof define&&define.amd?define(["knockout","exports"],a):a(ko,ko.postbox={})}(function(a,b,c){var d,e,f={},g=1;b.subscriptions=f,a.subscribable.call(b),b.topicCache={},b.serializer=a.toJSON,b.publish=function(a,c){a&&(b.topicCache[a]={value:c,serialized:b.serializer(c)},b.notifySubscribers(c,a))},e=b.subscribe,b.subscribe=function(a,d,h,i){var j,k,l;return a?("boolean"==typeof h&&(i=h,h=c),j=e.call(b,d,h,a),j.subId=++g,f[g]=j,i&&(k=b.topicCache[a],k!==c&&d.call(h,k.value)),l=j.dispose,j.dispose=function(){delete f[j.subId],l.call(j)},j):void 0},b.reset=function(){var a;for(var c in f)f.hasOwnProperty(c)&&(a=f[c],a&&"function"==typeof a.dispose&&a.dispose());b.topicCache={}},b.defaultComparer=function(a,c){return c&&b.serializer(a)===c.serialized},a.subscribable.fn.publishOn=function(a,c,e){var h,i,j;return a&&("function"==typeof c?e=c:h=c,e=e||b.defaultComparer,d.call(this,a,"publishOn"),i=this.subscribe(function(c){e.call(this,c,b.topicCache[a])||b.publish(a,c)},this),i.id=++g,f[g]=i,j=i.dispose,i.dispose=function(){delete this.postboxSubs[a].publishOn,delete f[i.id],j.call(i)}.bind(this),this.postboxSubs[a].publishOn=i,h||b.publish(a,this())),this},d=function(a,b){var c=this.postboxSubs=this.postboxSubs||{};c[a]=c[a]||{},c[a][b]&&c[a][b].dispose()},a.subscribable.fn.stopPublishingOn=function(a){return d.call(this,a,"publishOn"),this},a.subscribable.fn.subscribeTo=function(e,f,g){var h,i,j,k,l,m=this;return"function"==typeof f?g=f:h=f,e&&a.isWriteableObservable(this)&&(d.call(this,e,"subscribeTo"),j=function(a){m(g?g.call(m,a):a)},k=b.subscribe(e,j),this.postboxSubs[e].subscribeTo=k,l=k.dispose,k.dispose=function(){delete this.postboxSubs[e].subscribeTo,l.call(k)}.bind(this),h&&(i=b.topicCache[e],i!==c&&j(i.value))),this},a.subscribable.fn.unsubscribeFrom=function(a){return d.call(this,a,"subscribeTo"),this},a.subscribable.fn.syncWith=function(a,b,c,d){return this.subscribeTo(a,b).publishOn(a,c,d),this},a.postbox=b}); -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/.bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "knockout", 3 | "version": "3.3.0", 4 | "homepage": "http://knockoutjs.com/", 5 | "description": "Knockout makes it easier to create rich, responsive UIs with JavaScript", 6 | "main": "dist/knockout.js", 7 | "moduleType": [ 8 | "amd", 9 | "globals", 10 | "node" 11 | ], 12 | "keywords": [ 13 | "knockout", 14 | "mvvm", 15 | "mvc", 16 | "spa" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "spec", 24 | "build/output" 25 | ], 26 | "_release": "3.3.0", 27 | "_resolution": { 28 | "type": "version", 29 | "tag": "v3.3.0", 30 | "commit": "26df265f41b51359e4746d78be51ab05ae2a75c6" 31 | }, 32 | "_source": "git://github.com/SteveSanderson/knockout.git", 33 | "_target": "~3.3.0", 34 | "_originalSource": "knockout", 35 | "_direct": true 36 | } -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) - http://www.opensource.org/licenses/mit-license.php 2 | 3 | Copyright (c) Steven Sanderson, the Knockout.js team, and other contributors 4 | http://knockoutjs.com/ 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/README.md: -------------------------------------------------------------------------------- 1 | **Knockout** is a JavaScript [MVVM](http://en.wikipedia.org/wiki/Model_View_ViewModel) (a modern variant of MVC) library that makes it easier to create rich, desktop-like user interfaces with JavaScript and HTML. It uses *observers* to make your UI automatically stay in sync with an underlying data model, along with a powerful and extensible set of *declarative bindings* to enable productive development. 2 | 3 | ##Getting started 4 | 5 | **Totally new to Knockout?** The most fun place to start is the [online interactive tutorials](http://learn.knockoutjs.com/). 6 | 7 | For more details, see 8 | 9 | * Documentation on [the project's website](http://knockoutjs.com/documentation/introduction.html) 10 | * Online examples at [http://knockoutjs.com/examples/](http://knockoutjs.com/examples/) 11 | 12 | ##Downloading Knockout 13 | 14 | You can [download released versions of Knockout](http://knockoutjs.com/downloads/) from the project's website. 15 | 16 | For Node.js developers, Knockout is also available from [npm](https://npmjs.org/) - just run `npm install knockout`. 17 | 18 | ##Building Knockout from sources 19 | 20 | If you prefer to build the library yourself: 21 | 22 | 1. **Clone the repo from GitHub** 23 | 24 | git clone https://github.com/knockout/knockout.git 25 | cd knockout 26 | 27 | 2. **Acquire build dependencies.** Make sure you have [Node.js](http://nodejs.org/) installed on your workstation. This is only needed to _build_ Knockout from sources. Knockout itself has no dependency on Node.js once it is built (it works with any server technology or none). Now run: 28 | 29 | npm install -g grunt-cli 30 | npm install 31 | 32 | The first `npm` command sets up the popular [Grunt](http://gruntjs.com/) build tool. You might need to run this command with `sudo` if you're on Linux or Mac OS X, or in an Administrator command prompt on Windows. The second `npm` command fetches the remaining build dependencies. 33 | 34 | 3. **Run the build tool** 35 | 36 | grunt 37 | 38 | Now you'll find the built files in `build/output/`. 39 | 40 | ## Running the tests 41 | 42 | If you have [phantomjs](http://phantomjs.org/download.html) installed, then the `grunt` script will automatically run the specification suite and report its results. 43 | 44 | Or, if you want to run the specs in a browser (e.g., for debugging), simply open `spec/runner.html` in your browser. 45 | 46 | ##License 47 | 48 | MIT license - [http://www.opensource.org/licenses/mit-license.php](http://www.opensource.org/licenses/mit-license.php) 49 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "knockout", 3 | "version": "3.3.0", 4 | "homepage": "http://knockoutjs.com/", 5 | "description": "Knockout makes it easier to create rich, responsive UIs with JavaScript", 6 | "main": "dist/knockout.js", 7 | "moduleType": [ 8 | "amd", 9 | "globals", 10 | "node" 11 | ], 12 | "keywords": [ 13 | "knockout", 14 | "mvvm", 15 | "mvc", 16 | "spa" 17 | ], 18 | "license": "MIT", 19 | "ignore": [ 20 | "**/.*", 21 | "node_modules", 22 | "bower_components", 23 | "spec", 24 | "build/output" 25 | ] 26 | } -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/build/fragments/amd-post.js: -------------------------------------------------------------------------------- 1 | })); 2 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/build/fragments/amd-pre.js: -------------------------------------------------------------------------------- 1 | (function(factory) { 2 | // Support three module loading scenarios 3 | if (typeof define === 'function' && define['amd']) { 4 | // [1] AMD anonymous module 5 | define(['exports', 'require'], factory); 6 | } else if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') { 7 | // [2] CommonJS/Node.js 8 | factory(module['exports'] || exports); // module.exports is for Node.js 9 | } else { 10 | // [3] No module loader (plain "); 26 | }; 27 | 28 | var buildFolderPath = getPathToScriptTagSrc(debugFileName); 29 | window.knockoutDebugCallback = function (scriptUrls) { 30 | for (var i = 0; i < scriptUrls.length; i++) 31 | referenceScript(buildFolderPath + scriptUrls[i]); 32 | }; 33 | referenceScript(buildFolderPath + sourcesReferenceFile); 34 | })(); 35 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "knockout", 3 | "description": "Knockout makes it easier to create rich, responsive UIs with JavaScript", 4 | "homepage": "http://knockoutjs.com/", 5 | "version": "3.3.0", 6 | "license": "MIT", 7 | "author": "The Knockout.js team", 8 | "main": "build/output/knockout-latest.debug.js", 9 | "scripts": { 10 | "prepublish": "grunt", 11 | "test": "node spec/runner.node.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/knockout/knockout.git" 16 | }, 17 | "bugs": "https://github.com/knockout/knockout/issues", 18 | "testling": { 19 | "preprocess": "build/build.sh", 20 | "html": "spec/runner.html?src=build/output/knockout-latest.js&testling=true", 21 | "browsers": [ 22 | "ie/6..latest", 23 | "chrome/20..latest", 24 | "firefox/3..latest", 25 | "safari/5.0.5..latest", 26 | "opera/11.0..latest", 27 | "iphone/6..latest", 28 | "ipad/6..latest" 29 | ] 30 | }, 31 | "licenses": [ 32 | { "type": "MIT", "url": "http://www.opensource.org/licenses/mit-license.php" } 33 | ], 34 | "devDependencies": { 35 | "grunt": "~0.4.1", 36 | "grunt-cli": "~0.1.0", 37 | "closure-compiler": "~0.2.1" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/bindingProvider.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var defaultBindingAttributeName = "data-bind"; 3 | 4 | ko.bindingProvider = function() { 5 | this.bindingCache = {}; 6 | }; 7 | 8 | ko.utils.extend(ko.bindingProvider.prototype, { 9 | 'nodeHasBindings': function(node) { 10 | switch (node.nodeType) { 11 | case 1: // Element 12 | return node.getAttribute(defaultBindingAttributeName) != null 13 | || ko.components['getComponentNameForNode'](node); 14 | case 8: // Comment node 15 | return ko.virtualElements.hasBindingValue(node); 16 | default: return false; 17 | } 18 | }, 19 | 20 | 'getBindings': function(node, bindingContext) { 21 | var bindingsString = this['getBindingsString'](node, bindingContext), 22 | parsedBindings = bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null; 23 | return ko.components.addBindingsForCustomElement(parsedBindings, node, bindingContext, /* valueAccessors */ false); 24 | }, 25 | 26 | 'getBindingAccessors': function(node, bindingContext) { 27 | var bindingsString = this['getBindingsString'](node, bindingContext), 28 | parsedBindings = bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node, { 'valueAccessors': true }) : null; 29 | return ko.components.addBindingsForCustomElement(parsedBindings, node, bindingContext, /* valueAccessors */ true); 30 | }, 31 | 32 | // The following function is only used internally by this default provider. 33 | // It's not part of the interface definition for a general binding provider. 34 | 'getBindingsString': function(node, bindingContext) { 35 | switch (node.nodeType) { 36 | case 1: return node.getAttribute(defaultBindingAttributeName); // Element 37 | case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node 38 | default: return null; 39 | } 40 | }, 41 | 42 | // The following function is only used internally by this default provider. 43 | // It's not part of the interface definition for a general binding provider. 44 | 'parseBindingsString': function(bindingsString, bindingContext, node, options) { 45 | try { 46 | var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache, options); 47 | return bindingFunction(bindingContext, node); 48 | } catch (ex) { 49 | ex.message = "Unable to parse bindings.\nBindings value: " + bindingsString + "\nMessage: " + ex.message; 50 | throw ex; 51 | } 52 | } 53 | }); 54 | 55 | ko.bindingProvider['instance'] = new ko.bindingProvider(); 56 | 57 | function createBindingsStringEvaluatorViaCache(bindingsString, cache, options) { 58 | var cacheKey = bindingsString + (options && options['valueAccessors'] || ''); 59 | return cache[cacheKey] 60 | || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString, options)); 61 | } 62 | 63 | function createBindingsStringEvaluator(bindingsString, options) { 64 | // Build the source for a function that evaluates "expression" 65 | // For each scope variable, add an extra level of "with" nesting 66 | // Example result: with(sc1) { with(sc0) { return (expression) } } 67 | var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options), 68 | functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}"; 69 | return new Function("$context", "$element", functionBody); 70 | } 71 | })(); 72 | 73 | ko.exportSymbol('bindingProvider', ko.bindingProvider); 74 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/attr.js: -------------------------------------------------------------------------------- 1 | var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' }; 2 | ko.bindingHandlers['attr'] = { 3 | 'update': function(element, valueAccessor, allBindings) { 4 | var value = ko.utils.unwrapObservable(valueAccessor()) || {}; 5 | ko.utils.objectForEach(value, function(attrName, attrValue) { 6 | attrValue = ko.utils.unwrapObservable(attrValue); 7 | 8 | // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely 9 | // when someProp is a "no value"-like value (strictly null, false, or undefined) 10 | // (because the absence of the "checked" attr is how to mark an element as not checked, etc.) 11 | var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined); 12 | if (toRemove) 13 | element.removeAttribute(attrName); 14 | 15 | // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the 16 | // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior, 17 | // but instead of figuring out the mode, we'll just set the attribute through the Javascript 18 | // property for IE <= 8. 19 | if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) { 20 | attrName = attrHtmlToJavascriptMap[attrName]; 21 | if (toRemove) 22 | element.removeAttribute(attrName); 23 | else 24 | element[attrName] = attrValue; 25 | } else if (!toRemove) { 26 | element.setAttribute(attrName, attrValue.toString()); 27 | } 28 | 29 | // Treat "name" specially - although you can think of it as an attribute, it also needs 30 | // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333) 31 | // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing 32 | // entirely, and there's no strong reason to allow for such casing in HTML. 33 | if (attrName === "name") { 34 | ko.utils.setElementName(element, toRemove ? "" : attrValue.toString()); 35 | } 36 | }); 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/click.js: -------------------------------------------------------------------------------- 1 | // 'click' is just a shorthand for the usual full-length event:{click:handler} 2 | makeEventHandlerShortcut('click'); 3 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/css.js: -------------------------------------------------------------------------------- 1 | var classesWrittenByBindingKey = '__ko__cssValue'; 2 | ko.bindingHandlers['css'] = { 3 | 'update': function (element, valueAccessor) { 4 | var value = ko.utils.unwrapObservable(valueAccessor()); 5 | if (value !== null && typeof value == "object") { 6 | ko.utils.objectForEach(value, function(className, shouldHaveClass) { 7 | shouldHaveClass = ko.utils.unwrapObservable(shouldHaveClass); 8 | ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass); 9 | }); 10 | } else { 11 | value = String(value || ''); // Make sure we don't try to store or set a non-string value 12 | ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false); 13 | element[classesWrittenByBindingKey] = value; 14 | ko.utils.toggleDomNodeCssClass(element, value, true); 15 | } 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/enableDisable.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['enable'] = { 2 | 'update': function (element, valueAccessor) { 3 | var value = ko.utils.unwrapObservable(valueAccessor()); 4 | if (value && element.disabled) 5 | element.removeAttribute("disabled"); 6 | else if ((!value) && (!element.disabled)) 7 | element.disabled = true; 8 | } 9 | }; 10 | 11 | ko.bindingHandlers['disable'] = { 12 | 'update': function (element, valueAccessor) { 13 | ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) }); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/event.js: -------------------------------------------------------------------------------- 1 | // For certain common events (currently just 'click'), allow a simplified data-binding syntax 2 | // e.g. click:handler instead of the usual full-length event:{click:handler} 3 | function makeEventHandlerShortcut(eventName) { 4 | ko.bindingHandlers[eventName] = { 5 | 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) { 6 | var newValueAccessor = function () { 7 | var result = {}; 8 | result[eventName] = valueAccessor(); 9 | return result; 10 | }; 11 | return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext); 12 | } 13 | } 14 | } 15 | 16 | ko.bindingHandlers['event'] = { 17 | 'init' : function (element, valueAccessor, allBindings, viewModel, bindingContext) { 18 | var eventsToHandle = valueAccessor() || {}; 19 | ko.utils.objectForEach(eventsToHandle, function(eventName) { 20 | if (typeof eventName == "string") { 21 | ko.utils.registerEventHandler(element, eventName, function (event) { 22 | var handlerReturnValue; 23 | var handlerFunction = valueAccessor()[eventName]; 24 | if (!handlerFunction) 25 | return; 26 | 27 | try { 28 | // Take all the event args, and prefix with the viewmodel 29 | var argsForHandler = ko.utils.makeArray(arguments); 30 | viewModel = bindingContext['$data']; 31 | argsForHandler.unshift(viewModel); 32 | handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler); 33 | } finally { 34 | if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true. 35 | if (event.preventDefault) 36 | event.preventDefault(); 37 | else 38 | event.returnValue = false; 39 | } 40 | } 41 | 42 | var bubble = allBindings.get(eventName + 'Bubble') !== false; 43 | if (!bubble) { 44 | event.cancelBubble = true; 45 | if (event.stopPropagation) 46 | event.stopPropagation(); 47 | } 48 | }); 49 | } 50 | }); 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/foreach.js: -------------------------------------------------------------------------------- 1 | // "foreach: someExpression" is equivalent to "template: { foreach: someExpression }" 2 | // "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }" 3 | ko.bindingHandlers['foreach'] = { 4 | makeTemplateValueAccessor: function(valueAccessor) { 5 | return function() { 6 | var modelValue = valueAccessor(), 7 | unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here 8 | 9 | // If unwrappedValue is the array, pass in the wrapped value on its own 10 | // The value will be unwrapped and tracked within the template binding 11 | // (See https://github.com/SteveSanderson/knockout/issues/523) 12 | if ((!unwrappedValue) || typeof unwrappedValue.length == "number") 13 | return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance }; 14 | 15 | // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates 16 | ko.utils.unwrapObservable(modelValue); 17 | return { 18 | 'foreach': unwrappedValue['data'], 19 | 'as': unwrappedValue['as'], 20 | 'includeDestroyed': unwrappedValue['includeDestroyed'], 21 | 'afterAdd': unwrappedValue['afterAdd'], 22 | 'beforeRemove': unwrappedValue['beforeRemove'], 23 | 'afterRender': unwrappedValue['afterRender'], 24 | 'beforeMove': unwrappedValue['beforeMove'], 25 | 'afterMove': unwrappedValue['afterMove'], 26 | 'templateEngine': ko.nativeTemplateEngine.instance 27 | }; 28 | }; 29 | }, 30 | 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) { 31 | return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor)); 32 | }, 33 | 'update': function(element, valueAccessor, allBindings, viewModel, bindingContext) { 34 | return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindings, viewModel, bindingContext); 35 | } 36 | }; 37 | ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings 38 | ko.virtualElements.allowedBindings['foreach'] = true; 39 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/hasfocus.js: -------------------------------------------------------------------------------- 1 | var hasfocusUpdatingProperty = '__ko_hasfocusUpdating'; 2 | var hasfocusLastValue = '__ko_hasfocusLastValue'; 3 | ko.bindingHandlers['hasfocus'] = { 4 | 'init': function(element, valueAccessor, allBindings) { 5 | var handleElementFocusChange = function(isFocused) { 6 | // Where possible, ignore which event was raised and determine focus state using activeElement, 7 | // as this avoids phantom focus/blur events raised when changing tabs in modern browsers. 8 | // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers, 9 | // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus 10 | // from calling 'blur()' on the element when it loses focus. 11 | // Discussion at https://github.com/SteveSanderson/knockout/pull/352 12 | element[hasfocusUpdatingProperty] = true; 13 | var ownerDoc = element.ownerDocument; 14 | if ("activeElement" in ownerDoc) { 15 | var active; 16 | try { 17 | active = ownerDoc.activeElement; 18 | } catch(e) { 19 | // IE9 throws if you access activeElement during page load (see issue #703) 20 | active = ownerDoc.body; 21 | } 22 | isFocused = (active === element); 23 | } 24 | var modelValue = valueAccessor(); 25 | ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'hasfocus', isFocused, true); 26 | 27 | //cache the latest value, so we can avoid unnecessarily calling focus/blur in the update function 28 | element[hasfocusLastValue] = isFocused; 29 | element[hasfocusUpdatingProperty] = false; 30 | }; 31 | var handleElementFocusIn = handleElementFocusChange.bind(null, true); 32 | var handleElementFocusOut = handleElementFocusChange.bind(null, false); 33 | 34 | ko.utils.registerEventHandler(element, "focus", handleElementFocusIn); 35 | ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE 36 | ko.utils.registerEventHandler(element, "blur", handleElementFocusOut); 37 | ko.utils.registerEventHandler(element, "focusout", handleElementFocusOut); // For IE 38 | }, 39 | 'update': function(element, valueAccessor) { 40 | var value = !!ko.utils.unwrapObservable(valueAccessor()); //force boolean to compare with last value 41 | if (!element[hasfocusUpdatingProperty] && element[hasfocusLastValue] !== value) { 42 | value ? element.focus() : element.blur(); 43 | ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously 44 | } 45 | } 46 | }; 47 | ko.expressionRewriting.twoWayBindings['hasfocus'] = true; 48 | 49 | ko.bindingHandlers['hasFocus'] = ko.bindingHandlers['hasfocus']; // Make "hasFocus" an alias 50 | ko.expressionRewriting.twoWayBindings['hasFocus'] = true; 51 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/html.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['html'] = { 2 | 'init': function() { 3 | // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications) 4 | return { 'controlsDescendantBindings': true }; 5 | }, 6 | 'update': function (element, valueAccessor) { 7 | // setHtml will unwrap the value if needed 8 | ko.utils.setHtml(element, valueAccessor()); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/ifIfnotWith.js: -------------------------------------------------------------------------------- 1 | // Makes a binding like with or if 2 | function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) { 3 | ko.bindingHandlers[bindingKey] = { 4 | 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) { 5 | var didDisplayOnLastUpdate, 6 | savedNodes; 7 | ko.computed(function() { 8 | var dataValue = ko.utils.unwrapObservable(valueAccessor()), 9 | shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue 10 | isFirstRender = !savedNodes, 11 | needsRefresh = isFirstRender || isWith || (shouldDisplay !== didDisplayOnLastUpdate); 12 | 13 | if (needsRefresh) { 14 | // Save a copy of the inner nodes on the initial update, but only if we have dependencies. 15 | if (isFirstRender && ko.computedContext.getDependenciesCount()) { 16 | savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */); 17 | } 18 | 19 | if (shouldDisplay) { 20 | if (!isFirstRender) { 21 | ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(savedNodes)); 22 | } 23 | ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element); 24 | } else { 25 | ko.virtualElements.emptyNode(element); 26 | } 27 | 28 | didDisplayOnLastUpdate = shouldDisplay; 29 | } 30 | }, null, { disposeWhenNodeIsRemoved: element }); 31 | return { 'controlsDescendantBindings': true }; 32 | } 33 | }; 34 | ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings 35 | ko.virtualElements.allowedBindings[bindingKey] = true; 36 | } 37 | 38 | // Construct the actual binding handlers 39 | makeWithIfBinding('if'); 40 | makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */); 41 | makeWithIfBinding('with', true /* isWith */, false /* isNot */, 42 | function(bindingContext, dataValue) { 43 | return bindingContext['createChildContext'](dataValue); 44 | } 45 | ); 46 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/selectedOptions.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['selectedOptions'] = { 2 | 'after': ['options', 'foreach'], 3 | 'init': function (element, valueAccessor, allBindings) { 4 | ko.utils.registerEventHandler(element, "change", function () { 5 | var value = valueAccessor(), valueToWrite = []; 6 | ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) { 7 | if (node.selected) 8 | valueToWrite.push(ko.selectExtensions.readValue(node)); 9 | }); 10 | ko.expressionRewriting.writeValueToProperty(value, allBindings, 'selectedOptions', valueToWrite); 11 | }); 12 | }, 13 | 'update': function (element, valueAccessor) { 14 | if (ko.utils.tagNameLower(element) != "select") 15 | throw new Error("values binding applies only to SELECT elements"); 16 | 17 | var newValue = ko.utils.unwrapObservable(valueAccessor()); 18 | if (newValue && typeof newValue.length == "number") { 19 | ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) { 20 | var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0; 21 | ko.utils.setOptionNodeSelectionState(node, isSelected); 22 | }); 23 | } 24 | } 25 | }; 26 | ko.expressionRewriting.twoWayBindings['selectedOptions'] = true; 27 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/style.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['style'] = { 2 | 'update': function (element, valueAccessor) { 3 | var value = ko.utils.unwrapObservable(valueAccessor() || {}); 4 | ko.utils.objectForEach(value, function(styleName, styleValue) { 5 | styleValue = ko.utils.unwrapObservable(styleValue); 6 | 7 | if (styleValue === null || styleValue === undefined || styleValue === false) { 8 | // Empty string removes the value, whereas null/undefined have no effect 9 | styleValue = ""; 10 | } 11 | 12 | element.style[styleName] = styleValue; 13 | }); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/submit.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['submit'] = { 2 | 'init': function (element, valueAccessor, allBindings, viewModel, bindingContext) { 3 | if (typeof valueAccessor() != "function") 4 | throw new Error("The value for a submit binding must be a function"); 5 | ko.utils.registerEventHandler(element, "submit", function (event) { 6 | var handlerReturnValue; 7 | var value = valueAccessor(); 8 | try { handlerReturnValue = value.call(bindingContext['$data'], element); } 9 | finally { 10 | if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true. 11 | if (event.preventDefault) 12 | event.preventDefault(); 13 | else 14 | event.returnValue = false; 15 | } 16 | } 17 | }); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/text.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['text'] = { 2 | 'init': function() { 3 | // Prevent binding on the dynamically-injected text node (as developers are unlikely to expect that, and it has security implications). 4 | // It should also make things faster, as we no longer have to consider whether the text node might be bindable. 5 | return { 'controlsDescendantBindings': true }; 6 | }, 7 | 'update': function (element, valueAccessor) { 8 | ko.utils.setTextContent(element, valueAccessor()); 9 | } 10 | }; 11 | ko.virtualElements.allowedBindings['text'] = true; 12 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/uniqueName.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['uniqueName'] = { 2 | 'init': function (element, valueAccessor) { 3 | if (valueAccessor()) { 4 | var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex); 5 | ko.utils.setElementName(element, name); 6 | } 7 | } 8 | }; 9 | ko.bindingHandlers['uniqueName'].currentIndex = 0; 10 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/binding/defaultBindings/visible.js: -------------------------------------------------------------------------------- 1 | ko.bindingHandlers['visible'] = { 2 | 'update': function (element, valueAccessor) { 3 | var value = ko.utils.unwrapObservable(valueAccessor()); 4 | var isCurrentlyVisible = !(element.style.display == "none"); 5 | if (value && !isCurrentlyVisible) 6 | element.style.display = ""; 7 | else if ((!value) && isCurrentlyVisible) 8 | element.style.display = "none"; 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/google-closure-compiler-utils.js: -------------------------------------------------------------------------------- 1 | // Google Closure Compiler helpers (used only to make the minified file smaller) 2 | ko.exportSymbol = function(koPath, object) { 3 | var tokens = koPath.split("."); 4 | 5 | // In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable) 6 | // At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko) 7 | var target = ko; 8 | 9 | for (var i = 0; i < tokens.length - 1; i++) 10 | target = target[tokens[i]]; 11 | target[tokens[tokens.length - 1]] = object; 12 | }; 13 | ko.exportProperty = function(owner, publicName, object) { 14 | owner[publicName] = object; 15 | }; 16 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/memoization.js: -------------------------------------------------------------------------------- 1 | 2 | ko.memoization = (function () { 3 | var memos = {}; 4 | 5 | function randomMax8HexChars() { 6 | return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1); 7 | } 8 | function generateRandomId() { 9 | return randomMax8HexChars() + randomMax8HexChars(); 10 | } 11 | function findMemoNodes(rootNode, appendToArray) { 12 | if (!rootNode) 13 | return; 14 | if (rootNode.nodeType == 8) { 15 | var memoId = ko.memoization.parseMemoText(rootNode.nodeValue); 16 | if (memoId != null) 17 | appendToArray.push({ domNode: rootNode, memoId: memoId }); 18 | } else if (rootNode.nodeType == 1) { 19 | for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++) 20 | findMemoNodes(childNodes[i], appendToArray); 21 | } 22 | } 23 | 24 | return { 25 | memoize: function (callback) { 26 | if (typeof callback != "function") 27 | throw new Error("You can only pass a function to ko.memoization.memoize()"); 28 | var memoId = generateRandomId(); 29 | memos[memoId] = callback; 30 | return ""; 31 | }, 32 | 33 | unmemoize: function (memoId, callbackParams) { 34 | var callback = memos[memoId]; 35 | if (callback === undefined) 36 | throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized."); 37 | try { 38 | callback.apply(null, callbackParams || []); 39 | return true; 40 | } 41 | finally { delete memos[memoId]; } 42 | }, 43 | 44 | unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) { 45 | var memos = []; 46 | findMemoNodes(domNode, memos); 47 | for (var i = 0, j = memos.length; i < j; i++) { 48 | var node = memos[i].domNode; 49 | var combinedParams = [node]; 50 | if (extraCallbackParamsArray) 51 | ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray); 52 | ko.memoization.unmemoize(memos[i].memoId, combinedParams); 53 | node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again 54 | if (node.parentNode) 55 | node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again) 56 | } 57 | }, 58 | 59 | parseMemoText: function (memoText) { 60 | var match = memoText.match(/^\[ko_memo\:(.*?)\]$/); 61 | return match ? match[1] : null; 62 | } 63 | }; 64 | })(); 65 | 66 | ko.exportSymbol('memoization', ko.memoization); 67 | ko.exportSymbol('memoization.memoize', ko.memoization.memoize); 68 | ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize); 69 | ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText); 70 | ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants); 71 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/namespace.js: -------------------------------------------------------------------------------- 1 | // Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler). 2 | // In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable. 3 | var ko = typeof koExports !== 'undefined' ? koExports : {}; 4 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/subscribables/dependencyDetection.js: -------------------------------------------------------------------------------- 1 | 2 | ko.computedContext = ko.dependencyDetection = (function () { 3 | var outerFrames = [], 4 | currentFrame, 5 | lastId = 0; 6 | 7 | // Return a unique ID that can be assigned to an observable for dependency tracking. 8 | // Theoretically, you could eventually overflow the number storage size, resulting 9 | // in duplicate IDs. But in JavaScript, the largest exact integral value is 2^53 10 | // or 9,007,199,254,740,992. If you created 1,000,000 IDs per second, it would 11 | // take over 285 years to reach that number. 12 | // Reference http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html 13 | function getId() { 14 | return ++lastId; 15 | } 16 | 17 | function begin(options) { 18 | outerFrames.push(currentFrame); 19 | currentFrame = options; 20 | } 21 | 22 | function end() { 23 | currentFrame = outerFrames.pop(); 24 | } 25 | 26 | return { 27 | begin: begin, 28 | 29 | end: end, 30 | 31 | registerDependency: function (subscribable) { 32 | if (currentFrame) { 33 | if (!ko.isSubscribable(subscribable)) 34 | throw new Error("Only subscribable things can act as dependencies"); 35 | currentFrame.callback(subscribable, subscribable._id || (subscribable._id = getId())); 36 | } 37 | }, 38 | 39 | ignore: function (callback, callbackTarget, callbackArgs) { 40 | try { 41 | begin(); 42 | return callback.apply(callbackTarget, callbackArgs || []); 43 | } finally { 44 | end(); 45 | } 46 | }, 47 | 48 | getDependenciesCount: function () { 49 | if (currentFrame) 50 | return currentFrame.computed.getDependenciesCount(); 51 | }, 52 | 53 | isInitial: function() { 54 | if (currentFrame) 55 | return currentFrame.isInitial; 56 | } 57 | }; 58 | })(); 59 | 60 | ko.exportSymbol('computedContext', ko.computedContext); 61 | ko.exportSymbol('computedContext.getDependenciesCount', ko.computedContext.getDependenciesCount); 62 | ko.exportSymbol('computedContext.isInitial', ko.computedContext.isInitial); 63 | ko.exportSymbol('computedContext.isSleeping', ko.computedContext.isSleeping); 64 | 65 | ko.exportSymbol('ignoreDependencies', ko.ignoreDependencies = ko.dependencyDetection.ignore); 66 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/subscribables/extenders.js: -------------------------------------------------------------------------------- 1 | ko.extenders = { 2 | 'throttle': function(target, timeout) { 3 | // Throttling means two things: 4 | 5 | // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies 6 | // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate 7 | target['throttleEvaluation'] = timeout; 8 | 9 | // (2) For writable targets (observables, or writable dependent observables), we throttle *writes* 10 | // so the target cannot change value synchronously or faster than a certain rate 11 | var writeTimeoutInstance = null; 12 | return ko.dependentObservable({ 13 | 'read': target, 14 | 'write': function(value) { 15 | clearTimeout(writeTimeoutInstance); 16 | writeTimeoutInstance = setTimeout(function() { 17 | target(value); 18 | }, timeout); 19 | } 20 | }); 21 | }, 22 | 23 | 'rateLimit': function(target, options) { 24 | var timeout, method, limitFunction; 25 | 26 | if (typeof options == 'number') { 27 | timeout = options; 28 | } else { 29 | timeout = options['timeout']; 30 | method = options['method']; 31 | } 32 | 33 | limitFunction = method == 'notifyWhenChangesStop' ? debounce : throttle; 34 | target.limit(function(callback) { 35 | return limitFunction(callback, timeout); 36 | }); 37 | }, 38 | 39 | 'notify': function(target, notifyWhen) { 40 | target["equalityComparer"] = notifyWhen == "always" ? 41 | null : // null equalityComparer means to always notify 42 | valuesArePrimitiveAndEqual; 43 | } 44 | }; 45 | 46 | var primitiveTypes = { 'undefined':1, 'boolean':1, 'number':1, 'string':1 }; 47 | function valuesArePrimitiveAndEqual(a, b) { 48 | var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes); 49 | return oldValueIsPrimitive ? (a === b) : false; 50 | } 51 | 52 | function throttle(callback, timeout) { 53 | var timeoutInstance; 54 | return function () { 55 | if (!timeoutInstance) { 56 | timeoutInstance = setTimeout(function() { 57 | timeoutInstance = undefined; 58 | callback(); 59 | }, timeout); 60 | } 61 | }; 62 | } 63 | 64 | function debounce(callback, timeout) { 65 | var timeoutInstance; 66 | return function () { 67 | clearTimeout(timeoutInstance); 68 | timeoutInstance = setTimeout(callback, timeout); 69 | }; 70 | } 71 | 72 | function applyExtenders(requestedExtenders) { 73 | var target = this; 74 | if (requestedExtenders) { 75 | ko.utils.objectForEach(requestedExtenders, function(key, value) { 76 | var extenderHandler = ko.extenders[key]; 77 | if (typeof extenderHandler == 'function') { 78 | target = extenderHandler(target, value) || target; 79 | } 80 | }); 81 | } 82 | return target; 83 | } 84 | 85 | ko.exportSymbol('extenders', ko.extenders); 86 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/subscribables/observable.js: -------------------------------------------------------------------------------- 1 | ko.observable = function (initialValue) { 2 | var _latestValue = initialValue; 3 | 4 | function observable() { 5 | if (arguments.length > 0) { 6 | // Write 7 | 8 | // Ignore writes if the value hasn't changed 9 | if (observable.isDifferent(_latestValue, arguments[0])) { 10 | observable.valueWillMutate(); 11 | _latestValue = arguments[0]; 12 | if (DEBUG) observable._latestValue = _latestValue; 13 | observable.valueHasMutated(); 14 | } 15 | return this; // Permits chained assignments 16 | } 17 | else { 18 | // Read 19 | ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation 20 | return _latestValue; 21 | } 22 | } 23 | ko.subscribable.call(observable); 24 | ko.utils.setPrototypeOfOrExtend(observable, ko.observable['fn']); 25 | 26 | if (DEBUG) observable._latestValue = _latestValue; 27 | observable.peek = function() { return _latestValue }; 28 | observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); } 29 | observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); } 30 | 31 | ko.exportProperty(observable, 'peek', observable.peek); 32 | ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated); 33 | ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate); 34 | 35 | return observable; 36 | } 37 | 38 | ko.observable['fn'] = { 39 | "equalityComparer": valuesArePrimitiveAndEqual 40 | }; 41 | 42 | var protoProperty = ko.observable.protoProperty = "__ko_proto__"; 43 | ko.observable['fn'][protoProperty] = ko.observable; 44 | 45 | // Note that for browsers that don't support proto assignment, the 46 | // inheritance chain is created manually in the ko.observable constructor 47 | if (ko.utils.canSetPrototype) { 48 | ko.utils.setPrototypeOf(ko.observable['fn'], ko.subscribable['fn']); 49 | } 50 | 51 | ko.hasPrototype = function(instance, prototype) { 52 | if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false; 53 | if (instance[protoProperty] === prototype) return true; 54 | return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain 55 | }; 56 | 57 | ko.isObservable = function (instance) { 58 | return ko.hasPrototype(instance, ko.observable); 59 | } 60 | ko.isWriteableObservable = function (instance) { 61 | // Observable 62 | if ((typeof instance == "function") && instance[protoProperty] === ko.observable) 63 | return true; 64 | // Writeable dependent observable 65 | if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction)) 66 | return true; 67 | // Anything else 68 | return false; 69 | } 70 | 71 | 72 | ko.exportSymbol('observable', ko.observable); 73 | ko.exportSymbol('isObservable', ko.isObservable); 74 | ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable); 75 | ko.exportSymbol('isWritableObservable', ko.isWriteableObservable); 76 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/templating/native/nativeTemplateEngine.js: -------------------------------------------------------------------------------- 1 | ko.nativeTemplateEngine = function () { 2 | this['allowTemplateRewriting'] = false; 3 | } 4 | 5 | ko.nativeTemplateEngine.prototype = new ko.templateEngine(); 6 | ko.nativeTemplateEngine.prototype.constructor = ko.nativeTemplateEngine; 7 | ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options, templateDocument) { 8 | var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly 9 | templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null, 10 | templateNodes = templateNodesFunc ? templateSource['nodes']() : null; 11 | 12 | if (templateNodes) { 13 | return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes); 14 | } else { 15 | var templateText = templateSource['text'](); 16 | return ko.utils.parseHtmlFragment(templateText, templateDocument); 17 | } 18 | }; 19 | 20 | ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine(); 21 | ko.setTemplateEngine(ko.nativeTemplateEngine.instance); 22 | 23 | ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine); 24 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/templating/templateEngine.js: -------------------------------------------------------------------------------- 1 | // If you want to make a custom template engine, 2 | // 3 | // [1] Inherit from this class (like ko.nativeTemplateEngine does) 4 | // [2] Override 'renderTemplateSource', supplying a function with this signature: 5 | // 6 | // function (templateSource, bindingContext, options) { 7 | // // - templateSource.text() is the text of the template you should render 8 | // // - bindingContext.$data is the data you should pass into the template 9 | // // - you might also want to make bindingContext.$parent, bindingContext.$parents, 10 | // // and bindingContext.$root available in the template too 11 | // // - options gives you access to any other properties set on "data-bind: { template: options }" 12 | // // - templateDocument is the document object of the template 13 | // // 14 | // // Return value: an array of DOM nodes 15 | // } 16 | // 17 | // [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature: 18 | // 19 | // function (script) { 20 | // // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result" 21 | // // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }' 22 | // } 23 | // 24 | // This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables. 25 | // If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does) 26 | // and then you don't need to override 'createJavaScriptEvaluatorBlock'. 27 | 28 | ko.templateEngine = function () { }; 29 | 30 | ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options, templateDocument) { 31 | throw new Error("Override renderTemplateSource"); 32 | }; 33 | 34 | ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) { 35 | throw new Error("Override createJavaScriptEvaluatorBlock"); 36 | }; 37 | 38 | ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) { 39 | // Named template 40 | if (typeof template == "string") { 41 | templateDocument = templateDocument || document; 42 | var elem = templateDocument.getElementById(template); 43 | if (!elem) 44 | throw new Error("Cannot find template with ID " + template); 45 | return new ko.templateSources.domElement(elem); 46 | } else if ((template.nodeType == 1) || (template.nodeType == 8)) { 47 | // Anonymous template 48 | return new ko.templateSources.anonymousTemplate(template); 49 | } else 50 | throw new Error("Unknown template type: " + template); 51 | }; 52 | 53 | ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) { 54 | var templateSource = this['makeTemplateSource'](template, templateDocument); 55 | return this['renderTemplateSource'](templateSource, bindingContext, options, templateDocument); 56 | }; 57 | 58 | ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) { 59 | // Skip rewriting if requested 60 | if (this['allowTemplateRewriting'] === false) 61 | return true; 62 | return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten"); 63 | }; 64 | 65 | ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) { 66 | var templateSource = this['makeTemplateSource'](template, templateDocument); 67 | var rewritten = rewriterCallback(templateSource['text']()); 68 | templateSource['text'](rewritten); 69 | templateSource['data']("isRewritten", true); 70 | }; 71 | 72 | ko.exportSymbol('templateEngine', ko.templateEngine); 73 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/utils.domData.js: -------------------------------------------------------------------------------- 1 | 2 | ko.utils.domData = new (function () { 3 | var uniqueId = 0; 4 | var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime(); 5 | var dataStore = {}; 6 | 7 | function getAll(node, createIfNotFound) { 8 | var dataStoreKey = node[dataStoreKeyExpandoPropertyName]; 9 | var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey]; 10 | if (!hasExistingDataStore) { 11 | if (!createIfNotFound) 12 | return undefined; 13 | dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++; 14 | dataStore[dataStoreKey] = {}; 15 | } 16 | return dataStore[dataStoreKey]; 17 | } 18 | 19 | return { 20 | get: function (node, key) { 21 | var allDataForNode = getAll(node, false); 22 | return allDataForNode === undefined ? undefined : allDataForNode[key]; 23 | }, 24 | set: function (node, key, value) { 25 | if (value === undefined) { 26 | // Make sure we don't actually create a new domData key if we are actually deleting a value 27 | if (getAll(node, false) === undefined) 28 | return; 29 | } 30 | var allDataForNode = getAll(node, true); 31 | allDataForNode[key] = value; 32 | }, 33 | clear: function (node) { 34 | var dataStoreKey = node[dataStoreKeyExpandoPropertyName]; 35 | if (dataStoreKey) { 36 | delete dataStore[dataStoreKey]; 37 | node[dataStoreKeyExpandoPropertyName] = null; 38 | return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended 39 | } 40 | return false; 41 | }, 42 | 43 | nextKey: function () { 44 | return (uniqueId++) + dataStoreKeyExpandoPropertyName; 45 | } 46 | }; 47 | })(); 48 | 49 | ko.exportSymbol('utils.domData', ko.utils.domData); 50 | ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully 51 | -------------------------------------------------------------------------------- /transports/web/public/js/bower_components/knockout/src/version.js: -------------------------------------------------------------------------------- 1 | ko.version = "##VERSION##"; 2 | 3 | ko.exportSymbol('version', ko.version); 4 | -------------------------------------------------------------------------------- /transports/web/public/js/knockout-postbox.min.js: -------------------------------------------------------------------------------- 1 | // knockout-postbox 0.5.2 | (c) 2015 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license 2 | !function(a){"function"==typeof require&&"object"==typeof exports&&"object"==typeof module?a(require("knockout"),exports):"function"==typeof define&&define.amd?define(["knockout","exports"],a):a(ko,ko.postbox={})}(function(a,b,c){var d,e,f={},g=1;b.subscriptions=f,a.subscribable.call(b),b.topicCache={},b.serializer=a.toJSON,b.publish=function(a,c){a&&(b.topicCache[a]={value:c,serialized:b.serializer(c)},b.notifySubscribers(c,a))},e=b.subscribe,b.subscribe=function(a,d,h,i){var j,k,l;return a?("boolean"==typeof h&&(i=h,h=c),j=e.call(b,d,h,a),j.subId=++g,f[g]=j,i&&(k=b.topicCache[a],k!==c&&d.call(h,k.value)),l=j.dispose,j.dispose=function(){delete f[j.subId],l.call(j)},j):void 0},b.reset=function(){var a;for(var c in f)f.hasOwnProperty(c)&&(a=f[c],a&&"function"==typeof a.dispose&&a.dispose());b.topicCache={}},b.defaultComparer=function(a,c){return c&&b.serializer(a)===c.serialized},a.subscribable.fn.publishOn=function(a,c,e){var h,i,j;return a&&("function"==typeof c?e=c:h=c,e=e||b.defaultComparer,d.call(this,a,"publishOn"),i=this.subscribe(function(c){e.call(this,c,b.topicCache[a])||b.publish(a,c)},this),i.id=++g,f[g]=i,j=i.dispose,i.dispose=function(){delete this.postboxSubs[a].publishOn,delete f[i.id],j.call(i)}.bind(this),this.postboxSubs[a].publishOn=i,h||b.publish(a,this())),this},d=function(a,b){var c=this.postboxSubs=this.postboxSubs||{};c[a]=c[a]||{},c[a][b]&&c[a][b].dispose()},a.subscribable.fn.stopPublishingOn=function(a){return d.call(this,a,"publishOn"),this},a.subscribable.fn.subscribeTo=function(e,f,g){var h,i,j,k,l,m=this;return"function"==typeof f?g=f:h=f,e&&a.isWriteableObservable(this)&&(d.call(this,e,"subscribeTo"),j=function(a){m(g?g.call(m,a):a)},k=b.subscribe(e,j),this.postboxSubs[e].subscribeTo=k,l=k.dispose,k.dispose=function(){delete this.postboxSubs[e].subscribeTo,l.call(k)}.bind(this),h&&(i=b.topicCache[e],i!==c&&j(i.value))),this},a.subscribable.fn.unsubscribeFrom=function(a){return d.call(this,a,"subscribeTo"),this},a.subscribable.fn.syncWith=function(a,b,c,d){return this.subscribeTo(a,b).publishOn(a,c,d),this},a.postbox=b}); -------------------------------------------------------------------------------- /transports/web/readme.md: -------------------------------------------------------------------------------- 1 | # HTTP server implementation -------------------------------------------------------------------------------- /transports/web/routes/api.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var util = require('util'); 4 | var thing_handler = require('../../../libs/thing/thing_handler'); 5 | var db = require('../../../data/db')(); 6 | 7 | function handleError(err, res) { 8 | var obj = { 9 | error: {} 10 | }; 11 | 12 | if (err && err.message) { 13 | obj.error = err.message 14 | } 15 | else if (typeof err === 'string') { 16 | obj.error = err 17 | } 18 | else { 19 | obj.error = 'Unknown error'; 20 | } 21 | 22 | res.send(obj); 23 | } 24 | 25 | router.route('/thing/model') 26 | .post(function (req, res) { 27 | 28 | try { 29 | var request = req.body; 30 | if (!request) { 31 | return handleError('invalid request parameter', res); 32 | } 33 | var thing_name = request.thing; 34 | if (!thing_name) { 35 | return handleError('invalid request thing name parameter', res); 36 | } 37 | 38 | thing_handler.get_model(thing_name, function (err, model) { 39 | if (err) { 40 | handleError(err, res); 41 | } 42 | else if (!model) { 43 | handleError('the thing model is null', res); 44 | } 45 | else { 46 | var response = { 47 | thing: thing_name, 48 | model: model 49 | }; 50 | return res.json(response); 51 | } 52 | }); 53 | 54 | 55 | } 56 | catch (e) { 57 | return handleError(e, res); 58 | } 59 | }); 60 | 61 | 62 | router.route('/things/list') 63 | .post(function (req, res) { 64 | 65 | try { 66 | db.things_list(function (err, things) { 67 | if (err) { 68 | return handleError(err, res); 69 | } 70 | 71 | if (!util.isArray(things)) { 72 | return handleError("invalid thing array", res); 73 | } 74 | 75 | res.json(things); 76 | }); 77 | } 78 | catch (e) { 79 | return handleError(e, res); 80 | } 81 | }); 82 | 83 | 84 | router.route('/thing/property/get') 85 | .post(function (req, res) { 86 | 87 | try { 88 | var request = req.body; 89 | if (!request) { 90 | return handleError('invalid request parameter', res); 91 | } 92 | var thing_name = request.thing; 93 | if (!thing_name) { 94 | return handleError('invalid request thing name parameter', res); 95 | } 96 | var property = request.property; 97 | if (!property) { 98 | return handleError('invalid request property parameter', res); 99 | } 100 | 101 | thing_handler.get_thing_async(thing_name, function (err, thing) { 102 | if (err) { 103 | return handleError('property get error', res); 104 | } 105 | 106 | // get the property asynchronously so the remote property can be retrieved in case the thing is a remote proxy 107 | thing.property_get(property, function (err, value) { 108 | if (err) { 109 | handleError(err, res); 110 | } 111 | else { 112 | var response = { 113 | thing: thing_name, 114 | property: property, 115 | value: value 116 | }; 117 | return res.json(response); 118 | } 119 | }); 120 | }); 121 | } 122 | catch (e) { 123 | return handleError(e, res); 124 | } 125 | }); 126 | 127 | 128 | module.exports = router; -------------------------------------------------------------------------------- /transports/web/routes/main.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var logger = require('../../../logger'); 3 | var thing_handler = require('../../../libs/thing/thing_handler'); 4 | 5 | 6 | var router = express.Router(); 7 | 8 | /* GET home page. */ 9 | router.get('/', function (req, res) { 10 | res.render('index'); 11 | }); 12 | 13 | router.get('/things', function (req, res) { 14 | res.render('things'); 15 | }); 16 | 17 | router.get('/docs', function (req, res) { 18 | res.render('docs'); 19 | }); 20 | 21 | router.get('/tutorials', function (req, res) { 22 | res.render('tutorials'); 23 | }); 24 | 25 | 26 | module.exports = router; -------------------------------------------------------------------------------- /transports/web/views/docs.handlebars: -------------------------------------------------------------------------------- 1 |  2 |
3 |
4 |

Documentation/API

5 |
6 |
7 | -------------------------------------------------------------------------------- /transports/web/views/error.handlebars: -------------------------------------------------------------------------------- 1 | 
2 |

{{ message }}

3 |

{{ error.status }}

4 |
5 |     {{ error.stack }}
6 |   
7 |
8 | -------------------------------------------------------------------------------- /transports/web/views/index.handlebars: -------------------------------------------------------------------------------- 1 |  2 |
3 |
4 |

Web of Things Test Page

5 |

A page for developing a basic Web of Things JavaScript library.

6 |
7 |
8 | -------------------------------------------------------------------------------- /transports/web/views/layouts/main.handlebars: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | WoT test page 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 43 | 44 |
45 |
46 | {{{body}}} 47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | {{{_sections.script}}} 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /transports/web/views/partials/door.html: -------------------------------------------------------------------------------- 1 | 
2 |

Door Device

3 |

Display here the door device UI controls and events

4 |
-------------------------------------------------------------------------------- /transports/web/views/partials/light.html: -------------------------------------------------------------------------------- 1 | 
2 |

Light Device

3 |

Display here the light device UI controls and events

4 |
-------------------------------------------------------------------------------- /transports/web/views/tutorials.handlebars: -------------------------------------------------------------------------------- 1 |  2 |
3 |
4 |

Tutorials

5 |
6 |
7 | --------------------------------------------------------------------------------