This article is a tutorial which considers a fictional smart coffee machine in order to demonstrate the capabilities of Web of Things (WoT) and the usage of node-wot API. In the world of Web of Thing properties, actions and events provided by a Thing are called Property Affordances, Action Affordances and Event Affordances, respectively. The difference of each becomes clear as we proceed the tutorial. So, we imagine a smart coffee machine which provides the following Property Affordances:
allAvailableResources- that is a current level of all available resources (i.e. water, milk, chocolate and coffee beans) given as an integer percentage for each particular resource. This data is read-only and is obtained from the machine’s sensors but can also be set manually via the
availableResourceLevelproperty (next one) in case the sensors are broken.
availableResourceLevel- that is a current level of a particular resource, which should be specified as a query string (called
uriVariablesin node-wot). This data is obtained from the previous property (
allAvailableResources). The difference is in usage of
uriVariablesand that this property is also writable, so that it can be used to override the values of
possibleDrinks- a read-only list of possible drinks in general. Doesn’t depend on the available resources.
servedCounter- the total number of served beverages. This property is writable. The data is obtained from the machine but can also be set manually (thus, writable). The case for that is explained below.
maintenanceNeeded- a boolean value showing whether the machine needs a maintenance. The property is observable, which means in WoT that a user can get notified every time the value of this property changes. Automatically set to true when the
servedCounterproperty exceeds 1000.
schedules- a read-only array containing scheduled tasks, i.e. a task which should be performed according to a specific schedule.
The idea behind
maintenanceNeeded is that, every time
servedCounter exceeds 1000 the
maintenanceNeeded flag is set to true.
And since this value is observable a “maintainer” gets notified, who then comes and performs the maintenance of the machine, and afterwards sets the
maintenanceNeeded to 0 and false, respectively.
The smart coffee machine has also the following Action Affordances:
makeDrink- make a drink from the list of possible beverages. Accepts drink id, size and quantity as
uriVariables. Brews one medium americano if no
setSchedule- add a scheduled task to the
schedulesproperty. Accepts drink id, size, quantity, time and mode as body of a request (i.e. a request payload). Assumes one medium americano if not specified, but time and mode are mandatory fields. Notice that, even though the
schedulesproperty is read-only, it’s being modified through the
setScheduleaction. That’s the same principle as creating setters for private properties in object-oriented programming languages.
Finally, the coffee machine has the following Event Affordances:
outOfResource- an out-of-resource event. Emitted when the available resource level is not sufficient for a desired drink.
Two main functionalities of node-wot is creating a WoT Thing and interacting with another WoT Thing.
These functionalities can also be combined to have a Thing interacting with other Things.
Creating a WoT Thing is called exposing or producing a Thing.
In order to expose our smart coffee machine we need to invoke
produce method of the WoT object.
It takes a Thing Description (TD) as the only parameter.
Note that, this TD can be set only partially.
The full TD will then be produced by the
produce method, assuming default data for non-specified TD terms and creating default protocol bindings (HTTP and CoAP).
This produced TD can then be used by other Things or clients to interact with the Thing.
The full script is available at node-wot GitHub repository.
Note that, all affordances (i.e. property, action and event) should be added withing the
After producing the Thing, we need to initialize the properties and all required handlers.
This is done by chaining
.then method after
Property initialization looks as follows.
In case a property needs a write handler, we can set the according
See an example below.
And then we are ready to initialize its value.
We also want to override write and read handlers for
availableResourceLevel property, since we need to utilize
As it has already been mentioned,
maintenanceNeeded property is observable, meaning we can could get notified when its value changes. For that, we need to provide a callback for the
Done with the Property Affordances! Now we need to set up action handlers, which proceed when another Thing or client invokes the action.
Notice, how in case of insufficient resources the
outOfResource event is emitted.
Note also that
uriVariables is being passed into options variable as a second argument of the handler.
The first argument
params contains a request body (i.e. payload of a request).
Another handler is for
As mentioned above, here we use the payload of a request, therefore we utilize the
Done with the Action Affordances! Now our final affordances, that is Event Affordances. We can specify a handler for an event, which then gets executed whenever the event is emitted. In node-wot this process is called “subscribing” for an event. Although it is possible to create event handlers in the producer Thing, usually it is done on the client side. So, the producer (server) only emits a particular event and the client is responsible for handling it. Below in the client part we will cover this process.
Now, finally, expose the Thing!
So far we are done with the “producer” Thing and now our smart coffee machine can be interacted via any HTTP or CoAP client (default protocol bindings as mentioned above).
The produced Thing Description is available at http://127.0.0.1:8080/smart-coffee-machine for HTTP and coap://127.0.0.1:5683/smart-coffee-machine for CoAP.
By default, in HTTP binding the GET method is used for reading properties, PUT for writing and POST for invoking actions.
So, for example the value of
allAvailableResources property can be read as:
The value of
availableResourceLevel property can be set as:
setSchedule actions can be invoked as:
As we already mentioned, note that one uses query string and the other one uses a payload.
We can also create a consumer Thing (i.e. a client) for our smart coffee machine using the node-wot API.
In order to create a consumer Thing, we need to invoke
fetch method of the WoTHelpers object giving it an exposed Thing Description as the only parameter, and then invoke
consume method of the WoT object as follows.
The full “client” script is available at node-wot GitHub repository.
Notice that, we are awaiting asynchronous functions to complete before proceeding, which is quite logical here.
Remember that we need the
async keyword in the outer function in order to use
await inside the function.
We could also chain the asynchronous
consume method with other methods using
But let’s stick with
async/await for our example.
A property can be read using
A property can be written using
Notice on usage of
In the same manner they can be used when reading properties which utilize
It’s also possible to set a client-side handler for observable properties.
Notice that, here we don’t need to await for a function to complete, since observing a property is a persistent action.
We can invoke an action using
Notice on usage of
They are passed as a third argument, whereas the second one is the payload of a request.
This can be well noted on invoking of
As it is already mentioned above, we also want a client to subscribe for events emitted from the producer Thing.
Again, here we don’t need to await for a function to complete, since subscribing for an event is a persistent action.
As it is mentioned above, these example scripts are available at node-wot GitHub repository. In order to run them do the following:
Now you can run the scripts as follows:
If you want to add your own example scripts be sure to follow the workflow.
In case you want to just consume a Thing you can use a tool like the Browsified node-wot. It allows you to interact with Things right from your browser. There is a deployed smart coffee machine producer Thing at http://plugfest.thingweb.io:8083/smart-coffee-machine that you can consume. You can also see its property values in real-time at http://plugfest.thingweb.io/examples/smart-coffee-machine.html.
Currently, node-wot supports different security schemas.
In the example above we have used the
NoSecurityScheme, as it is assumed by default if no security scheme is explicitly used.
Node-wot also supports oAuth 2.0, so let’s extend this tutorial with the same coffee machine having oAuth 2.0 authorization.
Extend the Thing Description within the
produce method with the following lines (add
Now if we run the producer and the consumer Things as before that will fail. The reason is simple - the client is not authorized. Let’s fix it.
We need an additional configuration file which will contain the appropriate credentials. The configuration file contains the following and is available as smart-coffee-machine-client.conf.json:
The first setting allows self-signed certificates, which is okay for testing and development purposes.
The other setting provides the credentials in a form of “Thing id - credentials” pair.
We will be using the oAuth 2.0 test server which is equipped with node-wot, and it expects exactly these
Now run the test oAuth server:
You should see a message saying
Now in a different terminal run the coffee machine producer Thing as usual:
Finally, from the third terminal run the coffee machine consumer Thing providing it with the configuration file we have created:
Now the client interacts with the smart coffee machine as before since it is authorized by the oAuth server.