W3C Web of Things implementation on NodeJS.
Visit http://www.thingweb.io for a practical node-wot API usage, hands-on tutorials or additional information.
Useful labels: question | good first issue
- License
- Implemented/supported features
- Prerequisites
- How to get the library
- No time for explanations - show me a running example!
- How to use the library
Dual-licensed under both
Pick one of these two licenses that fits your needs. Please also see the additional notices and how to contribute.
- HTTP ✔️
- HTTPS ✔️
- CoAP ✔️
- CoAPS ✔️
- MQTT ✔️
- Firestore ✔️
- Websocket ➕ (Server only)
- OPC-UA ➕ (Client only)
- NETCONF ➕ (Client only)
- Modbus ➕ (Client only)
- M-Bus ➕ (Client only)
Note: More protocols can be easily added by implementing ProtocolClient
, ProtocolClientFactory
, and ProtocolServer
interface.
Note: the bindings for binding-fujitsu and binding-oracle were removed after v0.7.x
due to lack of maintainers.
- JSON ✔️
- Text (HTML, CSS, XML, SVG) ✔️
- Base64 (PNG, JPEG, GIF) ✔️
- Octet stream ✔️
- CBOR ⏲️
- EXI ⏲️
Note: More mediaTypes can be easily added by implementing ContentCodec
interface.
const ContentSerdes = require('@node-wot/core').ContentSerdes
const JsonCodec = require('@node-wot/core').JsonCodec
// e.g., assign built-in codec for *new* contentType
let cs = ContentSerdes.get();
cs.addCodec(new JsonCodec("application/calendar+json"));
// e.g., assign *own* MyCodec implementation (implementing ContentCodec interface)
cs.addCodec(new MyCodec("application/myType"));
All systems require:
Meet the node-gyp requirements:
- Python v3.6, v3.7, or v3.8
- make
- A proper C/C++ compiler toolchain, like GCC
Install the Windows build tools through a CMD shell as administrator:
npm install -g --production windows-build-tools
WSL: Windows Services for Linux should follow Linux instructions.
Meet the node-gyp requirements:
xcode-select --install
To use node-wot as a browser-side JavaScript Library, the browser needs to support ECMAScript 2015. Supported browsers include:
- Microsoft Edge 15 and later
- Firefox 54 and later
- Chrome 58 and later
- Safari 10 and later
Using a browser with only ES5 support (eg. IE 11) might be possible if you add polyfills.
You can install node-wot in the following ways:
- As a normal dependency (i.e., like loadsh). In this case, you are embedding a servient inside your application.
- As a CLI to run scripts. In this case, your application is running inside the default servient.
If you want to use node-wot as a library in your Node.js application, you can use npm to install the node-wot packages that you need. To do so, cd
inside you application folder, and run:
npm i @node-wot/core @node-wot/binding-http --save
Now, you can implement a thing as follows:
// server.js
// Required steps to create a servient for creating a thing
const Servient = require('@node-wot/core').Servient;
const HttpServer = require('@node-wot/binding-http').HttpServer;
const servient = new Servient();
servient.addServer(new HttpServer());
servient.start().then((WoT) => {
// Then from here on you can use the WoT object to produce the thing
// i.e WoT.produce({.....})
});
A client consuming a thing can be implemented like this:
// client.js
// Required steps to create a servient for a client
const { Servient, Helpers } = require("@node-wot/core");
const { HttpClientFactory } = require('@node-wot/binding-http');
const servient = new Servient();
servient.addClientFactory(new HttpClientFactory(null));
const WoTHelpers = new Helpers(servient);
WoTHelpers.fetch("http://localhost:8080/example").then(async (td) => {
try {
servient.start().then(async (WoT) => {
// Then from here on you can consume the thing
// i.e let thing = await WoT.consume(td) ...
});
}
catch (err) {
console.error("Script error:", err);
}
}).catch((err) => { console.error("Fetch error:", err); });
You can then start the applications with node by running node server.js
and node client.js
.
You can alternatively use node-wot via its command line interface (CLI). Please visit the CLI tool's Readme to find out more.
Clone the repository:
git clone https://github.com/eclipse/thingweb.node-wot
Go into the repository:
cd thingweb.node-wot
Install root dependencies (locally installs tools such as typescript):
npm ci
Use tsc
to transcompile TS code to JS in dist directory for each package:
Note: This step automatically calls npm run bootstrap
.
npm run build
Make all packages available on your local machine (as symlinks). You can then use each package in its local version via npm link <module>
instead of npm install <module>
(see also https://docs.npmjs.com/cli/link).
sudo npm run link
(On Windows omit sudo
)
To evolve the Scripting API in development, you need to use a locally changed version of the wot-typescript-definitions. Use npm link for this as well:
git clone https://github.com/w3c/wot-scripting-api/
cd wot-scripting-api/typescript/
sudo npm link
(On Windows omit sudo
)
In each node-wot package, link the local version made available in the previous step:
sudo npm link wot-typescript-definitions
(On Windows omit sudo
)
To reduce the size of the installation from about 800 MByte down to about 200 MByte, you can run the following commands (currently only tested on Linux):
npm prune --production
- Build error about
No matching version found for @node-wot/...
or something aboutmatch
- try
npm run unlock
from project root before building
- try
sudo npm run link
does not work- try
npm run unlock
from project root before calling[sudo] npm run link
- try
npm link
in each package directory in this order: td-tools, core, binding-*, cli, demo-servients
- try
- Error mesage for
npm link @node-wot/<module>
ELOOP: too many symbolic links encountered, stat '/usr/lib/node_modules/@node-wot/<module>
- Run
npm run link
inthingweb.node-wot
again - Remove
node_modules
in the targeted project - Remove all
@node-wot/<module>
dependencies in yourpackage.json
- Run
npm i
again - Install the packages with
npm link @node-wot/<module>
- Run
- Build error around
prebuild: npm run bootstrap
- This has been seen failing on WSL. Try using a more recent NodeJS version
Alternatively, node-wot can be built as a Docker image with the Dockerfile
.
Make sure you are under linux or under WSL if you are running on Windows.
Clone the repository:
git clone https://github.com/eclipse/thingweb.node-wot
Go into the repository:
cd thingweb.node-wot
Build the Docker image named wot-servient
from the Dockerfile
:
npm run build:docker
Run the wot-servient as a container:
docker run --rm wot-servient -h
node-wot can also be imported as browser-side library. To do so, include the following script
tag in your html:
<script src="https://cdn.jsdelivr.net/npm/@node-wot/browser-bundle@latest/dist/wot-bundle.min.js"></script>
In the browser, node wot only works in client mode with limited binding support. Supported bindings: HTTP / HTTPS / WebSockets You can access all node-wot functionality through the "Wot" global object:
var servient = new Wot.Core.Servient();
var client = new Wot.Http.HttpClient();
Run all the steps above including "Link Packages" and then run this:
wot-servient -h
cd examples/scripts
wot-servient
Without the "Link Packages" step, the wot-servient
command is not available and node
needs to be used (e.g., Windows CMD shell):
# expose
node packages\cli\dist\cli.js examples\scripts\counter.js
# consume
node packages\cli\dist\cli.js --client-only examples\scripts\counter-client.js
- Go to http://localhost:8080/counter and you'll find a thing description
- Query the count by http://localhost:8080/counter/properties/count
- Modify the count via POST on http://localhost:8080/counter/actions/increment and http://localhost:8080/counter/actions/decrement
- Application logic is in
examples/scripts/counter.js
First build the docker image and then run the counter example:
# expose
docker run -it --init -p 8080:8080/tcp -p 5683:5683/udp -v "$(pwd)"/examples:/srv/examples --rm wot-servient /srv/examples/scripts/counter.js
# consume
docker run -it --init -v "$(pwd)"/examples:/srv/examples --rm --net=host wot-servient /srv/examples/scripts/counter-client.js --client-only
- The counter exposes the HTTP endpoint at 8080/tcp and the CoAP endpoint at 5683/udp and they are bound to the host machine (with
-p 8080:8080/tcp -p 5683:5683/udp
). - The counter-client binds the network of the host machine (
--net=host
) so that it can access the counter thing's endpoints. --init
allows the containers to be killed with SIGINT (e.g., Ctrl+c)-v "$(pwd)"/examples:/srv/examples
mounts theexamples
directory to/srv/examples
on the container so that the node inside the container can read the example scripts.
An example of how to use node-wot as a browser-side library can be found under examples/browser/index.html
.
To run it, open examples/browser/index.html
in a modern browser, and consume the test Thing available under http://plugfest.thingweb.io:8083/testthing
to interact with it.
The JavaScript code that uses node-wot as a library to power this application can be found under: examples/browser/index.js
This library implements the WoT Scripting API:
- Editors Draft in master
- Working Draft corresponding to node-wot release versions
Additionally, you can have a look at our API Documentation.
To learn by examples, see examples/scripts
to have a feeling of how to script a Thing or a Consumer.
The package td-tools provides utilties around ThingDescription (TD) tooling:
- ThingDescription (TD) parsing
- ThingModel (TM) tooling
- Asset Interface Description (AID) utility
- ...
Logging in node-wot is implemented via the debug
package.
This allows users to enable log messages for specific logging levels (info
, debug
, warn
, or error
) or packages.
Which log messages are emitted is controlled by the DEBUG
environment variable.
In the following, we will show a couple of examples for its usage using wildcard characters (*
).
Note, however, that the syntax for setting an environment variable depends on your operating system and the terminal you use.
See the debug
documentation for more details on platform-specific differences.
First, you can enable all log messages by setting DEBUG
to a wildcard like so:
DEBUG=* npm start
To only show node-wot
-specific logging messages, prefix the wildcard with node-wot
:
DEBUG=node-wot* npm start
To only show a specific log level, use one of info
, debug
, warn
, or error
as the suffix.
Note in this context that you can provide multiple values for DEBUG
.
For example, if you want to show only debug
and info
messages, you can use the following:
DEBUG='*debug,*info' npm start
Finally, you can choose to only display log messages from a specific node-wot
package.
For example, if you only want to see log messages for the core
package, use the following:
DEBUG=node-wot:core* npm start
Using the log levels above, you can also apply more fine-grained parameters for logging.
For instance, if you only want to see error
messages from the binding-coap
package, use this:
DEBUG=node-wot:binding-coap*error npm start
Using NPM, you can install NodeJS independent from the usually outdated package managers such as apt. This is nicely done by n:
sudo npm cache clean -f
sudo npm install -g n
To get the "stable" version:
sudo n stable
To get the "latest" version:
sudo n latest
Finally, make the node command available through:
sudo ln -sf /usr/local/n/versions/node/<VERSION>/bin/node /usr/bin/node
details
Run npm publish --workspaces
in root node-wot folder.
- Delete
package-lock.json
file - Delete any local cache (like
node_modules
folders etc.) - Run
npm install
- Run
npm dedupe
(see eclipse-thingweb#765 (comment))