This document describes a formal information model and a common representation for a Web of Things (WoT) Thing Description (TD), Version 2.0. A Thing Description describes the metadata and interfaces of Things, where a Thing is an abstraction of a physical or virtual entity that provides interactions to and participates in the Web of Things. Thing Descriptions provide a set of interactions based on a small vocabulary that makes it possible both to integrate diverse devices and to allow diverse applications to interoperate. Thing Descriptions, by default, are encoded in a JSON format that also allows JSON-LD processing. The latter provides a powerful foundation to represent knowledge about Things in a machine-understandable way. A Thing Description instance can be hosted by the Thing itself or hosted externally when a Thing has resource restrictions (e.g., limited memory space) or when a Web of Things-compatible legacy device is retrofitted with a Thing Description. Furthermore, this document introduces the Thing Model, which allows authors to describe only the model or class of an Internet of Things (IoT) entity. Thing Models can be seen as a template for Thing Description instances, but with reduced constraints such as no or few requirements for specific communication metadata.
This specification continues the work of [[WOT-THING-DESCRIPTION11]] with no guarantees on backwards compatibility. In case of no backwards compatibility, there will be concrete guidelines for implementers to migrate to the new version.
The WoT Thing Description (TD) is a central building block in the W3C Web of Things (WoT) and can be considered as the entry point of a Thing (much like the index.html of a Web site). A TD instance has five main components: textual metadata about the Thing itself, a set of Interaction Affordances that indicate how the Thing can be used, schemas for the data exchanged with the Thing for machine-understandability, Security Definitions to provide metadata about the security mechanisms that must be used for interactions, and, finally, Web links to express any formal or informal relation to other Things or documents on the Web.
The Interaction Model of W3C WoT defines three types of Interaction Affordances: Properties (PropertyAffordance
class) can be used for sensing and controlling parameters, such as getting the current value or setting an
operation state. Actions (ActionAffordance class) model
invocation of physical (and hence time-consuming) processes, but can also be used to abstract RPC-like calls
of existing platforms. Events (EventAffordance class) are used for
the push model of communication where notifications, discrete events, or streams of values are sent
asynchronously to the receiver. See [[wot-architecture11]] for details.
In general, the TD provides metadata for different Protocol Bindings identified by URI schemes
[[RFC3986]] (e.g., http, coap, etc. [[?IANA-URI-SCHEMES]]), content types based on
media types [[RFC2046]] (e.g., application/json, application/xml,
application/cbor, application/exi, etc. [[?IANA-MEDIA-TYPES]]), and security
mechanisms (for authentication, authorization, confidentiality, etc.). Serialization of TD instances is based
on JSON [[RFC8259]], where JSON names refer to terms of the TD vocabulary, as defined in this specification
document. In addition the JSON serialization of TDs follows the syntax of JSON-LD 1.1 [[?JSON-LD11]] to enable
extensions and rich semantic processing.
Example 1 shows a TD instance and illustrates the Interaction Model with Properties, Actions, and Events by describing a lamp Thing with the title MyLampThing.
From this TD example, we know there exists one Property affordance with the
title status. In addition, information is provided to indicate that this Property is accessible via
(the secure form of) the HTTP protocol with a GET method at the URI
https://mylamp.example.com/status (announced within the forms structure by the
href member), and will return a string-based status value. The use of the GET method is not
stated explicitly, but is one of the default assumptions defined by this document.
In a similar manner, an Action affordance is specified to toggle the switch
status using the POST method on the https://mylamp.example.com/toggle resource, where POST is
again a default assumption for invoking Actions.
The Event affordance enables a mechanism for asynchronous messages to be sent
by a Thing. Here, a subscription to be notified upon a possible overheating event of the lamp can be
obtained by using HTTP with its long polling subprotocol on https://mylamp.example.com/oh.
This example also specifies the basic security scheme, requiring a username and password for
access. Note that a security scheme is first given a name in securityDefinitions and then
activated by specifying that name in a security section. In combination with the use of the HTTP
protocol this example demonstrates the use of HTTP Basic Authentication. Specification of at least one
security scheme at the top level is mandatory, and gives the default access requirements for every resource.
However, security schemes can also be specified per-form, with configurations given at the form level
overriding configurations given at the Thing level, allowing for the specification of
fine-grained access control. It is also possible to use a special nosec security scheme to
indicate that no access control mechanisms are used. Additional examples will be provided later.
The Thing Description offers the possibility to add contextual definitions in some namespace. This mechanism
can be used to integrate additional semantics to the content of the Thing Description instance, provided that
formal knowledge, e.g., logic rules for a specific domain of application, can be found under the given
namespace. Contextual information can also help specify some configurations and behavior of the underlying
communication protocols declared in the forms field.
Example 2 extends the TD sample from Example 1 by
introducing a second definition in the @context to declare the prefix saref as
referring to SAREF, the Smart Appliance Reference Ontology
[[SMARTM2M]]. This IoT ontology includes terms interpreted as semantic labels that can be set as values of the
@type field, giving the semantics of Things and their Interaction Affordances. In
the example below, the Thing is labelled with saref:LightSwitch, the status
Property is labelled with saref:OnOffState and the toggle Action with
saref:ToggleCommand.
The declaration mechanism inside some
@context is specified by JSON-LD. A TD instance complies to version 1.1 of that specification
[[?json-ld11]]. Hence, a TD instance can be also processed as an RDF document (for details about semantic
processing, please refer to Appendix and the documentation under the
namespace IRIs, e.g., https://www.w3.org/2019/wot/td).
One of the main intentions of a Thing Description is to provide a Consumer with all the details necessary to successfully interact with a Thing. In some IoT application scenarios, a fully detailed Thing Description, e.g., with communication metadata is not necessary (e.g., IoT ecosystems may implicitly handle communication separately), or may not be available because a new entity has not yet been deployed (e.g., IP address is not yet known). Sometimes, also a kind of class definition is required that forces capability definitions that should be available for all created instances (e.g., large-scale production of new devices).
In order to address the above-mentioned scenarios or others, the Thing Model can be used that mainly provides the data model definitions within Things' Properties, Actions, and/or Events and can be potentially used as template for creating Thing Description instances. In the following a sample Thing Model is presented that can be seen as a model for the Thing Description instance in .
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Lamp Thing Model",
"properties": {
"status": {
"description": "current status of the lamp (on|off)",
"type": "string",
"readOnly": true
}
},
"actions": {
"toggle": {
"description": "Turn the lamp on or off"
}
},
"events": {
"overheating": {
"description": "Lamp reaches a critical temperature (overheating)",
"data": {"type": "string"}
}
}
}
Thing Model definitions are identified by the "@type": "tm:ThingModel". As the example
shows, it does not provide details about a single Thing instance due to the lack of communication and
security metadata. This specification presents a mechanism for deriving valid
Thing Description instances from such Thing Model definitions. In addition, other design
concepts are specified, including how to override, extend, and reuse existing Thing Model definitions.
A Thing Description instance complies with this specification if it follows the normative statements in and regarding Thing Description serialization.
A JSON Schema [[?JSON-SCHEMA]] to validate Thing Description instances is provided in Appendix .
The fundamental WoT terminology such as Thing, Consumer, Producer, Thing Description (TD), Partial TD, Thing Model (TM), Interaction Model, Interaction Affordance, IoT Platform, Property, Action, Event, Data Schema, Content Type, Protocol Binding, Servient, Vocabulary, Term, Vocabulary Term, WoT Interface, and WoT Runtime are defined in Section 3 of the WoT Architecture specification [[wot-architecture11]].
In addition, this specification introduces the following definitions:
@type members, and through the use of string prefixes using a colon (:).
Thing class. For that purpose, a
TD Processor can compute fill in the forms of Thing Descriptions in which all possible
Default Values are assigned. A TD Processor is typically a sub-system of a WoT Runtime.
Implementations of a TD Processor can be a TD producer (able to serialize to TD Documents) or a TD
consumer (able to deserialize from TD Documents) or both.
@context are defined is the Thing level, forms are defined within the Affordance
level, type, maximum are defined within the Data Schema level and
href is defined within the Forms level. Even if not defined, other levels can be used such as
Links level.
href starting with http:// or https://.
The version of the TD Information Model defined in of this specification is identified by the following IRI:
https://www.w3.org/ns/wot-next/td
This IRI [[RFC3987]], which is also a URI [[!RFC3986]], can be dereferenced to obtain a JSON-LD context file [[?json-ld11]], allowing the compact strings in TD Documents to be expanded to full IRI-based Vocabulary Terms. However, this processing is only required when transforming JSON-based TD Documents to RDF, an optional feature of TD Processor implementations.
Note that this namespace is temporary until the specification reaches Recommendation status. At that time, a permanent namespace will be assigned. All documents using the temporary namespace point to the main branch of the git repository of the specification, thus not stable.
In the present specification, Vocabulary Terms are always presented in their compact form. Their expanded form can be accessed under the namespace IRI of the Vocabulary they belong to. These namespaces follow the structure of . Each Vocabulary used in the TD Information Model has its own namespace IRI, as follows:
| Vocabulary | Namespace IRI |
|---|---|
| Core | https://www.w3.org/ns/wot-next/td-ontology |
| Data Schema | https://www.w3.org/ns/wot-next/json-schema-ontology |
| Security | https://www.w3.org/ns/wot-next/security-ontology |
| Hypermedia Controls | https://www.w3.org/ns/wot-next/security-ontologyy |
All vocabularies that are additionally used for Thing Model definitions have the following namespace IRI:
| Vocabulary | Namespace IRI |
|---|---|
| Thing Model | https://www.w3.org/ns/wot-next/tm-ontology |
The Vocabularies are independent from each other. They may be reused and extended in other W3C
specifications. Every breaking change in the design of a Vocabulary will require the assignment of a new
year-based namespace URI. Note that to maintain the general coherence of the TD Information Model, the
associated JSON-LD context file is versioned such that every version has its own URI (v1,
v1.1, v2, ...) to also identify non-breaking changes, in particular the addition of
new Terms.
Because a Vocabulary under some namespace IRI can only undergo non-breaking changes, its content can be safely cached or embedded in applications. One advantage of exposing relatively static content under a namespace IRI is to optimize payload sizes of messages exchanged between constrained devices. It also avoids any privacy leakage resulting from devices accessing publicly available vocabularies from private networks (see also ).
This section introduces the TD Information Model. The TD Information Model serves as the conceptual basis for the processing of Thing Descriptions and their serialization, which is described separately in .
The TD Information Model is built upon the following, independent Vocabularies:
Each of these Vocabularies is essentially a set of Terms that can be used to build data structures, interpreted as objects in the traditional object-oriented sense. Objects are instances of classes and have properties. In the context of W3C WoT, they denote Things and their Interaction Affordances. A formal definition of objects is given in . The main elements of the TD Information Model are then presented in . Certain object properties may be omitted in a TD when Default Values exist. A list of defaults is given in .
The UML diagram shown next gives an overview of the TD Information Model. It represents all classes as
tables and the associations that exist between classes, starting from the class
Thing, as directed arrows. For the sake of readability, the diagram was split in four parts, one for each of the
four base Vocabularies.
To provide a model that can be easily processed by both, simple rules on a tree-based document (i.e., raw JSON processing) and rich Semantic Web tooling (i.e., JSON-LD processing), this document defines the following formal preliminaries to construct the TD Information Model accordingly.
All definitions in this section refer to sets, which intuitively are collections of elements that can themselves be sets. All arbitrarily complex data structures can be defined in terms of sets. In particular, an Object is a data structure recursively defined as follows:
Though this definition does not prevent Objects to include multiple name-value pairs with the same name, they are generally not considered in this specification. An Object whose elements only have numbers as names is called an Array. Similarly, an Object whose elements only have Terms (that do not belong to any Vocabulary) as names is called a Map. All names appearing in some name-value pair in a Map are assumed to be unique within the scope of the Map.
Moreover, Objects can be instances of some Class. A Class, which is denoted by a Vocabulary Term, is first defined by a set of Vocabulary Terms called a Signature. A Class whose Signature is empty is called a Simple Type.
The Signature of a Class allows to construct two functions that further define Classes:
an Assignment Function and a Type Function. The Assignment Function of a
Class takes a Vocabulary Term of the Class's Signature as input and returns either
true or false as output. Intuitively, the Assignment Function indicates
whether an element of the Signature is mandatory or optional when instantiating the Class. The
Type Function of a Class also takes a Vocabulary Term of the Class's
Signature as input and returns another Class as output. These functions are partial:
their domain is limited to the Signature of the Class being defined.
On the basis of these two functions, an Instance Relation can be defined for a pair composed of an Object and a Class. This relation is defined as constraints to be satisfied. That is, an Object is an instance of a Class if the two following constraints are both satisfied:
true, the Object includes a name-value pair with the Vocabulary Term as name.
According to the definition above, an Object would be an instance of every Simple Type,
regardless of its structure. Instead, another definition for the Instance Relation is introduced for
Simple Types: an Object is an instance of a Simple Type if it is a Term with a
given lexical form (e.g., true, false for the boolean type,
1, 2, 3, ... for the unsignedInt type, etc.).
Moreover, additional Classes, called Parameterized Classes, can be derived from the generic Map and Array structures. An Object is a Map of some Class, that is, an instance of the Map type parameterized with some Class, if it is a Map such that the value in all the name-value pairs it contains is an instance of this Class. The same applies to Arrays.
Finally, a Class is a Subclass of some other Class if every instance of the former is also an instance of the latter.
Given all definitions above, the TD Information Model is to be understood as a set of
Class definitions, which include a Class name (a Vocabulary Term), a Signature (a
set of Vocabulary Terms), an Assignment Function, and a Type Function. These
Class definitions are provided as tables in . For each table, the
values "mandatory" (respectively, "optional") in the assignment column indicates that the
Assignment Function returns true (respectively, false) for the corresponding
Vocabulary Term.
By convention, Simple Types are denoted by names starting with lowercase. The
TD Information Model references the following Simple Types
defined in XML Schema [[XMLSCHEMA11-2-20120405]]:
string, anyURI, dateTime, integer,
unsignedInt, double, and boolean. Their definition (i.e., the
specification of their lexical form) is outside of the scope of the TD Information Model.
In addition, the TD Information Model defines a global function on pairs of Vocabulary Terms.
The function takes a Class name and another Vocabulary Term as input and returns an
Object. If the returned Object is different from null, it represents the
Default Value for some assignment on the input Vocabulary Term in an instance of the input
Class. This function allows to relax the constraint defined above on the Assignment Function: an
Object is an instance of a Class if it includes all mandatory assignments or if
Default Value exist for the missing assignments. All Default Values are given in the table of
. In each table of , the assignment column
contains the value "with default" if a Default Value is available for the corresponding combination of
Class and Vocabulary Term in the TD Information Model.
The formalization introduced here does not consider the possible relation between Objects as abstract data structures and physical world objects such as Things. However, care was given to the possibility of re-interpreting all Vocabulary Terms involved in the TD Information Model as RDF resources, so as to integrate them in a larger model of the physical world (an ontology). For details about semantic processing, please refer to and the documentation under the namespace IRIs, e.g., https://www.w3.org/2019/wot/td.
A TD Processor MUST satisfy the Class instantiation constraints on all Classes defined in , , , and .
In particular, note that all vocabulary terms and values are case sensitive. This is also true for the serialization of the information model (Section ).
ThingAn abstraction of a physical or a virtual entity whose metadata and interfaces are described by a WoT Thing Description, whereas a virtual entity is the composition of one or more Things.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
@context |
JSON-LD keyword to define short-hand names called terms that are used throughout a TD document. | mandatory |
anyURI or
Array
|
@type |
JSON-LD keyword to label the object with semantic tags (or types). | optional |
string or
Array of
string
|
id |
Identifier of the Thing in form of a URI [[RFC3986]] (e.g., stable URI, temporary and mutable URI, URI with local IP address, URN, etc.). | optional |
anyURI
|
title |
Provides a human-readable title (e.g., display a text for UI representation) based on a default language. | mandatory | any type |
titles |
Provides multi-language human-readable titles (e.g., display a text for UI representation in different languages). Also see MultiLanguage. | optional |
Map of MultiLanguage
|
description |
Provides additional (human-readable) information based on a default language. | optional |
string
|
descriptions |
Can be used to support (human-readable) information in different languages. Also see MultiLanguage. | optional |
Map of MultiLanguage
|
version |
Provides version information. | optional |
VersionInfo
|
created |
Provides information when the TD instance was created. | optional |
dateTime
|
modified |
Provides information when the TD instance was last modified. | optional |
dateTime
|
support |
Provides information about the TD maintainer as URI scheme (e.g., mailto [[RFC6068]],
tel [[RFC3966]], https [[RFC9112]]).
|
optional |
anyURI
|
base |
Define the base URI that is used for all relative URI references throughout a TD document. In TD
instances, all relative URIs are resolved relative to the base URI using the algorithm defined in
[RFC3986].base does not affect the URIs used in @context and the IRIs used within
Linked Data [LINKED-DATA] graphs that are relevant when semantic processing is applied to TD instances.
|
optional |
anyURI
|
properties |
All Property-based Interaction Affordances of the Thing. | optional |
Map of PropertyAffordance
|
actions |
All Action-based Interaction Affordances of the Thing. | optional |
Map of ActionAffordance
|
events |
All Event-based Interaction Affordances of the Thing. | optional |
Map of EventAffordance
|
links |
Provides Web links to arbitrary resources that relate to the specified Thing Description. | optional |
Array of Link
|
forms |
Set of form hypermedia controls that describe how an operation can be performed. Forms are serializations of Protocol Bindings. Thing level forms are used to describe endpoints for a group of interaction affordances. | optional |
Array of Form
|
security |
Set of security definition names, chosen from those defined in securityDefinitions.
These must all be satisfied for access to resources.
|
mandatory |
string or
Array of
string
|
securityDefinitions |
Set of named security configurations (definitions only). Not actually applied unless names are used
in a security name-value pair.
|
mandatory |
Map of SecurityScheme
|
profile |
Indicates the WoT Profile mechanisms followed by this Thing Description and the corresponding Thing implementation. | optional |
anyURI or
Array of
anyURI
|
schemaDefinitions |
Set of named data schemas. To be used in a schema
name-value pair inside an
AdditionalExpectedResponse object.
|
optional |
Map of DataSchema
|
uriVariables |
Define URI template variables according to [[RFC6570]] as collection based on DataSchema
declarations. The Thing level uriVariables can be used in Thing level
forms or in Interaction Affordances. The individual variables DataSchema cannot be an
ObjectSchema or an ArraySchema since each variable needs to be serialized to a string inside the
href upon the execution of the operation. If the same variable is both declared in
Thing level uriVariables and in Interaction Affordance level, the Interaction
Affordance level variable takes precedence.
|
optional |
Map of DataSchema
|
The exact value of @context URI will change upon the publication of the
W3C Recommendation version.
For @context the following rules are defined for Thing Description instances:
@context
name-value pair MUST contain the anyURI
https://www.w3.org/ns/wot-next/td
in order to identify the document as a TD 2.0 which would allow Consumers to use the newly
introduced terms.
@context is an
Array, the anyURI
https://www.w3.org/ns/wot-next/td MAY be followed by
elements of type anyURI or type
Map in any order, while it is
RECOMMENDED to include only one
Map with all the name-value pairs in
the @context
Array.
@context Array MAY
contain name-value pairs, where the value is a namespace identifier of type anyURI and
the name a Term or prefix denoting
that namespace.
@context Array SHOULD
contain a name-value pair that defines the default language for the Thing Description, where the name
is the Term
@language and the value is a well-formed language tag as defined by [BCP47] (e.g., en, de-AT, gsw-CH, zh-Hans,
zh-Hant-HK, sl-nedis).
To determine the base direction of all human-readable text in Thing Description and Thing Model instances this specification recommends to follow the [[STRING-META]] guideline about string-specific directional information when no built-in mechanism for associating base direction metadata is available.
TD Processors should be aware of certain special cases when processing bidirectional text. TD Processors SHOULD take care to use bidi isolation when presenting strings to users, particularly when embedding in surrounding text (e.g., for Web user interface). Mixed direction text can occur in any language, even when the language is properly identified.
TD producers SHOULD attempt to provide mixed direction strings in a way that can be displayed successfully by a naive user agent. For example, if an RTL string begins with an LTR run (such as a number or a brand or trade name in Latin script), including an RLM character at the start of the string or wrapping opposite direction runs in bidi controls can assist in proper display.
Strings on the Web: Language and Direction Metadata [string-meta] provides some guidance and illustrates a number of pitfalls when using bidirectional text.
In addition to the explicitly provided
Interaction Affordances
in the properties, actions, and events
Maps, a
Thing can also provide
meta-interactions, which are indicated by Form instances in its optional forms
Array.
When the forms Array of
a Thing instance contains
Form instances, it MUST contain op member with the string values assigned to
the name op, either directly or within an
Array, MUST be one of the following
operation types: readallproperties, writeallproperties,
readmultipleproperties, writemultipleproperties,
observeallproperties, unobserveallproperties, queryallactions,
subscribeallevents, or unsubscribeallevents.
(See an example for an usage of form in a Thing
instance.)
The data schema for each of the property meta-interactions is constructed by combining the data schemas of
each PropertyAffordance instance in a single ObjectSchema instance, where the
properties Map of the
ObjectSchema instance contains each data schema of the
PropertyAffordances identified by the name of the corresponding
PropertyAffordances instance.
If not specified otherwise (e.g., through a
TD Context Extension), the request
data of the readmultipleproperties operation is an
Array that contains the intended
PropertyAffordances instance names, which is serialized to the content type specified by the
Form instance.
InteractionAffordanceMetadata of a Thing that shows the possible choices to Consumers, thereby suggesting how Consumers may interact with the Thing. There are many types of potential affordances, but W3C WoT defines three types of Interaction Affordances: Properties, Actions, and Events.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
@type |
JSON-LD keyword to label the object with semantic tags (or types). | optional |
string or
Array of
string
|
title |
Provides a human-readable title (e.g., display a text for UI representation) based on a default language. | optional |
string
|
titles |
Provides multi-language human-readable titles (e.g., display a text for UI representation in different languages). Also see MultiLanguage. | optional |
Map of MultiLanguage
|
description |
Provides additional (human-readable) information based on a default language. | optional |
string
|
descriptions |
Can be used to support (human-readable) information in different languages. Also see MultiLanguage. | optional |
Map of MultiLanguage
|
forms |
Set of form hypermedia controls that describe how an operation can be performed. Forms are serializations of Protocol Bindings. The array cannot be empty. | mandatory |
Array of Form
|
uriVariables |
Define URI template variables according to [[RFC6570]] as collection based on DataSchema
declarations. The individual variables DataSchema cannot be an ObjectSchema or an ArraySchema since
each variable needs to be serialized to a string inside the href upon the execution of
the operation. If the same variable is both declared in Thing level
uriVariablesand in Interaction Affordance level, the Interaction Affordance level
variable takes precedence.
|
optional |
Map of DataSchema
|
The class InteractionAffordance has the following subclasses:
PropertyAffordanceAn Interaction Affordance that exposes state of the Thing. This state can then be retrieved (read) and/or updated (write). Things can also choose to make Properties observable by pushing the new state after a change.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
observable |
A hint that indicates whether Servients hosting the Thing and Intermediaries should provide a
Protocol Binding that supports the observeproperty and
unobserveproperty operations for this Property.
|
with default |
boolean
|
Property instances are also instances of the class DataSchema.
Therefore, it can contain the type, unit, readOnly and
writeOnly members, among others.
PropertyAffordance is a
Subclass of the
InteractionAffordance
Class and the DataSchema
Class.
When a Form instance is within a PropertyAffordance instance, the value assigned to
op MUST be one of readproperty, writeproperty,
observeproperty, unobserveproperty or an
Array containing a combination of
these terms.
It is considered to be good practice that each observeproperty has a corresponding
unobserveproperty unless the protocol supports implicit unsubscription mechanisms (e.g.,
heartbeat to detect connection loss).
The observation mechanism depends on the underlying protocol or sub-protocol. Having said that, it is not guaranteed that the current Property value will be provided once the subscription is initiated. Hence, it may be necessary to read the current Property value before/after the subscription to get a first value.
ActionAffordanceAn Interaction Affordance that allows to invoke a function of the Thing, which manipulates state (e.g., toggling a lamp on or off) or triggers a process on the Thing (e.g., dim a lamp over time).
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
input |
Used to define the input data schema of the Action. | optional |
DataSchema
|
output |
Used to define the output data schema of the Action. | optional |
DataSchema
|
safe |
Signals if the Action is safe (=true) or not. Used to signal if there is no internal state (cf. resource state) is changed when invoking an Action. In that case responses can be cached as example. | with default |
boolean
|
idempotent |
Indicates whether the Action is idempotent (=true) or not. Informs whether the Action can be called repeatedly with the same result, if present, based on the same input. | with default |
boolean
|
synchronous |
Indicates whether the action is synchronous (=true) or not. A synchronous action means that the response of action contains all the information about the result of the action and no further querying about the status of the action is needed. Lack of this keyword means that no claim on the synchronicity of the action can be made. | optional |
boolean
|
ActionAffordance is a
Subclass of the
InteractionAffordance
Class.
When a Form instance is within an ActionAffordance instance, the value assigned to op MUST
either be invokeaction, queryaction, cancelaction or an
Array
containing a combination of these terms.
EventAffordanceAn Interaction Affordance that describes an event source, which asynchronously pushes event data to Consumers (e.g., overheating alerts).
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
subscription |
Defines data that needs to be passed upon subscription, e.g., filters or message format for setting up Webhooks. | optional |
DataSchema
|
data |
Defines the data schema of the Event instance messages pushed by the Thing. | optional |
DataSchema
|
dataResponse |
Defines the data schema of the Event response messages sent by the consumer in a response to a data message. | optional |
DataSchema
|
cancellation |
Defines any data that needs to be passed to cancel a subscription, e.g., a specific message to remove a Webhook. | optional |
DataSchema
|
EventAffordance is a
Subclass of the
InteractionAffordance
Class.
When a Form instance is within an EventAffordance instance, the value assigned to
op
MUST be either
subscribeevent, unsubscribeevent, or both terms within an
Array.
It is considered to be good practice that each subscribeevent has a corresponding
unsubscribeevent unless the protocol supports implicit unsubscription mechanisms (e.g.,
heartbeat to detect connection loss).
EventAffordances are similar to observable PropertyAffordances in the sense that the Thing itself informs
interested Consumers about state changes. However, a main difference of EventAffordances is that not every
change of the associated resource needs to trigger an event message to be emitted, e.g. a critical
threshold for a numeric value. Furthermore, EventAffordances allow for more complex subscribing and
unsubscribing mechanisms via the definition of subscription, dataResponse, and
cancellation DataSchema definitions. Not all protocols might support these more advanced
mechanisms, however, which is why in some scenarios, events may be very similar to observable
PropertyAffordances. In these cases, the choice between a Property and a Event for modelling the
Affordance should be made based on the semantics of the underlying resource; for example, if the state of
the affordance is also supposed to be read or written by a Consumer, then a Property is most likely the
appropriate choice.
VersionInfoMetadata of a Thing that provides version information about the TD document. If required, additional version information such as firmware and hardware version (term definitions outside of the TD namespace) can be extended via the TD Context Extension mechanism.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
instance |
Provides a version indicator of this TD. | mandatory |
string
|
model |
Provides a version indicator of the underlying TM. | optional |
string
|
It is recommended that the values within instances and model of the
VersionInfo Class follow
the semantic versioning pattern, where a sequence of three numbers separated by a dot indicates the major
version, minor version, and patch version, respectively. See [SEMVER] for details.
MultiLanguageA Map providing a set of human-readable texts in different languages identified by language tags described in [[BCP47]]. See for example usages of this container in a Thing Description instance.
Each name of the MultiLanguage Map MUST be a language tag as defined in
[[!BCP47]].
Each value of the MultiLanguage Map MUST be of type string.
A data schema is an abstract notation for data contained in data formats.
The data schema vocabulary definition reflects a very common subset of the terms defined by JSON Schema [[?JSON-SCHEMA]]. A JSON Schema [[?JSON-SCHEMA]] processor for JSON Schema draft 7 can consume a data schema. It is noted that data schema definitions within Thing Description instances are not limited to this defined subset and may use additional terms found in JSON Schema using a TD Context Extension for the additional terms as described in , otherwise these terms are semantically ignored by TD Processors (for details about semantic processing, please refer to and the documentation under the namespace IRIs, e.g., https://www.w3.org/2019/wot/td).
In a TD, concrete data formats are specified in Forms (see ) using content types. When
the value of a content type in an instance of the Form is application/json, the data schema can
be processed directly by JSON Schema processors. Otherwise, entries in Web of Things (WoT) Binding Registry
[[?WOT-BINDING-REGISTRY]] define available mappings from data schemas to other content types such as XML
[[?xml]]. If the content type in an instance of the Form is not application/json and if no
mapping is defined for the content type, specifying a data schema does not make sense for the content type.
The following table contains content types which MAY use data schema to describe the structure of their payloads.
| Format | Content Type |
|---|---|
| JSON/CBOR |
application/json application/ld+json application/senml+json application/cbor application/senml+cbor |
| XML/EXI |
application/xml application/senml+xml application/exi application/senml-exi |
DataSchemaMetadata that describes the data format used. It can be used for validation.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
@type |
JSON-LD keyword to label the object with semantic tags (or types) | optional |
string or
Array of
string
|
title |
Provides a human-readable title (e.g., display a text for UI representation) based on a default language. | optional |
string
|
titles |
Provides multi-language human-readable titles (e.g., display a text for UI representation in different languages). Also see MultiLanguage. | optional |
Map of MultiLanguage
|
description |
Provides additional (human-readable) information based on a default language. | optional |
string
|
descriptions |
Can be used to support (human-readable) information in different languages. Also see MultiLanguage. | optional |
Map of MultiLanguage
|
const |
Provides a constant value. | optional | any type |
default |
Supply a default value. The value SHOULD validate against the data schema in which it resides. | optional | any type |
unit |
Provides unit information that is used, e.g., in international science, engineering, and business. To preserve uniqueness, it is recommended that the value of the unit points to a semantic definition (also see Section Semantic Annotations). | optional |
string
|
oneOf |
Used to ensure that the data is valid against one of the specified schemas in the array. This can be used to describe multiple input or output schemas. | optional |
Array of DataSchema
|
enum |
Restricted set of values provided as an array. | optional | Array of any type |
readOnly |
Boolean value that is a hint to indicate whether a property interaction / value is read only (=true) or not (=false). | with default |
boolean
|
writeOnly |
Boolean value that is a hint to indicate whether a property interaction / value is write only (=true) or not (=false). | with default |
boolean
|
format |
Allows validation based on a format pattern such as "date-time", "email", "uri", etc. (Also see below.) | optional |
string
|
type |
Assignment of JSON-based data types compatible with JSON Schema (one of boolean, integer, number, string, object, array, or null). | optional |
anyURI (one
of object, array, string, number,
integer, boolean, or null)
|
The class DataSchema has the following subclasses:
The format string values are known from a fixed set of values and their corresponding format
rules defined in [JSON-SCHEMA] (Section 7.3 Defined Formats in particular).
Servients MAY use the format value to perform additional validation accordingly.
When a value that is not found in the known set of values is assigned to format, such a
validation SHOULD succeed.
any type (e.g., const,
default) follow data types compatible with JSON Schema (boolean, integer, number, string,
object, array, or null).
The format term is not widely implemented by JSON Schema tools. In addition, the term
format is being discussed by the JSON Schema standardisation community and may be replaced by
another mechanism or removed in a future JSON Schema version.
ArraySchema
Metadata describing data of type Array.
This Subclass is indicated by the
value array assigned to type in DataSchema instances.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
items |
Used to define the characteristics of an array. | optional |
DataSchema or Array of
DataSchema
|
minItems |
Defines the minimum number of items that have to be in the array. | optional |
unsignedInt
|
maxItems |
Defines the maximum number of items that have to be in the array. | optional |
unsignedInt
|
BooleanSchema
Metadata describing data of type boolean. This
Subclass is indicated by the value
boolean assigned to type in DataSchema instances.
NumberSchema
Metadata describing data of type number. This
Subclass is indicated by the value
number assigned to type in DataSchema instances.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
minimum |
Specifies a minimum numeric value, representing an inclusive lower limit. Only applicable for associated number or integer types. | optional |
double
|
exclusiveMinimum |
Specifies a minimum numeric value, representing an exclusive lower limit. Only applicable for associated number or integer types. | optional |
double
|
maximum |
Specifies a maximum numeric value, representing an inclusive upper limit. Only applicable for associated number or integer types. | optional |
double
|
exclusiveMaximum |
Specifies a maximum numeric value, representing an exclusive upper limit. Only applicable for associated number or integer types. | optional |
double
|
multipleOf |
Specifies the multipleOf value number. The value must strictly greater than 0. Only applicable for associated number or integer types. | optional |
double
|
IntegerSchema
Metadata describing data of type integer. This
Subclass is indicated by the value
integer assigned to type in DataSchema instances.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
minimum |
Specifies a minimum numeric value, representing an inclusive lower limit. Only applicable for associated number or integer types. | optional |
integer
|
exclusiveMinimum |
Specifies a minimum numeric value, representing an exclusive lower limit. Only applicable for associated number or integer types. | optional |
integer
|
maximum |
Specifies a maximum numeric value, representing an inclusive upper limit. Only applicable for associated number or integer types. | optional |
integer
|
exclusiveMaximum |
Specifies a maximum numeric value, representing an exclusive upper limit. Only applicable for associated number or integer types. | optional |
integer
|
multipleOf |
Specifies the multipleOf value number. The value must strictly greater than 0. Only applicable for associated number or integer types. | optional |
integer
|
ObjectSchema
Metadata describing data of type
Object. This
Subclass is indicated by the value
object assigned to type in DataSchema instances.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
properties |
Data schema nested definitions. | optional |
Map of DataSchema
|
required |
Defines which members of the object type are mandatory, i.e. which members are mandatory in the
payload that is to be sent (e.g. input of invokeaction, writeproperty) and
what members will be definitely delivered in the payload that is being received (e.g. output of
invokeaction, readproperty)
|
optional |
Array of
string
|
StringSchema
Metadata describing data of type string. This
Subclass is indicated by the value
string assigned to type in DataSchema instances.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
minLength |
Specifies the minimum length of a string. Only applicable for associated string types. | optional |
unsignedInt
|
maxLength |
Specifies the maximum length of a string. Only applicable for associated string types. | optional |
unsignedInt
|
pattern |
Provides a regular expression to express constraints of the string value. The regular expression must follow the [[ECMA-262]] dialect. | optional |
string
|
contentEncoding |
Specifies the encoding used to store the contents, as specified in [[RFC2045]] (Section 6.1) and [[RFC4648]]. | optional |
string
(e.g., 7bit, 8bit, binary, quoted-printable,
base16, base32, or base64)
|
contentMediaType |
Specifies the MIME type of the contents of a string value, as described in [[RFC2046]]. | optional |
string
(e.g., image/png, or audio/mpeg)
|
The length of a string (i.e., minLength and maxLength) is defined as the number
of Unicode code points, as defined by [[RFC8259]]. Note that some
user-perceived characters
are composed of more than one Unicode code point. Arbitrary index values might not fall on these grapheme
boundaries, so truncation according to maxLength might alter the appearance or meaning of the
string.
NullSchema
Metadata describing data of type null. This subclass is indicated by the value
null assigned to type in DataSchema instances. This Subclass
describes only one acceptable value, namely null. It is important to note that
null does not mean the absence of a value. It is analogous to null in
JavaScript, None in Python, null in Java and nil in Ruby
programming languages. It can be used as part of a oneOf declaration, where it is used to
indicate, that the data can also be null.
This specification provides a selection of well-established security mechanisms that are directly built into protocols eligible as Protocol Bindings for W3C WoT or are widely in use with those protocols. The current set of HTTP security schemes is partly based on OpenAPI 3.0.1 (see also [[?OPENAPI]]). However while the HTTP security schemes, Vocabulary, and syntax given in this specification share many similarities with OpenAPI, they are not compatible.
Generally, security schemes require some form of secure transport to be effective, such as TLS or DTLS. Requirements for the use of secure transport are given in Section in this document and in the Security Considerations section of [[wot-architecture11]].
SecurityScheme
Metadata describing the configuration of a security mechanism.
The value assigned to the name scheme MUST be defined within a
Vocabulary
included in the
Thing Description, either
in the standard
Vocabulary defined in
§ 5. TD Information Model
or in a
TD Context Extension.
For all security schemes, any keys, passwords, or other sensitive information directly providing access MUST NOT be stored in the TD and should instead be shared and stored out-of-band via other mechanisms. The purpose of a TD is to describe how to access a Thing if and only if a Consumer already has authorization, and is not meant be used to grant that authorization.
Each security scheme object used in a TD defines a set of requirements to be met before access can be granted. We say a security scheme is satisfied when all its requirements are met. In some cases requirements from multiple security schemes will have to be met before access can be granted.
Security schemes generally may require additional authentication parameters, such as a password or key.
The location of this information is indicated by the value associated with the name in, often
in combination with the value associated with name. The value associated with
in can take one of the following values:
header:name.
query:name.
body:name.
When used in the context of a body security information location, the value of
name MUST be in the form of a JSON pointer [[!RFC6901]] relative to the root of the input
DataSchema for each interaction it is used with.
Since this value is not a fragment identifier, and is not relative to the root of the TD but to
whichever data schemas the security scheme is bound to, this value should not start with #;
it is a "pure" JSON pointer. Since this value is not a fragment identifier, it also does not need to
URL-encode special characters. The targeted element may or may not already exist at the specified
location in the referenced object or array schema (consequently the mechanism is not applicable to
simple types). If it does not, it will be inserted. This avoids having to duplicate definitions in the
data schemas of every interaction.
When an element of a data schema indicated by a JSON pointer indicated in a body locator
does not already exist in the indicated schema, it MUST be possible to insert the indicated element at
the location indicated by the pointer.
The JSON pointer used in the body locator MAY use the "-" character to
indicate a non-existent array element when it is necessary to insert an element after the last element
of an existing array.
The element referenced (or created) by a body security information location MUST be
required and of type "string".
If name is not given, it is assumed the entire body is to be used as the security
parameter.
cookie:name.uri:name. This is more general than the
query mechanism but more complex.
The value uri SHOULD be specified for the name in in a security scheme only
if query is not applicable.
The URIs provided in interactions where a security scheme using uri as the value for
in
MUST be a URI template including the defined variable.
auto:auto is set for the in field of a
SecurityScheme, then the name field SHOULD NOT be set.
In this case, the application of the SecurityScheme is subject to the respective
specification for the given protocol (e.g. [[!RFC8288]] when using the
BasicSecurityScheme with HTTP).
If multiple parameters are needed for a security scheme, repeat the security scheme definition for each
parameter and combine them using a combo security scheme and allOf. In some
cases parameters may not actually be secret but a user may wish to leave them out of the TD to help
protect privacy. As an example of this, some security mechanisms require both a client identifier and a
secret key. In theory, the client identifier is public however it may be hard to update and pose a
tracking risk. In such a case it can be provided as an additional security parameter so it does not appear
in the TD.
The names of URI variables declared in a SecurityScheme MUST be distinct from all other
URI variables declared in the TD.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
@type |
JSON-LD keyword to label the object with semantic tags (or types). | optional |
string or
Array of
string
|
description |
Provides additional (human-readable) information based on a default language. | optional |
string
|
descriptions |
Can be used to support (human-readable) information in different languages. Also see MultiLanguage. | optional |
Map of MultiLanguage
|
proxy |
URI of the proxy server this security configuration provides access to. If not given, the corresponding security configuration is for the endpoint. | optional |
anyURI
|
scheme |
Identification of the security mechanism being configured. | mandatory |
string
(e.g., nosec, combo, basic, digest,
bearer, psk, oauth2, apikey, or
auto)
|
The class SecurityScheme has the following subclasses:
NoSecurityScheme
A security configuration corresponding to identified by the
Vocabulary Term
nosec (i.e., "scheme": "nosec"), indicating there is no authentication or other
mechanism required to access the resource.
AutoSecurityScheme
An automatic authentication security configuration identified by the term auto (i.e.,
"scheme": "auto"). This scheme indicates that the security parameters are going to be
negotiated by the underlying protocols at runtime, subject to the respective specifications for the
protocol (e.g. [[!RFC8288]] for Basic Authentication when using HTTP).
ComboSecurityScheme
A combination of other security schemes identified by the Vocabulary Term combo (i.e.,
"scheme": "combo"). Elements of this scheme define various ways in which other named schemes
defined in securityDefinitions, including other
ComboSecurityScheme definitions, are to be combined to
create a new scheme definition.
Exactly one of either oneOf or allOf vocabulary terms MUST be
included.
Only security scheme definitions which can be used together can be combined with allOf. For
example, it is not possible in general to combine different OAuth 2.0 flows together using
allOf unless one applies to a proxy and one to the endpoint. Note that when multiple named
security scheme definitions are listed in a security field the same semantics apply as in an
allOf combination (and the same limitations on allowable combinations). The
oneOf combination is equivalent to using different security schemes on forms that are
otherwise identical. In this sense a oneOf scheme is not an essential feature but it does
avoid redundancy in such cases.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
oneOf |
Array of two or more strings identifying other named security scheme definitions, any one of which, when satisfied, will allow access. Only one may be chosen for use. | mandatory |
Array of
string
|
allOf |
Array of two or more strings identifying other named security scheme definitions, all of which must be satisfied for access. | mandatory |
Array of
string
|
BasicSecurityScheme
Basic Authentication [RFC7617] security configuration identified by the
Vocabulary Term
basic (i.e., "scheme": "basic"), using an unencrypted username and password.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
name |
Name for query, header, cookie, or uri parameters. | optional |
string
|
in |
Specifies the location of security authentication information. | with default |
string (one
of header, query, body, cookie, or
auto)
|
DigestSecurityScheme
Digest Access Authentication [RFC7616] security configuration identified by the
Vocabulary Term
digest (i.e., "scheme": "digest"). This scheme is similar to basic
authentication but with added features to avoid man-in-the-middle attacks.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
name |
Name for query, header, cookie, or uri parameters. | optional |
string
|
in |
Specifies the location of security authentication information. | with default |
string (one
of header, query, body, cookie, or
auto)
|
qop |
Quality of protection. | with default |
string (one
of auth, or auth-int)
|
APIKeySecurityScheme
API key authentication security configuration identified by the
Vocabulary Term
apikey (i.e., "scheme": "apikey"). This scheme is to be used when the access
token is opaque, for example when a key in an unknown or proprietary format is provided by a cloud service
provider. In this case the key may not be using a standard token format. This scheme indicates that the
key provided by the service provider needs to be supplied as part of service requests using the mechanism
indicated by the "in" field.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
name |
Name for query, header, cookie, or uri parameters. | optional |
string
|
in |
Specifies the location of security authentication information. | with default |
string (one
of header, query, body, cookie,
uri, or auto)
|
BearerSecurityScheme
Bearer Token [RFC6750] security configuration identified by the
Vocabulary Term
bearer (i.e., "scheme": "bearer") for situations where bearer tokens are used
independently of OAuth2. If the oauth2 scheme is specified it is not generally necessary to
specify this scheme as well as it is implied. For format, the value
jwt indicates conformance with [RFC7519], jws indicates conformance with [RFC7797], cwt indicates conformance with [RFC8392], and jwe indicates conformance with [RFC7516], with values for alg interpreted consistently with those standards.
Other formats and algorithms for bearer tokens MAY be specified in vocabulary extensions.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
authorization |
URI of the authorization server. | optional |
anyURI
|
name |
Name for query, header, cookie, or uri parameters. | optional |
string
|
in |
Specifies the location of security authentication information. | with default |
string (one
of header, query, body, cookie, or
auto)
|
alg |
Encoding, encryption, or digest algorithm. | with default |
string
(e.g., ES256, or ES512-256)
|
format |
Specifies format of security authentication information. | with default |
string
(e.g., jwt, cwt, jwe, or jws)
|
PSKSecurityScheme
Pre-shared key authentication security configuration identified by the
Vocabulary Term
psk (i.e., "scheme": "psk"). This is meant to identify that a standard is used
for pre-shared keys such as TLS-PSK [[RFC4279]], and that the ciphersuite used for keys will be
established during protocol negotiation.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
identity |
Identifier providing information which can be used for selection or confirmation. | optional |
string
|
OAuth2SecurityScheme
OAuth 2.0 authentication security configuration for systems conformant with [[!RFC6749]] and [[!RFC8252]],
identified by the Vocabulary Term oauth2 (i.e., "scheme": "oauth2").
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
authorization |
URI of the authorization server. | optional |
anyURI
|
token |
URI of the token server. | optional |
anyURI
|
refresh |
URI of the refresh server. | optional |
anyURI
|
scopes |
Set of authorization scope identifiers provided as an array. These are provided in tokens returned
by an authorization server and associated with forms in order to identify what resources a client
may access and how. The values associated with a form SHOULD be chosen from those defined in an
OAuth2SecurityScheme active on that form.
|
optional |
string or
Array of
string
|
flow |
Authorization flow. | mandatory |
string
(e.g., code, or client)
|
For the code flow both authorization and token
vocabulary terms MUST be included.
For the client flow token vocabulary term MUST be included.
For the client flow authorization vocabulary term MUST NOT be
included.
The mandatory elements for each flow are summarized in the following table:
| Element | code |
client |
|---|---|---|
authorization |
mandatory | omit |
token |
mandatory | mandatory |
refresh |
optional | optional |
The present model provides a representation for (typed) Web links and Web forms exposed by a Thing.
The Link class definition reflects a very common subset of the terms defined in Web Linking
[[!RFC8288]]. The defined terms can be used, e.g., to describe the relation to another Thing such as
a Lamp Thing is controlled by a Switch Thing. The Form class corresponds to a
newly introduced form of hypermedia control to manipulate the state of Things (and other Web
resources).
LinkA link can be viewed as a statement of the form "link context has a relation type resource at link target", where the optional target attributes may further describe the resource.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
href |
Target IRI of a link or submission target of a form. | mandatory |
anyURI
|
type |
Target attribute providing a hint indicating what the media type [RFC2046] of the result of dereferencing the link should be. | optional |
string
|
rel |
A link relation type identifies the semantics of a link. | optional |
string
|
anchor |
Overrides the link context (by default the Thing itself identified by its id) with the
given URI or IRI.
|
optional |
anyURI
|
sizes |
Target attribute that specifies one or more sizes for the referenced icon. Only applicable for relation type "icon". The value pattern follows {Height}x{Width} (e.g., "16x16", "16x16 32x32"). | optional |
string
|
hreflang |
The hreflang attribute specifies the language of a linked document. The value of this must be a valid language tag [[BCP47]]. | optional |
string or
Array of
string
|
The hreflang attribute is allowed to be a string or array in this
version of the spec. Depending on the result of [[LINKSET-MEDIA-TYPES]] the values of
hrefLang can be restricted to array only.
Link relations can be used to describe relations such as to other Things (e.g., a Switch Thing controls a Lamp Thing), to a specific kind of Thing Models (e.g., a Thing Description is an instance of a specific Thing Model), or to further documentations information (e.g., device manual of a Thing). It is recommended to reuse existing and established Link Relation definitions from IANA.
In the following a best practice relation type table is introduced that is recommended to use within WoT Thing Description or Thing Model instances.
| Value | Occurrence | Explanation | Source of value origin |
|---|---|---|---|
icon
|
0..* | Imports an icon associated to the Thing (e.g., for UI purposes). | IANA Link Relation |
service-doc
|
0..* | Relation to a resource that provide (human-readable) documentation or descriptions. | IANA Link Relation |
alternate
|
0..* | Point to alternative representation of the Thing (i.e. RDF-Turtle, human-readable HTML document, ...). | IANA Link Relation |
type
|
0..1 | Indicate that the Thing is an instance of the target resource such as to a Thing Model. | IANA Link Relation |
tm:extends
|
0..1 | Extends an existing definition of the target resource such as a Thing Model. Only applicable for Thing Model definitions. | W3C WoT Thing Model |
tm:submodel
|
0..* | Used to compose one or multiple Thing Models. Only applicable for Thing Model definitions. | W3C WoT Thing Model |
manifest
|
0..* | Point to the web app manifest of a web application which provides, e.g., a user interface with which a user can interact with the Thing (also see [[APPMANIFEST]]). | IANA Link Relation |
proxy-to
|
0..* |
Target resource provide the address of a proxy. Additional security metadata can be provided using
the proxy field in a SecurityScheme.
|
W3C WoT Security and WoT Binding Template |
collection
|
0..1 | Points to a collections of Things. | IANA Link Relation |
item
|
0..* | Points to a Thing that is member of the current Thing collections. | IANA Link Relation |
predecessor-version
|
0..1 | Points to a previous Thing Description or Thing Model version. | IANA Link Relation |
controlledBy
|
0..* | Refers to a Thing that controls the context Thing. | W3C Thing Description |
FormA form can be viewed as a statement of "To perform an operation type operation on form context, make a request method request to submission target" where the optional form fields may further describe the required request. In Thing Descriptions, the form context is the surrounding Object, such as Properties, Actions, and Events or the Thing itself for meta-interactions.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
href |
Target IRI of a link or submission target of a form. | mandatory |
anyURI
|
contentType |
Assign a content type based on a media type (e.g., text/plain) and potential parameters
(e.g., charset=utf-8) for the media type [RFC2046].
|
optional |
string
|
contentCoding |
Content coding values indicate an encoding transformation that has been or can be applied to a representation. Content codings are primarily used to allow a representation to be compressed or otherwise usefully transformed without losing the identity of its underlying media type and without loss of information. Examples of content coding include "gzip", "deflate", etc. . | optional |
string
|
security |
Set of security definition names, chosen from those defined in securityDefinitions.
These must all be satisfied for access to resources.
|
optional |
string or
Array of
string
|
scopes |
Set of authorization scope identifiers provided as an array. These are provided in tokens returned
by an authorization server and associated with forms in order to identify what resources a client
may access and how. The values associated with a form SHOULD be chosen from those defined in an
OAuth2SecurityScheme active on that form.
|
optional |
string or
Array of
string
|
response |
This optional term can be used if, e.g., the output communication metadata differ from input metadata (e.g., output contentType differ from the input contentType). The response name contains metadata that is only valid for the primary response messages. | optional |
ExpectedResponse
|
additionalResponses |
This optional term can be used if additional expected responses are possible, e.g. for error reporting. Each additional response needs to be distinguished from others in some way (for example, by specifying a protocol-specific error code), and may also have its own data schema. | optional |
Array of AdditionalExpectedResponse
|
subprotocol |
Indicates the exact mechanism by which an interaction will be accomplished for a given protocol when
there are multiple options. For example, for HTTP and Events, it indicates which of several
available mechanisms should be used for asynchronous notifications such as long polling
(longpoll), WebSub [websub] (websub), Server-Sent Events (sse) [html] (also known as EventSource). Please note that there is no restriction on the subprotocol
selection and other mechanisms can also be announced by this subprotocol term.
|
optional |
string
(e.g., longpoll, websub, or sse)
|
op |
Indicates the semantic intention of performing the operation(s) described by the form. For example, the Property interaction allows get and set operations. The protocol binding may contain a form for the get operation and a different form for the set operation. The op attribute indicates which form is for which and allows the client to select the correct form for the operation required. op can be assigned one or more interaction verb(s) each representing a semantic intention of an operation. | with default |
string or
Array of
string (one
of readproperty, writeproperty, observeproperty,
unobserveproperty, invokeaction, queryaction,
cancelaction, subscribeevent, unsubscribeevent,
readallproperties, writeallproperties,
readmultipleproperties, writemultipleproperties,
observeallproperties, unobserveallproperties,
subscribeallevents, unsubscribeallevents, or queryallactions)
|
Possible values for the contentCoding property can be found, e.g., in the
IANA HTTP content coding registry.
The list of possible operation types of a form is fixed. As of this version of the specification, it only includes the well-known types necessary to implement the WoT interaction model described in [wot-architecture11]. Future versions of the standard may extend this list but operations types MUST be restricted to the values in the table below.
| Operation Type | Description |
|---|---|
| readproperty | Identifies the read operation on Property Affordances to retrieve the corresponding data. |
| writeproperty | Identifies the write operation on Property Affordances to update the corresponding data. |
| observeproperty | Identifies the observe operation on Property Affordances to be notified with the new data when the Property is updated. |
| unobserveproperty | Identifies the unobserve operation on Property Affordances to stop the corresponding notifications. |
| invokeaction | Identifies the invoke operation on Action Affordances to perform the corresponding action. |
| queryaction | Identifies the querying operation on Action Affordances to get the status of the corresponding action. |
| cancelaction | Identifies the cancel operation on Action Affordances to cancel the ongoing corresponding action. |
| subscribeevent | Identifies the subscribe operation on Event Affordances to be notified by the Thing when the event occurs. |
| unsubscribeevent | Identifies the unsubscribe operation on Event Affordances to stop the corresponding notifications. |
| readallproperties | Identifies the readallproperties operation on a Thing to retrieve the data of all Properties in a single interaction. |
| writeallproperties | Identifies the writeallproperties operation on a Thing to update the data of all writable Properties in a single interaction. |
| readmultipleproperties | Identifies the readmultipleproperties operation on a Thing to retrieve the data of selected Properties in a single interaction. |
| writemultipleproperties | Identifies the writemultipleproperties operation on a Thing to update the data of selected writable Properties in a single interaction. |
| observeallproperties | Identifies the observeallproperties operation on Properties to be notified with new data when any Property is updated. |
| unobserveallproperties | Identifies the unobserveallproperties operation on Properties to stop notifications from all Properties in a single interaction. |
| queryallactions | Identifies the queryallactions operation on a Thing to get the status of all Actions in a single interaction. |
| subscribeallevents | Identifies the subscribeallevents operation on Events to subscribe to notifications from all Events in a single interaction. |
| unsubscribeallevents | Identifies the unsubscribeallevents operation on Events to unsubscribe from notifications from all Events in a single interaction. |
A Thing Description of a WoT producer may have multiple forms entries with, e.g., different protocol and/or content types declarations that a Consumer could possibly support. In that case the Consumer may choose any form entry that works (e.g., the protocol and content type is supported) for them. When one form is chosen, it is expected that the Consumer will continue to use it as long as possible for every new interaction with the WoT producer.
Protocols that can be used with TDs follow request-response or eventing mechanisms. The Data Schema of
an affordance generally correlates with the op keywords used in forms. The
table below informatively summarizes the available data schema related terms with the
op keywords.
| Operation Type | Consumer to Thing DataSchema Correlation | Thing to Consumer DataSchema Correlation |
|---|---|---|
| readproperty | No correlation. | All fields in the Property Affordance without "writeOnly":true. |
| writeproperty | All fields in the Property Affordance without "readOnly":true. |
No correlation. additionalResponses can be used in the form level. |
| observeproperty | No correlation. | All fields in the Property Affordance without "writeOnly":true. |
| unobserveproperty | No correlation. | No correlation. |
| invokeaction | Value of the input key. |
Value of the output key. |
| queryaction | No correlation. | No correlation. additionalResponses can be used in the form level. |
| cancelaction | No correlation. | No correlation. additionalResponses can be used in the form level. |
| subscribeevent |
Value of the subscription key with all fields without "readOnly":true
|
Value of the subscription key with all fields without "writeOnly":true
|
| unsubscribeevent |
Value of the subscription key with all fields without "readOnly":true
|
Value of the subscription key with all fields without "writeOnly":true
|
Writing to a property does not necessarily mean that a new value will be sent to the Consumer observing the property. It depends on the protocol and implementation.
Further specification of how to map operations to data schemas, as well as mapping meta operations such
as readallproperties
can be found in the respective protocol specification of the [[WOT-BINDING-TEMPLATES]].
The optional response name-value pair can be used to provide metadata for the expected
response message. With the core vocabulary, it can include only content type information, but TD Context
Extensions could be applied.
If no response name-value pair is provided, it MUST be assumed that the content type of
the response is equal to the content type assigned to the Form instance.
Note that contentType within an
ExpectedResponse
Class does not have a
Default Value.
In some cases additional responses might be possible. One example of this is error responses but in some
cases there might also be additional successful responses. In this case, the
response name-value pair is still used for the primary response but
additionalResponses may also be provided, whose value is an array of
AdditionalExpectedResponse objects. Each additional response must be distinguished in some
way from the primary response, either by contentType or by protocol-specific settings such
as error code header values. Each additional response may also have a data schema which can differ from
the normal output data schema for the interaction.
In some use cases, input and output data might be represented in a different form, for instance an Action that accepts JSON, but returns an image. In such a case, the optional `response` key-value pair can describe the content type of the expected response. As there is no default value defined, the following assertions apply:
Similar considerations apply to additional responses:
The different cases on the variation of request and response are explained above. The tables at summarize these cases in a concise manner.
ExpectedResponseCommunication metadata describing the expected response message for the primary response.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
contentType |
Assign a content type based on a media type (e.g., text/plain) and potential parameters
(e.g., charset=utf-8) for the media type [RFC2046].
|
optional |
string
|
AdditionalExpectedResponseCommunication metadata describing the expected response message for additional responses.
| Vocabulary term | Description | Assignment | Type |
|---|---|---|---|
success |
Signals if an additional response should not be considered an error. | with default |
boolean
|
schema |
Used to define the output data schema for an additional response if it differs from the default
output data schema. Rather than a DataSchema object, the name of a previous definition
given in a schemaDefinitions map must be used.
|
optional |
string
|
contentType |
Assign a content type based on a media type (e.g., text/plain) and potential parameters
(e.g., charset=utf-8) for the media type [RFC2046].
|
optional |
string
|
When assignments in a TD are missing, a TD Processor MUST follow the Default Value assignments expressed in the table of Default Value Definitions.
The following table gives all Default Values defined in the TD Information Model.
| Class | Vocabulary Term | Default Value | Comment |
|---|---|---|---|
PropertyAffordance |
readOnly |
false |
The default value for this vocabulary term applies only to the PropertyAffordance level
definition. In other contexts, such as DataSchema definitions, the vocabulary term is
optional.
|
PropertyAffordance |
writeOnly |
false |
The default value for this vocabulary term applies only to the PropertyAffordance level
definition. In other contexts, such as DataSchema definitions, the vocabulary term is
optional.
|
PropertyAffordance |
observable |
false |
|
ActionAffordance |
safe |
false |
|
ActionAffordance |
idempotent |
false |
|
AdditionalExpectedResponse |
success |
false |
|
Form |
contentType |
application/json |
|
Form |
op |
Array of string with the
elements readproperty and writeproperty when readOnly and
writeOnly are set to false or
Array of string with the
element readproperty when readOnly is set to true or
Array of string with the
element writeproperty when writeOnly is set to true.
|
If defined within an instance of PropertyAffordance |
Form |
op |
invokeaction |
If defined within an instance of ActionAffordance |
Form |
op |
Array of string with the elements subscribeevent and
unsubscribeevent
|
If defined within an instance of EventAffordance |
BasicSecurityScheme |
in |
header |
|
DigestSecurityScheme |
in |
header |
|
DigestSecurityScheme |
qop |
auth |
|
APIKeySecurityScheme |
in |
query |
|
BearerSecurityScheme |
in |
header |
|
BearerSecurityScheme |
alg |
ES256 |
|
BearerSecurityScheme |
format |
jwt |
Additionally, following considerations apply to the use of default values:
forms entry has multiple op values, the form MUST NOT restrict the
messages that can be sent by the Consumer to only one operation.
For example, a form with "op":["readproperty", "writeproperty"] cannot contain
htv:methodName. Typically, a TD Processor will internally extend the multiple
op values to separate forms entries and associate each operation with the concrete
protocol request using the default assumption. The address information (e.g., href) and other
metadata are carried over to the extended version. Please see
the example
in the HTTP Binding.
@context, a TD Processor SHOULD expand the @context by adding definitions
for those prefixes according to bindings defined in the [[WOT-BINDING-REGISTRY]].
This requires that the TD Processor is aware of the prefixes used in the TD. This is typically the
case when the TD Processor has been implemented to support a specific set of protocols and data
formats. See also [[[#example-context-expansion]]].
Note that the default values and the expansion mechanisms can be applied in a sequence. For example, the lack
of "readOnly" and "writeOnly" means that the default value false is
applied to both, following
[[[#table-default-values-of-vocabulary-terms-that-are-used-when-the-terms-are-not-present-in-a-td]]], which in
turn means that the default value for "op" is ["readproperty", "writeproperty"].
Using the default methods for the protocol binding, this means that both "GET" and
"PUT" correspond to "readproperty" and "writeproperty", respectively.
However, following the expansion of multiple operations mechanism, two
separate forms are created internally, one for each operation and indicating the default method. Then, the
default context expansion mechanism is applied to add the
definition of the htv prefix to the @context. The example below shows the initial TD
and the fully expanded TD after applying all default values and expansion mechanisms.
WoT Thing Descriptions represent Things and are modeled and structured based on
. This section defines a JSON-based representation format for
Things, a serialization of instances of the Class Thing defined by the
TD Information Model.
A TD Processor MUST be able to serialize Thing Descriptions into the JSON format [[!RFC8259]] and/or deserialize Thing Descriptions from that format, according to the rules noted in and .
The JSON serialization of the TD Information Model is aligned with the syntax of JSON-LD 1.1 [[?json-ld11]] in order to streamline semantic evaluation. Hence, the TD representation format can be processed either as raw JSON or with a JSON-LD 1.1 processor (for details about semantic processing, please refer to and the documentation under the namespace IRIs, e.g., https://www.w3.org/2019/wot/td).
In order to support interoperable internationalization, TDs MUST be serialized according to the requirements defined in Section 8.1 of RFC8259 [[!RFC8259]] for open ecosystems. In summary, this requires the following:
The TD Information Model is constructed, so that there is an easy mapping between model Objects and JSON types. Every Class instances maps to a JSON object, where each name-value pair of the Class instance is a member of the JSON object.
Every Simple Type mentioned in (i.e., string,
anyURI, dateTime, integer, unsignedInt,
double, and boolean) maps to a primitive JSON type (string, number, boolean), as per
the rules listed below. These rules apply to values in name-value pairs:
string or anyURI MUST be serialized as JSON strings.
dateTime
MUST be serialized as JSON strings following the "date-time" format specified by [[RFC3339]].
Examples would include 2019-05-24T13:12:45Z and 2015-07-11T09:32:26+08:00.
Values that are of type dateTime SHOULD use the literal Z
representing the UTC time zone instead of an offset.
integer or unsignedInt
MUST be serialized as JSON numbers without a fraction or exponent part.
double
MUST be serialized as JSON number.
boolean
MUST be serialized as JSON boolean.
Every complex type of the TD Information Model (i.e., Arrays, Maps, and Class instances) maps to a structured JSON type (array and object), as per the rules listed below:
A Thing Description serialization may omit Vocabulary Term for which Default Values are defined, as listed in the table given in .
The following example shows the TD instance from Example 1 with a checkbox to also include the members with Default Values (=checkbox checked). These members can be omitted (=checkbox unchecked) to simplify the TD serialization. Note that a TD Processor interprets these omitted members identically as if they were explicitly present with a given Default Value.
Please note that, depending on the Protocol Binding used, additional protocol-specific Vocabulary Terms may apply. They may also have associated Default Values, and hence can also be omitted as explained in this subsection. Further information can be found in .
A Thing Description is a data structure rooted at an Object of type
Thing. In turn, a JSON serialization of the Thing Description is a JSON object, which is the root of a syntax
tree constructed from the TD Information Model.
The root element of a TD Serialization MUST be a JSON object that includes a member with the name
@context and a value of type string or array that equals or respectively contains
https://www.w3.org/ns/wot-next/td.
In general, this URI is used to identify the TD representation format version defined by this specification.
For JSON-LD processing [[?json-ld11]], this URI specifies the Thing Description context file. An
@context of type array indicates TD Context Extensions (see
for details).
{
"@context": "https://www.w3.org/ns/wot-next/td",
// ...
}
All name-value pairs of an instance of Thing, where the name is a Vocabulary Term in
the Signature of Thing, MUST be serialized as JSON members of the root object.
A TD snippet for a serialized root object including all mandatory and optional members is given below:
{
"@context": "https://www.w3.org/ns/wot-next/td",
"@type": "Thing",
"id": "urn:uuid:1b37933b-3212-4dad-9c2c-74c6042c3e2b",
"title": "MyThing",
"titles": {/*...*/},
"description": "Human readable information.",
"descriptions": {/*...*/},
"support": "mailto:support@example.com",
"version": {/*...*/},
"created": "2018-11-14T19:10:23.824Z",
"modified": "2019-06-01T09:12:43.124Z",
"securityDefinitions": {/*...*/},
"security": /*...*/,
"base": "https://servient.example.com/",
"properties": {/*...*/},
"actions": {/*...*/},
"events": {/*...*/},
"links": [...],
"forms": [...]
}
All values assigned to
version, securityDefinitions, descriptions,
schemaDefinitions, uriVariables, properties, actions,
and
events
in an instance of the Class Thing
MUST be serialized as JSON objects.
All values assigned to
links, and
forms
in an instance of the Class Thing MUST be serialized as JSON arrays containing JSON
objects as defined in and
, respectively.
The value assigned to
security
in an instance of Class Thing
MUST be serialized as JSON string or as JSON array whose elements are JSON strings.
JSON members named title and description are used within a TD document to provide
human-readable metadata. They can be used as comments for developers inspecting a TD document or as display
texts for user interface.
As defined in , the base text direction used to display human-readable metadata can
either be estimated using heuristics such as the first-strong rule or inferred from language information. In
TD documents the default language is defined by a value assigned to @language in the
@context, and this, along with a script subtag if necessary, can be used to determine a base
text direction.
However, when interpreting human-readable text, each human-readable string value MUST be processed
independently.
In other words, a TD Processor cannot carry forward changes in direction from one string to another,
or infer direction for one string from another one elsewhere in the TD.
A TD snippet using title and description is shown below. The default language is
set to en through the definition of the @language member within a JSON object in
the @context array.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{ "@language": "en" }
],
"title": "MyThing",
"description": "Human readable information.",
// ...
"properties": {
"on": {
"title": "On/Off",
"type": "boolean",
"forms": [...]
},
"status": {
"title": "Status",
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
Strings on the Web [[?STRING-META]] recommends the use of metadata to determine the
base direction of string values.
Given that the Thing Description format is based on JSON-LD 1.1 [[?json-ld11]],
@direction with the string values "ltr", "rtl" and null value
null MAY be used inside the @context to indicate the default text direction for
the human readable strings in the entire TD document.
When metadata such as @direction is not present, TD Consumers SHOULD use
first-strong detection as a fallback.
For the MultiLanguage Map, TD Consumers MAY infer the
base direction from the language tag of the individual strings.
These can be summarized into the steps below that can be implemented by TD Consumers based on the
information provided in a TD.
@direction found in the @context.
@language and then guess the direction of the
text
dir=auto in HTML attributes.
Please note string-specific direction metadata is not possible in the current version of the specification. The working group is working on a mechanism to make it possible. After which, that will be the preferred way to handle text direction for TD Consumers.
Additionally, the example below illustrates the use of the @direction and
@language terms. See [[?json-ld11]] and [[string-meta]] for more detailed information.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"@language": "ar-EG",
"@direction": "rtl"
}
],
"title": "شيء يخصني يقيس درجة الحرارة",
"description": "شيء يقيس درجة الحرارة و يظهر حالته",
// ...
"properties": {
"temp": {
"title": "درجة الحرارة",
"type": "boolean",
"forms": [...]
},
"status": {
"title": "حالة",
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
The JSON members named titles and descriptions are used within the TD document to
provide human-readable metadata in multiple languages within a single TD document.
All name-value pairs of a MultiLanguage Map MUST be serialized as members of a JSON
object, where the name is a valid language tag as defined by [[!BCP47]] (also see
W3C I18N Glossary) and the value is a
human-readable string in the language indicated by the tag.
See for details.
All MultiLanguage object within a TD document SHOULD contain the same set of language
members.
A TD snippet using titles and descriptions at different levels is given below:
{
"@context": "https://www.w3.org/ns/wot-next/td",
"title": "MyThing",
"titles": {
"en": "MyThing",
"de": "MeinDing",
"ja": "私の物",
"zh-Hans": "我的东西",
"zh-Hant": "我的東西"
},
"descriptions": {
"en": "Human readable information.",
"de": "Menschenlesbare Informationen.",
"ja": "人間が読むことができる情報",
"zh-Hans": "人们可阅读的信息",
"zh-Hant": "人們可閱讀的資訊"
},
// ...
"properties": {
"on": {
"titles": {
"en": "On/Off",
"de": "An/Aus",
"ja": "オンオフ",
"zh-Hans": "开关",
"zh-Hant": "開關" },
"type": "boolean",
"forms": [...]
},
"status": {
"titles": {
"en": "Status",
"de": "Zustand",
"ja": "状態",
"zh-Hans": "状态",
"zh-Hant": "狀態" },
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
TD instances may also combine the use of title and description with
titles and descriptions.
When title and titles or description and
descriptions are present within the same JSON object, the values of title and
description MAY be seen as the default text.
When title and titles or description and
descriptions are present in a TD document, each title and
description member SHOULD have a corresponding titles and
descriptions member, respectively.
The language of the default text is indicated by the default language, which is usually set by the creator
of the Thing Description instance.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{ "@language": "de" }
],
"title": "MeinDing",
"titles": {
"en": "MyThing",
"de": "MeinDing",
"ja": "私の物",
"zh-Hans": "我的东西",
"zh-Hant": "我的東西"
},
"description": "Menschenlesbare Informationen.",
"descriptions": {
"en": "Human readable information.",
"de": "Menschenlesbare Informationen.",
"ja": "人間が読むことができる情報",
"zh-Hans": "人们可阅读的信息",
"zh-Hant": "人們可閱讀的資訊"
},
// ...
"properties": {
"on": {
"title": "An/Aus",
"titles": {
"en": "On/Off",
"de": "An/Aus",
"ja": "オンオフ",
"zh-Hans": "开关",
"zh-Hant": "開關" },
"type": "boolean",
"forms": [...]
},
"status": {
"title": "Zustand",
"titles": {
"en": "Status",
"de": "Zustand",
"ja": "状態",
"zh-Hans": "状态",
"zh-Hant": "狀態" },
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
Another possibility to set the default language is through a language negotiation mechanism, such as the
Accept-Language header field of HTTP.
In cases where the default language has been negotiated, an @language member MUST be present
to indicate the result of the negotiation and the corresponding default language of the returned content.
When the default language has been negotiated successfully, TD documents SHOULD include the appropriate
matching values for the members title and description in preference to
MultiLanguage objects in titles and descriptions members.
Note however that Things MAY choose to not support such dynamically-generated TDs nor to support language
negotiation (e.g., because of resource constraints).
There is no guarantee that strings in TDs will be displayed in an HTML rendering context. In fact, to mitigate the XSS security risk described in , HTML tags embedded in strings sourced from TDs should be sanitized (and so not interpreted as HTML) in applications embedding these strings in web pages or web applications. Therefore HTML embedded in strings is not an appropriate mechanism for specifying text rendering direction.
version
All name-value pairs of an instance of VersionInfo, where the name is a
Vocabulary Term included in the Signature of VersionInfo, MUST be serialized as
JSON members with the Vocabulary Term as name.
A TD snippet of a version information object is given below:
{
// ...
"version": { "instance": "1.2.1" },
// ...
}
The version member is intended as container for additional application- and/or device-specific
version information based on TD Context Extensions. See for
details.
securityDefinitions and security
In a Thing instance, the value assigned to securityDefinitions is a Map of
instances of SecurityScheme.
All name-value pairs of a Map of SecurityScheme instances MUST be serialized as
members of the JSON object that results from serializing the Map; the name of a pair MUST be
serialized as a JSON string and the value of the pair, an instance of SecurityScheme, MUST be
serialized as a JSON object.
All name-value pairs of an instance of one of the Subclasses of SecurityScheme, where
the name is a Vocabulary Term included in the Signature of that Subclass or in the
Signature of SecurityScheme, MUST be serialized as members of the JSON object that
results from serializing the SecurityScheme Subclass's instance, with the
Vocabulary Term as name.
The following TD snippet shows a simple security configuration specifying basic username/password
authentication in the header. The value given for in is actually the
Default Value (header) and could be omitted. A named security configuration
(basic_sc) is given in the securityDefinitions map. In this example, that
definition is activated by including its JSON name in the security member.
{
// ...
"securityDefinitions": {
"basic_sc": {
"scheme": "basic",
"in": "header"
}
},
"security": "basic_sc",
// ...
}
Security configuration in the TD is mandatory.
At least one security definition MUST be activated through the
security member at the Thing level (i.e., in the TD root object).
This configuration can be seen as the default security mechanism required to interact with the Thing.
Security definitions MAY also be activated at the level of the form elements by including a
security member in form objects, which overrides (i.e., completely replace) all definitions
activated at the Thing level.
The nosec security scheme is provided for the case that no security is needed. The minimal
security configuration for a Thing is activation of the nosec security scheme at the
Thing level, as shown in the following example:
{
"@context": "https://www.w3.org/ns/wot-next/td",
"id": "urn:uuid:e9ecb6ad-cd4c-481b-96ce-5b4c57ddb844",
"title": "MyThing",
"description": "Human readable information.",
"support": "https://servient.example.com/contact",
"securityDefinitions": { "nosec_sc": { "scheme": "nosec" }},
"security": "nosec_sc",
"properties": {/*...*/},
"actions": {/*...*/},
"events": {/*...*/},
"links": [/*...*/]
}
To give a more complex example, suppose we have a Thing where all
Interaction Affordances require basic authentication except for one, for which no authentication is
required. For the status Property and the toggle Action,
basic authentication is required and defined at the Thing level. For the
overheating Event, however, no authentication is required, and hence the security
configuration is overridden at the form level.
{
// ...
"securityDefinitions": {
"basic_sc": {"scheme": "basic"},
"nosec_sc": {"scheme": "nosec"}
},
"security": "basic_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://mylamp.example.com/status"
}]
}
},
"actions": {
"toggle": {
// ...
"forms": [{
"href": "https://mylamp.example.com/toggle"
}]
}
},
"events": {
"overheating": {
// ...
"forms": [{
"href": "https://mylamp.example.com/oh",
"security": "nosec_sc"
}]
}
}
}
TDs can specify a combination of security schemes as well. Below is a TD snippet showing digest
authentication on a proxy combined with bearer token authentication on the Thing. In the
digest scheme, the Default Value of in (i.e., header) is
omitted, but still applies. Note that the corresponding private security configuration such as
username/password and tokens need to be configured in the Consumer to interact successfully. When
activating multiple security definitions, the security member becomes an array.
{
// ...
"securityDefinitions": {
"proxy_sc": {
"scheme": "digest",
"proxy": "https://portal.example.com/"
},
"bearer_sc": {
"scheme": "bearer",
"in": "header",
"format": "jwt",
"alg": "ES256",
"authorization": "https://servient.example.com:8443/"
}
},
"security": ["proxy_sc", "bearer_sc"],
// ...
}
However, the use of an array with multiple elements to combine security schemes in a
security element is now deprecated, instead a
ComboSecurityScheme
SHOULD be used.
In the following example, which is exactly equivalent to the one above, this is demonstrated:
{
// ...
"securityDefinitions": {
"proxy_sc": {
"scheme": "digest",
"proxy": "https://portal.example.com/"
},
"bearer_sc": {
"scheme": "bearer",
"in": "header",
"format": "jwt",
"alg": "ES256",
"authorization": "https://servient.example.com:8443/"
},
"combo_sc": {
"scheme": "combo",
"allOf": ["proxy_sc", "bearer_sc"]
}
},
"security": "combo_sc",
// ...
}
security in Forms
Security configurations can also be specified for different forms within the same
Interaction Affordance. This may be required for devices that support multiple protocols, for
example HTTP and CoAP [[?RFC7252]], which support different security mechanisms. This is also useful when
alternative authentication mechanisms are allowed. Here is a TD snippet demonstrating three possible ways
to activate a Property affordance: via HTTPS with basic authentication, with digest authentication, with
bearer token authentication. In other words, the use of different security configurations within multiple
forms provides a way to combine security mechanisms in an "OR" fashion. In contrast, putting multiple
security configurations in the same security member combines them in an "AND" fashion, since
in that case they would all need to be satisfied to allow activation of the Interaction Affordance.
Note that activating one (default) configuration at the Thing level is still mandatory.
{
// ...
"securityDefinitions": {
"basic_sc": { "scheme": "basic" },
"digest_sc": { "scheme": "digest" },
"bearer_sc": { "scheme": "bearer" }
},
"security": "basic_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://mylamp.example.com/status"
}, {
"href": "https://mylamp.example.com/status",
"security": "digest_sc"
}, {
"href": "https://mylamp.example.com/status",
"security": "bearer_sc"
}]
}
},
// ...
}
ComboSecurityScheme
To avoid redundancy in this case, e.g., repeating the details of the form elements, a
ComboSecurityScheme with oneOf can be used
instead.
{
// ...
"securityDefinitions": {
"basic_sc": { "scheme": "basic" },
"digest_sc": { "scheme": "digest" },
"bearer_sc": { "scheme": "bearer" },
"combo_sc": {
"scheme": "combo",
"oneOf": [ "basic_sc", "digest_sc", "bearer_sc" ]
}
},
"security": "combo_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://mylamp.example.com/status"
}]
}
},
// ...
}
As another more complex example, OAuth 2.0 makes use of scopes. These are identifiers that may appear in
tokens and must match with corresponding identifiers in a resource to allow access to that resource (or
Interaction Affordance in the case of W3C WoT). For example, in the following, the
status Property can be read by Consumers using bearer tokens containing the scope
limited, but the configure Action can only be invoked with a token containing
the special scope. Scopes are not identical to roles, but are often associated with them; for
example, perhaps only those in an administrative role are authorized to perform "special" interactions.
Tokens can have more than one scope and are issued by dedicated web services to users. In this example, an
administrator could be issued tokens with both the limited and special scopes,
while ordinary users could be provided with tokens with the limited scope.
{
// ...
"securityDefinitions": {
"oauth2_sc": {
"scheme": "oauth2",
"flow": "client",
"token": "https://example.com/token",
"scopes": ["limited", "special"]
}
},
"security": "oauth2_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://scopes.example.com/status",
"scopes": ["limited"]
}]
}
},
"actions": {
"configure": {
// ...
"forms": [{
"href": "https://scopes.example.com/configure",
"scopes": ["special"]
}]
}
},
// ...
}
A Thing can require an onboarding process that results in the Consumer requiring an API key to interact with the Thing. This API key can be included in the request to the Thing in different ways as the API key scheme specifies. Below is an example of how it can be used as a URI template where the API key should be replaced in the URI by the Consumer when sending an HTTPS request.
{
// ...
"securityDefinitions": {
"apikey_key": {
"scheme": "apikey",
"in": "uri",
"name": "adminKey"
}
},
"security": "apikey_key",
"properties": {
"status": {
// ...
"forms": [{
"href": "https://example.com/{adminKey}/status",
// ...
}]
}
},
// ...
}
To give another example of the use of the
ComboSecurityScheme in addition to the use of URI
templates example shown above, suppose there is a security scheme where a client ID and a "secret" key
provided by a cloud service provider must both be embedded in the URL. Technically, only the key is
actually secret and must be handled out-of-band, and the client ID, which is not secret, could be embedded
in the TD. However, if the client ID cannot be easily rotated we may want to avoid embedding it in the TD
to enhance privacy. In this case we can combine two instances of
APIKeySecurityScheme, both using the uri value for the in location specifier, to declare two URI
variables. These can then (in fact, they must) be used in the href in a
Form where the security scheme is active. An example follows:
{
// ...
"securityDefinitions": {
"apikey_key": {
"scheme": "apikey",
"in": "uri",
"name": "secKey"
},
"apikey_id": {
"scheme": "apikey",
"in": "uri",
"name": "secClientID"
},
"apikey_combo": {
"scheme": "combo",
"allOf": ["apikey_key","apikey_id"]
}
},
"security": "apikey_combo",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://example.com/{secClientID}/status/{secKey}",
// ...
}]
}
},
// ...
}
While not shown in this example, it is legal to declare additional URI template variables using
uriVariables and include them in the same URI template, although the names cannot conflict
with those declared in security schemes. Using a specific prefix as in the above example for URI variables
declared in security schemes can make it easier to avoid name conflicts.
API Key in Body: Security parameters might also be included along with the payload in some systems.
For example, suppose a system requires every payload to be a JSON object including a member named
auth whose value is an object containing a member called key containing an
access key. Depending on the interaction, however, other elements of the JSON object might vary. This
situation can be dealt with using the body security information location. Note that for this
location, the name parameter is actually a JSON pointer evaluated relative to the root of the
DataSchema for each interaction it is bound with, which allows it to be used with payloads
that vary in other respects. As an example, here is a light that has a property to set its brightness and
color and two separate actions to turn it on and off. Although the JSON payloads are different for these
actions the /auth/key element occurs in the same relative location so single JSON pointer can
be used. Note: if the security key occurs in different inconsistent locations, it will be necessary to use
multiple security scheme definitions.
{
// ...
"securityDefinitions": {
"apikey_body": {
"scheme": "apikey",
"in": "body",
"name": "/auth/key"
}
},
"security": "apikey_body",
// ...
"properties": {
"color": {
// ...
"type": "object",
"properties": {
"brightness": {
"type": "number",
// ...
},
"rgb": {
"type": "array",
// ...
},
"auth": {
"type": "object",
"properties": {
"key": {
"type": "string"
}
},
"required": ["key"]
}
},
"required": ["brightness", "rgb", "auth"],
"forms": [{
"href": "https://example.com/color",
// ...
}]
}
},
"action": {
"on": {
// ...
"input": {
"auth": {
"type": "object",
"properties": {
"key": {
"type": "string"
}
},
"required": ["key"]
}
},
"required": ["auth"],
"forms": [{
"href": "https://example.com/on",
// ...
}]
},
"off": {
// ...
"input": {
"auth": {
"type": "object",
"properties": {
"key": {
"type": "string"
}
},
"required": ["key"]
}
},
"required": ["auth"],
"forms": [{
"href": "https://example.com/off",
// ...
}]
}
},
// ...
}
However, it is rather annoying and redundant to add the security information to every data schema. It is
possible to simplify this example by using the feature that the location referenced by a JSON pointer in a
body location will be automatically inserted if it does not exist. In this case the above
example can be simplified to the following. Note that in fact a data schema will effectively be
created for the actions on and off to hold just the security information.
{
// ...
"securityDefinitions": {
"apikey_body": {
"scheme": "apikey",
"in": "body",
"name": "/auth/key"
}
},
"security": "apikey_body",
// ...
"properties": {
"color": {
// ...
"type": "object",
"properties": {
"brightness": {
"type": "number",
// ...
},
"rgb": {
"type": "array",
// ...
}
},
"required": ["brightness", "rgb"],
"forms": [{
"href": "https://example.com/color",
// ...
}]
}
},
"action": {
"on": {
// ...
"required": ["auth"],
"forms": [{
"href": "https://example.com/on",
// ...
}]
},
"off": {
// ...
"forms": [{
"href": "https://example.com/off",
// ...
}]
}
},
// ...
}
properties
The value assigned to properties in a Thing instance is a Map of instances
of PropertyAffordance.
All name-value pairs of a Map of PropertyAffordance instances MUST be serialized as
members of the JSON object that results from serializing the Map; the name of a pair MUST be
serialized as a JSON string and the value of the pair, an instance of PropertyAffordance,
MUST be serialized as a JSON object.
All name-value pairs of an instance of PropertyAffordance, where the name is a
Vocabulary Term included in (one of) the Signatures of PropertyAffordance,
InteractionAffordance, or DataSchema, MUST be serialized as members of the JSON
object that results from serializing the PropertyAffordance instance, with the
Vocabulary Term as name.
See for details on serializing
DataSchema instances.
The value assigned to forms in an instance of PropertyAffordance MUST be
serialized as a JSON array containing one or more JSON object serializations as defined in
.
A snippet for two Property affordances is given below:
actions
In a Thing instance, the value assigned to actions is a Map of instances of
ActionAffordance.
All name-value pairs of a Map of ActionAffordance instances MUST be serialized as
members of the JSON object that results from serializing the Map; the name of a pair MUST be
serialized as a JSON string and the value of the pair, an instance of ActionAffordance, MUST
be serialized as a JSON object.
All name-value pairs of an instance of ActionAffordance, where the name is a
Vocabulary Term included in (one of) the Signatures of ActionAffordance or
InteractionAffordance, MUST be serialized as members of the JSON object that results from
serializing the ActionAffordance instance, with the Vocabulary Term as name.
The values assigned to input and output in an instance of
ActionAffordance
MUST be serialized as JSON objects.
They rely on the Class DataSchema, whose serialization is defined in .
The value assigned to forms in an instance of ActionAffordance MUST be
serialized as a JSON array containing one or more JSON object serializations as defined in
.
A TD snippet of an Action affordance is given below:
events
In a Thing instance, the value assigned to events is a map of instances of
EventAffordance.
All name-value pairs of a Map of EventAffordance instances MUST be serialized as
members of the JSON object that results from serializing the Map; the name of a pair MUST be
serialized as a JSON string and the value of the pair, an instance of EventAffordance, MUST
be serialized as a JSON object.
All name-value pairs of an instance of EventAffordance, where the name is a
Vocabulary Term included in (one of) the Signatures of EventAffordance or
InteractionAffordance, MUST be serialized as members of the JSON object that results from
serializing the EventAffordance instance, with the Vocabulary Term as name.
The values assigned to subscription, data, and cancellation in an
instance of EventAffordance
MUST be serialized as JSON objects.
They rely on the Class DataSchema, whose serialization is defined in .
The value assigned to forms in an instance of EventAffordance MUST be serialized
as a JSON array containing one or more JSON object serializations as defined in
.
A TD snippet of an Event object is given below:
Event affordances have been defined in a flexible manner, in order to adopt existing (e.g., WebSub
[[websub]]) or customer-oriented event mechanisms (e.g., Webhooks). For this reason,
subscription and cancellation can be defined according to the desired mechanism.
Please find further details in [[?WOT-BINDING-TEMPLATES]]. Example
illustrates how Events can use subscription and
cancellation to describe Webhooks.
links
All name-value pairs of an instance of Link, where the name is a
Vocabulary Term included in the Signature of Link, MUST be serialized as
members of the JSON object that results from serializing the Link instance, with the
Vocabulary Term as name.
It is recommended to follow the link relation values as provided in Section . The examples provided below demonstrate the use of different link relation types.
A reference can be provided that points to a Thing (e.g., a controller) that controls the underlying
unit (e.g., a lamp). For this controlledBy can be used:
To point to a developer documentation of a Thing the value service-doc can be used:
{
// ...
"links": [{
"rel": "service-doc",
"href": "https://example.com/howTo",
"type": "application/pdf",
"hreflang": "en"
}]
// ...
}
A superordinate Thing can collect a group of Things and refer to them by using the item value:
{
"title": "Electric Drive",
// ...
"links": [{
"rel": "item",
"href": "coaps://motor1.example.com",
"type": " application/td+json"
},
{
"rel": "item",
"href": "coaps://motor2.example.com",
"type": " application/td+json"
}]
// ...
}
A Thing refers to a group in which it is collected with the collection value:
{
"title": "Electric Motor 1",
"base": "coaps://motor1.example.com",
// ...
"links": [{
"rel": "collection",
"href": "coaps://drive.example.com",
"type": " application/td+json"
}]
// ...
}
forms
All name-value pairs of an instance of Form, where the name is a
Vocabulary Term included in the Signature of Form, MUST be serialized as
members of the JSON object that results from serializing the Form instance, with the
Vocabulary Term as name.
If required, form objects MAY be supplemented with protocol-specific Vocabulary Terms identified with a prefix. See also .
A TD snippet of a form object in the forms array is given below:
uriVariables
href may also carry a URI that contains dynamic variables such as lat and
lon in http://example.org/weather/?lat=35&lon=139. In that case the URI can
be defined as template as defined in [[RFC6570]]: http://example.org/weather/{?lat,long}.
In such a case, the URI Template variables MUST be collected in the JSON-object based
uriVariables member either in the Thing level or in Interaction Affordance level
with the associated (unique) variable names as JSON names.
The serialization of each value in the map assigned to uriVariables in an instance of
Form MUST rely on the Class
DataSchema, whose serialization is defined in .
A TD snippet using a URI Template for query parameters and uriVariables in the Interaction
Affordance level is given below:
{
"@context": ["https://www.w3.org/ns/wot-next/td", {
"htv": "http://www.w3.org/2011/http#"
}],
// ...
"properties": {
"weather": {
// ...
"uriVariables": {
"lat": {
"type": "number",
"minimum": 0,
"maximum": 90,
"description": "Latitude for the desired location in the world" },
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Longitude for the desired location in the world" }
},
"forms": [{
"href": "http://example.org/weather/{?lat,long}",
"htv:methodName": "GET"
}]
},
// ...
},
// ...
}
Alternatively, as defined in [[RFC6570]], uriVariables can be used for replacing the
href structure. An example TD is provided below where a valid request to get the forecast of
Bogota, Colombia would be an HTTP GET request to http://example.org/weather/bogota:
{
"@context": ["https://www.w3.org/ns/wot-next/td", {
"htv": "http://www.w3.org/2011/http#"
}],
// ...
"properties": {
"weather": {
// ...
"uriVariables": {
"city": {
"type": "string",
"description": "City name to find the weather information for"
}
},
"forms": [{
"href": "http://example.org/weather/{city}",
"htv:methodName": "GET"
}]
},
// ...
},
// ...
}
The two examples below can be also combined, while using the same uriVariables feature. An
HTTP GET request to http://example.org/weather/bogota/?unit=Celsius can be described as
follows:
{
"@context": ["https://www.w3.org/ns/wot-next/td", {
"htv": "http://www.w3.org/2011/http#"
}],
// ...
"properties": {
"weather": {
// ...
"uriVariables": {
"city": {
"type": "string",
"description": "City name to find the weather information for"
},
"unit": {
"type": "string",
"enum": ["fahrenheit_value","celsius_value"],
"description": "Desired unit for the temperature value"
}
},
"forms": [{
"href": "http://example.org/weather/{city}/{?unit}",
"htv:methodName": "GET"
}]
},
// ...
},
// ...
}
uriVariables are mainly for properties and events. When retrofitting an existing system, it
may be necessary to use uriVariables for actions. In general, it is recommended to avoid
uriVariables as much as possible when a new WoT-based system is designed.
contentType
The contentType member is used to assign a media type [[!RFC2046]] including media type
parameters as attribute-value pairs separated by a ; character. Example:
{
// ...
"contentType": "text/plain; charset=utf-8",
// ...
}
response
In some use cases, the form metadata of the Interaction Affordance not only describes the request,
but also provides metadata for the expected response. For instance, an Action
takePhoto defines an input schema to submit parameter settings of a camera
(aperture priority, timer, etc.) using JSON for the request payload (i.e.,
"contentType": "application/json"). The output of this action is the photo taken, which is
available in JPEG format, for example. In such cases, the response member is used to indicate
the representation format of the response payload (e.g., "contentType": "image/jpeg"). Here
no output schema is required, as the content type fully specifies the representation format.
A form snippet with the response member is shown below based on the
takePhoto Action described above:
{
// ...
"actions": {
"takePhoto": {
// ...
"forms": [{
"op": "invokeaction",
"href": "http://camera.example.com/api/snapshot",
"contentType": "application/json",
"response": {
"contentType": "image/jpeg"
}
}]
}
},
// ...
}
In cases where responses are not expected to contain a payload and therefore no `contentType` either, an empty `response` object can be used to convey this information.
{
// ...
"actions": {
"brewCoffee": {
"description": "Invoking this action does not return a payload.",
"input": {
"type": "object",
"properties": {
"coffeeType": {
"enum": [
"espresso",
"americano",
"cappuccino",
"latte"
]
},
"useOatMilk": {
"type": "boolean",
"default": false
}
},
"required": [
"coffeeType"
]
},
"forms": [{
"op": "invokeaction",
"href": "http://coffee-maker.example.com/brew-coffee",
"contentType": "application/json",
"response": {}
}]
}
},
// ...
}
additionalResponses
In some cases, the message received from the Thing as part of an Interaction Affordance can differ
due to different reasons. Such reasons could be error cases or alternative responses for a valid response.
In these cases, additionalResponses terms can be used to describe this behavior.
For example, an Action Affordance to turn on a car engine may not work in bad weather conditions or in case the engine needs maintenance. In such a case, the Thing needs to reply with payloads that are not usually used.
A TD snippet with the additionalResponses member in an Action Affordance is
shown below. Its first element ilustrates the case mentioned above when an error response can be sent with
another payload than what is described in the output. The success with the value
false refers to the fact that this payload refers to an error case and
schema allows linking to the payload description used at schemaDefinitions. The
second element within `additionalResponses` also describes an error response, but this time the response
does not have a payload.
{
// ...
"schemaDefinitions": {
"actionErrorPayload": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"enum": ["cold","hot","maintenance"]
},
"timeStamp": {
"description": "UNIX time in numbers indicating when the error happened",
"type": "number"
}
}
}
},
// ...
"actions": {
"startEngine": {
"output": {
"type": "string"
},
"forms": [{
"op": "invokeaction",
"href": "http://mycar.example.com/api/engine",
"contentType": "application/json",
"additionalResponses": [
{
"success": false,
"contentType": "application/json",
"schema": "actionErrorPayload"
},
{
"success": false
},
]
}]
}
},
// ...
}
The additionalResponses term can be used in non-error cases as well. In that case,
success is set to true and another schema can be used to describe the payload.
contentMediaType and contentEncoding
In some cases binary data is embedded in text-based values, e.g., a JSON string-based value embeds a
base64 encoded image. The terms contentMediaType and contentEncoding can be used
to clarify the context and encoding format of such name-value pairs. A sample usage of
contentMediaType and contentEncoding
is shown below:
{
// ...
"properties": {
"image": {
"description": "Provides latest image",
"type": "string",
"contentMediaType": "image/png",
"contentEncoding": "base64",
"forms": [{
"op": "readproperty",
"href": "coaps://mylamp.example.com/lastPicture",
"cov:methodName": "GET",
"contentType": "application/json"
}]
}
},
// ...
}
forms
When forms is present at the top level, it can be used to describe meta interactions offered
by a Thing. For example, the operation types readallproperties and
writeallproperties are for meta interactions with a Thing by which
Consumers can read, write or observe all properties at once. In the example below, a
forms member is included in the TD root object and the Consumer can use the submission
target https://mylamp.example.com/properties both to read or write all Properties (i.e.,
on, brightness, and timer) of the Thing in a single protocol
transaction.
{
// ...
"properties": {
"on": {
"type": "boolean",
"forms": [...]
},
"brightness": {
"type": "number",
"forms": [...]
},
"timer": {
"type": "integer",
"forms": [...]
}
},
// ...
"forms": [{
"op": "readallproperties",
"href": "https://mylamp.example.com/properties",
"contentType": "application/json",
"htv:methodName": "GET"
},
{
"op": "writeallproperties",
"href": "https://mylamp.example.com/properties",
"contentType": "application/json",
"htv:methodName": "PUT"
}]
}
Thing-level uriVariables can be used here to supply further variables to the operation or to
specify a list of Property Affordance names for a readmultipleproperties operation. In the
example below, the unit for the properties can be set via such a variable and the desired list of
properties can be set:
{
// ...
"properties": {
"temperature": {
"type": "number",
"forms": [...]
},
"brightness": {
"type": "number",
"forms": [...]
},
"humidity": {
"type": "integer",
"forms": [...]
}
},
"uriVariables": {
"propertyNames": {
"type": "string",
"description": "Comma separated list of property names to select."
},
"unitSystem": {
"type": "string",
"enum": ["metric","imperial","uscustomary"],
"description": "System of Measurement that will be used for the values"
}
},
"forms": [{
"op": "readallproperties",
"href": "https://mything.example.com/properties{?unitSystem}",
"contentType": "application/json",
"htv:methodName": "GET"
},
{
"op": "readmultipleproperties",
"href": "https://mylamp.example.com/properties{?propertyNames,unitSystem}",
"contentType": "application/json",
"htv:methodName": "GET"
}]
}
For a readmultipleproperties operation, an example HTTP GET request to the URI
https://mylamp.example.com/properties?propertyNames=humidity,temperature&unitSystem=metric
would return the values humidity and temperature Property Affordances, with the
metric
System of Measurement.
In the case of operation type writeallproperties, it is expected that the
Consumer provides all writable (non readOnly) properties and the (new) assigned values
(e.g., within payload). Similarly, for the writemultipleproperties operation type, it is
expected that the Consumer provides writable (non readOnly) properties. On the
Thing side, Thing is expected to return readable (non writeOnly) properties in
the case of readmultipleproperties and readallproperties operation types.
The data schemas of the WoT Thing Description defined through the
DataSchema Class are based on a subset of the
JSON Schema terms [[?JSON-SCHEMA]]. Thus, serializations of the TD data schemas can be fed directly into
JSON Schema validator implementations to validate the data exchanged with Things.
Data schema serialization applies to PropertyAffordance instances, the values assigned to
input and output in ActionAffordance instances, the values assigned
to subscription, data, and cancellation in
EventAffordance instances, and the value assigned to uriVariables in instances of
Subclasses of InteractionAffordance (when a
form object uses a URI Template).
All name-value pairs of an instance of one of the Subclasses of DataSchema, where the
name is a Vocabulary Term included in the Signature of that Subclass or in the
Signature of DataSchema, MUST be serialized as members of the JSON object that results
from serializing the DataSchema Subclass's instance, with the
Vocabulary Term as name.
The value assigned to properties in an instance of ObjectSchema MUST be
serialized as a JSON object.
The values assigned to enum, required, and oneOf in an instance of
DataSchema
MUST be serialized as a JSON array.
The value assigned to items in an instance of ArraySchema MUST be serialized as
a JSON object or a JSON array containing JSON objects.
A TD snippet data schema members is given below. Note that the surrounding object may be a data schema
object (e.g., for input and output) or a Property object, which would contain
additional members.
The terms readOnly and writeOnly can be used to signal which data items are
exchanged in read interactions (i.e., when reading a Property) and which in write interactions (i.e., when
writing a Property). This can be used as a workaround when Properties of an unconventional Thing
exhibit different data for reading and writing, which can be the case when augmenting an existing device or
service with a Thing Description.
A TD snippet with the usage of readOnly and writeOnly is given below:
{
// ...
"properties": {
"status": {
"description": "Read or write On/Off status.",
"type": "object",
"properties": {
"latestStatus": {
"type": "string",
"enum": ["on_value", "off_value"],
"readOnly": true
},
"newStatusValue": {
"type": "string",
"enum": ["on_value", "off_value"],
"writeOnly": true
}
},
"forms": [...]
}
}
// ...
}
When the status Property is read, the status data is returned using a
latestStatus member in the payload. To update the status Property, the new value
must be provided through a newStatusValue member in the payload.
As an additional feature, a Thing Description instance allows the usage of a unit member within
data schemas. This can be used to associate a unit of measure to a data item. Its string value can be
selected freely. However, it is recommended to select units defined in well-known Vocabularies. See
for an example.
The JSON-based serialization of Thing Descriptions is identified by the media type
application/td+json or the CoAP Content-Format ID 432 (see
).
In several contexts automatic validation of a JSON-based serialization of a Thing Description is useful. Formally, a valid TD satisfies all the assertions in this specification, but not all assertions can be validated given only the JSON serialization, for instance, the assertions listed under that relate a TD to the behavior of a Thing that it describes. Extensions are also problematic, in that even if formal metadata is given for validating an extension, dynamically fetching this metadata in a deployment might pose a privacy risk. In this section, therefore, we name and define various levels of validation appropriate for different contexts.
This level of validation includes all assertions implied by normative tables in this document, and those that can be checked by looking only at the TD itself.
Minimal Validation is appropriate where validation needs to be self-contained (e.g., devices on isolated networks). It does not attempt to validate context extensions and vocabularies.
In practice, these assertions can be validated using a JSON Schema in combination with a few spot checks, for example to check that security schema names have matching definitions.
This level of validation includes all those covered by as well as basic validation of semantic definitions.
Basic validation is appropriate in situations where network access is possible and does not pose a privacy risk, and for relatively unconstrained computing requirements. It is suitable for gateways, for example, but not for endpoints, since semantic processing is required. It can do basic validation of extensions, specfically that the vocabulary used is defined.
In this case, context definition files and SHACL definitions can be used to validate additional assertions and check TDs for semantic consistency. In addition, if context definitions and SHACL constraints for extension vocabularies can be fetched, then these can be used to validate extensions.
Full validation confirms that all the assertions in this document are satisfied, including the assertions given in that confirm the TD is consistent with the Thing it describes.
This level of validation is appropriate during development, before release, and possibly after installation. Validation during development would have to be on test Things. Actual installation of instances of such Things requires updating the TD with appropriate per-instance identifiers and URLs and so for maximum assurance, in-field validation would have to take place after installation.
In addition to the standard Vocabulary definitions in , the WoT Thing Description offers the possibility to add context knowledge from additional namespaces. This mechanism can be used to enrich the Thing Description instances with additional (e.g., domain-specific) semantics. It can also be used to import additional Protocol Bindings or new security schemes in the future.
For such TD Context Extensions, the Thing Descriptions use the @context mechanism known from
JSON-LD [[?json-ld11]]. When using TD Context Extensions, the value of @context of the
Class Thing is an Array with additional elements of type anyURI identifying
JSON-LD context files or Map containing namespace IRIs as defined in .
The serialization rules for complex types in define the serialization of
an extended @context name-value pair. A snippet with TD Context Extensions is given below:
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"eg": "http://example.org/iot#",
"cov": "http://www.example.org/coap-binding#"
},
"https://schema.org/"
],
// ...
}
TD Context Extensions allow for the use of additional Vocabulary Terms in a Thing Description
instance. If the included namespaces are based on Class definitions such as those provided by the RDF
Schema or OWL, they can be used to annotate any Class instance of a Thing Description semantically by
associating the instance to a such an external Class definition. This is done by assigning a
Class name to the @type name-value pair or including Class name in its
Array value for multiple associations/annotations. Following the serialization rules in
, @type is either serialized as a JSON string or as a JSON
array. @type is the JSON-LD keyword [[?json-ld11]] used to set the type of a node.
TD Context Extensions also allow the inclusion of additional name-value pairs and well-defined values within any Class instance of a Thing Description. These pairs and values are defined through the included Vocabulary Terms and are serialized as additional members in the corresponding JSON objects or values of existing members, respectively. Examples are additional version metadata for the Thing or units of measure for data items.
The next subsections show some sample usage of different kind of ontologies in Thing Descriptions.
The sample TD snippet below provides additional metadata terms from different external context files as
provided in @context. The version information container is extended by adding additional
version information about the used software (s:softwareVersion).
schema.org is used for providing serial number and organisation information
such as the company name of the Thing. The
SAREF ontology is used to provide a semantic context of the
Thing (saref:TemperatureSensor), and for the unit assignment for the temperature
property the
Ontology of Units of Measure (OM)
is used.
Please note that these Vocabularies and ontologies are used as examples. Others can be used based on application domain and use case.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"saref": "https://w3id.org/saref#",
"om": "http://www.ontology-of-units-of-measure.org/resource/om-2/",
"schema": "https://schema.org"
}
],
"version": {
"instance": "1.2.1",
"schema:softwareVersion": "1.0.1"
},
"schema:serialNumber": "4CE0460D0G",
"schema:manufacturer": {"name": "CompanyName"},
// ...
"@type": "saref:TemperatureSensor",
"properties": {
"temperature": {
"description": "Temperature value of the weather station",
"type": "number",
"minimum": -32.5,
"maximum": 55.2,
"unit": "om:degreeCelsius",
"forms": [...]
},
// ...
},
// ...
}
In many cases, TD Context Extensions may be used to annotate pieces of a data schema, to be able to semantically process the state information of the physical world object, which is represented by the data exchanged during an interaction (e.g., in the payload of a response). For example, a semantic description of this state information in RDF can be embedded in the TD Document and pieces of a data schema can be individually annotated as referring to specific parts of that RDF-modeled state of the physical world object.
The TD snippet below uses SAREF to describe the state of a lamp. The external Vocabulary Term
ssn:forProperty, taken from SSN, the Semantic
Sensor Network Ontology [[VOCAB-SSN]], is being used to link the data schema of the status
Property with the actual on/off state of the physical world object.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"saref": "https://w3id.org/saref#",
"ssn": "http://www.w3.org/ns/ssn/"
}
],
"id": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4",
"@type": "saref:LightSwitch",
"saref:hasState": {
"@id": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4/state",
"@type": "saref:OnOffState"
},
// ...
"properties": {
"status": {
"ssn:forProperty": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4/state",
"type": "string",
"forms": [{"href": "https://mylamp.example.com/status"}]
},
"fullStatus": {
"ssn:forProperty": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4/state",
"type": "object",
"properties": {
"statusString": { "type": "string" },
"statusCode": { "type": "number" },
"statusDescription": { "type": "string" }
},
"forms": [{"href": "https://mylamp.example.com/status?full=true"}]
},
// ...
},
// ...
}
In , the state of the Thing is given by the
status affordance itself and possible state changes are given by the
toggle affordance. In other words, the state of the physical world object directly provides the
Interaction Affordances of the Thing. This design is satisfactory for simple cases. In more
elaborate cases, however, several affordances may be available for the same physical state. In the example
above, the fullStatus Property provides an alternative, more verbose representation for
the state of the lamp.
For many use cases like in building, agriculture, or smart city location based data is required. This information can be provided in the Thing Description in different ways and can be relied on different kind of location ontologies (e.g.,[[w3c-basic-geo]], schema.org) depending on purpose (e.g., indoor, outdoor). Also see [[sdw-bp]].
The TD snippet below uses lat and long from the [[w3c-basic-geo]] ontology to
provide static latitude and longitude metadata at Thing's top level.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"geo": "http://www.w3.org/2003/01/geo/wgs84_pos#"
}
],
"@type": "Thing",
"geo:lat": "26.58",
"geo:long": "297.83",
// ...
"properties": {
// ...
}
}
In some use cases location based metadata have to be provided at the interaction level, e.g., as provided as
a Property that returns the latest longitude, latitude, and
elevation values based on schema.org:
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"schema": "https://schema.org#"
}
],
// ...
"properties": {
"position": {
"type": "object",
"@type": "schema:GeoCoordinates",
"properties": {
"longitude": { "type": "number" },
"latitude": { "type": "number" },
"elevation": { "type": "number" }
},
"forms": [{"href": "https://robot.example.com/position"}]
},
// ...
},
// ...
}
In case a different name is desired for, e.g., longitude, latitude, and
elevation in the data model, the jsonld:context can be used to link terms to
specific vocabulary from an ontology (also see [[JSON-SCHEMA-ONTOLOGY]], Section 3.3 Defining a JSON-LD
context for data instances):
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"schema": "https://schema.org#"
}
],
// ...
"properties": {
"position": {
"jsonld:context": {
"schema": "https://schema.org/",
"long": "schema:longitude",
"lat": "schema:latitude",
"height": "schema:elevation"
},
"type": "object",
"properties": {
"long": { "type": "number" },
"lat": { "type": "number" },
"height": { "type": "number" }
}
}
},
// ...
}
With the TD Context Extensions in a Thing Description, the communication metadata can be supplemented
via Binding Specifications from the WoT Binding Registry [[WOT-BINDING-REGISTRY]], which are added
through additional Vocabulary Terms serialized into JSON objects representing a
Form instance. Please see for further information.
Finally, new security schemes that are not included in can
be imported using the TD Context Extension mechanism. This example uses a fictional ACE security scheme
based on [[?RFC9200]] that is, for this example, defined by the namespace at
http://www.example.org/ace-security#.
Additional security schemes MUST be Subclasses of the Class
SecurityScheme.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"cov": "http://www.example.org/coap-binding#",
"ace": "http://www.example.org/ace-security#"
}
],
// ...
"securityDefinitions": {
"ace_sc": {
"scheme": "ace:ACESecurityScheme",
// ...
"ace:as": "coaps://as.example.com/token",
"ace:audience": "coaps://rs.example.com",
"ace:scopes": ["limited", "special"],
"ace:cnonce": true
}
},
"security": ["ace_sc"],
"properties": {
"status": {
// ...
"forms": [{
"op": "readproperty",
"href": "coaps://rs.example.com/status",
"contentType": "application/cbor",
"cov:methodName": "GET",
"ace:scopes": ["limited"]
}]
}
},
"actions": {
"configure": {
// ...
"forms": [{
"op": "invokeaction",
"href": "coaps://rs.example.com/configure",
"contentType": "application/cbor",
"cov:methodName": "POST",
"ace:scopes": ["special"]
}]
}
},
// ...
}
Note that all security schemes defined in are already part of the TD context and need not to be included through a TD Context Extension.
Every message sent from a Consumer to the Thing and back needs to travel over a network protocol, despite the
Property–Action–Event abstraction provided by WoT. The operations in the Forms level need to be
bound to how the message is meant to look, over the network. Thus, every form in a WoT Thing Description needs
to have a submission target, given by the href member, as indicated in Form.
For instance, if the target starts with http or https, a Consumer can infer
that the Thing implements the Protocol Binding based on HTTP, and it should expect HTTP-specific
terms in an instance of this form. See [[[#protocol-bindings]]] for more explanation and examples.
Furthermore, the payloads described by the Data Schema in the Affordance Level need to be serialized to a
data format and sent on the network protocol. Similar to the way operations are bound to protocol messages, the
Data Schema is bound to a data format indicated by the contentType or protocol-specific
terms provided in the Form. From these terms, a Consumer can infer the required
serialization method and transform the application-level data to the data to be sent on the network protocol.
Similarly, for messages coming from the Thing, the Consumer can deserialize the data and present
it to the application level. For example, a Consumer implemented in Python can read
application/json as the value of contentType and serialize a Python dictionary data
structure into a JSON object. See [[[#payload-bindings]]] for more explanation and examples.
The mechanism above are called Bindings in the Web of Things and a specific example is illustrated in
[[[#fig-mechanism]]] with an excerpt of a TD of a robot arm with of HTTP and JSON Bindings. Here, the Consumer
intends to invoke an action of the robot arm (goTo) in order to move it to the position x equals 12
and y equals 100. To do so, it creates the correct payload, serializes it, and sends it using the correct
protocol options. The Thing gets the message over the network and responds with a message that corresponds to
its TD. Other protocols, payload formats, and/or their combination are possible and are explained in
[[[#binding-mechanisms]]].
In summary, Bindings enable a Thing Description to be adapted to a specific protocol, data payload formats or both in specific ways. This is done through URI Schemes, additional descriptive vocabularies, Thing Models and examples that aim to guide the implementors of Things and Consumers alike. This section explains the overall mechanism and gives basic guidance on creating new Bindings. The [[WOT-BINDING-REGISTRY]] contains a registry (list) of existing Bindings as well the requirements to follow to register new entries to the registry.
When producing a TD for a particular IoT device, the corresponding Binding can be used to look up the communication metadata that is to be provided in the Thing Description. [[[#fig-building-block]]] shows how Bindings are used. Based on the protocol or media type, a TD is created. The Consumer that is processing a TD implements the required Bindings that are present in the TD by including a corresponding protocol stack and media type encoder/decoder by configuring the stack (or its messages) according to the information given in the TD such as serialization format of the messages and header options.
The editors of this specification also recommend reading the related chapters in [[WOT-ARCHITECTURE]], such as WoT Binding Templates Building Block, Hypermedia Controls, Protocol Bindings and Media Types.
[[WOT-THING-DESCRIPTION]] defines abstract operations such as readproperty,
invokeaction
and
subscribeevent that describe the intended semantics of performing the operation described by
the form in a Thing Description. In order for the operations to be performed on the affordance, a
binding of the operation to the protocol needs to happen. In other words, the form needs to contain all the
information for a Consumer to, for example read a property, with the protocol in the form.
Most protocols have a relatively small set of methods that define the message type, the semantic intention
of the message. REST and PubSub architecture patterns result in different protocols with different methods.
Each target protocol may specify different method names for similar operations, and there may be semantic
differences between similar method names of different protocols. Additionally, Things may use
different methods for performing a particular WoT operation. For example, an HTTP POST request may be used
for a writeproperty operation in one Thing, while HTTP PUT may be used in another. For these
reasons, Thing Descriptions require the ability to specify which method to use per operation.
Common methods found in REST and PubSub protocols are GET, PUT, POST, DELETE, PUBLISH, and SUBSCRIBE.
Binding specifications describe how these existing methods and associated vocabularies can be used in a
Thing Description to bind to the WoT operations. This is done by defining the URI scheme of the
protocol and mapping the protocol methods to the abstract WoT operations such as readproperty,
invokeaction and subscribeevent. In some cases, additional instructions are
provided to explain how the vocabulary terms should be used in different cases of protocol usage.
The examples below show binding instances of the readproperty operation for the HTTP and Modbus
protocols. Please note that these are examples and please always refer to the corresponding binding
specification to learn about the relevant vocabulary terms and their values.
{
"href": "http://example.com/props/temperature",
"op": "readproperty",
"htv:methodName": "GET"
}
|
{
"href": "modbus+tcp://127.0.0.1:60000/1/4",
"op": "readproperty",
"modv:function": "readCoil"
}
|
The form elements in the examples above convey the following statements:
readproperty of the subject Property Affordance by performing an HTTP
GET request on the resource props/temperature to the host at example.com on port
80 (Port 80 is assumed as per [[RFC2616]]).
readproperty of the subject Property Affordance using the
readCoil function of Modbus at coil 4 of the device with the
127.0.0.1 IP address and unitID 1 at its port 60000
These binding instances and their statements are possible for other operations and protocols as well. Below
are examples for invokeaction and subscribeevent:
{
"op": "invokeaction",
"href": "http://192.168.1.32:8081/example/levelaction",
"htv:methodName": "POST"
}
|
{
"op": "subscribeevent",
"href": "mqtt://iot.platform.com:8088",
"mqv:filter": "thing1/events/overheating",
"mqv:controlPacket": "subscribe"
}
|
The form elements in the examples above convey the following statements:
invokeaction of the subject Action Affordance by performing an HTTP
POST request on the resource example/levelaction to the host at 192.168.1.32 on
port 8081.
subscribeevent of the subject Event Affordance by connecting to the
MQTT broker at iot.platform.com and port 8088, then subscribing to the topic
thing1/events/overheating.
In some cases, header options or other parameters of the protocols need to be included. Given that these are
highly protocol dependent, please refer to the bindings listed in [[[WOT-BINDING-REGISTRY]]]. Additionally,
protocols may have defined Subprotocols that can be used for some interaction types. For example, to receive
asynchronous notifications using HTTP, some servers may support long polling (longpoll), WebSub
[[WebSub]] (websub) and Server-Sent Events [[eventsource]] (sse).
As defined in [[WOT-ARCHITECTURE]], a subprotocol is an extension mechanism to a protocol. A subprotocol
can require a sequence of protocol messages or a specific structure of message payloads, which can have
its own semantics within that subprotocol. The use of a subprotocol is expressed with the
subprotocol field, as defined in [[!WOT-THING-DESCRIPTION]]. It can be used in a form
instance to indicate the use of one of these protocols, for example long polling with its special use of
HTTP:
{
"op": "subscribeevent",
"href": "https://mylamp.example.com/overheating",
"subprotocol": "longpoll"
}
The values that the subprotocol term can take is not constrained by the
[[!WOT-THING-DESCRIPTION]] since different protocols can have different subprotocols. Correspondingly,
subprotocols are linked to the protocol they are extending and should be understood together with the
protocol indicated in href of the forms (or the base). For WebSockets, the
IANA-registered Websocket Subprotocols [[iana-web-socket-registry]] may be used. For CoAP,
"subprotocol":"cov:observe" can be used to describe asynchronous observation operations as
defined by [[RFC6741]]. The subprotocols can be defined and explained as a part of a protocol
binding specification.
Protocol Binding Specifications contain vocabularies that extend the vocabulary found in the [[WOT-THING-DESCRIPTION]]. This means that the way a TD is consumed and how the interactions happen with the Thing are adapted to such vocabularies. The steps below explain how this process typically looks like.
href member and the base (if exists) and
identify the protocol.
subprotocol or other vocabulary terms introduced by the protocol
binding. The interaction affordance data exchanged with the Thing SHOULD be according to the
Data Schema and Content Type present in the TD. The Data Schema corresponding to the
operation can be found in the Table [[[#table-mapping-op-values-to-data-schemas]]].
Consequently, the following requirements apply to Things and Consumers:
href member.
[[WOT-THING-DESCRIPTION]] defines two mechanisms to describe how a payload of a message over any protocol
can look like. Firstly, media types [[IANA-MEDIA-TYPES]] describe the serialization used for sending and
receiving the data with a protocol. They are represented within the contentType in the Forms of
a TD, which is mandatory for each Interaction Affordance. Secondly, it defines the Data Schema concept to
describe the structure of the messages, which are used together with media types. The combination of the two
allows any message to be described in a TD, allowing correct serialization and deserialization of the
messages by the Thing and Consumers.
In the rest of this section at [[[#payload-bindings-contentType]]] and [[[#payload-bindings-dataschema]]], you can find examples of how payload bindings can look like.
Content type includes the media type and potential parameters for the media type and it enables proper processing of the serialized documents. This way, the messages can be exchanged in any format and allow the upper layers of an application to adapt to different formats. In some cases such as images, videos or any unstructured data, content type is enough to describe the payload but in cases like JSON ([[RFC8259]]) a Data Schema is usually provided, like explained in [[[#payload-bindings-dataschema]]].
For example, a number payload can be serialized as JSON or XML and be indicated in the
contentType of the forms with application/json or application/xml,
respectively. Further parametrization is possible via the plus (+) or the semicolon
(;) notations.
In the example below, you can find the form elements with content types for JSON and plain text with
additional parameters. In this specific case, the forms describe that reading this property with
http or coap result in different content types. For structured media types, a
Data Schema is generally provided in the affordance level as explained in
[[[#payload-bindings-dataschema]]] and [[[#sec-data-schema-vocabulary-definition]]]. However, for
unstructured data such as images and videos, a Data Schema is typically not available.
{
"forms":[
{
"href": "http://example.com/properties/temperature",
"op": "readproperty",
"contentType": "application/json"
},
{
"href": "coap://example.com/properties/temperature",
"op": "readproperty",
"contentType": "text/plain;charset=utf-8"
}]
}
Other content types can be also expressed in TDs. In the list below, examples of different content type variations can be found. These content types can replace the ones in [[[#example-payload-binding]]].
application/json: JSON [[RFC8259]]application/xml: XML [[RFC5364]]application/cbor: CBOR [[RFC8949]]text/csv: CSV [[RFC4180]]application/senml+json: SenML Data serialized in JSON [[RFC8259]]application/senml+xml: SenML Data serialized as XMLapplication/ocf+cbor: OCF payload serialized in CBORtext/csv;charset=utf-8: CSV encoded in UTF-8 [[RFC4180]]image/jpeg: JPEG imagevideo/mp4: MP4 Videoapplication/octet-stream: Generic binary streamData Schema, as explained in [[[#sec-data-schema-vocabulary-definition]]], describes the structure of the messages, which are used together with media types. Even though it is largely inspired by JSON Schema [[json-schema]], it can be used for describing other payload types such as [[XML]], string-encoded images, bit representations of integers, etc. Data Schema SHOULD be used in addition to the media types.
Depending on the case, the structure of the messages can be anything from a simple number to arrays or objects with multiple levels of nesting. Existing IoT Platforms and Standards have certain payload formats with variations on how the data is structured. As explained in [[[#sec-data-schema-vocabulary-definition]]], Data Schema can be used in a TD in one of the following places:
input and output vocabulary terms are used to
provide two different schemas when data is exchanged in both directions, such as in the case of invoking
an Action Affordance with input parameters and receiving status information.
data, dataResponse, subscription and
cancellation are used to describe the payload when the event data is delivered by the
Exposed Thing, the payload to reply with for event deliveries, the payload needed to subscribe to the
event and the payload needed to cancel receiving event data from the Exposed Thing, respectively.
uriVariables can describe the data
that needs to be supplied inside the request URI as a string.
Below is an example of a simple JSON object payload with the corresponding Data Schema. Examples from various IoT Platforms and Standards can be found in [[[#sec-payload-examples]]].
{
"level": 50,
"time": 10
}
|
{
"type": "object",
"properties": {
"level": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"time": {
"type": "integer",
"minimum": 0,
"maximum": 65535
}
}
}
|
In cases like IoT platforms or standards like OPC-UA or BACnet, the protocol, media type, and data structure can be specified. In these cases, their binding specification can either depend on a set of and or specify protocol, media type, and data structure at the same time.
In IoT platforms, there can be a requirement about the use of HTTP together with certain JSON payload structures. Thus, the corresponding binding specification provides Thing Models and examples of TDs that allow semantic grouping of multiple bindings. This requires having a binding specification for HTTP and JSON in the first place.
In standards like OPC-UA or BACnet, the binding specification contains requirements on the protocol and media type, and possibly also on data structure. Thus, the binding specification is enough on its own to specify how a binding instance should look.
The Web of Things also defines a profiling mechanism that allows the reduction of implementation effort. Profiles are built on top of existing Bindings by constraining the flexibility of TDs. Such constraints can be bindings, semantic contexts, link relations, security schemes, and discovery mechanisms. With these constraints, they provide additional interoperability guarantees over bindings.
The profiling mechanism currently specified in [[WOT-PROFILES]] does not exactly follow the above-mentioned mechanism. However, there is agreement on the future of the profiling mechanism. Once the profiling mechanism is updated, this section will be updated accordingly.
For example, a profile can constrain the usage of HTTP GET Method for readproperty operations and
require payloads to be always serialized in JSON. The usage of a profile is indicated by the
profile term in the TD, which is a URI that points to the profile definition. How a Consumer can
use a profile is explained in the Profiling Mechanism section of the [[WOT-PROFILES]] specification.
The following assertions relate to the behavior of components of a WoT system, as opposed to the representation or information model of the TD. However, note that TDs are descriptive, and may in particular be used to describe pre-existing network interfaces. In these cases, assertions cannot be made that constrain the behavior of such pre-existing interfaces. Instead, the assertions are to be interpreted as constraints on the TD to accurately represent such interfaces.
To enable secure interoperation, security configurations need to accurately reflect the requirements of the Thing:
Some security protocols may ask for authentication information dynamically, including required encoding or encryption schemes. One consequence of the above is that if a protocol asks for a form of security credentials or an encoding or encryption scheme not declared in the Thing Description then the Thing Description is to be considered invalid.
The data schemas provided in the TD should accurately represent the data payloads returned and accepted by the described Thing in the interactions specified in the TD. In general, Consumers should follow the data schemas strictly, not generating anything not given in the WoT Thing Description, but should accept additional data from the Thing not given explicitly in the WoT Thing Description. In general, Things are described by WoT Thing Descriptions, but Consumers are constrained to follow WoT Thing Descriptions when interacting with Things.
ObjectSchema and ArraySchema (when items is an Array
of DataSchema) where there can be additional properties or items in the data returned. This
behaves as if "additionalProperties":true or "additionalItems":true as defined in
[[?JSON-SCHEMA]].
ObjectSchema and ArraySchema (when items is an Array
of DataSchema) where there can be additional properties or items in the data returned. This
behaves as if "additionalProperties":true or "additionalItems":true as defined in
[[?JSON-SCHEMA]].
The figure below illustrates the relation of the Thing Model and Thing Description. A Thing Model mainly describes interaction affordances such as the Properties, Actions, and Events and common metadata. When a Thing Descriptions is instantiated by relying on a Thing Model, it SHOULD be valid according to that Thing Model. This paradigm can be compared with abstract class or interface definition (~Thing Model) in object-oriented programming to create objects (~Thing Descriptions).
The Thing Model is a logical description of the interface and possible interaction with Thing's Properties, Actions, and Events, however it does not contain Thing instance-specific information, such as concrete protocol usage (e.g., IP address), or even a serial number and GPS location. However, Thing Models allows to include, e.g., security schemes if they apply to the entire class of instances the model describes. They might have URLs (e.g., like token servers) that might need to be omitted or parameterized (with templates) although in a lot of cases these might also be given.
Thing Model can be serialized in the same JSON-based format as a Thing Description which also allows
JSON-LD processing. Note that a Thing Model cannot be validated in the same way as
Thing Description instances due to some missing mandatory terms. This means that any term that is not
using the placeholder type, still uses the types declared in
TD Information Model. For example, the value of
minimum needs to be an integer, unless a placeholder is used.
You can use the JSON Schema to validate TM instances that are serialized as JSON.
A Thing Model is recognized by the top level @type.
Thing Model definitions MUST use the keyword @type at top level and a value of type
string or array that equals or respectively contains tm:ThingModel.
Additionally, in order to identify it as a JSON-LD document, Thing Model definitions MUST use the
keyword @context at top level with same rules as a Thing Description.
The prefix tm is defined within Thing Descriptions' context and points to the
Thing Model namespace as defined in . It is intended that vocabulary from the
tm context only be used in Thing Model definitions and are removed or replaced when
Thing Descriptions are generated (also see ).
A Thing Model MAY NOT contain instance specific Protocol Binding and security information such as endpoint addresses. Consequently, Thing Model definitions will also be valid if there are no JSON members like forms, base, securityDefinitions, and security. Thing Models are also valid even if these JSON members are used (e.g., as template), however, the nested mandatory members like href are omitted.
shows a valid sample lamp Thing Model without any protocol and security information.
In the context of Thing Model definitions specific features are introduced that can be used for Thing modelling.
When the Thing Model definitions change over time, this SHOULD be reflected in the version
container.
The string-based term model is used within the version container to provide such
versioning information, like [[SEMVER]]. The following snippet shows the usage of model in a
Thing Model instance.
{
// ...
"@type": "tm:ThingModel",
"title": "Lamp Thing Model",
"description": "Lamp Thing Description Model",
"version" : {"model": "1.0.0"},
// ...
}
Due to the definition of Thing Model the term instance MUST be omitted within the
version container.
When Thing Models are updated and have a new version, this may affect other Thing Models that use the extension and import features (see Section ). In some cases it is also useful to reflect a new version in the file name and/or in a corresponding URL to identify the version.
A Thing Model can extend an existing Thing Model by using the
tm:extends mechanism announced in the links definition:
When a Thing Model extends another Thing Model, at least one links entry with
"rel": "tm:extends" that targets a Thing Model that is be extended MUST be used.
The Thing Model will inherit all definitions from the extended Thing Model. There is the
opportunity to extend the existing definition with further metadata by providing further JSON name-value
pairs from the existing TD information model () or using the
context extension concept (). A Thing Model can also overwrite
existing definitions such as title(s) and maximum etc.. For this there exist two
limitations:
A Thing Model SHOULD NOT overwrite the JSON names defined within the properties,
actions, and/or events Map of the extended Thing Model.
Definitions SHOULD NOT be overwritten in such a way that possible instance values are no longer valid
compared to the origin extended definitions.
Those assertions preserve the semantics throughout of the extended Thing Model. E.g., it is not
allowed that a "minimum":2 from a extended Thing Model can be overwritten with
"minimum":0. Meanwhile, overwriting with "minimum":5 would work since all
instances values will always fulfill the restrictions of the extended Thing Model (also see Figure
for further explanation).
Lets assume we have a basic model description as provided in the following example:
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Basic On/Off Thing Model",
"properties": {
"onOff": {
"type": "boolean"
}
}
}
Now a new device class model called 'Smart Lamp Control' that will be used as template for creating TD
instances is designed. This model will reuse the existing definition of the 'Basic On/Off Thing Model' and
extend it with a dim property:
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control with Dimming",
"links" : [{
"rel": "tm:extends",
"href": "http://example.com/BasicOnOffTM",
"type": "application/tm+json"
}],
"properties" : {
"dim" : {
"title": "Dimming level",
"type": "integer",
"minimum": 0,
"maximum": 100
}
}
}
Please note that the title is overwritten and will be used when TD instances are created (also
see in the next subsection ).
The tm:extends feature only permits inheriting all definitions of one Thing Model. In
many use cases, however, it is desired only to import pieces of definitions of one or more existing
Thing Models.
For importing pieces of definitions of one or more existing Thing Models, the
tm:ref term is introduced that provides the location of an existing (sub-)definition that
SHOULD be reused.
The tm:ref value MUST follow the pattern that starts with the file location as URI
[[RFC3986]](Section 4.1)), followed by # character, and followed by JSON Pointer [[RFC6901]]
definition.
Note that the URI can also be empty, indicating a same-document reference [[RFC3986]](Section 4.4)). In this
case, the tm:ref is supposed to be interpreted as a relative reference.
Every time tm:ref is used, the referenced pre-definition and its dependencies (e.g., by
context extension) MUST be assumed at the new defined definition.
Portions of the tm:ref value might contain non-ASCII characters that require URL ("percent")
encoding before use. Before applying escapes to a tm:ref value, implementations should check
that the value is not already encoded.
The following example shows a new TM definition that imports the existing definition of the property
onOff from into the new property definition
switch.
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control",
"properties" : {
"switch" : {
"tm:ref": "http://example.com/BasicOnOffTM.tm.jsonld#/properties/onOff"
}
}
}
As an example for relative imports using tm:ref, the following Thing Model re-uses and augments
(see below) a genericTemperature property in two more specific properties, which describe an
inner and an outer temperature value, respectively.
{
"@context": "https://www.w3.org/ns/wot-next/td",
"@type": "tm:ThingModel",
"title": "Multi Sensor",
"properties": {
"genericTemperature": {
"type": "number",
"unit": "C"
},
"innerTemperature": {
"tm:ref": "#/properties/genericTemperature",
"title": "The inner temperature",
"minimum": 10
},
"outerTemperature": {
"tm:ref": "#/properties/genericTemperature",
"title": "The outer temperature",
"description": "The outer temperature is measured in Kelvin",
"unit": "K"
}
},
"tm:optional": [
"/properties/genericTemperature"
]
}
At the place the "tm:ref" is defined, additional name-value pairs can be added. It is also permitted to
override name-value pairs from the referenced definition.
If the intention is to override an existing JSON name-value pair definition from tm:ref, the
same JSON name MUST be used at the same level of the tm:ref declaration that provides a new
value.
The process to overwrite MUST follow the JSON Merge Patch algorithm as defined in [RFC7396] where the
content of the referenced definition is patched with the new provided JSON name-value pairs.
It is noted that the values can also be based on a JSON object or array, or simply
be a null value. null would result to a removal of existing JSON name-value pair
in the target.
Similar to tm:extends and to keep the semantic meaning, definitions SHOULD NOT be overwritten
in such a way that possible instance values are no longer valid compared to the origin referenced
definition.
The following example shows a new TM definition that overwrites (maximum), enhances
(unit), and removes (title) existing definitions from
.
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control",
"properties" : {
"dimming" : {
"tm:ref": "http://example.com/SmartLampControlwithDimming.tm.jsonld#/properties/dim",
"title": null,
"maximum": 80,
"unit": "%"
}
}
}
Based on the JSON Merge Patch algorithm the {"title": null,"maximum": 80,"unit": "%"} would act
as a patch for the referenced origin content
{"title": "Dimming level", "type": "integer", "minimum": 0, "maximum": 100}.
The tm:extends and the import mechanism based on tm:ref can also be used at the
same time in a TM definition. The following example extends the TM from
and imports the status and
dim definitions from and
respectively.
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control",
"links" : [{
"rel": "extends",
"href": "http://example.com/BasicOnOffTM",
"type": "application/tm+json"
}],
"properties" : {
"status" : {
"tm:ref": "http://example.com/LampTM.tm.jsonld#/properties/status"
},
"dimming" : {
"tm:ref": "http://example.com/LampWithDimmingTM.tm.jsonld#/properties/dim"
}
}
}
The tm:extends and the import mechanism based on tm:ref explicitly supports
transitive extension (a hierarchy of extensions). For example, assuming there are 3 TMs: "A" which defines a
tm:extends of the TM "B" which itself defines a tm:extends of the TM "C".
Consequently, the "A" TM extends all definitions of both "B" and "C".
Recursive extensions leading to an infinite loop MUST NOT be defined.
The following figure summarizes the allowable override behaviour of the extension and imports TM functions
presented in this section. Three Thing Models use the tm:ref or
tm:extends feature to reuse TM definitions of the Smart Lamp Control Thing Model. The
first Thing Model imports and overwrites the maximum value to 120 within
the dimmer property. However, this results in possible instance values (at runtime) that may
not be in the range of the original dim definition between 0 and
100 of the dim definition of the Smart Lamp Control Thing Model. Thus, such a
Thing Model definition is not allowed. The second model overwrites the property
type value by number. Again, this will potentially result in numeric
dim values that are not accepted by the definition of the origin dim type
definition (integer) of the Smart Lamp Control Thing Model. The last model is defined in a correct
way. The new ranges of dim produce potential instance values that are also fulfilled by the
original dim definition.
In some applications, it is beneficial to reuse existing Thing Model definitions and compose them
into a new IoT system. An example would be that a new Smart Ventilator is designed to consist of two
sub/child Thing Model definitions such as a Ventilation Thing Model that provides
on/off and adjustRpm capabilities, and an LED Thing Model that provides
dimmable and RGB capabilities.
Such composition can be introduced by the usage of the links container.
If it is desired to provide information that a Thing Model consists of one or more (sub-)Thing Models, the links entries MUST use the "rel": "tm:submodel" that targets to the
(sub-) Thing Models.
Optionally an instanceName MAY be provided to associate an individual name to the composed
(sub-) Thing Model.
This is useful when multiple similar Thing Model definitions are composed and needs to be
distinguished.
Different strategies can be followed to generate Thing Descriptions from composed
Thing Model definitions. The default recommendation is to generate from each parent and sub/child
Thing Model a corresponding Thing Descriptions (also see
). The composition relation can be reflected by the
collection and item relation types in the links container of the
Thing Descriptions. An example based on Smart Ventilation is given here:
A single TD can also be generated which contains the interaction definitions of the top level/parent Thing Model and all interaction definitions of all sub/child Thing Models. Thereby the generation process MUST avoid possible name collisions. The following example shows a potential generated (self-contained) Thing Description of the Smart Ventilator Thing Model.
{
"@context": "https://www.w3.org/ns/wot-next/td",
"title": "Smart Ventilator",
"securityDefinitions": {
"basic_sc": {
"scheme": "basic",
"in": "header"
}
},
"security": "basic_sc",
"links": [
{
"rel": "type",
"href": "./SmartVentilator.tm.jsonld",
"type": "application/tm+json"
}
],
"properties": {
"status": {
"type": "string",
"enum": [
"on_value",
"off_value",
"error_value"
],
"forms": [
{
"href": "http://127.0.13.232:4563/status"
}
]
},
"switch": {
"type": "boolean",
"description": "True=On; False=Off",
"forms": [
{
"href": "http://127.0.13.212:4563/switch"
}
]
},
"adjustRpm": {
"type": "number",
"minimum": 200,
"maximum": 1200,
"forms": [
{
"href": "http://127.0.13.212:4563/adjustRpm"
}
]
},
"R": {
"type": "number",
"description": "Red color",
"forms": [
{
"href": "http://127.0.13.211:4563/R"
}
]
},
"G": {
"type": "number",
"description": "Green color",
"forms": [
{
"href": "http://127.0.13.211:4563/G"
}
]
},
"B": {
"type": "number",
"description": "Blue color",
"forms": [
{
"href": "http://127.0.13.211:4563/B"
}
]
}
},
"actions": {
"fadeIn": {
"title": "fadeIn",
"input": {
"type": "number",
"description": "fadeIn in ms"
},
"forms": [
{
"href": "http://127.0.13.211:4563/fadeIn"
}
]
},
"fadeOut": {
"title": "fadeOut",
"input": {
"type": "number",
"description": "fadeOut in ms"
},
"forms": [
{
"href": "http://127.0.13.211:4563/fadeOut"
}
]
}
}
}
In some cases it is desirable to not enforce which interaction affordances are mandatory and do not
necessarily need to be implemented in a Thing Description instance.
If interaction models are not mandatory to be implemented in a Thing Description instance,
Thing Model definitions MUST use the JSON member name tm:optional.
tm:optional MUST be a JSON array at the top level.
The value of tm:optional MUST provide JSON Pointer [[RFC6901]] references to the required
interaction model definitions.
The JSON Pointers of tm:optional MUST resolve to an entire interaction affordance Map
definition.
The following sample shows the usage of tm:optional for the Event interaction
overheating.
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Lamp Thing Model",
"description": "Lamp Thing Model Description",
"tm:optional": [
"/events/overheating"
],
"properties": {
"status": {
"description": "current status of the lamp (on|off)",
"type": "string",
"readOnly": true
}
},
"actions": {
"toggle": {
"description": "Turn the lamp on or off"
}
},
"events": {
"overheating": {
"description": "Lamp reaches a critical temperature (overheating)",
"data": {"type": "string"}
}
}
}
Since the Event overheating is not mandatory it may not be available in a
Thing Description
instance.
Please note that an optional definition in a Thing Model definition can be overwritten in the case it
is extended by another Thing Model through the use of tm:ref:
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Lamp Thing Model (All Mandatory)",
"description": "Lamp Thing Model description expects all interaction affordances (status, toggle, and overheating)",
"links": [
{
"rel": "tm:extends",
"href": "./lampThingModel.tm.jsonld",
"type": "application/tm+json"
}
],
"events": {
"overheating": {
"tm:ref": "./lampThingModel.tm.jsonld#/events/overheating"
}
}
}
A Thing Model can specify which terms should be used in a TD instance, but their values are
unspecific and are first known during TD instantiation.
In a case where TD instance terms, but not their values, are known in advance, the placeholder labeling
MAY be used in a Thing Model.
The placeholder labeling MUST be substituted with a concrete value (e.g., as JSON number, JSON string,
JSON object, etc) when TD instance is created from the Thing Model.
The string-based pattern of the placeholder MUST follow a valid pattern based on the regular expression
{{2}[ -~]+}{2} (e.g., {{PLACEHOLDER_IDENTIFIER}}). The
characters between {{ and }} are used as identifier name of the placeholder. The
identifier name can be used to identify the placeholder for the substitution process.
A placeholder MUST be applied within the value of the JSON name-value pair.
If a non string-based value of a JSON name-value pair has a placeholder, the value MUST be (temporarily)
typed as string.
After replacing the placeholder, e.g., when creating a Thing Description instance, the original type is
applied with the corresponding replaced value.
The following Thing Model example defines different placeholders. The placeholder map is used to apply the replacement and to transform the intended value type.
Thing Models can be used as templates to generate a Thing Description based on the restrictions defined in Sections and . During this process missing data such as communication and security metadata have to be complemented to create valid Thing Description instances. A Thing Model MUST be defined in such a way that there are no inconsistencies that would result in a Thing Description not being able to meet the requirements as described in Section and . A TM-to-TD generator to derive a Thing Description instance from a Thing Model transforms it to a Partial TD using the following steps:
links element entry with "rel":"tm:extends" MUST be removed from the
current Partial TD
tm:ThingModel value of the top-level @type MUST be removed in the
Partial TD instance.
tm:optional) MUST be taken over to the
Partial TD instance.
tm:optional) MAY be taken over to the
Partial TD instance.
Finally, a TM-to-TD generator will take the resulting Partial TD and transform it into a Thing Description with this last step
It is recommended that the id value of a Thing Model provides a placeholder such as
"id": "urn:example:{{RANDOM_ID_PATTERN}}" for
the TD generation process. Please avoid including metadata in the id pattern.
Thing Description instances that follow a Thing Model can carry the information regarding which
type of Thing Model is derived. In this context, the linking concept can be used with
"rel": "type" (also see Section ), as shown in the following example:
Please note that a TD can only be an instance of one TM at a time. That means for Thing Descriptions:
The links array MUST use the entry with "rel": "type" a maximum of once.
If it is desired to reflect all relationships to other Things in a Thing Description, the composition
mechanism in TMs can be considered (see Section ).
The following Thing Model extends the model as shown in
and overwrites the maximum value of the
dim property
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"links" : [{
"rel": "tm:extends",
"href": "http://example.com/SmartControlLampTM",
"type": "application/tm+json"
}],
"properties" : {
"dim" : {
"maximum": 200
}
}
}
The expected Thing Description that is derived from this Thing Model would be (with HTTP Binding and basic security applied):
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "Thing",
"title": "Smart Lamp Control",
"securityDefinitions": {
"basic_sc": {"scheme": "basic", "in": "header"}
},
"security": "basic_sc",
"links" : [{
"rel": "type",
"href": "url/to/SmartLampControlModifiedDimTM",
"type": "application/tm+json"
}
],
"properties" : {
"onOff": {
"type": "boolean",
"forms": [{"href": "https://smartlamp.example.com/onoff"}]
},
"dim" : {
"type": "integer",
"minimum": 0,
"maximum": 200,
"forms": [{"href": "https://smartlamp.example.com/dim"}]
}
}
}
In general the security measures taken to protect a WoT system will depend on the threats and attackers that system may face and the value of the assets that need to be protected. A detailed discussion of security (and privacy) considerations for the Web of Things, including a threat model that can be adapted to various circumstances, is presented in the informative document [[WOT-SECURITY-GUIDELINES]]. Many WoT Things are similar to and use the same technologies as web services. In addition to the specific security considerations below, the security risks and mitigations discussed in guides such as the OWASP Top 10 [[OWASP-Top-10]] for web services should be evaluated, and if applicable, addressed. This section discusses only security risks and possible mitigations directly relevant to the WoT Thing Description.
A WoT Thing Description can describe both secure and insecure network interfaces. When a Thing Description is retro-fitted to an existing network interface, no change in the security status of the network interface is to be expected.
The use of a WoT Thing Description introduces the security risks given in the following sections. After each risk, we suggest some possible mitigations.
Intercepting and tampering with TDs can be used to launch man-in-the-middle attacks, for example by rewriting URLs in TDs to redirect accesses to a malicious intermediary that can capture or manipulate data.
Intercepting and tampering with context definition files can be used to facilitate attacks by modifying the interpretation of vocabulary. Context extensions (see ) that are loaded from the Web over non-secure connections, such as HTTP, run the risk of being altered by an attacker, and may modify the TD Information Model in ways that could compromise security.
As recommended in , on constrained implementations context definition files should be pre-installed and managed using a secure software update process and the context URLs only used to identify known contexts, not to fetch them. This consideration therefore applies only when fetching context definition files dynamically is otherwise unavoidable, for example in a directory service supporting general semantic processing.
In some scenarios, it may be desirable to limit the scope and duration of access to a set of Things by some users. For example, if A is visiting B's house, B may want to provide A with temporary and limited access to the garage door opener and car charger so A can use them. The scope however may be limited so that A cannot access certain administrative functions of these Things (for example, to change how long the garage door can remain open, or to change the charging rate). In addition, the access should expire after A is expected to have left, e.g., after one week.
An attacker with access to a set of TDs, for example those returned by WoT Discovery, may be able to use this information to identify vulnerable devices and plan attacks on them.
auto security scheme MAY be used if vulnerability scanning is a concern.
Many strings given in TDs, in particular the values carried in title/titles
and
description/descriptions, are meant to be human-readable. An application may take
such strings and use them to generate a user interface, for example, a web dashboard listing a set of
available Things with their titles and descriptions. If such an interface is naively generated using string
substitution, for example inserting the values of these strings into marked places in a HTML template to
create final HTML, any HTML markup in the original string will be interpreted in the context of the browser
displaying the dashboard. It is possible for an attacker to embed scripts in HTML in various ways and have
these scripts executed upon user interaction or even automatically (e.g., upon page load, or upon an error,
which can be done intentionally). Since the string will be generated by the TD producer and the
dashboard will be generated by a different origin, this is a form of cross-site-scripting (XSS) attack.
See RFC 8259, section 12: JSON
should not be parsed as JavaScript using eval(). A WoT Thing Description is intended to be a pure
data exchange format for Thing metadata, not for holding executable content. An (invalid) TD may,
however, contain JavaScript code that, when executed, could have side effects compromising the security of a
system.
eval()
function to be parsed.
There are additional code injection risks discussed in [[WOT-DISCOVERY]]. Other strings in TDs, such as the
values given for
title and description, should be sanitized before being used in templates for SQL,
HTML, or other executable contexts. This risk, however, is specifically about the Javascript injection risk
when parsing JSON.
JSON-LD processing usually includes the replacement of short terms with longer IRIs [[RFC3987]]. For this reason, WoT Thing Descriptions may expand considerably when processed using a JSON-LD 1.1 processor and, in the worst case, the resulting data might consume all of the recipient's resources or cause an exploitable buffer overflow.
Privacy risks will depend on the association of Things with identifiable people and both the direct information and the inferred information available from such an association. A detailed discussion of privacy (and security) considerations for the Web of Things, including a threat model that can be adapted to various circumstances, is presented in the informative document [[WOT-SECURITY-GUIDELINES]]. This section discusses only privacy risks and possible mitigations directly relevant to the WoT Thing Description.
The use of a WoT Thing Description introduces the privacy risks given in the following sections. After each risk, we suggest some possible mitigations.
WoT Thing Descriptions can be evaluated with a JSON-LD 1.1 processor [[json-ld11]], which typically follows links to remote contexts (i.e., TD context extensions, see ) automatically, resulting in the transfer of files without the explicit request of the Consumer for each one. If remote contexts are served by third parties, it may allow them to gather usage patterns or similar information leading to disclosure of private information, or information that can be used to infer private information. In the case of the WoT, an attacker can also observe the network traffic produced by such fetches and can use the metadata of the fetch, such as the destination IP address, to infer information about the device, especially if domain-specific vocabularies are used. This is a risk even if the connection is encrypted, and is related to DNS privacy leaks. See also , which is a related security risk which can also be avoided with the following mitigations.
A Thing Description containing an identifier (id) may describe a Thing that is associated with an
identifiable person. Such identifiers pose various risks including tracking. However, if the identifier is
also immutable, then the tracking risk is amplified, since a device may be sold or given to another person and
the known ID used to track that person.
All identifiers used in a TD SHOULD be mutable, and in particular there SHOULD be a mechanism to update
the id of a Thing when necessary.
Specifically, the id of a Thing should not be fixed in hardware. This does, however,
conflict with the Linked Data ideal that identifiers are fixed URIs. However, as a matter of policy, it is
strongly suggested that deployments update identifiers upon major changes in configuration or
reinitialization. Examples of major changes in configuration include moving a Thing to a new local area
network, assigning a new domain name, or unregistering the Thing from one hub and registering it with a
new one. Generally, changes in configuration indicating a potential change in ownership should result in a
new identifier being created. If more frequent changes are desired during the operational phase of a
device, a mechanism can be put into place to notify only authorized users of the change in identifier when
a change is made. Note however that some classes of devices, e.g., medical devices, may require immutable
IDs by law in some jurisdictions.
Ideally, any required immutable identifiers should only be made available via affordances, such as a
property, whose value can only be obtained after appropriate authentication and authorization, and managed
separately from the TD identifier.
If it is necessary to use an immutable identifier as the TD identifier, extra attention should be paid to
secure access to files, such as Thing Descriptions, containing such immutable identifiers.
As noted above, the id member in a TD can pose a privacy risk. However, even if the
id is updated as described to mitigate its tracking risk, it may still be possible to associate a
TD with a particular physical device, and from there to an identifiable person, through fingerprinting.
Even if a specific device instance cannot be identified through fingerprinting, it may be possible to infer the type of a device from the information in the TD, such as the set of interactions, and use this type to infer private information about an identifiable person, such as a medical condition.
id can be omitted. If the
Consumer does not need certain interactions for its use case, they can be omitted. If the Consumer is not
authorized to use certain interactions, they can likewise be omitted.
The value of the id field of a TD might become available to entities that do not have access to
the full TD. If the value of the id
contains embedded metadata, such as the type of the device or the owner, this could be used to infer personal
information.
id of a TD SHOULD NOT contain metadata describing the Thing or from the TD
itself.
Any temporary ID generated to manage TDs, for example an ID for a database or directory service, SHOULD
NOT contain metadata describing the Thing or from the TD itself.
Using random UUIDs as recommended in
also mitigates this risk.
Globally unique identifiers pose a privacy risk if a centralized authority is needed to create and distribute them, since then a third party has knowledge of the identifiers.
id field in TDs is intentionally not required to be globally unique. There are several
cryptographic mechanisms (e.g., random UUIDs) available to generate suitable IDs in a distributed fashion
that do not require a central registry. These mechanisms typically have a very low probability of generating
duplicate identifiers, and this needs to be taken into account in the system design; for example, by
detecting duplicates and regenerating IDs when necessary. The scope of IDs also does not need to be global:
it is acceptable to use identifiers that only distinguish Things in a certain context, such as within a home
or factory.
TD identifiers SHOULD be generated using a distributed mechanism such as UUIDs that provides a high
probability of uniqueness.
TD identifiers SHOULD NOT be generated using a centralized authority.
In many locales, in order to protect the privacy of users, there are legal requirements for the handling of personally identifiable information, that is, information that can be associated with a particular person. Such information can of course be generated by IoT devices directly. However, the existence and metadata of IoT devices (the kind of data stored in a Thing Description) can also contain or be used to infer personally identifiable information. This information can be as simple as the fact that a certain person owns a certain type of device, which can lead to additional inferences about that person.
application/td+json Media Type RegistrationRules for processing both conforming and non-conforming content are defined in this specification.
Please look at the current IANA registration; in the future .td.json and .td.jsonld may also be allowed.
application/tm+json Media Type RegistrationRules for processing both conforming and non-conforming content are defined in this specification.
IANA assigns compact CoAP Content-Format IDs for media types in the CoAP Content-Formats subregistry within the Constrained RESTful Environments (CoRE) Parameters registry [[RFC7252]]. The Content-Format ID for WoT Thing Description is 432 and for the WoT Thing Model is - (tbd).
The following TD example uses HTTP, CoAP, and MQTT Protocol Bindings. These TDs have Context Extensions which
assume that there are CoAP-in-RDF and MQTT-in-RDF vocabularies similar to [[?HTTP-in-RDF10]] that are accessible
via the namespaces http://www.example.org/coap-binding# and
http://www.example.org/mqtt-binding#, respectively. Please note that the TD context at
"https://www.w3.org/2022/wot/td/v1.1" already includes the [[?HTTP-in-RDF10]], so HTTP context
extensions can be used directly. Note that each Binding Specification contains the most up-to-date
vocabulary terms and examples.
The context extensions we see below have the following instructions to the TD Consumer:
"htv:methodName" member instructs the Consumer which HTTP method has to be applied (e.g.,
"GET" for retrieving a resource or "POST" for sending data to a resource).
"cov:method" member instructs the Consumer which CoAP method has to be applied (e.g.,
"GET" for the CoAP Method Code 0.01, "POST" for the CoAP Method Code 0.02, or
iPATCH for CoAP Method Code 0.07).
"mqv:controlPacket" member instructs the Consumer which MQTT command has to be applied (e.g.,
"subscribe" for the subscribing to a topic and "unsubscribe" for unsubscribing).
First, TDs with a single protocol are shown. Then, TDs with multiple protocols are introduced where each interaction affordance has one form with one protocol.
Feature list of the Thing:
Feature list of the Thing:
/illuminance by the MQTT broker running behind the address
192.168.1.187:1883. Also see
MQTT Binding
Feature list of the Thing:
temperature which periodically
pushes the latest temperature value to the Consumer using a Webhook mechanism, where the
Thing sends POST requests to a callback URI provided by the Consumer. To describe this, the
subscription member defines a write-only parameter callbackURL, which must be
submitted through the subscribeevent form. The read-only parameter
subscriptionID is returned by the subscription. The TemperatureSensor will then
periodically POST to this callback URI with a payload defined by data. To unsubscribe, the
Consumer has to submit the unsubscribeevent form with the subscriptionID as
described in cancellation. Alternatively, a uriVariables approach, that informs
the Consumer to include the subscriptionID string in the URIs that have to be called
with the delete method (see tab 'With uriVariables'), can be used. In such setup, the
cancellation container can be obmitted. In general, this example can be further automated by
using a TD Context Extension to include proper semantic annotations.
Instead of a periodic POST request to the Thing, the Consumer may provide response data with
information when the next POST request should be provided by the Thing. This is described by using the
dataResponse field.
Feature list of the Thing:
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"cov": "http://www.example.org/coap-binding#",
"mqv": "http://www.example.org/mqtt-binding#",
"htv": "http://www.w3.org/2011/http#"
}
],
"title": "LampThing",
"id": "urn:dev:ops:32473-WoTLamp-1234",
"securityDefinitions": {
"nosec_sc": {
"scheme": "nosec"
}
},
"security": ["nosec_sc"],
"properties": {
"switchState": {
"type": "boolean",
"readOnly": true,
"observable": false,
"forms": [
{
"href": "http://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"htv:methodName":"GET"
}
]
},
"brightness": {
"type": "number",
"readOnly": true,
"observable": false,
"forms": [
{
"href": "coap://example.com/light/brightness",
"op": "readproperty",
"contentType": "application/json",
"cov:method": "GET"
}
]
}
},
"actions": {
"switchLight": {
"input": {
"type": "boolean"
},
"forms": [
{
"href": "http://example.com/switch/state",
"op": "invokeaction",
"contentType": "application/json",
"htv:methodName":"POST"
}
]
},
"setBrightness": {
"input": {
"type": "number",
"maximum":255
},
"forms": [
{
"href": "coap://example.com/light/brightness",
"op": "invokeaction",
"contentType": "application/json",
"cov:method": "POST"
}
]
}
},
"events":{
"concentration": {
"title": "Gas Concentration Event Stream",
"data":{
"type": "integer",
"minimum": -1,
"maximum": 65535
},
"forms": [
{
"href": "mqtt://broker.com",
"contentType": "application/json",
"op": "subscribeevent",
"mqv:filter": "application/deviceid/sensor/concentration",
"mqv:controlPacket": "subscribe"
}
]
}
}
}
Feature list of the Thing:
brightness property can be read via HTTP and CoAP, and observed via MQTT;
concentration event can be subscribed to via CoAP and MQTT. In this case, the Consumer would
pick the form it can support based on its internal implementation, e.g., whether it has a CoAP protocol
stack or not. Also see
HTTP Binding,
CoAP Binding,
and
MQTT Binding.
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"cov": "http://www.example.org/coap-binding#",
"mqv": "http://www.example.org/mqtt-binding#",
"htv": "http://www.w3.org/2011/http#"
}
],
"title": "Lamp",
"id": "urn:dev:ops:32473-WoTLamp-5678",
"securityDefinitions": {
"nosec_sc": {
"scheme": "nosec"
}
},
"security": ["nosec_sc"],
"properties": {
"switchState": {
"type": "boolean",
"readOnly": true,
"observable": false,
"forms": [
{
"href": "http://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"htv:methodName":"GET"
},
{
"href": "coap://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"cov:method": "GET"
}
]
},
"brightness": {
"type": "number",
"readOnly": true,
"observable": true,
"forms": [
{
"href": "http://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"htv:methodName":"GET"
},
{
"href": "coap://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"cov:method": "GET"
},
{
"href": "mqtt://broker.com",
"mqv:filter": "application/deviceid/sensor/brightness",
"op": "observeproperty",
"mqv:controlPacket": "subscribe"
}
]
}
},
"actions": {
"switchLight": {
"input": {
"type": "boolean"
},
"forms": [
{
"href": "http://example.com/switch/state",
"op": "invokeaction",
"contentType": "application/json",
"htv:methodName":"POST"
}
]
},
"setBrightness": {
"input": {
"type": "number",
"maximum":255
},
"forms": [
{
"href": "coap://example.com/light/brightness",
"op": "invokeaction",
"contentType": "application/json",
"cov:method": "POST"
}
]
}
},
"events":{
"concentration": {
"title": "Gas Concentration Event Stream",
"data":{
"type": "integer",
"minimum": -1,
"maximum": 65535
},
"forms": [
{
"href": "mqtt://broker.com",
"contentType": "application/json",
"op": "subscribeevent",
"mqv:filter": "application/deviceid/sensor/concentration",
"mqv:controlPacket": "subscribe"
},
{
"cov:method": "GET",
"href": "coap://example.com/sensor/gasconcentration",
"contentType": "application/json",
"op": "subscribeevent",
"subprotocol": "cov:observe"
}
]
}
}
}
A JSON Schema [[?JSON-SCHEMA]] document for syntactically validating Thing Description instances serialized in JSON based format is available at https://www.w3.org/ns/wot-next/td-schema. This JSON Schema does not require the terms with Default Values to be present. Thus, the terms with Default Values are optional. (see also )
The Thing Description defined by this document allows for adding external vocabularies by using
@context mechanism known from JSON-LD [[?json-ld11]], and the terms in those external vocabularies
can be used in addition to the terms defined in . For this reason, the
below JSON schema is intentionally non-strict in that regard. You can replace the value of
additionalProperties schema property true with false in different
scopes/levels in order to perform a stricter validation in case no external vocabularies are used.
The different cases on the variation of request and response are explained at
. The tables below summarize these cases in a concise manner. The tables start
from simpler cases, such as single contentType, and go for more complex cases, such as multiple
contentTypes. In all the tables, the messages are seen from the Thing point of view, where input
means messages sent from Consumer to the Thing (e.g., request) and output means messages sent from Thing to the
Consumer (e.g., response).
The cases are numbered, which can be used to associate them with examples after the tables.
| Case | Needed Terms | Explanation | Consumer Behavior | Thing Behavior |
|---|---|---|---|---|
| Case 1A: Input present, output not present | contentType inside the form |
contentType refers only to the input |
|
|
| Case 1B: Input not present, output present. | contentType inside the form. |
contentType refers only to the output. |
|
|
Case 1C: Input and output present, same contentType for messages. |
contentType inside the form. |
contentType refers both to input and output. |
|
|
The following table takes into account further variations that are relevant for cases where an operation input
can accept different contentTypes or the output can return different contentTypes.
There can be cases where an Interaction Affordance has multiple forms. Such cases with multiple forms should be
treated as a combination of the cases in the table above and below.
| Case | Needed Terms | Explanation | Consumer Behavior | Thing Behavior |
|---|---|---|---|---|
Case 2A: Single input and single output present, different contentType for messages. |
contentType and response inside the form. response has
contentType with a different value.
|
contentType in the form level refers to the input and contentType in the
response (response-level) refers to the output
|
|
|
Case 2B: Input and multiple possible outputs present, same contentType for messages |
contentType and additionalResponses inside the form. schema in the
additionalResponses array items can be needed.
|
contentType in the form level refers to the input and the normal output.
additionalResponses does not need contentType since the default value rule
applies. This is the same case (Case 1C) as there is actually a single contentType. However,
there can be different Data Schemas delivered in the output, requiring the
additionalResponses and schema terms in the form.
|
See Case 1C | See Case 1C |
Case 2C: Input and multiple possible outputs present, different contentType for output
messages
|
contentType, additionalResponses and possibly response inside the
form. additionalResponses needs contentType for output the messages with
different contentTypes.
|
This the most complicated case that can have different ways to be described in a TD.
contentType in the form level refers to the input and to the expected output if the output is
of the same contentType (like in case 1C). contentType inside
response refers to the expected output if the output is of a different
contentType (like in case 2A). contentType inside
additionalResponses refers to other possible outputs.
|
|
|
The present specification introduces the TD Information Model as a set of constraints over different
Vocabularies, i.e. sets of Vocabulary Terms. This section briefly explains how a machine-readable
definition of these constraints can be integrated into client applications, by making use of the mandatory
@context of a TD document.
Accessing the TD Information Model from a TD document is done in two steps. First, clients must retrieve a mapping from JSON strings to IRIs. This mapping is defined as a JSON-LD context, as explained later. Second, clients can access the constraints defined on these IRIs by dereferencing them. Constraints are defined as logical axioms in the RDF format, readily interpretable by client programs.
All Vocabulary Terms referenced in
are serialized as (compact) JSON strings in a TD document. However, each of these terms is unambiguously
identified by a full IRI, as per the first Linked Data principle [[LINKED-DATA]]. The mappings from JSON keys to
IRIs is what the
@context value of a TD points to. For instance, the file at
https://www.w3.org/ns/wot-next/td
includes the following mappings (among others):
properties |
→ | https://www.w3.org/2019/wot/td#hasPropertyAffordance |
object |
→ | https://www.w3.org/2019/wot/json-schema#ObjectSchema |
basic |
→ | https://www.w3.org/2019/wot/security#BasicSecurityScheme |
href |
→ | https://www.w3.org/2019/wot/hypermedia#hasTarget |
| ... | ||
This JSON file follows the JSON-LD 1.1 syntax [[JSON-LD11]]. Numerous JSON-LD libraries can automatically
process the @context of a TD and expand all the JSON strings it includes.
Once every Vocabulary Term of a TD is expanded to a IRI, the second step consists in dereferencing this IRI to get fragments of the TD Information Model that refer to that Vocabulary Term. For instance, dereferencing the IRI
https://www.w3.org/2019/wot/json-schema#ObjectSchema
results in an RDF document stating that the term ObjectSchema is a Class and more precisely,
a sub-class of DataSchema. Such logical axioms are represented in RDF using formalisms of various
complexity: here, sub-class relations are expressed as RDF Schema axioms [[RDF-SCHEMA]]. Moreover, these axioms
may be serialized in various formats. Here, they are serialized in the Turtle format [[TURTLE]]:
<https://www.w3.org/2019/wot/json-schema#ObjectSchema>
a rdfs:Class .
<https://www.w3.org/2019/wot/json-schema#ObjectSchema>
rdfs:subClassOf <https://www.w3.org/2019/wot/json-schema#DataSchema> .
By default, if a user agent does not perform any content negotiation, a human-readable HTML documentation is
returned instead of the RDF document. To negotiate content, clients must include the HTTP header
Accept: text/turtle in their request.
As an extension of [[[#payload-bindings-dataschema]]], this section collects examples of different payloads and
their corresponding DataSchema. These are from well-known IoT Platforms and Standards and aim to
illustrate the various ways a payload can look like and how one can describe it with a Data Schema.
SenML [[RFC8428]] might use the following construct:
[
{
"bn": "/example/light/"
},
{
"n": "level",
"v": 50
},
{
"n": "time",
"v": 10
}
]
|
{
"type": "array",
"items": [
{
"type": "object",
"properties": {
"bn": {
"type": "string",
"const": "example/light"
}
}
},
{
"type": "object",
"properties": {
"n": {
"type": "string",
"const": "level"
},
"v": {
"@type": ["iot:LevelData"],
"type": "integer",
"minimum": 0,
"maximum": 255
}
}
},
{
"type": "object",
"properties": {
"n": {
"type": "string",
"const": "time"
},
"v": {
"@type": ["iot:TransitionTimeData"],
"type": "integer",
"minimum": 0,
"maximum": 65535
}
}
}
]
}
|
A Batch Collection according to OCF[[OCF]] may be structured like this:
[
{
"href": "/example/light/level",
"rep": {
"dimmingSetting": 50
}
},
{
"href": "/example/light/time",
"rep": {
"rampTime": 10
}
}
]
|
{
"type": "array",
"items": [
{
"type": "object",
"properties": {
"href": {
"type": "string",
"const": "/example/light/level"
},
"rep": {
"type": "object",
"properties": {
"dimmingSetting": {
"@type": ["iot:LevelData"],
"type": "integer",
"minimum": 0,
"maximum": 255
}
}
}
}
},
{
"type": "object",
"properties": {
"href": {
"type": "string",
"const": "/example/light/time"
},
"rep": {
"type": "object",
"properties": {
"rampTime": {
"@type": ["iot:TransitionTimeData"],
"type":"integer",
"minimum": 0,
"maximum": 65535
}
}
}
}
}
]
}
|
And an IPSO Smart Object on LWM2M [[LWM2M]] might look like the following:
{
"bn": "/3001/0/",
"e": [
{
"n": "5044",
"v": 0.5
},
{
"n": "5002",
"v": 10.0
}
]
}
|
{
"type": "object",
"properties": {
"bn": {
"type": "string",
"const": "/3001/0/"
},
"e": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"n": {
"type": "string",
"const": "5044"
},
"v": {
"@type": ["iot:LevelData"],
"type": "number",
"minimum": 0.0,
"maximum": 1.0
}
}
},
{
"type": "object",
"Properties": {
"n": {
"type": "string",
"const": "5002"
},
"v": {
"@type": ["iot:TransitionTimeData"],
"type": "number",
"minimum": 0.0,
"maximum": 6553.5
}
}
}
]
}
}
}
|
contentType optional without defaults in all levels.The editors would like to specially thank Cristiano Aguzzi, Thomas Jäckle, Jan Romann, Elodie Thiéblin, Michael Koster, Michael Lagally, Kazuyuki Ashimura, Daniel Peintner, Toru Kawaguchi, María Poveda, Dave Raggett, Kunihiko Toumura, Takeshi Yamada, Ben Francis, Manu Sporny, Klaus Hartke, Addison Phillips, Jose M. Cantera, Tomoaki Mizushima, Soumya Kanti Datta and Benjamin Klotz for providing contributions, guidance and expertise.
Also, many thanks to the W3C staff and all other current and former active Participants of the W3C Web of Things Interest Group (WoT IG) and Working Group (WoT WG) for their support, technical input and suggestions that led to improvements to this document.
Finally, special thanks to Joerg Heuer for leading the WoT IG for 2 years from its inception and guiding the group to come up with the concept of WoT building blocks including the Thing Description.
Temporary ReSpec fix regarding non-listed references: [[RFC6068]], [[RFC3966]], [[html]], [[RFC6750]], [[RFC7519]], [[RFC7797]], [[RFC8392]], [[RFC7516]], [[LDML]], [[SEMVER]], [[RFC7617]], [[RFC7616]]