Copyright © 2015 EVRYTHNG. This document is available under the W3C Document License. See the W3C Intellectual Rights Notice and Legal Disclaimers for additional information.
This document proposes the basis of a common model to describe the virtual counterpart of physical objects in the Web of Things. It defines a model and Web API for Things to be followed by anyone wanting to create a product, device, service, or application for the Web of Things. This document considers the definition of the Web of Things (WoT) proposed in [WoTPaper] and [WoTBook], i.e., the Application layer of the Internet of Things. The model and protocols proposed here aim at making the interaction between Things in the Internet of Things accessible through Web standards to facilitate the implementation of Web applications making use or retrieving data from real-world objects.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document is based on work undertaken within the COMPOSE European project and submitted to W3C as a possible starting point for a future Working Group chartered to work on the Web of Things.
By publishing this document, W3C acknowledges that the Submitting Members have made a formal Submission request to W3C for discussion. Publication of this document by W3C indicates no endorsement of its content by W3C, nor that W3C has, is, or will be allocating any resources to the issues addressed by it. This document is not the product of a chartered W3C group, but is published as potential input to the W3C Process. A W3C Team Comment has been published in conjunction with this Member Submission. Publication of acknowledged Member Submissions at the W3C site is one of the benefits of W3C Membership. Please consult the requirements associated with Member Submissions of section 3.3 of the W3C Patent Policy. Please consult the complete list of acknowledged W3C Member Submissions.
GET
, POST
, PUT
and DELETE
HTTP verbs200
, 400
,
500
GET
on its root URLOPTIONS
verb for each of its resourcesThis section is non-normative.
The following guidelines and recommendations aim at ensuring interoperability across all entities on the Web of Things. Unlike custom (non-Web) protocols used for machine-to-machine communications that create a “parallel universe” to the existing Web; the Web of Things is designed to be seamlessly integrated to the existing Web so it can fully leverage its infrastructure and standards to minimize integrations across applications and systems.
The proposal is composed of three sub-parts:
While the Web Things Requirements are described with the HTTP and WebSockets protocols using JSON because they are well supported on the Web of browsers, the Web Thing Model can also be applied to describe the models and interactions of Things supported via other RESTful protocols such as CoAP [RFC7252] or even pub/sub protocols such as [MQTT].
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, and SHOULD are to be interpreted as described in [RFC2119].
This specification has two classes of products:
A Web Thing conforms to this specification if it follows the statements defined in 5. Web Things requirements.
An Extended Web Thing conforms to this specification if it follows the statements defined in 5. Web Things requirements and 6. Web Things model.
The following terms are considered in this proposal:
This part looks into the different ways of integrating physical objects to the Web to make them Web Things. Once a pattern has been choosen, the server of a Web Thing should follow the Web Things Requirements and the resources and payloads it uses should follow the Web Things Model .
Some physical entities might not expose a Web API themselves for various reasons (e.g., a ZigBee sensor node, or a heart rate monitor accessible over Bluetooth only), in which case they are not Web Things as such, but they can use another Web Thing as a proxy or gateway to provide a Web API for them, therefore turning them into Web Things.
While the three integration patterns described below need to be taken into account, it is worth noting that the requirements and model apply regardless of the integration pattern of choice.
In the most straightforward case, a Web Thing is simply a Web API that Clients send requests to. In some cases, the Client and the Web Thing can be on the same network or on different networks. In both cases, you are sending the same request to a Web Thing. The only difference is the URL to which you are sending the request (and obviously how the Web Thing gets the message).
Gateway-based connectivity is used when a Thing cannot offer a Web API directly. In this case an intermediate Web Thing - the gateway - exposes a Web API on the Thing's behalf. The Web Thing therefore acts as a proxy for the Thing (or gateway depending on the complexity/layer of the translation).
This third case is similar to 4.2 Gateway-Based Connectivity. However, in this case the gateway is a cloud service and not another device in situ.
This part defines a set of rules for implementing Web Things. It assumes that an Integration Pattern was chosen.
This section defines the Level 0 requirements – all of which MUST be in place in any Web Thing implementation, as all Clients will expect these constraints.
All Web Things MUST support communication over HTTP/1.1 [RFC2616]. When possible, Web Things SHOULD also support HTTP/2 [RFC7540].
HTTP/1.1 is the most widely spread protocol over the Web and virtually any HTTP client or server implementation supports it, therefore it is likely that the majority of clients might not support HTTP/2 as of yet. This can be implemented directly on the Web Thing or can be provided via a proxy (see Integration Patterns).
A Web Thing MUST have a so-called “root resource” identified by a HTTP URL (uses the HTTP
protocol, therefore starts with http://
or https://
) that acts as the entry
point for the Web Thing and enables the interaction with it. This root resource makes the Web
Thing both uniquely identifiable and addressable over a network so that Clients can interact with it.
If the Web Thing is a device connected on a LAN (e.g. a printer, a lamp, etc.), the root URL of a Web Thing SHOULD be its IP address and standard HTTP port, so that, knowing only the IP address of a networked device that is a Web Thing, a Client can send an HTTP GET request on that IP address over the default port (80 for HTTP, 443 for HTTPS) to retrieve a representation of the Web Thing. This feature is envisioned to facilitate discovery of devices at the network level, without requiring an additional protocol.
A Web Thing does not need to be publicly accessible over the Internet, as some Web of Things scenarios might only work within a local area network (LAN) as defined above. This means a root URL does not need to be public and can be simply the local IP address of a device. The Root URL of a Web Thing is referred to as {wt} throughout this document.
http://gateway.api.com/devices/TV http://kitchen-raspberry.device-lab.co.uk https://192.168.10.10:9002 https://kitchen:3000/fridge/root
GET
, POST
, PUT
and DELETE
HTTP verbs
The Web of Things aims to maximise interoperability by exposing the services of Things using REST
[REST]. For this idea to come to reality, supporting certain HTTP verbs of the specification is
required. Considering that the REST paradigm is based on resources and CRUD operations on them, a Web Thing MUST
support GET
for reading operations, POST
for creation, PUT
for
updates and state changes, and DELETE
for removal.
200
, 400
,
500
Proper usage of HTTP/1.1 error codes is advisable. However, considering that some devices are restricted, only the following subset is mandatory:
A Web Thing MUST always accept a valid JSON document [RFC7159] as input payload for requests and
always return a JSON representation when requested. If no Accept:
HTTP header is specified
in the request (or if the format is unknown or not supported), the Web Thing SHOULD return an
appropriate error code, but it also MAY return JSON as default. Fields in JSON objects should follow the camelCase convention starting with a lowerCase letter (e.g., backColor) or a special character (e.g., _customRelation).
A Web Thing MAY support additional formats.
A consequence of supporting JSON is that UTF-8 is the default encoding for payloads (see Character Encoding in the JSON specification [RFC7159])
GET
on its root URL
Because they all have a unique root URL and sometimes it is all we know about them, Web Things MUST respond to HTTP GET
requests on their root URL
with their basic representation, so that Clients can use and understand it.
The basic representation returned by an Extended Web Thing is defined in 6. Web Things model
Unless there are technical or practical limitations for not adhering to Level 1 constraints, Web Things SHOULD support the following constraints.
Ideally, Web Thing SHOULD support secure connections with HTTP over TLS [RFC5246]. The ideal case for security is to support only HTTP over TLS. Web Thing that are exposed on the Internet MUST always implement HTTP over TLS.
Web Things MAY use other security mechanisms if they want to (in addition or in place of HTTPS). In some cases, it might be impossible or impractical to implement HTTPS over TLS (for example in pure intranet scenario), in which case using another security mechanism is still highly recommended.
Clients SHOULD be able to subscribe to notifications from Web Thing using a Publish/Subscribe (Pub/Sub) pattern implemented using the WebSocket protocol [RFC6455].
If possible, every Web Thing SHOULD implement the Web Things Model. It is not essential to use it for a device to be part of the Web of Things, but implementing it will lead to a higher degree of interoperability.
An Extended Web Thing fulfills this requirement by definition. In other words, while this specification acknowledges the usefulness of the Web Thing level to accommodate legacy devices and very restricted scenarios, implementers are encouraged to implement Extended Web Things.
By default, all PUT, POST, and DELETE requests to a Web Thing should not return the payload of the object that was created/modified, therefore should return a 204 NO CONTENT
response and no response body.
To interact with a Web Thing, a Client needs to know how to use a Web Thing. The format of the API documentation is left to implementers, but should describe the resources offered, the verbs they support, the payloads accepted and returned, and possible status codes that can be returned and when.
A Web Thing MAY support these rules, but is not expected to. It depends on the device capabilities and other implementation aspects.
OPTIONS
verb for each of its resourcesAny resource of a Web Thing should implement the OPTIONS verb to describe what verbs are supported by each resource.
A Web Thing MAY provide additional representations of its data and descriptions. JSON is the only mandatory representation. Additional formats are up to the implementers if needed for additional purposes. The discovery of additional representation SHOULD be supported via HTTP content-negotiation [content-negotiation].
A Web Thing MAY expose a UI in HTML, CSS and JavaScript. For example, the UI may be a HTML widget to integrate the Web Thing in dashboard environments.
A Web Thing MAY provide additional meta data to precisely describe the meaning of individual building blocks of a model in a machine-understandable way.
This part defines the model, JSON payloads and REST API that an Extended Web Thing MUST implement to allow Clients to automatically discover and use its properties. It assumes an Integration Pattern and that the Web Thing follows the Web Things Requirements. As such, the Web Things model is a contract between clients and Things in the IoT.
An Extended Web Thing has a root resource accessible via an HTTP URL and supports HTTP GET
requests on that URL (see 5.1.2 R0.2 – A Web Thing MUST have a root resource accessible via an HTTP URL
and 5.1.6 R0.6 – A Web Thing MUST support GET on its root URL).
An Extended Web Thing MUST create a URL endpoint for all the resources that it exposes, including itself. Relative URLs are to be resolved against the URL of the resource that includes them. Implementers are encouraged to create a logical tree structure for resources and to use relative URLs to keep JSON payloads short, for instance:
URL | Description |
---|---|
{wt}
| The root resource URL |
{wt}/model/
| The model of a Web Thing |
{wt}/properties/
| The list of properties |
{wt}/properties/{id}
| A specific property |
{wt}/actions/
| The list of actions |
{wt}/actions/{id}
| A specific action |
{wt}/actions/{id}/{actionId}
| A specific execution of an action |
{wt}/.../
| ... |
In response to an HTTP GET
request on one of its resources (including the root resource), an
Extended Web Thing MUST return a JSON representation of that resource that follows the JSON schema
defined in the table below:
Field name | Type | Description |
---|---|---|
id |
String | The URL of this resource following the URI format [RFC3986]. Relative URLs are resolved against
the URL of the enclosing resource.
This field is required. |
createdAt |
String | Timestamp when this resource was created, following the ISO8601 notation [ISO8601]. |
updatedAt |
String | Timestamp when this resource was last updated, following the ISO8601 notation [ISO8601]. |
name |
String | A short human-readable name for the resource. |
description |
String | A human-readable description of the resource. |
tags |
[String] | An array of tags. |
customFields |
Object | A JSON object with key-value pairs to store custom information about this resource (e.g. {"key":"value",...}). |
links |
Object | A JSON object that lists the sub-resources that this resource links to. See 6.2 Links for details. |
{ "id": "myCar", "name": "My great car", "description": "This is such a great car.", "createdAt": "2012-08-24T17:29:11.683Z", "updatedAt": "2012-08-24T17:29:11.683Z", "tags": [ "cart", "device", "test" ], "customFields": { "size": "20", "color": "blue" }, "links": { "model": { "link": "model/", "title": "Model this Web Thing." }, "properties": { "link": "properties/", "title": "Properties of this Web Thing." }, "actions": { "link": "actions/", "title": "Actions of this Web Thing." }, ... } }
The JSON response MAY contain additional fields, depending on the type of resource being considered, check the 6.4 Resources for details.
GET {wt}/properties/acceleration?page=3&perPage=100
Extra pagination data is sent in response headers.
Result-Count: 562 Link: <http://webofthings.io/properties/acceleration?page=3&perPage=100<; rel="next", <http://webofthings.io/properties/acceleration?page=56&perPage=100<; rel="last"
Result-Count
header contains the total number of results.
The pagination info is included in the Link header.
rel value | Description |
---|---|
next |
The URL of the last page of results. |
first |
The URL of the first page of results. |
prev |
The URL of the immediate previous page of results. |
A resource may link to a number of sub-resources. To enable the discovery of these sub-resources (as
required by the HATEOAS constraint of the
REST application architecture), an Extended Web Thing SHOULD expose sub-resources associated with
a given resource using the HTTP Link
header field [RFC5988].
In particular, each link is defined by a relation type (the "link type"), the actual URL of the sub-resource (the "link"), and a human-readable identifier for the relation (the "title"). Relation types defined in [RFC5988] may be used to characterize the relation with the sub-resource. Additionally, the Web Things model defines the following relation types:
Relation name | Description | Section |
---|---|---|
model |
A link to an Extended Web Thing compliant description of a resource. | Model Resource |
properties |
The properties of this resource. | Properties Resource |
actions |
The actions that this resource can perform. | Actions Resource |
things |
The Web things proxied by this resource (if applicable). | Things Resource |
subscriptions |
The endpoint to manage subscriptions to this resource. | Subscriptions Resource |
type |
Can be used to indicate that the context resource is an instance of the resource identified by the target external URL. | |
product |
A link to authoritative product information for this Web Thing. | Product |
help |
A link to the online manual page for this Web Thing. | 4.8.4.4 Link type "help" |
ui |
A link to the HTML-based user interface for this Web Thing. | External Resource |
<_customRelType> |
A link to a custom resource. | Custom Resource |
An Extended Web Thing MAY use custom relation types using URLs as described in [RFC5988].
As a convention, custom relation types start with an underscore _
.
In addition to exposing them in the HTTP Header of each resource, links SHOULD be exposed from the
Model resource of a Extended Web Thing using the links
field of the JSON payload.
The keys of this object represent the relation type while each value describes the actual link as illustrated below.
{ ... "links":{ "<relType>":{ "link": "<String>", "title": "<String>" } "<_customRelType>":{ "link": "<String>", "title": "<String>" }, ... } ... }
The following fields define the actual link:
Field name | Type | Description |
---|---|---|
link |
String | The URL of the destination of the link.
This field is required. |
title |
String | A human-readable label of the destination of the link.
This field is required. |
{ "model": { "link": "model/", "title": "Model of this Web Thing." }, "properties": { "link": "properties/", "title": "Properties of this Web Thing." }, "actions": { "link": "actions/", "title": "Actions of this Web Thing." }, "product": { "link": "https://www.raspberrypi.org/products/raspberry-pi-2-model-b/", "title": "Product this Web Thing is an instance of" }, "type": { "link": "http://webofthings.org/schemas/web-thing/", "title": "External information about the instance type of this Thing" }, "help": { "link": "http://webofthings.org/docs/pi/", "title": "Documentation" }, "ui": { "link": "ui/", "title": "User Interface" }, "_myCustomLinkRelType": { "link": "custom/", "schema": "http://webofthings.org/schemas/custom.html", "title": "My custom resource" }, "_..." : {"..." : {"..."}} }
A GET
request on any resource of a Web Thing should return the list of all related resources as "Link" HTTP headers, which allows to use the same standard model regardless of the representation chosen. This is an example of the headers returned after a GET {wt}/
on the root URL of a Web Thing:
Link: <model/>; rel="model" Link: <properties/>; rel="properties" Link: <actions/>; rel="actions" Link: <product/>; rel="product" Link: <type/>; rel="type" Link: <help/>; rel="help" Link: <ui/>; rel="ui"
Several resources support values (particularly Actions and Properties).
A values
object contains the description of a set of values identified by their name. The
description includes the value type, unit, and possible concrete values that the value can take. A values
object is typically used to define the parameters a Client can use when it issues an Action or
accesses the channels of a Property.
The following fields MAY be used to describe a values
object:
Field name | Type | Description |
---|---|---|
<valueName> |
String | The identifier of this value This field is required. |
name |
String | A human-readable caption for this value. |
description |
String | A human-readable description of this value. |
type |
String | The type of this value. The supported types are integer , float , boolean ,
string .
|
unit |
String | The unit of this value using one the (case-insensitive) full names defined in the International System of Units
[SI].
Example: "meter per second squared" |
required |
Boolean | Specifies whether this value is required or optional. If omitted, the default is true .
|
minValue |
Number | The minimal concrete value that this value can take. |
maxValue |
Number | The maximal concrete value of this value |
enum |
Object | Specifies a set of concrete values that this value can take, e.g.
{"LOCK":"Locks the door.", "UNLOCK":"unlocks the door."} |
{ ... "values": { "<valueName>":{ "name":"<String>", "description":"<String>", "type":"<String>", "unit":"<String>", "required":"<Boolean>", "minValue":"<Numeric>", "maxValue":"<Numeric>" }, ... } ... }
The value name timestamp
is reserved. An Extended Web Thing MUST append a timestamp
,
set to the current date and time, whenever it creates a value unless that timestamp
is already
provided. The timestamp
field follows the ISO8601 notation [ISO8601]. The
createdAt
is different from timestamp
because it used to refer when a resource has
been created (server side information only), whereas the timestamp
indicates when a value
(property) has been measured (by the client or the Web Thing).
Ideally, an Extended Web Thing SHOULD support all end-points. The letters D,G,C
refer to 4. Web Things integration patterns and is here as an indication of which type of integration would typically implement these resources. A D
means that the resource should be implemented on Web Things using the the Direct integration pattern, a G
means the resource should be implemented when using the Gateway integration pattern, a C
means the resource should be implemented when using the Cloud integration pattern.
The URLs used in this table are indicative as an Extended Web Thing may choose to use
other URLs for them. The actual URLs are to be reported in the representation of the in
Link
HTTP Headers and in the JSON links
field as described in 6.2 Links of the Model resource.
REST URL | POST | GET | PUT | DELETE | OPTIONS | Details |
---|---|---|---|---|---|---|
{wt} |
G,C | D,G,C | D,G,C | G,C | D,G,C | Thing Resource |
{wt}/model |
- | D,G,C | G,C | - | D,G,C | Model Resource |
{wt}/properties |
G,C | D,G,C | - | - | D,G,C | Properties Resource |
{wt}/properties/{id} |
- | D,G,C | G,C | - | D,G,C | Properties Resource |
{wt}/actions |
G,C | D,G,C | - | - | D,G,C | Actions Resource |
{wt}/actions/{id} |
D,G,C | D,G,C | - | - | D,G,C | Actions Resource |
{wt}/actions/{id}/{actionId} |
- | D,G,C | - | D,G,C | D,G,C | Actions Resource |
{wt}/things |
G,C | G,C | - | - | G,C | Things Resource |
{wt}/things/{id} |
- | G,C | G,C | G,C | G,C | Things Resource |
{wt}/subscriptions |
- | D,G,C | - | D,G,C | D,G,C | Subscriptions Resource |
A Web Thing is the virtual representation of a physical object. It is the root resource of the Web Things model.
The Web Thing URL is either the root URL of the API or, in the case of a proxy for other Web Things,
the result of resolving the id
returned in the representation of the Web Things
resource.
In response to an HTTP GET
request on the root URL of a Thing
, an Extended Web Thing MUST return an object that its representation.
--> REQUEST GET {wt} <-- RESPONSE 200 OK Link: <model/>; rel="model" Link: <properties/>; rel="properties" Link: <actions/>; rel="actions" Link: <product/>; rel="product" Link: <type/>; rel="type" Link: <help/>; rel="help" Link: <ui/>; rel="ui" Link: <_myCustomLinkRelType/>; rel="_myCustomLinkRelType" { "id": "myCar", "name": "My super great car", "description": "This is such a great car.", "createdAd": "2012-08-24T17:29:11.683Z", "updatedAd": "2012-08-24T17:29:11.683Z", "tags":["cart", "device", "test"], "customFields":{ "size": "20", "color":"blue" } }
In response to an HTTP PUT
request on a Web Thing URL with a Web Thing object as
request body, an Extended Web Thing MUST either reject the request with the appropriate
status code (e.g. because the Client is unauthenticated or because the Thing is
read-only) or store the provided value(s) by updating the Web Thing. Partial updates
are authorized and result in updating the fields that were provided in the request body.
--> REQUEST PUT {wt} { "name":"My really super great car" } <-- RESPONSE 204 NO CONTENT
A Model describes the values of properties
and actions
that can
be
performed on Things.
The Model URL is the result of resolving the id
returned in the
representation of a Property against the destination URL of the properties
link
that
gave birth to it.
In response to an HTTP GET
request on the destination URL of a model
link, an Extended Web Thing MUST return an object containing the model of the Thing.
--> REQUEST GET {wt}/model <-- RESPONSE 200 OK { "id": "pi", "name": "My WoT Raspberry PI", "description": "A simple WoT-connected Raspberry PI for the WoT Label.", "tags": [ "raspberry", "pi", "WoT" ], "customFields" : { "port" : 8484 }, "links": { "product": { "link": "https://www.raspberrypi.org/products/raspberry-pi-2-model-b/", "title": "Product this Web Thing is based on" }, "properties": { "link": "/properties", "title": "List of Properties", "resources": { "temperature": { "name": "Temperature Sensor", "description": "An ambient temperature sensor.", "values": { "temp": { "name": "Temperature sensor", "description": "The temperature in celsius", "unit": "celsius", "customFields": { "gpio": 21 } } }, "tags": [ "sensor", "public", "indoors" ] }, "humidity": { "name": "Humidity Sensor", "description": "An ambient humidity sensor.", "values": { "h": { "name": "Humidity", "description": "Percentage of Humidity", "unit": "percent", "customFields": { "gpio": 21 } } }, "tags": [ "sensor", "public" ] }, "pir": { "name": "Passive Infrared", "description": "A passive infrared sensor.", "values": { "p": { "name": "Presence", "description": "Current sensor value (true=motion detected)", "type": "boolean", "customFields": { "gpio": 20 } } }, "tags": [ "sensor", "public" ] }, "leds": { "name": "LEDs", "description": "The LEDs of this device.", "values": { "1": { "name": "LED 1", "customFields": { "gpio": 17 } }, "2": { "name": "LED 2", "customFields": { "gpio": 19 } } }, "tags": [ "sensor", "public" ] } } }, "actions": { "link": "/actions", "title": "Actions of this Web Thing", "resources": { "ledState": { "values": { "ledId": { "type": "string", "required": true }, "state": { "type": "boolean", "required" : true } } } } }, "type": { "link": "http://w3c.org/schemas/webthing/", "title": "Instance type of the Pi" }, "help": { "link": "http://webofthings.org/docs/pi/", "title": "Documentation" }, "ui": { "link": "/ui", "title": "User Interface" } } }
In response to an HTTP PUT
request on a Model URL with a Model object as
request body, an Extended Web Thing MUST either reject the request with the appropriate
status code (e.g. because the Client is unauthenticated or because the Model is
read-only) or store the provided value(s) by updating the Model. Partial updates
are authorized and result in updating the fields that were provided in the request body.
Usually, the model will be hardcoded in the device and generally cannot be altered by clients. If the Web Thing is hosted on a cloud service, the model can be updated by sending an HTTP PUT
request to the same URL, with the new model document in the request body.
A Property keeps track of a set of variables about a device (its location, the temperature sensor reading, etc.).
The Property URL is the result of resolving the id
returned in the
representation of a Property against the destination URL of the properties
link
that
gave birth to it.
In response to an HTTP GET
request on the destination URL of a
properties
link, an Extended Web Thing MUST return an array of Property that the initial
resource
contains.
--> REQUEST GET {wt}/properties <-- RESPONSE 200 OK Link: <http://webofthings.io/properties>; rel="type" [ { "id":"temperature", "name":"Kitchen Temperature Sensor", "values":{ "temp":22, "timestamp":"2015-06-14T14:30:00.000Z" } }, { "id":"status", "name":"Device Status", "values":{ "status":"OK", "timestamp":"2015-06-14T14:30:00.000Z" } }, { "id":"acceleration", "name":"Acceleration", "values":{ "x":22, "y":22.56, "z":1.4, "timestamp":"2015-06-14T14:30:00.000Z" } }, { "id":"engineAngle", "name":"Engine Angle", "values":{ "theta":2, "rho":-0.1, "timestamp":"2015-06-14T14:30:00.000Z" } } ]
In response to an HTTP GET
request on a Property URL, an Extended Web
Thing MUST return an array that lists recent values of that Property.
Some Web Things might not store the history of sensor readings but only the most recent value of a given property, in which case the array will always contain one object. However, Web Things on clouds and gateway are likely to store many past values of the property, in which case they can be retrieved using pagination.
--> REQUEST GET {wt}/properties/acceleration <-- RESPONSE 200 OK Link <model/>; rel="model" [ { "x":11, "y":1, "z":-4.4, "timestamp":"2015-06-14T14:30:00.000Z" }, { "x":3.4, "y":-1, "z":-4.6, "timestamp":"2015-06-14T14:00:00.000Z" } ]
In response to an HTTP PUT
request on a Property URL with an array of
values as
request body, an Extended Web Thing MUST either reject the request with the appropriate
status code (e.g. because the Client is unauthenticated or because the Property is
read-only) or store the provided value(s) as new values for the Property. The body of the request SHOULD always be an array of values (at least one), which allows to send several property value updates within a single request.
--> REQUEST PUT {wt}/properties/temperature/ [ { "temp":24 } ] <-- RESPONSE 204 NO CONTENT Location: {wt}/properties/temperature/
A Property URL is always a collection of resources, therefore its representation is an array of individual values with different timestamps. The individual values are not adressable individually, therefore the Location:
header in response to a successful property update request SHOULD always be the Property URL itself.
In response to an HTTP POST
request on the destination URL of a properties
link, an Extended Web Thing MUST either reject the request with the appropriate status
code
or store the provided values as new values for each of the provided Properties.
--> REQUEST PUT {wt}/properties/ [ { "id":"temperature", "value":{ "temp":24, "timestamp":"2015-06-14T14:30:00.000Z" } }, { "id":"acceleration", "value":{ "x":-22, "y":2.1, "z":3, } } ] <-- RESPONSE 204 NO CONTENT Location: {wt}/properties/
On top of 6.1 Common Constructs, the JSON representation used to describe an Action includes the following fields:
Field name | Type | Description |
---|---|---|
values |
Object | A description of the parameters that his action accepts.
See 6.3 Values. This field is required. |
The Action URL is the result of resolving the id
returned in an
Action
description against the destination URL of the actions
link that gave birth to it.
In response to an HTTP GET
request on the destination URL of an
actions
link exposed by a resource, an Extended Web Thing MUST return an array of Action
descriptions that the initial resource may perform.
--> REQUEST GET {wt}/actions <-- RESPONSE 200 OK Link: <http://webofthings.org/actions/upgradefirmware>; rel="type" [ { "id":"upgradeFirmware", "name":"Upgrade Device Firmware" }, { "id":"reboot", "name":"Reboot" } ]
In response to an HTTP GET
request on an Action URL, an Extended Web
Thing MUST return an array that lists the recent executions of a specific Action.
On top of 6.1 Common Constructs, the JSON representation used to describe the execution of an Action includes the following fields:
Field name | Type | Description |
---|---|---|
status | String | The execution status. One of pending , executing ,
completed or failed |
--> REQUEST GET {wt}/actions/upgradefirmware <-- RESPONSE 200 OK Link: <http://webofthings.org/actions/upgradefirmware>; rel="type" Link: <model/>; rel="model" [ { "id":"223", "value":{ "delay":30, "mode":"SOFT" }, "status":"executing" "timestamp":"2015-06-14T18:33:25.938Z" }, { "id":"222", "value":{ "delay":60, "mode":"FORCE" }, "status":"completed" "timestamp":"2015-06-14T14:22:23.233Z" } ]
In response to an HTTP POST
request on an Action URL with valid parameters
as
request body, an Extended Web Thing MUST either reject the request with the appropriate
status code or queue a task to run the action and return the status of that action in a 201
Created
response. The action may not run immediately. The Location
HTTP
header
identifies the URL to use to retrieve the most recent update on the action's status.
This is how a Client sends a command to a device.
--> REQUEST POST {wt}/actions/reboot { "delay":50, "mode":"debug" } <-- RESPONSE 204 NO RESPONSE Location: {wt}/actions/reboot/233
In response to an HTTP GET
request on the URL targeted by the Location
HTTP header returned in response to the request to execute an action, an Extended Web
Thing
MUST return the status of this action or a 404 Not Found
status code if the
action's
status is no longer available.
--> REQUEST GET {wt}/actions/reboot/233 <-- RESPONSE 200 OK { "id":"233", "value":{ "delay":50, "mode":"debug" }, "status":"executing", "timestamp":"2015-06-14T14:30:00.000Z" }
A Web Thing may proxy other Web Things via the Things resource. For instance, it is expected that gateways and cloud services will proxy a number of third party devices. On top of 6.1 Common Constructs, the JSON representation used to describe a link to another thing includes the following fields:
Field name | Type | Description |
---|---|---|
rootUrl |
String | The URL of the root resource of the Web Thing if it is different from
{wt}/thing/{id} |
In response to an HTTP GET
request on the destination URL of a things
link, an Extended Web Thing MUST return an array of things descriptions.
--> REQUEST GET {wt}/things <-- RESPONSE 200 OK [ { "id":"982tjqogeih", "name":"Shopping Cart" }, { "id":"2398h87wt489foz", "name":"Shopping Cart", "rootUrl":"/pi", "description":"Shopping Cart that updates its location as it moves" }, { "id":"p9qrnc89w48oh", "name":"Shopping Cart", "rootUrl":"https://192.168.0.6/", "description":"LAN-connected gateway to Lamp #4." } ]
The id
can be interpreted as a URL, but if a Web Thing can be directly accessed without the proxy, the rootUrl
can be used to provide a different Root URL.
Clients can add new Things to be proxied by a Web Thing (especially for gateways/cloud) using an HTTP POST
request on the Thing URL of a Web Thing
and by sending in the request body the root resource representation of the Thing to be proxied.
--> REQUEST POST {wt}/things { "id":"p9qrnc89w48oh", "name":"Shopping Cart", "rootUrl":"https://192.168.0.6/", "description":"LAN-connected gateway to Lamp #4." } <-- RESPONSE 204 NO CONTENT Location: {wt}/things/p9qrnc89w48oh
All resources can be subscribed to but in particular, an Extended Web Thing SHOULD enable subscriptions to Actions and Properties. Subscriptions allows for a Client to be notified via a push event whenever the state of an observed resource changes.
The Subscription resource allows to list current subscriptions to resources as well as cancelling a subscription. Such a resource is accessible via the root URL of the Extended Web Thing.
On top of 6.1 Common Constructs, the JSON representation used to describe a subscription includes the following fields:
Field name | Type | Description |
---|---|---|
subscriberId |
String | A unique identifier for the subscriber
This field is required. |
type |
String | The type of connection used to exchange updates with the subscriber. One of
httpCallback or websockets |
resource |
String | The URL of the resource whose changes the subscriber is subscribed to. |
An Extended Web Thing SHOULD support subscriptions via the WebSocket [RFC6455] protocol and MAY support subscriptions via WebHooks (HTTP callbacks). Subscriptions are enabled via the HTTP protocol upgrade mechanism [RFC2616] as shown below.
To subscribe to a resource the following HTTP headers should be provided via a GET request (e.g., on /properties/temp
).
Header name | Description |
---|---|
Upgrade |
The protocol that should be used for the subscription, one of
webhook or websocket
This header is required. |
Callback |
The callback URL to which updates should be pushed.
webhook or websocket
This header is required in the case of a webhook subscription. |
In response to a HTTP GET
request on the destination URL of a resource, an Extended Web Thing MUST either reject the request with an appropriate status code or MUST return a 101 Switching Protocol
response for a subscription via Websocket or a 200 OK
for a subscription via Webhook. It SHOULD then create a record for the subscription that can be retrieved via the /subscriptions
URL. For both Websockets and Webhooks subscriptions the following headers must be returned (on top of the protocol specific headers):
Header name | Description |
---|---|
Subscription-ID |
The identifier of the subscription
This header is required. |
In response to an HTTP GET
request on the destination URL of a
subscriptions
link, an Extended Web Thing MUST return the array of
subscriptions to the underlying resource.
[ { "id":"2349", "type":"webhook", "resource":"/properties/temperature", "callbackUrl":"http://www.compose-project.eu/so/ServiceObject-123213213/callback" }, { "id":"2350", "subscriberId":"ServiceObject-123213213", "type":"websocket", "resource":"/properties/location" } ]
The Subscription URL is the result of resolving the id
returned in a Subscription
resource description against the destination URL of the subscriptions
link that
gave birth to it.
In response to an HTTP GET
request on a Subscription URL, an Extended Web
Thing MUST return a JSON representation of the subscription. The JSON representation should
be
the same as the one returned for that subscription in 6.4.7.2 Retrieve a list of subscriptions.
{ "id":"2349", "type":"webhook", "resource":"/properties/temperature", "callbackUrl":"http://www.compose-project.eu/so/ServiceObject-123213213/callback" }
In response to an HTTP DELETE
request on the destination URL of a
subscriptions
an Extended
Web Thing MUST either reject the request with an appropriate status code or remove (unsubscribe) the
subscription and return a 200 OK
status code.
GET /model HTTP/1.1 Host: mydevice.webofthings.org Accept: application/json,application/ld+json,*/*;q=0.1 ==================================== HTTP/1.1 200 OK ... Content-Type: application/json Link: <https://schema.org/Product>; rel="http://www.w3.org/ns/json-ld#context"; type="application/ld+json" { "name": "Beaglebone Black", "description": "A Beaglebone Black embedded device", "productID" : "asin:B00CO3MZCW", "manufacturer" : "Beagleboard", ... }
This work is supported by the European Union's 7th Research Framework Programme (FP7/2013-2015) under grant agreement nº317862 – COMPOSE).
The authors would like to thank the participants of the W3C Web of Things Interest Group, the Web of Things online community and in particular Joel Vogt and Iker Larizgoitia Abad, Francois Daoust, Johannes Hund and Joerg Heuer who have provided very valuable feedback on the drafts of this submission.
Further tools and examples to work with this specification are available on Web of Things online community Website.