W3C
Editor's
Draft
26
August
2024
Copyright
©
2017-2024
2017-2025
World
Wide
Web
Consortium
.
W3C
®
liability
,
trademark
and
permissive
document
license
rules
apply.
The Web of Things is made of entities ( Thing s) that can describe their capabilities in a machine-interpretable Thing Description (TD) and expose these capabilities through the WoT Interface , that is, network interactions modeled as Properties (for reading and writing values), Action s (to execute remote procedures with or without return values) and Event s (for signaling notifications).
The main Web of Things (WoT) concepts are described in the Web of Things (WoT) Architecture 1.1 specification.
Scripting is an optional building block in WoT and it is typically used in gateways or browsers that are able to run a WoT Runtime and script management , providing a convenient way to extend WoT support to new types of endpoints and implement WoT applications such as TD Directory .
This specification describes an application programming interface (API) representing the WoT Interface that allows scripts to discover, operate Thing s and to expose locally defined Thing s characterized by WoT Interactions specified by a script.
The APIs defined in this document deliberately follow the Web of Things (WoT) Thing Description 1.1 specification closely. It is possible to implement more abstract APIs on top of them, or implementing directly the WoT network facing interface (i.e. the WoT Interface ).
This specification is implemented at least by the Eclipse Thingweb project also known as node-wot , which is considered the reference open source implementation at the moment. Check its source code , including examples .
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
standards
and
drafts
index
at
https://www.w3.org/TR/.
Implementers need to be aware that this specification is considered unstable. Vendors interested in implementing this specification before it eventually reaches the Candidate Recommendation phase should subscribe to the repository and take part in the discussions.
Please contribute to this draft using the GitHub Issues page of the WoT Scripting API repository. For feedback on security and privacy considerations, please use the WoT Security and Privacy Issues.
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
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 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 03 November 2023 W3C Process Document .
WoT provides layered interoperability based on how Thing s are used: "consumed" and "exposed", as defined in the Web of Things (WoT) Architecture 1.1 terminology.
By consuming a TD , a client Thing creates a local runtime resource model that allows accessing the Properties , Actions and Events exposed by the server Thing on a remote device.
Typically scripts are meant to be used on bridges or gateways that expose and control simpler devices as WoT Thing s and have means to handle (e.g. install, uninstall, update etc.) and run scripts.
This specification does not make assumptions on how the WoT Runtime handles and runs scripts, including single or multiple tenancy, script deployment and lifecycle management. The API already supports the generic mechanisms that make it possible to implement script management, for instance by exposing a manager Thing whose Actions (action handlers) implement script lifecycle management operations.
This section is non-normative.
The business use cases listed in the [ wot-usecases ] document may be implemented using this API, based on the scripting use case scenarios described here.
After evaluating dynamic modifications to Thing Descriptions through several versions of this API, the editors concluded that the simplest way to represent these use cases is to take an existing TD , modify it (i.e. add or remove definitions) and then create a new Thing based on the modified TD .
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY , MUST , and SHOULD 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.
This specification used to be a Working Draft which was expected to become a W3C Recommendation. However, it is now a WG Note which contains informative statements only. Therefore we need to consider how to deal with the description within this Conformance section.
This specification describes the conformance criteria for the following classes of user agent ( UA ).
Due
to
requirements
of
small
embedded
implementations,
splitting
WoT
client
and
server
interfaces
was
needed.
Then,
discovery
is
a
distributed
application,
but
typical
scenarios
have
been
covered
by
a
generic
discovery
API
in
this
specification.
This
resulted
in
using
3
conformance
classes
for
a
UA
that
implements
this
API,
one
for
client,
one
for
server,
and
one
for
discovery.
An
application
that
uses
this
API
can
introspect
for
the
presence
of
the
consume()
,
produce()
and
discover()
methods
on
the
WoT
API
object
in
order
to
determine
which
conformance
class
the
UA
implements.
Implementations
of
this
conformance
class
MUST
implement
the
interface
and
the
ConsumedThing
consume()
method
on
the
WoT
API
object
.
Implementations
of
this
conformance
class
MUST
implement
interface
and
the
ExposedThing
produce()
method
on
the
WoT
API
object
.
Implementations
of
this
conformance
class
MUST
implement
the
interface,
the
ThingDiscoveryProcess
discover()
method,
the
exploreDirectory()
method,
and
the
requestThingDescription()
method
on
the
WoT
API
object
.
These conformance classes MAY be implemented in a single UA .
This specification can be used for implementing the WoT Scripting API in multiple programming languages. The interface definitions are specified in [ WEBIDL ].
The UA may be implemented in the browser, or in a separate runtime environment, such as Node.js or in small embedded runtimes.
Implementations that use ECMAScript executed in a browser to implement the APIs defined in this document MUST implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [ WEBIDL ].
Implementations that use TypeScript or ECMAScript in a runtime to implement the APIs defined in this document MUST implement them in a manner consistent with the TypeScript Bindings defined in the TypeScript specification [ TYPESCRIPT ].
The generic WoT terminology is defined in [ wot-architecture11 ]: Thing , Thing Description (in short TD ), Partial TD , Web of Things (in short WoT ), WoT Interface , Protocol Bindings , WoT Runtime , Consuming a Thing Description , TD Directory , Property , Action , Event , DataSchema , Form , SecurityScheme , NoSecurityScheme etc.
WoT Interaction is a synonym for Interaction Affordance . An Interaction Affordance (or shortly, affordance) is the term used in [ wot-thing-description11 ] when referring to Thing capabilities, as explained in TD issue 282 . However, this term is not well understood outside the TD semantic context. Hence for the sake of readability, this document will use the previous term WoT interaction or, simply, interaction instead.
WoT network interface synonym for WoT Interface .
JSON Schema is defined in these specifications .
Promise
,
Error
,
JSON
,
JSON.stringify
,
JSON.parse
,
internal
method
and
internal
slot
are
defined
in
[
ECMASCRIPT
].
WebIDL
typedef
object
ThingDescription
;
Represents a Thing Description ( TD ) as defined in [ wot-thing-description11 ]. It is expected to be a parsed JSON object that is validated using JSON Schema validation .
Requesting a TD given a URL should be done with the requestThingDescription() method. Alternatively, external methods, such as the Fetch API or an HTTP client library, can be used.
try {
);
WoT.consume(td);
+ thing.getThingDescription().title);
const td = await requestThingDescription('https://tds.mythings.biz/sensor11');
const thing = await WoT.consume(td);
console.log("Thing name: " + thing.getThingDescription().title);
} catch (err) {
, err.message);
console.log("Requesting TD failed", err.message);
}
Note that the Web of Things (WoT) Thing Description 1.1 specification allows using a shortened Thing Description by the means of defaults and requiring clients to expand them with default values specified in the Web of Things (WoT) Thing Description 1.1 specification for the properties that are not explicitly defined in a given TD .
The
[
wot-thing-description11
]
specification
defines
how
a
TD
should
be
validated.
Therefore,
this
API
expects
the
ThingDescription
objects
be
validated
before
used
as
parameters.
This
specification
defines
a
basic
TD
validation
as
follows.
TypeError
"
and
stop.
Additional steps may be added to fill the default values of mandatory fields.
Defines the WoT API object as a singleton and contains the API methods, grouped by conformance classes.
WebIDL[SecureContext, Exposed=(Window,Worker)]
namespace WOT
{
// methods defined in UA conformance classes
};
WebIDLpartial namespace WOT
{
Promise<ConsumedThing
> consume
(ThingDescription
td);
};
Promise
that
resolves
with
a
ConsumedThing
object
that
represents
a
client
interface
to
operate
with
the
Thing
.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
ConsumedThing
object
constructed
from
td
.
Implementations encapsulate the complexity of how to use the Protocol Bindings for implementing WoT interactions . In the future elements of that could be standardized.
WebIDLtypedef object ExposedThingInit
;
partial namespace WOT
{
Promise<ExposedThing
> produce
(ExposedThingInit
init);
};
Promise
that
resolves
with
an
ExposedThing
object
that
extends
ConsumedThing
with
a
server
interface,
i.e.
the
ability
to
define
request
handlers.
The
init
object
is
an
instance
of
the
ExposedThingInit
type.
Specifically,
an
ExposedThingInit
value
is
a
dictionary
used
for
the
initialization
of
an
ExposedThing
and
it
represents
a
Partial
TD
as
described
in
the
[
wot-architecture11
].
As
such,
it
has
the
same
structure
of
a
Thing
Description
but
it
may
omit
some
information.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
ExposedThing
object
constructed
with
init
.
SyntaxError
and
stop.
"securityDefinitions"
],
make
a
request
to
the
underlying
platform
to
check
if
it
is
supported
by
at
least
one
Protocol
Binding
.
If
not,
then
remove
scheme
from
td
.
"security"
]
does
not
exist
in
td
.[
"securityDefinitions"
],
then
remove
security
from
td
.
authority
it
is
not
recognized
by
the
runtime
as
valid,
remove
href
from
form
.
The editors find this step vague. It will be improved or removed in the next iteration.
title
generate
a
runtime
unique
name
and
assign
to
title
.
@context
assign
the
latest
supported
Thing
Description
context
URI.
instance
assign
the
string
1.0.0
.
forms
generate
a
list
of
Forms
using
the
available
Protocol
Bindings
and
content
types
encoders.
Then
assign
the
obtained
list
to
forms
.
security
assign
the
label
of
the
first
supported
SecurityScheme
in
securityDefinitions
field.
If
no
SecurityScheme
is
found
generate
a
NoSecurityScheme
called
nosec
and
assign
the
string
nosec
to
security
.
The
discussion
about
how
to
properly
generate
a
value
for
security
is
still
open.
See
issue
#299
href
define
formStub
as
the
partial
Form
that
does
not
have
href
.
Generate
a
valid
url
using
the
first
Protocol
Binding
that
satisfy
the
requirements
of
formStub
.
Assign
url
to
href
.
If
not
Protocol
Binding
can
be
found
remove
formStub
from
td
.
title
,
@context
,
instance
,
forms
,
security
,
and
href
.
required
execute
the
following
steps:
Array
then
remove
all
its
elements
equal
to
the
elements
in
optional
string
then
if
value
is
equal
to
one
of
the
elements
in
optional
remove
key
from
exposedThingInitSchema
The validating an object with JSON Schema steps are still under discussion. Currently this specification reference to the validation process of JSONSchema. Please follow this document when validating init with exposedThingInitSchema . Notice that the working group is evaluating an alternative formal approach.
WebIDLpartial namespace WOT
{
Promise<ThingDiscoveryProcess
> discover
(optional ThingFilter
filter = {});
};
ThingDescription
objects
for
Thing
Description
s
that
match
an
optional
filter
argument
of
type
ThingFilter
.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
NotSupportedError
and
stop.
ThingDiscoveryProcess
object.
[[filter]]
to
filter
.
[[url]]
to
undefined
.
undefined
or
null
,
reject
promise
with
NotSupportedError
and
stop.
OperationError
and
stop.
Note
that
the
details
of
the
discovery
process
depend
on
the
underlying
implementation
which
needs
to
be
preconfigured
in
order
to
use,
for
example,
the
appropriate
Introduction
methods
as
defined
in
the
Web
of
Things
(WoT)
Discovery
specification.
Since
the
discover()
method
outputs
Thing
Description
s
and
not
URLs,
it
is
expected
to
cover
both
the
Introduction
and
the
Exploration
phase.
WebIDLpartial namespace WOT
{
,
Promise<ThingDiscoveryProcess
> exploreDirectory
(USVString url,
optional ThingFilter
filter = {});
};
ThingDescription
objects
for
Thing
Description
s
that
match
an
optional
filter
argument
of
type
ThingFilter
.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
NotSupportedError
and
stop.
ThingDiscoveryProcess
object.
[[url]]
to
url
.
[[filter]]
to
filter
.
This is a placeholder for more details in the discovery algorithm. Implementations should follow the procedures described in the [ wot-discovery ] and [wot-binding-templates] specifications. Some normative steps are indicated below.
NotSupportedError
and
terminate
these
steps.
undefined
or
null
,
reject
promise
with
NotSupportedError
and
stop.
From
this
point
on,
errors
are
recorded
only
on
error
,
but
don't
affect
promise
any
longer.
WebIDLpartial namespace WOT
{
Promise<ThingDescription
> requestThingDescription
(USVString url);
};
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
NotSupportedError
and
stop.
NotFoundError
and
stop.
As
specified
in
the
Web
of
Things
(WoT)
Thing
Description
1.1
specification,
WoT
interactions
extend
DataSchema
and
include
a
number
of
possible
Form
s,
out
of
which
one
is
selected
for
the
interaction.
The
Form
contains
a
contentType
to
describe
the
data.
For
certain
content
types,
a
DataSchema
is
defined,
based
on
JSON
Schema
,
making
possible
to
represent
these
contents
as
JavaScript
types
and
eventually
set
range
constraints
on
the
data.
WebIDLtypedef any DataSchemaValue
;
typedef
(
ReadableStream
or
DataSchemaValue
)
InteractionInput
;
Belongs to the WoT Consumer conformance class and represents the WoT Interaction data provided by application scripts to the UA.
DataSchemaValue
is
an
ECMAScript
value
that
is
accepted
for
DataSchema
defined
in
[
wot-thing-description11
].
The
possible
values
MUST
be
of
type
null
,
boolean
,
number
,
string
,
array
,
or
object
.
ReadableStream
is
meant
to
be
used
for
WoT
Interactions
that
don't
have
a
DataSchema
in
the
Thing
Description
,
only
a
Form
's
contentType
that
can
be
represented
by
a
stream.
In
practice,
any
ECMAScript
value
may
be
used
for
WoT
Interactions
that
have
a
DataSchema
defined
in
the
Thing
Description
,
or
which
can
be
mapped
by
implementations
to
the
Form
's
contentType
defined
in
the
Thing
Description
.
The algorithms in this document specify how exactly input data is used in WoT Interactions .
Belongs
to
the
WoT
Consumer
conformance
class.
An
InteractionOutput
object
is
always
created
by
the
implementations
and
exposes
the
data
returned
from
WoT
Interactions
to
application
scripts.
This
interface
exposes
a
convenience
function
which
should
cover
the
vast
majority
of
IoT
use
cases:
the
value()
function.
Its
implementation
will
inspect
the
data,
parse
it
if
adheres
to
a
DataSchema
,
or
otherwise
fail
early,
leaving
the
underlying
stream
undisturbed
so
that
application
scripts
could
attempt
reading
the
stream
themselves,
or
handling
the
data
as
ArrayBuffer
.
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface InteractionOutput
{
readonly attribute
readonly attribute
readonly attribute ReadableStream? data
;
readonly attribute boolean dataUsed
;
readonly attribute Form? form
;
readonly attribute DataSchema? schema
;
Promise<ArrayBuffer> arrayBuffer
();
Promise<DataSchemaValue
> value
();
};
The
data
property
represents
the
raw
payload
in
WoT
Interactions
as
a
ReadableStream
,
initially
null
.
The
dataUsed
property
tells
whether
the
data
stream
has
been
disturbed
.
Initially
false
.
The
form
attribute
represents
the
Form
selected
from
the
Thing
Description
for
this
WoT
Interaction
,
initially
null
.
The
schema
attribute
represents
the
DataSchema
(defined
in
[
wot-thing-description11
])
of
the
payload
as
a
JSON
object,
initially
null
.
The
[[value]]
internal
slot
represents
the
parsed
value
of
the
WoT
Interaction
,
initially
undefined
(note
that
null
is
a
valid
value).
contentType
of
the
interaction
Form
.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
undefined
,
resolve
promise
with
that
value
and
stop.
ReadableStream
or
if
dataUsed
is
true
,
or
if
form
is
not
an
object
or
if
schema
is
null
or
undefined
,
then
reject
promise
with
NotReadableError
and
stop.
application/json
and
if
a
mapping
is
not
available
in
the
Protocol
Bindings
from
form
.
contentType
to
[
JSON-SCHEMA
],
reject
promise
with
NotSupportedError
and
stop.
true
.
application/json
and
if
a
mapping
is
available
in
the
Protocol
Bindings
from
form
.
contentType
to
[
JSON-SCHEMA
],
transform
bytes
with
that
mapping.
Promise
promise
and
execute
the
next
steps
in
parallel
.
ReadableStream
or
if
dataUsed
is
true
,
reject
promise
with
NotReadableError
and
stop.
true
.
ArrayBuffer
whose
contents
are
bytes
.
If
that
throws,
reject
promise
with
that
exception
and
stop.
null
or
undefined
,
return
undefined
.
TypeError
and
stop.
TypeError
and
stop.
TypeError
and
stop.
"null"
and
if
payload
is
not
null
,
throw
TypeError
and
stop,
otherwise
return
null
.
"boolean"
and
payload
is
a
falsy
value
or
its
byte
length
is
0,
return
false
,
otherwise
return
true
.
"integer"
or
"number"
,
TypeError
and
stop.
RangeError
and
stop.
"string"
,
return
payload
.
"array"
,
run
these
sub-steps:
TypeError
and
stop.
RangeError
and
stop.
"object"
,
run
these
sub-steps:
object
,
throw
TypeError
and
stop.
SyntaxError
and
stop.
ConsumedThing
object
thing
,
in
order
to
create
interaction
request
given
a
source
,
form
and
schema
,
run
these
steps:
InteractionOutput
object.
null
and
set
idata
.
[[value]]
to
undefined
.
ReadableStream
object,
let
idata
.
data
be
source
,
return
idata
and
stop.
null
,
run
these
sub-steps:
"null"
and
source
is
not
"null"
,
throw
TypeError
and
stop.
"boolean"
and
source
is
a
falsy
value,
set
idata
.
[[value]]
to
false
,
otherwise
set
it
to
true
.
"integer"
or
"number"
and
source
is
not
a
number,
or
if
form
.
minimum
is
defined
and
source
is
smaller,
or
if
form
.
maximum
is
defined
and
source
is
bigger,
throw
RangeError
and
stop.
"string"
and
source
is
not
a
string,
let
idata
.
[[value]]
be
the
result
of
running
serialize
JSON
to
bytes
given
source
.
If
that
is
failure,
throw
SyntaxError
and
stop.
"array"
,
run
these
sub-steps:
TypeError
and
stop.
RangeError
and
stop.
[[value]]
to
source
.
"object"
,
run
these
sub-steps:
TypeError
and
stop.
TypeError
and
stop.
SyntaxError
and
stop.
[[value]]
to
source
.
ReadableStream
created
from
idata
.
[[value]]
internal
slot
as
its
underlying
source
.
ConsumedThing
object
thing
,
in
order
to
parse
interaction
response
given
response
,
form
and
schema
,
run
these
steps:
InteractionOutput
object.
ReadableStream
with
the
payload
data
of
response
as
its
underlying
source
.
false
.
Belongs
to
the
WoT
Consumer
conformance
class.
An
ActionInteractionOutput
object
is
always
created
by
a
consumer
implementation
and
exposes
functionality
to
interact
with
long
running
(asynchronous)
actions.
Note:
The
output
of
a
synchronous
action
MAY
be
limited
to
the
functionality
of
a
regular
InteractionOutput
object,
e.g.,
invoking
the
cancel()
method
might
not
have
an
effect.
This interface exposes functions which will allow cancelling asynchronous actions and query the status of a long running action.
WebIDL/**
* Note: retrieving the result of an action via the implicit InteractionOutput interface
* will only work after the action has been completed
*/
[SecureContext, Exposed=(Window,Worker)]
interface ActionInteractionOutput
: InteractionOutput
{
Promise<InteractionOutput
> query
(
optional InteractionInput
params = {},
optional InteractionOptions
options = {});
Promise<undefined> cancel
(
optional InteractionInput
params = {},
optional InteractionOptions
options = {});
};
Promise
promise
and
execute
the
next
steps
in
parallel
.
NotSupportedError
and
stop.
OperationError
and
stop.
Promise
promise
and
execute
the
next
steps
in
parallel
.
NotSupportedError
and
stop.
OperationError
and
stop.
InteractionInput
,
InteractionOutput
and
ActionInteractionOutput
As
illustrated
in
the
next
pictures,
the
InteractionOutput
interface
is
used
every
time
implementations
provide
data
to
scripts,
while
InteractionInput
is
used
when
the
scripts
pass
data
to
the
implementation.
When
a
ConsumedThing
reads
data,
it
receives
it
from
the
implementation
as
an
InteractionOutput
object.
An
ExposedThing
read
handler
provides
the
read
data
to
the
implementation
as
InteractionInput
.
When
a
ConsumedThing
writes
data,
it
provides
it
to
the
implementation
as
InteractionInput
.
An
ExposedThing
write
handler
receives
data
from
to
implementation
as
an
InteractionOutput
object.
When
a
ConsumedThing
invokes
an
Action
,
it
provides
the
parameters
as
InteractionInput
and
receives
the
output
of
the
Action
as
an
object.
InteractionOutput
ActionInteractionOutput
An
ExposedThing
action
handler
receives
arguments
from
the
implementation
as
an
InteractionOutput
object
and
provides
Action
output
as
InteractionInput
to
the
implementation.
The algorithms in this API define the errors to be reported to application scripts.
The errors reported to the other communication end are mapped and encapsulated by the Protocol Bindings .
This topic is still being discussed in Issue #200 . A standardized error mapping would be needed in order to ensure consistency in mapping script errors to protocol errors and vice versa. In particular, when algorithms say "error received from the Protocol Bindings ", that will be factored out as an explicit error mapping algorithm. Currently, that is encapsulated by implementations.
Represents a client API to operate a Thing . Belongs to the WoT Consumer conformance class.
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface ConsumedThing
{
,
optional
(
optional
,
optional
,
optional
Promise<InteractionOutput
> readProperty
(DOMString propertyName,
optional InteractionOptions
options = {});
Promise<PropertyReadMap
> readAllProperties
(
optional InteractionOptions
options = {});
Promise<PropertyReadMap
> readMultipleProperties
( sequence<DOMString> propertyNames,
optional InteractionOptions
options = {});
Promise<undefined> writeProperty
(DOMString propertyName, InteractionInput
value,
optional InteractionOptions
options = {});
Promise<undefined> writeMultipleProperties
(
PropertyWriteMap
valueMap,
optional
optional InteractionOptions
options = {});
/*Promise<undefined> writeAllProperties(
PropertyWriteMap valueMap,
optional InteractionOptions options = {});*/
,
optional = {},
optional
Promise<ActionInteractionOutput
> invokeAction
(DOMString actionName,
optional InteractionInput
params = {},
optional InteractionOptions
options = {});
Promise<Subscription
> observeProperty
(DOMString name,
InteractionListener
listener,
optional ErrorListener
onerror,
optional
optional InteractionOptions
options = {});
Promise<Subscription
> subscribeEvent
(DOMString name,
InteractionListener
listener,
optional ErrorListener
onerror,
optional
optional InteractionOptions
options = {});
ThingDescription
getThingDescription
();
};
dictionary
dictionary InteractionOptions
{
unsigned long formIndex
; object uriVariables
; any data
;
};
[]
[SecureContext, Exposed=(Window,Worker)]
interface Subscription
{
readonly attribute
readonly attribute boolean active
;
Promise<undefined> stop
(optional InteractionOptions
options = {});
};
[]
[SecureContext, Exposed=(Window,Worker)]
interface PropertyReadMap
{
readonly
readonly maplike<DOMString, InteractionOutput
>;
};
[]
[SecureContext, Exposed=(Window,Worker)]
interface PropertyWriteMap
{
readonly
readonly maplike<DOMString, InteractionInput
>;
};
callback
callback InteractionListener
= undefined(InteractionOutput
data);
callback
ErrorListener
=
undefined
(
Error
error
);
The
writeAllProperties()
method
is
still
under
discussion.
Meanwhile,
use
the
writeMultipleProperties()
method
instead.
ConsumedThing
A
ConsumedThing
object
has
the
following
internal
slots
:
Internal Slot | Initial value | Description ( non-normative ) |
---|---|---|
[[td]] |
null
|
The
Thing
Description
of
the
ConsumedThing
.
|
[[activeSubscriptions]] |
{}
|
An
ordered
map
keyed
on
a
string
name
representing
the
Event
and
value
is
a
Subscription
object.
|
[[activeObservations]] |
{}
|
An
ordered
map
keyed
on
a
string
name
representing
a
Property
and
value
is
a
Subscription
object.
|
After
requesting
a
Thing
Description
as
a
JSON
object,
one
can
create
a
ConsumedThing
object.
ConsumedThing
with
the
ThingDescription
td
,
run
the
following
steps:
SyntaxError
and
stop.
ConsumedThing
object.
[[td]]
of
thing
to
td
.
Returns
the
[[td]]
of
the
ConsumedThing
object
that
represents
the
Thing
Description
of
the
ConsumedThing
.
Applications
may
consult
the
Thing
metadata
stored
in
[[td]]
in
order
to
introspect
its
capabilities
before
interacting
with
it.
Promise
that
resolves
with
a
Property
value
represented
as
an
InteractionOutput
object
or
rejects
on
error.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[td]]
.
properties
.
propertyName
.
undefined
,
reject
promise
with
a
NotFoundError
and
stop.
readproperty
,
selected
by
the
implementation.
SyntaxError
and
stop.
SyntaxError
and
stop.
Promise
that
resolves
with
a
PropertyReadMap
object
that
maps
keys
from
propertyNames
to
values
returned
by
this
algorithm.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[td]]
.
forms
array,
otherwise
let
form
be
the
Form
in
[[td]]
.
forms
array
whose
op
is
readmultipleproperties
,
as
selected
by
the
implementation.
SyntaxError
and
stop.
null
.
NotSupportedError
and
stop.
[[td]]
.
properties
[
key
].
Promise
that
resolves
with
a
PropertyReadMap
object
that
maps
keys
from
Property
names
to
values
returned
by
this
algorithm.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[interaction]]
.
forms
.
undefined
,
reject
promise
with
a
SyntaxError
and
stop.
undefined
and
is
less
than
forms
.
length
,
set
subscription
.
[[form]]
to
forms
.[
formIndex
].
[[form]]
to
a
Form
in
forms
whose
op
is
"readallproperties"
,
as
selected
by
the
implementation.
[[form]]
is
failure,
reject
promise
with
a
SyntaxError
and
stop.
NotSupportedError
and
stop.
[[td]]
.
properties
[
key
].
Promise
that
resolves
on
success
and
rejects
on
failure.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[td]]
.
properties
[
propertyName
].
undefined
,
reject
promise
with
a
NotFoundError
and
stop.
undefined
,
let
form
be
the
Form
associated
with
formIndex
in
the
interaction
.
forms
array,
otherwise
let
form
be
a
Form
in
interaction
.
forms
whose
op
is
writeproperty
,
as
selected
by
the
implementation.
SyntaxError
and
stop.
promise
with
that
exception
and
stop.
As discussed in Issue #193 , the design decision is that write interactions only return success or error, not the written value (optionally). TD s should capture the schema of the Property values, including precision and alternative formats. When a return value is expected from the interaction, an Action should be used instead of a Property .
Promise
that
resolves
on
success
and
rejects
on
failure.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[td]]
.
forms
array,
otherwise
let
form
be
a
Form
in
[[td]]
.
forms
array
whose
op
is
writemultipleproperties
,
as
selected
by
the
implementation.
SyntaxError
and
stop.
[[td]]
.
properties
[
name
].
null
or
undefined
or
is
not
writeable
reject
promise
with
NotSupportedError
and
stop.
null
.
[[td]]
.
properties
[
name
].
promise
with
that
exception
and
stop.
NotSupportedError
and
stop.
Promise
that
resolves
on
success
and
rejects
on
failure.
This
algorithm
allows
for
only
one
active
Subscription
per
Property
.
If
a
new
Subscription
is
made
while
an
existing
Subscription
is
active
the
runtime
will
throw
an
NotAllowedError
.
ConsumedThing
object.
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
Function
,
reject
promise
with
a
TypeError
and
stop.
null
and
is
not
a
Function
,
reject
promise
with
a
TypeError
and
stop.
[[activeObservations]]
[
propertyName
]
[=map/exists],
reject
promise
with
a
NotAllowedError
and
stop.
Subscription
object
with
its
internal
slots
set
as
follows:
[[type]]
be
"property"
.
[[name]]
be
propertyName
.
[[interaction]]
be
[[td]]
.
properties
[
propertyName
].
[[thing]]
be
thing
.
[[interaction]]
.
forms
.
undefined
,
reject
promise
with
a
SyntaxError
and
stop.
undefined
and
is
less
than
forms
.
length
,
set
subscription
.
[[form]]
to
forms
.[
formIndex
].
[[form]]
to
a
Form
in
forms
whose
op
is
"observeproperty"
,
as
selected
by
the
implementation.
[[form]]
is
failure,
reject
promise
with
a
SyntaxError
and
stop.
[[interaction]]
is
undefined
,
reject
promise
with
a
NotFoundError
and
stop.
[[activeObservations]]
[|propertyName]
to
subscription
and
resolve
promise
.
[[form]]
and
subscription
.
[[interaction]]
.
If
that
throws,
reject
promise
with
that
exception
and
stop.
false
and
suppress
further
notifications.
NetworkError
and
set
its
message
to
reflect
the
underlying
error
condition.
Function
,
invoke
it
given
error
.
Promise
that
resolves
with
the
result
of
the
Action
represented
as
an
InteractionOutput
object,
or
rejects
with
an
error.
The
method
MUST
run
the
following
steps:
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[td]]
.
actions
[
actionName
].
object
,
reject
promise
with
a
NotFoundError
and
stop.
[[interaction]]
.
forms
.
undefined
,
reject
promise
with
a
SyntaxError
and
stop.
undefined
and
is
less
than
forms
.
length
,
set
subscription
.
[[form]]
to
forms
.[
formIndex
].
[[form]]
to
a
Form
in
forms
whose
op
is
"invokeaction"
,
as
selected
by
the
implementation.
[[form]]
is
failure,
reject
promise
with
a
SyntaxError
and
stop.
promise
with
that
exception
and
stop.
Promise
to
signal
success
or
failure.
This
algorithm
allows
for
only
one
active
Subscription
per
Event
.
If
a
new
Subscription
is
made
while
an
existing
Subscription
is
active
the
runtime
will
throw
an
NotAllowedError
.
ConsumedThing
object.
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
Function
,
reject
promise
with
a
TypeError
and
stop.
null
and
is
not
a
Function
,
reject
promise
with
a
TypeError
and
stop.
[[activeSubscriptions]]
[
eventName
]
does
not
exist
,
reject
promise
with
a
NotAllowedError
and
stop.
Subscription
object
with
its
internal
slots
set
as
follows:
[[type]]
be
"event"
.
[[name]]
be
eventName
.
[[interaction]]
be
thing
.
[[td]]
.
events
[
eventName
].
[[interaction]]
is
undefined
,
reject
promise
with
a
NotFoundError
and
stop.
[[thing]]
be
thing
.
[[form]]
be
thing
.
[[interaction]]
.
forms
[
formIndex
].
[[form]]
be
an
implementation-defined
Form
from
the
subscription
.
[[interaction]]
.
forms
array
whose
op
is
"subscribeevent"
.
[[form]]
does
not
exist
,
reject
promise
with
a
SyntaxError
and
stop.
[[form]]
,
optional
URI
templates
given
in
options
.
uriVariables
and
optional
subscription
data
given
in
options
.
data
.
[[activeSubscriptions]]
[
eventName
]
to
subscription
.
[[form]]
and
subscription
.
[[interaction]]
.
false
and
suppress
further
notifications.
NetworkError
and
set
its
message
to
reflect
the
underlying
error
condition.
Function
,
invoke
it
given
error
.
Holds the interaction options that need to be exposed for application scripts according to the Thing Description .
The
formIndex
property,
if
defined,
represents
an
application
hint
for
which
Form
definition,
identified
by
this
index,
of
the
TD
to
use
for
the
given
WoT
interaction.
Implementations
SHOULD
use
the
Form
with
this
index
for
making
the
interaction,
but
MAY
override
this
value
if
the
index
is
not
found
or
not
valid.
If
not
defined,
implementations
SHOULD
attempt
to
use
the
Form
definitions
in
order
of
appearance
as
listed
in
the
TD
for
the
given
Wot
Interaction.
The
uriVariables
property
if
defined,
represents
the
URI
template
variables
to
be
used
with
the
WoT
Interaction
that
are
represented
as
parsed
JSON
objects
defined
in
[
wot-thing-description11
].
The support for URI variables comes from the need, exposed by the Web of Things (WoT) Thing Description 1.1 specification, to be able to describe existing RESTful endpoints that use them. However, it should be possible to write a Thing Description that would use Action s for representing this kind of interactions and model the URI variables as action parameters. In that case, implementations can serialize the parameters as URI variables, and therefore, the options parameter could be dismissed.
The
data
property
if
defined,
represents
additional
opaque
data
that
needs
to
be
passed
to
the
interaction.
Represents
a
map
of
Property
names
to
an
InteractionOutput
object
that
represents
the
value
the
Property
can
take.
It
is
used
as
a
property
bag
for
interactions
that
involve
multiple
Properties
at
once.
Represents
a
map
of
Property
names
to
an
InteractionInput
that
represents
the
value
the
Property
can
take.
It
is
used
as
a
property
bag
for
interactions
that
involve
multiple
Properties
at
once.
User
provided
callback
that
is
given
an
argument
of
type
InteractionOutput
and
is
used
for
observing
Property
changes
and
handling
Event
notifications.
Since
subscribing
to
Events
are
WoT
interactions
and
might
take
options
or
even
data,
they
are
not
modelled
with
software
events.
User
provided
callback
that
is
given
an
argument
of
type
Error
and
is
used
for
conveying
critical
and
non-critical
errors
from
the
Protocol
Bindings
to
applications.
Represents a subscription to Property change and Event interactions.
The
active
boolean
property
denotes
if
the
subscription
is
active,
i.e.
it
is
not
stopped
because
of
an
error
or
because
of
invocation
of
the
stop()
method.
Subscription
Subscription
object
has
the
following
internal
slots
:
Internal Slot | Initial value | Description ( non-normative ) |
---|---|---|
[[type]] |
null
|
Indicates
what
WoT
Interaction
the
Subscription
refers
to.
The
value
can
be
either
"property"
or
"event"
or
null
.
|
[[name]] |
null
|
The Property or Event name. |
[[interaction]] |
null
|
The Thing Description fragment that describes the WoT interaction . |
[[form]] |
null
|
The Form associated with the subscription. |
[[thing]] |
null
|
The
ConsumedThing
associated
with
the
subscription.
|
Stops
delivering
notifications
for
the
subscription.
It
takes
an
optional
parameter
options
and
returns
a
.
When
invoked,
the
method
MUST
execute
the
following
steps:
Promise
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[interaction]]
's
forms
array.
[[form]]
.
SyntaxError
and
stop.
[[type]]
is
"property"
,
make
a
request
to
the
underlying
platform
via
the
Protocol
Bindings
to
stop
observing
the
Property
identified
by
[[name]]
with
unsubscribeForm
and
optional
URI
templates
given
in
options
'
uriVariables
.
[[type]]
is
"event"
,
make
a
request
to
the
underlying
platform
via
the
Protocol
Bindings
to
unsubscribe
from
the
Event
identified
by
[[name]]
with
unsubscribeForm
,
with
optional
URI
templates
given
in
options
'
uriVariables
and
optional
unsubscribe
data
given
in
options
.
data
.
false
.
[[type]]
is
"event"
,
remove
[[name]]
from
[[thing]]
.
[[activeSubscriptions]]
.
[[type]]
is
"property"
,
remove
[[name]]
from
[[thing]]
.
[[activeObservations]]
.
This
algorithm
is
under
development
and
is
non-normative
.
Implementations
MAY
choose
another
algorithm
to
find
a
matching
unsubscribe
Form
to
a
given
subscribe
Form
.
Subscription
object,
run
the
following
steps:
[[interaction]]
.
forms
,
0
.
"unobserveproperty"
if
[[type]]
is
"property"
or
if
form
.
op
is
"unsubscribeevent"
if
[[type]]
is
"event"
,
null
and
terminate
these
steps.
The
next
example
illustrates
how
to
fetch
a
TD
by
URL,
create
a
ConsumedThing
,
read
metadata
(title),
read
property
value,
subscribe
to
property
change,
subscribe
to
a
WoT
event,
unsubscribe.
try {
);
td = res.json();
ConsumedThing(td);
);
let res = await fetch("https://tds.mythings.org/sensor11");
let td = res.json();
let thing = new ConsumedThing(td);
console.log("Thing " + thing.getThingDescription().title + " consumed.");
} catch (e) {
+ e.message);
console.log("TD fetch error: " + e.message);
};
try {
// subscribe to property change for "temperature"
(data) => {
await thing.observeProperty("temperature", async (data) => {
try {
data.value());
console.log("Temperature changed to: " + await data.value());
} catch (error) {
);
.error(error);
console.error("Cannot read the observed property temperature");
console.error(error);
}
});
// subscribe to the "ready" event defined in the TD
(eventData) => {
await thing.subscribeEvent("ready", async (eventData) => {
try {
eventData.value());
console.log("Ready; index: " + await eventData.value());
// run the "startMeasurement" action defined by TD
});
);
await thing.invokeAction("startMeasurement", { units: "Celsius" });
console.log("Measurement started.");
} catch (error) {
);
.error(error)
console.error("Cannot read the ready event or startMeasurement failed");
console.error(error)
}
});
} catch (e) {
);
console.log("Error starting measurement.");
}
() => {
setTimeout(async () => {
try {
)
temperatureData.value();
+ temperature);
const temperatureData = await thing.readProperty("temperature")
const temperature = await temperatureData.value();
console.log("Temperature: " + temperature);
);
);
await thing.unsubscribe("ready");
console.log("Unsubscribed from the 'ready' event.");
} catch (error) {
);
console.log("Error in the cleanup function");
}
},
10000
);
The
following
shows
an
advance
usage
of
InteractionOutput
to
read
a
property
without
a
DataSchema
.
/*
* takePicture affordance form:
* "form": {
* "op": "invokeaction",
* "href" : "http://camera.example.com:5683/takePicture",
* "response": {
* "contentType": "image/jpeg",
* "contentCoding": "gzip"
* }
*}
* See https://www.w3.org/TR/wot-thing-description/#example-23
*/
let response;
let image;
try {
response = );
image =
response = await thing.invokeAction("takePicture");
image = await response.value() // throws NotReadableError --> schema not defined
} catch(ex) {
image = response.arrayBuffer();
image = await response.arrayBuffer();
// image: ArrayBuffer [0x1 0x2 0x3 0x5 0x15 0x23 ...]
}
Finally,
the
next
two
examples
shows
the
usage
of
a
ReadableStream
from
an
InteractionOutput
.
/*{
"video": {
"description" : "the video stream of this camera",
"forms": [
{
"op": "readproperty",
"href": "http://camera.example.com/live",
"subprotocol": "hls"
"contentType": "video/mp4"
}
]
}}*/
)
reader = video.data.getReader()
reader.read().then({
const video = await thing.readProperty("video")
const reader = video.data.getReader()
reader.read().then(function processVideo({ done, value }) {
if (done) {
);
console.log("live video stoped");
return;
}
decoded = decode(value)
UI.show(decoded)
const decoded = decode(value)
UI.show(decoded)
// Read some more, and call this function again
reader.read().then(processText);
return reader.read().then(processText);
});
Here consider that the JSON object is too big to be read wholly in the memory. Therefore, we use streaming processing to get the total number of the events recorded by the remote Web Thing.
/*
* "eventHistory":
* {
* "description" : "A long list of the events recorded by this thing",
* "type": "array",
* "forms": [
* {
* "op": "readproperty",
* "href": "http://recorder.example.com/eventHistory",
* }
* ]
* }
*/
// Example of streaming processing: counting json objects
let objectCounter = 0
const parser = new Parser() //User library for json streaming parsing (i.e. https://github.com/uhop/stream-json/wiki/Parser)
parser.on( && ++objectCounter);
parser.on());
parser.on('data', data => data.name === 'startObject' && ++objectCounter);
parser.on('end', () => console.log(`Found ${objectCounter} objects.`));
)
response.data.pipeTo(parser);
const response = await thing.readProperty("eventHistory")
await response.data.pipeTo(parser);
//
Found
N
objects
The
ExposedThing
interface
is
the
server
API
to
operate
the
Thing
that
allows
defining
request
handlers,
Property
,
Action
,
and
Event
interactions.
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface ExposedThing
{
ExposedThing
setPropertyReadHandler
(DOMString name,
PropertyReadHandler
handler);
ExposedThing
setPropertyWriteHandler
(DOMString name,
PropertyWriteHandler
handler);
ExposedThing
setPropertyObserveHandler
(DOMString name,
PropertyReadHandler
handler);
ExposedThing
setPropertyUnobserveHandler
(DOMString name,
PropertyReadHandler
handler);
,
optional
Promise<undefined> emitPropertyChange
(DOMString name,
optional InteractionInput
data);
ExposedThing
setActionHandler
(DOMString name, ActionHandler
action);
ExposedThing
setEventSubscribeHandler
(DOMString name,
EventSubscriptionHandler
handler);
ExposedThing
setEventUnsubscribeHandler
(DOMString name,
EventSubscriptionHandler
handler);
,
optional
Promise<undefined> emitEvent
(DOMString name,
optional InteractionInput
data);
Promise<undefined> expose
();
Promise<undefined> destroy
();
ThingDescription
getThingDescription
();
};
callback (
optional
callback PropertyReadHandler
= Promise<InteractionInput
>(
optional InteractionOptions
options = {});
callback
,
optional
callback PropertyWriteHandler
= Promise<undefined>(
InteractionOutput
value,
optional InteractionOptions
options = {});
callback
,
optional
callback ActionHandler
= Promise<InteractionInput
>(
InteractionOutput
params,
optional InteractionOptions
options = {});
callback (
callback EventSubscriptionHandler
= Promise<undefined>(
optional
InteractionOptions
options
=
{});
An
ExposedThing
object
has
the
following
internal
slots
:
Internal Slot | Initial value | Description ( non-normative ) |
---|---|---|
[[td]] |
null
|
The
Thing
Description
of
the
ExposedThing
.
|
[[readHandlers]] |
{}
|
A
Map
with
property
names
as
keys
and
PropertyReadHandler
s
as
values
|
[[writeHandlers]] |
{}
|
A
Map
with
property
names
as
keys
and
PropertyWriteHandler
s
as
values
|
[[observeHandlers]] |
{}
|
A
Map
with
property
names
as
keys
and
PropertyReadHandler
s
as
values
|
[[unobserveHandlers]] |
{}
|
A
Map
with
property
names
as
keys
and
Function
s
as
values
|
[[actionHandlers]] |
{}
|
A
Map
with
action
names
as
keys
and
ActionHandler
s
as
values
|
[[subscribeHandlers]] |
{}
|
A
Map
with
event
names
as
keys
and
EventSubscriptionHandler
s
as
values
|
[[unsubscribeHandlers]] |
{}
|
A
Map
with
event
names
as
keys
and
EventSubscriptionHandler
s
as
values
|
[[propertyObservers]] |
{}
|
A
Map
with
property
names
as
keys
and
an
Array
of
listeners
as
values
|
[[eventListeners]] |
{}
|
A
Map
with
event
names
as
keys
and
Array
of
listeners
as
values
|
ExposedThing
The
ExposedThing
interface
is
created
from
a
full
or
partial
ThingDescription
object.
Note
that
an
existing
ThingDescription
object
can
be
optionally
modified
(for
instance
by
adding
or
removing
elements
on
its
properties
,
actions
and
events
internal
properties)
and
the
resulting
object
can
used
for
creating
an
ExposedThing
object.
This
is
the
current
way
of
adding
and
removing
Property
,
Action
and
Event
definitions,
as
illustrated
in
the
examples
.
Before
invoking
expose()
,
the
ExposedThing
object
does
not
serve
any
requests.
This
allows
first
creating
ExposedThing
and
then
initialize
its
Properties
and
service
handlers
before
starting
serving
requests.
ExposedThing
with
the
ExposedThingInit
init
,
run
the
following
steps:
SecurityError
and
stop.
ExposedThing
object.
[[td]]
of
thing
to
td
.
Returns
the
[[td]]
of
the
ExposedThing
object
that
represents
the
Thing
Description
of
the
Thing
.
Applications
may
consult
the
Thing
metadata
stored
in
[[td]]
in
order
to
introspect
its
capabilities
before
interacting
with
it.
A
function
that
is
called
when
an
external
request
for
reading
a
Property
is
received
and
defines
what
to
do
with
such
requests.
It
returns
a
and
resolves
with
an
Promise
ReadableStream
object
or
an
ECMAScript
value
conforming
to
DataSchema
,
or
rejects
with
an
error.
Takes as arguments name and handler . Sets the service handler that defines what to do when a request is received for reading the specified Property matched by name . Throws on error. Returns a reference to this object for supporting chaining.
Note
that
there
is
no
need
to
register
handlers
for
handling
requests
for
reading
multiple
or
all
Properties
.
The
request
and
reply
are
transmitted
in
a
single
network
request,
but
the
ExposedThing
may
implement
them
using
multiple
calls
to
the
single
read
handler.
The handler callback function should implement reading a Property and SHOULD be called by implementations when a request for reading a Property is received from the underlying platform.
There
MUST
be
at
most
one
handler
for
any
given
Property
,
so
newly
added
handlers
MUST
replace
the
previous
handlers.
If
no
handler
is
initialized
for
any
given
Property
,
implementations
SHOULD
implement
a
default
property
read
handler
based
on
the
Thing
Description
provided
in
the
[[td]]
internal
slot
.
SecurityError
and
stop.
[[td]]
.
properties
[
name
]
does
not
exist
,
throw
NotFoundError
and
stop.
[[readHandlers]]
[
name
]
to
handler
.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
[[td]]
.
properties
.
name
.
NotFoundError
and
stop.
null
.
PropertyReadHandler
in
[[readHandlers]]
internal
slot
for
interaction
,
let
handler
be
that.
null
,
throw
NotSupportedError
and
stop.
The
value
returned
here
SHOULD
either
conform
to
DataSchema
or
it
SHOULD
be
an
ReadableStream
object
created
by
the
handler
.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
null
.
Takes as arguments name and handler . Sets the service handler that defines what to do when a request is received for observing the specified Property matched by name . Throws on error. Returns a reference to this object for supporting chaining.
The
handler
callback
function
should
implement
reading
a
Property
and
resolve
with
an
InteractionOutput
object
or
reject
with
an
error.
There MUST be at most one handler for any given Property , so newly added handlers MUST replace the previous handlers. If no handler is initialized for any given Property , implementations SHOULD implement a default property read handler based on the Thing Description .
SecurityError
and
stop.
[[td]]
.
properties
[
name
]
does
not
exist
,
throw
NotFoundError
and
stop.
[[observeHandlers]]
[
name
]
to
handler
.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
[[td]]
.
properties
[
name
]
does
not
exist
,
send
back
a
NotFoundError
in
the
reply
and
stop.
[[propertyObservers]]
[
name
],
in
order
to
be
able
to
notify
about
Property
value
changes.
Every
time
the
value
of
property
changes,
emitPropertyChange()
needs
to
be
explicitly
called
by
the
application
script.
Takes as arguments name and handler . Sets the service handler that defines what to do when a request is received for unobserving the specified Property matched by name . Throws on error. Returns a reference to this object for supporting chaining.
The handler callback function should implement what to do when an unobserve request is received by the implementation.
There MUST be at most one handler for any given Property , so newly added handlers MUST replace the previous handlers. If no handler is initialized for any given Property , implementations SHOULD implement a default handler based on the Thing Description .
SecurityError
and
stop.
[[td]]
.
properties
[
name
]
does
not
exist
,
throw
NotFoundError
and
stop.
[[unobserveHandlers]]
[
name
]
to
handler
.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
[[td]]
.
properties
[
name
]
does
not
exist
,
send
back
a
NotFoundError
in
the
reply
and
stop.
[[unobserveHandlers]]
[
name
];
Function
,
invoke
that
given
options
,
then
send
back
a
reply
following
the
Protocol
Bindings
and
stop.
[[propertyObservers]]
[
name
]
exists
,
remove
it
from
this
.
[[propertyObservers]]
,
send
back
a
reply
as
defined
in
the
Protocol
Bindings
and
stop.
NotFoundError
in
the
reply
as
defined
in
the
Protocol
Bindings
and
stop.
Promise
.
SecurityError
and
stop.
[[td]]
.
properties
[
name
].
undefined
,
reject
promise
with
NotFoundError
and
stop.
undefined
,
run
the
following
sub-steps:
null.
[[readHandlers]]
,
reject
promise
and
stop.
[[readHandlers]]
[
name
].
null
or
undefined
,
reject
promise
and
stop.
null
.
[[propertyObservers]]
[
name
],
run
the
following
sub-steps:
This clause needs expanding and/or refer to an algorithm in [ wot-binding-templates ].
A
function
that
is
called
when
an
external
request
for
writing
a
Property
is
received
and
defines
what
to
do
with
such
requests.
Takes
as
argument
value
and
returns
a
,
resolved
when
the
value
of
the
Property
-
identified
by
the
name
provided
when
setting
the
handler
has
been
updated
-,
or
rejects
with
an
error
if
the
property
is
not
found
or
the
value
cannot
be
updated.
Promise
Note that the code in this callback function can read the property before updating it in order to find out the old value, if needed. Therefore the old value is not provided to this function.
The
value
is
provided
by
implementations
as
an
InteractionOutput
object
in
order
to
be
able
to
represent
values
that
are
not
described
by
a
DataSchema
,
such
as
streams.
Takes as arguments name and handler . Sets the service handler that defines what to do when a request is received for writing the Property matched by name given when setting the handler. Throws on error. Returns a reference to this object for supporting chaining.
Note that even for readonly Properties it is possible to specify a write handler, as explained in Issue 199 . In this case, the write handler may define in an application-specific way to fail the request.
There MUST be at most one write handler for any given Property , so newly added handlers MUST replace the previous handlers. If no write handler is initialized for any given Property , implementations SHOULD implement default property update if the Property is writeable and notifying observers on change if the Property is observable, based on the Thing Description .
SecurityError
and
stop.
[[td]]
.
properties
[
name
]
does
not
exist
,
throw
NotFoundError
and
stop.
[[writeHandlers]]
[
name
]
to
handler
.
"single"
:
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
[[td]]
.
properties
[
name
].
undefined
,
return
a
NotFoundError
in
the
reply
and
stop.
[[writeHandlers]]
[
name
].
undefined
and
if
there
is
a
default
write
handler
provided
by
the
implementation,
let
handler
be
that.
undefined
,
send
back
a
NotSupportedError
with
the
reply
and
stop.
"single"
,
reply
to
the
request
reporting
success,
following
the
Protocol
Bindings
and
stop.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
"multiple"
.
If
that
fails,
reply
to
the
request
with
that
error
and
stop.
A
function
that
is
called
when
an
external
request
for
invoking
an
Action
is
received
and
defines
what
to
do
with
such
requests.
It
is
invoked
given
params
and
optionally
with
an
options
object.
It
returns
a
that
rejects
with
an
error
or
resolves
with
the
value
returned
by
the
Action
as
Promise
InteractionInput
.
Application
scripts
MAY
return
a
ReadableStream
object
from
an
ActionHandler
.
Implementations
will
then
use
the
stream
for
constructing
the
Action
's
response.
Takes as arguments name and action . Sets the handler function that defines what to do when a request is received to invoke the Action matched by name . Throws on error. Returns a reference to this object for supporting chaining.
The action callback function will implement an Action and SHOULD be called by implementations when a request for invoking the Action is received from the underlying platform.
There MUST be at most one handler for any given Action , so newly added handlers MUST replace the previous handlers.
SecurityError
and
stop.
[[td]]
.
actions
[
name
].
undefined
,
throw
a
NotFoundError
and
stop.
[[actionHandlers]]
[
name
]
to
action
.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
[[td]]
.
properties
[
name
].
undefined
,
return
a
NotFoundError
in
the
reply
and
stop.
[[actionHandlers]]
[
name
].
undefined
,
return
a
NotSupportedError
with
the
reply
created
by
following
the
Protocol
Bindings
and
stop.
A
function
that
is
called
when
an
external
request
for
subscribing
to
an
Event
is
received
and
defines
what
to
do
with
such
requests.
It
is
invoked
given
an
options
object
provided
by
the
implementation
and
coming
from
subscribers.
It
returns
a
that
rejects
with
an
error
or
resolves
when
the
subscription
is
accepted.
Promise
Takes as arguments name and handler . Sets the handler function that defines what to do when a subscription request is received for the specified Event matched by name . Throws on error. Returns a reference to this object for supporting chaining.
The handler callback function SHOULD implement what to do when an subscribe request is received, for instance necessary initializations. Note that the handler for emitting Events is set separately.
There MUST be at most one event subscribe handler for any given Event , so newly added handlers MUST replace the previous handlers.
SecurityError
and
stop.
[[td]]
.
events
[
name
].
undefined
,
throw
a
NotFoundError
and
stop.
[[subscribeHandlers]]
[
name
]
to
handler
.
this
.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
[[td]]
.
events
[
name
].
undefined
,
send
back
a
NotFoundError
and
stop.
[[subscribeHandlers]]
[
name
]
is
a
Function
,
invoke
it
given
options
and
stop.
[[eventListeners]]
[
name
]
to
subscriber
.
Takes as arguments name and handler . Sets the handler function that defines what to do when the specified Event matched by name is unsubscribed from. Throws on error. Returns a reference to this object for supporting chaining.
The handler callback function SHOULD implement what to do when an unsubscribe request is received.
There MUST be at most one handler for any given Event , so newly added handlers MUST replace the previous handlers.
SecurityError
and
stop.
[[td]]
.
events
[
name
].
undefined
,
throw
a
NotFoundError
and
stop.
[[unsubscribeHandlers]]
[
name
]
to
handler
.
this
.
NotSupportedError
according
to
the
Protocol
Bindings
and
stop.
NotAllowedError
according
to
the
Protocol
Bindings
and
stop.
[[td]]
.
events
[
name
].
undefined
,
send
back
a
NotFoundError
and
stop.
[[unsubscribeHandlers]]
[
name
]
exists
and
is
a
Function
,
invoke
it
given
options
and
stop.
[[eventListeners]]
,
remove
name
.
this
.
[[eventListeners]]
.
name
.
undefined
,
assume
that
the
notification
response
will
contain
an
empty
data
payload
as
specified
by
Protocol
Bindings
.
The error reporting is protocol specific and it is encapsulated by implementations. On the client end, the error listener passed with the subscription will be invoked if the client UA detects the error.
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[td]]
.
events
.
name
.
NotFoundError
and
stop.
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
[[td]]
.
[[td]]
.
If
that
fails,
reject
promise
with
a
TypeError
and
stop.
[[td]]
.
properties
initialize
this
.
[[propertyObservers]]
.
key
to
an
empty
Array
in
order
to
store
observe
request
data
needed
to
notify
the
observers
on
value
changes.
[[td]]
.
events
initialize
this
.
[[eventListeners]]
.
key
to
an
empty
Array
in
order
to
store
subscribe
request
data
needed
to
notify
the
subscribers
on
event
emission.
[[td]]
as
explained
in
[
wot-thing-description11
]
and
[
wot-binding-templates
].
Make
a
request
to
the
underlying
platform
to
initialize
the
Protocol
Bindings
and
then
start
serving
external
requests
for
WoT
Interactions
(read,
write
and
observe
Properties
,
invoke
Action
s
and
manage
Event
subscriptions),
based
on
the
Protocol
Bindings
.
Implementations
MAY
reject
this
step
for
any
reason
(e.g.
if
they
want
to
enforce
further
checks
and
constraints
on
interaction
forms).
Error
object
error
with
error
.
message
set
to
the
error
code
seen
by
the
Protocol
Bindings
and
stop.
Promise
promise
and
execute
the
next
steps
in
parallel
.
SecurityError
and
stop.
Error
object
error
with
its
message
set
to
the
error
code
seen
by
the
Protocol
Bindings
and
stop.
The
next
example
illustrates
how
to
create
an
ExposedThing
based
on
a
partial
TD
object
constructed
beforehand.
try {
let temperaturePropertyDefinition = {
type: "number",
minimum: -50,
maximum: 10000
};
let tdFragment = {
properties: {
temperature: temperaturePropertyDefinition
},
actions: {
reset: {
description: "Reset the temperature sensor",
input: {
temperature: temperatureValueDefinition
},
output: null,
forms: []
},
},
events: {
onchange: temperatureValueDefinition
}
};
WOT.produce(tdFragment);
let thing1 = await WOT.produce(tdFragment);
// initialize Properties
);
await thing1.writeProperty("temperature", 0);
// add service handlers
thing1.setPropertyReadHandler( {
thing1.setPropertyReadHandler("temperature", () => {
return readLocalTemperatureSensor(); // Promise
});
// start serving requests
thing1.expose();
await thing1.expose();
} catch (err) {
+ err);
console.log("Error creating ExposedThing: " + err);
}
The
next
example
illustrates
how
to
add
or
modify
a
Property
definition
on
an
existing
ExposedThing
:
take
its
td
property,
add
or
modify
it,
then
create
another
ExposedThing
with
that.
try {
// create a deep copy of thing1's TD
.stringify(thing1.td));
let instance = JSON.parse(JSON.stringify(thing1.td));
const statusValueDefinition = {
type: "object",
properties: {
brightness: {
type: "number",
minimum: 0.0,
maximum: 100.0,
required: true
},
rgb: {
type: "array",
"minItems": 3,
"maxItems": 3,
: {
items : {
"type" : "number",
"minimum": 0,
"maximum": 255
}
}
};
instance["name"] = "mySensor";
instance.properties[] = {
instance.properties["brightness"] = {
type: "number",
minimum: 0.0,
maximum: 100.0,
required: true,
};
instance.properties[] = statusValueDefinition;
instance.actions[] = {
instance.properties["status"] = statusValueDefinition;
instance.actions["getStatus"] = {
description: "Get status object",
input: null,
output: {
: statusValueDefinition;
status : statusValueDefinition;
},
forms: [...]
};
instance.events[] = statusValueDefinition;
instance.forms = [...];
ExposedThing(instance);
instance.events["onstatuschange"] = statusValueDefinition;
instance.forms = [...]; // update
var thing2 = new ExposedThing(instance);
// TODO: add service handlers
thing2.expose();
await thing2.expose();
});
} catch (err) {
+ err);
console.log("Error creating ExposedThing: " + err);
}
The
following
will
cover
a
set
of
examples
for
the
generation
of
a
Thing
Description
from
an
ExposedThingInit
using
expand
an
ExposedThingInit
steps.
As
hypothesis
the
runtime
supports
HTTP
and
COAP
protocol
bindings
and
it
is
hosted
at
192.168.0.1.
The
next
example
shows
how
to
exploit
a
ExposedThingInit
to
create
a
simple
Thing
Description
with
one
Property
with
the
default
values.
TODO:
add
more
examples
where
the
ExposedThingInit
contains
suggested
values
that
are
replaced
by
the
algorithm.
Discovery is a distributed application that requires provisioning and support from participating network nodes (clients, servers, directory services). This API models the client side of typical discovery schemes supported by various IoT deployments.
The
ThingDiscoveryProcess
object
provides
the
properties
and
methods
controlling
the
discovery
process
and
returning
the
results.
WebIDL[SecureContext, Exposed=(Window,Worker)]
interface ThingDiscoveryProcess
{
constructor
(optional ThingFilter
filter = {});
readonly attribute
readonly attribute boolean done
;
readonly attribute Error? error
;
async
undefined stop
();
async iterable<ThingDescription
>;
};
The
ThingDiscoveryProcess
object
has
the
following
internal
slot
s.
Internal Slot | Initial value | Description ( non-normative ) |
---|---|---|
[[filter]] |
undefined
|
The
ThingFilter
object
used
in
discovery.
|
[[url]] |
undefined
|
A
URL
representing
the
TD
Directory
when
used
within
the
exploreDirectory()
method.
|
The
done
property
is
true
if
the
discovery
has
been
stopped
or
completed
with
no
more
results
to
report.
The
error
property
represents
the
last
error
that
occurred
during
the
discovery
process.
Typically
used
for
critical
errors
that
stop
discovery.
The
ThingDiscoveryProcess
object
implements
the
async
iterator
concept.
ThingDiscoveryProcess
ThingDiscoveryProcess
with
a
filter
,
run
the
following
steps:
null
,
throw
a
TypeError
and
stop.
ThingDiscoveryProcess
object.
[[filter]]
to
filter
.
done
to
false
.
error
to
null
.
Represents an object containing the constraints for discovering Thing s as key-value pairs.
WebIDLdictionary ThingFilter
{
object? fragment
;
};
The
fragment
property
represents
a
template
object
used
for
matching
property
by
property
against
discovered
Thing
s.
The
query
property
was
temporarily
removed
from
ThingFilter
,
until
it
is
standardized
in
the
WoT
Discovery
task
force.
It
represented
a
query
string
accepted
by
the
implementation,
for
instance
a
SPARQL
or
JSON
query.
Support
was
to
be
implemented
locally
in
the
WoT
Runtime
or
remotely
as
a
service
in
a
TD
Directory
.
The url property was removed. It used to represent the target entity serving the discovery request, for instance the URL of a TD Directory , or the URL of a directly targeted Thing , but these are implemented by dedicated methods now.
error
property
to
SyntaxError
,
discard
td
and
continue
the
discovery
process.
At this point implementations MAY control the flow of the discovery process (depending on memory constraints, for instance queue the results, or temporarily stop discovery if the queue is getting too large, or resume discovery when the queue is emptied sufficiently). These steps are run for each discovered/fetched td .
[[filter]]
.
fragment
.
object
,
then
for
each
key
defined
in
it:
asyncIterator
.
Improve this step using proper asyncIterator terminology.
The last error is retained. Implementations MAY choose to stop the discovery process if they consider it should be reported.
Error
object.
Set
error
.
name
to
"DiscoveryError"
.
error
to
error
.
done
to
true
and
terminate
these
steps.
SecurityError
and
stop.
done
property
to
true
.
The
following
example
finds
ThingDescription
objects
of
Thing
s
that
are
exposed
by
local
hardware,
regardless
how
many
instances
of
WoT
Runtime
it
is
running
Using
the
asyncIterator
provided
by
the
Discovery
object,
we
can
iterate
asynchronously
over
the
results
and
perform
operations
with
the
obtained
ThingDescription
objects.
let url = "https://mythings.com/thing1";
WOT.requestThingDescription(url);
let td = await WOT.requestThingDescription(url);
console
.log(
.
log
(
"Found
Thing
Description
for
"
+
td.title);
td.
title
);
The
next
example
finds
ThingDescription
objects
of
Thing
s
listed
in
a
TD
Directory
service.
We
set
a
timeout
for
safety.
let discovery = await WOT.exploreDirectory("http://directory.wotservice.org");
setTimeout( () => {
discovery.stop();
);
discovery.stop();
console.log("Discovery stopped after timeout.");
},
3000);
discovery) {
+ td.title);
ConsumedThing(td);
+ thing.getThingDescription().title);
for await (const td of discovery) {
console.log("Found Thing Description for " + td.title);
let thing = new ConsumedThing(td);
console.log("Thing name: " + thing.getThingDescription().title);
};
(discovery.error) {
+ error.message);
if (discovery.error) {
console.log("Discovery stopped because of an error: " + error.message);
}
The next example is for a generic discovery, by any means provisioned to the WOT runtime, including local Things, if any is available.
let discovery = await WOT.discover();
setTimeout( () => {
discovery.stop();
);
discovery.stop();
console.log("Stopped open-ended discovery");
},
10000);
discovery) {
+ td.title);
for await (const td of discovery) {
console.log("Found Thing Description for " + td.title);
};
(discovery.error) {
+ error.message);
if (discovery.error) {
console.log("Discovery stopped because of an error: " + error.message);
}
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 ]. This section discusses only security and privacy risks and possible mitigations directly relevant to the scripts and WoT Scripting API.
A suggested set of best practices to improve security for WoT devices and services has been documented in [ wot-security ]. That document may be updated as security measures evolve. Following these practices does not guarantee security, but it might help avoid commonly known vulnerabilities.
This section is normative and contains specific risks relevant for the WoT Scripting Runtime.
A typical way to compromise any process is to send it a corrupted input via one of the exposed interfaces. This can be done to a script instance using WoT interface it exposes.
In case a script is compromised or misbehaving, the underlying physical device (and potentially surrounded environment) can be damaged if a script can use directly exposed native device interfaces. If such interfaces lack safety checks on their inputs, they might bring the underlying physical device (or environment) to an unsafe state (i.e. device overheats and explodes).
If the WoT Scripting Runtime supports post-manufacturing provisioning or updates of scripts, WoT Scripting Runtime or any related data (including security credentials), it can be a major attack vector. An attacker can try to modify any above described element during the update or provisioning process or simply provision attacker's code and data directly.
Typically the WoT Scripting Runtime needs to store the security credentials that are provisioned to a WoT device to operate in WoT network. If an attacker can compromise the confidentiality or integrity of these credentials, then it can obtain access to the WoT assets, impersonate WoT things or devices or create Denial-Of-Service (DoS) attacks.
This section is non-normative.
This section describes specific risks relevant for script developers.
A script instance may receive data formats defined by the TD, or data formats defined by the applications. While the WoT Scripting Runtime SHOULD perform validation on all input fields defined by the TD, scripts may be still exploited by input data.
If a script performs heavy functional processing on received requests before the request is authenticated, it presents a great risk for Denial-of-Service (DoS) attacks.
API rationale usually belongs to a separate document, but in the WoT case the complexity of the context justifies including basic rationale here.
The WoT Interest Group and Working Group have explored different approaches to application development for WoT that have been all implemented and tested.
It is possible to develop WoT applications that only use the WoT network interface , typically exposed by a WoT gateway that presents a RESTful API towards clients and implements IoT protocol plugins that communicate with supported IoT deployments. One such implementation is the Mozilla WebThings platform.
WoT Thing s show good synergy with software objects, so a Thing can be represented as a software object, with Properties represented as object properties, Action s as methods, and Event s as events. In addition, metadata is stored in special properties. Consuming and exposing is done with factory methods that produce a software object that directly represents a remote Thing and its interactions. One such implementation is the Arena Web Hub project.
In
the
next
example,
a
Thing
that
represents
interactions
with
a
lock
would
look
like
the
following:
the
status
property
and
the
open()
method
are
directly
exposed
on
the
object.
let lock = await WoT.consume('https://td.my.com/lock-00123');
console.log(lock.status);
lock.
open
(
'withThisKey'
);
Since the direct mapping of Thing s to software objects have had some challenges, this specification takes another approach that exposes software objects to represent the Thing metadata as data property and the WoT interactions as methods. One implementation is node-wot in the Eclipse ThingWeb project, which is the current reference implementation of the API specified in this document.
The
same
example
now
would
look
like
the
following:
the
status
property
and
the
open()
method
are
represented
indirectly.
const lockTd = await WoT.requestThingDescription('https://td.my.com/lock-00123');
const lock = WoT.consume(lockTd);
console.log(lock.readProperty('status'));
lock.
invokeAction
(
'open'
,
'withThisKey'
);
In conclusion, the WoT WG decided to explore the third option that closely follows the Web of Things (WoT) Thing Description 1.1 specification. Based on this, a simple API can also be implemented. Since Scripting is an optional module in WoT, this leaves room for applications that only use the WoT network interface . Therefore all three approaches above are supported by the Web of Things (WoT) Thing Description 1.1 specification.
Moreover, the WoT network interface can be implemented in many languages and runtimes. Consider this API an example for what needs to be taken into consideration when designing a Scripting API for WoT.
The
current
version
of
this
specification
defines
a
new
requestThingDescription
method
that
simplifies
the
process
of
retrieving
and
validating
a
Thing
Description.
However,
it
only
covers
simple
use
cases
that
do
not
require
additional
parameters
or
special
HTTP
headers
for
the
retrieval.
More sophisticated use cases need to be covered by external methods, such as the Fetch API or an HTTP client library, which offer already standardized options on specifying fetch details. In these cases, the user is required to perform validation manually as described by the Web of Things (WoT) Thing Description 1.1 specification.
In
the
future,
requestThingDescription()
might
be
extended
with
an
options
argument,
including
frequently
used
fetch
options.
Please
open
an
issue
to
request
support
for
options.
Earlier drafts used the Observer construct, but since it has not become standard, a new design was needed that was light enough for embedded implementations. Therefore observing Property changes and handling WoT Event s is done with callback registrations.
The
reason
to
use
function
names
like
readProperty()
,
readMultipleProperties()
etc.
instead
of
a
generic
polymorphic
read()
function
is
that
the
current
names
map
exactly
to
the
"op"
vocabulary
from
the
Form
definition
in
the
Web
of
Things
(WoT)
Thing
Description
1.1
specification.
formIndex
,
InteractionData
including
streams.
For a complete list of changes, see the github change log . You can also view the recently closed issues .
WebIDLtypedef object ThingDescription
;
]
[SecureContext, Exposed=(Window,Worker)]
namespace WOT
{
// methods defined in UA conformance classes
};
partial namespace WOT
{
Promise<ConsumedThing
> consume
(ThingDescription
td);
};
typedef object ExposedThingInit
;
partial namespace WOT
{
Promise<ExposedThing
> produce
(ExposedThingInit
init);
};
partial namespace WOT
{
Promise<ThingDiscoveryProcess
> discover
(optional ThingFilter
filter = {});
};
partial namespace WOT
{
,
Promise<ThingDiscoveryProcess
> exploreDirectory
(USVString url,
optional ThingFilter
filter = {});
};
partial namespace WOT
{
Promise<ThingDescription
> requestThingDescription
(USVString url);
};
typedef
typedef any DataSchemaValue
;
typedef (ReadableStream or DataSchemaValue
) InteractionInput
;
]
interface
readonly attribute
readonly attribute
[SecureContext, Exposed=(Window,Worker)]
interface InteractionOutput
{
readonly attribute ReadableStream? data
;
readonly attribute boolean dataUsed
;
readonly attribute Form? form
;
readonly attribute DataSchema? schema
;
Promise<ArrayBuffer> arrayBuffer
();
Promise<DataSchemaValue
> value
();
};
]
/**
* Note: retrieving the result of an action via the implicit InteractionOutput interface
* will only work after the action has been completed
*/
[SecureContext, Exposed=(Window,Worker)]
interface ActionInteractionOutput
: InteractionOutput
{
Promise<InteractionOutput
> query
(
optional InteractionInput
params = {},
optional InteractionOptions
options = {});
Promise<undefined> cancel
(
optional InteractionInput
params = {},
optional InteractionOptions
options = {});
};
[SecureContext, Exposed=(Window,Worker)]
interface ConsumedThing
{
,
optional
(
optional
,
optional
,
optional
Promise<InteractionOutput
> readProperty
(DOMString propertyName,
optional InteractionOptions
options = {});
Promise<PropertyReadMap
> readAllProperties
(
optional InteractionOptions
options = {});
Promise<PropertyReadMap
> readMultipleProperties
( sequence<DOMString> propertyNames,
optional InteractionOptions
options = {});
Promise<undefined> writeProperty
(DOMString propertyName, InteractionInput
value,
optional InteractionOptions
options = {});
Promise<undefined> writeMultipleProperties
(
PropertyWriteMap
valueMap,
optional
optional InteractionOptions
options = {});
/*Promise<undefined> writeAllProperties(
PropertyWriteMap valueMap,
optional InteractionOptions options = {});*/
,
optional = {},
optional
Promise<ActionInteractionOutput
> invokeAction
(DOMString actionName,
optional InteractionInput
params = {},
optional InteractionOptions
options = {});
Promise<Subscription
> observeProperty
(DOMString name,
InteractionListener
listener,
optional ErrorListener
onerror,
optional
optional InteractionOptions
options = {});
Promise<Subscription
> subscribeEvent
(DOMString name,
InteractionListener
listener,
optional ErrorListener
onerror,
optional
optional InteractionOptions
options = {});
ThingDescription
getThingDescription
();
};
dictionary
dictionary InteractionOptions
{
unsigned long formIndex
; object uriVariables
; any data
;
};
[]
[SecureContext, Exposed=(Window,Worker)]
interface Subscription
{
readonly attribute
readonly attribute boolean active
;
Promise<undefined> stop
(optional InteractionOptions
options = {});
};
[]
[SecureContext, Exposed=(Window,Worker)]
interface PropertyReadMap
{
readonly
readonly maplike<DOMString, InteractionOutput
>;
};
[]
[SecureContext, Exposed=(Window,Worker)]
interface PropertyWriteMap
{
readonly
readonly maplike<DOMString, InteractionInput
>;
};
callback
callback
callback InteractionListener
= undefined(InteractionOutput
data);
callback ErrorListener
= undefined(Error error);
]
[SecureContext, Exposed=(Window,Worker)]
interface ExposedThing
{
ExposedThing
setPropertyReadHandler
(DOMString name,
PropertyReadHandler
handler);
ExposedThing
setPropertyWriteHandler
(DOMString name,
PropertyWriteHandler
handler);
ExposedThing
setPropertyObserveHandler
(DOMString name,
PropertyReadHandler
handler);
ExposedThing
setPropertyUnobserveHandler
(DOMString name,
PropertyReadHandler
handler);
,
optional
Promise<undefined> emitPropertyChange
(DOMString name,
optional InteractionInput
data);
ExposedThing
setActionHandler
(DOMString name, ActionHandler
action);
ExposedThing
setEventSubscribeHandler
(DOMString name,
EventSubscriptionHandler
handler);
ExposedThing
setEventUnsubscribeHandler
(DOMString name,
EventSubscriptionHandler
handler);
,
optional
Promise<undefined> emitEvent
(DOMString name,
optional InteractionInput
data);
Promise<undefined> expose
();
Promise<undefined> destroy
();
ThingDescription
getThingDescription
();
};
callback (
optional
callback PropertyReadHandler
= Promise<InteractionInput
>(
optional InteractionOptions
options = {});
callback
,
optional
callback PropertyWriteHandler
= Promise<undefined>(
InteractionOutput
value,
optional InteractionOptions
options = {});
callback
,
optional
callback ActionHandler
= Promise<InteractionInput
>(
InteractionOutput
params,
optional InteractionOptions
options = {});
callback (
optional
callback EventSubscriptionHandler
= Promise<undefined>(
optional InteractionOptions
options = {});
]
[SecureContext, Exposed=(Window,Worker)]
interface ThingDiscoveryProcess
{
constructor
(optional ThingFilter
filter = {});
readonly attribute
readonly attribute boolean done
;
readonly attribute Error? error
;
async
undefined stop
();
async iterable<ThingDescription
>;
};
dictionary ThingFilter
{
object? fragment
;
};
Special thanks to former editor Johannes Hund (until August 2017, when at Siemens AG) and Kazuaki Nimura (until December 2018) for developing this specification. Also, the editors would like to thank Dave Raggett, Matthias Kovatsch, Michael Koster, Elena Reshetova, Michael McCool as well as the other WoT WG members for their comments, contributions and guidance.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: