W3C Web of Things: The revolution is here

The missing interoperability between devices is hindering the development of IoT.
An increasing amoung of systems are vendor locked and are not able to talk to each other.
In 2014 the W3C took over this challenge and formed the Web of Things Working Group.
The same organization which already standardizes HTML, CSS, SVG and other
important standards used in the Web today.
In April 2020 the Web of Things Architecture and Thing Description became recommended standards by the W3C.
The standards are embraced by well known companies in the industry,
such as Panasonic, Hitachi, Intel and Siemens.

The Web of Things (WoT) doesn’t aim to replace any standard.
The WoT standards are the glue to enable interoperability.
The best of all: The standards are open and free to use for everyone.
Even the process and protocols are transparent and open.
The W3C is well known to be vendor neutral. Any organization can join the W3C.
This guarantees the maximal adoption possible.

Let’s take a look into the Web of Things

The entry point for the Web of Things is the Thing Description (TD).
In a way it is similar to the index.html for the World Wide Web.
As the name suggests it contains all the metadata and API description of an IoT device.
Details of where to get the TD from is described in the
WoT discovery document.
It is also possible to store WoT TDs of multiple devices in a TD directory.
The directory makes it possible to search and filter TDs from multiple devices at once.

Interaction Affordances

The APIs of the device are described in the InteractionAffordances.
There are three types of InteractionAffordances in the Thing Description.
ActionAffordances are used to describe available functions on the device.
This could be the trigger for a sprinkler system or some other functionality.
PropertyAffordances expose the state of device. The states can be read and written.
EventAffordances describe events. This can be alerts or continues event streams.
Overall InteractionAffordances make it possible to describe a wide range of use-cases.
The input and output can be defined in the forms of each InteractionAffordance.
As well as the API endpoints.

A practical example

Let’s take a practical example of a WoT TD.
Given is a simple weather station with its Thing Description.

{
   "id":"urn:dev:weather_sensor-23451",
   "title":"Weather station",
   "description":"Weather station with humidity, pressure and temperature",
   "@context":[
      "https://www.w3.org/2019/wot/td/v1"
   ],
   "securityDefinitions":{
      "nosec_sc":{
         "scheme":"nosec"
      }
   },
   "security":[
      "nosec_sc"
   ],
   "properties":{
      "temperature":{
         "type":"object",
         "properties":{
            "temperature":{
               "type":"number",
               "unit":"°C"
            }
         },
         "title":"Temperature",
         "forms":[
            {
               "href":"/properties/temperature"
            }
         ]
      },
      "humidity":{
         "type":"object",
         "properties":{
            "humidity":{
               "type":"number",
               "unit":"%",
               "minimum":0,
               "maximum":100
            }
         },
         "readOnly":true,
         "title":"Humidity",
         "forms":[
            {
               "href":"/properties/humidity"
            }
         ]
      },
      "pressure":{
         "type":"object",
         "properties":{
            "pressure":{
               "type":"number",
               "unit":"hPa"
            }
         },
         "readOnly":true,
         "title":"Pressure",
         "forms":[
            {
               "href":"/properties/pressure"
            }
         ]
      }
   },
   "base":"coap://[2003:f0:2701:c700:260f:c4ff:feaf:5b8c]"
}

The base has the prefix coap:.
Therefore the APIs are available under the CoAP protocol.
The device can support multiple protocols if needed.
Details about discoverability are defined in the WoT discovery document.

This device only has PropertyAffordances defined.
They are defined in properties property of the JSON object.

Let's take a deeper look into the first PropertyAffordance.
The PropertyAffordance temperature is defined as the following

{
   "temperature":{
      "type":"object",
      "properties":{
         "temperature":{
            "type":"number",
            "unit":"°C"
         }
      },
      "title":"Temperature",
      "forms":[
         {
            "href":"/properties/temperature"
         }
      ]
   }
}

The key of the affordance can become important when you consume the TD with a WoT TD library.
You can also semantically tag the Property Affordance.
One example mentioned in the WoT TD specification is saref.
The temperature is available under the URL
coap://[2003:f0:2701:c700:260f:c4ff:feaf:5b8c]/properties/temperature.

type indicates what data type is returned. In this case it is an object.
The default contenType in the form is defined as application/json
according to the WoT TD 1.0 §5.4.
Therefore we are dealing here with JSONs.
When another serialization format is used the contentType has to be set accordingly.
The details of how to interprete it for other serialization format are defined as Web of Things Binding Templates.

Since this example uses JSONs the interpretation is pretty straight forward.
We have a JSON object with one property called temperature.
This property contains a number as unit °C.

When we request the URL we get the following response

> ./coap-client -m get coap://[2003:f0:2701:c700:260f:c4ff:feaf:5b8c]/properties/temperature
{
  "temperature": 19.39
}

Consuming the data

When it comes to libraries there are several options.
There is an overview of tools and libraries on the website of the
Web of Things Working Group.
Let's take a short look into the node-wot Javascript library.

const servient = new Servient()
servient.addClientFactory(new CoapClientFactory())

const wotHelper = new Helpers(servient)
Promise.all(
  [
    wotHelper.fetch("coap:[2003:f0:2701:c700:260f:c4ff:feaf:5b8c]/.well-known/wot-thing-description"),
    servient.start()
  ]
).then((values) => {
  const td = values[0]
  const WoT = values[1]

  return WoT.consume(td).then((thing) => {
    // read the property "temperature" and print the value
    return thing.readProperty("temperature").then((s) => {
        console.log(s.value())
    })
  });
}).catch((err) => { console.error("Fetch error:", err) })

As you can see the Web of Things also reduces the development effort dramatically
due to the standardized way of descripting device metadata and APIs.
No complicated glueing of different libraries in order to consume the device necessary.
Libraries are able to implement a generalized way to handle Thing Descriptions.
This also enables to build genalized gateway solutions.
Due to the nature of standards generalized software solutions can replace vendor-dependend implementatios.
The node-wot library implements the Web of Thing Scripting API.
The Web of Things Scripting API is designed to get eventually implemented by browser vendors.

I hope this gives you a good introduction into the Web of Things.
If you want to have more practical examples, you can find a couple of written tutorials on bind.system.

Select a repo