Copyright © 2017-2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
The Web of Things is made of entities (Things) 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), Actions (to execute remote procedures with or without return values) and Events (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 Things and to expose locally defined Things 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 standards and drafts index.
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, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a 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 that 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 18 August 2025 W3C Process Document.
WoT provides layered interoperability based on how Things 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 Things 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 ConsumedThingconsume() method on the WoT API object.
        
          Implementations of this conformance class MUST implement  interface and the ExposedThingproduce() method on the WoT API object.
        
          Implementations of this conformance class MUST implement the
           interface, the
          ThingDiscoveryProcessdiscover() 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].
    
WebIDLtypedef 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 {
  const td = await requestThingDescription('https://tds.mythings.biz/sensor11');
  const thing = await WoT.consume(td);
  console.log("Thing name: " + thing.getThingDescription().title);
} catch (err) {
  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 optionalstring then if value is equal to one of the elements in optional remove key from exposedThingInitSchemaThe 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 Descriptions 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 Descriptions 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 Descriptions 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 Forms, 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 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.
        
        While the value() function provides built-in validation, we recognize that some
        use cases may require returning values without validation. In such cases, developers
        can use alternative patterns, such as directly accessing the underlying data 
        using streams or the arrayBuffer() function (see Example 4 and Example 5).
      
Warning: Disabling validation may introduce risks, particularly when interacting with remote Things, as mismatches in data formats or schema expectations can lead to unforeseen bugs and vulnerabilities. For more details, see the consumer assertions.
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 ActionInteractionOutput object.
    
      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 {
  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 InteractionOptions options = {});
  /*Promise<undefined> writeAllProperties(
                              PropertyWriteMap valueMap,
                              optional InteractionOptions options = {});*/
  Promise<ActionInteractionOutput> invokeAction(DOMString actionName,
                              optional InteractionInput params = {},
                              optional InteractionOptions options = {});
  Promise<Subscription> observeProperty(DOMString name,
                              InteractionListener listener,
                              optional ErrorListener onerror,
                              optional InteractionOptions options = {});
  Promise<Subscription> subscribeEvent(DOMString name,
                              InteractionListener listener,
                              optional ErrorListener onerror,
                              optional InteractionOptions options = {});
  ThingDescription getThingDescription();
};
dictionary InteractionOptions {
  unsigned long formIndex;
  object uriVariables;
  any data;
};
[SecureContext, Exposed=(Window,Worker)]
interface Subscription {
  readonly attribute boolean active;
  Promise<undefined> stop(optional InteractionOptions options = {});
};
[SecureContext, Exposed=(Window,Worker)]
interface PropertyReadMap {
  readonly maplike<DOMString, InteractionOutput>;
};
[SecureContext, Exposed=(Window,Worker)]
interface PropertyWriteMap {
  readonly maplike<DOMString, InteractionInput>;
};
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). TDs 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] 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 ActionInteractionOutput 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] exists, 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 Actions 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.
      
SubscriptionSubscription 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 {
  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) {
  console.log("TD fetch error: " + e.message);
};
try {
  // subscribe to property change for "temperature"
  await thing.observeProperty("temperature", async (data) => {
    try {
      console.log("Temperature changed to: " + await data.value());
    } catch (error) {
      console.error("Cannot read the observed property temperature");
      console.error(error);
    }
  });
  // subscribe to the "ready" event defined in the TD
  await thing.subscribeEvent("ready", async (eventData) => {
    try {
      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) {
      console.error("Cannot read the ready event or startMeasurement failed");
      console.error(error)
    }
  });
} catch (e) {
  console.log("Error starting measurement.");
}
setTimeout(async () => {
  try {
    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 = await thing.invokeAction("takePicture");
  image = await response.value() // throws NotReadableError --> schema not defined
} catch(ex) {
  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"
    }
  ]
}}*/
const video = await thing.readProperty("video")
const reader = video.data.getReader()
reader.read().then(function processVideo({ done, value }) {
  if (done) {
    console.log("live video stopped");
    return;
  }
  const decoded = decode(value)
  UI.show(decoded)
  // Read some more, and call this function again
  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('data', data => data.name === 'startObject' && ++objectCounter);
parser.on('end', () => console.log(`Found ${objectCounter} objects.`));
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);
  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);
  Promise<undefined> emitEvent(DOMString name,
          optional InteractionInput data);
  Promise<undefined> expose();
  Promise<undefined> destroy();
  ThingDescription getThingDescription();
};
callback PropertyReadHandler = Promise<InteractionInput>(
        optional InteractionOptions options = {});
callback PropertyWriteHandler = Promise<undefined>(
        InteractionOutput value,
        optional InteractionOptions options = {});
callback ActionHandler = Promise<InteractionInput>(
        InteractionOutput params,
        optional InteractionOptions options = {});
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 PropertyReadHandlers as values | 
          
| [[writeHandlers]] | {} | 
            A Map with property names as keys and PropertyWriteHandlers as values | 
          
| [[observeHandlers]] | {} | 
            A Map with property names as keys and PropertyReadHandlers as values | 
          
| [[unobserveHandlers]] | {} | 
            A Map with property names as keys and Functions as values | 
          
| [[actionHandlers]] | {} | 
            A Map with action names as keys and ActionHandlers as values | 
          
| [[subscribeHandlers]] | {} | 
            A Map with event names as keys and EventSubscriptionHandlers as values | 
          
| [[unsubscribeHandlers]] | {} | 
            A Map with event names as keys and EventSubscriptionHandlers 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 PromiseReadableStream 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 PromiseInteractionInput.
      
        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 Actions 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
    }
  };
  let thing1 = await WOT.produce(tdFragment);
  // initialize Properties
  await thing1.writeProperty("temperature", 0);
  // add service handlers
  thing1.setPropertyReadHandler("temperature", () => {
     return readLocalTemperatureSensor();  // Promise
  });
  // start serving requests
  await thing1.expose();
} catch (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
  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["brightness"] = {
    type: "number",
    minimum: 0.0,
    maximum: 100.0,
    required: true,
  };
  instance.properties["status"] = statusValueDefinition;
  instance.actions["getStatus"] = {
    description: "Get status object",
    input: null,
    output: {
      status : statusValueDefinition;
    },
    forms: [...]
  };
  instance.events["onstatuschange"] = statusValueDefinition;
  instance.forms = [...];  // update
  var thing2 = new ExposedThing(instance);
  // TODO: add service handlers
  await thing2.expose();
  });
} catch (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 boolean done;
  readonly attribute Error? error;
  undefined stop();
  async_iterable<ThingDescription>;
};
    
      The ThingDiscoveryProcess object has the following internal slots.
    
| 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.
    
ThingDiscoveryProcessThingDiscoveryProcess 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 Things as key-value pairs.
WebIDLdictionary ThingFilter {
  object? fragment;
  
};
      
        The fragment property represents a template object used for matching property by property against discovered Things.
      
        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 Things 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";
let td = await WOT.requestThingDescription(url);
console.log("Found Thing Description for " + td.title);
      
        The next example finds ThingDescription objects of Things listed in a TD Directory service. We set a timeout for safety.
      
let discovery = await WOT.exploreDirectory("http://directory.wotservice.org");
setTimeout( () => {
    discovery.stop();
    console.log("Discovery stopped after timeout.");
  },
  3000);
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);
};
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();
    console.log("Stopped open-ended discovery");
  },
  10000);
for await (const td of discovery) {
  console.log("Found Thing Description for " + td.title);
};
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 Things show good synergy with software objects, so a Thing can be represented as a software object, with Properties represented as object properties, Actions as methods, and Events 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 Things 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 Events 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 any DataSchemaValue;
typedef (ReadableStream or DataSchemaValue) InteractionInput;
[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 {
  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 InteractionOptions options = {});
  /*Promise<undefined> writeAllProperties(
                              PropertyWriteMap valueMap,
                              optional InteractionOptions options = {});*/
  Promise<ActionInteractionOutput> invokeAction(DOMString actionName,
                              optional InteractionInput params = {},
                              optional InteractionOptions options = {});
  Promise<Subscription> observeProperty(DOMString name,
                              InteractionListener listener,
                              optional ErrorListener onerror,
                              optional InteractionOptions options = {});
  Promise<Subscription> subscribeEvent(DOMString name,
                              InteractionListener listener,
                              optional ErrorListener onerror,
                              optional InteractionOptions options = {});
  ThingDescription getThingDescription();
};
dictionary InteractionOptions {
  unsigned long formIndex;
  object uriVariables;
  any data;
};
[SecureContext, Exposed=(Window,Worker)]
interface Subscription {
  readonly attribute boolean active;
  Promise<undefined> stop(optional InteractionOptions options = {});
};
[SecureContext, Exposed=(Window,Worker)]
interface PropertyReadMap {
  readonly maplike<DOMString, InteractionOutput>;
};
[SecureContext, Exposed=(Window,Worker)]
interface PropertyWriteMap {
  readonly maplike<DOMString, InteractionInput>;
};
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);
  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);
  Promise<undefined> emitEvent(DOMString name,
          optional InteractionInput data);
  Promise<undefined> expose();
  Promise<undefined> destroy();
  ThingDescription getThingDescription();
};
callback PropertyReadHandler = Promise<InteractionInput>(
        optional InteractionOptions options = {});
callback PropertyWriteHandler = Promise<undefined>(
        InteractionOutput value,
        optional InteractionOptions options = {});
callback ActionHandler = Promise<InteractionInput>(
        InteractionOutput params,
        optional InteractionOptions options = {});
callback EventSubscriptionHandler = Promise<undefined>(
        optional InteractionOptions options = {});
[SecureContext, Exposed=(Window,Worker)]
interface ThingDiscoveryProcess {
  constructor(optional ThingFilter filter = {});
  readonly attribute boolean done;
  readonly attribute Error? error;
  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:
Referenced in:
Referenced in: