├── .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 |
--------------------------------------------------------------------------------