Copyright © 2020-2022 W3C ® ( MIT , ERCIM , Keio , Beihang ). W3C liability , trademark and permissive document license rules apply.
The WoT Profile Specification defines a Profiling Mechanism and a WoT Core Profile , which enables out of the box interoperability among things and devices. Out of the box interoperability implies, that devices can be integrated into various application scenarios without deep level adaptations. Typically only minor configuration operations are necessary (such as entering a network key, or IP address) to use the device in a certain scenario. These actions can be done by anyone without specific training.
The WoT Core Profile defines a set of constraints and rules , which compliant thing descriptions have to adopt to guarantee interoperability.
These rules are prescriptive, to ensure that compliant implementations satisfy the semantic guarantees implied by them. We call this set of rules a Profile .
The WoT Profile Specification as defined in this document serves two purposes:
This document incudes a binding of the core data model to HTTP(S) and selected notification sub-protocols. The core data model can be bound to other protocols - it is expected that bindings to other protocols (e.g. MQTT, CoAP) will be defined in the near future.
A TD that is compliant to the core profile MUST adhere to both the constraints on the data model and the protocol binding.
Devices that constrain their use of the Thing Description to the WoT Core Profile can interoperate with each other out-of-the-box.
Note that the core profile is not exclusive. Device implementers are free to adopt other features of the thing description that go beyond the constraints of the core profile, however the interoperability guarantees of the core profile hold only for the WoT Core Profile subset.
The W3C WoT Thing Architecture [ wot-architecture11 ] and WoT Thing Description [ wot-thing-description11 ] define a powerful description mechanism and a format to describe myriads of very different devices, which may be connected over various protocols. The format is very flexible and open and puts very few normative requirements on devices that implement it.
However, this flexibility de-facto prevents interoperability, since, without additional rules , it allows implementers to make many choices that do not provide guarantees of common behavior between implementations.
This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
This document was published by the Web of Things Working Group as an Editor's Draft.
Publication as an Editor's Draft does not imply endorsement by W3C and its Members.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 1 August 2017 W3C Patent Policy . W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 2 November 2021 W3C Process Document .
The W3C WoT Architecture [ wot-architecture11 ] and the WoT Thing Description [ wot-thing-description11 ] have been developed as a versatile format, that allows describing the interactions between multiple devices and protocols.
This flexibility permits an easy integration of new device types and protocols, however it risks interoperability, since there are no guarantees that two devices which are formally spec-compliant, will be able to communicate.
To increase adoption of the WoT specifications, interoperability between on premise devices, edge devices and the cloud is essential. Even if every manufacturer is implementing the current Thing Description specification in full flexibility, there is no interoperability guarantee; many choices are still left to the implementations and there are very few normative requirements that a device has to fulfill.
A Thing Description can be used in two fundamentally different deployment scenarios:
For green field deployments, where the implementations are being carried out and corresponding thing descriptions are being created, it is easier to achieve full interoperability by using a small, extensible Core Profile .
In the brown field area, due to the nature of existing deployments and protocols, a broad spectrum of variations and potentially high complexity of thing descriptions inhibits interoperability and will most likely lead to additional profiles of the WoT Thing Description and domain-specific thing consumer implementations.
The WoT Core Profile can be used by green field deployments and gives guidance to new implementers of the WoT specifications. It has already proved in brown-field scenarios in the PlugFests, where existing devices, that already existed as products, prototypes or demonstrators, were described with Thing Descriptions that are constrained to the Core Profile .
A set of over 30 use cases for the Web of Things were contributed by stakeholders from multiple industries for various application domains. These have been published in the WoT Use Cases and Requirements document [ wot-usecases ].
Based on these use cases a set of requirements have been derived which drive the development of the W3C Web of Things specification family. Several of these domains require easy integration of devices from multiple vendors, in other words, out-of-the-box interoperability. However, the descriptive approach taken by the WoT specifications generally leads to a large variety of different protocols and data formats, which can work against out-of-the box interoperability.
For example, a WoT Thing Description (TD) can in theory include a description based on a networking protocol unknown to a device that wishes to connect to it. To ensure interoperability without additional customization (e.g. by writing software or performing complex setup or configuration steps), the range of such choices needs to be limited to a finite set so that a consumer of a Thing Description can be sure it will be able to interact with any possible Thing. A finite set of customization choices is also important for implementing devices with a fixed code base. Defining such constraints leads to the profile mechanism and the WoT Core profile.
In addition to multiple vertical use cases that will use HTTP(S) for their implementations, there are horizontal use cases that are addressed by this profile specification. The primary focus is to enable Multi-Vendor system integration with out of the box interoperability:
During the recent WoT PlugFests there were many de-facto agreements on the use of a small constrained subset of interaction patterns and protocol choices. These de-facto agreements select a common subset of the WoT Thing Description , based on proven interoperability among manufacturers.
The aim of this specification is to formalize these agreements by defining a WoT Core Profile based on the choices that were made by the implementers of PlugFest devices.
The WoT Core Profile contains additional normative requirements that MUST be satisfied by devices to be compliant to the profile.
Adoption of the WoT Core Profile will significantly limit the implementation burden of device and cloud implementors.
The WoT Core Profile was defined with the following main goals:
It makes choices on the required metadata fields as well as the supported interactions and protocol endpoints. It introduces some constraints on data schemas for properties and actions which are required for resource constrained devices in real-world deployments. The format does not forbid the use of additional elements of the WoT Thing Description for vendor specific extensions, however this will impact interoperability.
Devices, which implement the Core Profile , are out-of-the-box interoperable with other Core Profile compliant devices. Furthermore, the Core Profile simplifies device validation and compliance testing since a corresponding conformance test suite can be defined.
The following classification adopts the terminology as described in the "H2020 – CREATE-IoT Project - Recommendations for commonalities and interoperability profiles of IoT platforms" [ H2020-CREATE-IoT ] report. The definitions below have been adapted to reflect the scope of the WoT profile.
Technical Interoperability is usually associated with communication protocols and the infrastructure needed for those protocols to operate. This implies agreeing on a common protocol (e.g. HTTP / TCP/IP) and providing additional clarifications, where required.
Syntactic Interoperability is usually associated with data formats and encodings along with techniques for compressing them. Examples for these formats and encodings in the WoT are JSON, XML, JSON-LD, UTF-8 payloads.
Semantic Interoperability is associated with a common understanding of the behavior of communication partners. In the profile context, it includes a common interpretation of (synchronous and asynchronous) action semantics, a common event model, how to set/get multiple properties, writable properties, a common error model and error messages.
Domain specific ontologies, e.g. semantic interop of automotive and medical devices exceed the scope of the profile.
Organisational Interoperability in the profile context implies that any consumer, which conforms with a given profile can interact with any Thing which conforms with the same profile, without additional customization.
Organisational Interoperability also requires commonly agreed approaches to security, trust and privacy, i.e. a consumer is provided access to Things only, when these common terms and conditions are applied.
Devices created by various engineers, vendors and SDOs that satisfy the requirements of the profile spec can be integrated with compliant consumers without additional customization. This works across infrastructures, regions and cultures.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , MUST NOT , NOT RECOMMENDED , OPTIONAL , RECOMMENDED , SHOULD , and SHOULD NOT in this document are to be interpreted as described in BCP 14 [ RFC2119 ] [ RFC8174 ] when, and only when, they appear in all capitals, as shown here.
A device or consumer implementation complies with this specification if it follows the normative statements in the present document.
A JSON Schema [ JSON-SCHEMA ] to validate the compliance of a Thing Description with the core profile is provided in Appendix A. JSON Schema of the Core Profile .
The fundamental WoT terminology such as Thing , Consumer , Thing Description ( TD ), WoT Thing Description , Partial TD , Thing Model ( TM ), Interaction Model , Interaction Affordance , Property , Action , Event , Protocol Binding , Servient , Vocabulary , Term , Vocabulary Term , WoT Interface , and WoT Runtime are defined in Section 3 of the WoT Architecture specification [ WOT-ARCHITECTURE ].
For convenience of the reader, we use the terms keyword and field for the linguistic notion vocabulary term as defined in the Thing Description Specification.
We use the terms device and thing in an interchangeable manner.
The following requirements were identified by the WoT profile task force and are addressed by the Profile 1.0 specification.
This is the most important objective of the profile. A TD Consumer satisfying the requirements of a profile should be able to process any TD also satisfying the profile and should be able to correctly interact with all affordances of the Thing such a TD describes.
This implies that a profile has three parts:Complexity addresses at least the follwing two things to simplify the development and reduce the implementation effort:
Get rid of ambiguities, i.e. clarify specifications to define interpretation of a TD and behavior of the thing and consumer.
Examples are the choice of properties vs. actions, use of PUT or POST for HTTP, observe protocols.
A profile should help define what needs to be implemented. This requirement also includes behavioral goals and recommendations about best practice for the implementation of Consumers and Things.
The mechanism used to indicate that a TD satisfies a profile should be general enough to indicate the TD satisfies the requirements for multiple profiles.
It should be possible to combine multiple profiles both for production and consumption:
It should be possible to indicate that a consumer can ingest TDs that satisfy one or more profiles, even if each TDs individually only satisfies one profile. For example, a Smart Building may need to use both "constrained" devices and "unconstrained" devices. A gateway consuming TDs should be able to ingest TDs designed for both the constrained and unconstrained contexts.
A Thing that satisfies all the requirements for multiple TDs (for example, a device using protocols common to two different usage contexts) should be able to indicate that.
Whether or not a TD satisfies the requirements of a given profile should be verifiable with automated tools. We can use the existing TD JSDON Schema as a basis and reuse the existing tooling (TD-playground)
There should be a mechanism to identify which profiles a TD satisfies. This mechanism should be intrinsic to a TD, i.e. be in-band.
A profile should limit the number of options, for example the set of possible protocols, to a finite set, so that a consumer can consume any TD in a given profile with a finite and static code base.
In order to conform with a profile, a Web Thing MUST conform with all the normative statements in the profile's specification.
In
order
to
denote
that
a
given
Web
Thing
conforms
to
one
or
more
profiles,
its
Thing
Description
MUST
include
a
profile
member
[
wot-thing-description11
].
The
value
of
the
profile
member
MUST
be
set
to
either
a
valid
URI
[
RFC3986
]
identifying
a
single
profile,
or
an
array
of
valid
URIs
identifying
multiple
profiles.
{
"@context": "https://www.w3.org/2019/wot/td/v1",
"id": "urn:dev:ops:32473-WoTLamp-1234",
"profile": "https://www.w3.org/2022/wot/profile/http-baseline/v1",
"title": "My Lamp",
"description": "A web connected lamp",
...
}
{
"@context": "https://www.w3.org/2019/wot/td/v1",
"id": "urn:dev:ops:32473-WoTLamp-1234",
"profile": [
"https://www.w3.org/2022/wot/profile/http-baseline/v1",
"https://www.w3.org/2022/wot/profile/http-sse/v1"
],
"title": "My Lamp",
"description": "A web connected lamp",
...
}
This section defines the HTTP Baseline Profile, which includes a Data Model and a Protocol Binding for reading and writing properties and invoking, querying and cancelling actions.
This profile may be used in conjunction with the HTTP SSE Profile or the HTTP Webhook Profile in order to provide operations for observing properties and listening for events.
In
order
to
denote
that
a
given
Web
Thing
conforms
to
the
HTTP
Baseline
Profile,
its
Thing
Description
MUST
have
a
profile
member
[
wot-thing-description
]
with
a
value
of
https://www.w3.org/2022/wot/profile/http-baseline/v1
.
The core data model incorporates the data model defined by chapter 5 of the Thing Description specification. The normative rules defined by that data model are the baseline for the definition of the core data model and are normative for the core data model. A core profile compliant implementation MUST additionally satisfy the requirements of this chapter.
The following rules are applicable to multiple classes of the WoT Thing Description Specification, as they provide clearer semantics, improved readability and simplified processing on resource constrained devices.
One of the primary benefits of the WoT Thing Description over a typical IoT format is the additional documentation for a human reader.
Therefore,
the
fields
title
and
description
are
MANDATORY
for
Things,
Property
Affordances,
Action
Affordances,
Event
Affordances
and
Data
Schemas.
It is possible to have empty values for these fields, if, for specific purposes it is not desired to provide documentation, however this is NOT RECOMMENDED and the conscious decision is obvious from the TD.
All date and time values MUST use the canonical dateTime representation format defined in section 3.2.7 of [xmlschema-2].
As described by this section the following constraints must be observed:All dateTime values MUST use UTC as the time zone and use the 'Z' identifier.
A time value of 24:00 is NOT PERMITTED, the value 00:00 MUST be used instead.
The
length
of
id
,
description
and
descriptions
values
is
limited
to
512
characters.
The
length
of
title
and
titles
values
is
limited
to
64
characters.
Where
a
type
permits
using
an
array
of
string
or
a
string
,
an
array
of
string
MUST
be
used.
TODO: decide if multiple types and contexts are required.
In this case the following section could be added:
The
only
exception
to
this
rule
are
@context
and
@type
annotations,
where
both
string
or
array
of
string
MAY
be
used.
Where
a
type
permits
using
an
array
of
DataSchema
or
a
DataSchema
,
an
array
of
DataSchema
MUST
be
used.
All
elements
of
an
enum
MUST
be
either
string
or
number
.
Different
types
in
a
single
enum
are
NOT
PERMITTED.
To provide minimum interoperability, the following metadata fields of a Thing MUST be contained in a compliant Thing Description:
keyword | type | remarks |
---|---|---|
title | string | human readable documentation |
id | urn_type | a globally unique urn of the thing |
description | string | human readable documentation |
created | date | human readable documentation |
modified | date | human readable documentation |
support | urn_type | human readable documentation |
security | array of string | simplified handling |
version | VersionInfo | clear versioning, easy to compare different TDs |
It is RECOMMENDED to use the value "" for strings, where the value cannot be determined.
If a Thing Description is used solely within a company, the email address of the developer SHOULD be used in the support field, if the Thing Description is provided externally, a support email address SHOULD be used.
It will be evaluated whether the profile also recommends some new TD terms that may be introduced in TD 1.1. Currently the following terms are discussed: serialNumber, hardwareRevision, softwareRevision, loc_latitude, loc_longitude loc_altitude, loc_height, and loc_depth. If these, or some of them, are defined in the TD 1.1 model, they may be recommended here in one of the next draft updates.
Data Schemas are used for the values of Properties, Action input and output parameters and Event message payloads. The value of a Data Schema can be a simple type (boolean, integer, number, string) or an instance of a structured type (array and object).
The Core Data Model applies the following constraints and rules to the
DataSchema
class
of
section
5.3.2.1
of
the
WoT
Thing
Description
Specification.
This
section
defines
a
subset
of
the
class
The
Core
Data
Model
restricts
the
use
of
arrays
and
objects
to
the
top
level
of
Data
Schemas,
i.e.
only
a
one-level
hierarchy
is
permitted.
The
members
of
a
top
level
This
may
appear
as
a
severe
limitation,
however
it
is
motivated
by
integrating
with
multiple
cloud
services.
Many
enterprise
services
and
applications
are
based
on
(relational)
databases,
where
individual
property
values
are
stored.
Of
course
databases
can
also
store
objects
(e.g.
encoded
as
a
JSON
string),
however
this
will
prevent
processing
by
other
enterprise
applications.
If
a
property
conceptually
has
a
deeper
structure,
such
as
grid
of
lamps
with
RGB
colors,
the
structure
can
be
represented
in
the
keyword
of
the
property,
i.e.
lamp1_color_r,
lamp1_color_g
and
lamp1_color_b.
A
similar
mapping
can
be
done
for
arrays
and
hierarchical
objects.
This
constraint
leads
to
simpler
Thing
Descriptions
that
can
be
handled
by
very
limited
devices.
The
following
fields
MUST
be
contained
in
a
DataSchema:
The
values
DataSchema
that
can
be
processed
on
resource-constrained
devices.
object
or
array
MUST
NOT
be
array
or
object
types.
keyword
type
constraints
description
human
readable
description
type
string
one
of
boolean,
integer,
number,
string,
array
or
object
object
,
array
MAY
only
be
used
at
the
top
level
of
a
Data
Schema.
The
type
value
MUST
NOT
be
null
.
PropertyAffordance
class
of
section
5.3.1.3
of
the
WoT
Thing
Description
Specification.
The
following
property
fields
MUST
be
contained
in
the
properties
element
of
a
Profile
compliant
TD
:
keyword | type | constraints |
---|---|---|
title | string | unique name among all properties |
description | string | human readable description |
type | string |
one
of
boolean
,
string
,
number
,
integer
,
object
or
array
.
The
type
value
null
MUST
NOT
be
used.
|
The
Thing
Description
permits
arbitrary
object
depths
for
properties.
Parsing
of
a
deeply
nested
structure
is
not
possible
on
resource
constrained
devices.
Therefore
each
property
MUST
NOT
exceed
a
maximum
depth
of
5
levels
of
nested
array
or
object
elements.
It
is
RECOMMENDED
to
keep
the
nesting
of
these
elements
below
4.
The following additional constraints MUST be applied to the Property Affordances of a Thing Description conforming to the Core Profile :
keyword | type | constraint |
---|---|---|
const | anyType | MUST NOT be used |
enum | array of simple type | Values of enums MAY only be simple types. Handling of any type is too complex to implement on resource constrained devices |
forms | array of Forms |
The
Array
of
Form
of
each
property
MUST
contain
only
a
single
endpoint
for
each
operation
readproperty
,
writeproperty
,
observeproperty
,
unobserveproperty
.
|
format | string |
If
the
field
format
is
used,
formats
defined
in
section
7.3.1-7.3.6
of
[
JSON-SCHEMA
]
MUST
be
used.
|
oneOf | string |
The
DataSchema
field
oneOf
does
not
make
sense
for
properties
and
MUST
NOT
be
used.
|
uriVariables | Map of DataSchema |
uriVariables
MUST
NOT
be
used.
|
It
is
highly
RECOMMENDED
to
always
specify
a
unit
,
if
a
value
has
a
metric.
Authors
of
Thing
Descriptions
should
be
aware,
that
units
that
are
common
in
their
geographic
region
are
not
globally
applicable
and
may
lead
to
misinterpretation
with
drastic
consequences.
The
field
unit
could
be
used
for
non-decimal
numeric
types
as
well,
e.g.
a
string
value
with
binary
or
hex
data
(
0xCAFEBABE
,
0b01000010
),
where
the
unit
is
hex
or
bin
,
to
indicate
how
the
value
should
be
interpreted.
It
is
strongly
RECOMMENDED
to
use
the
values
hex
,
oct
or
bin
in
this
case
to
achieve
interoperability.
ActionAffordance
class
of
section
5.3.1.4
of
the
WoT
Thing
Description
Specification.
The following fields MUST be contained in an action element of an Core Profile compliant TD:
keyword | type | constraints |
---|---|---|
title | string | unique name among all actions |
input | array of DataSchema | all elements of the subclasses objectSchema and dataSchema MUST only contain simple types. |
output | array of DataSchema | all elements of the subclasses objectSchema and dataSchema MUST only contain simple types. |
The
elements
of
the
DataSchema
subclasses
ArraySchema
and
ObjectSchema
for
the
fields
input
and
output
are
restricted
to
simple
types
in
a
Thing
Description
conforming
to
the
Core
Data
Model
.
Without
this
limitation
a
higher
implementation
burden
would
be
put
on
resource
constrained
devices
(arbitrary
cascaded
arrays
and
multi-level
objects)
which
cannot
be
satisfied
by
all
consuming
devices.
The following additional constraints MUST be applied to the Interaction Affordances of a Thing Description conforming to the Core Data Model :
keyword | type | constraint |
---|---|---|
forms | array of Forms |
The
Array
of
Form
of
each
action
MUST
contain
only
a
single
endpoint.
|
format | string |
If
the
field
format
is
used,
formats
defined
in
section
7.3.1-7.3.6
of
[
JSON-SCHEMA
]
MUST
be
used.
|
oneOf | string |
The
DataSchema
field
oneOf
does
not
make
sense
for
properties
and
MUST
NOT
be
used.
|
uriVariables | Map of DataSchema |
uriVariables
MUST
NOT
be
used.
|
TODO:
- no optional parameters
- timeout
EventAffordance
class
of
section
5.3.1.5
of
the
WoT
Thing
Description
Specification.
A Thing MAY provide more than one event mechanism to enable a variety of consumers.
TODO:
The events section needs to be signifcantly extended and define addtional constraints to ensure OOTBI. LongPoll, WebSockets and WebHooks can be considered as initial candidates for supported protocols for the event mechanism to identify appropriate data model constraints.
The individual protocol constraints need to be defined in a respective protocol binding chapter after they have been identified/evaluated in plugfests.
The following fields MUST be present in an event element of a Core TD :
keyword | type | constraints |
---|---|---|
title | string | unique name among all events |
description | string | human readable description |
data | set of DataSchema instances in a JSON object | only the DataSchema subclasses booleanSchema, IntegerSchema, NumberSchema, StringSchema are permitted |
The following additional constraints MUST be applied to the Event Affordances of a WoT Thing Description conforming to the profile:
keyword | type | constraint |
---|---|---|
forms | array of Forms |
The
Array
of
Form
of
each
event
MUST
contain
only
a
single
endpoint.
|
uriVariables | Map of DataSchema |
uriVariables
MUST
NOT
be
used.
|
A Thing MAY provide more than one event mechanism to enable a variety of consumers.
The following fields MUST be present in a form element of a Core TD :
keyword | type | constraints |
---|---|---|
title | string | unique name among all events |
description | string | human readable description |
data | set of DataSchema instances in a JSON object | only the DataSchema subclasses booleanSchema, IntegerSchema, NumberSchema, StringSchema are permitted |
The following additional constraints MUST be applied to the Form elements of a WoT Thing Description conforming to the Core profile :
keyword | type | constraint |
---|---|---|
security | string or Array of string |
security
at
form
level
MUST
NOT
be
used.
|
scopes | string or Array of string |
scopes
MUST
NOT
be
used.
|
The "type" relationship as defined in chapter 6 of [ RFC6903 ] is reserved for indicating an instance relationship between a thing and a thing template. The Core Data Model does not put additional constraints or requirements on links. The interpretation of a link is out of scope.
This section defines a protocol binding which describes how a Consumer communicates with a Web Thing [ wot-architecture11 ] using JSON [ JSON ] payloads over the HTTP [ HTTP11 ] protocol.
A Consumer or Web Thing conforming to the HTTP Baseline Profile MUST implement this protocol binding.
The
URL
of
a
Property
resource
to
be
used
when
reading
the
value
of
a
property
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
corresponding
PropertyAffordance
for
which:
op
member
contains
the
value
readproperty
.
href
member
is
http
or
https
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Property
resource.
In order to read the value of a property, a Consumer MUST send an HTTP request to a Web Thing with:
GET
Property
resource
Accept
header
set
to
application/json
GET /things/lamp/properties/on HTTP/1.1
Host: mythingserver.com
Accept
:
application/json
If a Web Thing receives an HTTP request following the format above and the Consumer has permission to read the corresponding property, then upon successfully reading the value of the property it MUST send an HTTP response with:
200
Content-Type
header
set
to
application/json
HTTP/1.1 200 OK
Content-Type: application/json
false
The
URL
of
a
Property
resource
to
be
used
when
writing
the
value
of
a
property
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
corresponding
PropertyAffordance
for
which:
op
member
contains
the
value
writeproperty
href
member
is
http
or
https
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Property
resource.
In order to write the value of a property, a Consumer MUST send an HTTP request to a Web Thing with:
PUT
Property
resource
Content-Type
header
set
to
application/json
PUT /things/lamp/properties/on HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
true
If a Web Thing receives an HTTP request following the format above and the Consumer has permission to write the corresponding property, then upon successfully writing the value of the property it MUST send an HTTP response with:
204
HTTP/1.1
204
No
Content
The
URL
of
a
Properties
resource
to
be
used
when
reading
the
value
of
all
properties
at
once
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
top
level
forms
member
for
which:
op
member
contains
the
value
readallproperties
href
member
is
http
or
https
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Properties
resource.
In order to read the value of all properties, a Consumer MUST send an HTTP request to a Web Thing with:
GET
Properties
resource
Accept
header
set
to
application/json
GET /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Accept
:
application/json
If a Web Thing receives an HTTP request following the format above, then upon successfully reading the values of all the readable properties to which the Consumer has permission to access, it MUST send an HTTP response with:
200
Content-Type
header
set
to
application/json
HTTP/1.1 200 OK
Content-Type: application/json
{
"on": false,
"level": 100
}
The
URL
of
a
Properties
resource
to
be
used
when
writing
the
value
of
multiple
properties
at
once
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
top
level
forms
member
for
which:
op
member
contains
the
value
writemultipleproperties
href
member
is
http
or
https
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Properties
resource.
In order to write the value of multiple properties at once, a Consumer MUST send an HTTP request to a Web Thing with:
PUT
Properties
resource
Content-Type
header
set
to
application/json
PUT /things/lamp/properties HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
{
"on": true,
"level": 50
}
If a Web Thing receives an HTTP request following the format above, then upon successfully writing the values of the requested writable properties it MUST send an HTTP response with:
204
HTTP/1.1
204
No
Content
Other
operations
under
consideration
include
observeproperty
,
unobserveproperty
,
observeallproperties
and
unobserveallproperties
.
These operations would require consesus on a default observe mechanism for HTTP (e.g. Server Sent Events or WebSockets).
readmultipleproperties
is
currently
excluded
due
to
the
complexities
of
the
request
payload
format
and
because
it
doesn't
add
much
functionality
over
readproperty
and
readallproperties
.
writeallproperties
is
currently
excluded
because
it
is
just
a
special
case
of
writemultipleproperties
.
The
URL
of
an
Action
resource
to
be
used
when
invoking
an
action
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
corresponding
ActionAffordance
for
which:
op
member
is
invokeaction
href
member
is
http
or
https
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Action
resource.
In order to invoke an action on a Web Thing, a Consumer MUST send an HTTP request to the Web Thing with:
POST
Action
resource
Accept
header
set
to
application/json
Content-Type
header
set
to
application/json
POST /things/lamp/actions/fade HTTP/1.1
Host: mythingserver.com
Content-Type: application/json
Accept: application/json
{
"level": 100,
"duration": 5
}
If a Web Thing receives an HTTP request following the format above then it MUST respond with one of three response formats:
For
long-running
actions
which
are
not
expected
to
finish
executing
within
the
timeout
period
of
an
HTTP
request
(e.g.
30
to
120
seconds),
it
is
RECOMMENDED
that
a
Web
Thing
respond
with
an
Asynchronous
Action
Response
so
that
a
Consumer
may
continue
to
monitor
the
status
of
an
action
request
with
a
queryaction
operation
on
a
dynamically
created
ActionStatus
resource,
after
the
initial
invokeaction
response.
For short-lived actions which are expected to finish executing within the timeout period of an HTTP request, a Web Thing MAY wait until the action has completed to send a Synchronous Action Response.
If
a
Web
Thing
encounters
an
error
in
attempting
to
execute
an
action
before
responding
to
the
invokeaction
request,
then
it
MUST
send
an
Error
Response.
Conforming
Consumers
MUST
support
all
three
types
of
response
to
the
initial
invokeaction
request,
but
support
for
subsequent
operations
on
an
ActionStatus
resource
is
OPTIONAL
.
The
status
of
an
action
invocation
request
is
represented
by
an
ActionStatus
object
which
includes
the
following
members:
Member | Description | Assignment | Type |
---|---|---|---|
status
|
The status of the action request. | mandatory |
string
(one
of
pending
,
running
,
completed
or
failed
)
|
output
|
The
output
data,
if
any,
of
a
completed
action
which
MUST
conform
with
the
output
data
schema
of
the
corresponding
ActionAffordance
.
|
optional | any type |
error
|
An
error
message,
if
any,
associated
with
a
failed
action
which
MUST
use
the
JSON
serialization
of
the
Problem
Details
format
[
RFC7807
]
(only
needed
in
response
to
a
queryaction
operation).
|
optional |
object
|
href
|
The
[
URL
]
of
an
ActionStatus
resource
which
can
be
polled
with
a
queryaction
operation
to
get
the
latest
status
of
the
action,
the
URI
scheme
[
RFC3986
]
of
which
MUST
resolve
to
http
or
https
(only
needed
for
an
Asynchronous
Action
Response
).
|
optional |
string
|
If providing a Synchronous Action Response, a Web Thing MUST send an HTTP response with:
200
Content-Type
header
set
to
application/json
ActionStatus
object
serialized
in
JSON
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "completed"
}
If
providing
an
Asynchronous
Action
Response,
a
Web
Thing
MUST
send
an
HTTP
response
containing
the
URL
of
an
ActionStatus
resource,
the
URI
scheme
[
RFC3986
]
of
which
MUST
resolve
to
http
or
https
.
The
response
MUST
have:
201
Content-Type
header
set
to
application/json
Location
header
set
to
the
URL
of
the
ActionStatus
resource
ActionStatus
object
serialized
in
JSON,
with
its
href
member
set
to
the
URL
of
the
ActionStatus
resource
HTTP/1.1 201 CREATED
Content-Type: application/json
Location: /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655
{
"status": "pending",
"href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655"
}
A
queryaction
operation
is
used
to
query
the
current
state
of
an
ongoing
action
request.
A
Web
Thing
which
provides
Asynchronous
Action
Response
s
to
an
invokeaction
operation
on
an
Action
MUST
also
support
queryaction
operations
on
that
same
Action
.
A
Web
Thing
which
only
provides
Synchronous
Action
Response
s
to
an
invokeaction
operation
on
an
Action
SHOULD
NOT
support
queryaction
operations
on
that
same
Action
.
The
URL
of
an
ActionStatus
resource
to
be
used
in
a
queryaction
operation
MUST
be
obtained
from
the
Location
header
of
an
Asynchronous
Action
Response
,
or
the
href
member
of
the
ActionStatus
object
in
its
body.
In order to query the status of an action request, a Consumer MUST send an HTTP request to a Web Thing with:
GET
ActionStatus
resource
Accept
header
set
to
application/json
GET /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655
Host: mythingserver.com
Accept:
application/json
If
a
Web
Thing
receives
an
HTTP
request
following
the
format
above
and
the
Consumer
has
permission
to
query
the
corresponding
ActionStatus
resource,
then
upon
successfully
reading
the
status
of
the
action
request
it
MUST
send
an
HTTP
response
with:
200
Content-Type
header
set
to
application/json
ActionStatus
object
representing
the
current
status
of
the
action
request,
serialized
in
JSON
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "running"
}
If
the
queried
action
failed
to
execute,
then
the
status
member
of
the
ActionStatus
object
MUST
be
set
to
"failed"
and
the
error
member
may
optionally
provide
additional
error
information
conforming
to
the
Problem
Details
format
[
RFC7807
].
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "failed",
"error": {
"type": "https://mythingserver.com/docs/errors/invalid-level",
"title": "Invalid value for level provided",
"invalid-params": [
{
"name": "level",
"reason": "Must be a valid number between 0 and 100",
}
]
}
}
A
cancelaction
operation
is
used
to
cancel
an
ongoing
Action
request.
A
Web
Thing
which
provides
Asynchronous
Action
Response
s
to
an
invokeaction
operation
on
an
Action
MAY
also
support
cancelaction
operations
on
that
same
Action
.
A
Web
Thing
which
only
provides
Synchronous
Action
Response
s
to
an
invokeaction
operation
on
an
Action
SHOULD
NOT
support
cancelaction
operations
on
that
same
Action
.
The
URL
of
an
ActionStatus
resource
to
be
used
in
a
cancelaction
operation
MUST
be
obtained
from
the
Location
header
of
an
Asynchronous
Action
Response
,
or
the
href
member
of
the
ActionStatus
object
in
its
body.
In order to cancel an action request, a Consumer MUST send an HTTP request to a Web Thing with:
DELETE
ActionStatus
resource
DELETE /things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655 HTTP/1.1
Host
:
mythingserver.com
If
a
Web
Thing
receives
an
HTTP
request
following
the
format
above
and
the
Consumer
has
permission
to
cancel
the
corresponding
Action
request,
then
upon
successfully
cancelling
Action
it
MUST
send
an
HTTP
response
with:
204
HTTP/1.1
204
No
Content
The
URL
of
an
Actions
resource
to
be
used
when
querying
the
status
of
all
ongoing
action
requests
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
top
level
forms
member
for
which:
op
member
contains
the
value
queryallactions
href
member
is
http
or
https
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Actions
resource.
In order to query the status of all ongoing action requests, a Consumer MUST send an HTTP request to a Web Thing with:
GET
Actions
resource
Accept
header
set
to
application/json
GET /things/lamp/actions HTTP/1.1
Host: mythingserver.com
Accept
:
application/json
If a Web Thing receives an HTTP request following the format above, then upon successfully retreiving the status of all ongoing action requests to which the Consumer has permission to access, it MUST send an HTTP response with:
200
Content-Type
header
set
to
application/json
Action
name,
with
the
value
of
each
object
member
being
an
array
of
ActionStatus
objects
representing
the
action
requests,
serialized
in
JSON.
Each
array
MUST
be
sorted
in
reverse
chronological
order
such
that
the
most
recent
action
request
appears
first.
HTTP/1.1 200 OK
Content-Type: application/json
{
"fade": [
{
"status": "completed",
"href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-426655"
},
{
"status": "failed",
"href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a456-558329",
},
{
"status": "running",
"href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a457-434656"
},
{
"status": "pending",
"href": "/things/lamp/actions/fade/123e4567-e89b-12d3-a457-ea9519"
}
]
}
Action
request
is
cancelled
with
a
cancelaction
operation,
its
ActionStatus
object
is
deleted
and
need
not
be
retained.
For
all
other
Action
requests
it
is
assumed
that
a
Web
Thing
will
store
the
ActionStatus
object
so
that
its
status
may
later
be
queried
with
a
queryaction
or
queryallactions
operation.
It
is
not
expected
that
ActionStatus
objects
should
be
retained
indefinitely,
they
may
be
stored
in
volatile
memory
and/or
periodically
pruned.
The
length
of
time
for
which
to
retain
ActionStatus
objects
is
expected
to
be
implementation-specific
and
may
depend
on
application-specific
requirements
or
resource
constraints.
If any of the operations defined above are unsuccessful then the Web Thing MUST send an HTTP response with an HTTP error code which describes the reason for the failure. It is RECOMMENDED that error responses use one of the following HTTP error codes:
400
Bad
Request
401
Unauthorized
403
Forbidden
404
Not
Found
500
Internal
Server
Error
Web
Things
MAY
respond
with
other
valid
HTTP
error
codes
(e.g.
418
I'm
a
teapot
),
but
Consumers
MAY
interpret
those
error
codes
as
a
generic
4xx
or
5xx
error
with
no
special
defined
behaviour.
TODO: If we define the finite set of error responses as above then we should also define what a Consumer should do if it receives a 3xx redirect type response.
If an HTTP error response contains a body, the content of that body MUST conform with with the Problem Details format [ RFC7807 ].
Below is a list of security schemes [ wot-thing-description ] which conformant Web Things MAY use and conformant Consumers MUST support:
The list of security schemes to include in the HTTP Baseline Profile is still under discussion .
A Thing MAY implement multiple security schemes.
Security
schemes
MUST
be
applied
using
the
top
level
security
member
of
a
Thing
and
MUST
NOT
be
applied
to
individual
Form
s.
Please see WoT Security Best Practices for implementation advice.
This section defines the HTTP SSE Profile, including a Protocol Binding for observing properties and listening for events using Server-Sent Events [ EVENTSOURCE ].
This profile may be used in conjunction with the HTTP Baseline Profile in order to provide operations to read and write properties and invoke, query and cancel actions.
In
order
to
denote
that
a
given
Web
Thing
conforms
to
the
HTTP
SSE
Profile,
its
Thing
Description
MUST
have
a
profile
member
[
wot-thing-description
]
with
a
value
of
https://www.w3.org/2022/wot/profile/http-sse/v1
.
This section defines a protocol binding which describes how a Consumer communicates with a Web Thing [ wot-architecture11 ] using Server-Sent Events [ EVENTSOURCE ].
A Consumer or Web Thing conforming to the HTTP SSE Profile MUST implement this protocol binding.
The HTTP SSE Profile uses Server-Sent Events [ EVENTSOURCE ] as a mechanism for Consumers to subscribe to events emitted by a Web Thing.
Consumers
are
not
required
to
implement
the
EventSource
JavaScript
API
from
the
Server-Sent
Events
specification
in
order
to
conform
with
this
profile.
Any
programming
language
may
be
used
to
consume
an
event
stream.
The
URL
of
an
Event
resource
to
be
used
when
subscribing
to
an
event
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
corresponding
EventAffordance
for
which:
op
member
contains
the
value
subscribeevent
href
member
is
http
or
https
subprotocol
member
has
a
value
of
"sse"
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Event
resource.
In
order
to
subscribe
to
an
event,
a
Consumer
MUST
follow
the
Server-Sent
Events
[
EVENTSOURCE
]
specification
to
open
a
connection
with
the
Web
Thing
at
the
URL
of
the
Event
resource.
This involves the Consumer sending an HTTP request to the Web Thing with:
GET
Event
resource
Accept
header
set
to
text/event-stream
Connection
header
set
to
keep-alive
GET /things/lamp/events/overheated HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream
Connection
:
keep-alive
For
Consumers
implemented
in
JavaScript
[
ECMASCRIPT
]
and
executed
in
a
runtime
which
exposes
the
EventSource
interface,
a
Server-Sent
Events
connection
can
be
initiated
using
the
EventSource
constructor.
const
overheatedEventSource
=
new
EventSource(
'/things/lamp/events/overheated'
);
If a Web Thing receives an HTTP request following the format above and the Consumer has permission to subscribe to the corresponding event, then it MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to maintain an open connection with the Consumer and push event data to the Consumer as events of the specified type are emitted.
This involves the Web Thing initially sending an HTTP response to the Consumer with:
200
Content-Type
header
set
to
text/event-stream
HTTP/1.1 200 OK
Content-Type
:
text/event-stream
Whenever
an
event
of
the
specified
type
occurs
while
the
Web
Thing
has
an
open
connection
with
a
Consumer,
the
Web
Thing
MUST
send
event
data
to
the
Consumer
using
the
event
stream
format
in
the
Server-Sent
Events
[
EVENTSOURCE
]
specification.
For
each
message
sent,
the
Web
Thing
MUST
set
the
event
field
to
the
name
of
the
EventAffordance
and
populate
the
data
field
with
event
data,
if
any.
The
event
data
MUST
follow
the
data
schema
specified
in
the
EventAffordance
and
MUST
be
serialized
in
JSON.
The
id
field
SHOULD
be
set
to
a
unique
identifier
for
the
event,
for
use
when
re-establishing
a
dropped
connection
(see
below).
event: overheated\n
data: 90\n
id:
12345\n\n
If
the
connection
between
the
Consumer
and
Web
Thing
drops
(except
as
a
result
of
the
unsubscribe
operation
defined
below),
the
Consumer
MUST
re-establish
the
connection
following
the
steps
outlined
in
the
Server-Sent
Events
specification
[
EVENTSOURCE
].
Once
the
connection
is
re-established
the
Web
Thing
SHOULD
,
if
possible,
send
any
missed
events
which
occured
since
the
last
event
specified
by
the
Consumer
in
a
Last-Event-ID
header.
In order to unsubscribe from an event, a Consumer MUST terminate the corresponding Server-Sent Events connection with the Web Thing as specified in the Server-Sent Events specification [ EVENTSOURCE ].
For
Consumers
implemented
in
JavaScript
[
ECMASCRIPT
]
and
executed
in
a
runtime
which
exposes
the
EventSource
interface,
a
Server-Sent
Events
connection
can
be
terminated
using
the
close()
method
on
an
EventSource
[
EVENTSOURCE
]
object.
overheatedEventSource.close()
;
The
URL
of
an
events
resource
to
be
used
when
subscribing
to
all
events
emitted
by
a
Web
Thing
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
top
level
forms
member
of
a
Thing
Description
for
which:
op
member
contains
the
value
subscribeallevents
href
member
is
http
or
https
subprotocol
member
has
a
value
of
"sse"
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
events
resource.
In order to subscribe to all events emitted by a Web Thing, a Consumer MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to open a connection with the Web Thing at the URL of the events resource.
This involves the Consumer sending an HTTP request to the Web Thing with:
GET
Accept
header
set
to
text/event-stream
Connection
header
set
to
keep-alive
GET /things/lamp/events HTTP/1.1
Host: mythingserver.com
Accept: text/event-stream
Connection
:
keep-alive
For
Consumers
implemented
in
JavaScript
[
ECMASCRIPT
]
and
executed
in
a
runtime
which
exposes
the
EventSource
interface,
a
Server-Sent
Events
connection
can
be
initiated
using
the
EventSource
constructor.
const
lampEventsSource
=
new
EventSource(
'/things/lamp/events'
);
If a Web Thing receives an HTTP request following the format above then it MUST follow the Server-Sent Events [ EVENTSOURCE ] specification to maintain an open connection with the Consumer and push event data to the Consumer for all event types for which it has permission to subscribe.
This involves the Web Thing initially sending an HTTP response to the Consumer with:
200
Content-Type
header
set
to
text/event-stream
HTTP/1.1 200 OK
Content-Type
:
text/event-stream
Whenever
an
event
occurs
while
the
Web
Thing
has
an
open
connection
with
a
Consumer,
the
Web
Thing
MUST
send
event
data
to
the
Consumer
using
the
event
stream
format
in
the
Server-Sent
Events
[
EVENTSOURCE
]
specification.
For
each
message
sent,
the
Web
Thing
MUST
set
the
event
field
to
the
name
of
the
EventAffordance
and
populate
the
data
field
with
event
data,
if
any.
The
event
data
MUST
follow
the
data
schema
specified
in
the
EventAffordance
and
MUST
be
serialized
in
JSON.
The
id
field
SHOULD
be
set
to
a
unique
identifier
for
the
event,
for
use
when
re-establishing
a
dropped
connection
(see
below).
event: overheated\n
data: 90\n
id:
12345\n\n
If
the
connection
between
the
Consumer
and
Web
Thing
drops
(except
as
a
result
of
the
unsubscribeallevents
operation
defined
below),
the
Consumer
MUST
re-establish
the
connection
following
the
steps
outlined
in
the
Server-Sent
Events
specification
[
EVENTSOURCE
].
Once
the
connection
is
re-established
the
Web
Thing
SHOULD
,
if
possible,
send
any
missed
events
which
occured
since
the
last
event
specified
by
the
Consumer
in
a
Last-Event-ID
header.
In order to unsubscribe from all events, a Consumer MUST terminate the corresponding Server-Sent Events connection with the events endpoint of the Web Thing, following the steps specified in the Server-Sent Events specification [ EVENTSOURCE ].
For
Consumers
implemented
in
JavaScript
[
ECMASCRIPT
]
and
executed
in
a
runtime
which
exposes
the
EventSource
interface,
a
Server-Sent
Events
connection
can
be
terminated
using
the
close()
method
on
an
EventSource
[
EVENTSOURCE
]
object.
lampEventsSource.close()
;
This section defines the HTTP Webhook Profile , including a Protocol Binding for observing properties and listening for events using WebHooks [ FIXME: add reference ].
The HTTP Webhook profile MAY be used in conjunction with the HTTP Baseline Profile in order to provide operations to read and write properties and invoke, query and cancel actions.
The HTTP Webhook profile MAY be used as an alternative event mechanism to the HTTP SEE Profile.
In
order
to
denote
that
a
given
Web
Thing
conforms
to
the
HTTP
Webhook
Profile,
its
Thing
Description
MUST
have
a
profile
member
[
wot-thing-description
]
with
a
value
of
https://www.w3.org/2022/wot/profile/http-webhook/v1
.
This section defines a protocol binding which describes how a Consumer communicates with a Web Thing [ wot-architecture11 ] using Webhook Events [ FIXME: Reference ].
A Consumer or Web Thing conforming to the HTTP Webhook Profile MUST implement this protocol binding.
The following sequence diagram illustrates the operation and message flow from subscription to an event via notification on a state change to unsubscription.
The following example contains a snippet from a TD that illustrates how a Webhook event can be described.
...
{
"events": {
"fireAlarm": { "description": "Fire!", "subscription": { "type": "object", "properties": {
...
listener: uri,
...
}
}
},
"data": {
"type": "boolean", "description": "true, if the alert button has been pushed, false, if the button was armed again."
},
"dataResponse": {
"type": "string", "description": "acknowledged by operator named: "
},
"cancellation": {
"type": "object", "properties": {
listener: uri
}
}
},
"forms": [
{
"op": "subscribeevent", "href": "http://192.168.0.124:8080/events/fireAlarm", "contentType": "application/json", "htv:methodName": "POST"
},
{
"op": "unsubscribeevent",
"href": "http://192.168.0.124:8080/events/fireAlarm/unsubscribe", "htv:methodName": "DELETE"
}
]
},
"batteryLow": {
...
}
}
}
The HTTP Webhook Profile uses Webhooks as a mechanism for Consumers to subscribe to events emitted by a Web Thing.
The mechanism is scalable and supports Consumers that receive events from multiple Things. Consumers implement a Webhook listener that is handling the event streams generated by Things. Depending on the use case, a single listener for multiple things and multiple event types may be used.
The
URL
of
an
Event
resource
to
be
used
when
subscribing
to
an
event
MUST
be
obtained
from
a
Thing
Description
by
locating
a
Form
inside
the
corresponding
EventAffordance
for
which:
op
member
contains
the
value
subscribeevent
href
member
is
http
or
https
subprotocol
member
has
a
value
of
"webhook"
The
resolved
value
of
the
href
member
MUST
then
be
used
as
the
URL
of
the
Event
resource.
In
order
to
subscribe
to
an
event,
a
Consumer
MUST
provide
the
listener
URL
in
the
data
payload
of
the
subscribe
operation
of
the
Event
resource.
This involves the Consumer sending an HTTP request to the Web Thing with:
POST
Event
resource
Accept
header
set
to
application/json
Request
Payload
contains
a
JSON
object
with
a
subscription
payload.
POST /things/lamp/events/overheated HTTP/1.1Host: mythingserver.comAccept: application/json{
"properties": {
...
listener: uri,
...
}
}
If a Web Thing receives an HTTP request following the format above and the Consumer has permission to subscribe to the corresponding event, then it MUST send event messsages to the Consumer as events of the specified type are emitted.
A Thing Description can be syntactically validated with the JSON Schema [ JSON-SCHEMA ] for compliance with the core profile.
Todo: Define a JSON-SCHEMA.
Referenced in:
Referenced in:
Referenced in: