diff --git a/.pr-preview.json b/.pr-preview.json new file mode 100644 index 00000000..010969ea --- /dev/null +++ b/.pr-preview.json @@ -0,0 +1,4 @@ +{ + "src_file": "index.html", + "type": "respec" + } diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..04f41dc4 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,3 @@ +# Code of Conduct + +All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..706c373d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Web of Things Working Group + +Contributions to this repository are intended to become part of Recommendation-track documents governed by the +[W3C Patent Policy](http://www.w3.org/Consortium/Patent-Policy-20040205/) and +[Software and Document License](http://www.w3.org/Consortium/Legal/copyright-software). To make substantive contributions to specifications, you must either participate +in the relevant W3C Working Group or make a non-member patent licensing commitment. + +If you are not the sole contributor to a contribution (pull request), please identify all +contributors in the pull request comment. + +To add a contributor (other than yourself, that's automatic), mark them one per line as follows: + +``` ++@github_username +``` + +If you added a contributor by mistake, you can remove them in a comment with: + +``` +-@github_username +``` + +If you are making a pull request on behalf of someone else but you had no part in designing the +feature, you can remove yourself with the above syntax. + +For further guidelines, refer to [https://github.com/w3c/wotwg#contributing](https://github.com/w3c/wotwg#contributing). diff --git a/Overview.html b/Overview.html new file mode 100644 index 00000000..60d57b03 --- /dev/null +++ b/Overview.html @@ -0,0 +1,5747 @@ + + + + + + + + + + + Web of Things (WoT) Scripting API + + + + + + + + +
+ +

Web of Things (WoT) + Scripting API

+

W3C Working + Draft

+
+
This version:
+
+ + https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/ +
+
Latest published version:
+
+ https://www.w3.org/TR/wot-scripting-api/ +
+
Latest editor's draft:
+
+ https://w3c.github.io/wot-scripting-api/ +
+
Previous version:
+
+ + https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ +
+
Editors:
+
+ Zoltan Kis (Intel) +
+
+ Kazuaki Nimura (Fujitsu Ltd.) +
+
+ Daniel Peintner (Siemens AG) +
+
Johannes Hund (Former Editor, when at + Siemens AG)
+
Contributors:
+
+ + In the GitHub repository +
+
Repository:
+
+ We are + on GitHub +
+
+ File a + bug +
+
+ +
+
+
+

Abstract

+

The overall Web of Things (WoT) concepts are + described in the WoT Architecture + document. The Web of Things is made of entities (Things) that can describe their capabilities in a + machine-interpretable format, the 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.

+

This specification describes a programming interface + representing the WoT Interface that + allows scripts run on a Thing to discover and + consume (retrieve) other Thing Descriptions + and to expose Things characterized by WoT Interactions specified by a script.

+

Scripting is an optional "convenience" building block in WoT + and it is typically used in gateways 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 like + Thing Directory.

+
+
+

Status of This Document

+

This section describes the status of this document at + the time of its publication. Other documents may supersede this + document. A list of current W3C publications and the + latest revision of this technical report can be found in the + W3C technical reports + 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.

+
+
+ Editor's note: The W3C WoT WG is asking for + feedback +
+

Please contribute to this draft using the + GitHub + Issue feature 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 + a Working Draft. This document is intended to become a W3C + Recommendation.

+

Comments regarding this document are welcome. Please send + them to public-wot-wg@w3.org + (subscribe, + archives).

+

Changes from the previous publication can be found in + Appendix A. A diff-marked version of this document is also + available for comparison purposes.

+

Publication as a Working Draft does not imply endorsement by + the W3C + Membership. This is a draft document and may be updated, + replaced or obsoleted by other documents at any time. It is + inappropriate to cite this document as other than work in + progress.

+

This document was produced by a group operating under the + 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 1 February 2018 + W3C Process + Document.

+
+ +
+ +

1. + Introduction

+

WoT provides layered interoperability based on how Things are modeled: as being "consumed" and + "exposed".

+

By consuming a TD, a client Thing creates a runtime resource model that allows + accessing the Properties, Actions and + Events exposed by the server Thing exposed on a + remote device.

+

Exposing a Thing requires defining a Thing Description (TD) and instantiating a software + stack to serve requests for accessing the exposed Properties, Actions and Events. This specification describes how to expose + and consume Things by a script.

+
+
+ Note +
+

Typically scripts are meant to be used on devices + able to provide resources (with a WoT Interface) for managing (installing, updating, + running) scripts, such as bridges or gateways that expose and + control simpler devices as WoT Things.

+
+
+
+ Note +
+

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.

+
+

For an introduction on how scripts could be used in Web of Things, check the Primer + document. For some background on API design decisions check the + Rationale + document.

+
+
+ +

2. Use + Cases

+

This section is non-normative.

+

The following scripting use cases are supported in this + specification:

+
+

2.1 + Discovery

+ +
+
+

2.2 Consuming a Thing

+ +
+
+

2.3 + Exposing a Thing

+ +
+
+
+ +

3. The + WoT + object

+

The WoT object is the API entry point and it is exposed by + an implementation of the WoT Runtime. The + WoT object + does not expose properties, only methods for discovering, + consuming and exposing a Thing.

+
+
+ Note +
+

Browser implementations SHOULD use a namespace object such as + navigator.wot. Node.js-like runtimes MAY provide the API object through + the require() or + + import mechanism.

+
+
+
// [SecureContext]
+// [NamespaceObject]
+interface WoT {
+  Observable discover(optional ThingFilter filter);
+  Promise<ThingDescription> fetch(USVString url);
+  ConsumedThing consume(ThingDescription td);
+  ExposedThing produce(ThingModel model);
+  Promise<void> register(USVString directory, ExposedThing thing);
+  Promise<void> unregister(USVString directory, ExposedThing thing);
+};
+typedef object ThingFragment;
+typedef object PropertyFragment;
+typedef object ActionFragment;
+typedef object EventFragment;
+typedef object DataSchema;
+typedef object SecurityScheme;
+typedef object Link;
+typedef object Form;
+typedef USVString ThingDescription;
+typedef (ThingFragment or ThingDescription) ThingModel;
+
+
+
+ Editor's note +
+

The algorithms for the WoT methods will be + specified later, including error handling and security + considerations.

+
+

The ThingModel type represents + either a ThingFragment, or a + ThingDescription.

+
+

3.1 The discover() + method

+

Starts the discovery process that will provide ThingDescriptions that match the + optional argument filter of type ThingFilter. Returns an + [Observable](https://github.com/tc39/proposal-observable) + object that can be subscribed to and unsubscribed from. The + handler function provided to the Observable during + subscription will receive an argument of type + USVString representing a ThingDescription.

+
+

+ 3.1.1 The DiscoveryMethod + enumeration

+
+
typedef DOMString DiscoveryMethod;
+
+

DiscoveryMethod + represents the discovery type to be used:

+
    +
  • "any" + does not provide any restriction
  • +
  • + "local" + for discovering Things defined + in the same device or connected to the device by wired + or wireless means. +
  • +
  • + "directory" for discovery based + on a service provided by a Thing Directory. +
  • +
  • + "multicast" for discovering + Things in the device's network + by using a supported multicast protocol. +
  • +
+
+
+

3.1.2 The ThingFilter + dictionary

+

The ThingFilter + dictionary that represents the constraints for discovering + Things as key-value pairs.

+
+
dictionary ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  USVString? url;
+  USVString? query;
+  ThingFragment? fragment;
+};
+
+

The method + property represents the discovery type that should be used + in the discovery process. The possible values are defined + by the DiscoveryMethod enumeration + that MAY be extended + by string values defined by solutions (with no guarantee of + interoperability).

+

The url property + represents additional information for the discovery method, + such as the URL of the target entity serving the discovery + request, for instance a Thing + Directory (if method is + "directory") or a Thing (otherwise).

+

The query + property represents a query string accepted by the + implementation, for instance a SPARQL or JSON query. + Support may be implemented locally in the WoT Runtime or remotely as a service in a + Thing Directory.

+

The fragment property + represents a ThingFragment dictionary used for + matching property by property against discovered Things.

+
+

The discover(filter) method MUST run the following steps:

+
    +
  1. If invoking discover() is not allowed for + the current scripting context for security reasons, throw + SecurityError and terminate these steps.
  2. +
  3. Return an Observable obs and + execute the next steps in parallel. +
  4. +
  5. If obs.subscribe(handler, errorHandler, + complete) is called, execute the following + sub-steps: +
      +
    1. If the first argument handler is not + defined or it is not a function, throw + TypeError and terminate the algorithm. + Otherwise configure handler to be invoked + when a discovery hit happens.
    2. +
    3. If the second argument errorHandler is + defined, but it is not a function, throw + TypeError and terminate these steps. + Otherwise if defined, save it to be invoked in error + conditions.
    4. +
    5. If the third argument onComplete is + defined, but it is not a function, throw + TypeError and terminate these steps. + Otherwise if defined, save it to be invoked when the + discovery process finished for other reasons than + having been canceled.
    6. +
    7. If filter.query is defined, pass it as + an opaque string to the underlying implementation to be + matched against discovered items. The underlying + implementation is responsible to parse it e.g. as a + SPARQL or JSON query and match it against the + Thing Descriptions found + during the discovery process. If queries are not + supported, implementations SHOULD throw a + NotSupported error and terminate these + steps. +
    8. +
    9. If filter.fragment is defined, and if it + contains other properties than the ones defined in + ThingFragment, + throw TypeError and terminate these steps. + Otherwise save the object for matching the discovered + items against it. +
    10. +
    11. Request the underlying platform to start the + discovery process, with the following parameters: +
        +
      • If filter.method is not defined or + the value is "any", use the widest + discovery method supported by the underlying + platform.
      • +
      • Otherwise if filter.method is + "local", use the local Thing Directory for + discovery. Usually that defines Things deployed in the same device, or + connected to the device in slave mode (e.g. + sensors connected via Bluetooth or a serial + connection). +
      • +
      • Otherwise if filter.method is + "directory", use the remote Thing Directory + specified in filter.url. +
      • +
      • Otherwise if filter.method is + "multicast", use all the multicast + discovery protocols supported by the underlying + platform.
      • +
      +
    12. +
    +
  6. +
  7. Whenever a new item td is discovered by the + underlying platform, run the following sub-steps: +
      +
    1. If filter.query is defined, check if + td is a match for the query. The matching + algorithm is encapsulated by implementations. If that + returns false, discard td and + continue the discovery process.
    2. +
    3. If filter.fragment is defined, for each + property defined in it, check if that property exists + in td and has the same value. If this is + false in any checks, discard td + and continue the discovery process.
    4. +
    5. Otherwise if td has not been discarded + in the previous steps, invoke the handler + function with td as parameter.
    6. +
    +
  8. +
  9. Whenever an error occurs during the discovery process, + and if errorHandler is defined, invoke it with + an argument of type Error whose + message property is set to + UnknownError unless there was an error code + provided by the Protocol Bindings, + in which case set it to that value. +
  10. +
  11. When the discovery process is finished, and if + onComplete is defined, invoke it run the + cancel discovery steps. +
  12. +
  13. When the obs.unsubscribe() method is + called, run the following cancel discovery steps: +
      +
    1. Request the underlying platform to stop the + discovery process. If this returns an error, or if it + is not possible, for instance when discovery is based + on open ended multicast requests, the implementation + SHOULD discard + subsequent discovered items.
    2. +
    3. Set obs.closed to + false.
    4. +
    +
  14. +
+
+
+

3.2 + The fetch() + method

+

Accepts an url argument of type + USVString that represents a URL (e.g. + "file://..." or "https://...") and + returns a Promise that resolves with a + ThingDescription (a + serialized JSON-LD document of type + USVString).

+

The fetch(url) method MUST run the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If invoking fetch() is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. If the argument url is not a URL, reject + promise with TypeError and + terminate these steps.
  6. +
  7. Make a request to fetch the content of url + as described by the Protocol + Bindings and wait for the reply. Implementations + encapsulate the fetching process and the accepted media + types (such as application/td+json), as far + as a valid Thing Description + can be obtained as defined in [WOT-TD]. Let td + be the Thing Description + string-serialized from the returned content, as specified + in the + Thing Description serialization. +
  8. +
  9. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  10. +
  11. Otherwise resolve promise with td + and terminate these steps.
  12. +
+
+
+

3.3 The consume() + method

+

Accepts an td argument of type ThingDescription and returns a + ConsumedThing object + instantiated based on parsing that description.

+

The consume(td) method must run the following + steps:

+
    +
  1. If the argument td is not a string, throw a + TypeError and terminate these steps.
  2. +
  3. Let stub be the result of running the + TD parsing algorithm with + td as argument. If that throws an error, + re-throw the error and terminate these steps. +
  4. +
  5. If stub does not have an own property that + is defined in ThingFragment with a default value, + add that property and value to stub. +
  6. +
  7. Create a ConsumedThing object + thing initialized from stub that + implements Observable. +
  8. +
  9. Add the read() and write() + methods to the ThingProperty elements so that they + make requests to access the remote Things and + wait for the reply, as defined by the Protocol Bindings. Also, all + ThingProperty + elements SHOULD + implement Observable, i.e. + define a subscribe() method that should make + request to observe the given Properties + as defined by the Protocol Bindings. +
  10. +
  11. Add the invoke() methods to the ThingAction elements so that they + make requests to the remote Thing to invoke its + actions, as defined by the Protocol + Bindings. +
  12. +
  13. Add the subscribe() method to all + ThingEvent elements + so that they make requests to subscribe to the events + defined by the remote Thing, as defined + by the Protocol Bindings. +
  14. +
  15. Return thing.
  16. +
+
+
+

3.4 The produce() + method

+

Accepts a model argument of type + ThingModel and + returns an ExposedThing + object.

+

The produce(model) method MUST run the following steps:

+
    +
  1. If invoking produce() is not allowed for + the current scripting context for security reasons, throw + SecurityError and terminate these steps.
  2. +
  3. If the argument model is a string, then run + the TD parsing algorithm with model + passed as parameter. If it throws an error, re-throw that + error and terminate this algorithm. Otherwise let + model be the returned value.
  4. +
  5. If model is not an object, throw + TypeError and terminate these steps.
  6. +
  7. If model does not have an own property that + is defined in ThingFragment with a default value, + add that property and value to model. +
  8. +
  9. Create an ExposedThing object thing + initialized from model. +
  10. +
  11. For each property of ExposedThing defined in ThingFragment, initialize the + property based on the provided initial or default values + provided to the local WoT Runtime + implementation, for instance initialize: +
      +
    1. the id property to be the final unique + identifier of the Thing, +
    2. +
    3. the security object of type SecurityScheme to + represent the actual security scheme and its properties + as set up by the implementation, +
    4. +
    5. the properties property to be an + object with all properties being ThingProperty + objects in which the read() and + write() methods are provided to define + local methods to get and set the Property values, +
    6. +
    7. the actions property to be an object + with all properties being ThingAction objects in which the + invoke() method is provided to define a + local method to run the defined Actions, +
    8. +
    9. the events property to be an object + with all properties being ExposedEvent objects in which + the emit() method is provided to define a + local way to trigger sending notifications to all + subscribed clients, +
    10. +
    11. and initialize the other properties as initialized + from model.
    12. +
    13. Return thing.
    14. +
    +

    The TD parsing algorithm + takes a string td as argument and runs the + following steps:

    +
      +
    1. Parse td according to the + WoT Thing Description in order to produce a + JSON + object json. Update thing + with the properties and values defined in + json. +
    2. +
    3. If there was an error during the parsing, throw + that error and terminate these steps.
    4. +
    5. Otherwise return json.
    6. +
    +
  12. +
+
+
+

3.5 The register() + method

+

Takes two mandatory arguments:

+ +

Generate the Thing Description as + td, given the Properties, Actions and Events defined for + this ExposedThing object. + Then make a request to register td to the given + WoT Thing Directory.

+
+
+

3.6 The + unregister() method

+

Takes two mandatory arguments:

+ +

Makes a request to unregister the thing from + the given WoT Thing Directory.

+
+
+

3.7 + Examples

+
+
+ Example + 1: Discover Things via + directory +
+
let discoveryFilter = {
+  method: "directory",
+  url: "http://directory.wotservice.org"
+};
+let subscription = wot.discover(discoveryFilter).subscribe(
+  td => {
+    console.log("Found Thing " + td.name);
+    // fetch the TD and create a ConsumedThing
+    let thing = wot.consume(td);
+  },
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout( () => {
+    subscription.unsubscribe();
+    console.log("Discovery timeout");
+  },
+  5000);
+
+
+
+ Example + 2: Discover Things + exposed by local hardware +
+
let subscription = wot.discover({ method: "local" }).subscribe(
+  td => { console.log("Found local Thing " + td.name); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+ + Example 3: Same as above + but with different Observable syntax +
+
let subscription = wot.discover({ method: "local" }).subscribe({
+  td => { console.log("Found local Thing " + td.name); },
+  error: err => { console.log("Discovery error: " + err.message); },
+  complete: () => { console.log("Discovery finished successfully");}
+});
+
+
+
+
+ +

4. The ConsumedThing + interface

+

Represents an object that extends a ThingFragment with methods for client + interactions (send request for reading and writing Properties), invoke Actions, subscribe and + unsubscribe for Property changes and Events.

+
+
interface ConsumedThing : ThingFragment {
+  readonly attribute DOMString id;
+  readonly attribute DOMString name;
+  readonly attribute DOMString? base;
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute EventMap events;
+  // getter for ThingFragment properties
+  getter any (DOMString name);
+};
+[NoInterfaceObject]
+interface PropertyMap {
+  readonly maplike<DOMString, ThingProperty>;
+};
+[NoInterfaceObject]
+interface ActionMap {
+  readonly maplike<DOMString, ThingAction>;
+};
+[NoInterfaceObject]
+interface EventMap {
+  readonly maplike<DOMString, ThingEvent>;
+};
+ConsumedThing includes Observable;  // for TD changes
+
+

The id attribute + represents the unique identifier of the Thing instance, + typically a URI, IRI, or URN as USVString.

+

The name attribute + represents the name of the Thing as + DOMString.

+

The base attribute + represents the base URI that is valid for all defined local + interaction resources.

+

The properties + attribute represents a dictionary of ThingProperty items. The + PropertyMap interface + represents a maplike dictionary where all values are ThingProperty objects. The + read() and write() methods make a + request to access the Properties on the remote + Thing represented by this ConsumedThing proxy object.

+

The actions + attribute represents a dictionary of ThingAction items. The + ActionMap interface represents a + maplike dictionary where all values are ThingAction objects. The + invoke() method represents a request to invoke the + Action on the remote Thing.

+

The events + attribute represents a dictionary of ThingEvent items. The EventMap interface + represents a maplike dictionary where all values are ThingEvent objects. Subscribing to the + events involves setting up an observation (subscription) + mechanism on the remote object.

+
+

4.1 + Examples

+

Below a ConsumedThing interface example + is given.

+
+
+ Example + 4: Consume a Thing +
+
try {
+  let subscription = wot.discover({ method: "local" }).subscribe(
+    td => {
+      let thing = wot.consume(td);
+      console.log("Thing " + thing.name + " has been consumed.");
+      let subscription = thing["temperature"].subscribe(function(value) {
+          console.log("Temperature: " + value);
+        });
+      thing.actions["startMeasurement"].invoke({ units: "Celsius" })
+        .then(() => { console.log("Temperature measurement started."); })
+        .catch(e => {
+           console.log("Error starting measurement.");
+           subscription.unsubscribe();
+         })
+    },
+    error => { console.log("Discovery error: " + error.message); },
+    () => { console.log("Discovery finished successfully");}
+  );
+} catch(error) {
+  console.log("Error: " + error.message);
+};
+
+
+
+
+ +

5. The ExposedThing + interface

+

The ExposedThing interface is + the server API that allows defining request handlers, + properties, Actions, and Events to a + Thing. It also implements the Observable interface. An ExposedThing is created by the produce() method.

+
+
interface ExposedThing : ThingFragment {
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute ExposedEvents events;
+  // getter for ThingFragment properties
+  getter any (DOMString name);
+  // setter for ThingFragment properties
+  setter void (DOMString name, any value);
+  // methods to expose and destroy the Thing
+  Promise<void> expose();
+  Promise<void> destroy();
+  // define Properties
+  ExposedThing addProperty(DOMString name, PropertyFragment property, optional any initValue);
+  ExposedThing setPropertyReadHandler(DOMString name, PropertyReadHandler readHandler);
+  ExposedThing setPropertyWriteHandler(DOMString name, PropertyWriteHandler writeHandler);
+  ExposedThing removeProperty(DOMString name);
+  // define Actions
+  ExposedThing addAction(DOMString name, ActionFragment init, ActionHandler action);
+  ExposedThing removeAction(DOMString name);
+  ExposedThing setActionHandler(DOMString name, ActionHandler action);
+  // define Events
+  ExposedThing addEvent(DOMString name, EventFragment event);
+  ExposedThing removeEvent(DOMString name);
+};
+[NoInterfaceObject]
+interface ExposedEvents {
+  maplike<DOMString, ExposedEvent>;
+};
+callback PropertyReadHandler = Promise<any> ();
+callback PropertyWriteHandler = Promise<void> (any value);
+callback ActionHandler = Promise<any> (any parameters);
+
+

The properties + attribute represents a dictionary of ThingProperty items in which the + read() and write() methods define + local methods that access the physical representations of the + Properties.

+

The actions + attribute represents a dictionary of ThingAction items in which the + invoke() method represents a local method to + invoke the Action.

+

The events + attribute represents a dictionary of ExposedEvent items that add the + emit() method to the ThingEvent definition. The + ExposedEvents interface + represents a maplike dictionary where all values are ExposedEvent objects.

+
+

5.1 The + expose() method

+

Start serving external requests for the Thing, so that WoT Interactions + using Properties, Actions and + Events will be possible.

+

The expose() method MUST run the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If invoking expose() is not allowed for + the current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform to attach + protocol handlers and start serving external requests for + WoT Interactions (read, write and + observe Properties, invoke Actions and manage Event + subscriptions), based on the Protocol Bindings. +
  6. +
  7. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  8. +
  9. Otherwise resolve promise with td + and terminate these steps.
  10. +
+
+
+

5.2 The + destroy() method

+

Stop serving external requests for the Thing and destroy the object. Note that eventual + unregistering should be done before invoking this method.

+

The destroy() method MUST run the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If invoking destroy() is not allowed for + the current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform to stop + serving external requests for WoT Interactions, based on the + Protocol Bindings. +
  6. +
  7. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  8. +
  9. Otherwise resolve promise with td + and terminate these steps.
  10. +
+
+
+

5.3 The + addProperty() method

+

Adds a Property with name defined by the + name argument, the data schema provided by the + property argument of type PropertyFragment, and optionally an + initial value provided in the argument initValue + whose type should match the one defined in the + type property according to the value-matching algorithm. If + initValue is not provided, it SHOULD be initialized as + undefined. Implementations SHOULD update the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.4 The + removeProperty() method

+

Removes the Property specified by the + name argument and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.5 The + addAction() method

+

Adds to the actions property of a Thing object an Action with name + defined by the name argument, defines input and + output data format by the init argument of type + ActionFragment, and + adds the function provided in the action argument + as a handler, then updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+

The provided action callback function will + implement invoking an Action and SHOULD be called by + implementations when a request for invoking the Action is received from the underlying platform. + The callback will receive a parameters + dictionary argument according to the definition in the + init.input argument and will return a value of + type defined by the init.output argument according + to the value-matching + algorithm.

+

There SHOULD be + exactly one handler for any given Action. If no + handler is initialized for any given Action, + implementations SHOULD throw a TypeError.

+
+
+

5.6 The + removeAction() method

+

Removes the Action specified by the + name argument and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.7 The + addEvent() method

+

Adds an event with name defined by the name + argument and qualifiers and initialization value provided by + the event argument of type EventFragmentto the Thing object and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.8 The + removeEvent() method

+

Removes the event specified by the name + argument and updates the Thing + Description. Returns a reference to the same object for + supporting chaining.

+
+
+

5.9 The PropertyReadHandler + callback

+

A function that is called when an external request for + reading a Property is received. It should + return a Promise and resolves it with the value of the + Property matching the name argument to + the setPropertyReadHandler function, or rejects + with an error if the property is not found or the value + cannot be retrieved.

+
+
+

5.10 The PropertyWriteHandler + callback

+

A function that is called when an external request for + writing a Property is received. It is given + the requested new value as argument and should + return a Promise which is resolved when the value of the + Property that matches the name + argument has been updated with value, or rejects + with an error if the property is not found or the value + cannot be updated.

+
+
+ Editor's note +
+

Note that this function is invoked by + implementations before the property is updated and it + actually defines what to do when a write request is + received. The code in this callback function can invoke the + read() method to find out the old value of the + property, if needed. Therefore the old value is not + provided to this function.

+
+
+
+

5.11 The ActionHandler + callback

+

A function called with a parameters + dictionary argument assembled by the WoT runtime based on the Thing Description and the external client request. + It returns a Promise that rejects with an error or resolves + if the action is successful or ongoing (may also resolve with + a control object such as an Observable for actions that need + progress notifications or that can be canceled).

+
+
+

5.12 The + setPropertyReadHandler() method

+

Takes name as string argument and + readHandler as argument of type PropertyReadHandler. + Sets the handler function for reading the specified Property matched by name. Throws on + error. Returns a reference to the same object for supporting + chaining.

+

The readHandler callback function will + implement reading a Property and + SHOULD be called by + implementations when a request for reading a Property is received from the underlying + platform.

+

There SHOULD be at + most one handler for any given Property and + newly added handlers replace the old handlers. If no handler + is initialized for any given Property, + implementations SHOULD implement a default property read + handler.

+

When an external request for reading Property propertyName is received, the + runtime SHOULD + execute the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If a Property with + propertyName does not exist, reject promise with a ReferenceError and + terminate these steps. +
  4. +
  5. Otherwise, if no read handler has been defined for + propertyName, resolve promise with + the value of the Property named + propertyName provided by the runtime implementation + and terminate these steps. +
  6. +
  7. Otherwise, invoke the read handler associated with + propertyName. If it rejects, then reject + promise with the same error, and resolve + promise with the same value. +
  8. +
+
+
+

+ 5.13 The + setPropertyWriteHandler() method

+

Takes name as string argument and + writeHandler as argument of type PropertyWriteHandler. + Sets the handler function for writing the specified Property matched by name. Throws on + error. Returns a reference to the same object for supporting + chaining.

+

There SHOULD be at + most one write handler for any given Property and newly added handlers replace the old + handlers. If no write handler is initialized for any given + Property, implementations SHOULD implement default property update + and notifying observers on change.

+

When an external request for writing a Property propertyName with a new value + value is received, the runtime SHOULD execute the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If a Property with + propertyName does not exist, reject promise with a ReferenceError and + terminate these steps. +
  4. +
  5. Otherwise, if no write handler has been defined for + propertyName, the runtime implementation + SHOULD update the + Property value with + value, resolve promise and terminate + these steps. +
  6. +
  7. Otherwise, invoke the write handler associated with + propertyName providing value as + argument. If it rejects, then reject promise + with the same error, and resolve promise with + the same value. +
  8. +
+
+
+

5.14 The + setActionHandler() method

+

Takes name as string argument and + action as argument of type ActionHandler. Sets the handler + function for the specified Action matched by + name. Throws on error. Returns a reference to + the same 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 SHOULD be at + most one handler for any given Action and newly added + handlers replace the old handlers.

+

When an external request for invoking the Action identified by name is received, + the runtime SHOULD + execute the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If an Action identified by + name does not exist, reject promise with a ReferenceError and + terminate these steps. +
  4. +
  5. Otherwise, if no action handler has been defined for + name, reject promise with a + ReferenceError and terminate these steps. +
  6. +
  7. Otherwise, invoke the Action handler + associated with name. If it rejects with + error, then reject promise with the + same error, otherwise if it resolves with + value, then resolve promise with the + same value. +
  8. +
+
+
+

5.15 + Examples

+

Below some ExposedThing interface examples + are given.

+
+
+ + Example 5: Create a new + exposed Thing with a simple property +
+
+        try {
+  var temperatureValueDefinition = {
+    type: "number",
+    minimum: -50,
+    maximum: 10000
+  };
+  var temperaturePropertyDefinition = temperatureValueDefinition;
+  // add the 'forms' property
+  temperaturePropertyDefinition.forms = [ ... ];
+  var thing = WoT.produce({
+    name: "tempSensor",
+    properties: {
+      temperature: temperaturePropertyDefinition
+    },
+    actions: {
+      reset: {
+        description: "Reset the temperature sensor",
+        input: {
+          temperature: temperatureValueDefinition
+        },
+        output: null,
+        forms: []
+      },
+    },
+    events: {
+      onchange: temperatureValueDefinition
+    },
+    links: []
+  });
+  await thing.expose();
+  await wot.register("https://mydirectory.org", thing);
+  // define Thing business logic
+  setInterval( async () => {
+    let mock = Math.random()*100;
+    let old = await thing["temperature"].read();
+    if (old < mock) {
+      await thing["temperature"].write(mock);
+      thing.emitEvent("onchange", mock);
+    }
+  }, 1000);
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ Example + 6: Create a new exposed + Thing with object property +
+
+        try {
+  var 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
+        }
+      }
+  };
+  var statusPropertyDefinition = statusValueDefinition;
+  // add the 'forms' property
+  statusPropertyDefinition["forms"] = [];
+  var thing = WoT.produce({
+    name: "mySensor",
+    properties: {
+      brightness: {
+        type: "number",
+        minimum: 0.0,
+        maximum: 100.0,
+        required: true,
+      },
+      status: statusPropertyDefinition
+    },
+    actions: {
+      status: {
+        description: "Get status object",
+        input: null,
+        output: {
+          status : statusValueDefinition;
+        },
+        forms: []
+      },
+    },
+    events: {
+      onstatuschange: statusValueDefinition;
+    },
+    links: []
+  });
+  thing.expose().then(() => {
+      thing.register();
+  });
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ + Example 7: Create a new + exposed Thing from a Thing Description +
+
+        let thingDescription = '{ \
+  "name": "mySensor", \
+  "@context": [ "http://www.w3.org/ns/td",\
+     "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ],\
+  "@type": [ "Thing", "Sensor" ], \
+  "geo:location": "testspace", \
+  "properties": { \
+    "prop1": { \
+      "type": "number",\
+      "@type": [ "Property", "Temperature" ], \
+      "saref:TemperatureUnit": "degree_Celsius" \
+  } } }';
+try {
+  // note that produce() fails if thingDescription contains error
+  let thing = WoT.produce(thingDescription);
+  // Interactions were added from TD
+  // WoT adds generic handler for reading any property
+  // define a specific handler for one property
+  let name = "examplePropertyName";
+  thing.setPropertyReadHandler(name, () => {
+    console.log("Handling read request for " + name);
+    return new Promise((resolve, reject) => {
+        let examplePropertyValue = 5;
+        resolve(examplePropertyValue);
+      },
+      e => {
+        console.log("Error");
+      });
+  });
+  thing.expose();
+} catch(err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ Example + 8: Create a new exposed + Thing from a TD URI +
+
+        // fetch an external TD, e.g., to set up a proxy for that Thing
+WoT.fetch("http://myservice.org/mySensor/description").then(td => {
+  // WoT.produce() ignores instance-specific metadata (security, form)
+  let thing = WoT.produce(td);
+  // Interactions were added from TD
+  // add server functionality
+  // ...
+});
+
+
+
+
+ +

6. Data types and structures

+

The [WOT-TD] specification defines the + + WoT information model, i.e. the data types and data + structures used in WoT Interactions. In + this API these definitions translate to dictionary objects that + are extended with methods by the interfaces defined in this + specification.

+

In order to avoid duplication of definitions, references to + these data types and structures is defined in this section, but + for their full description please refer to the Thing + Description specification.

+
+

+ 6.1 The DataSchema + dictionary and its subclasses

+

Value types basically represent types that may be used in + JSON object definitions and are used in ThingFragment to define Properties, Events and Action parameters. Value types are represented as + dictionary objects whose properties and possible sub-classes + are defined in the + DataSchema section of [WOT-TD].

+

One property of all DataSchema dictionary is the + type property whose value is from a set of + enumerated strings defined in the DataSchema + section of [WOT-TD] and is referred as + DataType in + this specification.

+

Based on type, the following sub-classes of + DataSchema are defined in + [WOT-TD]: BooleanSchema, NumberSchema, IntegerSchema, StringSchema, ObjectSchema, ArraySchema.

+
+
+

+ 6.2 The SecurityScheme dictionary + and its subclasses

+

Security metadata is represented as dictionary objects + whose properties and sub-classes are defined in the + SecurityScheme section of [WOT-TD].

+

One property of the SecurityScheme dictionary is the + scheme property whose value is from a set of + enumerated strings defined in the + SecurityScheme section of [WOT-TD]. Based on type, + multiple subclasses of SecurityScheme are defined.

+
+ +
+

6.4 The Form dictionary

+

Represents metadata describing service details, with + properties defined in the Form + section of [WOT-TD].

+
+
+

6.5 The InteractionFragment + dictionary

+

Represents the common properties of WoT Interactions, one of Property, + Action or Event, as defined in the + InteractionPattern section of [WOT-TD]. Its subclasses are + referred as PropertyFragment, ActionFragment and EventFragment.

+
+
+

6.6 The PropertyFragment + dictionary

+

Represents the Property interaction + data that initializes a ThingProperty object. Its properties + are defined in the Property + and + InteractionPattern sections of [WOT-TD].

+
+
+

6.7 The ActionFragment + dictionary

+

Represents the Action interaction data that + initializes a ThingAction object. Its + properties are defined in the Action + and + InteractionPattern sections of [WOT-TD].

+
+
+

6.8 The EventFragment + dictionary

+

Represents the Event interaction data that + initializes a ThingEvent object. Its + properties are defined in the Event + section of [WOT-TD].

+
+
+

6.9 The ThingFragment + dictionary

+

The ThingFragment + dictionary is defined as Thing + in [WOT-TD]. It is a dictionary that + contains properties representing semantic metadata and + interactions (Properties, Actions and + Events). It is used for initializing an internal + representation of a Thing Description and + its properties may be used in ThingFilter.

+
+
+

6.10 The ThingDescription + type

+

Serialized representation of the Thing Description (a JSON-LD document).

+
+
+ Note +
+

In this version of the API, Thing Descriptions are represented + as an opaque USVString that can be transmitted + between devices.

+
+
+
+
+ +

7. Interfaces for WoT Interactions

+

The data types and structures imported from [WOT-TD] are extended by + this specification in order to provide the interfaces for + WoT Interactions.

+

Every Thing describes its metadata as + defined in ThingFragment, and basic + interactions defined as Properties, Actions and Events. The following interfaces are + used for representing these interactions.

+
+

7.1 The Interaction + interface

+

The Interaction interface + is an abstract class to represent Thing + interactions: Properties, Actions and + Events.

+

The InteractionFragment + dictionary holds the common properties of PropertyFragment, ActionFragment and EventFragment dictionaries used for + initializing ThingProperty, ThingAction and ThingEvent objects in a ThingFragment dictionary used for + creating an ExposedThing + object.

+
+
interface Interaction {
+  readonly attribute (Form or FrozenArray<Form>) forms;
+};
+Interaction includes InteractionFragment;
+
+

The forms read-only + property represents the protocol bindings initialization data + and is initialized by the WoT Runtime.

+
+
+

7.2 The ThingProperty + interface

+

The ThingProperty interface + is used in ConsumedThing and + ExposedThing objects to + represent Thing Property + interactions.

+

The PropertyFragment + dictionary is used for initializing Property objects + in a ThingFragment + dictionary used for creating an ExposedThing object. It MUST implement one of the + DataSchema dictionaries.

+
+
interface ThingProperty : Interaction {
+  // getter for PropertyFragment properties
+  getter any (DOMString name);
+  // get and set interface for the Property
+  Promise<any> read();
+  Promise<void> write(any value);
+};
+ThingProperty includes PropertyFragment;
+ThingProperty includes Observable;
+
+

The ThingProperty interface + contains all the properties defined on PropertyFragment as read-only + properties.

+

The type + read-only property represents the type definition for the + Property as a DataSchema dictionary object.

+

The writable read-only property tells + whether the Property value can be updated. If it + is false, then the set(value) + method SHOULD always + reject.

+

The observable read-only + property tells whether the Property supports + subscribing to value change notifications. If it is + false, then the subscribe() method + SHOULD always + fail.

+

The constant read-only property + - defined in DataSchema - tells + whether the Property value is a constant. If + true, the set() and + subscribe() methods SHOULD always fail.

+

The required read-only property + - defined in DataSchema - tells + whether the Property should be always present on + the ExposedThing + object.

+

The read() + method will fetch the value of the Property. + Returns a Promise that resolves with the + value, or rejects with an error.

+

The + write() method will attempt to set the value of + the Propertyspecified in the + value argument whose type SHOULD match the one specified by the + type property. Returns a Promise that + resolves on success, or rejects on an error.

+
+
+

7.3 The ThingAction + interface

+
+
interface ThingAction : Interaction {
+  Promise<any> invoke(optional any inputValue);
+};
+ThingAction includes ActionFragment;
+
+

The + invoke() method when invoked, starts the + Action interaction with the input value provided by + the inputValue argument. If inputValue + is null, the action does not take any arguments + and rejects if any arguments are provided. If the value is + undefined, the action will ignore any arguments + provided. Otherwise the type of inputValue + SHOULD match the + DataSchema definition in the + input property. Returns a Promise that + will reject with an error or will resolve with a value of + type defined by the output property.

+
+
+

7.4 The ThingEvent interface

+
+
interface ThingEvent : Interaction {
+};
+ThingEvent includes EventFragment;
+ThingEvent includes ThingProperty;
+
+

Since ThingEvent implements + Observable through the ThingProperty interface, event + subscription is done by invoking the subscribe() + method on the event object that returns a cancelable Subscription.

+
+
+

7.5 The ExposedEvent + interface

+
+
interface ExposedEvent : ThingEvent {
+  void emit(any payload);
+};
+
+
+

7.5.1 The emit() + method

+

Emits an event that carries data specified by the + payload argument.

+
+
+
+

7.6 The value-matching + algorithm

+

The value-matching algorithm is applied to a + value input in relation to a valueType + property of type DataSchema, for instance the + value and type properties of a + PropertyFragment + object, or the inputValue parameter to the + invoke() method of a ThingAction object in relation to the + same object. It executes the following steps:

+
    +
  1. If valueType.type is not defined, or does + not fully match a string enumerated in DataType, return false. +
  2. +
  3. Otherwise, if valueType.type is + "null": if value is + null, return true, otherwise + return false.
  4. +
  5. Otherwise, if valueType.type is + "boolean": if value is either + true or false, then return + true, otherwise return + false.
  6. +
  7. Otherwise, if valueType.type is + "integer": if value is not an + integer type defined by the underlying platform (such as + long or long long), then return + false, otherwise execute the following + sub-steps: +
      +
    1. If valueType.minimum is defined and + value is not greater or equal than that + value, return false.
    2. +
    3. If valueType.maximum is defined and + value is not less or equal than that value, + return false.
    4. +
    5. Return true.
    6. +
    +
  8. +
  9. Otherwise, if valueType.type is + "number", if value is not an + integer or floating point type defined by the underlying + platform (such as long or long + long or double), then return + false, otherwise otherwise execute the + following sub-steps: +
      +
    1. If valueType.minimum is defined and + value is not greater or equal than that + value, return false.
    2. +
    3. If valueType.maximum is defined and + value is not less or equal than that value, + return false.
    4. +
    5. Return true.
    6. +
    +
  10. +
  11. Otherwise, if valueType.type is + "string": if value is not a string + type defined by the underlying platform, then return + false, otherwise return true. In this + case the algorithm expects a third parameter + valueType.enum and runs the following + sub-steps: +
      +
    • If valueType.enum is an array of + strings, then if value fully matches one of + the strings defined in the array, return + true.
    • +
    • Otherwise, return false.
    • +
    +
  12. +
  13. Otherwise, if valueType.type is + "array", execute the following sub-steps: +
      +
    1. If value is not an array, return + false.
    2. +
    3. If valueType.minItems is defined, and + value does not contain at least + valueType.minItems elements, return + false.
    4. +
    5. If valueType.maxItems is defined, and + value contains more than + valueType.maxItems elements, return + false.
    6. +
    7. Otherwise, if valueType.items is + undefined, return false.
    8. +
    9. Otherwise, if valueType.items is + null, return true (i.e. any + type is accepted as array element, including + heterogenous arrays).
    10. +
    11. Otherwise, for each element of the array + value run the value-matching algorithm + against the valueType.items object. If any + of these runs returns false, then return + false. +
    12. +
    13. Otherwise, return true.
    14. +
    +
  14. +
  15. Otherwise, if type is "object", + execute the following sub-steps: +
      +
    1. If value is not an Object, + return false.
    2. +
    3. If valueType.properties is not defined, + return false.
    4. +
    5. If valueType.properties is + null, return true (i.e. + accept any object value).
    6. +
    7. For each string in the + valueType.required array, if it does not + match a property name in the + value.properties object or in the + value object, then return + false.
    8. +
    9. For each property with name propName and + value propDataSchema found in + valueType.properties, run the following + sub-steps: +
        +
      1. If the result of applying the value-matching algorithm + on the value value[propName] and + propDataSchema is false, + then return false. +
      2. +
      +
    10. +
    11. Return true.
    12. +
    +
  16. +
+
+
+
+ +

8. + Observables

+

This section is non-normative.

+

Observables are proposed to + be included in ECMAScript and are used for handling pushed data + associated with various possible sources, for instance events, + timers, streams, etc. A minimal required implementation is + described here.

+
+
+ Editor's note +
+

This section is informal and contains rather + laconic information for implementations on what to support + for interoperability.

+
+
+
interface Observable {
+  Subscription subscribe(EventHandler handler,
+                         optional ErrorHandler errorHandler,
+                         optional OnComplete onComplete);
+};
+interface Subscription {
+  void unsubscribe();
+  readonly attribute boolean closed;
+};
+callback EventHandler = void (any value);
+callback ErrorHandler = void (Error error);
+callback OnComplete = void ();
+
+

The following callbacks can be provided when subscribing to + an Observable:

+ +
+

8.1 The Subscription + interface

+

Contains the closed + property of type boolean that tells if the + subscription is closed or active.

+

Also, contains the unsubscribe() + method that cancels the subscription, i.e. makes a request to + the underlying platform to stop receiving data from the + source, and sets the closed property to + false.

+
+
+

8.2 The Observable interface

+

The Observable interface + enabled subscribing to pushed data notifications by the + subscribe() + method:

+ +
+
+
+ +

9. Security and + Privacy

+

In general the security measures taken to protect a WoT + system will depend on the threats and attackers that system may + face and the value of the assets needs to protect. 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-CONSIDERATIONS]. + This section includes only normative recommendations relevant + to the WoT Thing Description.

+

When designing new devices and services + for use with the WoT, we have documented a set of best + practices in [WOT-SECURITY-BEST-PRACTICES] + that SHOULD be + followed. This best-practices document may be updated as + security measures evolve. Following these practices does not + guarantee security, but it at least will help to avoid common + known vulnerabilities and pitfalls.

+

Below are specific recommendations related to WoT runtime + implementations:

+ +

Some additional specific recommendations relevant for WoT + script developers:

+ +
+
+ +

10. Terminology and conventions

+

The generic WoT terminology is defined in [WOT-ARCHITECTURE]: + Thing, Thing Description (in short + TD), + Web of + Things (in short WoT), WoT Interface, + Protocol + Bindings, WoT Runtime, Consuming a Thing + Description, Thing Directory, + WoT + Interactions, Property, + Action, Event etc.

+

JSON-LD is + defined in [JSON-LD] as a JSON document that is + augmented with support for Linked Data.

+

The terms URL and URL path are defined in + [URL].

+

The following terms are defined in [HTML52] and are used in the context + of browser implementations: + + + browsing + context, + + + top-level browsing + context, + + + global + object, + + + incumbent settings + object, + + + Document, + + + document base URL, + + + Window, + + + WindowProxy, + + + origin, + + + ASCII + serialized origin, + + executing algorithms + + + in parallel, + + + queue a task, + + + task source, + + + iframe, + + + valid MIME type.

+ +

A browsing context refers to the + environment in which Document objects are + presented to the user. A given browsing context + has a single WindowProxy + object, but it can have many Document + objects, with their associated Window + objects. The script execution context + associated with the browsing context identifies the + entity which invokes this API, which can be a web app, a + web page, or an iframe.

+

The term + secure + context is defined in [WEBAPPSEC].

+

Error, EvalError, RangeError, ReferenceError, SyntaxError, + TypeError, + URIError , + script execution + context, + Promise, + + JSON, + JSON.stringify and + JSON.parse are defined in + [ECMASCRIPT].

+

DOMString, USVString, ArrayBuffer, BufferSource and any are defined in + [WEBIDL].

+

The algorithms utf-8 encode, and utf-8 decode are defined in + [ENCODING].

+

IANA media + types (formerly known as MIME types) are defined in + RFC2046.

+

The terms hyperlink reference and + relation + type are defined in [HTML52] and RFC8288.

+
+
+ +

11. + Conformance

+

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, SHOULD, and SHOULD NOT + are to be interpreted as described in [RFC2119].

+

This document defines conformance criteria that apply to a + single product: the UA (user agent) that implements the interfaces + it contains.

+

This specification can be used for implementing the WoT + Scripting API in multiple programming languages. The interface + definitions are specified in [WEBIDL].

+

The user agent (UA) may be implemented in the browser, or in + a separate runtime environment, such as Node.js or 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].

+

This document serves a general description of the WoT + Scripting API. Language and runtime specific issues are + discussed in separate extensions of this document.

+
+
+ +

A. + Changes

+

The following is a list of major changes to the document. + For a complete list of changes, see the github + change log. You can also view the + recently closed issues.

+ +
+
+ +

B. Open issues

+

The following problems are being discussed and need most + attention:

+ +
+
+ +

C. + Acknowledgments

+

Special thanks to former editor Johannes Hund (until August + 2017, when at Siemens AG) for developing this specification. + Also, the editors would like to thank Dave Raggett, Matthias + Kovatsch, Michael Koster and Michael McCool for their comments + and guidance.

+
+
+ +

D. + References

+
+

D.1 Normative references

+
+
[ECMASCRIPT]
+
+ ECMAScript + Language Specification. Ecma International. + URL: https://tc39.github.io/ecma262/ +
+
[ENCODING]
+
+ Encoding. + Anne van Kesteren; Joshua Bell; Addison Phillips. W3C. 15 + December 2016. W3C Candidate Recommendation. URL: + https://www.w3.org/TR/encoding/ +
+
[HTML52]
+
+ HTML 5.2. + Steve Faulkner; + Arron Eicholz; + Travis Leithead; + Alex Danilo; + Sangwhan Moon; + Erika Doyle Navara; + Theresa O'Connor; + Robin Berjon. + W3C. 14 December 2017. W3C Recommendation. URL: + https://www.w3.org/TR/html52/ +
+
[JSON-LD]
+
+ JSON-LD + 1.0. Manu Sporny; Gregg Kellogg; Markus + Lanthaler. W3C. 16 January 2014. W3C Recommendation. URL: + https://www.w3.org/TR/json-ld/ +
+
[RFC2119]
+
+ Key + words for use in RFCs to Indicate Requirement + Levels. S. Bradner. IETF. March 1997. Best + Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
+
[TYPESCRIPT]
+
+ + TypeScript Language Specification. + Microsoft. 1 October 2012. URL: + https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md +
+
[URL]
+
+ URL + Standard. Anne van Kesteren. WHATWG. Living + Standard. URL: https://url.spec.whatwg.org/ +
+
[WEBAPPSEC]
+
+ + Secure Contexts. W3C. 17 July 2015. URL: + https://w3c.github.io/webappsec/specs/powerfulfeatures +
+
[WEBIDL]
+
+ Web + IDL. Cameron McCormack; Boris Zbarsky; Tobie + Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: + https://heycam.github.io/webidl/ +
+
[WOT-ARCHITECTURE]
+
+ Web of + Things Architecture. W3C. 20 August 2017. URL: + https://w3c.github.io/wot-architecture/ +
+
+ [WOT-SECURITY-BEST-PRACTICES]
+
+ + Web of Things Security and Privacy Best Practices + (WIP). W3C. WIP. URL: + https://github.com/w3c/wot-security/blob/master/wot-security-best-practices.md +
+
+ [WOT-SECURITY-CONSIDERATIONS]
+
+ Web + of Things Security and Privacy Considerations. + W3C. 28 August 2017. URL: https://w3c.github.io/wot-security/ +
+
+ [WOT-SECURITY-TESTING]
+
+ + Web of Things Security Testing and + Validation. W3C. WIP. URL: + https://github.com/w3c/wot-security/blob/master/wot-security-testing.md +
+
[WOT-TD]
+
+ WoT + Thing Description . W3C. 21 October 2018. URL: + https://www.w3.org/TR/2018/WD-wot-thing-description-20181021/ +
+
+
+
+

D.2 Informative references

+
+
[HTML]
+
+ HTML + Standard. Anne van Kesteren; Domenic Denicola; + Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. + Living Standard. URL: https://html.spec.whatwg.org/multipage/ +
+
+
+
+ + + + diff --git a/README.md b/README.md new file mode 100644 index 00000000..5b5ffb88 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Specification 'Web of Things (WoT) Scripting API' + +The main deliverable is the [WoT Scripting API Specification](http://w3c.github.io/wot-scripting-api/). + +Releases for [published versions](https://www.w3.org/TR/wot-scripting-api/) are found in [releases](./releases/). + +See the [rationale.md](./rationale.md) for explanation on API design choices. + +To make contributions, please refer to [https://github.com/w3c/wotwg#contributing](https://github.com/w3c/wotwg#contributing). + +If you want to make a full text review on the spec or other files, follow the steps outlined [here](https://github.com/w3c/wot-scripting-api/pull/248). + +## TypeScript Definitions + +The specification uses WebIDL definitions, but TypeScript definititions are also available (see https://github.com/w3c/wot-scripting-api/blob/master/typescript/index.d.ts). diff --git a/applications/script-manager/ManagerThing1.uml b/applications/script-manager/ManagerThing1.uml new file mode 100644 index 00000000..b3b29908 --- /dev/null +++ b/applications/script-manager/ManagerThing1.uml @@ -0,0 +1,5 @@ +@startuml +ManagerThing -> TD_repo: register TD for ManagerThing +TD_repo <- ConsumedThing: get TD by Wot.discover +TD_repo --> ConsumedThing: TD +@enduml diff --git a/applications/script-manager/ManagerThing2.uml b/applications/script-manager/ManagerThing2.uml new file mode 100644 index 00000000..83295d04 --- /dev/null +++ b/applications/script-manager/ManagerThing2.uml @@ -0,0 +1,20 @@ +@startuml +participant Script_repo +participant ManagerThing +participant Execution_area +participant ConsumedThing + +ConsumedThing -> ManagerThing: invokeAction("install",... +ManagerThing -> Script_repo: get script +ManagerThing <-- Script_repo: script +Execution_area <-- ManagerThing: install script + +ConsumedThing -> ManagerThing: invokeAction("run",... +ManagerThing -> Execution_area: execute script + +ConsumedThing -> ManagerThing: invokeAction("stop",... +ManagerThing -> Execution_area: stop executing script + +ConsumedThing -> ManagerThing: invokeAction("uninstall",... +ManagerThing -> Execution_area: uninstall script +@enduml diff --git a/applications/script-manager/README.md b/applications/script-manager/README.md new file mode 100644 index 00000000..9a7ee5f7 --- /dev/null +++ b/applications/script-manager/README.md @@ -0,0 +1,142 @@ +# WoT Script Manager Thing + +The purpose of this document is to explain ManagerThing that can deal remote Thing lifecycle management by co-working with ScriptingAPI. + +### 1. ManagerThing + +ManagerThing is a capability in servient that provide management functionalities of servient and exposes management APIs to external clients.
+ +The managerThing takes advantage of [Thing Description(TD)](https://w3c.github.io/wot-thing-description/), [ScriptingAPI](https://w3c.github.io/wot-scripting-api/), and [wot security-privacy](https://github.com/w3c/wot/tree/master/security-privacy). + +TD for ManagerThing declares fixed management commands as actions that a servient supports.
+A Client that supports Scripting API(ConsumedThing) obtains the TD and knows what management capabilities are available. Then the Client issue commands to control the servient remotely.
+ +### 2. Management commands +ManagerThing provides the following managemet commands.
+ +The following commands deals life cycle of script. +* install: install a script and return a handle (e.g. URI, UUID).
+* run: run a script by a handle.
+* stop: stop a running script by a handle.
+* uninstall: uninstall a script specified by a handle and discard the handle.
+ +The script may include Scripting API commands.
+ +### 3. Thing Description for ManagerThing + +A sample TD for ManagerThing is as follows: + +```rb +{ +"@context": ["http://w3c.github.io/wot/w3c-wot-td-context.jsonld", + { "manager": "http://w3c.github.io/wot/managerthing#" } + ], + "@type": ["ManagerThing"], + "name": "ManagerThing", + "interaction": [ + { + "@type": ["Action","manager:install"], + "name": "install", + "inputData": { "type": "string" }, + "outputData": { "type": "string" }, + "link": [{ + "href" : "coap://mytemp.example.com:5683/install", + "mediaType": "application/json" + }] + }, + { + "@type": ["Action","manager:run"], + "name": "run", + "inputData": { "type": "string" }, + "link": [{ + "href" : "coap://mytemp.example.com:5683/run", + "mediaType": "application/json" + }] + }, + { + "@type": ["Action","manager:stop"], + "name": "stop", + "inputData": { "type": "string" }, + "link": [{ + "href" : "coap://mytemp.example.com:5683/stop", + "mediaType": "application/json" + }] + }, + { + "@type": ["Action","manager:uninstall"], + "name": "uninstall", + "inputData": { "type": "string" }, + "link": [{ + "href" : "coap://mytemp.example.com:5683/uninstall", + "mediaType": "application/json" + }] + } + ] +} +``` + +### 4. WebIDL + +The ManagerThing can be described in WebIDL as follows. + +```rb +typedef ScriptID USVString; // e.g. UUID + +interface ScriptManagerThing { + // main actions + any run(USVString script); // run a serialized script and return the result or error + ScriptID? install(USVString script, optional unsigned long bootSequence); // save + bool uninstall(ScriptID handle); // uninstall a script by handle (stop, unmark, delete) + bool stop(ScriptID handle); // stop a running script by handle +}; +``` + +### 5. Usage + +#### 5.1 Preparation for remote management +Servient supports fixed management command that declared as TD for ManagerThing. The servient exposes API and is controlled by external client through the TD. Client has a program that issues WoT.discover() command to obtain the TD.
+ +Fig.1 + +The following diagram depicts how ManagerThing preapard to use. + +Fig.2 + +- ManagerThing registers a TD for ManagerThing to a TD repository. +- ConsumedThing in an external client acquires the TD by WoT. discover command. +- ConsumedThing receives the TD and understands the what management capabilities are supported in the ManagerThing. + +#### 5.2 Remote management of servient + +The external client manages a servient remotely using Scripting API(ConsumedThing).
+- Servient has a ManagerThing and the ManagerThing is accessed from the client remotely. +- ManagerThing inherited the mechanism from ExposedThing and expose WoT API for ManagerThing. + +Fig.3 + +The script of left hand side (Script#1) shows the part of ManagerThing program to manage servient and the APIs are exposed.
+ +The script of the middle (Script#2) shows a script from a Script repository.
+- For example, a script in Script repository may include e.g. Create a new exposed Thing from a Thing Description. + +The script of right hand side (Script#3) shows a sript for ConsumedThing to manage the servient remotely.
+- For example, when client invoke "install" and "run" commands, servient gets script and save, then execute the script. + +The following diagram depicts how ManagerThing works based on the usage of a script installation. +Fig.4 + +- Install:
+ConsumedThing in external client issues install command to ManagerThing by invokeAction.
+ManagerThing downloads a script from script repository and saves the script to file system in servient.
+- Run:
+ConsumedThing issues run command to ManagerThing by invokeAction.
+ManagerThing deploys the script to execution area in servient and run the script.
+- Stop:
+ConsumedThing issues stop command to ManagerThing by invokeAction.
+ManagerThing stop the execution of script in execution area.
+- Uninstall:
+ConsumedThing issues uninstall command to ManagerThing by invokeAction.
+ManagerThing uninstall and discard the script from execution area and servient.
+ +### 6. Security consideration +... diff --git a/applications/script-manager/images/ManagerThing1.png b/applications/script-manager/images/ManagerThing1.png new file mode 100644 index 00000000..4bfceb41 Binary files /dev/null and b/applications/script-manager/images/ManagerThing1.png differ diff --git a/applications/script-manager/images/ManagerThing2.png b/applications/script-manager/images/ManagerThing2.png new file mode 100644 index 00000000..89fe409a Binary files /dev/null and b/applications/script-manager/images/ManagerThing2.png differ diff --git a/applications/script-manager/images/ManagerThing_Fig1.png b/applications/script-manager/images/ManagerThing_Fig1.png new file mode 100644 index 00000000..a3da8727 Binary files /dev/null and b/applications/script-manager/images/ManagerThing_Fig1.png differ diff --git a/applications/script-manager/images/ManagerThing_Fig2.png b/applications/script-manager/images/ManagerThing_Fig2.png new file mode 100644 index 00000000..05ce3723 Binary files /dev/null and b/applications/script-manager/images/ManagerThing_Fig2.png differ diff --git a/applications/thing-directory/README.md b/applications/thing-directory/README.md new file mode 100644 index 00000000..edae1c76 --- /dev/null +++ b/applications/thing-directory/README.md @@ -0,0 +1,129 @@ +# WoT Thing Directory (reverse proxy) + +This document explains about reverse proxy that provides a mean for realizing proxy or agent of things that depicted in [Web of Things (WoT) Architecture](https://w3c.github.io/wot-architecture/) or [Primer for Scripting API](https://w3c.github.io/wot-scripting-api/primer) and how it realized using ScriptingAPI. + +## 1. Reverse proxy + +WoT reverse proxy is a kind of servient that provides roles of reverse proxy to avoid direct access to another servient underneath to keep quality of service regardless of the network connection of device.
+ +The reverse proxy has two types: +- reverse proxy without cache: When a servient (servient#1) for reverse proxy is called, it synchronously accesses to another servient (servient#2) and device underneath. +- reverse proxy with cache: Caching the status of servient#1 and replicating on servient#2 even if servient#1 or device underneath loose the network connection. + +## 2. Reverse proxy using TD and Scripting API + +One way to realize the reverse proxy is synchronization of [Thing Description(TD)](https://w3c.github.io/wot-thing-description/) using [Scripting API](https://w3c.github.io/wot-scripting-api/).
+ +Fig.1 + +### 2.1. Reverse proxy without cache + +#### Description +- The state synchronization of servients can be achieved by observing servient#1. + +#### Setup +- servient#1 registers a TD of connected devices to TD repository #1. +- servient#2 has a script that transferring all of the accesses for the synchronization. servient#2 gets the TD by WoT.discover, parses the TD, then servient#2 exposes the same functions as the servient#1 and registers new TD to TD repository #2. The callback functions access the servient#1. + +##### Script for reverse proxy +The following is outline of a script to relize reverse proxy without cache. + +```rb +WoT.discover() + .subscribe(function(cthing) { + createLocalThing({name: cthing.name}) + .then(function(ething) { + …(code for transferring access of all interactions) … + ething.onInvokeAction(function(request) { + cthing.invokeAction(request.action.name, request.inputData) + .then(function(response) {return response;} + … +``` +cthing: an instance of ConsumedThing in a servient
+ething: an instance of ExposedThing in the servient
+ +#### Usage +- Client gets the TD from TD repository #2 by WoT.discover, and accesses the servient#1 via servient#2. +
+ +Fig.2 + + +#### Flow +Fig.3 + +##### TD synchronization +When thing has changed e.g. network IP has changed, it is necessary to propagete to the corresponding servients. +- servient#1 reflects the change to a TD for a thing and registers the TD to TD_repo1. +- servient#2 issues WoT.discover(Discover2) command to get the TD.
+Note that the timeing of the issue depends on implementations. Discover2 might periodically issue Wot.discover(Discover2) or might receive a notification from servient#1. This is out of the scope of this document. +- servient#2 receives the TD and exposes WoT API based on the TD using ScriptingAPI(ExposedThing). servient#2 setups callback for accesing the device as ConsumedThing(2) using ScriptingAPI. +- servient#2 registers the TD to TD_repo2. +- Client issues WoT.discver(Discover3) command to get the TD and receive the TD. +- Client setups callback for accessing the device as ConsumeThing(3) using ScriptingAPI. + +##### Device access +- ConsumedThing(3) in Client issues comman to turn on the device. +- ExposedThing(2) in servient#2 receives the command and the callback pass-throughs the command to servient#1 through ConsumedThing(2). +- ExposedThing(1) in servient#1 receives the command and turn on the device. Then return an acknowledge. + + +### 2.2. Reverse proxy with cache + +#### Description +- The state synchronization of servients can be achieved by observing servient#1. In addition, servient#2 holds the state and replicate the status even if servient#1 or device underneath looses the network connection for some reason. + +#### Setup +- servient#1 registers a TD of connected devices to TD repoistory #1. +- servient#2 has a script for the reverse proxy with cache that replicates on servient#2. servient#2 gets TD by WoT.discover, parses the TD, then servient#2 exposes the same functions with the servient#1 and registers new TD to TD repository #2. The callback functions access the servient#1. + +##### Script for reverse proxy +The following is outline of a script to relize reverse proxy with cache.
+Difference from the previous one is if an instance of consumedThing is not connected to network, replicate using cache. + +```rb +WoT.discover() + .subscribe(function(cthing) { + createLocalThing({name: cthing.name}) + .then(function(ething) { + …(code for transferring access of all interactions) … + ething.onRetrieveProperty(function(request) { + if (isConnected(cthing)) { + cthing.getProperty(request.action.name) + .then(function(response) {return response;} + } else { + return cache[request.action.name]; + } +``` + +cthing: an instance of ConsumedThing in a servient
+ething: an instance of ExposedThing in the servient
+ +#### Usage +- Client gets the TD from TD repo #2 by WoT.discover, accesses the servient#1 via servient#2 when servient#1 is accessible, and replicate the responses by accessing a cache in the servient#2 when servient#1 is not accessible. +
+ +Fig.4 + +#### Flow + +Fig.5 + +##### TD synchronization +TD synchronization behaves same as the previous one. + +##### Device access +The cache holds the behavior of event, action, and propert. It might holds linked data from a sensor for event, holds command issueing or event watting for action, and holds status of thing or command issueing for property. + +In the above flow: +- ConsumedThing(3) in Client issues comman to turn on the device. + +If device connected:
+- ExposedThing(2) in servient#2 receives the command and the callback forwards the command to servient#1 through ConsumedThing(2) if the device is connected.
+Note that how to detect the device connection is up to the implementation and out of the scope of this document.
+- ExposedThing(1) in servient#1 receives the command and turn on the device. Then return an acknowledge. + +If device disconnected: +- ExposedThing(2) in servient#2 receives the command and return an acknowledgement to ConsumedThing(3) in Client. +- The cache mechanizm of servient#2 holds the comman until the device connected to the network. +- When it is connected, issues the commands to servient#1. diff --git a/applications/thing-directory/ReverseProxy3.uml b/applications/thing-directory/ReverseProxy3.uml new file mode 100644 index 00000000..66605fa5 --- /dev/null +++ b/applications/thing-directory/ReverseProxy3.uml @@ -0,0 +1,35 @@ +@startuml +participant ExposedThing1 +participant TD_repo1 +participant ConsumedThing2 +participant Discover2 +participant ExposedThing2 +participant TD_repo2 +participant ConsumedThing3 +participant Discover3 + +== TD synchronization== +ExposedThing1 -> ExposedThing1: TD change +ExposedThing1 -> TD_repo1: register TD +Discover2 -> TD_repo1: get TD by WoT.discover +Discover2 <-- TD_repo1: TD + +create ExposedThing2 +Discover2 -> ExposedThing2: expose +create ConsumedThing2 +Discover2 -> ConsumedThing2: callback + +ExposedThing2 -> TD_repo2: register TD +Discover3 -> TD_repo2: get TD by WoT.discover +Discover3 <-- TD_repo2: TD +create ConsumedThing3 +ConsumedThing3 <-- Discover3: callback + +== device access == +ConsumedThing3 -> ExposedThing2: turn on +ExposedThing2 -> ConsumedThing2: turn on +ConsumedThing2 -> ExposedThing1: turn on +ConsumedThing2 <-- ExposedThing1: ok +ExposedThing2 <-- ConsumedThing2: ok +ConsumedThing3 <-- ExposedThing2: ok +@enduml diff --git a/applications/thing-directory/ReverseProxy5.uml b/applications/thing-directory/ReverseProxy5.uml new file mode 100644 index 00000000..e99fadbc --- /dev/null +++ b/applications/thing-directory/ReverseProxy5.uml @@ -0,0 +1,49 @@ +@startuml +participant ExposedThing1 +participant TD_repo1 +participant ConsumedThing2 +participant Discover2 +participant ExposedThing2 +participant TD_repo2 +participant ConsumedThing3 +participant Discover3 + +== TD synchronization== +ExposedThing1 -> ExposedThing1: TD change +ExposedThing1 -> TD_repo1: register TD +Discover2 -> TD_repo1: get TD by WoT.discover +Discover2 <-- TD_repo1: TD + +create ExposedThing2 +Discover2 -> ExposedThing2: expose +create ConsumedThing2 +Discover2 -> ConsumedThing2: callback + +ExposedThing2 -> TD_repo2: register TD +Discover3 -> TD_repo2: get TD by WoT.discover +Discover3 <-- TD_repo2: TD +create ConsumedThing3 +ConsumedThing3 <-- Discover3: callback + +== device access == + +ConsumedThing3 -> ExposedThing2: turn on +alt device connected +ExposedThing2 -> ConsumedThing2: turn on +ConsumedThing2 -> ExposedThing1: turn on +ConsumedThing2 <-- ExposedThing1: ok +ConsumedThing2 --> ExposedThing2: ok +ExposedThing2 --> ConsumedThing3: ok +else device disconnected +ExposedThing2 --> ConsumedThing2: turn on +ConsumedThing2 --> ExposedThing2: ok +ExposedThing2 --> ConsumedThing3: ok +ConsumedThing2 -> ConsumedThing2: until connected +ConsumedThing2 -> ExposedThing1: turn on +ConsumedThing2 <-- ExposedThing1: ok +ConsumedThing2 --> ExposedThing2: ok + +end + + +@enduml diff --git a/applications/thing-directory/images/ReverseProxy1.png b/applications/thing-directory/images/ReverseProxy1.png new file mode 100644 index 00000000..831a07e0 Binary files /dev/null and b/applications/thing-directory/images/ReverseProxy1.png differ diff --git a/applications/thing-directory/images/ReverseProxy2.png b/applications/thing-directory/images/ReverseProxy2.png new file mode 100644 index 00000000..0b056214 Binary files /dev/null and b/applications/thing-directory/images/ReverseProxy2.png differ diff --git a/applications/thing-directory/images/ReverseProxy3.png b/applications/thing-directory/images/ReverseProxy3.png new file mode 100644 index 00000000..0f605274 Binary files /dev/null and b/applications/thing-directory/images/ReverseProxy3.png differ diff --git a/applications/thing-directory/images/ReverseProxy4.png b/applications/thing-directory/images/ReverseProxy4.png new file mode 100644 index 00000000..44ba9174 Binary files /dev/null and b/applications/thing-directory/images/ReverseProxy4.png differ diff --git a/applications/thing-directory/images/ReverseProxy5.png b/applications/thing-directory/images/ReverseProxy5.png new file mode 100644 index 00000000..c1ba207b Binary files /dev/null and b/applications/thing-directory/images/ReverseProxy5.png differ diff --git a/diff.html b/diff.html new file mode 100644 index 00000000..dd07b8ae --- /dev/null +++ b/diff.html @@ -0,0 +1,19154 @@ + + + + + + + + + + + + +Web of Things (WoT) Scripting API + + + + + + + + + + + +
+ +

+Web +of +Things +(WoT) +Scripting +API +

+

+ +W3C + +Working +Draft +5 +April + + +

+
+
+This +version: +
+
+https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ + + +https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/ + + +
+
+Latest +published +version: +
+
+ +https://www.w3.org/TR/wot-scripting-api/ + +
+
+Latest +editor's +draft: +
+
+ +https://w3c.github.io/wot-scripting-api/ + +
+
+Previous +version: +
+
+https://www.w3.org/TR/2017/WD-wot-scripting-api-20170914/ + + +https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ + + +
+
+Editors: +
+
+ +Zoltan +Kis + +( + +Intel + +) +
+
+ +Kazuaki +Nimura + +( + +Fujitsu +Ltd. + +) +
+
+ +Daniel +Peintner + +( + +Siemens +AG + +) +
+
+ +Johannes +Hund + +(Former +Editor, +when +at +Siemens +AG) +
+
+Contributors: +
+
+ +In +the +GitHub +repository + +
+
+Repository: +
+
+ +We +are +on +GitHub + +
+
+ +File +a +bug + +
+
+ +
+
+
+

+Abstract +

+

+The +overall + + +Web +of +Things + +(WoT) +provides +layered +interoperability +between + +concepts +are +described +in +the + +WoT +Architecture + +document. +The +Web +of + +Things +is +made +of +entities +( + +Thing + + +by +using + +s) +that +can +describe +their +capabilities +in +a +machine-interpretable +format, +the + +Thing +Description + +(TD) +and +expose +these +capabilities +through + +the + +WoT +Interface +, +that +is, +network +interactions +modeled +as + +Properties + + +s. + +for +reading +and +writing +values, + +Action + +s +to +execute +remote +procedures +with +or +without +return +values +and + +Event + +s +for +signaling +notifications. + +

+

+This +specification +describes +a +programming +interface +representing +the + +WoT +Interface + +that +allows +scripts +run +on +a + +Thing + +to +discover +and +consume +(retrieve) +other + +Thing +Description + + +s +and +to +expose + +Things + +characterized +by + +WoT +Interactions +, +i.e. +Properties +, +Actions + + +and +Events +. + +specified +by +a +script. + +

+

+Scripting +is +an +optional +"convenience" +building +block +in +WoT +and +it +is +typically +used +in +gateways +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 +like + +Thing +Directory +. +

+
+
+

+Status +of +This +Document +

+

+ +This +section +describes +the +status +of +this +document +at +the +time +of +its +publication. +Other +documents +may +supersede +this +document. +A +list +of +current + +W3C + +publications +and +the +latest +revision +of +this +technical +report +can +be +found +in +the + + +W3C + +technical +reports +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. +

+
+
+ +Editor's +note + +: +The +W3C +WoT +WG +is +asking +for +feedback + +
+

+Please +contribute +to +this +draft +using +the + +GitHub +Issue + +feature +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 +a +Working +Draft. +This +document +is +intended +to +become +a +W3C +Recommendation. +

+

+Comments +regarding +this +document +are +welcome. +Please +send +them +to + +public-wot-wg@w3.org + +( + +subscribe +, + +archives + +). +

+

+Changes +from +the +previous +publication +can +be +found +in + +Appendix +A +. +A + +diff-marked +version + +of +this +document +is +also +available +for +comparison +purposes. +

+

+Publication +as +a +Working +Draft +does +not +imply +endorsement +by +the + +W3C + +Membership. +This +is +a +draft +document +and +may +be +updated, +replaced +or +obsoleted +by +other +documents +at +any +time. +It +is +inappropriate +to +cite +this +document +as +other +than +work +in +progress. +

+

+This +document +was +produced +by +a +group +operating +under +the + + +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 + +1 +February +2018 + +W3C + +Process +Document +. +

+
+ +
+

+ +1. + +Introduction + + +

+

+The +overall + +WoT +concepts +are +described +in +the +WoT +Architecture +document. +The +Web +of +Things +is +made +of +entities +( +Thing +s) +that +can +describe +their +capabilities +in +a +machine-interpretable +format, +the + +provides +layered +interoperability +based +on +how + +Thing +Description + + +(TD) + +s +are +modeled: +as +being +"consumed" + +and +expose +these +capabilities +through +the +WoT +Interface +. +Support +for +scripting +is +optional +for +WoT +devices. + +"exposed". + +

+

+By + +consuming +a +TD +, +a +client + +Thing + +creates +a +runtime +resource +model +that +allows +accessing +the + +Properties +, + +Actions + +and + +Events + +exposed +by +the +server + +Thing +. + + +exposed +on +a +remote +device. + +

+

+Exposing +a + +Thing + +requires +defining +a + +Thing +Description + +(TD) +and +instantiating +a +software +stack +needed + +to +serve +requests +for +accessing +the +exposed + +Properties +, + +Actions + +and + +Events +. +This +specification +describes +how +to +expose +and +consume + +Thing + +s +by +a +script. +

+
+
+ +Note + +
+

+Typically +scripts +are +meant +to +be +used +on +devices +able +to +provide +resources +(with +a + +WoT +interface + +Interface + + +) +for +managing +(installing, +updating, +running) +scripts, +such +as +bridges +or +gateways +that +expose +and +control +simpler +devices +as +WoT + +Thing + +s. +

+
+
+
+ +Note + +
+

+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. +

+
+

+For +an +introduction +on +how +scripts +could +be +used +in + +Web +of +Things +, +check +the + +Primer + +document. +For +some +background +on +API +design +decisions +check +the + +Rationale + +document. +

+
+
+

+ +2. + +Use +Cases + + +

+

+ +This +section +is +non-normative. + +

+

+The +following +scripting +use +cases +are +supported +in +this +specification: +

+
+

+ +2.1 + +Discovery + + +

+ +
+
+

+ +2.2 + +Consuming +a +Thing + + +

+ +
+
+

+ +2.3 + +Exposing +a +Thing + + +

+ +
+
+
+

+ +3. + +The + + +WoT + + +object + + +

+

+The +WoT +object +is +the +API +entry +point +and +it +is +exposed +by +an +implementation +of +the + +WoT +Runtime +. +The + +WoT +object + +does +not +expose +properties, +only +methods +for +discovering, +consuming +and +exposing +a + +Thing +. +

+
+
+ +Note + +
+

+Browser +implementations + +SHOULD + +use +a +namespace +object +such +as + +wot +, +and + +navigator.wot +. + +Node.js + +-like +runtimes + +MAY + +provide +the +API +object +through +the + +require() + +or + +import + +mechanism. +

+
+
+
data-idl="" data-title="WoT">interface <span class=
+"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-wot" class="internalDFN" data-link-type=
+"dfn"> {
+<span class="idlMethod" id="idl-def-wot-discover-filter" data-idl=
+"" data-title="discover" data-dfn-for="wot">    <span class=
+"idlMethType"><a href="#dom-observable" class="internalDFN"
+data-link-type="dfn"><<a href=
+"#dom-consumedthing" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMethName"><a data-no-default="" data-link-for="wot" data-lt=
+"discover()|discover" href="#dom-wot-discover" class="internalDFN"
+data-link-type="dfn">discover(<span class=
+"idlParam">optional <a href=
+"#dom-thingfilter" class="internalDFN" data-link-type=
+
+data-idl="" data-title="WoT">// [SecureContext]
+// [NamespaceObject]
+interface 
+data-link-for="" data-lt="" href="#dom-wot" class="internalDFN"
+data-link-type="dfn">WoT {
+  
+data-link-type=
+"dfn">Observable discover(optional 
+"dfn">ThingFilter "idlParamName">filter
+<span class="idlMethod" id="idl-def-wot-fetch-url" data-idl=""
+data-title="fetch" data-dfn-for="wot">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<<a href="#dom-thingdescription"
+class="internalDFN" data-link-type=
+
+"idlParamName">filter);
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<
+"dfn">ThingDescription> "fetch()|fetch" href="#dom-wot-fetch" class="internalDFN"
+data-link-type="dfn">fetch(<span class=
+
+"wot.fetch()|wot.fetch|fetch()|fetch" href="#dom-wot-fetch" class=
+"internalDFN" data-link-type=
+"dfn">fetch(
+"idlParam">"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id="idl-def-wot-consume-td" data-idl=""
+data-title="consume" data-dfn-for="wot">    <span class=
+"idlMethType"><a href="#dom-consumedthing" class="internalDFN"
+
+"https://heycam.github.io/webidl/#idl-USVString">USVString url);
+  "dfn"><a data-no-default=""
+data-link-for="wot" data-lt="consume()|consume" href=
+
+"dfn">ConsumedThing 
+"#dom-wot-consume" class="internalDFN" data-link-type=
+"dfn">consume<span class=
+"idlParamType"><a href="#dom-thingdescription" class="internalDFN"
+data-link-type=
+
+"dfn">consume(
+"dfn">ThingDescription "idlParamName">td
+<span class="idlMethod" id="idl-def-wot-produce-model" data-idl=""
+data-title="produce" data-dfn-for="wot">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+
+"idlParamName">td);
+  "dfn"><a data-no-default=""
+data-link-for="wot" data-lt="produce()|produce" href=
+"#dom-wot-produce" class="internalDFN" data-link-type=
+"dfn">produce<span class=
+"idlParamType"><a href="#dom-thingmodel" class="internalDFN"
+
+"dfn">ExposedThing produce(ThingModel model);
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> register(USVString directory, ExposedThing thing);
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> unregister(USVString directory, ExposedThing thing);
+};
+typedef object ThingFragment;
+typedef object PropertyFragment;
+typedef object ActionFragment;
+typedef object EventFragment;
+typedef object DataSchema;
+typedef object SecurityScheme;
+typedef object 
+data-link-type=
+"dfn">
+};
+<span class="idlTypedef" id="idl-def-thingdescription" data-idl=""
+data-title="ThingDescription">typedef <span class=
+"idlTypedefType"><a href=
+
+"dfn">Link;
+typedef object Form;
+typedef 
+"https://heycam.github.io/webidl/#idl-USVString">USVString "dfn">
+<span class="idlTypedef" id="idl-def-thingmodel" data-idl=""
+data-title="ThingModel">typedef <span class=
+"idlTypedefType">(<a href="#dom-thingtemplate" class="internalDFN"
+data-link-type="dfn"> or <a href=
+
+"dfn">ThingDescription;
+typedef (ThingFragment or 
+"#dom-thingdescription" class="internalDFN" data-link-type=
+"dfn">ThingDescription) 
+
+ThingModel
+
+
+
+;
+
+
+
+
+
+ +Editor's +note + +
+

+The +algorithms +for +the +WoT +methods +will +be +specified +later, +including +error +handling +and +security +considerations. +

+
+

+The + +ThingModel + +type +represents +either +a + +ThingFragment +, +or +a + +ThingDescription +.

+
+

+ +3.1 + +The + + +discover() + + +method + + +

+

+Starts +the +discovery +process +that +will +provide + + +ConsumedThing + +ThingDescription + + + +objects + +s + +that +match +the +optional +argument + +filter + +of +type + + + + +ThingFilter + + +. +When +the +argument +is +not +provided, +starts +the +widest +discovery +the +Thing +Description +and +Protocol +Bindings +allow +and +support. + +Returns +an +[ + + +Observable + +](https://github.com/tc39/proposal-observable) + +object +that +can +be +subscribed +to +and +unsubscribed +from. +The +handler +function +provided +to +the +Observable +during +subscription +will +receive +an +argument +of +type + +USVString + +representing +a + +ThingDescription +. +

+
+

+ +3.1.1 + +The + + +DiscoveryMethod + + +enumeration + + +

+
+
"DiscoveryMethod">typedef <a href=
+
+"DiscoveryMethod">typedef 
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString 
+
+DiscoveryMethod
+
+
+
+;
+
+
+
+

+ + +DiscoveryMethod + + +represents +the +discovery +type +to +be +used: +

+ +
+
+

+ +3.1.2 + +The + + +ThingFilter + + +dictionary + + +

+

+The + + +ThingFilter + + +dictionary +that +represents +the +constraints +for +discovering + +Thing + +s +as +key-value +pairs. +

+
+
dictionary "dfn"> {
+<span class="idlMember" id="idl-def-thingfilter-method" data-idl=""
+data-title="method" data-dfn-for="thingfilter">    <span class=
+"idlMemberType"><a href="#dom-discoverymethod" class="internalDFN"
+data-link-type=
+"dfn">      <span class=
+"idlMemberName"><a data-no-default="" data-link-for="thingfilter"
+data-lt="" href="#dom-thingfilter-method" class="internalDFN"
+data-link-type="dfn"> = <span class=
+"idlMemberValue">"any"
+<span class="idlMember" id="idl-def-thingfilter-url" data-idl=""
+data-title="url" data-dfn-for="thingfilter">    <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default=""
+
+"dfn">ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  
+"https://heycam.github.io/webidl/#idl-USVString">USVString? 
+data-link-for="thingfilter" data-lt="" href="#dom-thingfilter-url"
+class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMember" id="idl-def-thingfilter-query" data-idl=""
+data-title="query" data-dfn-for="thingfilter">    <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default=""
+
+"dfn">url;
+  
+"https://heycam.github.io/webidl/#idl-USVString">USVString? 
+data-link-for="thingfilter" data-lt="" href=
+"#dom-thingfilter-query" class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMember" id="idl-def-thingfilter-constraints"
+data-idl="" data-title="constraints" data-dfn-for=
+"thingfilter">    <a href=
+"https://heycam.github.io/webidl/#idl-sequence">sequence<a data-no-default=""
+data-link-for="thingfilter" data-lt="" href=
+"#dom-thingfilter-constraints" class="internalDFN" data-link-type=
+"dfn">
+
+"dfn">query;
+  
+data-link-type=
+"dfn">ThingFragment? fragment;
+
+};
+
+
+
+

+The + + +method + + +property +represents +the +discovery +type +that +should +be +used +in +the +discovery +process. +The +possible +values +are +defined +by +the + + + +DiscoveryMethod + + + +enumeration +that +can + + +MAY + +be +extended +by +string +values +defined +by +solutions +(with +no +guarantee +of +interoperability). +

+Editor's +note +The +DiscoveryMethod +enumeration +can +be +extended +by +the +Thing +Description +with +values +that +are +not +specified +here. +This +extensibility +of +DiscoveryMethod +by +proprietary +or +private +methods +is +a +working +assumption +until +consensus +is +formed +and +may +be +removed +later. + +

+The + + +url + + +property +represents +additional +information +for +the +discovery +method, +such +as +the +URL +of +the +target +entity +serving +the +discovery +request, +such +as + +for +instance + +a + +Thing +Directory + +(if + +method + +is + +"directory" + +) + +or +a +Thing. + +Thing +(otherwise). + +

+

+The + + +query + + +property +represents +a +query +string +accepted +by +the +implementation, +for +instance +a +SPARQL +or +JSON + +query. +Support +may +be +implemented +locally +in +the + +WoT +Runtime + +or +remotely +as +a +service +in +a + +Thing +Directory +. +

+

+The + + +constraints + +fragment + + + +property +represents +additional +information + +a + +ThingFragment + +dictionary +used + +for +the +discovery + +matching +property +by +property +against +discovered + +Thing + +s. +

+The + +discover(filter) + +method +in + + +MUST + +run + +the +form +of +a +list +of +sets +of +property-value +pairs +(dictionaries). +The +list +elements +(dictionaries) +are +in +OR +relationship, + +following +steps: +

  1. +If +invoking + +discover() + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +throw + +SecurityError + +and +within +a +constraint +dictionary + +terminate +these +steps. +
  2. +Return +an + +Observable + +obs + +and +execute + +the +key-value +pairs +are + +next +steps + +in +AND +relationship. +Implementations +SHOULD +make + +parallel +.
  3. +If + +obs.subscribe(handler, +errorHandler, +complete) + +is +called, +execute + +the +following +mapping +from + +sub-steps: +
    1. +If + +the +constraint +dictionaries + +first +argument + +handler + +is +not +defined +or +it +is +not +a +function, +throw + +TypeError + +and +terminate +the +algorithm. +Otherwise +configure + +handler + +to +be +invoked +when +a +discovery +hit +happens. +
    2. +If +the +second +argument + +errorHandler + +is +defined, +but +it +is +not +a +function, +throw + + +SemanticAnnotations + +TypeError + + +: +for +each +property-value +pair + +and +terminate +these +steps. +Otherwise +if +defined, +save +it +to +be +invoked + +in +error +conditions. +
    3. +If +the +third +argument + +onComplete + +is +defined, +but +it +is +not + +a +constraint +dictionary, + +function, +throw + +TypeError + +and +terminate +these +steps. +Otherwise +if +defined, +save +it +to +be +invoked +when +the +discovery +process +finished +for +other +reasons +than +having +been +canceled. +
    4. +
    5. +Each +property +name +in + +If + +filter.query + +is +defined, +pass +it +as +an +opaque +string +to + +the +constraint +dictionary +SHOULD + +underlying +implementation +to +be +matched +against +discovered +items. +The +underlying +implementation +is +responsible +to +parse +it +e.g. +as +a +SPARQL +or +JSON +query +and + +match +it +against + +the +either + + +Thing +Description + +s +found +during + +the +discovery +process. +If +queries +are +not +supported, +implementations + +SHOULD + +throw +a + + +name + +NotSupported + + +property +of +a + +error +and +terminate +these +steps. +
    6. +If + +filter.fragment + +is +defined, +and +if +it +contains +other +properties +than +the +ones + +defined +in + + +SemanticType + +ThingFragment + + +on + +, +throw + +TypeError + +and +terminate +these +steps. +Otherwise +save + +the +target + +object +for +matching +the +discovered +items +against +it. +
    7. +Request +the +underlying +platform +to +start +the +discovery +process, +with +the +following +parameters: +
      • +If + +filter.method + +is +not +defined +or +the +value +is + +"any" +, +use +the +widest +discovery +method +supported +by +the +underlying +platform. +
      • +Otherwise +if + +filter.method + +is + +"local" +, +use +the +local + +Thing +Directory + + +object, + +for +discovery. +Usually +that +defines + +Thing + +s +deployed +in +the +same +device, + +or +connected +to + +the +name +of + +device +in +slave +mode +(e.g. +sensors +connected +via +Bluetooth +or + +a +Property +on + +serial +connection). +
      • +Otherwise +if + +filter.method + +is + +"directory" +, +use + +the +target + +remote + +Thing +. + +Directory + +specified +in + +filter.url +. +
      • +
      • +When + +Otherwise +if + +filter.method + +is + +"multicast" +, +use +all + +the +name +matches, + +multicast +discovery +protocols +supported +by + +the +values +are +compared. + +underlying +platform. +
  4. +Whenever +a +new +item + +td + +is +discovered +by +the +underlying +platform, +run +the +following +sub-steps: +
    1. +If + +filter.query + +is +defined, +check +if + +td + +is +a +match +for + +the +values +match, + +query. +The +matching +algorithm +is +encapsulated +by +implementations. +If +that +returns + +false +, +discard + +td + +and +continue + +the +constraint + +discovery +process. +
    2. +If + +filter.fragment + +is +matched. + +defined, +for +each +property +defined +in +it, +check +if +that +property +exists +in + +td + +and +has +the +same +value. +If +this +is + +false + +in +any +checks, +discard + +td + +and +continue +the +discovery +process. + +
    3. +Editor's +note +Constraints +are +experimental +feature, +implementations +are + +
    4. +Otherwise +if + +td + +has + +not +required +to +support +them. +Editor's +note +Semantic +annotations +need +revisiting + +been +discarded + +in +order +to +simplify +their +representation. +In + +the +[ +WOT-TD +] +specification +they +represent + +previous +steps, +invoke + +the + +handler + +function +with + +td + +as +parameter. +
  5. +Whenever +an +error +occurs +during +the +discovery +process, +and +if + +errorHandler + +is +defined, +invoke +it +with +an +argument +of +type + + +@type + +Error + + +construct. +At +the +moment +only + +whose + + +@context +, + +message + +property +is +set +to + + +@type + +UnknownError + + +unless +there +was +an +error +code +provided +by +the + +Protocol +Bindings +, +in +which +case +set +it +to +that +value. +
  6. +When +the +discovery +process +is +finished, + +and +if + +onComplete + +is +defined, +invoke +it +run +the + +cancel +discovery + +steps. +
  7. +When +the + + +@id + +obs.unsubscribe() + + +constructs +are +used +in + +method +is +called, +run + +the +TD +. + +following + +cancel +discovery + +steps: +
    1. +Request +the +underlying +platform +to +stop +the +discovery +process. +If +this +returns +an +error, +or +if +it +is +not +possible, +for +instance +when +discovery +is +based +on +open +ended +multicast +requests, +the +implementation + +SHOULD + +discard +subsequent +discovered +items. +
    2. +Set + +obs.closed + +to + +false +.
+
+
+

+ +3.2 + +The + + +fetch() + + +method + + +

+

+Accepts +an + +url + +argument +of +type + +USVString + +that +represents +a +URL +(e.g. + +"file://..." + +or + +"https://..." + +) + +and +returns +a + + +Promise + + +that +resolves +with +a + + +ThingDescription + +. + + +(a +serialized + +JSON-LD + +document +of +type + +USVString + +). + +

+3.3 + +

+The + +ThingDescription + +fetch(url) + + +type +Representation +of + +method + +MUST + +run + +the +Thing +Description +, +standardized + +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +invoking + +fetch() + +is +not +allowed +for + +the +Wot +Things + +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  3. +If +the +argument + +url + +is +not +a +URL, +reject + +promise + +with + +TypeError + +and +terminate +these +steps. +
  4. +Make +a +request +to +fetch +the +content +of + +url + +as +described +by +the + +Protocol +Bindings + +and +wait +for +the +reply. +Implementations +encapsulate +the +fetching +process +and +the +accepted +media +types +(such +as + +application/td+json + +), +as +far +as +a +valid + +Thing + +Description + +specification. + +can +be +obtained +as +defined +in +[ + +Note + + +WOT-TD + +In +this +version +of + + +]. +Let + +td + +be + +the +API, + + +Thing +Description + +s +are +represented + +string-serialized +from +the +returned +content, + +as +opaque +strings, +denoting +a +serialized +form, +for +instance +JSON +or +JSON-LD. +See +Issue +38 + +specified +in +the + +Thing +Description +serialization +.
  5. +If +there +was +an +error +during +the +request, +reject + +promise + +with +an + +Error + +object + +error + +with + +error.message + +set +to +the +error +code +seen +by +the + +Protocol +Bindings + + +and +Issue +45 +. + +terminate +these +steps. +
  6. +Otherwise +resolve + +promise + +with + +td + +and +terminate +these +steps. +
+
+
+

+ +3.4 + +3.3 + + +The + + +consume() + + +method + + +

+

+Accepts +an + +td + +argument +of +type + + + +ThingDescription + + + +and +returns +a + + +ConsumedThing + + +object +instantiated +based +on +parsing + +that +description. +

+

+The + +consume(td) + +method +must +run +the +following +steps: +

  1. +If +the +argument + +td + +is +not +a +string, +throw +a + +TypeError + +and +terminate +these +steps. +
  2. +Let + +stub + +be +the +result +of +running +the + +TD +parsing +algorithm + +with + +td + +as +argument. +If +that +throws +an +error, +re-throw +the +error +and +terminate +these +steps. +
  3. +If + +stub + +does +not +have +an +own +property +that +is +defined +in + +ThingFragment + +with +a +default +value, +add +that +property +and +value +to + +stub +.
  4. +Create +a + +ConsumedThing + +object + +thing + +initialized +from + +stub + +that +implements + +Observable +.
  5. +Add +the + +read() + +and + +write() + +methods +to +the + +ThingProperty + +elements +so +that +they +make +requests +to +access +the +remote + +Thing + +s +and +wait +for +the +reply, +as +defined +by +the + +Protocol +Bindings +. +Also, +all + +ThingProperty + +elements + +SHOULD + +implement + +Observable +, +i.e. +define +a + +subscribe() + +method +that +should +make +request +to +observe +the +given + +Properties + +as +defined +by +the + +Protocol +Bindings +.
  6. +Add +the + +invoke() + +methods +to +the + +ThingAction + +elements +so +that +they +make +requests +to +the +remote + +Thing + +to +invoke +its +actions, +as +defined +by +the + +Protocol +Bindings +.
  7. +Add +the + +subscribe() + +method +to +all + +ThingEvent + +elements +so +that +they +make +requests +to +subscribe +to +the +events +defined +by +the +remote + +Thing +, +as +defined +by +the + +Protocol +Bindings +.
  8. +Return + +thing +.
+
+
+

+ +3.5 + +3.4 + + +The + + +produce() + + +method + + +

+

+Accepts +a + +model + +argument +of +type + + + +ThingModel + + + +and +returns +an + + +ExposedThing + + +object, +locally +created +based +on +the +provided +initialization +parameters. +An + +object. +

+The + + +ExposedThing + +produce(model) + + +can +be +created +in + +method + +MUST + +run + +the +following +ways: + +steps: + +

+
    +
  1. +from +an +initial + +If +invoking + +produce() + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +throw + +SecurityError + +and +terminate +these +steps. +
  2. +If +the +argument + +model +(including + + +is + +a +user +given +name +and +semantic +annotations +), + +string, + +then +adding +properties, +actions, +events + +run +the + +TD +parsing +algorithm + +with + +model + +passed +as +parameter. +If +it +throws +an +error, +re-throw +that +error + +and +request +handlers; + +terminate +this +algorithm. +Otherwise +let + +model + +be +the +returned +value. + +
  3. +
  4. +from +a +Thing +Description +(possibly +of +a + +If + +model + +is +not +an +object, +throw + +TypeError + +and +terminate +these +steps. +
  5. +If + +model + +does +not +have +an +own +property +that +is +defined +in + + +ConsumedThing + +ThingFragment + + + +object), +then +adding +request +handlers. + +with +a +default +value, +add +that +property +and +value +to + +model +. +
  6. +3.6 +The + +
  7. +Create +an + + +ThingModel + +ExposedThing + + +type +A +Thing + + +object + +thing + +initialized +from + +model +is +used +for +producing +a +new + +. +
  8. +
  9. +For +each +property +of + + +ExposedThing + + +and +can +be +either +a + +defined +in + + +ThingTemplate + +ThingFragment + + +, +initialize +the +property +based +on +the +provided +initial + +or +a + +default +values +provided +to +the +local + +WoT +Runtime + +implementation, +for +instance +initialize: +
    1. +the + + +ThingDescription + +id + + +. +3.7 +The + +property +to +be +the +final +unique +identifier +of +the + +Thing +,
    2. +the + +security + +object +of +type + + +SemanticAnnotations + +SecurityScheme + + +dictionary +A +dictionary +that +provides + + +to +represent + +the +semantic +types + +actual +security +scheme + +and +semantic +metadata. +<span class="idlDictionary" id= +"idl-def-semanticannotations" data-idl="" data-title= +"SemanticAnnotations">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-semanticannotations" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id= +"idl-def-semanticannotations-semantictype" data-idl="" data-title= +"semanticType" data-dfn-for="semanticannotations"> <span class= +"idlMemberType"><a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-semantictype" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for= +"semanticannotations" data-lt="" href= +"#dom-semanticannotations-semantictype" class="internalDFN" +data-link-type="dfn"> +<span class="idlMember" id="idl-def-semanticannotations-metadata" +data-idl="" data-title="metadata" data-dfn-for= +"semanticannotations"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-semanticmetadata" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for= +"semanticannotations" data-lt="" href= +"#dom-semanticannotations-metadata" class="internalDFN" +data-link-type="dfn"> +}; +The + +its +properties +as +set +up +by +the +implementation, +
    3. +the + + +semanticType + +properties + + +property +denotes +a +list +of + +to +be +an +object +with +all +properties +being + + +SemanticType + +ThingProperty + + + +objects +that + +in +which +the + +read() + +and + +write() + +methods +are +provided +to + +define +local +methods +to +get +and +set +the + +Property + +values, +
    4. +the +semantic +types +that +can +be +used +in +semantic +metadata +type-value +pairs. +The + + +metadata + +actions + + +property +denotes +a +list +of + +to +be +an +object +with +all +properties +being + + +SemanticMetadata + +ThingAction + + + +objects +(type-value +pairs). +3.8 +The + +in +which +the + + +SemanticType + +invoke() + + +dictionary +<span class="idlDictionary" id= +"idl-def-semantictype" data-idl="" data-title= +"SemanticType">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-semantictype" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-semantictype-name" data-idl="" +data-title="name" data-dfn-for= +"semantictype"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="semantictype" data-lt="" href= +"#dom-semantictype-name" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-semantictype-context" data-idl= +"" data-title="context" data-dfn-for= +"semantictype"> required <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="semantictype" data-lt="" href= +"#dom-semantictype-context" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-semantictype-prefix" data-idl= +"" data-title="prefix" data-dfn-for= +"semantictype"> <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="semantictype" data-lt="" href= +"#dom-semantictype-prefix" class="internalDFN" data-link-type= +"dfn"> +}; +Represents +a +semantic +type +annotation, +containing +a +name, +a +context +and + +method +is +provided +to +define + +a +prefix. + +local +method +to +run +the +defined + +Action + +s, +
    5. +
    6. +The + +the + +events + +property +to +be +an +object +with +all +properties +being + + +name + +ExposedEvent + + +attribute +represents +the +name +of +the +semantic +type + + +objects + +in +which + +the +given +context. +The + + +context + +emit() + + +attribute +represents +an +URL +link + +method +is +provided + +to +define +a +local +way +to +trigger +sending +notifications +to +all +subscribed +clients, +
    7. +and +initialize + +the +context +of +the +semantic +classification. + +other +properties +as +initialized +from + +model +. +
    8. +
    9. +Return + +thing +.

    +The +prefix + + +TD +parsing +algorithm + + +attribute +represents + +takes + +a +short +prefix +associated +with + +string + +td + +as +argument +and +runs +the +following +steps: +

    1. +Parse + +td + +according +to +the + +WoT +Thing +Description + +in +order +to +produce + +a +context. + + +JSON +object + +json +. +Update + +thing + +with +the +properties +and +values +defined +in + +json +. +
    2. +Editor's +note +Semantic +type +examples +to +be +added. + +
    3. +If +there +was +an +error +during +the +parsing, +throw +that +error +and +terminate +these +steps. +
    4. +Otherwise +return + +json +.
+
+
+

+3.9 + + +3.5 + + +The + + +SemanticMetadata + +register() + + + +dictionary +<span class="idlDictionary" id= +"idl-def-semanticmetadata" data-idl="" data-title= +"SemanticMetadata">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-semanticmetadata" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-semanticmetadata-type" +data-idl="" data-title="type" data-dfn-for= +"semanticmetadata"> <a href= +"#dom-semantictype" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for= +"semanticmetadata" data-lt="" href="#dom-semanticmetadata-type" +class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-semanticmetadata-value" +data-idl="" data-title="value" data-dfn-for= +"semanticmetadata"> <a href= +"https://heycam.github.io/webidl/#idl-any">any<a data-no-default="" +data-link-for="semanticmetadata" data-lt="" href= +"#dom-semanticmetadata-value" class="internalDFN" data-link-type= +"dfn"> +}; + +method + + +

+

+The + +Takes +two +mandatory +arguments: +

+3.10 +The +ThingTemplate +dictionary + +

+A + +Generate +the + +Thing +Template +is +a +dictionary +that +provides +a +user + +Description + +as + +td +, +given +name, +and + +the +semantic +types + + +Properties +, +Action + +s + +and +semantic +metadata +attached +to +the + + +Event + +s +defined +for +this + + + +ExposedThing + + +object. +Then +make +a +request +to +register + +td + +to +the +given +WoT + +Thing +Description +'s +root +level. + +Directory +. +

+<span class="idlDictionary" id= +"idl-def-thingtemplate" data-idl="" data-title= +"ThingTemplate">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingtemplate" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingtemplate-name" data-idl="" +data-title="name" data-dfn-for= +"thingtemplate"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingtemplate" data-lt="" href= +"#dom-thingtemplate-name" class="internalDFN" data-link-type= +"dfn"> +}; + +
+
+

+ +3.6 + +The + + +ThingTemplate + +unregister() + + + +method + + +dictionary +extends + +

+

+Takes +two +mandatory +arguments: +

+Makes +a +request +to +unregister + +the +user +given +name +of + + +thing + +from + +the +given +WoT + +Thing +Directory + +. +Editor's +note +Support +for +configuration +and +security +data +might +be +added +later. + +

+
+
+

+ +3.11 + +3.7 + + +Examples + + +

+
+
+ +Example +1 + +: + +: +Discover +Things +via +directory + +
+
let discoveryFilter = {
+  method: "directory",
+  url: "http://directory.wotservice.org"
+};
+let subscription = wot.discover(discoveryFilter).subscribe(
+  "hljs-params">thing { <span class=
+"hljs-built_in">console.log(<span class=
+"hljs-string">"Found Thing " + thing.name); },
+
+"hljs-params">td => {
+    console.log(
+"hljs-string">"Found Thing " + td.name);
+    
+"hljs-comment">// fetch the TD and create a ConsumedThing
+    let thing = wot.consume(td);
+  },
+
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout( () => {
+    subscription.unsubscribe();
+    console.log("Discovery timeout");
+  },
+
+5000
+
+);
+
+
+Note +Note +that +canceling +a +discovery +(through +unsubscribe() +) +may +not +be +successful +in +all +cases, +for +instance +when +discovery +is +based +on +open +ended +broadcast +requests. +However, +once +unsubscribe() +has +been +called, +implementations +MUST +suppress +further +event +handling +( +i.e. +further +discoveries +and +errors) +on +the +Observable. +Also, +a +discovery +error +may +not +mean +the +end +of +the +discovery +process. +However, +in +order +to +respect +Observable +semantics +(error +always +terminates +processing), +implementations +MUST +close +or +suppress +further +event +handling +on +the +Observable. + +
+
+ +Example +2 + +: + +: +Discover +Things +exposed +by +local +hardware + +
+
let subscription = wot.discover({ method: "local" }).subscribe(
+  "hljs-params">thing { <span class=
+
+"hljs-params">td => { 
+"hljs-built_in">console.log("hljs-string">"Found local Thing " + thing.name); },
+
+"hljs-string">"Found local Thing " + td.name); },
+
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +Example +3 + +: + +: +Same +as +above +but +with +different +Observable +syntax + +
+
let subscription = wot.discover({ method: "local" }).subscribe({
+  thing => { <span class=
+
+  td => { 
+"hljs-built_in">console.log("hljs-string">"Found local Thing " + thing.name); },
+
+"hljs-string">"Found local Thing " + td.name); },
+
+  error: err => { console.log("Discovery error: " + err.message); },
+  complete: () => { console.log("Discovery finished successfully");}
+});
+
+
+Example +4 +: +Discover +Things +exposed +nearby, +via +Bluetooth +or +NFC +<span class= +"hljs-keyword">let subscription = wot.discover({ + : <span class= +"hljs-string">"nearby", + : [{ <span class= +"hljs-attr">protocol: <span class= +"hljs-string">"BLE-4.2" }, { <span class= +"hljs-attr">protocol: <span class= +"hljs-string">"NFC"}] +}).subscribe( + <span class= +"hljs-params">thing { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Found nearby Thing " + thing.name); }, + error => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery error: " + error.message); }, + () => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} +); +Example +5 +: +Discover +Things +exposed +in +a +proprietary +way +<span class= +"hljs-keyword">let subscription = wot.discover({ + : <span class= +"hljs-string">"other", + : [{ <span class= +"hljs-attr">solution: <span class= +"hljs-string">"XYZ123", <span class= +"hljs-attr">key}] +}).subscribe( + <span class= +"hljs-params">thing { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Found Thing " + thing.name); }, + error => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery error: " + error.message); }, + () => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} +); + +
+
+
+

+ +4. + +The + + +ConsumedThing + + +interface + + +

+

+The + +Represents +an +object +that +extends +a + + +ConsumedThing + +ThingFragment + + + +interface +is +a + +with +methods +for + +client +API + +interactions +(send +request + +for +sending +requests +to +servers +in +order +to +retrieve +or +update + +reading +and +writing + +Properties +, + + +), + +invoke +Actions +, + + +Action + +s, +subscribe + +and +observe +Properties + +unsubscribe +for + +Property + + +changes + +and + +Events +. + +Event + +s. + +

+
+
interface "dfn"> {
+<span class="idlAttribute" id="idl-def-consumedthing-name"
+data-idl="" data-title="name" data-dfn-for=
+"consumedthing">    readonly attribute <span class=
+"idlAttrType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default=""
+data-link-for="consumedthing" data-lt="" href=
+"#dom-consumedthing-name" class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMethod" id=
+"idl-def-consumedthing-getthingdescription" data-idl="" data-title=
+"getThingDescription" data-dfn-for="consumedthing">    <span class=
+"idlMethType"><a href="#dom-thingdescription" class="internalDFN"
+
+"dfn">ConsumedThing : 
+data-link-type=
+"dfn"> <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="getthingdescription()|getThingDescription" href=
+"#dom-consumedthing-getthingdescription" class="internalDFN"
+data-link-type="dfn">getThingDescription
+<span class="idlMethod" id=
+"idl-def-consumedthing-readproperty-name" data-idl="" data-title=
+"readProperty" data-dfn-for="consumedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="consumedthing" data-lt="readproperty()|readProperty"
+href="#dom-consumedthing-readproperty" class="internalDFN"
+data-link-type="dfn">readProperty(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-writeproperty-name-value" data-idl=""
+data-title="writeProperty" data-dfn-for=
+"consumedthing">    <a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="consumedthing" data-lt=
+"writeproperty()|writeProperty" href=
+"#dom-consumedthing-writeproperty" class="internalDFN"
+data-link-type="dfn">writeProperty(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-invokeaction-name-parameters" data-idl=""
+data-title="invokeAction" data-dfn-for=
+"consumedthing">    <a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="consumedthing" data-lt="invokeaction()|invokeAction"
+href="#dom-consumedthing-invokeaction" class="internalDFN"
+data-link-type="dfn">invokeAction(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-onpropertychange-name" data-idl=""
+data-title="onPropertyChange" data-dfn-for=
+"consumedthing">    <a href=
+"#dom-observable" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="onpropertychange()|onPropertyChange" href=
+"#dom-consumedthing-onpropertychange" class="internalDFN"
+data-link-type="dfn">onPropertyChange(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-consumedthing-onevent-name"
+data-idl="" data-title="onEvent" data-dfn-for=
+"consumedthing">    <a href=
+"#dom-observable" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="onevent()|onEvent" href="#dom-consumedthing-onevent"
+class="internalDFN" data-link-type=
+"dfn">onEvent<span class=
+"idlParamType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-consumedthing-ontdchange"
+data-idl="" data-title="onTDChange" data-dfn-for=
+"consumedthing">    <a href=
+
+"dfn">ThingFragment {
+  readonly attribute DOMString id;
+  readonly attribute DOMString name;
+  readonly attribute DOMString? base;
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute EventMap events;
+  // getter for ThingFragment properties
+  getter 
+"https://heycam.github.io/webidl/#idl-any">any (DOMString name);
+};
+[NoInterfaceObject]
+interface PropertyMap {
+  readonly maplike<DOMString, ThingProperty>;
+};
+[NoInterfaceObject]
+interface ActionMap {
+  readonly maplike<DOMString, ThingAction>;
+};
+[NoInterfaceObject]
+interface EventMap {
+  readonly maplike<DOMString, ThingEvent>;
+};
+
+"dfn">ConsumedThing includes 
+"#dom-observable" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="ontdchange()|onTDChange" href=
+"#dom-consumedthing-ontdchange" class="internalDFN" data-link-type=
+"dfn">onTDChange
+};
+
+"dfn">Observable;
+//
+for
+TD
+changes
+
+
+
+
+

+The + + +ConsumedThing + +id + + + +attribute + +represents +a +local +proxy +object + +the +unique +identifier + +of +the +remote + + +Thing +. + + +instance, +typically +a +URI, +IRI, +or +URN +as + +USVString +. +

+4.1 + +

+The + + +name + + +property +The +name +property + +attribute + +represents +the +name +of +the + +Thing + +as +specified +in +the +TD +. +In +this +version +it +is +read +only. + + +DOMString +. +

+4.2 + +

+The + + +getThingDescription() + +base + + + +method +Returns +the +Thing +Description +of + +attribute +represents + +the +Thing +. +Editor's +note +In +this +version, +introspection +based +on +TD +is +out +of +scope. +Parsing +and +exposing +Thing +Description +s + +base +URI +that + +is +discussed +in +Issue +38 +. + +valid +for +all +defined +local +interaction +resources. + +

+4.3 + +

+The + + +readProperty() + +properties + + + +method +Takes +the +Property +name +as +the +name +argument, +then +requests +from +the +underlying +platform +and +the +Protocol +Bindings +to +retrieve +the +Property +on +the +remote +Thing +and +return +the +result. +Returns + +attribute +represents + +a +dictionary +of + + +ThingProperty + +Promise + + +items. +The + + +PropertyMap + + +that +resolves +with +the +Property +value +or +rejects +with +an +Error +. + +4.4 +The + + +interface +represents +a +maplike +dictionary +where +all +values +are + + +writeProperty() + +ThingProperty + + +method +Takes +the +Property + + +name +as +the +name +argument +and +the +new +value +as +the +value +argument, +then +requests +from +the +underlying +platform + +objects. +The + +read() + +and +the +Protocol +Bindings + + +write() + +methods +make +a +request + +to +update + +access + +the + +Property + +Properties + + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + +represented +by +this + + +ConsumedThing + +Promise + + +that +resolves +on +success +or +rejects +with +an +Error +. + +proxy +object. + +

+4.5 + +

+The + + +invokeAction() + +actions + + + +method +Takes +the +Action +name +from +the +name +argument +and +the +list +of +parameters, +then +requests +from +the +underlying +platform +and +the +Protocol +Bindings +to +invoke +the +Action +on +the +remote +Thing +and +return +the +result. +Returns + +attribute +represents + +a +Promise + +dictionary +of + + +ThingAction + + +that +resolves +with +the +return +value +or +rejects +with +an +Error +. + +4.6 + + +items. + +The + + +onPropertyChange() + +ActionMap + + + +method +Returns +an + +interface +represents +a +maplike +dictionary +where +all +values +are + + +Observable + +ThingAction + + + +for +the +Property +specified +in +the +name +argument, +allowing +subscribing +to +and +unsubscribing +from +notifications. + +objects. + +The +callback +function +passed +to +the + + +subscribe() + +invoke() + + +method +when +invoked +on + +represents +a +request +to +invoke + +the +returned +observer +will +receive + + +Action + +on + +the +new +property +value +each +time +it +is +changed. + +remote + +Thing +. +

+4.7 + +

+The + + +onEvent() + +events + + + +method +Returns +an + +attribute +represents +a +dictionary +of + + +Observable + +ThingEvent + + + +for +the +Event +specified +in +the +name +argument, +allowing +subscribing +to +and +unsubscribing +from +notifications. +The +callback +function +passed +to +the +subscribe() +method +when +invoked +on +the +returned +observer +will +receive +the +event +data +each +time +the +event +is +fired. +4.8 + +items. + +The + + +onTDChange() + +EventMap + + + +method +Returns +an + +interface +represents +a +maplike +dictionary +where +all +values +are + + +Observable + +ThingEvent + + +, +allowing +subscribing +to +and +unsubscribing +from +notifications +to +the +Thing +Description +. +The +callback +function +passed + + +objects. +Subscribing + +to +the +subscribe() +method +when +invoked + +events +involves +setting +up +an +observation +(subscription) +mechanism + +on +the +returned +observer +will +receive +the +new +Thing +Description +each +time +it +is +changed. + +remote +object. + +

+
+

+ +4.9 + +4.1 + + +Examples + + +

+

+Below +a + + + +ConsumedThing + + + +interface +example +is +given. +

+
+
+ +Example +6 + +4 + +: + +: +Consume +a +Thing + +
+try { + let td = await wot.fetch("http://mmyservice.org/mySensor"); + let thing = wot.consume(td); + console.log("Thing " + thing.name + " has been consumed."); + let subscription = thing.onPropertyChange("temperature") + .subscribe(function(value) { + console.log("Temperature + " has changed to " + value); + }); + thing.invokeAction("startMeasurement", { units: "Celsius" }) + .then(() => { console.log("Temperature measurement started."); }) + .catch(e => { + console.log("Error starting measurement."); + subscription.unsubscribe(); + }) +} catch(error) { + console.log("Error during fetch or consume: " + error.message); + +
"hljs-keyword">try {
+  
+"hljs-keyword">let subscription = wot.discover({ method: "local" }).subscribe(
+    
+"hljs-params">td => {
+      
+"hljs-keyword">let thing = wot.consume(td);
+      console.log(
+"hljs-string">"Thing " + thing.name + " has been consumed.");
+      
+"hljs-keyword">let subscription = thing["temperature"].subscribe(function(value) {
+          
+"hljs-built_in">console.log("Temperature: " + value);
+        });
+      thing.actions["startMeasurement"].invoke({ units: "Celsius" })
+        .then(() => { console.log("Temperature measurement started."); })
+        .catch(e => {
+           
+"hljs-built_in">console.log("Error starting measurement.");
+           subscription.unsubscribe();
+         })
+    },
+    error => { console.log("Discovery error: " + error.message); },
+    () => { console.log("Discovery finished successfully");}
+  );
+} catch(error) {
+  console.log(
+"hljs-string">"Error: " + error.message);
+
+};
+
+
+
+
+
+

+ +5. + +The + + +ExposedThing + + +interface + + +

+

+The + + +ExposedThing + + +interface +is +the +server +API +that +allows +defining +request +handlers, +properties, + +Actions +, +and + +Events + +to +a + +Thing +. +It +also +implements +the + + +ConsumedThing + +Observable + + + +interface. +An + + +ExposedThing + + +is +created +by +the + +produce() + +method. +

+Editor's +note +It +is +under +consideration +to +use +a +constructor +for +ExposedThing +instead +of +a +factory +method. + +
+<a href= +"#dom-exposedthing" class="internalDFN" data-link-type= +"dfn"> implements <a href= +"#dom-consumedthing" class="internalDFN" data-link-type= +"dfn"> +<span class="idlInterface" id="idl-def-exposedthing" data-idl="" +data-title="ExposedThing">interface <span class= + +
"idl-def-exposedthing" data-idl="" data-title=
+"ExposedThing">interface 
+"idlInterfaceID">"dfn"> {
+<span class=
+"idlSectionComment">    // define how to expose and run the Thing
+<span class="idlMethod" id="idl-def-exposedthing-start" data-idl=""
+data-title="start" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="exposedthing" data-lt="start()|start" href=
+"#dom-exposedthing-start" class="internalDFN" data-link-type=
+"dfn">start
+<span class="idlMethod" id="idl-def-exposedthing-stop" data-idl=""
+data-title="stop" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="exposedthing" data-lt="stop()|stop" href=
+"#dom-exposedthing-stop" class="internalDFN" data-link-type=
+"dfn">stop
+<span class="idlMethod" id=
+"idl-def-exposedthing-register-directory" data-idl="" data-title=
+"register" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="exposedthing" data-lt="register()|register" href=
+"#dom-exposedthing-register" class="internalDFN" data-link-type=
+"dfn">register(<span class=
+"idlParam">optional <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id=
+"idl-def-exposedthing-unregister-directory" data-idl="" data-title=
+"unregister" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+
+"dfn">ExposedThing : ThingFragment {
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute ExposedEvents events;
+  // getter for ThingFragment properties
+  getter 
+"https://heycam.github.io/webidl/#idl-any">any (DOMString name);
+  // setter for ThingFragment properties
+  setter void (
+"idlParam">DOMString name, any value);
+  // methods to expose and destroy the Thing
+  Promise<void> data-link-for="exposedthing" data-lt="unregister()|unregister"
+href="#dom-exposedthing-unregister" class="internalDFN"
+data-link-type="dfn">unregister(<span class=
+"idlParam">optional <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id=
+"idl-def-exposedthing-emitevent-eventname-payload" data-idl=""
+data-title="emitEvent" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+
+data-link-for="exposedthing" data-lt=
+"exposedthing.expose()|exposedthing.expose|expose()|expose" href=
+"#dom-exposedthing-expose" class="internalDFN" data-link-type=
+"dfn">expose();
+  Promise<void> data-link-for="exposedthing" data-lt="emitevent()|emitEvent" href=
+"#dom-exposedthing-emitevent" class="internalDFN" data-link-type=
+"dfn">emitEvent<span class=
+"idlParamType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class=
+"idlSectionComment">    // define Thing Description modifiers
+<span class="idlMethod" id=
+"idl-def-exposedthing-addproperty-property" data-idl="" data-title=
+"addProperty" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+data-link-type=
+"dfn">  <span class=
+
+data-link-for="exposedthing" data-lt=
+"exposedthing.destroy()|exposedthing.destroy|destroy()|destroy"
+href="#dom-exposedthing-destroy" class="internalDFN"
+data-link-type="dfn">destroy();
+  // define Properties
+  
+"internalDFN" data-link-type=
+"dfn">ExposedThing 
+"idlMethName">data-lt="addproperty()|addProperty" href=
+"#dom-exposedthing-addproperty" class="internalDFN" data-link-type=
+"dfn">addProperty<span class=
+"idlParamType"><a href="#dom-thingproperty" class="internalDFN"
+
+data-lt=
+"exposedthing.addproperty()|exposedthing.addproperty|addproperty()|addproperty"
+href="#dom-exposedthing-addproperty" class="internalDFN"
+
+data-link-type=
+"dfn"> <span class=
+"idlParamName">property
+<span class="idlMethod" id=
+"idl-def-exposedthing-removeproperty-name" data-idl="" data-title=
+"removeProperty" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+
+"dfn">addProperty(DOMString name, PropertyFragment property, optional any initValue);
+  "dfn">  <span class=
+
+"dfn">ExposedThing 
+"idlMethName">data-lt="removeproperty()|removeProperty" href=
+"#dom-exposedthing-removeproperty" class="internalDFN"
+data-link-type="dfn">removeProperty(<span class=
+
+data-lt=
+"exposedthing.setpropertyreadhandler()|exposedthing.setpropertyreadhandler|setpropertyreadhandler()|setpropertyreadhandler"
+href="#dom-exposedthing-setpropertyreadhandler" class="internalDFN"
+data-link-type=
+"dfn">setPropertyReadHandler(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-exposedthing-addaction-action"
+data-idl="" data-title="addAction" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+"idlMethName"><a data-no-default="" data-link-for="exposedthing"
+data-lt="addaction()|addAction" href="#dom-exposedthing-addaction"
+class="internalDFN" data-link-type=
+"dfn">addAction<span class=
+"idlParamType"><a href="#dom-thingaction" class="internalDFN"
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, PropertyReadHandler readHandler);
+  "dfn"> <span class=
+"idlParamName">action
+<span class="idlMethod" id="idl-def-exposedthing-removeaction-name"
+data-idl="" data-title="removeAction" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"dfn">ExposedThing 
+"idlMethName">data-lt="removeaction()|removeAction" href=
+"#dom-exposedthing-removeaction" class="internalDFN"
+data-link-type="dfn">removeAction(<span class=
+
+data-lt=
+"exposedthing.setpropertywritehandler()|exposedthing.setpropertywritehandler|setpropertywritehandler()|setpropertywritehandler"
+href="#dom-exposedthing-setpropertywritehandler" class=
+"internalDFN" data-link-type=
+"dfn">setPropertyWriteHandler(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-exposedthing-addevent-event"
+data-idl="" data-title="addEvent" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+"idlMethName"><a data-no-default="" data-link-for="exposedthing"
+data-lt="addevent()|addEvent" href="#dom-exposedthing-addevent"
+class="internalDFN" data-link-type=
+"dfn">addEvent<span class=
+"idlParamType"><a href="#dom-thingevent" class="internalDFN"
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, PropertyWriteHandler writeHandler);
+  "dfn">
+<span class="idlMethod" id="idl-def-exposedthing-removeevent-name"
+data-idl="" data-title="removeEvent" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+"idlMethName"><a data-no-default="" data-link-for="exposedthing"
+data-lt="removeevent()|removeEvent" href=
+"#dom-exposedthing-removeevent" class="internalDFN" data-link-type=
+"dfn">removeEvent<span class=
+"idlParamType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class=
+"idlSectionComment">    // define request handlers
+<span class="idlMethod" id=
+"idl-def-exposedthing-setpropertyreadhandler-name-readhandler"
+data-idl="" data-title="setPropertyReadHandler" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"dfn">ExposedThing 
+"idlMethName">data-lt="setpropertyreadhandler()|setPropertyReadHandler" href=
+"#dom-exposedthing-setpropertyreadhandler" class="internalDFN"
+data-link-type="dfn">setPropertyReadHandler(<span class=
+
+data-lt=
+"exposedthing.removeproperty()|exposedthing.removeproperty|removeproperty()|removeproperty"
+href="#dom-exposedthing-removeproperty" class="internalDFN"
+data-link-type=
+"dfn">removeProperty(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString,
+                                         <span class=
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name);
+  // define Actions
+  
+"internalDFN" data-link-type=
+"dfn">ExposedThing addAction(
+"idlParam">"#dom-propertyreadhandler" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">readHandler
+<span class="idlMethod" id=
+"idl-def-exposedthing-setpropertywritehandler-name-writehandler"
+data-idl="" data-title="setPropertyWriteHandler" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, ActionFragment init, ActionHandler action);
+  
+data-link-type=
+"dfn">ExposedThing 
+"idlMethName">data-lt="setpropertywritehandler()|setPropertyWriteHandler" href=
+"#dom-exposedthing-setpropertywritehandler" class="internalDFN"
+
+data-lt=
+"exposedthing.removeaction()|exposedthing.removeaction|removeaction()|removeaction"
+href="#dom-exposedthing-removeaction" class="internalDFN"
+
+data-link-type=
+"dfn">setPropertyWriteHandler,
+                                          <span class=
+
+"dfn">removeAction(
+"idlParam">"#dom-propertywritehandler" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">writeHandler
+<span class="idlMethod" id=
+"idl-def-exposedthing-setactionhandler-name-action" data-idl=""
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name);
+data-title="setActionHandler" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"exposedthing">
+  
+data-link-type=
+"dfn">ExposedThing 
+"idlMethName">data-lt="setactionhandler()|setActionHandler" href=
+"#dom-exposedthing-setactionhandler" class="internalDFN"
+data-link-type="dfn">setActionHandler(<span class=
+
+data-lt=
+"exposedthing.setactionhandler()|exposedthing.setactionhandler|setactionhandler()|setactionhandler"
+href="#dom-exposedthing-setactionhandler" class="internalDFN"
+data-link-type=
+"dfn">setActionHandler(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a href="#dom-actionhandler"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">action
+};
+<span class="idlCallback" id="idl-def-propertyreadhandler"
+data-idl="" data-title="PropertyReadHandler">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-propertyreadhandler" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise
+<span class="idlCallback" id="idl-def-propertywritehandler"
+data-idl="" data-title="PropertyWriteHandler">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-propertywritehandler" class="internalDFN"
+data-link-type="dfn">
+<span class="idlCallback" id="idl-def-actionhandler" data-idl=""
+data-title="ActionHandler">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, 
+href="#dom-actionhandler" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType"><a href=
+
+"dfn">ActionHandler action);
+  // define Events
+  
+"internalDFN" data-link-type=
+"dfn">ExposedThing addEvent(DOMString name, EventFragment event);
+  
+data-link-type=
+"dfn">ExposedThing removeEvent(DOMString name);
+};
+[NoInterfaceObject]
+interface ExposedEvents {
+  maplike<DOMString, ExposedEvent>;
+};
+callback PropertyReadHandler = Promise<any> ();
+callback PropertyWriteHandler = Promise<void> (any value);
+callback ActionHandler = 
+"https://heycam.github.io/webidl/#idl-promise">
+Promise
+
+<
+
+any
+
+>
+
+(
+
+
+
+any
+
+
+
+parameters
+
+
+);
+
+
+
+5.1 +The +start() +method + +

+Start +serving +external +requests +for +the +Thing +. +5.2 + +The + + +stop() + +properties + + + +method +Stop +serving +external +requests +for +the +Thing +. +5.3 +The + +attribute +represents +a +dictionary +of + + +register() + +ThingProperty + + +method +Generates +the +Thing +Description + + +given + +items +in +which + +the +properties, +Actions + + +read() + +and +Event +defined +for +this +object. +If +a + + +directory + +write() + + +argument +is +given, +make +a +request +to +register + +methods +define +local +methods +that +access + +the +Thing +Description +with + +physical +representations +of + +the +given +WoT +repository +by +invoking +its +register +Action + + +Properties + +. +

+5.4 + +

+The + + +unregister() + +actions + + + +method +If + +attribute +represents + +a +dictionary +of + + +directory + +ThingAction + + +argument +is +given, +make +a +request +to +unregister +the +Thing +Description + + +with + +items +in +which + +the +given +WoT +repository +by +invoking +its + + +unregister + +invoke() + + +Action +. +Then, +and +in +the +case +no +arguments +were +provided + +method +represents +a +local +method + +to +this +function, +stop +the +Thing +and +remove + +invoke + +the +Thing +Description + + +Action + +. +

+5.5 + +

+The + + +emitEvent() + +events + + + +method +Emits +an +the +event +initialized +with +the +event +name +specified +by + +attribute +represents +a +dictionary +of + +ExposedEvent + +items +that +add + +the + +eventName + +emit() + + +argument +and +data +specified +by + +method +to + +the + + +payload + +ThingEvent + + +argument. + +5.6 + + +definition. + +The + + +DataSchema + +ExposedEvents + + + +type +<span class="idlTypedef" id= +"idl-def-dataschema" data-idl="" data-title= +"DataSchema">typedef <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="" data-lt="" href="#dom-dataschema" class= +"internalDFN" data-link-type= +"dfn"> + +interface +represents +a +maplike +dictionary +where +all +values +are + + +DataSchema + +ExposedEvent + + + +objects. +

+ +5.1 + + +; + +The + + +DataSchema + +expose() + + + +method + + +type +represents +a +data +type +specified +in + +

+

+Start +serving +external +requests +for + +the + +Thing +Description + +, +so +that + +WoT +Interactions + + +in +a +serialized +form. + +using + +Properties +, +Action + +s +and + +Event + +s +will +be +possible. + +

+Editor's +note + +

+The + + +DataSchema + +expose() + + +is +under +development, +currently +it +can +denote +any +type +supported +by + +method + +MUST + +run + +the +Thing +Description + +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute + +the +WoT +Runtime + +next +steps + +in +parallel + +. +5.7 +The + +
  2. +
  3. +If +invoking + + +addProperty() + +expose() + + +method +Adds + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  4. +Make + +a +Property +defined +by + +request +to + +the +argument + +underlying +platform +to +attach +protocol +handlers + +and +updates + +start +serving +external +requests +for + +WoT +Interactions + +(read, +write +and +observe + +Properties +, +invoke + +Action + +s +and +manage + +Event + +subscriptions), +based +on + +the +Thing +Description + + +Protocol +Bindings + +. +Throws +on +error. +Returns +a +reference +to + +
  5. +
  6. +If +there +was +an +error +during + +the +same + +request, +reject + +promise + +with +an + +Error + +object +for +supporting +chaining. + + +error + +with + +error.message + +set +to +the +error +code +seen +by +the + +Protocol +Bindings + +and +terminate +these +steps. +
  7. +Otherwise +resolve + +promise + +with + +td + +and +terminate +these +steps. +

+5.7.1 + + +5.2 + + +The + + +ThingProperty + +destroy() + + + +dictionary +<span class="idlDictionary" id= +"idl-def-thingproperty" data-idl="" data-title= +"ThingProperty">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingproperty" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingproperty-name" data-idl="" +data-title="name" data-dfn-for= +"thingproperty"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-name" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingproperty-schema" data-idl= +"" data-title="schema" data-dfn-for= +"thingproperty"> required <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingproperty" +data-lt="" href="#dom-thingproperty-schema" class="internalDFN" +data-link-type="dfn"> +<span class="idlMember" id="idl-def-thingproperty-value" data-idl= +"" data-title="value" data-dfn-for= +"thingproperty"> <a href= +"https://heycam.github.io/webidl/#idl-any">any<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-value" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingproperty-writable" +data-idl="" data-title="writable" data-dfn-for= +"thingproperty"> <a href= +"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-writable" class="internalDFN" data-link-type= +"dfn"> = <span class= +"idlMemberValue">false +<span class="idlMember" id="idl-def-thingproperty-observable" +data-idl="" data-title="observable" data-dfn-for= +"thingproperty"> <a href= +"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-observable" class="internalDFN" data-link-type= +"dfn"> = <span class= +"idlMemberValue">false +}; + +method + + +

+

+Represents + +Stop +serving +external +requests +for + +the + +Thing + +Property +description. + +and +destroy +the +object. +Note +that +eventual +unregistering +should +be +done +before +invoking +this +method. + +

+

+The + +name + +destroy() + + +attribute +represents + +method + +MUST + +run + +the +name +of + +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute + +the +Property + +next +steps + +in +parallel + +. +
  2. +
  3. +The + +If +invoking + + +schema + +destroy() + + +attribute +represents +the +data +type + +is +not +allowed + +for +the +Property +described +by + +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +DataSchema + +SecurityError + + +. + +and +terminate +these +steps. + +
  4. +
  5. +The +value +attribute +represents + +Make +a +request +to + +the +value +of + +underlying +platform +to +stop +serving +external +requests +for + +WoT +Interactions +, +based +on + +the +Property + + +Protocol +Bindings + +. +
  6. +
  7. +The + +If +there +was +an +error +during +the +request, +reject + +promise + +with +an + + +writable + +Error + + +attribute +defines +whether + +object + +error + +with + +error.message + +set +to + +the +Property + +error +code +seen +by +the + +Protocol +Bindings + + +can +be +updated. +The +default +value +is +false +. + +and +terminate +these +steps. + +
  8. +
  9. +The + +Otherwise +resolve + +promise + +with + +td + +and +terminate +these +steps. +

+ +5.3 + +The + + +observable + +addProperty() + + + +attribute +defines +whether +the + +method +

+Adds +a + + +Property + +changes +can +be +observed + +with +name +defined +by +the + +name + +argument, +the +data +schema +provided + +by +the + +property + +argument +of +type + +PropertyFragment +, +and +optionally + +an +external +client. +The +default + +initial + +value +provided +in +the +argument + +initValue + +whose +type +should +match +the +one +defined +in +the + +type + +property +according +to +the + +value-matching +algorithm +. +If + +initValue + +is +not +provided, +it + +SHOULD + +be +initialized +as + + +false + +undefined + +. +Implementations + +SHOULD + +update +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.8 + +5.4 + + +The + + +removeProperty() + + +method + + +

+

+Removes +the + +Property + +specified +by +the + +name + +argument +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.9 + +5.5 + + +The + + +addAction() + + +method + + +

+

+Adds +an +Action + +to +the + +actions + +property +of +a + +Thing + +object +as + +an + +Action + +with +name + +defined +by +the +action + + +name + +argument, +defines +input +and +output +data +format +by +the + +init + +argument +of +type + + +ThingAction + +ActionFragment + + +, +and +adds +the +function +provided +in +the + +action + +argument +as +a +handler, +then + +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+5.9.1 +The +ThingAction +dictionary +<span class="idlDictionary" id= +"idl-def-thingaction" data-idl="" data-title= +"ThingAction">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingaction" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingaction-name" data-idl="" +data-title="name" data-dfn-for= +"thingaction"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingaction" data-lt="" href="#dom-thingaction-name" +class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingaction-inputschema" +data-idl="" data-title="inputSchema" data-dfn-for= +"thingaction"> <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingaction" +data-lt="" href="#dom-thingaction-inputschema" class="internalDFN" +data-link-type="dfn"> +<span class="idlMember" id="idl-def-thingaction-outputschema" +data-idl="" data-title="outputSchema" data-dfn-for= +"thingaction"> <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingaction" +data-lt="" href="#dom-thingaction-outputschema" class="internalDFN" +data-link-type="dfn"> +}; + +

+The +ThingAction + +provided + +action + +callback +function +will +implement +invoking +an + +Action + + +dictionary +describes +the +arguments + +and + +SHOULD + +be +called +by +implementations +when +a +request +for +invoking + +the +return +value. +The +name +attribute +provides +the + + +Action + +name. +The +inputSchema +attribute +provides +the +description +of +the +input +arguments +(argument +list + +is +represented +by +an +object). +If +missing, +it +means + +received +from + +the +action +does +not +accept +arguments. + +underlying +platform. + +The +callback +will +receive +a + + +outputSchema + +parameters + + +attribute +provides + +dictionary +argument +according +to + +the +description + +definition +in +the + +init.input + +argument +and +will +return +a +value + +of +type +defined +by + +the +returned +data. +If +missing, +it +means + + +init.output + +argument +according +to + +the +action +does +not +return +data. + + +value-matching +algorithm +.

+There + +SHOULD + +be +exactly +one +handler +for +any +given + +Action +. +If +no +handler +is +initialized +for +any +given + +Action +, +implementations + +SHOULD + +throw +a + +TypeError +.

+
+
+

+ +5.10 + +5.6 + + +The + + +removeAction() + + +method + + +

+

+Removes +the + +Action + +specified +by +the + +name + +argument +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.11 + +5.7 + + +The + + +addEvent() + + +method + + +

+

+Adds +an +event +to +the +Thing +object +as + +with +name + +defined +by +the + +name + +argument +and +qualifiers +and +initialization +value +provided +by +the + +event + +argument +of +type + + +ThingEvent + +EventFragment + + + +to +the + +Thing + +object + +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+5.11.1 +The +ThingEvent +dictionary +<span class="idlDictionary" id= +"idl-def-thingevent" data-idl="" data-title= +"ThingEvent">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingevent" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingevent-name" data-idl="" +data-title="name" data-dfn-for= +"thingevent"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingevent" data-lt="" href="#dom-thingevent-name" +class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingevent-schema" data-idl="" +data-title="schema" data-dfn-for= +"thingevent"> <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingevent" +data-lt="" href="#dom-thingevent-schema" class="internalDFN" +data-link-type="dfn"> +}; +The +name +attribute +represents +the +event +name. +The +schema +attribute +represents +the +type +of +the +data +that +is +attached +to +the +event. +If +missing, +it +means +the +event +does +not +carry +data. + +
+
+

+5.12 + + +5.8 + + +The + + +removeEvent() + + +method + + +

+

+Removes +the +event +specified +by +the + +name + +argument +and +updates +the + +Thing +Description +. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.13 + +5.9 + + +The + + +PropertyReadHandler + + +callback + + +

+

+A +function +that +returns + +is +called +when +an +external +request +for +reading +a + +Property + +is +received. +It +should +return + +a +Promise +and +resolves +it +with +the +value +of +the + +Property + +matching +the + +name + +argument +to +the + +setPropertyReadHandler + +function, +or +rejects +with +an +error +if +the +property +is +not +found +or +the +value +cannot +be +retrieved. +

+
+
+

+ +5.14 + +5.10 + + +The + + +PropertyWriteHandler + + +callback + + +

+

+A +function +that +is + +called +with + +when +an +external +request +for +writing +a + +Property + +is +received. +It +is +given +the +requested +new + + +value + +as +argument +that +returns + +and +should +return + +a +Promise +which +is +resolved +when +the +value +of +the + +Property + +matching + +that +matches + +the + +name + +argument +to +the +setPropertyReadHandler +function +is + +has +been + +updated +with + +value +, +or +rejects +with +an +error +if +the +property +is +not +found +or +the +value +cannot +be +updated. +

+
+
+ +Editor's +note + +
+

+Note +that +this +function +is +invoked +by +implementations +before +the +property +is +updated, +so +the + +updated +and +it +actually +defines +what +to +do +when +a +write +request +is +received. +The + +code +in +this +callback +function +can +invoke +the + +readProperty() + +read() + + +method +to +find +out +the +old +value +of +the +property, +if +needed. +Therefore +the +old +value +is +not +provided +to +this +method. + +function. + +

+
+
+
+

+ +5.15 + +5.11 + + +The + + +ActionHandler + + +callback + + +

+

+A +function +called +with +a + +parameters + +dictionary +argument +assembled +by +the + +WoT +runtime + +based +on +the + +Thing +Description + +and +the +external +client +request. +It +returns +a +Promise +that +rejects +with +an +error +or +resolves +if +the +action +is +successful +or +ongoing +(may +also +resolve +with +a +control +object +such +as +an + + +Observable + + +for +actions +that +need +progress +notifications +or +that +can +be +canceled). +

+
+
+

+ +5.16 + +5.12 + + +The + + +setPropertyReadHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +readHandler + +as +argument +of +type + + +PropertyReadHandler + +. +Sets +the +handler +function +for +reading +the +specified + +Property + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+

+The + +readHandler + +callback +function +will +implement +reading +a + +Property + +and + +SHOULD + +be +called +by +implementations +when +a +request +for +reading +a + +Property + +is +received +from +the +underlying +platform. +

+

+There + +SHOULD + +be +at +most +one +handler +for +any +given + +Property + +and +newly +added +handlers +replace +the +old +handlers. +If +no +handler +is +initialized +for +any +given + +Property +, +implementations + +SHOULD + +implement +a +default +property +read +handler. +

+

+When +an +external +request +for +reading + +Property + +propertyName + +is +received, +the +runtime + +SHOULD + +execute +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +a + +Property + +with + +propertyName + +does +not +exist, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  3. +Otherwise, +if +no +read +handler +has +been +defined +for + +propertyName +, +resolve + +promise + +with +the +value +of +the + +Property + +named + +propertyName + +provided +by +the +runtime +implementation +and +terminate +these +steps. +
  4. +Otherwise, +invoke +the +read +handler +associated +with + +propertyName +. +If +it +rejects, +then +reject + +promise + +with +the +same +error, +and +resolve + +promise + +with +the +same +value. +
+
+
+

+ +5.17 + +5.13 + + +The + + +setPropertyWriteHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +writeHandler + +as +argument +of +type + + +PropertyWriteHandler + +. +Sets +the +handler +function +for +writing +the +specified + +Property + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+

+There + +SHOULD + +be +at +most +one +write +handler +for +any +given + +Property + +and +newly +added +handlers +replace +the +old +handlers. +If +no +write +handler +is +initialized +for +any +given + +Property +, +implementations + +SHOULD + +implement +default +property +update +and +notifying +observers +on +change. +

+

+When +an +external +request +for +writing +a + +Property + +propertyName + +with +a +new +value + +value + +is +received, +the +runtime + +SHOULD + +execute +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +a + +Property + +with + +propertyName + +does +not +exist, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  3. +Otherwise, +if +no +write +handler +has +been +defined +for + +propertyName +, +the +runtime +implementation + +SHOULD + +update +the + +Property + +value +with + +value +, +resolve + +promise + +and +terminate +these +steps. +
  4. +Otherwise, +invoke +the +write +handler +associated +with + +propertyName + +providing + +value + +as +argument. +If +it +rejects, +then +reject + +promise + +with +the +same +error, +and +resolve + +promise + +with +the +same +value. +
+
+
+

+ +5.18 + +5.14 + + +The + + +setActionHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +action + +as +argument +of +type + + +ActionHandler + +. +Sets +the +handler +function +for +the +specified + +Action + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+

+If +provided, +this + +The + +action + +callback +function +will +implement +invoking + +an + +Action + +and + +SHOULD + +be +called +by +implementations +when +a +request +for +invoking +a + +the + +Action + +is +received +from +the +underlying +platform. +The +callback +will +receive +a +parameters +dictionary +argument. + +

+

+There + +SHOULD + +be +exactly + +at +most + +one +handler +for +any +given + +Action + +and +newly +added +handlers +replace +the +old +handlers. +

+When +an +external +request +for +invoking +the + +Action + +identified +by + +name + +is +received, +the +runtime + +SHOULD + +execute +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel + +. +
  2. +
  3. +If +an + +Action + +identified +by + +name + +does +not +exist, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  4. +Otherwise, +if + +no +action + +handler +is +initialized + +has +been +defined + +for +any +given + + +name +, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  5. +Otherwise, +invoke +the + + +Action +, +implementations +SHOULD +return + + +handler +associated +with + +name +. +If +it +rejects +with + +error +, +then +reject + +promise + +with +the +same + +error +, +otherwise + +if +it +resolves +with + +value +, +then +resolve + +promise + +with + +the +action +is +invoked +by +any +client. + +same + +value +.
+
+
+

+ +5.19 + +5.15 + + +Examples + + +

+

+Below +some + + + +ExposedThing + + + +interface +examples +are +given. +

+
+
+ +Example +7 + +5 + +: + +: +Create +a +new +blank + +exposed +Thing +with +a +simple +property + + +
+
+        try {
+  "hljs-keyword">var thing = WoT.produce({ <span class=
+"hljs-attr">name: <span class=
+"hljs-string">"tempSensor" });
+  
+  thing.addProperty({
+    : <span class=
+"hljs-string">"temperature",
+    : <span class=
+"hljs-number">0.0,
+    : <span class=
+"hljs-string">'{ "type": "number" }'
+    <span class=
+"hljs-comment">// use default values for the rest
+  }).addProperty({
+    : <span class=
+"hljs-string">"max",
+    : <span class=
+"hljs-number">0.0,
+    : <span class=
+"hljs-string">'{ "type": "number" }'
+    <span class=
+"hljs-comment">// use default values for the rest
+  }).addAction({
+    : <span class=
+"hljs-string">"reset",
+    
+  }).addEvent({
+
+"hljs-keyword">var temperatureValueDefinition = {
+    type: 
+"hljs-string">"number",
+    minimum: 
+"hljs-number">-50,
+    maximum: 
+"hljs-number">10000
+  };
+  
+"hljs-keyword">var temperaturePropertyDefinition = temperatureValueDefinition;
+  // add the 'forms' property
+  temperaturePropertyDefinition.forms = [ ... ];
+  var thing = WoT.produce({
+    name: "hljs-string">"onchange",
+    : <span class=
+"hljs-string">'{ "type": "number" }'
+  });
+  
+  thing.setActionHandler(<span class=
+"hljs-string">"reset", () => {
+    .log(<span class=
+"hljs-string">"Resetting maximum");
+    thing.writeProperty(<span class=
+"hljs-string">"max");
+  });
+  thing.start().then(<span class=
+"hljs-params">() {
+      thing.register();
+
+"hljs-string">"tempSensor",
+    properties: {      
+"hljs-attr">temperature: temperaturePropertyDefinition
+    },
+    actions: {      reset: {        description: 
+"hljs-string">"Reset the temperature sensor",
+        input: {          
+"hljs-attr">temperature: temperatureValueDefinition
+        },
+        output: 
+"hljs-literal">null,
+        forms: []
+      },
+    },
+    events: {      
+"hljs-attr">onchange: temperatureValueDefinition
+    },
+    links: []
+  });
+  await thing.expose();
+  await wot.register("hljs-string">"https://mydirectory.org", thing);
+
+  // define Thing business logic
+  setInterval( async () => {
+    let mock = Math.random()*100;
+    thing.writeProperty(<span class=
+"hljs-string">"temperature", mock);
+
+    let old = "hljs-keyword">await thing.readProperty(<span class=
+"hljs-string">"max");
+
+"hljs-keyword">await thing["temperature"].read();
+
+    if (old < mock) {
+      thing.writeProperty(<span class=
+"hljs-string">"max", mock);
+      thing.emitEvent();
+
+      await thing["hljs-string">"temperature"].write(mock);
+      thing.emitEvent("onchange", mock);
+
+    }
+  }, 1000);
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+
+ +Example +8 + +6 +: +Create +a +new +exposed +Thing +with +object +property + + +: + +
+
+        try {
+  var statusValueDefinition = {
+    type: "hljs-string">"object",
+    properties: {      brightness: {        type: 
+"hljs-string">"number",
+        minimum: 
+"hljs-number">0.0,
+        maximum: 
+"hljs-number">100.0,
+        required: 
+"hljs-literal">true
+      },
+      rgb: {        type: 
+"hljs-string">"array",
+        "minItems": 
+"hljs-number">3,
+        "maxItems": 
+"hljs-number">3,
+        items : {            "type" : 
+"hljs-string">"number",
+            
+"hljs-string">"minimum": 0,
+            
+"hljs-string">"maximum": 255
+        }
+      }
+  };
+  
+"hljs-keyword">var statusPropertyDefinition = statusValueDefinition;
+  // add the 'forms' property
+  statusPropertyDefinition["forms"] = [];
+  var thing = WoT.produce({    name: 
+"hljs-string">"mySensor",
+    properties: {      brightness: {        type: 
+"hljs-string">"number",
+        minimum: 
+"hljs-number">0.0,
+        maximum: 
+"hljs-number">100.0,
+        required: 
+"hljs-literal">true,
+      },
+      
+"hljs-attr">status: statusPropertyDefinition
+    },
+    actions: {      status: {        description: 
+"hljs-string">"Get status object",
+        input: 
+"hljs-literal">null,
+        output: {          
+"hljs-attr">status : statusValueDefinition;
+        },
+        forms: []
+      },
+    },
+    events: {      
+"hljs-attr">onstatuschange: statusValueDefinition;
+    },
+    links: []
+  });
+  thing.expose().then(() => {
+      thing.register();
+  });
+} catch (err) {
+   console.log(
+"hljs-string">"Error creating ExposedThing: " + err);
+}
+
+Example +7 +: +Create +a +new +exposed +Thing +from +a +Thing +Description + +
+
+        let thingDescription = "hljs-string">'{ "@context": [ "https://w3c.github.io/wot/w3c-wot-td-context.jsonld", "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ], "@type": [ "Thing", "Sensor" ], "name": "mySensor", "geo:location": "testspace", "interaction": [ { "@type": [ "Property", "Temperature" ], "name": "prop1", "schema": { "type": "number" }, "saref:TemperatureUnit": "degree_Celsius" } ] }';
+
+"hljs-string">'{ \
+  "name": "mySensor", \
+  "@context": [ "http://www.w3.org/ns/td",\
+     "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ],\
+  "@type": [ "Thing", "Sensor" ], \
+  "geo:location": "testspace", \
+  "properties": { \
+    "prop1": { \
+      "type": "number",\
+      "@type": [ "Property", "Temperature" ], \
+      "saref:TemperatureUnit": "degree_Celsius" \
+  } } }';
+
+try {
+  // note that produce() fails if thingDescription contains error
+  let thing = WoT.produce(thingDescription);
+  // Interactions were added from TD
+  // WoT adds generic handler for reading any property
+  // define a specific handler for one property
+  let name = "examplePropertyName";
+  thing.setPropertyReadHandler(name, () => {
+    console.log("Handling read request for " + name);
+    return new Promise((resolve, reject) => {
+        let examplePropertyValue = 5;
+        resolve(examplePropertyValue);
+      },
+      e => {
+        console.log("Error");
+      });
+  });
+  thing.start();
+
+  thing.expose();
+
+} catch(err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+
+ +Example +9 + +8 + +: + +: +Create +a +new +exposed +Thing +from +a +TD +URI + +
+
+        // fetch an external TD, e.g., to set up a proxy for that Thing
+WoT.fetch("http://myservice.org/mySensor/description").then(td => {
+  // WoT.produce() ignores instance-specific metadata (security, form)
+  let thing = WoT.produce(td);
+  // Interactions were added from TD
+  // add server functionality
+  // ...
+});
+
+
+
+
+
+

+ +6. + +Experimental +extensions +to +the +ConsumedThing +interface + +Data +types +and +structures + +

+

+The +[ + +This +section +is +non-normative. + + +WOT-TD + + +] +specification +defines +the + +WoT +information +model +, +i.e. +the +data +types +and +data +structures +used +in + +WoT +Interactions +. +In +this +API +these +definitions +translate +to +dictionary +objects +that +are +extended +with +methods +by +the +interfaces +defined +in +this +specification. + +

+

+In +order +to +avoid +duplication +of +definitions, +references +to +these +data +types +and +structures +is +defined +in +this +section, +but +for +their +full +description +please +refer +to +the + +Thing +Description +specification +.

+6.1 + +The + + +ThingDescription + +DataSchema + + + +dictionary +and +its +subclasses + + +related +functionality, +such +as +enumerating + +

+

+Value +types +basically +represent +types +that +may +be +used +in + +JSON + +object +definitions +and +are +used +in + +ThingFragment + +to +define + +Properties +, +Action +s, + + +Event + +s +and +links +(introspection) + + +Action + +parameters. +Value +types +are +represented +as +dictionary +objects +whose +properties +and +possible +sub-classes +are +defined +in +the + +DataSchema + +section +of +[ + +WOT-TD + +]. +

+One +property +of +all + +DataSchema + +dictionary + +is +an +API +extension +that + +the + +type + +property +whose +value + +is +out + +from +a +set + +of +scope +for + +enumerated +strings +defined +in +the + +DataSchema + +section +of +[ + +WOT-TD + +] +and +is +referred +as + +DataType + +in + +this +specification. +However, + +

+

+Based +on + +type +, +the +draft +interfaces + +following +sub-classes +of + +DataSchema + +are +defined +here +for +informative +purposes. +<span class="idlInterface" id= +"idl-def-consumedthing-partial-1" data-idl="" data-title= +"ConsumedThing">partial interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-consumedthing" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMethod" id="idl-def-consumedthing-getproperties" +data-idl="" data-title="getProperties" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-thingproperty" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getproperties()|getProperties" href= +"#dom-consumedthing-getproperties" class="internalDFN" +data-link-type="dfn">getProperties +<span class="idlMethod" id="idl-def-consumedthing-getactions" +data-idl="" data-title="getActions" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-thingaction" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getactions()|getActions" href= +"#dom-consumedthing-getactions" class="internalDFN" data-link-type= +"dfn">getActions +<span class="idlMethod" id="idl-def-consumedthing-getevents" +data-idl="" data-title="getEvents" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-thingevent" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getevents()|getEvents" href="#dom-consumedthing-getevents" +class="internalDFN" data-link-type= +"dfn">getEvents +<span class="idlMethod" id="idl-def-consumedthing-getlinks" +data-idl="" data-title="getLinks" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-tdlink" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getlinks()|getLinks" href="#dom-consumedthing-getlinks" +class="internalDFN" data-link-type= +"dfn">getLinks +}; + +in +[ + + +WOT-TD + + +]: + +BooleanSchema + +6.1 + +, + + +NumberSchema +, +IntegerSchema +, +StringSchema +, +ObjectSchema +, +ArraySchema +.

+6.2 + + +The + + +getProperties() + +SecurityScheme + + + +method + +dictionary +and +its +subclasses + +

+

+Returns +the +list +of +Properties + +Security +metadata +is +represented +as +dictionary +objects +whose +properties +and +sub-classes +are + +defined +in +the +Thing +Description + + +SecurityScheme + + +section +of +[ + +WOT-TD + +]. +

+One +property + +of +the +Thing + + + +SecurityScheme + + +dictionary +is +the + +scheme + +property +whose +value +is +from +a +set +of +enumerated +strings +defined + +in +the +form + + +SecurityScheme + +section + +of +a +list + +[ + +WOT-TD + +]. +Based +on + +type +, +multiple +subclasses + +of + + +ThingProperty + +SecurityScheme + + + +objects. + +are +defined. + +

+
+

+6.4 + +The + +Form + +dictionary +

+Represents +metadata +describing +service +details, +with +properties + +defined +in +the +Thing +Description + + +Form + + +section + +of +[ + +WOT-TD + +]. +

+6.5 + +The + +InteractionFragment + +dictionary +

+Represents + +the +Thing + +common +properties +of + +WoT +Interactions +, +one +of + +Property +, +Action + + +or + +Event +, +as +defined + +in +the +form + + +InteractionPattern + +section + +of +[ + +WOT-TD + +]. +Its +subclasses +are +referred +as + +PropertyFragment +, +ActionFragment + +and + +EventFragment +.

+6.6 + +The + +PropertyFragment + +dictionary +

+Represents +the + +Property + +interaction +data +that +initializes + +a +list + + + +ThingProperty + +object. +Its +properties +are +defined +in +the + +Property + +and + +InteractionPattern + +sections + +of +[ + +WOT-TD + +]. +

+6.7 + +The + +ActionFragment + +dictionary +

+Represents +the + +Action + +interaction +data +that +initializes +a + + + +ThingAction + + +objects. + +object. +Its +properties +are +defined +in +the + +Action + +and + +InteractionPattern + +sections +of +[ + +WOT-TD + +]. + +

+
+
+

+6.3 + + +6.8 + + +The + + +getEvents() + +EventFragment + + + +method + +dictionary + +

+

+Returns + +Represents + +the +list +of + + +Event + +s + +interaction +data +that +initializes +a + +ThingEvent + +object. +Its +properties +are + +defined +in +the +Thing +Description + + +Event + + +section + +of +the + +[ + +WOT-TD + +]. +

+6.9 + +The + +ThingFragment + +dictionary +

+The + +ThingFragment + +dictionary +is +defined +as + +Thing + + +in +the +form +of + +[ + +WOT-TD + +]. +It +is + +a +list + +dictionary +that +contains +properties +representing +semantic +metadata +and +interactions +( + +Properties +, +Action + +s +and + +Event + +s). +It +is +used +for +initializing +an +internal +representation + +of +a + +Thing +Description + +and +its +properties +may +be +used +in + + +ThingEvent + +ThingFilter + + +objects. + +. +

+
+
+

+6.4 + + +6.10 + + +The + + +getLinks() + +ThingDescription + + + +method + +type + +

+

+Returns +the +list + +Serialized +representation + +of +linked +resources +in + +the + + +Thing +Description + +(a + +JSON-LD + +document). +

+Note +

+In +this +version + +of +the +API, + +Thing +Description + +s +are +represented +as +an +opaque + +USVString + +that +can +be +transmitted +between +devices. +

+7. + +Interfaces +for + +WoT +Interactions + + + + +

+

+The +data +types +and +structures +imported +from +[ + +WOT-TD + +] +are +extended +by +this +specification + +in +order +to +provide + +the +form +of +a +list +of + +interfaces +for + +WoT +Interactions +.

+Every + +Thing + +describes +its +metadata +as +defined +in + + +TDLink + +ThingFragment + + +, +and +basic +interactions +defined +as + +Properties +, +Action + + +objects. + +s +and + +Event + +s. +The +following +interfaces +are +used +for +representing +these +interactions. + +

+
+

+ +6.4.1 + +7.1 + + +The + + +TDLink + +Interaction + + + +dictionary + +interface +

+

+Contains +a +hyperlink +reference, +a +relation +type + +The + +Interaction + +interface +is +an +abstract +class +to +represent + +Thing + +interactions: + +Properties +, +Actions + +and + +Events +.

+The + +InteractionFragment + +dictionary +holds +the +common +properties +of + +PropertyFragment +, +ActionFragment + +and + +EventFragment + +dictionaries +used +for +initializing + +ThingProperty +, +ThingAction + +and + +ThingEvent + +objects +in + +a +media +type. + + + +ThingFragment + +dictionary +used +for +creating +an + +ExposedThing + +object. + +

+
+<span class="idlDictionary" id= +"idl-def-tdlink" data-idl="" data-title= +"TDLink">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-tdlink" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-tdlink-href" data-idl="" +data-title="href" data-dfn-for="tdlink"> required <span class= +"idlMemberType"><a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="tdlink" data-lt="" href="#dom-tdlink-href" class= +"internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-tdlink-mediatype" data-idl="" +data-title="mediaType" data-dfn-for= +"tdlink"> <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="tdlink" data-lt="" href="#dom-tdlink-mediatype" + +
"idl-def-interaction" data-idl="" data-title=
+"Interaction">interface Interaction {
+  readonly attribute (Form or FrozenArray<Form>) 
+class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMember" id="idl-def-tdlink-rel" data-idl=""
+data-title="rel" data-dfn-for="tdlink">             <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default=""
+data-link-for="tdlink" data-lt="" href="#dom-tdlink-rel" class=
+"internalDFN" data-link-type=
+"dfn">
+};
+
+"dfn">forms;
+};
+
+"dfn">Interaction includes 
+
+InteractionFragment
+
+;
+
+
+
+
+

+The + + +TDLink + +forms + +read-only +property +represents +the +protocol +bindings +initialization +data +and +is +initialized +by +the + +WoT +Runtime +.

+7.2 + +The + +ThingProperty + +interface +

+The + +ThingProperty + +interface +is +used +in + +ConsumedThing + +and + +ExposedThing + +objects +to +represent + +Thing + +Property + +interactions. +

+The + +PropertyFragment + + + +dictionary +contains + +is +used +for +initializing + +Property + +objects +in +a + +ThingFragment + +dictionary +used +for +creating +an + +ExposedThing + +object. +It + +MUST + +implement +one +of + +the +following +properties: + + + +DataSchema + +dictionaries. + +

+
+
"idl-def-thingproperty" data-idl="" data-title=
+"ThingProperty">interface ThingProperty : Interaction {
+  // getter for PropertyFragment properties
+  getter 
+"https://heycam.github.io/webidl/#idl-any">any (DOMString name);
+  // get and set interface for the Property
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> read();
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> write(any value);
+};
+
+"dfn">ThingProperty includes PropertyFragment;
+
+"dfn">ThingProperty includes 
+
+Observable
+
+;
+

+The + + +href + +ThingProperty + + + +interface +contains +all +the +properties +defined +on + +PropertyFragment + +as +read-only +properties. +

+The + +type + + +attribute + +read-only +property + +represents +the +type +definition +for +the + +Property + +as + +a +hyperlink +reference + + + +DataSchema + +dictionary +object. +

+The + +writable + +read-only +property +tells +whether +the + +Property + +value +can +be +updated. +If +it +is + +false +, +then +the + +set(value) + +method + +SHOULD + +always +reject. +

+The + +observable + +read-only +property +tells +whether +the + +Property + +supports +subscribing +to +value +change +notifications. +If +it +is + +false +, +then +the + +subscribe() + +method + +SHOULD + +always +fail. +

+The + +constant + +read-only +property +- +defined +in + +DataSchema + +- +tells +whether +the + +Property + +value +is +a +constant. +If + +true +, +the + +set() + +and + +subscribe() + +methods + +SHOULD + +always +fail. +

+The + +required + +read-only +property +- +defined +in + +DataSchema + +- +tells +whether +the + +Property + +should +be +always +present +on +the + +ExposedThing + +object. +

+The + +read() + +method +will +fetch +the +value +of +the + +Property + +. +Returns +a + +Promise + +that +resolves +with +the +value, +or +rejects +with +an +error. +

+The + + +rel + +write() + + + +attribute +represents + +method +will +attempt +to +set +the +value +of +the + +Property + +specified +in +the + +value + +argument +whose +type + +SHOULD + +match +the +one +specified +by +the + +type + +property. +Returns + +a +relation + + +Promise + +that +resolves +on +success, +or +rejects +on +an +error. +

+7.3 + +The + +ThingAction + +interface +


+"idl-def-thingaction" data-idl="" data-title=
+"ThingAction">interface ThingAction : Interaction {
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> invoke(optional any inputValue);
+};
+
+"dfn">ThingAction includes 
+
+ActionFragment
+
+;
+

+The + +invoke() + +method +when +invoked, +starts +the + +Action + +interaction +with +the +input +value +provided +by +the + +inputValue + +argument. +If + +inputValue + +is + +null +, +the +action +does +not +take +any +arguments +and +rejects +if +any +arguments +are +provided. +If +the +value +is + +undefined +, +the +action +will +ignore +any +arguments +provided. +Otherwise +the + +type +of + +inputValue + +SHOULD + +match +the + +DataSchema + +definition +in +the + +input + +property. +Returns +a + +Promise + +that +will +reject +with +an +error +or +will +resolve +with +a +value +of +type +defined +by +the + +output + +property. +

+7.4 + +The + +ThingEvent + +interface +


+"idl-def-thingevent" data-idl="" data-title=
+"ThingEvent">interface ThingEvent : Interaction {
+};
+
+"dfn">ThingEvent includes EventFragment;
+
+"dfn">ThingEvent includes 
+
+ThingProperty
+
+;
+

+Since + +ThingEvent + +implements + +Observable + +through +the + +ThingProperty + +interface, +event +subscription +is +done +by +invoking +the + +subscribe() + +method +on +the +event +object +that +returns +a +cancelable + +Subscription + +. +

+
+
+

+ +7.5 + +The + + +mediaType + +ExposedEvent + + + +attribute +represents + +interface +


+"idl-def-exposedevent" data-idl="" data-title=
+"ExposedEvent">interface ExposedEvent : ThingEvent {
+  void emit(any payload);
+};
+

+7.5.1 + +The + +emit() + +method +

+Emits +an +event +that +carries +data +specified +by +the + +payload + +argument. +

+7.6 + +The + +value-matching +algorithm +

+The +value-matching +algorithm +is +applied +to + +a +IANA +media + + +value + +input +in +relation +to +a + +valueType + +property +of + +type +. +For +TD + + + +DataSchema +, +for +instance +the + +value + +and + +type + +properties +of +a + +PropertyFragment + + +s +there +will +be +registered +media +types, +so +applications +will +be +able + +object, +or +the + +inputValue + +parameter + +to +check +whether +an + +the + + +href + +invoke() + + +link +points + +method +of +a + +ThingAction + +object +in +relation + +to +the +same +object. +It +executes +the +following +steps: +

  1. +If + +valueType.type + +is +not +defined, +or +does +not +fully +match + +a +TD + +string +enumerated +in + +DataType + +, +i.e. +whether + +return + +false +.
  2. +Otherwise, +if + +valueType.type + +is + +"null" +: +if + +value + +is + +null +, +return + +true +, +otherwise +return + +false +.
  3. +Otherwise, +if + +valueType.type + +is + +"boolean" +: +if + +value + +is +either + +true + +or + +false +, +then +return + +true +, +otherwise +return + +false +.
  4. +Otherwise, +if + +valueType.type + +is + +"integer" +: +if + +value + +is +not +an +integer +type +defined +by + +the +link + +underlying +platform +(such +as + +long + +or + +long +long + +), +then +return + +false +, +otherwise +execute +the +following +sub-steps: +
    1. +If + +valueType.minimum + +is +fetcheable +with + +defined +and + +value + +is +not +greater +or +equal +than +that +value, +return + +false +.
    2. +If + +valueType.maximum + +is +defined +and + +value + +is +not +less +or +equal +than +that +value, +return + +false +.
    3. +Return + +true +.
  5. +Otherwise, +if + +valueType.type + +is + +"number" +, +if + +value + +is +not +an +integer +or +floating +point +type +defined +by +the +underlying +platform +(such +as + +long + +or + +long +long + +or + +double + +), +then +return + +false +, +otherwise +otherwise +execute +the +following +sub-steps: +
    1. +If + +valueType.minimum + +is +defined +and + +value + +is +not +greater +or +equal +than +that +value, +return + +false +.
    2. +If + +valueType.maximum + +is +defined +and + +value + +is +not +less +or +equal +than +that +value, +return + +false +.
    3. +Return + +true +.
  6. +Otherwise, +if + +valueType.type + +is + +"string" +: +if + +value + +is +not +a +string +type +defined +by +the +underlying +platform, +then +return + +false +, +otherwise +return + +true +. +In + +this +API. + +case +the +algorithm +expects +a +third +parameter + +valueType.enum + +and +runs +the +following +sub-steps: +
    • +If + +valueType.enum + +is +an +array +of +strings, +then +if + +value + +fully +matches +one +of +the +strings +defined +in +the +array, +return + +true +.
    • +Otherwise, +return + +false +. +
    • +
    +
  7. +
  8. +Otherwise, +if + +valueType.type + +is + +"array" +, +execute +the +following +sub-steps: +
    1. +If + +value + +is +not +an +array, +return + +false +.
    2. +If + +valueType.minItems + +is +defined, +and + +value + +does +not +contain +at +least + +valueType.minItems + +elements, +return + +false +.
    3. +If + +valueType.maxItems + +is +defined, +and + +value + +contains +more +than + +valueType.maxItems + +elements, +return + +false +.
    4. +Otherwise, +if + +valueType.items + +is + +undefined +, +return + +false +.
    5. +Otherwise, +if + +valueType.items + +is + +null +, +return + +true + +(i.e. +any +type +is +accepted +as +array +element, +including +heterogenous +arrays). +
    6. +Otherwise, +for +each +element +of +the +array + +value + +run +the + +value-matching +algorithm + +against +the + +valueType.items + +object. +If +any +of +these +runs +returns + +false +, +then +return + +false +.
    7. +Otherwise, +return + +true +.
  9. +Otherwise, +if + +type + +is + +"object" +, +execute +the +following +sub-steps: +
    1. +If + +value + +is +not +an + +Object +, +return + +false +.
    2. +If + +valueType.properties + +is +not +defined, +return + +false +.
    3. +If + +valueType.properties + +is + +null +, +return + +true + +(i.e. +accept +any +object +value). +
    4. +For +each +string +in +the + +valueType.required + +array, +if +it +does +not +match +a +property +name +in +the + +value.properties + +object +or +in +the + +value + +object, +then +return + +false +.
    5. +For +each +property +with +name + +propName + +and +value + +propDataSchema + +found +in + +valueType.properties +, +run +the +following +sub-steps: +
      1. +If +the +result +of +applying +the + +value-matching +algorithm + +on +the +value + +value[propName] + +and + +propDataSchema + +is + +false +, +then +return + +false +.
    6. +Return + +true +.
+
+
+
+

+ +7. + +8. + + +Observables + + +

+

+ +This +section +is +non-normative. + +

+

+ +Observables + +are + +proposed + +to +be +included +in +ECMAScript +and +are +used +for +handling +pushed +data +associated +with +various +possible +sources, +for +instance +events, +timers, +streams, +etc. +A +minimal +required +implementation +is +described +here. +

+
+
+ +Editor's +note + +
+

+This +section +is +informal +and +contains +rather +laconic +information +for +implementations +on +what +to +support +for +interoperability. +

+
+
+
interface "dfn"> {
+<span class="idlMethod" id=
+"idl-def-observable-subscribe-next-error-complete" data-idl=""
+data-title="subscribe" data-dfn-for="observable">    <span class=
+"idlMethType"><a href="#dom-subscription" class="internalDFN"
+
+"dfn">Observable {
+  Subscription subscribe("idlParam">(<a href="#dom-observer"
+class="internalDFN" data-link-type=
+"dfn"> or <a href="#dom-onnext" class=
+
+"idlParam">EventHandler handler,
+                         optional ErrorHandler errorHandler,
+                         optional 
+"internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">next,
+                           <span class=
+"idlParam">optional <a href=
+"#dom-onerror" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">error,
+                           <span class=
+"idlParam">optional <a href=
+"#dom-oncomplete" class="internalDFN" data-link-type=
+
+"dfn">OnComplete "idlParamName">complete
+};
+<span class="idlInterface" id="idl-def-subscription" data-idl=""
+data-title="Subscription">interface <span class=
+"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-subscription" class="internalDFN" data-link-type=
+"dfn"> {
+<span class="idlMethod" id="idl-def-subscription-unsubscribe"
+data-idl="" data-title="unsubscribe" data-dfn-for=
+"subscription">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="subscription"
+data-lt="unsubscribe|unsubscribe()" href=
+"#dom-subscription-unsubscribe" class="internalDFN" data-link-type=
+"dfn">
+<span class="idlAttribute" id="idl-def-subscription-closed"
+data-idl="" data-title="closed" data-dfn-for=
+"subscription">    readonly attribute <span class=
+"idlAttrType"><a href=
+
+"idlParamName">onComplete);
+};
+interface Subscription {
+  void unsubscribe();
+  readonly attribute 
+"https://heycam.github.io/webidl/#idl-boolean">boolean data-link-for="subscription" data-lt="" href=
+"#dom-subscription-closed" class="internalDFN" data-link-type=
+
+data-link-for="subscription" data-lt="subscription.closed|closed"
+href="#dom-subscription-closed" class="internalDFN" data-link-type=
+
+"dfn">closed;
+};
+<span class="idlInterface" id="idl-def-observer" data-idl=""
+data-title="Observer">interface <span class=
+"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-observer" class="internalDFN" data-link-type=
+"dfn"> {
+<span class="idlMethod" id="idl-def-observer-next-value" data-idl=
+"" data-title="next" data-dfn-for="observer">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="observer"
+data-lt="next()|next" href="#dom-observer-next" class="internalDFN"
+data-link-type="dfn">next(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-any">any
+<span class="idlMethod" id="idl-def-observer-error-error" data-idl=
+"" data-title="error" data-dfn-for="observer">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="observer"
+data-lt="error()|error" href="#dom-observer-error" class=
+"internalDFN" data-link-type="dfn">error(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-Error">Error
+<span class="idlMethod" id="idl-def-observer-complete" data-idl=""
+data-title="complete" data-dfn-for="observer">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="observer"
+data-lt="complete()|complete" href="#dom-observer-complete" class=
+"internalDFN" data-link-type="dfn">complete
+};
+<span class="idlCallback" id="idl-def-onnext" data-idl=""
+data-title="OnNext">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-onnext" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType">void<span class=
+
+};
+callback EventHandler = void (
+"idlParamType">"https://heycam.github.io/webidl/#idl-any">any
+<span class="idlCallback" id="idl-def-onerror" data-idl=""
+data-title="OnError">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-onerror" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType">void<span class=
+
+"https://heycam.github.io/webidl/#idl-any">any value);
+callback ErrorHandler = void (
+"idlParamType">"https://heycam.github.io/webidl/#idl-Error">Error
+<span class="idlCallback" id="idl-def-oncomplete" data-idl=""
+data-title="OnComplete">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-oncomplete" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+
+"https://heycam.github.io/webidl/#idl-Error">Error error);
+callback OnComplete =
+"idlCallbackType">
+void
+
+();
+
+
+
+7.1 +The +Observer +interface + +

+The +Observer +interface +defines +the + +following + +callbacks +needed + +can +be +provided +when +subscribing + +to +handle + +an + + +Observable + +: +

+ +
+

+ +7.2 + +8.1 + + +The + + +Subscription + + +interface + + +

+

+Contains +the + + +closed + + +property +of +type + +boolean + +that +tells +if +the +subscription +is +closed +or +active. +

+

+Also, +contains +the + + +unsubscribe + + +() +method +that +cancels +the +subscription, +i.e. +makes +a +request +to +the +underlying +platform +to +stop +receiving +data +from +the +source, +and +sets +the + +closed + +property +to + +false +. +

+
+
+

+ +7.3 + +8.2 + + +The + + +Observable + + +interface + + +

+

+The + + +Observable + + +interface +enabled +subscribing +to +pushed +data +notifications +by +the + + +subscribe + + +() +method: +

+ +
+
+
+

+ +8. + +9. + + +Security +and +Privacy + +Editor's +note + + +Please +see + +

+

+In +general + +the +security +measures +taken +to +protect +a + +WoT +Security + +system +will +depend +on +the +threats + +and +Privacy +repository + +attackers +that +system +may +face +and +the +value +of +the +assets +needs +to +protect. +A +detailed +discussion +of +security +and +privacy +considerations + +for +work +in +progress +regarding + +the +Web +of +Things, +including +a + +threat +models, +assets, +risks, +recommended +mitigations, + +model +that +can +be +adapted +to +various +circumstances, +is +presented +in +the +informative +document +[ + +WOT-SECURITY-CONSIDERATIONS + +]. +This +section +includes +only +normative +recommendations +relevant +to +the +WoT +Thing +Description. +

+When +designing +new +devices + +and +services +for +use +with +the +WoT, +we +have +documented +a +set +of + +best +practices +for + +in +[ + +WOT-SECURITY-BEST-PRACTICES + +] +that + +SHOULD + +be +followed. + +This +best-practices +document +may +be +updated +as + +security +measures +evolve. +Following +these +practices +does +not +guarantee +security, +but +it +at +least +will +help +to +avoid +common +known +vulnerabilities + +and +privacy +for +systems + +pitfalls. +

+Below +are +specific +recommendations +related +to +WoT +runtime +implementations: +

+Some +additional +specific +recommendations +relevant +for +WoT +script +developers: + +

+ +
+
+

+ +9. + +10. + + +Terminology +and +conventions + + +

+

+The +generic +WoT +terminology +is +defined +in +[ + + +WOT-ARCHITECTURE + + +]: + +Thing +, + +Thing +Description + +(in +short + +TD + +), + +Web +of +Things + +(in +short + + +WoT + + +), + +WoT +Interface +, + +Protocol +Bindings +, + +WoT +Runtime +, + +Consuming +a +Thing +Description +, + +Thing +Directory +, + +WoT +Interactions +, + +Property +, + +Action +, + +Event + +etc. +

+

+ +JSON-LD + +is +defined +in +[ + + +JSON-LD + + +] +as +a +JSON +document +that +is +augmented +with +support +for +Linked +Data +by +providing +a +@context +property +with +a +defining +URI +. + +Data. + +

+

+The +terms + + +URL + + +and + + +URL +path + + +are +defined +in +[ + + +URL + + +]. +

+

+The +following +terms +are +defined +in +[ + + +HTML52 + + +] +and +are +used +in +the +context +of +browser +implementations: + + +browsing +context + +, + + +top-level +browsing +context + +, + + +global +object + +, + + +incumbent +settings +object + +, + + +Document + +, + + +document +base +URL + +, + + +Window + +, + + +WindowProxy + +, + + +origin + +, + + +ASCII +serialized +origin + +, +executing +algorithms + + +in +parallel + +, + + +queue +a +task + +, + + +task +source + +, + + +iframe + +, + + +valid +MIME +type + +. +

+

+A + +browsing +context + +refers +to +the +environment +in +which + +Document + +objects +are +presented +to +the +user. +A +given + +browsing +context + +has +a +single + + +WindowProxy + + +object, +but +it +can +have +many + + +Document + + +objects, +with +their +associated + + +Window + + +objects. +The + +script +execution +context + +associated +with +the + +browsing +context + +identifies +the +entity +which +invokes +this +API, +which +can +be +a + +web +app +, +a + +web +page +, +or +an + +iframe +. +

+

+The +term + + +secure +context + + +is +defined +in +[ + + +WEBAPPSEC + + +]. +

+

+ + +Error +, + +EvalError +, + +RangeError +, + +ReferenceError +, + +SyntaxError +, + +TypeError +, + +URIError + + +, + + +script +execution +context + +, + + +Promise + +, + + +JSON + +, + + +JSON.stringify + + +and + + +JSON.parse + + +are +defined +in +[ + + +ECMASCRIPT + + +]. +

+

+ + +DOMString + +, + + +USVString + +, + + +ArrayBuffer + +, + + +BufferSource + + +and + + +any + + +are +defined +in +[ + + +WEBIDL + + +]. +

+

+The +algorithms + + +utf-8 +encode + +, +and + + +utf-8 +decode + + +are +defined +in +[ + + +ENCODING + + +]. +

+

+ +IANA +media +type + +s +(formerly +known +as +MIME +types) +are +defined +in + +RFC2046 +. +

+

+The +terms + +hyperlink +reference + +and + +relation +type + +are +defined +in +[ + + +HTML52 + + +] +and + +RFC8288 +. +

+
+
+

+ +10. + +11. + + +Conformance + + +

+

+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 +, + +SHOULD +, +and + +SHOULD +NOT + + +are +to +be +interpreted +as +described +in +[ + + +RFC2119 + + +]. +

+

+This +document +defines +conformance +criteria +that +apply +to +a +single +product: +the + +UA + +(user +agent) +that +implements +the +interfaces +it +contains. +

+

+This +specification +can +be +used +for +implementing +the +WoT +Scripting +API +in +multiple +programming +languages. +The +interface +definitions +are +specified +in +[ + + +WEBIDL + + +]. +

+

+The +user +agent +(UA) +may +be +implemented +in +the +browser, +or +in +a +separate +runtime +environment, +such +as + +Node.js + +or +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 + + +]. +

+

+This +document +serves +a +general +description +of +the +WoT +Scripting +API. +Language +and +runtime +specific +issues +are +discussed +in +separate +extensions +of +this +document. +

+
+
+

+ +A. + +Changes + + +

+

+The +following +is +a +list +of +major +changes +to +the +document. +For +a +complete +list +of +changes, +see +the + +github +change +log +. +You +can +also +view +the + +recently +closed +bugs + +issues + +. +

+ +
+
+

+ +B. + +Open +issues + + +

+

+The +following +problems +are +being +discussed +and +need +most +attention: +

+ +
+
+

+ +C. + +Acknowledgements + +Acknowledgments + +

+

+Special +thanks +to +former +editor +Johannes +Hund +(until +August +2017, +when +at +Siemens +AG) +for +developing +this +specification. +Also, +the +editors +would +like +to +thank +Dave +Raggett, +Matthias +Kovatsch, +Michael +Koster +and +Michael +McCool +for +their +comments +and +guidance. +

+
+
+

+ +D. + +References + + +

+
+

+ +D.1 + +Normative +references + + +

+
+
+[ECMASCRIPT] +
+
+ + +ECMAScript +Language +Specification + +. +Ecma +International. +URL: + +https://tc39.github.io/ecma262/ + +
+
+[ENCODING] +
+
+ + +Encoding + +. +Anne +van +Kesteren; +Joshua +Bell; +Addison +Phillips. +W3C. +15 +December +2016. +W3C +Candidate +Recommendation. +URL: + +https://www.w3.org/TR/encoding/ + +
+
+[HTML52] +
+
+ + +HTML +5.2 + +. +Steve +Faulkner; +Arron +Eicholz; +Travis +Leithead; +Alex +Danilo; +Sangwhan +Moon; +Erika +Doyle +Navara; +Theresa +O'Connor; +Robin +Berjon. +W3C. +14 +December +2017. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/html52/ + +
+
+[JSON-LD] +
+
+ + +JSON-LD +1.0 + +. +Manu +Sporny; +Gregg +Kellogg; +Markus +Lanthaler. +W3C. +16 +January +2014. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/json-ld/ + +
+
+[RFC2119] +
+
+ + +Key +words +for +use +in +RFCs +to +Indicate +Requirement +Levels + +. +S. +Bradner. +IETF. +March +1997. +Best +Current +Practice. +URL: + +https://tools.ietf.org/html/rfc2119 + +
+
+[TYPESCRIPT] +
+
+ + +TypeScript +Language +Specification + +. +Microsoft. +1 +October +2012. +URL: + +https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md + +
+
+[URL] +
+
+ + +URL +Standard + +. +Anne +van +Kesteren. +WHATWG. +Living +Standard. +URL: + +https://url.spec.whatwg.org/ + +
+
+[WEBAPPSEC] +
+
+ + +Secure +Contexts + +. +W3C. +17 +July +2015. +URL: +https://w3c.github.io/webappsec/specs/powerfulfeatures/ + + +https://w3c.github.io/webappsec/specs/powerfulfeatures + + +
+
+[WEBIDL] +
+
+ + +Web +IDL + +. +Cameron +McCormack; +Boris +Zbarsky; +Tobie +Langel. +W3C. +15 +December +2016. +W3C +Editor's +Draft. +URL: + +https://heycam.github.io/webidl/ + +
+
+[WOT-ARCHITECTURE] +
+
+ + +Web +of +Things +Architecture + +. +W3C. +14 +September + +20 +August + +2017. +URL: +https://www.w3.org/TR/2017/WD-wot-architecture-20170914/ + + +https://w3c.github.io/wot-architecture/ +
+[WOT-SECURITY-BEST-PRACTICES] +
+Web +of +Things +Security +and +Privacy +Best +Practices +(WIP) +. +W3C. +WIP. +URL: + +https://github.com/w3c/wot-security/blob/master/wot-security-best-practices.md +
+[WOT-SECURITY-CONSIDERATIONS] +
+Web +of +Things +Security +and +Privacy +Considerations +. +W3C. +28 +August +2017. +URL: + +https://w3c.github.io/wot-security/ +
+[WOT-SECURITY-TESTING] +
+Web +of +Things +Security +Testing +and +Validation +. +W3C. +WIP. +URL: + +https://github.com/w3c/wot-security/blob/master/wot-security-testing.md +
+[WOT-TD] +
+WoT +Thing +Description + +. +W3C. +21 +October +2018. +URL: + +https://www.w3.org/TR/2018/WD-wot-thing-description-20181021/ + + +
+
+
+
+

+ +D.2 + +Informative +references + + +

+
+[WOT-TD] + +
+[HTML] + +
+
+ + +WoT +Thing +Description + +HTML +Standard + + +. +W3C. +20 +August +2017. + +. +Anne +van +Kesteren; +Domenic +Denicola; +Ian +Hickson; +Philip +Jägenstedt; +Simon +Pieters. +WHATWG. +Living +Standard. + +URL: +https://www.w3.org/TR/2018/WD-wot-thing-description-20180405/ + + +https://html.spec.whatwg.org/multipage/ + + +
+
+
+
+ + + + diff --git a/images/scripting-action-data.png b/images/scripting-action-data.png new file mode 100644 index 00000000..7fa19f8b Binary files /dev/null and b/images/scripting-action-data.png differ diff --git a/images/scripting-action-data.svg b/images/scripting-action-data.svg new file mode 100644 index 00000000..213aa916 --- /dev/null +++ b/images/scripting-action-data.svg @@ -0,0 +1,3 @@ + + +
 invokeAction(
  string action,
  InteractionInput args,
  object options)
invokeAction(...
ConsumedThing
ConsumedThing
 Request to invoke name with params and options via Protocol Binding 
 Request to invoke name with params and options via Protocol Binding 
 Promise<InteractionOutput
 Promise<InteractionOutput> 
WoT
implementation
WoT...
 ActionHandler(
    string action,
    InteractionOutput args,
    object options)
ActionHandler(...
 Response (Body) 
 Response (Body) 
WoT
implementation
WoT...
extract parameters
from args
extract parameters...
 ExposedThing
 ExposedThing
return
value
return...
HAL
(sensors, actuators)
HAL...
Promise<InteractionInput>
Promise<InteractionInput>
Invoking an Action
Invoking an Action
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/images/scripting-error-handling.png b/images/scripting-error-handling.png new file mode 100644 index 00000000..88c8158c Binary files /dev/null and b/images/scripting-error-handling.png differ diff --git a/images/scripting-error-handling.svg b/images/scripting-error-handling.svg new file mode 100644 index 00000000..0a9f544c --- /dev/null +++ b/images/scripting-error-handling.svg @@ -0,0 +1,3 @@ + + +
 WoT Interaction
 WoT Interaction
ConsumedThing
ConsumedThing
 Request
 Request
 Promise
 Promise
WoT
implementation
WoT...
WoT handler
WoT handler
 Response (Body or Error) 
 Response (Body or Error) 
WoT
implementation
WoT...
 request + params 
 request + params 
 ExposedThing
 ExposedThing
return
value or error
return...
HAL
(sensors, actuators)
HAL...
Promise
Promise
Error handling
Error handling
Protocol Bindings
Protocol Bi...
Protocol Bindings
Protocol Bi...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/images/scripting-read-data.png b/images/scripting-read-data.png new file mode 100644 index 00000000..ed81c820 Binary files /dev/null and b/images/scripting-read-data.png differ diff --git a/images/scripting-read-data.svg b/images/scripting-read-data.svg new file mode 100644 index 00000000..31f871bf --- /dev/null +++ b/images/scripting-read-data.svg @@ -0,0 +1,3 @@ + + +
readProperty(
    string name,
    object options)
readProperty(...
ConsumedThing
ConsumedThing
 Request to read name with options via Protocol Binding 
 Request to read name with options via Protocol Binding 
WoT
implementation
WoT...
 Response (Body) 
 Response (Body) 
WoT
implementation
WoT...
read
value
read...
Promise<InteractionInput>
Promise<InteractionInput>
ExposedThing
ExposedThing
 return
value
return...
HAL
(sensors)
HAL...
PropertyReadHandler(
    string name,
    object options)
PropertyRe...
 Promise<InteractionOutput
Promise<I...
 Reading a Property
 Reading a Property
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/images/scripting-write-data.png b/images/scripting-write-data.png new file mode 100644 index 00000000..2456d2f6 Binary files /dev/null and b/images/scripting-write-data.png differ diff --git a/images/scripting-write-data.svg b/images/scripting-write-data.svg new file mode 100644 index 00000000..0299ccf4 --- /dev/null +++ b/images/scripting-write-data.svg @@ -0,0 +1,3 @@ + + +
writeProperty(
  string name,
  InteractionInput value,
  object options)
writeProperty(...
ConsumedThing
ConsumedThing
Request to write name with value and options via Protocol Binding 
Request to write name with value and options via Protocol Binding 
Promise<void>
Promise<void>
WoT
implementation
WoT...
  PropertyWriteHandler(
    string name,
    InteractionOutput value,
    object options)
  PropertyWriteHandler(    string name,    InteractionOutput value,    object options)
 Response 
 Response 
WoT
implementation
WoT...
write
value
write...
ExposedThing
ExposedThing
return
status
return...
HAL
(actuators)
HAL...
Promise<void>
Promise<void>
 Writing a Property
 Writing a Property
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..22ba6d1e --- /dev/null +++ b/index.html @@ -0,0 +1,3939 @@ + + + + + Web of Things (WoT) Scripting API + + + + + +
+

+ 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 [[[WOT-ARCHITECTURE]]] 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 Thing 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 [[[WOT-TD]]] 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. +

+
+ +
+

+ 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. +

+
+ +

Introduction

+

+ WoT provides layered interoperability based on how Things are used: + "consumed" and "exposed", as defined in the [[[WOT-ARCHITECTURE]]] 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. +

+
+ Exposing a Thing requires: + + This specification describes how to expose and consume Things by a script. Also, it defines a generic API for Thing discovery. +
+

+ 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. +

+ +
+ +

Use Cases

+

+ The following scripting use cases are supported in this specification: +

+

Consuming a Thing

+ +
+ +

Exposing a Thing

+ +
+ +

Discovery

+ +
+
+ +
+

+ 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. +

+
+
+ WoT Consumer UA +
+
+

+ Implementations of this conformance class MUST implement the {{ConsumedThing}} interface and the consume() method on the WoT API object. +

+
+
+ WoT Producer UA +
+
+

+ Implementations of this conformance class MUST implement {{ExposedThing}} interface and the produce() method on the WoT API object. +

+
+
+ WoT Discovery UA +
+
+

+ Implementations of this conformance class MUST implement the ThingDiscovery interface and the discover() 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 ThingDescription type

+
+      typedef object ThingDescription;
+    
+ +

+ Represents a Thing Description (TD) as + defined in + [[!WOT-TD]]. It is expected to be + a parsed JSON object that is validated using JSON Schema validation. +

+

Fetching a Thing Description

+

+ Fetching a TD given a URL should be done with an external method, such as the Fetch API or a HTTP client library, which offer already standardized options on specifying fetch details. +

+
+        try {
+          let res = await fetch('https://tds.mythings.biz/sensor11');
+          // ... additional checks possible on res.headers
+          let td = await res.json();
+          let thing = await WOT.consume(td);
+          console.log("Thing name: " + thing.getThingDescription().title);
+        } catch (err) {
+          console.log("Fetching TD failed", err.message);
+        }
+      
+
+ +

Expanding a Thing Description

+

+ Note that the [[[WOT-TD]]] specification allows using a shortened Thing Description + by the means of defaults and requiring clients to expand them with default values specified in the + [[[WOT-TD]]] specification for the properties that are not explicitly defined in a given + TD. +

+
+ To expand a TD given |td:ThingDescription|, run the following steps: +
    +
  1. + For each item in the TD default values table from [[!WOT-TD]], if the term is not defined in |td|, add the term definition with the default value specified in [[!WOT-TD]]. +
  2. +
+
+
+ +

Validating a Thing Description

+

+ The [[!WOT-TD]] 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. +

+
+ To validate a TD given |td:ThingDescription|, run the following steps: +
    +
  1. + If JSON Schema + validation fails on |td|, [= exception/throw =] a {{"TypeError"}} and abort these steps. +
  2. +
+

+ Additional steps may be added to fill the default values of mandatory fields. +

+
+
+
+ +
+

The WOT namespace

+

+ Defines the WoT API object as a singleton and contains the API + methods, grouped by conformance classes. +

+
+    [SecureContext, Exposed=(Window,Worker)]
+    namespace WOT {
+      // methods defined in UA conformance classes
+    };
+  
+

The consume() method

+
+      partial namespace WOT {
+        Promise<ConsumedThing> consume(ThingDescription td);
+      };
+    
+
+ Belongs to the WoT Consumer conformance class. Expects an |td:ThingDescription| argument and returns a {{Promise}} that resolves with a {{ConsumedThing}} object that represents a client interface to operate with the Thing. The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + Let |thing:ConsumedThing| be a new {{ConsumedThing}} object constructed from |td|. +
  6. +
  7. + Set up the WoT Interactions based on introspecting td as explained in [[!WOT-TD]] and [[!WOT-PROTOCOL-BINDINGS]]. Make a request to the underlying platform to initialize the Protocol Bindings. +

    + Implementations encapsulate the complexity of how to use the + Protocol Bindings for implementing WoT interactions. + In the future elements of that could be standardized. +

    +
  8. +
  9. + Resolve |promise| with |thing|. +
  10. +
+

+ Note the difference between constructing ConsumedThing and using + the consume() method: the latter also initializes the protocol + bindings, whereas a simple constructed object will not have WoT Interactions + initialized until they are invoked. +

+
+
+ +

The produce() method

+
+      partial namespace WOT {
+        Promise<ExposedThing> produce(ThingDescription td);
+      };
+    
+
+ Belongs to the WoT Producer conformance class. Expects a |td:ThingDescription| argument and returns a {{Promise}} that resolves with an {{ExposedThing}} object that extends {{ConsumedThing}} with a server interface, i.e. the ability to define request handlers. The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + Let |thing:ExposedThing| be a new {{ExposedThing}} object constructed with |td|. +
  6. +
  7. + Resolve |promise| with |thing|. +
  8. +
+
+
+ +

The discover() method

+
+      partial namespace WOT {
+        ThingDiscovery discover(optional ThingFilter filter = null);
+      };
+    
+
+ Belongs to the WoT Discovery conformance class. Starts the discovery process that will provide {{ThingDescription}} objects for Thing Descriptions that match an optional |filter:ThingFilter| argument of type {{ThingFilter}}. The method MUST run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{"SecurityError"}} and abort these steps. +
  2. +
  3. + Construct a ThingDiscovery object |discovery:ThingDiscovery| with |filter|. +
  4. +
  5. + Invoke the discovery.start() method. +
  6. +
  7. + Return |discovery|. +
  8. +
+
+
+
+ +

Handling interaction data

+

+ As specified in the [[[WOT-TD]]] 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. +

+ +
+

The InteractionInput type

+
+      typedef 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-TD]] + (i.e. 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. +

+
+ +
+

The InteractionOutput interface

+

+ 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}}. +

+
+      [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<any> 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-TD]]) 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). +

+

The value() function

+ Parses the data returned by the WoT Interaction and returns a + value with the type described by the interaction DataSchema + if that exists, or by the `contentType` of the interaction Form. The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps + in parallel. +
  2. +
  3. + If the value of the [[\value]] internal slot is not + `undefined`, resolve |promise| with that value and abort these steps. +
  4. +
  5. + If the value of the |data| property is not a {{ReadableStream}} or if + |dataUsed| is `true`, or if |form| is `null` or if |schema| or its + |type| are `null` or `undefined`, + reject |promise| with {{NotReadableError}} and abort these steps. +
  6. +
  7. + If |form|'s |contentType| is not `application/json` and if a mapping is + not available in the Protocol Bindings from |form|'s |contentType| + to [[!JSON-SCHEMA]], reject |promise| with {{NotSupportedError}} and + abort these steps. +
  8. +
  9. + Let |reader| be the result of + + getting a reader from |data|. If that threw an exception, reject + |promise| with that exception and abort these steps. +
  10. +
  11. + Let |bytes| be the result of + reading all bytes from |data| with |reader|. +
  12. +
  13. + Set |dataUsed| to `true`. +
  14. +
  15. + If |form|'s |contentType| is not `application/json` and if a mapping is + available in the Protocol Bindings from |form|'s |contentType| + to [[!JSON-SCHEMA]], transform |bytes| with that mapping. +
  16. +
  17. + Let |json| be the result of running parse JSON from bytes on + |bytes|. If that throws, reject |promise| with that exception and + abort these steps. +
  18. +
  19. + Set [[\value]] to the result of running check data schema + on |json| and |schema|. If that throws, reject |promise| with that + exception and abort these steps. +
  20. +
  21. + Resolve |promise| with [[\value]]. +
  22. +
+
+ +

The arrayBuffer() function

+ When invoked, MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps + in parallel. +
  2. +
  3. + If |data| is not {{ReadableStream}} or if |dataUsed| is `true`, + reject |promise| with {{NotReadableError}} and abort these steps. +
  4. +
  5. + Let |reader| be the result of + + getting a reader from |data|. If that threw an exception, reject + |promise| with that exception and abort these steps. +
  6. +
  7. + Let |bytes| be the result of + reading all bytes from |data| with |reader|. +
  8. +
  9. + Set |dataUsed| to `true`. +
  10. +
  11. + Let |arrayBuffer| be a new {{ArrayBuffer}} whose contents are |bytes|. + If that throws, reject |promise| with that exception and abort these steps. +
  12. +
  13. + Resolve |promise| with |arrayBuffer|. +
  14. +
+
+ +

The check data schema algorithm

+ To run the check data schema steps on |payload| and |schema:object|, +
    +
  1. + Let |type| be |schema|'s |type|. +
  2. +
  3. + If |type| is `"null"` and if |payload| is not `null`, + throw {{TypeError}} and abort these steps, otherwise return `null`. +
  4. +
  5. + If |type| is `"boolean"` and |payload| is a falsey value or its byte + length is 0, return `false`, otherwise return `true`. +
  6. +
  7. + If |type| is `"integer"` or `"number"`, +
      +
    1. + If |payload| is not a number, throw {{TypeError}} and abort these steps. +
    2. +
    3. + If |form|'s |minimum| is defined and |payload| is smaller, or if |form|'s |maximum| is defined and |payload| is bigger, throw + {{RangeError}} and abort these steps. +
    4. +
    +
  8. +
  9. + If |type| is `"string"`, return |payload|. +
  10. +
  11. + If |type| is `"array"`, run these sub-steps: +
      +
    1. + If |payload| is not an array, throw {{TypeError}} and abort these steps. +
    2. +
    3. + If |form|'s |minItems| is defined and |payload|'s |length| is + less than that, or if |form|'s |maxItems| is defined and |payload|'s + |length| is more than that, throw {{RangeError}} and abort these steps. +
    4. +
    5. + Let |payload| be an array of items obtained by running the + check data schema steps on each element |item| of |payload| + and |schema|'s |items|. + If this throws at any stage, re-throw that exception and abort these steps. +
    6. +
    +
  12. +
  13. + If |type| is `"object"`, run these sub-steps: +
      +
    1. + If |payload| or |schema|'s |properties| is not an object, + throw {{TypeError}} and abort these steps. +
    2. +
    3. + For each property |key| in |payload|, +
        +
      1. Let |prop| be the value of |key|.
      2. +
      3. + Let |propSchema| be the value of |key| in |interaction|'s + |properties|. +
      4. +
      5. + Let |prop| be the result of running the + check data schema steps on |prop| and |propSchema|. + If this throws, re-throw that exception and abort these steps. +
      6. +
      +
    4. +
    5. + Let |required| be |schema|'s |required| if that is an array + or an empty array otherwise. +
    6. +
    7. + For each |key| in |required|, if |key| is not present in |payload|, + throw {{SyntaxError}} and abort these steps. +
    8. +
    +
  14. +
  15. + Return |payload|. +
  16. +
+
+ +

The create interaction request algorithm

+ For a given ConsumedThing object |thing:ConsumedThing|, in order to + create interaction request given a |source: InteractionInput|, |form:Form| and + |schema:object|, run these steps: +
    +
  1. + Let |idata| be a new an {{InteractionOutput}} object whose |form| is + set to |form|, whose |schema| is set to |schema|, whose [[\value]] + internal slot is `undefined` and whose |data| is `null`. +
  2. +
  3. + If |source| is a {{ReadableStream}} object, let |idata|'s |data| be + |source|, return |idata| and abort these steps. +
  4. +
  5. + If |schema| and its |type| are defined and not `null`, run these sub-steps: +
      +
    1. + If |type| is `"null"` and |source| is not, + throw {{TypeError}} and abort these steps. +
    2. +
    3. + If |type| is `"boolean"` and |source| is a falsy value, set + |idata|'s [[\value]] |value| to `false`, otherwise to `true`. +
    4. +
    5. + If |type| is `"integer"` or `"number"` and |source| is not a number, + or if |form|'s |minimum| is defined and |source| is smaller, + or if |form|'s |maximum| is defined and |source| is bigger, + throw {{RangeError}} and abort these steps. +
    6. +
    7. + If |type| is `"string"` and |source| is not a string, let |idata|'s + [[\value]] be the result of running serialize JSON to bytes + on |source|. + If that is failure, throw {{SyntaxError}} and abort these steps. +
    8. +
    9. + If |type| is `"array"`, run these sub-steps: +
        +
      1. + If |source| is not an array, throw a {{TypeError}} and abort these steps. +
      2. +
      3. + Let |length| be the length of |source|. +
      4. +
      5. + If |form|'s |minItems| is defined and |length| is less than + that, or if |form|'s |maxItems| is defined and |length| is + more than that, throw {{RangeError}} and abort these steps. +
      6. +
      7. + For each |item| in |source|, let |itemschema| be |schema|'s + |items| and let |item| be the result of running the + create interaction request steps on |item|, |form| and + |itemschema|. + If this throws, re-throw that exception and abort these steps. +
      8. +
      9. + Set |data|'s [[\value]] to |source|. +
      10. +
      +
    10. +
    11. + If |type| is `"object"`, run these sub-steps: +
        +
      1. + If |source| is not an object, throw {{TypeError}} and abort these steps. +
      2. +
      3. + If |schema|'s |properties| is not an object, + throw {{TypeError}} and abort these steps. +
      4. +
      5. + For each property |key| in |source|, +
          +
        1. Let |value| be the value of |key|.
        2. +
        3. Let |propschema| be the value of |key| in |properties|.
        4. +
        5. + Let |value| be the result of running the + create interaction request steps on |value|, |form| + and |propschema|. + If this throws, re-throw that exception and abort these steps. +
        6. +
        +
      6. +
      7. + If |schema|'s |required| is an array, for each |item| in |required| + check if |item| is a property name in |source|. If an |item| is + not found in |source|, throw {{SyntaxError}} and abort these steps. +
      8. +
      9. + Set |data|'s [[\value]] to |source|. +
      10. +
      +
    12. +
    +
  6. +
  7. + Set |idata|'s |data| to a new {{ReadableStream}} created from |idata|'s + [[\value]] internal slot as its + + underlying source. +
  8. +
  9. + Return |idata|. +
  10. +
+
+ +

The parse interaction response algorithm

+ For a given ConsumedThing object |thing:ConsumedThing|, in order to + parse interaction response given |response|, |form:Form| and + |schema:object|, run these steps: +
    +
  1. + Let |result| be a new {{InteractionOutput}} object. +
  2. +
  3. + Let |result|'s |schema| be |schema|. +
  4. +
  5. + Let |result|'s |form| be |form|. +
  6. +
  7. + Let |result|'s |data| be a new {{ReadableStream}} with the payload data + of |response| as its + + underlying source. +
  8. +
  9. + Let |result|'s |dataUsed| be `false`. +
  10. +
  11. + Return |result|. +
  12. +
+
+
+

Using {{InteractionInput}} and {{InteractionOutput}}

+

+ 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. +

+
+ +
Data structures used when reading data
+
+

+ 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}}. +

+ +
+ +
Data structures used when writing data
+
+

+ 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. +

+ +
+ +
Data structures used when invoking an Action
+
+

+ When a {{ConsumedThing}} invokes an Action data, it provides the + parameters as {{InteractionInput}} and receives the output of the + Action as an {{InteractionOutput}} object. +

+

+ An {{ExposedThing}} + action handler receives arguments from the implementation as + an {{InteractionOutput}} object and provides Action output as + {{InteractionInput}} to the implementation. +

+
+ +

Error handling

+

+ 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. +

+
+ +
Error handling in WoT interactions
+
+

+ 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. +

+
+ +
+ +
+

The ConsumedThing interface

+

+ Represents a client API to operate a Thing. Belongs to the + WoT Consumer conformance class. +

+
+      [SecureContext, Exposed=(Window,Worker)]
+      interface ConsumedThing {
+        constructor(ThingDescription td);
+        Promise<InteractionOutput> readProperty(DOMString propertyName,
+                                    optional InteractionOptions options = null);
+        Promise<PropertyMap> readAllProperties(optional InteractionOptions options = null);
+        Promise<PropertyMap> readMultipleProperties(
+                                    sequence<DOMString> propertyNames,
+                                    optional InteractionOptions options = null);
+        Promise<undefined> writeProperty(DOMString propertyName,
+                                    InteractionInput value,
+                                    optional InteractionOptions options = null);
+        Promise<undefined> writeMultipleProperties(PropertyMap valueMap,
+                                    optional InteractionOptions options = null);
+        /*Promise<undefined> writeAllProperties(PropertyMap valueMap,
+                                    optional InteractionOptions options = null);*/
+        Promise<InteractionOutput> invokeAction(DOMString actionName,
+                                    optional InteractionInput params = null,
+                                    optional InteractionOptions options = null);
+        Promise<Subscription> observeProperty(DOMString name,
+                                    InteractionListener listener,
+                                    optional ErrorListener onerror,
+                                    optional InteractionOptions options = null);
+        Promise<Subscription> subscribeEvent(DOMString name,
+                                    InteractionListener listener,
+                                    optional ErrorListener onerror,
+                                    optional InteractionOptions options = null);
+        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 = null);
+      };
+
+      typedef object PropertyMap;
+
+      callback InteractionListener = undefined(InteractionOutput data);
+      callback ErrorListener = undefined(Error error);
+    
+

+ The writeAllProperties() method is still under discussion. + Meanwhile, use the writeMultipleProperties() method instead. +

+
+

Internal slots for ConsumedThing

+

+ A {{ConsumedThing}} object has the following internal slots: +

+ + + + + + + + + + + + + + + +
Internal SlotInitial valueDescription (non-normative)
[[\td]]`null`The Thing Description of the {{ConsumedThing}}.
+
+ +
+

Constructing ConsumedThing

+

+ After fetching a + Thing Description as a JSON object, one can create a + {{ConsumedThing}} object. +

+
+ To create {{ConsumedThing}} with the {{ThingDescription}} + |td:ThingDescription|, run the following steps: +
    +
  1. + Run the validate a TD steps on |td|. If that fails, + [= exception/throw =] {{SyntaxError}} and abort these steps. +
  2. +
  3. + Run the expand a TD steps on |td|. If that fails, re-[= exception/throw =] the error and abort these steps. +
  4. +
  5. + Let |thing:ConsumedThing| be a new {{ConsumedThing}} object. +
  6. +
  7. + Set the internal slot [[\td]] of |thing| to |td|. +
  8. +
  9. + Return |thing|. +
  10. +
+
+
+ +
+

The getThingDescription() method

+

+ Returns the internal slot [[\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. +

+
+ +
+

The readProperty() method

+
+ Reads a Property value. Takes as arguments |propertyName:string| + and optionally |options:InteractionOptions|. + It returns a {{Promise}} that resolves with a Property value + represented as an {{InteractionOutput}} object or rejects on error. + The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps + in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting + context for security reasons, reject |promise| with a + {{SecurityError}} and abort these steps. +
  4. +
  5. + Let |interaction| be the value of [[\td]]'s |properties|'s + |propertyName|. +
  6. +
  7. + If |option|'s |formIndex| is defined, let |form| be the + Form associated with |formIndex| in |interaction|'s |forms| + array, otherwise let |form| be the first Form in + |interaction|'s |forms| whose |op| is `readproperty`. +
  8. +
  9. + If |form| is failure, reject |promise| with a {{SyntaxError}} and + abort these steps. +
  10. +
  11. + Make a request to the underlying platform (via the + Protocol Bindings) to retrieve the value of the Property + given by |propertyName| using |form| and the optional URI templates + given in |options|' |uriVariables|. +
  12. +
  13. + If the request fails, reject |promise| with the error received from the Protocol Bindings and abort these steps. +
  14. +
  15. + Let |response| be the response received to the request. +
  16. +
  17. + Let |data| be the result of running parse interaction response + on |response|, |form| and |interaction|. + If that fails, reject |promise| with a {{SyntaxError}} and abort these steps. +
  18. +
  19. + Resolve |promise| with |data|. +
  20. +
+
+
+ +
+

The readMultipleProperties() method

+
+ Reads multiple Property values with one request. + Takes as arguments |propertyNames: string sequence| and optionally + |options:InteractionOptions|. + It returns a {{Promise}} that resolves with a {{PropertyMap}} object + that maps keys from |propertyNames| to values returned by this algorithm. + The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + If |option|'s |formIndex| is defined, let |form| be the + Form associated with |formIndex| in [[\td]]'s |forms| array, otherwise let |form| be the first Form in [[\td]]'s |forms| array whose |op| is `readmultipleproperties`. +
  6. +
  7. + If |form| is failure, reject |promise| with a {{SyntaxError}} and abort these steps. +
  8. +
  9. + Let |result:object| be an object and for each string |name:string| in |propertyNames| add a property with key |name| and the value `null`. +
  10. +
  11. + Make a request to the underlying platform (via the Protocol Bindings) to retrieve the Property values given by |propertyNames| with |form| and optional URI templates given in |options|' |uriVariables|. +
  12. +
  13. + If this cannot be done with a single request with the Protocol Bindings, reject |promise| with a {{NotSupportedError}} and abort these steps. +
  14. +
  15. + Process the response and for each |key| in |result|, run the following + sub-steps: +
      +
    1. + Let |value| be the value of |result|'s |key|. +
    2. +
    3. + Let |schema| be the value of [[\td]]'s |properties|'s |key|. +
    4. +
    5. + Let |property| be the result of running + parse interaction response on |value|, |form| and + |schema|. +
    6. +
    +
  16. +
  17. + If the above step throws at any point, reject |promise| with that + exception and abort these steps. +
  18. +
  19. + Resolve |promise| with |result|. +
  20. +
+
+
+ +
+

The readAllProperties() method

+
+ Reads all properties of the Thing with one request. Takes |options:InteractionOptions| as optional argument. + It returns a {{Promise}} that resolves with a {{PropertyMap}} object that + maps keys from Property names to values returned by this algorithm. + The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + If |option|'s |formIndex| is defined, let |form| be the + Form associated with |formIndex| in [[\td]]'s |forms| array, otherwise let |form| be the first Form in [[\td]]'s |forms| array whose |op| is `readallproperties`. +
  6. +
  7. + If |form| is failure, reject |promise| with a {{SyntaxError}} and abort these steps. +
  8. +
  9. + Make a request to the underlying platform (via the Protocol Bindings) to retrieve the value of the all the Property definitions from the TD with |form| and optional URI templates given in |options|' |uriVariables|. +
  10. +
  11. + If this cannot be done with a single request with the Protocol Bindings of the Thing, then reject |promise| with a {{NotSupportedError}} and abort these steps. +
  12. +
  13. + If the request fails, reject |promise| with the error received from the Protocol Bindings and abort these steps. +
  14. +
  15. + Process the reply and let |result:object| be an object with the keys and values obtained in the reply. +
  16. +
  17. + Process the response and for each |key| in |result|, run the following + sub-steps: +
      +
    1. + Let |value| be the value of |result|'s |key|. +
    2. +
    3. + Let |schema| be the value of [[\td]]'s |properties|'s |key|. +
    4. +
    5. + Let |property| be the result of running + parse interaction response on |value|, |form| and + |schema|. +
    6. +
    +
  18. +
  19. + Resolve |promise| with |result|. +
  20. +
+
+
+ +
+

The writeProperty() method

+
+ Writes a single Property. Takes as arguments |propertyName:string|, + |value:InteractionInput| and optionally |options:InteractionOptions|. + It returns a {{Promise}} that resolves on success and rejects on failure. + The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + Let |interaction| be the value of [[\td]]'s |properties|'s + |propertyName|. +
  6. +
  7. + If |option|'s |formIndex| is defined, let |form| be the + Form associated with |formIndex| in |interaction|'s |forms| + array, otherwise let |form| be the first Form in + |interaction|'s |forms| whose |op| is `writeproperty`. +
  8. +
  9. + If |form| is failure, reject |promise| with a {{SyntaxError}} and abort these steps. +
  10. +
  11. + Let |data| be the result of running the create interaction request steps on |value|, |form| and |interaction|. If that throws, reject promise with that exception and abort these steps. +
  12. +
  13. + Make a request to the underlying platform (via the Protocol Bindings) + to write the Property given by |propertyName| using + |data:InteractionOutput| and the optional URI templates given in + |options|' |uriVariables|. +
  14. +
  15. + If the request fails, reject |promise| with the error received from the Protocol Bindings and abort these steps. +
  16. +
  17. + Otherwise resolve |promise|. +
  18. +
+
+

+ 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. +

+
+ +
+

The writeMultipleProperties() method

+
+ Writes a multiple Property values with one request. + Takes as arguments |properties:object| - as an object with keys being + Property names and values as Property values - and optionally + |options:InteractionOptions|. + It returns a {{Promise}} that resolves on success and rejects on failure. The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps + in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting + context for security reasons, reject |promise| with a + {{SecurityError}} and abort these steps. +
  4. +
  5. + If |option|'s |formIndex| is defined, let |form| be the + Form associated with |formIndex| in [[\td]]'s |forms| array, + otherwise let |form| be the first Form in [[\td]]'s |forms| + array whose |op| is `writemultipleproperties`. +
  6. +
  7. + If |form| is failure, reject |promise| with a {{SyntaxError}} and + abort these steps. +
  8. +
  9. + Let |propertyNames| be an array of |string| with as elements the keys of the |properties| object. +
  10. +
  11. + For each |name:string| in |propertyNames|, let |property| be the value of [[\td]]'s |properties|'s |name|. + If |property| is `null` or `undefined` or is not `writeable` reject |promise| with {{NotSupportedError}} + and abort these steps. +
  12. +
  13. + Let |result:object| be an object and for each string |name:string| in |propertyNames| add a property with key |name| and let its value be + `null`. +
  14. +
  15. + Let |schemas:object| be an object and for each string |name:string| + in |propertyNames| add a property with key |name| and let its value + be the value of [[\td]]'s |properties|'s |name|. +
  16. +
  17. + For each key |key:string| in |properties|, take its value as |value| + and run the create interaction request steps on |value|, |form| + and the value for |schema|'s |key|. + If that throws for any |name|, reject promise with that + exception and abort these steps. +
  18. +
  19. + Make a single request to the underlying platform (via the + Protocol Bindings) to write each Property provided in + |properties| with optional URI templates given in |options|' + |uriVariables|. +
  20. +
  21. + If this cannot be done with a single request with the + Protocol Bindings of the Thing, then reject |promise| + with a {{NotSupportedError}} and abort these steps. +
  22. +
  23. + If the request fails, return the error received from the + Protocol Bindings and abort these steps. +
  24. +
  25. + Otherwise resolve |promise|. +
  26. +
+
+
+ +
+

The observeProperty() method

+
+ Makes a request for Property value change notifications. + Takes as arguments |propertyName:string|, |listener:InteractionListener| and + optionally |onerror:ErrorListener| and |options:InteractionOptions|. + It returns a {{Promise}} that resolves on success and rejects on failure. + The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + If |listener| is not a {{Function}}, reject |promise| + with a {{TypeError}} and abort these steps. +
  6. +
  7. + If |onerror| is not `null` and is not a {{Function}}, reject |promise| + with a {{TypeError}} and abort these steps. +
  8. +
  9. + Let |subscription| be a new {{Subscription}} object with its internal slots + set as follows: +
      +
    • + Let |subscription|'s [[\type]] be `"property"`. +
    • +
    • + Let |subscription|'s [[\name]] be the value of |propertyName|. +
    • +
    • + Let |subscription|'s [[\interaction]] be the value of [[\td]]'s + |properties|'s |propertyName|. +
    • +
    • + Let |subscription|'s [[\form]] be the Form associated with + |formIndex| in [[\interaction]]'s |forms| array if |option|'s + |formIndex| is defined, otherwise let [[\form]] be the first + Form in [[\interaction]]'s |forms| array whose |op| is + `"observeproperty"`. +
    • +
    • + If |subscription|'s [[\form]] is failure, reject |promise| with a + {{SyntaxError}} and abort these steps. +
    • +
    +
  10. +
  11. + Make a request to the underlying platform to observe the + Property identified by |propertyName| with |form| and + optional URI templates given in |options|' |uriVariables|. +
  12. +
  13. + If the request fails, reject |promise| with the error received from + the Protocol Bindings and abort these steps. +
  14. +
  15. + Otherwise resolve |promise|. +
  16. +
  17. + Whenever the underlying platform detects a notification for this + subscription with a new Property value |value|, + run the following sub-steps: +
      +
    • + Let |reply| be the result of running parse interaction response + with |value|, [[\form]] and [[\interaction]]. + If that throws, reject |promise| with that exception and abort these steps. +
    • +
    • + Invoke |listener| with |reply|. +
    • +
    +
  18. +
  19. + Whenever the underlying platform detects an error for + this subscription, run the following sub-steps: +
      +
    • + If the error is irrecoverable and stops the subscription, set + |subscription|'s |active| to `false` and suppress further notifications. +
    • +
    • + Let |error| be a new {{NetworkError}} and set its |message| + to reflect the underlying error condition. +
    • +
    • + If |onerror| is a {{Function}}, invoke it with |error|. +
    • +
    +
  20. +
+
+
+ +
+

The invokeAction() method

+
+ Makes a request for invoking an Action and return the result. + Takes as arguments |actionName:string|, optionally + |params:InteractionInput| and optionally |options:InteractionOptions|. + It returns a {{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: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + Let |interaction| be the value of [[\td]]'s |actions|'s + |actionName|. +
  6. +
  7. + If |option|'s |formIndex| is defined, let |form| be the + Form associated with |formIndex| in |interaction|'s |forms| + array, otherwise let |form| be the first Form in + |interaction|'s |forms| array whose |op| is `invokeaction`. +
  8. +
  9. + If |form| is failure, reject |promise| with a {{SyntaxError}} and abort these steps. +
  10. +
  11. + Let |args| be the result of running the create interaction request steps on |params|, |form| and |interaction|. If that throws, reject promise with that exception and abort these steps. +
  12. +
  13. + Make a request to the underlying platform (via the Protocol Bindings) to invoke the Action identified by |actionName| with parameters provided in |args| and optional URI templates given in |options|'s |uriVariables|. +
  14. +
  15. + If the request fails locally or returns an error over the network, reject |promise| with the error received from the Protocol Bindings and abort these steps. +
  16. +
  17. + Let |value| be the reply returned in the reply. +
  18. +
  19. + Let |result| be the result of running parse interaction response + with |value|, |form| and |interaction|. If that throws, reject |promise| with that exception and abort these steps. +
  20. +
  21. + Resolve |promise| with |result|. +
  22. +
+
+
+ +
+

The subscribeEvent() method

+
+ Makes a request for subscribing to Event notifications. + Takes as arguments |eventName:string|, |listener:WoTListener| and + optionally |onerror:ErrorListener| and |options:InteractionOptions|. + It returns a {{Promise}} to signal success or failure. + The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + If |listener| is not a {{Function}}, reject |promise| + with a {{TypeError}} and abort these steps. +
  6. +
  7. + If |onerror| is not `null` and is not a {{Function}}, reject |promise| + with a {{TypeError}} and abort these steps. +
  8. +
  9. + Let |subscription| be a new {{Subscription}} object with its internal slots + set as follows: +
      +
    • + Let |subscription|'s [[\type]] be `"event"`. +
    • +
    • + Let |subscription|'s [[\name]] be the value of |eventName|. +
    • +
    • + Let |subscription|'s [[\interaction]] be the value of [[\td]]'s + |events|'s |eventName|. +
    • +
    • + Let |subscription|'s [[\form]] be the Form associated with + |formIndex| in [[\interaction]]'s |forms| array if |option|'s + |formIndex| is defined, otherwise let [[\form]] be the first + Form in [[\interaction]]'s |forms| array whose |op| is + `"subscribeevent"`. +
    • +
    • + If |subscription|'s [[\form]] is failure, reject |promise| with a + {{SyntaxError}} and abort these steps. +
    • +
    +
  10. +
  11. + Make a request to the underlying platform via the Protocol Bindings + to subscribe to an Event identified by |eventName:string| with + [[\form]], optional URI templates given in |options|' |uriVariables| + and optional subscription data given in |options|'s |data|. +
  12. +
  13. + If the request fails, reject |promise| with the error received from + the Protocol Bindings and abort these steps. +
  14. +
  15. + Otherwise resolve |promise|. +
  16. +
  17. + Whenever the underlying platform detects a notification for this + Event subscription, run the following sub-steps: +
      +
    1. + Invoke |listener| with the result of running + parse interaction response on the data provided with the + Event, [[\form]] and [[\interaction]]. +
    2. +
    +
  18. +
  19. + Whenever the underlying platform detects an error for + this subscription, run the following sub-steps: +
      +
    • + If the error is irrecoverable and stops the subscription, set + |subscription|'s |active| to `false` and suppress further notifications. +
    • +
    • + Let |error| be a new {{NetworkError}} and set its |message| + to reflect the underlying error condition. +
    • +
    • + If |onerror| is a {{Function}}, invoke it with |error|. +
    • +
    +
  20. +
+
+
+ +
+

+ The InteractionOptions dictionary +

+

+ 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-TD]]. +

+

+ The support for URI variables comes from the need, exposed by the [[[WOT-TD]]] specification, to be able to describe + existing REST-ful 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. +

+
+ +
+

The PropertyMap type

+

+ Represents a map of Property names as strings to a value that the Property can take. It is used as a property bag for interactions that involve multiple Properties at once. +

+

+ It could be defined in Web IDL (as well as {{ThingDescription}}) as a maplike interface from string to any. +

+
+ + +
+

The InteractionListener callback

+

+ 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. +

+
+ +
+

The ErrorListener callback

+

+ 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. +

+
+ +
+

The Subscription interface

+

+ 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. +

+

Internal slots for {{Subscription}}

+ A {{Subscription}} object has the following internal slots: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Internal SlotInitial valueDescription (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.
+
+
+

The stop() method

+

+ Stops delivering notifications for the subscription. It takes an + optional parameter |options:InteractionOptions| and returns a {{Promise}}. + When invoked, the method MUST execute the following steps: +

    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps + in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting + context for security reasons, reject |promise| with a + {{SecurityError}} and abort these steps. +
  4. +
  5. + If |options|' |formIndex| is defined, let |unsubscribeForm| be the + Form associated with |formIndex| in [[\interaction]]'s + |forms| array. +
  6. +
  7. + Otherwise let |unsubscribeForm| be the result of running the + find a matching unsubscribe form algorithm given [[\form]]. +
  8. +
  9. + If |unsubscribeForm| is failure, reject |promise| with a {{SyntaxError}} and + abort these steps. +
  10. +
  11. + If [[\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|. +
  12. +
  13. + Otherwise, if [[\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|'s |data|. +
  14. +
  15. + If the request fails, reject |promise| with the error received from + the Protocol Bindings and abort these steps. +
  16. +
  17. + Otherwise set active to + `false` and resolve |promise|. +
  18. +
  19. + If the underlying platform receives further notifications for this + subscription, implementations SHOULD silently suppress them. +
  20. +
+

+
+

Finding an unsubscribe Form

+ To find a matching unsubscribe form given |subscribeForm| + in the context of a {{Subscription}} object, run the following steps: +
    +

    + 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. +

    +
  1. + Let |results| be an empty array. +
  2. +
  3. + For each |form| in [[\interaction]]'s |forms| array, +
      +
    1. + Add an internal slot [[\matchLevel]] on |form| and set + its value to `0`. +
    2. +
    3. + If |form|'s |op| is `"unobserveproperty"` if [[\type]] is + `"property"` or if |form|'s |op| is `"unsubscribeevent"` + if [[\type]] is`"event"`, +
        +
      1. + Set the internal slot [[\matchLevel]] on |form| to 1 + and add |form| to |results|. +
      2. +
      3. + If |form|'s |href| and [[\subscribeForm]]'s |href| are + + same origin-domain, increment |form|'s [[\matchLevel]]. +
      4. +
      5. + If |form|'s |contentType| is equal to [[\subscribeForm]]'s + |contentType| and |form|'s [[\matchLevel]] is greater than 2, + increment |form|'s [[\matchLevel]]. +
      6. +
      +
    4. +
    +
  4. +
  5. + If |results| is empty, return `null` and terminate these steps. +
  6. +
  7. + Return the first |form| in |results| that has the highest + [[\matchLevel]] value. +
  8. +
+
+
+ +
+

ConsumedThing Examples

+

+ 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 stoped");
+            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 recorderd 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

+

+ The {{ExposedThing}} interface is the server API to operate the Thing that allows defining request handlers, Property, Action, and Event interactions. +

+
+      [SecureContext, Exposed=(Window,Worker)]
+      interface ExposedThing: ConsumedThing {
+        ExposedThing setPropertyReadHandler(DOMString name,
+                PropertyReadHandler handler);
+        ExposedThing setPropertyWriteHandler(DOMString name,
+                PropertyWriteHandler handler);
+        ExposedThing setPropertyObserveHandler(DOMString name,
+                PropertyReadHandler handler);
+        ExposedThing setPropertyUnobserveHandler(DOMString name,
+                PropertyReadHandler handler);
+
+        ExposedThing setActionHandler(DOMString name, ActionHandler action);
+
+        ExposedThing setEventSubscribeHandler(DOMString name,
+                EventSubscriptionHandler handler);
+        ExposedThing setEventUnsubscribeHandler(DOMString name,
+                EventSubscriptionHandler handler);
+        ExposedThing setEventHandler(DOMString name,
+                EventListenerHandler eventHandler);
+        undefined emitEvent(DOMString name, InteractionInput data);
+
+        Promise<undefined> expose();
+        Promise<undefined> destroy();
+      };
+
+      callback PropertyReadHandler = Promise<any>(
+              optional InteractionOptions options = null);
+
+      callback PropertyWriteHandler = Promise<undefined>(
+              InteractionOutput value,
+              optional InteractionOptions options = null);
+
+      callback ActionHandler = Promise<InteractionInput>(
+              InteractionOutput params,
+              optional InteractionOptions options = null);
+
+      callback EventSubscriptionHandler = Promise<undefined>(
+              optional InteractionOptions options = null);
+
+      callback EventListenerHandler = Promise<InteractionInput>();
+    
+
+

Constructing {{ExposedThing}}

+

+ The {{ExposedThing}} interface extends {{ConsumedThing}}. It + is constructed 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 constructing 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 constructing {{ExposedThing}} and then initialize its Properties and service handlers before starting serving requests. +

+
+ To construct an {{ExposedThing}} with the {{ThingDescription}} + |td:ThingDescription|, run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Run the expand a TD steps on |td|. If that fails, re-[= exception/throw =] the error and abort these steps. +
  4. +
  5. + Let |thing:ExposedThing| be a new {{ExposedThing}} object. +
  6. +
  7. + Set the internal slot [[\td]] of |thing| to |td|. +
  8. +
  9. + Return |thing|. +
  10. +
+
+
+
+

Methods inherited from {{ConsumedThing}}

+

+ The readProperty(), readMultipleProperties(), readAllProperties(), writeProperty(), writeMultipleProperties(), writeAllProperties() methods have the same algorithmic steps as described in ConsumedThing, with the difference that making a request to the underlying platform MAY be implemented with local methods or libraries and don't necessarily need to involve network operations. +

+

+ The implementation of {{ConsumedThing}} interface in an {{ExposedThing}} provide the default methods to interact with the {{ExposedThing}}. +

+

+ After constructing an {{ExposedThing}}, a script can initialize its Properties and can set up the optional read, write and action request handlers (the default ones are provided by the implementation). The script provided handlers MAY use the default handlers, thereby extending the default behavior, but they can also bypass them, overriding the default behavior. Finally, the script would call expose() on the {{ExposedThing}} in order to start serving external requests. +

+

+ The request handlers actually implement the behavior and it is the + responsibility of the developers to keep the Thing Description + defined in {{ExposedThing}} synchronized with the implementation of the + request handlers. +

+
+ +
+

The PropertyReadHandler callback

+

+ 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 {{Promise}} and resolves with an {{ReadableStream}} object or an + + ECMAScript value conforming to DataSchema, or rejects with an + error. +

+
+ +

The setPropertyReadHandler() method

+

+ Takes as arguments |name:string| and |handler:PropertyReadHandler|. + 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. +

+
+ When the method is invoked given |name:string| and + |handler:PropertyReadHandler|, implementations MUST run the + following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |properties|'s + |name|. +
  4. +
  5. + If a Property interaction with |name| is not found, + [= exception/throw =] {{NotFoundError}} and abort these steps. +
  6. +
  7. + Add the internal slot [[\readHandler]] to |interaction| and + set it to |handler|. +
  8. +
+
+
+ +

Handling requests for reading a Property

+
+ When a network request for reading Property |name:string| + is received by the implementation with |options:InteractionOptions|, + run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |value| be the result of running the read server property + steps with |name:string| and |options:InteractionOptions|: +
      +
    1. + Let |interaction| be the value of [[\td]]'s |properties|'s + |name|. +
    2. +
    3. + If a Property with |name| does not exist, throw {{NotFoundError}} and abort these steps. +
    4. +
    5. + Let |handler:function| be `null`. +
    6. +
    7. + If there is a user provided internal slot [[\readHandler]] + on |interaction|, let |handler| be that. +
    8. +
    9. + Otherwise, if there is a default read handler provided by the implementation, let |handler| be that. +
    10. +
    11. + If |handler| is `null`, throw {{NotSupportedError}} + and abort these steps. +
    12. +
    13. + Let |value| be the result of invoking |handler| with |options|. + If that fails, throw the error and abort these steps. +
    14. +
    15. + Return |value|. +

      + The |value| returned here SHOULD either conform to DataSchema + or it SHOULD be an {{ReadableStream}} object created by the + |handler|. +

      +
    16. +
    +
  6. +
  7. + If the previous step has thrown an error, send the error back with + the reply created by following the Protocol Bindings and abort + these steps. +
  8. +
  9. + Serialize and add the returned |value| to the reply created by + following the Protocol Bindings. +
  10. +
+
+
+ +

Handling requests for reading multiple Properties

+
+ When a network request for reading multiple Properties given in + an object |propertyNames| is received with |options:InteractionOptions|, + run the following read multiple properties steps on |propertyNames| and |options|: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + For each property with key |name| defined in |propertyNames|, +
      +
    1. + Let |value| be the result of running the read server property + steps on |name| and |options|. + If that throws, send back the error in the reply created by following the Protocol Bindings and abort these steps. +
    2. +
    3. + Set the value of |propertyNames|'s |name| to |value|. +
    4. +
    +
  6. +
  7. + Reply to the request by sending a single reply created from |propertyNames| according to the Protocol Bindings. +
  8. +
+
+
+ +

Handling requests for reading all Properties

+
+ When a network request for reading all Properties is received + with |options:InteractionOptions|, run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |properties| be an object created with all properties defined in + the Thing with values set to `null`. +
  6. +
  7. + Run the read multiple properties steps on |properties| and + |options|. +
  8. +
+
+
+ +

The setPropertyObserveHandler() method

+

+ Takes as arguments |name:string| and |handler:PropertyReadHandler|. + 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. +

+
+ When the method is invoked given |name:string| and + |handler:PropertyReadHandler|, implementations MUST run the + following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |properties|'s + |name|. +
  4. +
  5. + If a Property interaction with |name| is not found, + [= exception/throw =] {{NotFoundError}} and abort these steps. +
  6. +
  7. + Set the internal slot [[\observeHandler]] on |interaction| + to |handler|. +
  8. +
+
+
+ +

Handling Property observe requests

+
+ When a network request for observing a Property |name:string| is + received by the implementation with |options:InteractionOptions|, + run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |property| be the value of [[\td]]'s |properties|'s |name|. + If it does not exist, send back a {{NotFoundError}} in the + reply and abort these steps. +
  6. +
  7. + Save the request sender information together with |options| to + |property|'s internal observer list, in order to be able + to notify about Property value changes. +
  8. +
  9. + Every time the value of |property| changes, run the following sub-steps: +
      +
    1. + Let |handler:function| be `null.` +
    2. +
    3. + If there is an [[\observeHandler]] internal slot associated + with |name| on |property|, let |handler| be that. +
    4. +
    5. + Otherwise, if there is a [[\readHandler]] internal slot + associated with |name| on |property|, let |handler| be that. +
    6. +
    7. + If |handler| is `null`, abort these steps. +
    8. +
    9. + Let |promise| be the result of invoking |handler| wih |options|. +
    10. +
    11. + If |promise| rejects, abort these steps. +
    12. +
    13. + If |promise| resolves with |data|, then for each |observer| in + |property|'s internal observer list, run the following + sub-steps: +
        +
      1. + Let |options| be the interaction options saved with |observer|. +
      2. +
      3. + Create a |reply| from |data| and |options| according to the + Protocol Bindings. +
      4. +
      5. + Send |reply| to |observer|. +
      6. +
      +
    14. +
    +
  10. +
+
+
+ +

The setPropertyUnobserveHandler() method

+

+ Takes as arguments |name:string| and |handler:PropertyReadHandler|. + 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. +

+
+ When the method is invoked given |name:string| and + |handler:PropertyReadHandler|, implementations MUST run the + following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a + {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |properties|'s + |name|. +
  4. +
  5. + If a Property interaction with |name| is not found, + [= exception/throw =] {{NotFoundError}} and abort these steps. +
  6. +
  7. + Set the internal slot [[\unobserveHandler]] on |interaction| + to |handler|. +
  8. +
+
+
+ +

Handling Property unobserve requests

+
+ When a network request for unobserving a Property |name:string| + with |options:InteractionOptions| is received by the implementation, + run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |property| be the value of [[\td]]'s |properties|'s |name|. + If it does not exist, send back a {{NotFoundError}} in the + reply and abort these steps. +
  6. +
  7. + If there is an [[\unobserveHandler]] of type {{Function}} defined + for |name| on |property|, invoke that with |options|, send back a + reply following the Protocol Bindings and abort these steps. +
  8. +
  9. + Let |sender| be the matching observer found in |property|'s + internal observer list. If not found, send back a + {{NotFoundError}} in the reply and abort these steps. +
  10. +
  11. + Remove |sender| from |property|'s internal observer list + and send back a reply following the Protocol Bindings. +
  12. +
+
+
+ +
+

The PropertyWriteHandler callback

+

+ 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:InteractionOutput| and returns a {{Promise}}, + 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. +

+

+ 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. +

+
+ +

The setPropertyWriteHandler() method

+

+ Takes as arguments |name:string| and |handler:PropertyWriteHandler|. + 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. +

+
+ When the method is invoked given |name:string| and + |handler:PropertyWriteHandler|, implementations MUST run the + following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |properties|'s + |name|. +
  4. +
  5. + If a Property interaction with |name| is not found, + [= exception/throw =] {{NotFoundError}} and abort these steps. +
  6. +
  7. + Set the internal slot [[\writeHandler]] on |interaction| + to |handler|. +
  8. +
+
+
+ +

Handling requests for writing a Property

+
+ When a network request for writing a Property |name:string| + with a new value |value:InteractionOutput| and |options:InteractionOptions| + is received, implementations MUST run the following + update property steps, given |name|, |value|, |options| + and |mode| set to `"single"`: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |interaction| be the value of [[\td]]'s |properties|'s + |name|. +
  6. +
  7. + If a Property with |name| does not exist, return a {{NotFoundError}} in the reply and abort these steps. +
  8. +
  9. + Let |handler:function| be `null`. +
  10. +
  11. + If there is a user provided internal slot [[\writeHandler]] + on |interaction|, let |handler| be that. +
  12. +
  13. + Otherwise, if there is a default write handler provided by the implementation, let |handler| be that. +
  14. +
  15. + Otherwise, if |handler| is `null`, send back a {{NotSupportedError}} + with the reply and abort these steps. +
  16. +
  17. + Let |promise| be the result of invoking |handler| with |name| and + |options|. If it fails, return the error in the reply and abort these steps. +
  18. +
  19. + If |mode| is `"single"`, reply to the request reporting success, following the Protocol Bindings and abort these steps. +
  20. +
+
+
+ +

Handling requests for writing multiple Properties

+
+ When a network request for writing multiple Properties given in an object |propertyNames| is received with |options:InteractionOptions|, + run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + For each property with key |name| and value |value| defined in |propertyNames|, run the update property steps with |name|, |value|, |options| and |mode| set to `"multiple"`. + If that fails, reply to the request with that error and abort these steps. +
  6. +
  7. + Reply to the request by sending a single reply according to the + Protocol Bindings. +
  8. +
+
+
+ +
+

The ActionHandler callback

+

+ 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 with |params:InteractionOutput| and optionally + with an |options:InteractionOptions| object. + It returns a {{Promise}} that rejects with an error or resolves with + the value returned by the Action as {{InteractionInput}}. +

+

+ Application scripts MAY return a {{ReadableStream}} object from an + {{ActionHandler}}. Implementations will then use the stream for + constructing the Action's response. +

+
+ +

The setActionHandler() method

+

+ Takes as arguments |name:string| and |action:ActionHandler|. + 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. +

+
+ When the method is invoked given |name:string| and |action:ActionHandler|, + run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |actions|'s + |name|. +
  4. +
  5. + If an Action with name |name| is not found, + [= exception/throw =] a {{NotFoundError}} and abort these steps. +
  6. +
  7. + Set the internal slot [[\actionHandler]] on |interaction| + to |action|. +
  8. +
+
+
+ +

Handling Action requests

+
+ When a network request for invoking the Action identified by |name:string| is received with |inputs| and optionally with + |options:InteractionOptions|, run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |interaction| be the value of [[\td]]'s |properties|'s + |name|. +
  6. +
  7. + If an Action identified by |name| does not exist, return a {{NotFoundError}} in the reply and abort these steps. +
  8. +
  9. + Let |handler:function| be `null`. +
  10. +
  11. + If there is a user provided internal slot [[\actionHandler]] + on |interaction|, let |handler| be its value. +
  12. +
  13. + If |handler| is `null`, return a {{NotSupportedError}} with the reply + created by following the Protocol Bindings and abort these steps. +
  14. +
  15. + Let |promise| be the result of invoking |handler| with |name|, |inputs| and |options|. +
  16. +
  17. + If |promise| rejects, send the error with the reply and abort these + steps. +
  18. +
  19. + When |promise| resolves with |data:InteractionInput|, use |data| to + create and send the reply according to the Protocol Bindings. +
  20. +
+
+
+ +
+

The EventListenerHandler callback

+

+ A function that is called when an associated Event is triggered + and provides the data to be sent with the Event to subscribers. + Returns a {{Promise}} that resolves with {{InteractionInput}} value + that represents the Event data, or rejects with an error. +

+

+ Applications MAY return {{ReadableStream}} from an {{EventListenerHandler}} + Implementations will then use the stream provided in + {{InteractionOutput}} when constructing the event notification. +

+
+ +
+

The EventSubscriptionHandler callback

+

+ 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 with an |options:InteractionOptions| object provided by the implementation and coming from subscribers. + It returns a {{Promise}} that rejects with an error or resolves when + the subscription is accepted. +

+
+ +

The setEventSubscribeHandler() method

+

+ Takes as arguments |name:string| and |handler:EventSubscriptionHandler|. + 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. +

+
+ When the method is invoked given |name:string| and + |handler:EventSubscriptionHandler|, run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |events|'s + |name|. +
  4. +
  5. + If an Event with the name |name| is not found, + [= exception/throw =] a {{NotFoundError}} and abort these steps. +
  6. +
  7. + Set the internal slot [[\subscribeHandler]] on |interaction| + to |handler|. +
  8. +
  9. + Return `this`. +
  10. +
+
+
+ +

Handling Event subscribe requests

+
+ When an Event subscription request for |name| is received by the + underlying platform with optional |options:InteractionOptions|, + run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |interaction| be the value of [[\td]]'s |events|'s + |name|. +
  6. +
  7. + If an Event with the name |name| is not found, send back a + {{NotFoundError}} and abort these steps. +
  8. +
  9. + If |name| has an associated [[\subscribeHandler]] internal slot, + invoke it with |options| and abort these steps. +
  10. +
  11. + Otherwise, if no [[\subscribeHandler]] is defined, then implement the + default subscriber mechanism: +
      +
    1. + Let |subscriber| be a tuple formed of |options| (from which + |uriVariables| and |data| may be used) and the + subscriber information needed to create an Event + notification response. +
    2. +
    3. + Add |subscriber| to the internal listener list of |interaction|. +
    4. +
    +
  12. +
+
+
+ +

The setEventUnsubscribeHandler() method

+

+ Takes as arguments |name:string| and |handler:EventSubscriptionHandler|. + 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. +

+
+ When the method is invoked with |name:string| and + |handler:EventSubscriptionHandler|, run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |events|'s + |name|. +
  4. +
  5. + If an Event with the name |name| is not found, + [= exception/throw =] a {{NotFoundError}} and abort these steps. +
  6. +
  7. + Set the internal slot [[\unsubscribeHandler]] on |interaction| + to |handler|. +
  8. +
  9. + Return `this`. +
  10. +
+
+
+ +

Handling Event unsubscribe requests

+
+ When an Event unsubscribe request for |name| is received by the + underlying platform optionally with |options:InteractionOptions|, + run the following steps: +
    +
  1. + If this operation is not supported, send back a {{NotSupportedError}} + according to the Protocol Bindings and abort these steps. +
  2. +
  3. + If this operation is not allowed, send back a {{NotAllowedError}} + according to the Protocol Bindings and abort these steps. +
  4. +
  5. + Let |interaction| be the value of [[\td]]'s |events|'s + |name|. +
  6. +
  7. + If an Event with the name |name| is not found, send back a + {{NotFoundError}} and abort these steps. +
  8. +
  9. + If |name| has an associated [[\unsubscribeHandler]] + internal slot that is a function, + invoke it with |options| and abort these steps. +
  10. +
  11. + Otherwise let |subscriber| be the tuple saved in |interaction|'s + internal listener list. +
  12. +
  13. + Remove |subscriber| from |interaction|'s + internal listener list. +
  14. +
  15. + Return `this`. +
  16. +
+
+
+ +

The setEventHandler() method

+

+ Takes as arguments |name:string| and |eventHandler:EventListenerHandler|. + Sets the event handler function for the specified Event + matched by |name|. + Throws on error. + Returns a reference to |this| object for supporting chaining. +

+

+ The |eventHandler| callback function will implement what to do when the + event is emitted. It SHOULD resolve with a value that represents the + Event data, or reject with an error. +

+

+ There MUST be at most one handler for any given Event, so newly added handlers MUST replace the previous handlers. +

+
+ When the method is invoked with |name:string| and + |eventHandler:EventListenerHandler|, run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |events|'s + |name|. +
  4. +
  5. + If an Event with the name |name| is not found, + [= exception/throw =] a {{NotFoundError}} and abort these steps. +
  6. +
  7. + Set the internal slot [[\eventHandler]] of |interaction| to + |eventHandler|. +
  8. +
  9. + Return `this`. +
  10. +
+
+
+ +

Handling Events

+
+ When an Event with name |name| is emitted with + |data:InteractionInput| either by the underlying platform or by the + emitEvent() method, run the + following steps: +
    +
  1. + Let |interaction| be the value of [[\td]]'s |events|'s + |name|. +
  2. +
  3. + If |data| is not defined or `null`, +
      +
    1. + Let |eventHandler| be the value of the [[\eventHandler]] + internal slot of |interaction|. +
    2. +
    3. + If |eventHandler| is failure, abort these steps. +
    4. +
    5. + Let |data| be the result of awaiting to resolve the invocation + of |eventHandler|. If it rejects, abort these steps. +
    6. +
    +
  4. +
  5. + For each |subscriber| in the internal listener list of + |interaction|, run the following sub-steps: +
      +
    1. + Create an Event notification |response| according to the + Protocol Bindings from |data| and |subscriber|, including + its |options|. +
    2. +
    3. + Send |response| to the subscriber identified by |subscriber|. +
    4. +
    +
  6. +
+
+
+ +

The emitEvent() method

+
+ Takes as arguments |name:string| denoting an Event name and + |data:InteractionInput|. + Triggers emitting the Event with the given data. + The method MUST run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, [= exception/throw =] a {{SecurityError}} and abort these steps. +
  2. +
  3. + Let |interaction| be the value of [[\td]]'s |events|'s |name|. +
  4. +
  5. + If an Event with the name |name| is not found, + [= exception/throw =] a {{NotFoundError}} and abort these steps. +
  6. +
  7. + Make a request to the underlying platform to emit an Event + with |data|. +

    + This will trigger the handling events + steps. +

    +
  8. +
+
+
+ +

The expose() method

+
+ Start serving external requests for the Thing, so that WoT Interactions using Properties, Actions and Events will be possible. The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + Run the expand a TD steps on the internal slot [[\td]]. +
  6. +
  7. + Run the validate a TD on [[\td]]. If that fails, + reject |promise| with a {{TypeError}} and abort these steps. +
  8. +
  9. + For each Property definition in [[\td]]'s |properties|, + initialize an |internal observer list| internal slot + in order to store observe request data needed to notify the observers on value changes. +
  10. +
  11. + For each Event definition is [[\td]]'s |events|, + initialize an |internal listener list| internal slot + in order to store subscription request data needed to notify the + Event listeners. +
  12. +
  13. + Set up the WoT Interactions based on introspecting [[\td]] + as explained in [[!WOT-TD]] and [[!WOT-PROTOCOL-BINDINGS]]. + 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). +
  14. +
  15. + If there was an error during the request, reject |promise| with an {{Error}} object |error| with |error|'s |message| set to the error code seen by the Protocol Bindings and abort these steps. +
  16. +
  17. + Otherwise resolve |promise| and abort these steps. +
  18. +
+
+
+ +

The destroy() method

+
+ Stop serving external requests for the Thing and destroy the object. Note that eventual unregistering should be done before invoking this method. The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If invoking this method is not allowed for the current scripting context for security reasons, reject |promise| with a {{SecurityError}} and abort these steps. +
  4. +
  5. + Make a request to the underlying platform to stop serving external requests for WoT Interactions, based on the Protocol Bindings. +
  6. +
  7. + If there was an error during the request, reject |promise| with an {{Error}} object |error| with its |message| set to the error code seen by the Protocol Bindings and abort these steps. +
  8. +
  9. + Otherwise resolve |promise| and abort these steps. +
  10. +
+
+
+ +
+

ExposedThing Examples

+

+ The next example illustrates how to create an {{ExposedThing}} based on a partial TD object constructed beforehands. +

+
+        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 ThingDiscovery interface

+

+ 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 {{ThingDiscovery}} object is constructed given a filter and provides the properties and methods controlling the discovery process. +

+
+      [SecureContext, Exposed=(Window,Worker)]
+      interface ThingDiscovery {
+        constructor(optional ThingFilter filter = null);
+        readonly attribute ThingFilter? filter;
+        readonly attribute boolean active;
+        readonly attribute boolean done;
+        readonly attribute Error? error;
+        undefined start();
+        Promise<ThingDescription> next();
+        undefined stop();
+      };
+    
+

+ The {{ThingDiscovery}} interface has a next() method and a done property, but it is not an Iterable. Look into Issue 177 for rationale. +

+

+ The discovery results internal slot is an internal queue for temporarily storing the found {{ThingDescription}} objects until they are consumed by the application using the next() method. Implementations MAY optimize the size of this queue based on e.g. the available resources and the frequency of invoking the next() method. +

+

+ The filter property represents the discovery filter of type ThingFilter specified for the discovery. +

+

+ The active property is `true` when the discovery is actively ongoing on protocol level (i.e. new TDs may still arrive) and `false` otherwise. +

+

+ The done property is `true` if the discovery has been completed with no more results to report and discovery results is also empty. +

+

+ The error property represents the last error that occurred during the discovery process. Typically used for critical errors that stop discovery. +

+ +

Constructing {{ThingDiscovery}}

+
+ To create {{ThingDiscovery}} with a |filter:ThingFilter| or type {{ThingFilter}}, run the following steps: +
    +
  1. + If |filter| is not an object or `null`, [= exception/throw =] a {{TypeError}} and abort these steps. +
  2. +
  3. + Let |discovery:ThingDiscovery| be a new {{ThingDiscovery}} object. +
  4. +
  5. + Set the filter property to |filter|. +
  6. +
  7. + Set the active and done properties to `false`. Set the error property to `null`. +
  8. +
  9. + Return |discovery|. +
  10. +
+
+

+ The start() method sets active to `true`. The stop() method sets the active property to |false|, but done may be still `false` if there are {{ThingDescription}} objects in the discovery results not yet consumed with next(). +

+

+ During successive calls of next(), the active property may be `true` or `false`, but the done property is set to `false` by next() only when both the active property is `false` and discovery results is empty. +

+
+ +
+

The DiscoveryMethod enumeration

+
+        typedef DOMString DiscoveryMethod;
+      
+

+ Represents the discovery type to be used: +

+ +
+ +
+

The ThingFilter dictionary

+

+ Represents an object containing the constraints for discovering Things as key-value pairs. +

+
+        dictionary ThingFilter {
+          (DiscoveryMethod or DOMString) method = "any";
+          USVString? url;
+          USVString? query;
+          object? fragment;
+        };
+      
+

+ The method property represents the discovery type that should be used in the discovery process. The possible values are defined by the DiscoveryMethod enumeration that MAY be extended by string values defined by solutions (with no guarantee of interoperability). +

+

+ The url property represents additional information for the discovery method, such as the URL of the target entity serving the discovery request, for instance the URL of a Thing Directory (if method is `"directory"`), or otherwise the URL of a directly targeted Thing. +

+

+ The query property represents a query string accepted by the implementation, for instance a SPARQL or JSON query. Support may be implemented locally in the WoT Runtime or remotely as a service in a Thing Directory. +

+

+ The fragment property represents a template object used for matching property by property against discovered Things. +

+
+ +
+

The start() method

+
+ Starts the discovery process. The method MUST run the following steps: +
    +
  1. + If invoking this method is not allowed for the current scripting context for security reasons, set the error property to a {{SecurityError}} and abort these steps. +
  2. +
  3. + If discovery is not supported by the implementation, set the error property to {{NotSupportedError}} and abort these steps. +
  4. +
  5. + Let |filter| denote the filter property. +
  6. +
  7. + If the |filter| is defined, +
      +
    • + If |filter|'s |query| is defined, pass it as an opaque string to the underlying implementation to be matched against discovered items. The underlying implementation is responsible to parse it e.g. as a SPARQL or JSON query and match it against the Thing Descriptions found during the discovery process. If queries are not supported, set |this.error| to {{NotSupportedError}} and abort these steps. +
    • +
    +
  8. +
  9. + Create the discovery results internal slot for storing discovered {{ThingDescription}} objects. +
  10. +
  11. + Request the underlying platform to start the discovery process, with the following parameters: +
      +
    • + If |filter|s |method| is not defined or the value is `"any"`, use the widest discovery method supported by the underlying platform. +
    • +
    • + Otherwise if |filter|s |method| is `"local"`, use the local Thing Directory for discovery. Usually that defines Things deployed in the same device, or connected to the device in slave mode (e.g. sensors connected via Bluetooth or a serial connection). +
    • +
    • + Otherwise if |filter|s |method| is `"directory"`, use the remote Thing Directory specified in |filter.url|. +
    • +
    • + Otherwise if |filter|s |method| is `"multicast"`, use all the multicast discovery protocols supported by the underlying platform. +
    • +
    +
  12. +
  13. + When the underlying platform has started the discovery process, set the active property to `true`. +
  14. +
  15. + Whenever a new Thing Description |td:ThingDescription| is discovered by the underlying platform, run the following sub-steps: +
      +
    1. + Fetch |td| as a JSON object |json|. If that fails, set the error property to {{SyntaxError}}, discard |td| and continue the discovery process. +
    2. +
    3. + If |filter|'s |query| is defined, check if |json| is a match for the query. The matching algorithm is encapsulated by implementations. If that returns `false`, discard |td| and continue the discovery process. +
    4. +
    5. + If |filter|'s |fragment| is defined, for each property defined in it, check if that property exists in |json|'s properties and has the same value. If this is `false` in any checks, discard |td| and continue the discovery process. +
    6. +
    7. + Otherwise add |td| to the discovery results. +
    8. +
    9. + At this point implementations MAY control the flow of the discovery process (depending on memory constraints, for instance temporarily stop discovery if the queue is getting too large, or resume discovery when the queue is emptied sufficiently). +
    10. +
    +
  16. +
  17. + Whenever an error occurs during the discovery process, +
      +
    1. + Let |error| be a new {{Error}} object. Set |error|'s |name| to `"DiscoveryError"`. +
    2. +
    3. + If there was an error code or message provided by the Protocol Bindings, set |error|'s |message| to that value as string. +
    4. +
    5. + Set error property to |error|. +
    6. +
    7. + If the error is irrecoverable and discovery has been stopped by the underlying platform, set the active property to `false`. +
    8. +
    +
  18. +
  19. + When the underlying platform reports the discovery process has completed, set the active property to `false`. +
  20. +
+
+
+ +
+

The next() method

+
+ Provides the next discovered {{ThingDescription}} object. The method MUST run the following steps: +
    +
  1. + Return a {{Promise}} |promise:Promise| and execute the next steps in parallel. +
  2. +
  3. + If the active property is `true`, wait until the discovery results internal slot is not empty. +
  4. +
  5. + If discovery results is empty and the active property is `false`, set the done property to `true` and reject |promise|. +
  6. +
  7. + Remove the first {{ThingDescription}} object |td| from discovery results. +
  8. +
  9. + Resolve |promise| with |td| and abort these steps. +
  10. +
+
+
+ +
+

The stop() method

+
+ Stops or suppresses the discovery process. It might not be supported by all discovery methods and endpoints, however, any further discovery results or errors will be discarded and the discovery is marked inactive. The method MUST run the following steps: +
    +
  1. + Request the underlying platform to stop the discovery process. If this returns an error, or if it is not possible, for instance when discovery is based on open ended multicast requests, the implementation SHOULD discard subsequent discovered items. +
  2. +
  3. + Set the active property to `false`. +
  4. +
+
+
+ +
+

Discovery Examples

+

+ The following example finds {{ThingDescription}} objects of Things that are exposed by local hardware, regardless how many instances of WoT Runtime it is running. Note that the discovery can end (become inactive) before the internal discovery results queue is emptied, so we need to continue reading {{ThingDescription}} objects until done. This is typical with local and directory type discoveries. +

+
+        let discovery = new ThingDiscovery({ method: "local" });
+        do {
+          let td = await discovery.next();
+          console.log("Found Thing Description for " + td.title);
+          let thing = new ConsumedThing(td);
+          console.log("Thing name: " + thing.getThingDescription().title);
+        } while (!discovery.done);
+      
+

+ The next example finds {{ThingDescription}} objects of Things listed in a Thing Directory service. We set a timeout for safety. +

+
+        let discoveryFilter = {
+          method: "directory",
+          url: "http://directory.wotservice.org"
+        };
+        let discovery = new ThingDiscovery(discoveryFilter);
+        setTimeout( () => {
+            discovery.stop();
+            console.log("Discovery stopped after timeout.");
+          },
+          3000);
+        do {
+          let td = await discovery.next();
+          console.log("Found Thing Description for " + td.title);
+          let thing = new ConsumedThing(td);
+          console.log("Thing name: " + thing.getThingDescription().title);
+        } while (!discovery.done);
+        if (discovery.error) {
+          console.log("Discovery stopped because of an error: " + error.message);
+        }
+      
+

+ The next example is for an open-ended multicast discovery, which likely won't complete soon (depending on the underlying protocol), so stopping it with a timeout is a good idea. It will likely deliver results one by one. +

+
+        let discovery = new ThingDiscovery({ method: "multicast" });
+        setTimeout( () => {
+            discovery.stop();
+            console.log("Stopped open-ended discovery");
+          },
+          10000);
+        do {
+          let td = await discovery.next();
+          let thing = new ConsumedThing(td);
+          console.log("Thing name: " + thing.getThingDescription().title);
+        } while (!discovery.done);
+      
+
+
+ +

Security and Privacy

+

+ A detailed discussion of security and privacy considerations for the Web of Things, including a threat model that can be adapted to various circumstances, is + presented in the informative document [[!WOT-SECURITY-GUIDELINES]]. + 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-BEST-PRACTICES]]. + That document may be updated as security measures evolve. + Following these practices does not guarantee security, + but it might help avoid common known vulnerabilities. +

+
+ The WoT security risks and possible mitigations are concerning the following groups: + +
+ +
+

Scripting Runtime Security and Privacy Risks

+

+ This section is normative and contains specific risks relevant for the WoT Scripting Runtime. +

+ +
+

Corrupted Input Security and Privacy Risk

+

+ 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. +

+
Mitigation:
+ Implementors of this API SHOULD perform validation on all script inputs. In addition to input validation, fuzzing should be used to verify that the input processing is done correctly. There are many tools and techniques in existence to do such validation. More details can be found in [[!WOT-SECURITY-TESTING]]. +
+
+ +
+

Physical Device Direct Access Security and Privacy Risk

+

+ 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). +

+
Mitigation:
+ The WoT Scripting Runtime SHOULD avoid directly exposing the native device interfaces to the script developers. Instead, a WoT Scripting Runtime should provide a hardware abstraction layer for accessing the native device interfaces. Such hardware abstraction layer should refuse to execute commands that might put the device (or environment) to an unsafe state. + Additionally, in order to reduce the damage to a physical WoT device in cases a script gets compromised, it is important to minimize the number of interfaces that are exposed or accessible to a particular script based on its functionality. +
+
+ +
+

Provisioning and Update Security Risk

+

+ 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. +

+
Mitigation:
+ Post-manufacturing provisioning or update of scripts, + WoT Scripting Runtime or any related data should be done in a secure fashion. + A set of recommendations for secure update and post-manufacturing + provisioning can be found in [[!WOT-SECURITY-GUIDELINES]]. +
+
+ +
+

Security Credentials Storage Security and Privacy Risk

+

+ 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. +

+
Mitigation:
+ The WoT Scripting Runtime should securely store the provisioned security credentials, guaranteeing their integrity and confidentiality. + In case there are more than one tenant on a single WoT-enabled device, a WoT Scripting Runtime should guarantee isolation of each tenant provisioned security credentials. + Additionally, in order to minimize a risk that provisioned security credentials get compromised, the WoT Scripting Runtime should not expose any API for scripts to query the provisioned security credentials. +
+
+
+ +
+

Script Security and Privacy Risks

+

+ This section describes specific risks relevant for script developers. +

+ +
+

Corrupted Script Input Security and Privacy Risk

+

+ 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. +

+
Mitigation:
+ Script developers should perform validation on all application defined script inputs. In addition to input validation, fuzzing could be used to verify that the input processing is done correctly. There are many tools and techniques in existence to do such validation. More details can be found in [[!WOT-SECURITY-TESTING]]. +
+
+ +
+

Denial Of Service Security Risk

+

+ If a script performs a heavy functional processing on received requests before the request is authenticated, it presents a great risk for Denial-Of-Service (DOS) attacks. +

+
Mitigation:
+ Scripts should avoid heavy functional processing without prior successful + authentication of requestor. The set of recommended authentication mechanisms + can be found in [[!WOT-SECURITY-BEST-PRACTICES]]. +
+
+ +
+

Stale TD Security Risk

+

+ During the lifetime of a WoT network, a content of a TD can change. + This includes its identifier, which might not be an immutable one and might be updated periodically. +

+
Mitigation:
+ Scripts should use this API to subscribe for notifications + on TD changes and do not rely on TD values to remain persistent. +
+

+ While stale TDs can present a potential problem for WoT network operation, + it might not be a security risk. +

+
+
+
+ +

Terminology and conventions

+

+ The generic WoT terminology is defined in [[!WOT-ARCHITECTURE]]: Thing, Thing Description (in short TD), Web of Things (in short WoT), WoT Interface (same as WoT network interface), Protocol Bindings, WoT Runtime, Consuming a Thing Description, Thing Directory, WoT Interactions, Property, Action, Event, + + DataSchema, Form etc. +

+

+ JSON-LD is defined in [[!JSON-LD]] as a JSON document that is augmented with support for Linked Data. +

+

+ JSON Schema is defined in these specifications. +

+

+ The terms + URL, + URL scheme, + URL host, + URL path, + URL record, + parse a URL, + absolute-URL string, + path-absolute-URL string, + basic URL parser + are defined in [[!URL]]. +

+

+ The terms + MIME type, + Parsing a MIME type, + Serializing a MIME type, + valid MIME type string, + JSON MIME type + are defined in [[!MIMESNIFF]]. +

+

+ The terms + UTF-8 encoding, + UTF-8 decode, + encode, + decode + are defined in [[!ENCODING]]. +

+

+ string, + parse JSON from bytes and + serialize JSON to bytes, + are defined in [[!INFRA]]. +

+

+ {{Promise}}, + Error, + JSON, + JSON.stringify, + JSON.parse, + internal method and + internal slot are defined in [[!ECMASCRIPT]]. +

+

+ The terms + browsing context, + top-level browsing context, + global object, + current settings object, + executing algorithms in parallel + are defined in [[!HTML5]] and are used in the context of browser implementations. +

+

+ The term + + secure context is defined in [[!WEBAPPSEC]]. +

+

+ IANA media types (formerly known as MIME types) are defined in + RFC2046. +

+

+ The terms hyperlink reference and relation type are defined in [[!HTML5]] and RFC8288. +

+
+ +
+

API design rationale

+

+ API rationale usually belongs to a separate document, but in the WoT case + the complexity of the context justifies including basic rationale here. +

+

Approaches to WoT application development

+

+ The WoT Interest Group and Working Group have explored different + approaches to application development for WoT that have been all + implemented and tested. +

+

No Scripting API

+

+ It is possible to develop WoT applications that only use the + WoT network interface, typically exposed by a WoT gateway that + presents a REST-ful API towards clients and implements IoT protocol + plugins that communicate with supported IoT deployments. One such + implementation is the + Mozilla WebThings platform. +

+
+

Simple Scripting API

+

+ 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');
+        
+
+

This API, aligned with the [[[WOT-TD]]] specification

+

+ 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 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. +

+
+          let res = await fetch(‘https://td.my.com/lock-00123’);
+          let td = await res.json();
+          let lock = new ConsumedThing(td);
+          console.log(lock.readProperty(‘status’));
+          lock.invokeAction(‘open’, 'withThisKey');
+        
+
+

+ In conclusion, the WoT WG decided to explore the third option that + closely follows the [[[WOT-TD]]] 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 [[[WOT-TD]]] 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. +

+
+

Fetching and validating a TD

+

+ The fetch(url) method has been part of this API in earlier versions. However, now fetching a TD given a URL should be done with an external method, such as the Fetch API or a HTTP client library, which offer already standardized options on specifying fetch details. The reason is that while simple fetch operations (covering most use cases) could be done in this API, when various fetch options were needed, there was no point in duplicating existing work to re-expose those options in this API. +

+

+ Since fetching a TD has been scoped out, and TD validation + is defined externally in the [[[WOT-TD]]] specification, that is scoped out, too. + This specification expects a TD as + parsed JSON object that has been validated according to the [[[WOT-TD]]] specification. +

+
+

Factory vs constructors

+

+ The factory methods for consuming and exposing Things are asynchronous and fully validate the input TD. In addition, one can also construct {{ConsumedThing}} and {{ExposedThing}} by providing a parsed and validated TD. Platform initialization is then done when needed during the WoT interactions. So applications that prefer validating a TD themselves, may use the constructors, whereas applications that leave validation to implementations and prefer interactions initialized up front SHOULD use the factory methods on the WoT API object. +

+
+

Observers

+

+ 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. +

+
+

Using Events

+
+ This API ended up not using software events at all, for the following + reasons: +
    +
  • + Subscription to WoT Events may be different from handling software events (subscription might need parameters, might involve security tokens etc). +
  • +
  • + Most implementations are for Node.js and browser implementations will likely be libraries (because possible dependency management issues in native implementations), using Events has been challenging. +
  • +
  • + Observing Property changes and handling WoT Events is done with the solution above. +
  • +
+
+
+

Polymorphic functions

+

+ 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 [[[WOT-TD]]] specification. +

+
+
+ +

Changes

+
+ The following is a list of major changes to the document. Major versions of this specification are the following: + +
+

+ For a complete list of changes, see the github change log. You can also view the recently closed issues. +

+
+ +

Full Web IDL

+ +
+ +

Acknowledgements

+

+ 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. +

+
+ + + diff --git a/primer/README.md b/primer/README.md new file mode 100644 index 00000000..a05c12df --- /dev/null +++ b/primer/README.md @@ -0,0 +1,235 @@ +# Primer for Scripting API + +This document attempts to explain how [W3C WoT(Web of Things) Scripting API](https://w3c.github.io/wot-scripting-api/index.html) works. + +## How Scripting API works? + +Scripting API is a building block to provide means for discovery, provisioning and control of thing that realizing [WoT Architecture](https://w3c.github.io/wot/architecture/wot-architecture.html). Scripting API consists of mainly two types of functions i.e. Expose Thing and Consumed Thing that are incorporated in WoT Server, WoT Client, or WoT Servient. The following sections attempt to explain how those work. + +### 1\. ExposedThing in WoT Server + +ExposedThing controls building block of WoT and manages life cycle of WoT Server API. + +#### (A) Provisioning: Development and Setup + +Given a script that has ExposedThing command tied with device access function, ExposedThing generate a [WoT Thing Description +(TD)](https://w3c.github.io/wot-thing-description/) and expose the server API. + +![Fig.1](./images/Fig1.png) + + +The followings shows the sequence of this figure. +(1) In the development phase of WoT Server, Write a script uses ExposedThing with callback function that can accessing a thing.
+(2) In the setup phase, run the script and make each object.
+(3) When exposing WoTAPI, as an option, it would generate the TD and register to TD repository.
+(4) Invoking expose command, expose WoTAPI based on the object made by parsing the script. + +#### (B) Runtime: Control of thing + +At the runtime, when a WoTAPI is called,the callback is executed to control the Thing. + +![Fig.2](./images/Fig2.png) + +#### (C) Runtime provisioning: add thing + +Given another script that has ExposedThing command tied with device access function, ExposedThing generate a TD and expose the server API. + +![Fig.3](./images/Fig3.png) + +#### (D) Runtime: unregister thing + +A script that has an unregister thing can unregister the exposed thing, the callback function, and the TD. + +![Fig.4](./images/Fig4.png) + +#### (E) Expose thing with semantics + +A script that comes with SemanticType generates a TD with semantic expression. It can be searched by accessing TD repository. + +![Fig.5](./images/Fig5.png) + +#### (F) Runtime provisioning: Set permission to WoTAPI + +Generate a security token using e.g. IETF ACE and set permission to WoTAPI. Check the security token when WoTAPI is called. + +![Fig.17](./images/Fig17.png) + +### 1-1\. Using Expose Thing + +ExposedThing can be used in any layers i.e. Client, Cloud/Server, Gateway/Edge, and Device. + +![Fig.6](./images/Fig6.png) + +ExposedThing in various layers and combinations. + +![Fig.7](./images/Fig7.png) + +### 2\. ConsumedThing in WoT Client + +ConsumedThing controls building blocks of WoT and manages life cycle of WoT Client API. + +#### (A) Runtime provisioning + +Search a device initiates a discovery and set up a ConsumedThing API to use. + +![Fig.8](./images/Fig8.png) + +The followings shows the sequence of this figure. +(a) Search a device from an application using discovery API.
+(i) Discovery function accesses to the TD repository.
+(ii) Download the TD.
+(iii) ConsumedThing parses the TD.
+(iv) ConsumedThing exposes client API.
+(a') Application receive the search result. + +#### (B) Runtime: Control of thing with abstracted manner + +Application access the device with method call. ConsumedThing interprit the access as WoTAPI call. + +![Fig.9](./images/Fig9.png) + +#### (C) Runtime provisioning: search and use another thing + +Search another device initiates a discovery and set up the Thing API to use. The sequence is the same with (a). + +![Fig.10](./images/Fig10.png) + +### 2-1\. Using Consumed Thing + +ConsumedThing can be used in any layers. + +![Fig.11](./images/Fig11.png) + +ConsumedThing in various layers and combinations. + +![Fig.12](./images/Fig12.png) + +### 2-2\. Example: WoT Server and WoT Client +A use case that uses a WoT Server and a WoT Client is shown here i.e. An electronic appliance with WoT server is controlled by a remote controller with WoT client. + +![Fig.13](./images/Fig13.png) + +The followings shows the sequence of this Figure. +(1) Script has ExposedThing call with callback function that has access method to a LED lamp.
+(2) Run an script that has scripting API call.
+(3) ExposeThing generate a TD.
+(3') Register the TD to TD repository.
+(4) ExposeThing expose server API.
+(a) Application issues discovery command to search LED lamp.
+(i) ConsumedThing discover command to Discovery function.
+(ii) The discovery function queries TD repository to search LED lamp and receive the TD as the query result.
+(iii) ConsumedThing parses the TD.
+(iv) ConsumedThing expose client API.
+(a') Application receive result of the discovery.
+(b) Application for example issue a command for turn on the LED lamp. ConsumedThing interprit the command to WoTAPI command then access WoT server that manage the LED lamp. ExposedThing in the WoT server call callback function to turn on the LED lamp. + +### 3\. ConsumedThing and ExposedThing in WoT Servient + +WoT servient consists of three part i.e. Server, Client, and Legacy communication. It deals ConsumedThing and ExposedThing methods described above. Application layer may have multiple scripts. + +### 3-1\. Provisioning / Control of thing + +The followings shows the sequence of how WoT servient works for the provisioning and control of thing. + +(1) A script that has ExposedThing call with callback to control a LED lamp.
+(2) The script generates ExposedThing object.
+(3) ExposedThing generates a TD.
+(3') Register the TD to TD repository.
+(4) ExposedThing expose server API.
+(i) An application issues discover command to discovery function.
+(ii) The discovery function queries TD repository or uses local discovery to search LED lamp and receive the TD.
+(iii) ConsumedThing parses the TD.
+(iv) ConsumedThing expose Client API.
+(b) WoTAPI of Server receives a command for turn on. Then callback function registerd to ExposedThing is called. If the LED lamp is connected to Client, Protocol Binding interprit the command in the callback to appropriate WoTAPI command. If the LED lamp is connected to Legacy Communication, the callback function issues the legacy communication command to control the LED lamp. + +![Fig.14](./images/Fig14.png) + +### 3-2\. Event handling + +The followings shows the sequence of how WoT servient works for the events handling. +(c) A WoT Servient that is connected to another WoT Servient , WoT Server, or a Legacy device receive an event from them. +(d) A callback function described in script handles the event. For example: +- (e) Access to underneath device: Issue action or property call described in TD#1 to the underneath device through ClientAPI. +- (f) Proxy event: Transfer and issue same event to ExposedThing/WoTAPI. TD#1 and TD#2 have same definitions about the event. +- (g) Generate another event: Transform the event and issue as another event through ExposedThing/WoTAPI. TD#1 has definition of the event defined by the device and TD#2 has definition of new event that is transformed from the original event. +- (h) Make linked data: Save the event/events and allow to access by a property call through WoTAPI. TD#2 has a property definition that returns the event/events data based on an URI call. + +![Fig.18](./images/Fig18.png) + +### 3-3\. Example: Voting +A use case that uses WoT Servients and a WoT Client is shown here. WoT servient #3 maybe on the cloud provide devices shadow and consolidate devices and expose a service. A script for Thing to Thing (T2T) service provides two functions: +- Using heat sensor, automatically turn on air conditioner if getting cold. +- Turn on/off air conditioner by voting "feel cold" or "feel hot" from WoT clients. Based on the consensus, T2T script issue on/off command of the air conditioner. + +Four types of scripts are placed in the application layers: +- control script for a heat sensor to WoT Servient #1 +- control script for an air conditioner to WoT Servient #2 +- Thing to thing service to WoT Servient #3 +- Voting script to WoT Client + +![Fig.15](./images/Fig15.png) + +The followings shows the sequence of the fugure. + +(1) + +- Develop a control script for a heat sensor that have callback function and upload to application layer in WoT Servient #1. +- Develop a control script for an air conditioner that have callback function and upload to application layer in WoT Servient #2. +- Develop a T2T service script that has ExposedThing command and calling method of things to application layer in WoT Servient #3. +- Develop a Voting script that uses ConsumedThing command tha t is accesing to calling method of Thing to thing (T2T) service then download to WoT Client.
+ +(a) + +- A heat sensor script tries to discover heat sensor through discovery mechanism. +- An air conditioner script tries to discover air conditioner through discovery mechanism. +- A T2T service script tries to discover the heat sensor and the air conditioner through discovery mechanism that is query TD repository. + +(a') T2T service discovers things and gets TDs from TD repository.
+ +(iii) + +- ConsumedThing of WoT Servient #3 and WoT Client parse the TD . + +(iv) + +- ConsumedThing of WoT Servient #1 expose a client API for receiving periodical data from heat sensor. +- ConsumedThing of WoT Servient #2 expose a client API for controlling an air conditioner. +- ConsumedThing of WoT Servient #3 expose client APIs for receiving data from WoT Servient #1 and controlling an air conditioner to WoT Servient #2. +- ConsumedThing of WoT Client expose a client API for voting. + +(2) + +- Control script for heat sensor registers a callback for event to ExposedThing. The callback calls the Client API that receive the data of heat sensor. +- Control script for air conditioner registers a callback for action to ExposedThing. The callback calls the Client API that controls air conditioner. +- T2T service script for voting registers a callback for action to ExposedThing. The callback calls the Client API that controls air conditioner of WoT Servient #2. + +(3) + +- ExposeThing of WoT Servient #1 generates a TD for receiving the sensor data. +- ExposeThing of WoT Servient #2 generates a TD for controllig air conditioner. +- ExposeThing of WoT Servient #3 generates a TD for voting. + +(3') ExposedThings register the TDs to TD repository.
+(4) ExposedThing expose the server APIs.
+ +At the runtime (b):
+Control route 1: T2T control + +- Heat sensor periodically generate heat values. +- WoT Servient #1 receives the raw data and issues a callback in the object of ConsumedThing. Then the control script for heat sensor issues an event to T2T service in WoT Servient #3 that subscribe the event. +- T2T service script check the value whether it surpass the threshold, if so, it calls turn on/off the air conditioner by issueing a WoTAPI command to WoT Servient #2\. When receiving the command, callback function in ExposedThing is called and control the air conditioner. + +Control route 2: Voting + +- Users can vote to express their preference by issueing too hot or too cold from a voting application that calls the object of ConsumedThing and ConsumedThing issues a voting command. The voting script issues a message to T2T service script. T2T service script counts the voting and if it surpass the threshold, issue command to control air conditioner by accessing Client API. +- The object of ExposedThing receives voting from WoT API that connected to clients, the T2T service receives, counts voting, and if the count surpass the threshold, the T2T service calls callback function. +- T2T service calls the control script for airconditioner, the control script issues command via the object of ConsumedThing to the air conditioner. + +### 3-4\. Example: Layered structure + +WoT can provide layerd structure and following is an example. +WoT Server are used in devices. +WoT Servient are used in gateways / edges and on the Cloud service. +WoT Client are used in clients. + +![Fig.16](./images/Fig16.png) diff --git a/primer/images/Fig1.png b/primer/images/Fig1.png new file mode 100644 index 00000000..9872ca14 Binary files /dev/null and b/primer/images/Fig1.png differ diff --git a/primer/images/Fig10.png b/primer/images/Fig10.png new file mode 100644 index 00000000..db40bbcd Binary files /dev/null and b/primer/images/Fig10.png differ diff --git a/primer/images/Fig11.png b/primer/images/Fig11.png new file mode 100644 index 00000000..ad163294 Binary files /dev/null and b/primer/images/Fig11.png differ diff --git a/primer/images/Fig12.png b/primer/images/Fig12.png new file mode 100644 index 00000000..3f3ec3ad Binary files /dev/null and b/primer/images/Fig12.png differ diff --git a/primer/images/Fig13.png b/primer/images/Fig13.png new file mode 100644 index 00000000..7e76a846 Binary files /dev/null and b/primer/images/Fig13.png differ diff --git a/primer/images/Fig14.png b/primer/images/Fig14.png new file mode 100644 index 00000000..2f7e687d Binary files /dev/null and b/primer/images/Fig14.png differ diff --git a/primer/images/Fig15.png b/primer/images/Fig15.png new file mode 100644 index 00000000..d4680ae1 Binary files /dev/null and b/primer/images/Fig15.png differ diff --git a/primer/images/Fig16.png b/primer/images/Fig16.png new file mode 100644 index 00000000..be34a524 Binary files /dev/null and b/primer/images/Fig16.png differ diff --git a/primer/images/Fig17.png b/primer/images/Fig17.png new file mode 100644 index 00000000..d927936c Binary files /dev/null and b/primer/images/Fig17.png differ diff --git a/primer/images/Fig18.png b/primer/images/Fig18.png new file mode 100644 index 00000000..3903f55c Binary files /dev/null and b/primer/images/Fig18.png differ diff --git a/primer/images/Fig2.png b/primer/images/Fig2.png new file mode 100644 index 00000000..2f5a3a40 Binary files /dev/null and b/primer/images/Fig2.png differ diff --git a/primer/images/Fig3.png b/primer/images/Fig3.png new file mode 100644 index 00000000..84bffb64 Binary files /dev/null and b/primer/images/Fig3.png differ diff --git a/primer/images/Fig4.png b/primer/images/Fig4.png new file mode 100644 index 00000000..29400b8a Binary files /dev/null and b/primer/images/Fig4.png differ diff --git a/primer/images/Fig5.png b/primer/images/Fig5.png new file mode 100644 index 00000000..a5c2bbd4 Binary files /dev/null and b/primer/images/Fig5.png differ diff --git a/primer/images/Fig6.png b/primer/images/Fig6.png new file mode 100644 index 00000000..4f47ae4b Binary files /dev/null and b/primer/images/Fig6.png differ diff --git a/primer/images/Fig7.png b/primer/images/Fig7.png new file mode 100644 index 00000000..66c310e2 Binary files /dev/null and b/primer/images/Fig7.png differ diff --git a/primer/images/Fig8.png b/primer/images/Fig8.png new file mode 100644 index 00000000..674b4a7f Binary files /dev/null and b/primer/images/Fig8.png differ diff --git a/primer/images/Fig9.png b/primer/images/Fig9.png new file mode 100644 index 00000000..fe2965c5 Binary files /dev/null and b/primer/images/Fig9.png differ diff --git a/rationale.md b/rationale.md new file mode 100644 index 00000000..ca0376ee --- /dev/null +++ b/rationale.md @@ -0,0 +1,50 @@ +# Rationale for Scripting API design + +This document attempts to explain why various decision for [W3C WoT(Web of Things) Scripting API](https://w3c.github.io/wot-scripting-api/index.html) were made the way they were. + +## Using factories vs constructors +As discussed in [issue 3](https://github.com/w3c/wot-scripting-api/issues/3), and as suggested [here](https://github.com/w3c/wot-scripting-api/issues/3#issuecomment-283746764), the guidelines are these: + +> The root WoT object should not be constructible. It represents the UA's magic ability to discover things, similar to how the Navigator object represents the UA's magic ability to do a bunch of stuff. A namespace might be a good replacement here, if it truly has no state. + +> Avoid constructor overloads. A true constructor should be something that directly copies the given essential data into internal fields. If there is a way to infer the essential data from some other data, then that should be a factory. So maybe ThingDescription is the essential data, and if we can infer that from a name or URL, then factory should be used (perhaps static factory, e.g. ExposedThing.fromName()). + +> The idea of using a builder pattern (first create an X, then call X.expose() on it to turn into another object, or X-with-UA-magic) is rather unidiomatic in JavaScript. The better way to represent something without UA magic is just a dictionary. Having the same class represent two very distinct things is not great. + + +Resolutions: +- The browser implementations of the WoT Scripting API uses a namespace object `wot` in the browser. +- Non-browser implementations that use various runtimes may use either a namespace object `wot`, or an API object provided by the `require()` or `import()` or similar mechanisms. +- The `ConsumedThing` and `ExposedThing` objects are expected to be created by factory methods, though constructors are defined. +- Interaction data can be retrieved with an attempted conversion by implementation as convenience interface for most JavaScript types, or as streams the applications can interpret. +- Errors during protocol operations are exposed to applications. + +## Discovery API + +Represents the second stage of discovery in the [2-stage discovery process](https://github.com/w3c/wot-discovery/blob/master/proposals/directory.md), i.e. the +operational stage when discovery is configured and discovery queries may be served. + +The discovery results may be filtered either at the source or at reception, by constraints made on the Thing Description. + +Based on [issue 16](https://github.com/w3c/wot-scripting-api/issues/16) there is a need to be able to tell the WoT Runtime to stop discovery (or in the case of open ended requests, suppress further discovery results). Therefore returning `Promise` was not an option any more, since cancellable `Promise`s were [dropped](https://github.com/tc39/proposal-cancelable-promises). + +Resolutions: +- Use [Observables](https://github.com/tc39/proposal-observable) or similar pattern for controlling the discovery process (subscribe, unsubscribe, handle notifications). +- Use a single filter definition that also contains a property for discovery type, defaulting to `"any"`. It is simpler and more intuitive to use than having a separate parameter for discovery type. Some of the discovery types, such as registry/directory based discovery also require another parameter for the address of the directory. This can be provided as a required property in the discovery filter, described in the discovery algorithm. + +## Server API (`ExposedThing`) +Scripts that define Exposed Things should ensure the following: +1. define properties, actions and events according to the Thing Description. +2. define request handler functions to implement the serving end for the Client API. + +## Client API (`ConsumedThing`) +Scripts that use the Client API are basically sending requests to servers in order to retrieve or update properties, invoke actions, and observe properties, actions and events. When the `ConsumedThing` is fetched, its Thing Description is also fetched, then client scripts can track changes by subscribing to events that signal TD changes. + +For browser compatibility of the Client API, events are used with the DOM convention: an Event (or Event sub-class) object is passed as an argument to the event listener, which contains a property with the event payload data, instead the Node.js convention where payload is directly passed to the event listener as arguments. + +There is no Client API for creating Things. ExposedThings can be created only locally through the Server API. However, a WoT Runtime may have a special management Thing exposed that would accept actions for installing, uninstalling, running and stopping scripts in that WoT Runtime. These scripts may create local ExposedThings, so the use case of remote Thing creation can be implemented. + +Write interactions only return success or error, not the written value as well. +Based on [issue 193](https://github.com/w3c/wot-scripting-api/issues/193) and discussions during Scripting calls, TDs should fully capture the schema of the Property values, including precision and alternative formats, so that these should not be determined from analyzing the return value. If a return value is needed from an interaction, an +Action should be used instead of a Property. + diff --git a/releases/fpwd/Overview.html b/releases/fpwd/Overview.html new file mode 100644 index 00000000..590ee849 --- /dev/null +++ b/releases/fpwd/Overview.html @@ -0,0 +1,2481 @@ + + + + + + + + + + + Web of Things (WoT) Scripting API + + + + + + + + + + + + + +
+

Abstract

+

+ The Web of Things (WoT) provides layered interoperability between Things by using the WoT Interfaces. +

+

+ This specification describes a programming interface representing the WoT Interface that allows scripts run on a Thing to discover and consume (retrieve) other Things and to expose Things characterized by properties, Actions and Events. +

+

+ Scripting is an optional "convenience" building block in WoT and it is typically used in gateways 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 like Thing Directory. +

+
+
+

Status of This Document

+

+ This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports 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. +

+
+
Editor's note: The W3C WoT WG is asking for feedback
+

+ Please contribute to this draft using the GitHub Issue feature 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 a First Public Working Draft. + This document is intended to become a W3C Recommendation. +

+

+ Comments regarding this document are welcome. Please send them to + public-wot-wg@w3.org (subscribe, + archives). +

+

+ Publication as a First Public Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate + to cite this document as other than work in progress. +

+

+ This document was produced by a group operating under the + 5 February 2004 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 1 March 2017 W3C Process Document. +

+ + +
+ +
+ +

1. Introduction

+

+ The overall WoT concepts are described in the WoT Architecture document. The Web of Things is made of entities (Things) + that can describe their capabilities in a machine-interpretable format, the Thing Description (TD) and expose these capabilities through the WoT Interface. Support for scripting is optional for WoT devices. +

+

+ By consuming a TD, a client Thing creates a runtime resource model that allows accessing + the properties, Actions and Events exposed by the server Thing. +

+

+ Exposing a Thing requires defining a Thing Description and instantiating a software stack needed + to serve requests for accessing the exposed properties, Actions and Events. This specification describes how + to expose and consume Things by a script. +

+
+
Note
+

+ Typically scripts are meant to be used on devices able to provide resources (with a WoT interface) for managing (installing, updating, running) scripts, such as + bridges or gateways that expose and control simpler devices as WoT Things. +

+
+

+ For an introduction on how scripts could be used in Web of Things, check the Primer document. For some background + on API design decisions check the Rationale document. +

+
+
+ +

2. Use Cases

+

This section is non-normative.

+

+ The following scripting use cases are covered in this specification: +

+ +

+ The following use cases are being considered for next versions: +

+ +
+
+ +

3. The WoT object

+

The WoT object is the main API entry point and it is exposed by an implementation of the WoT Runtime. The WoT object has + no internal state and provides methods for discovering, consuming and exposing a Thing. +

+
+
Note
+

+ Browser implementations SHOULD use a namespace object such as wot, and Node.js-like runtimes MAY provide the + API object through the require() or import mechanism. +

+
+
+
interface WoT {
+    Observable<ConsumedThing> discover(optional ThingFilter filter);
+    Promise<ConsumedThing>    consume(USVString url);
+    Promise<ExposedThing>     expose(ThingInit init);
+};
+
+
+
Editor's note
+

+ The algorithms for the WoT methods will be specified later. +

+
+
+

3.1 The discover() method

+

+ Starts the discovery process that will provide ConsumedThing + objects that match the optional argument ThingFilter + . When the argument is not provided, starts the widest discovery the Thing Description and Protocol Bindings allow. Returns an Observable object that can be subscribed and unsubscribed to. +

+
+

3.1.1 The ThingFilter dictionary

+

+ The ThingFilter dictionary that represents the constraints for discovering Things + as key-value pairs. +

+
+
dictionary ThingFilter {
+    (DiscoveryType or DOMString) method = "any";
+    USVString                    url;
+    Dictionary                   description;
+};
+
+

+ The method property represents the discovery type that should be used in the discovery process. The + possible values are defined by the DiscoveryMethod + enumeration that can be extended by string values defined by solutions (with no guarantee of interoperability). +

+

+ The url property represents additional information for the discovery method, such as the URL of the Thing Directory server to be used. +

+

+ The description property represents additional information for the discovery method in the + form of a set of key-value pairs, as defined in the Thing Description. +

+
+
Editor's note
+

+ The DiscoveryMethod enumeration can be extended by the Thing Description with values that are not specified here. This extensibility of DiscoveryMethod by proprietary or private methods is a working assumption until + consensus is formed and may be removed later. +

+
+
+
Editor's note
+

+ The ThingFilter dictionary may be extended later with further attributes.

+
+
+
+

3.1.2 The DiscoveryMethod enumeration

+
+
enum DiscoveryMethod {
+    "any",
+    "local",
+    "nearby",
+    "directory",
+    "broadcast",
+    "other"
+};
+
+

+ The DiscoveryMethod enumeration represents the discovery type to be used: +

+
    +
  • "any" does not provide any restriction
  • +
  • "local" for discovering Things + defined in the same device
  • +
  • + "nearby" for discovering Things + nearby the device, e.g. by Bluetooth or NFC +
  • +
  • + "directory" for discovery based on a service provided by a directory or repository + of Things +
  • +
  • + "broadcast" for an open ended discovery based on sending a request to a broadcast + address +
  • +
  • + "other" for a proprietary method defined by the solution. +
  • +
+
+
+
+

3.2 The consume() method

+

+ Accepts an url argument and returns a Promise of a ConsumedThing. +

+
+
+

3.3 The expose() method

+

+ Returns a Promise of a locally created ExposedThing based on the provided + initialization parameters. +

+
+
Editor's note
+

+ The reason ExposedThings are created by a factory method instead of a constructor is that an ExposedThing may be created in the local WoT Runtime or in a remote runtime. Even though currently only local creation is supported, the method is designed with this possible + future compatibility in mind. +

+
+
+

3.3.1 The ThingInit dictionary

+
+
dictionary ThingInit {
+    DOMString  name;
+    USVString  url;
+    Dictionary description;
+};
+
+

The ThingInit dictionary contains properties to initialize a Thing: +

+
    +
  • The name attribute represents the user given name of the Thing.
  • +
  • The url attribute represents the address of the Thing.
  • +
  • The description attribute represents the Thing Description of the Thing.
  • +
+
+
+
+

3.4 Examples

+
+
Example 1: Discover Things via directory
+
let discoveryType = { method: "directory", url: "http://directory.wotservice.org" };
+let subscription = wot.discover(discoveryType).subscribe(
+  thing => { console.log("Found Thing " + thing.url); },
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout(
+  () => { subscription.unsubscribe(); console.log("Discovery timeout"); },
+  5000);
+
+
+
Note
+

+ Note that canceling a discovery (through unsubscribe) may not be successful in all cases, for instance when discovery is based on open ended broadcast requests. However, once unsubscribe() has been called, implementations + MUST suppress further event handling ( i.e. further discoveries and errors) on the Observable. Also, a discovery error may not mean the end of the discovery process. However, in order to respect + Observable semantics (error always terminates processing), implementations MUST close or suppress further event handling on the Observable. +

+
+
+
Example 2: Discover Things exposed by local hardware
+
let subscription = wot.discover({ method: "local" }).subscribe(
+  thing => { console.log("Found local Thing " + thing.url); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
Example 3: Discover Things exposed nearby, e.g. via Bluetooth
+
let subscription = wot.discover({ method: "nearby", description: {protocol: "BLE4.2"} }).subscribe(
+  thing => { console.log("Found nearby Thing " + thing.url); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
Example 4: Discover Things exposed in a proprietary way
+
let subscription = wot.discover({ method: "other", description: { solution: "XYZ123", key: "..."} }).subscribe(
+  thing => { console.log("Found Thing " + thing.url); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +

4. The ConsumedThing interface

+

+ The ConsumedThing interface is a client API for sending requests to servers in order to retrieve or update properties, invoke Actions, and observe properties, Actions and Events. +

+
+
interface ConsumedThing {
+    readonly attribute DOMString        name;
+    readonly attribute USVString        url;
+    readonly attribute ThingDescription description;
+    Promise<any>  invokeAction(DOMString name, any parameters);
+    Promise<void> setProperty(DOMString name, any value);
+    Promise<any>  getProperty(DOMString name);
+    ConsumedThing addListener(DOMString eventName, ThingEventListener listener);
+    ConsumedThing removeListener(DOMString eventName,
+                                 ThingEventListener listener);
+    ConsumedThing removeAllListeners(optional DOMString eventName);
+    Observable    observe(DOMString name, RequestType requestType);
+};
+
+callback ThingEventListener = void (Event event);
+
+

+ Represents a local proxy object of the remote Thing. +

+ +
+

4.1 The invokeAction() method

+

+ Takes the Action name from the name argument and the list of parameters, then requests from the underlying platform and the Protocol Bindings to invoke the Action on the remote Thing and return the result. Returns a Promise that resolves with the return value or rejects with an Error. +

+
+
+

4.2 The setProperty() method

+

+ Takes the Property name as the name argument and the new value as the value argument, then requests from the underlying platform and the Protocol Bindings to update the Property on the remote Thing and return the result. Returns a Promise that resolves on success or rejects with an Error. +

+
+
+

4.3 The getProperty() method

+

+ Takes the Property name as the name argument, then requests from the underlying platform and the Protocol Bindings to retrieve the Property on the remote Thing and return the result. Returns a Promise that resolves with the Property value or rejects with an Error. +

+
+
+

4.4 The addListener() method

+

+ Adds the listener provided in the argument listener to the Event name provided in the argument eventName. +

+
+
+

4.5 The removeListener() method

+

+ Removes a listener from the Event identified by the provided eventName and listener argument. +

+
+
+

4.6 The removeAllListeners() method

+

+ Removes all listeners for the Event provided by the eventName optional argument, or if that was not provided, then removes all listeners from all Events. +

+
+
+

4.7 The observe() method

+

+ Returns an Observable for the Property, Event or Action specified in the name argument, allowing subscribing and unsubscribing to notifications. The requestType specifies whether a Property, an Event or an Action is observed. +

+
+
Editor's note
+

+ The observe() method could replace addListener() and removeListener(), though they could be kept for convenience. +

+
+
+
+

4.8 The ThingEventListener callback

+

+ A function called with an Event object when an event is emitted. +

+
+
+

4.9 Events

+

+ Clients can subscribe to the Events defined in ExposedThing events. The event types are described in this section. +

+
+

4.9.1 The PropertyChangeEvent interface

+
+
[Constructor(PropertyChangeEventInit init)]
+interface PropertyChangeEvent : Event {
+    readonly attribute PropertyChangeEventInit data;
+};
+
+

+ The data attribute represents the changed Property. +

+
+
4.9.1.1 The PropertyChangeEventInit dictionary
+
+
dictionary PropertyChangeEventInit {
+    DOMString name;
+    any       value;
+};
+
+

The name> attribute represents the Property name.

+

The value attribute represents the new value of the Property.

+
+
+
+

4.9.2 The ActionInvocationEvent interface

+
+
[Constructor(ActionInvocationEventInit init)]
+interface ActionInvocationEvent : Event {
+    readonly attribute ActionInvocationEventInit data;
+};
+
+

+ The data attribute represents the notification data from the Action invocation. +

+
+
4.9.2.1 The ActionInvocationEventInit dictionary
+
+
dictionary ActionInvocationEventInit {
+    DOMString actionName;
+    any       returnValue;
+};
+
+
+
Editor's note
+

+ Action parameters could be also included, but it's debatable because privacy reasons. +

+
+

+ The actionName attribute represents the name of the Action that has been invoked. +

+

+ The returnValue attribute represents the return value of the + Action. +

+
+
+
+

4.9.3 The ThingDescriptionChangeEvent interface

+
+
[Constructor(ThingDescriptionChangeEventInit init)]
+interface ThingDescriptionChangeEvent : Event {
+    readonly attribute ThingDescriptionChangeEventInit data;
+};
+
+

+ The data attribute represents the changes that occurred to the Thing Description. +

+
+
4.9.3.1 The ThingDescriptionChangeEventInit dictionary
+
+
dictionary ThingDescriptionChangeEventInit {
+    TDChangeType     type;
+    TDChangeMethod   method;
+    DOMString        name;
+    TDChangeData     data;
+    ThingDescription description;
+};
+
+
    +
  • + The type attribute represents the change type, whether has + it been applied on properties, Actions or Events. +
  • +
  • + The method attribute tells what operation has been applied, + addition, removal or change. +
  • +
  • + The name attribute represents the name of the Property, Action or event that has changed. +
  • +
  • + The description attribute is defined for the + addition and change methods, and represents the new description. +
  • +
  • + The data attribute provides the initialization data for + the added or changed elements. +
  • +
+
+
4.9.3.1.1 The TDChangeMethod enumeration
+
+
enum TDChangeMethod {
+    "add",
+    "remove",
+    "change"
+};
+
+
    +
  • The add value denotes addition of a Property, + Action or event.
  • +
  • The remove value denotes removal of a Property, + Action or event.
  • +
  • The change value denotes a change applied on a Property, Action or event.
  • +
+
+
+
4.9.3.1.2 The TDChangeType enumeration
+ +
    +
  • The property value tells the operation was applied on a Property definition.
  • +
  • The action value tells the operation was applied on a action definition.
  • +
  • The event value tells the operation was applied on an event definition.
  • +
+
+
+
4.9.3.1.3 The TDChangeData type
+

+ Represents the new description of the changed element. Depending on the change type, it can be either a ThingPropertyInit, ThingActionInit, or ThingEventInit. +

+
+
+
+
+
+

4.10 Examples

+

+ Below a ConsumedThing + interface example is given. +

+
+
Example 5: Consume a Thing
+
wot.consume("http://mmyservice.org/mySensor").then( thing => {
+    console.log("Thing " + thing.name + " has been consumed.");
+    console.log("{ " + JSON.serialize(thing) + " }");
+    thing.addListener("onchange", function(event) {
+        if (event instanceof PropertyChangeEvent) {
+            console.log("Property " + event.name + " value has changed to " + event.value);
+        }
+    }).invokeAction("startMeasurement", ["Celsius"]);
+  },
+).catch(error => {
+  console.log("Discovery finished because an error: " + error.message);
+});
+
+
+
+
+ +

5. The ExposedThing interface

+

+ The ExposedThing interface is the server API that allows defining request handlers, properties, Actions, + and Events to a Thing. +

+
+
typedef USVString ThingDescription;
+
+callback RequestHandler = any (Request request);
+
+interface ExposedThing {
+    // define Thing Description modifiers
+    ExposedThing  addProperty(ThingPropertyInit property);
+    ExposedThing  removeProperty(DOMString name);
+    ExposedThing  addAction(ThingActionInit action);
+    ExposedThing  removeAction(DOMString name);
+    ExposedThing  addEvent(ThingEventInit event);
+    ExposedThing  removeEvent(DOMString name);
+    // define request handlers
+    ExposedThing  onRetrieveProperty(RequestHandler handler);
+    ExposedThing  onUpdateProperty(RequestHandler handler);
+    ExposedThing  onInvokeAction(RequestHandler handler);
+    ExposedThing  onObserve(RequestHandler handler);
+    // define how to expose and run the Thing
+    Promise<void> register(optional USVString directory);
+    Promise<void> unregister(optional USVString directory);
+    Promise<void> start();
+    Promise<void> stop();
+    Promise<void> emitEvent(DOMString eventName, any payload);
+};
+
+ExposedThing implements ConsumedThing;
+
+
+

5.1 The ThingDescription type

+

+ WoT provides a unified representation for data exchange between Things, standardized in the Wot Things Description specification. +

+
+
Note
+

+ In this version of the API, Thing Descriptions are represented as opaque strings, denoting a serialized form, for instance JSON or JSON-LD. See Issue 38 and Issue 45. Parsing and composing Thing Descriptions is left for external libraries until + standardized here. +

+
+
+
+

5.2 The Request interface

+
+
interface Request {
+    readonly attribute RequestType type;
+    readonly attribute USVString   from;
+    readonly attribute DOMString   name;
+    readonly attribute Dictionary  options;
+    readonly attribute any         data;
+    Promise respond(any response);
+    void    respondWithError(Error error);
+};
+
+

+ Represents an incoming request the ExposedThing is supposed to handle, for instance retrieving and updating properties, invoking Actions and observing Events (WoT interactions). +

+ +
+

5.2.1 The RequestType enumeration

+
+
enum RequestType {
+    "property",
+    "action",
+    "event",
+    "td"
+};
+
+
    +
  • The value "property" represents requests to retrieve or update a Property.
  • +
  • The value "action" represents requests to invoke an Action.
  • +
  • The value "event" represents requests to emit an event.
  • +
  • + The value "td" represents requests to change the Thing Description, + i.e. to add, remove or modify properties, Actions or Events. +
    +
    Editor's note
    +

    + This functionality is here for the sake of completeness for future versions of the API. Currently there is no corresponding functionality at the ConsumedThing level and it is not guaranteed that a Thing Description could be remotely changed by scripting. +

    +
    +
  • +
+
+
+

5.2.2 The respond() method

+

+ Sends a positive response to the Request based on the Protocol Bindings and includes the data specified by the data argument. +

+
+
+

5.2.3 The respondWithError() method

+

+ Sends a negative response to the Request based on the Protocol Bindings and includes the error specified by the error argument. +

+
+
+
+

5.3 The RequestHandler callback

+

+ Callback function for handling interaction requests. Receives an argument request of type Request + and should return an object or value that is used by Protocol Bindings to reply to the request. The returned type is defined by the Thing Description. +

+
+
+

5.4 The addProperty() method

+

+ Adds a Property defined by the argument and updates the Thing Description. +

+
+

5.4.1 The ThingPropertyInit dictionary

+
+
dictionary ThingPropertyInit {
+    DOMString              name;
+    boolean                configurable = true;
+    boolean                enumerable = true;
+    boolean                writable = true;
+    sequence<SemanticType> semanticTypes;
+    ThingDescription       description;
+    any                    value;
+};
+
+

+ Represents the Thing + Property description. +

+
    +
  • The name attribute represents the name of the Property.
  • +
  • The value attribute represents the value of the Property.
  • +
  • + The configurable attribute defines whether the Property can be deleted from the object and whether its properties can be changed. The default value is false. +
  • +
  • + The enumerable attribute defines whether the Property can be listed and iterated. The default value is true. +
  • +
  • + The writable attribute defines whether the Property can be updated. The default value is true. +
  • +
  • + The semanticTypes attribute represents a list of semantic type annotations + (e.g. labels, classifications etc) relevant to the Property, represented as SemanticType dictionaries. +
  • +
  • + The description attribute represents the Property description to be added to the Thing Description. +
  • +
+
+
+

5.4.2 The SemanticType dictionary

+
+
dictionary SemanticType {
+    DOMString name;
+    USVString context;
+};
+
+

+ Represents a semantic type annotation, containing a name and a context. +

+
    +
  • The name attribute represents the name of the semantic type in the given context.
  • +
  • The context attribute represents an URL link to the context of the semantic classification.
  • +
+
+
Editor's note
+

+ Semantic type examples to be added. +

+
+
+
+
+

5.5 The removeProperty() method

+

+ Removes the Property specified by the name argument, updates the Thing Description and returns the object. +

+
+
+

5.6 The addAction() method

+

+ Adds an Action to the Thing object as defined by the action argument of type ThingActionInit and updates the Thing Description. +

+
+

5.6.1 The ThingActionInit dictionary

+
+
dictionary ThingActionInit {
+    DOMString              name;
+    ThingDescription       inputDataDescription;
+    ThingDescription       outputDataDescription;
+    sequence<SemanticType> semanticTypes;
+    Function               action;
+};
+
+

+ The ThingActionInit dictionary describes the arguments and the return value. +

+
    +
  • The name attribute provides the Action name.
  • +
  • The action attribute provides a function that defines the Action.
  • +
  • The inputDataDescription attribute provides the description of the + input arguments.
  • +
  • The outputDataDescription attribute provides the description of + the returned data.
  • +
  • + The semanticTypes attribute provides a list of semantic type annotations (e.g. + labels, classifications etc) relevant to the Action, represented as SemanticType dictionaries. +
  • +
+
+
+
+

5.7 The removeAction() method

+

+ Removes the Action specified by the name argument, updates the Thing Description and returns the object. +

+
+
+

5.8 The addEvent() method

+

+ Adds an event to the Thing object as defined by the event argument of type ThingEventInit and updates the Thing Description. +

+
+

5.8.1 The ThingEventInit dictionary

+
+
dictionary ThingEventInit {
+    DOMString              name;
+    sequence<SemanticType> semanticTypes;
+    ThingDescription       dataDescription;
+};
+
+
    +
  • The name attribute represents the event name.
  • +
  • The semanticTypes attribute represent a list of semantic type annotations attached + to the event.
  • +
  • The dataDescription attribute represents the description of the data that is + attached to the event.
  • +
+
+
+
+

5.9 The removeEvent() method

+

+ Removes the event specified by the name argument, updates the Thing Description and returns the object. +

+
+
+

5.10 The onRetrieveProperty() method

+

+ Registers the handler function for Property retrieve requests received for the Thing, as defined by + the handler property of type RequestHandler + . The handler will receive an argument request of type Request + where at least request.name is defined and represents the name of the Property to be retrieved. +

+
+
+

5.11 The onUpdateProperty() method

+

+ Defines the handler function for Property update requests received for the Thing, as defined by the + handler property of type RequestHandler + . The handler will receive an argument request of type Request + where request.name defines the name of the Property to be retrieved and request.data defines the new value of the Property. +

+
+
+

5.12 The onInvokeAction() method

+

+ Defines the handler function for Action invocation requests received for the Thing, as defined by the + handler property of type RequestHandler + . The handler will receive an argument request of type Request + where request.name defines the name of the Action to be invoked and request.data defines the input arguments for the Action as defined by the Thing Description. +

+
+
+

5.13 The onObserve() method

+

+ Defines the handler function for observe requests received for the Thing, as defined by the handler property of type RequestHandler + . The handler will receive an argument request of type Request + where +

+ +
+
+

5.14 The register() method

+

+ Generates the Thing Description given the properties, Actions and Event defined for this object. If a directory argument is given, make a request to register the Thing Description with + the given WoT repository by invoking its register + Action. +

+
+
+

5.15 The unregister() method

+

+ If a directory argument is given, make a request to unregister the Thing Description with the given WoT repository by invoking its unregister + Action. Then, and in the case no arguments were provided to this function, stop the Thing and remove the + Thing Description. +

+
+
+

5.16 The start() method

+

+ Start serving external requests for the Thing. +

+
+
+

5.17 The stop() method

+

+ Stop serving external requests for the Thing. +

+
+
+

5.18 The emitEvent() method

+

+ Emits an the event initialized with the event name specified by the eventName argument and data specified by the payload argument. +

+
+
+

5.19 Events supported by ExposedThing

+

+ The following default events SHOULD be supported by ExposedThing implementations: +

+ +

+ In addition, user defined events are specified by the Thing Description. +

+
+
+

5.20 Examples

+

+ Below some ExposedThing + interface examples are given. +

+
+
Example 6: Create a new blank exposed Thing
+
WoT.createExposedThing(thingDescription)
+  .then(function(thing) {
+    // manually add properties, actions, and events
+    thing.addProperty({
+      name: "temperature",
+      value: "0",
+      writable: false
+      // use default values for the rest
+    }).addEvent({
+      name: "onchange",
+      outputDataDescription: {
+        type: "float32"
+      }
+    }).addAction({
+      name: "reset",
+      action: () => { this.temperature = 0; }
+    })
+    // add server functionality
+    .onRetrieveProperty( request => {
+      console.log("Handling read request");
+      return this.temperature;
+    }).onObserve( request => {
+      console.log("Handling observe request");
+      // add listener identified by request.from
+    }).onInvokeAction( request => {
+      console.log("Handling action request");
+    }).start();
+  });
+
+
+
Example 7: Create a new exposed Thing from a TD URI
+
let thingDescription = '{
+  "name": "mySensor",
+  "url": "http://myservice.org/mySensor/description"
+}';
+WoT.createExposedThing(thingDescription)
+  .then(function(thing) {
+    // properties, actions and events are added based on the TD
+    console.log("created " + thing.name });
+    // now add the requests handlers
+    thing.onRetrieveProperty(function(request) {
+        console.log("Sending property '" + request.property + "' to " + request.from);
+    }).onUpdateProperty(function(request) {
+        console.log("Updating property '" + request.property + "' by " + request.from);
+    }).onObserve(function(request) {
+        console.log("Adding listener " + request.from);
+        console.log("Observing " + request.type + " " + request.name +
+            (request.subscribe? " recursively" : ""));
+    }).start().then(function() {
+       console.log("Thing started serving requests");
+    });
+  })
+
+
+
Example 8: Create a new exposed Thing from a Thing Description
+
let thingDescription = '{
+  "name": "mySensor",
+  "description": {
+    "@context": [
+      "http://w3c.github.io/wot/w3c-wot-td-context.jsonld",
+      "http://w3c.github.io/wot/w3c-wot-common-context.jsonld",
+    ],
+    "@type": [ "Thing" ],
+    "interaction": [
+      // ...
+    ]
+    // ...
+  }'
+};
+WoT.createExposedThing(thingDescription)
+  .then(function(thing) {
+    // properties, actions and events are added based on the TD
+    // ...
+  });
+
+
+
+
+ +

6. Security and Privacy

+
+
Editor's note
+

+ Please see the WoT Security and Privacy repository for work in progress regarding threat models, assets, risks, recommended mitigations, and best practices for security and privacy for + systems using the Web of Things. Once complete, security and privacy considerations relevant to the Scripting API will be summarized in this section. +

+
+
+
+ +

7. Terminology and conventions

+

+ The generic WoT terminology is defined in [WOT-ARCHITECTURE]: Thing, Thing Description (in short TD), Web of Things (in short WoT), WoT Interface, Protocol Bindings, WoT Runtime, Consuming a Thing Description, Thing Directory, Property, Action, Event etc. +

+
+
Note
+

+ In this version of the specification, a WoT Runtime is assumed to run scripts that uses this API to define one or more Things + that share a common event loop. Script deployment methods are out of scope of this version. In future versions, running multiple scripts (as modules) may be possible, and script deployment MAY be implemented + using a manager Thing whose Actions permit script lifecycle management operations. +

+
+

+ JSON-LD is defined in [JSON-LD] as a JSON document that is augmented with support for Linked Data by providing a @context property + with a defining URI . +

+

+ The terms URL and + + URL path are defined in [URL]. +

+

+ The following terms are defined in [HTML5] and are used in the context of browser implementations: + + browsing context, + + + top-level browsing context, + + + global object, + + + incumbent settings object, + + + Document, + + + document base URL, + + + Window, + + + WindowProxy, + + + origin, + + + ASCII serialized origin, executing algorithms + in parallel, + + + queue a task, + + + task source, + + + iframe, + + + valid MIME type. +

+

+ A browsing context refers to the environment in which + Document objects are presented to the user. A given + browsing context has a single WindowProxy object, but it can have many Document objects, with their associated + Window objects. The script execution context associated with the browsing context identifies the entity which invokes this API, which can be a web app, a web page, or an + iframe. +

+

+ The term + + secure context is defined in [WEBAPPSEC]. +

+

+ + Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError + , + + script execution context, + + Promise, + + JSON, + + JSON.stringify and + + JSON.parse are defined in [ECMASCRIPT]. +

+

+ DOMString, + USVString, + ArrayBuffer, + BufferSource and + any are defined in [WEBIDL]. +

+

+ The term event and the Event object are defined in DOM and Node.js. +

+
+
Note
+

+ This specification uses the convention that an event listener will receive an Event object. This should work both in a browser environment and in a Node.js + like environment. +

+
+

+ Observables are proposed to be included in ECMAScript. +

+

+ The algorithms + utf-8 encode, and + + utf-8 decode are defined in [ENCODING]. +

+

+ IANA media types (formerly known as MIME types) are defined in + RFC2046. +

+
+
+ +

8. Conformance

+

+ As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative. +

+

The key words MAY, MUST, and SHOULD are to be interpreted as described in [RFC2119]. +

+

+ This document defines conformance criteria that apply to a single product: the UA (user agent) that implements the interfaces it contains. +

+

+ This specification can be used for implementing the WoT Scripting API in multiple programming languages. The interface definitions are specified in [WEBIDL]. +

+

+ The user agent (UA) may be implemented in the browser, or in a separate runtime environment, such as Node.js or 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]. +

+

+ This document serves a general description of the WoT Scripting API. Language and runtime specific issues are discussed in separate extensions of this document. +

+
+
+ +

A. Changes

+

+ The following is a list of major changes to the document. For a complete list of changes, see the github change log. You can also view the recently closed bugs. +

+
+
+ +

B. Open issues

+

+ The following problems are being discussed and need most attention: +

+ +
+
+ +

C. Acknowledgements

+

+ Special thanks to former editor Johannes Hund for developing this specification. Also, the editors would like to thank Dave Raggett, Matthias Kovatsch, Michael Koster and Michael McCool for their comments and guidance. +

+
+
+ +

D. References

+
+

D.1 Normative references

+
[ECMASCRIPT]
+
ECMAScript Language Specification. Ecma International. URL: https://tc39.github.io/ecma262/ +
[ENCODING]
+
Encoding Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://encoding.spec.whatwg.org/ +
[HTML5]
+
HTML5. Ian Hickson; Robin Berjon; Steve Faulkner; Travis Leithead; Erika Doyle Navara; Theresa O'Connor; Silvia Pfeiffer. W3C. 28 October 2014. W3C Recommendation. URL: https://www.w3.org/TR/html5/ +
[JSON-LD]
+
JSON-LD 1.0. Manu Sporny; Gregg Kellogg; Markus Lanthaler. W3C. 16 January 2014. W3C Recommendation. URL: https://www.w3.org/TR/json-ld/ +
[RFC2119]
+
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
[TYPESCRIPT]
+
TypeScript Language Specification. Microsoft. 1 October 2012. URL: https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md +
[URL]
+
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/ +
[WEBAPPSEC]
+
Secure Contexts. W3C. 17 July 2015. URL: https://w3c.github.io/webappsec/specs/powerfulfeatures +
[WEBIDL]
+
Web IDL. Cameron McCormack; Boris Zbarsky; Tobie Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: https://heycam.github.io/webidl/ +
[WOT-ARCHITECTURE]
+
Web of Things Architecture. W3C. 20 August 2017. URL: https://w3c.github.io/wot-architecture/ +
+
+
+
+ + + + + diff --git a/releases/fpwd/diff.html b/releases/fpwd/diff.html new file mode 100644 index 00000000..c22818df --- /dev/null +++ b/releases/fpwd/diff.html @@ -0,0 +1,9758 @@ + + + + + + + + + + + Web of Things (WoT) Scripting API + + + + + + + + + + + + + + +
+

+Abstract +

+

+The + +Web +of +Things + +(WoT) +provides +layered +interoperability +between + +Things + +by +using +the + +WoT +Interface + +s. +

+

+This +specification +describes +a +programming +interface +representing +the + +WoT +Interface + +that +allows +scripts +run +on +a + +Thing + +to +discover +and +consume +(retrieve) +other + +Thing + +s +and +to +expose + +Things + +characterized +by +properties, + +Actions + +and + +Events +. +

+

+Scripting +is +an +optional +"convenience" +building +block +in +WoT +and +it +is +typically +used +in +gateways +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 +like + +Thing +Directory +. +

+
+
+

+Status +of +This +Document +

+

+ +This +section +describes +the +status +of +this +document +at +the +time +of +its +publication. +Other +documents +may +supersede +this +document. +A +list +of +current + +W3C + +publications +and +the +latest +revision +of +this +technical +report +can +be +found +in +the + + +W3C + +technical +reports +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. +

+
+
+ +Editor's +note + +: +The +W3C +WoT +WG +is +asking +for +feedback + +
+

+Please +contribute +to +this +draft +using +the + +GitHub +Issue + +feature +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 + +a +First +Public +Working + +Draft. +This +document +is +intended +to +become +a + +W3C + +Recommendation. +

+Comments +regarding +this +document +are +welcome. +Please +send +them +to + +public-wot-wg@w3.org + +( + +subscribe +, + +archives + +). +

+

+Publication +as +an +Editor's + +a +First +Public +Working + +Draft +does +not +imply +endorsement +by +the + +W3C + +Membership. +This +is +a +draft +document +and +may +be +updated, +replaced +or +obsoleted +by +other +documents +at +any +time. +It +is +inappropriate +to +cite +this +document +as +other +than +work +in +progress. +

+

+This +document +was +produced +by +a +group +operating +under +the + +5 +February +2004 + +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 + +1 +March +2017 + +W3C + +Process +Document +. +

+
+ +
+

+ +1. + +Introduction +

+

+The +overall +WoT +concepts +are +described +in +the + +WoT +Architecture + +document. +The +Web +of +Things +is +made +of +entities +( + +Thing + +s) +that +can +describe +their +capabilities +in +a +machine-interpretable +format, +the + +Thing +Description + +(TD) +and +expose +these +capabilities +through +the + +WoT +Interface +. +Support +for +scripting +is +optional +for +WoT +devices. +

+

+By + +consuming +a +TD +, +a +client + +Thing + +creates +a +runtime +resource +model +that +allows +accessing +the +properties, + +Actions + +and + +Events + +exposed +by +the +server + +Thing +. +

+

+Exposing +a + +Thing + +requires +defining +a + +Thing +Description + +and +instantiating +a +software +stack +needed +to +serve +requests +for +accessing +the +exposed +properties, + +Actions + +and + +Events +. +This +specification +describes +how +to +expose +and +consume + +Thing + +s +by +a +script. +

+
+
+ +Note + +
+

+Typically +scripts +are +meant +to +be +used +on +devices +able +to +provide +resources +(with +a + +WoT +interface + +) +for +managing +(installing, +updating, +running) +scripts, +such +as +bridges +or +gateways +that +expose +and +control +simpler +devices +as +WoT + +Thing + +s. +

+
+

+For +an +introduction +on +how +scripts +could +be +used +in + +Web +of +Things +, +check +the + +Primer + +document. +For +some +background +on +API +design +decisions +check +the + +Rationale + +document. +

+
+
+

+ +2. + +Use +Cases +

+

+ +This +section +is +non-normative. + +

+

+The +following +scripting +use +cases +are +covered +in +this +specification: +

+ +

+The +following +use +cases +are +being +considered +for +next +versions: +

+ +
+
+

+ +3. + +The + + +WoT + + +object +

+

+The +WoT +object +is +the +main +API +entry +point +and +it +is +exposed +by +an +implementation +of +the + +WoT +Runtime +. +The + +WoT +object + +has +no +internal +state +and +provides +methods +for +discovering, +consuming +and +exposing +a + +Thing +. +

+
+
+ +Note + +
+

+Browser +implementations + +SHOULD + +use +a +namespace +object +such +as + +wot +, +and + +Node.js + +-like +runtimes + +MAY + +provide +the +API +object +through +the + + +require() + + +or + + +import + + +mechanism. +

+
+
+
interface WoT {
+    Observable<ConsumedThing> discover(optional ThingFilter filter);
+    Promise<ConsumedThing>    consume(USVString url);
+    Promise<ExposedThing>     expose(ThingInit init);
+};
+
+
+
+
+
+ +Editor's +note + +
+

+The +algorithms +for +the +WoT +methods +will +be +specified +later. +

+
+
+

+ +3.1 + +The + + +discover() + + +method +

+

+Starts +the +discovery +process +that +will +provide + + + +ConsumedThing + + + +objects +that +match +the +optional +argument + + + +ThingFilter + + +. +When +the +argument +is +not +provided, +starts +the +widest +discovery +the + +Thing +Description + +and + +Protocol +Bindings + +allow. +Returns +an + + +Observable + + +object +that +can +be +subscribed +and +unsubscribed +to. +

+
+

+ +3.1.1 + +The + + +ThingFilter + + +dictionary +

+

+The + + +ThingFilter + + +dictionary +that +represents +the +constraints +for +discovering + +Thing + +s +as +key-value +pairs. +

+
+
dictionary ThingFilter {
+    (DiscoveryType or DOMString) method = "any";
+    USVString                    url;
+    Dictionary                   description;
+};
+
+
+
+

+The + + +method + + +property +represents +the +discovery +type +that +should +be +used +in +the +discovery +process. +The +possible +values +are +defined +by +the + + + +DiscoveryMethod + + + +enumeration +that +can +be +extended +by +string +values +defined +by +solutions +(with +no +guarantee +of +interoperability). +

+

+The + + +url + + +property +represents +additional +information +for +the +discovery +method, +such +as +the +URL +of +the + +Thing +Directory + +server +to +be +used. +

+

+The + + +description + + +property +represents +additional +information +for +the +discovery +method +in +the +form +of +a +set +of +key-value +pairs, +as +defined +in +the + +Thing +Description +. +

+
+
+ +Editor's +note + +
+

+The + + +DiscoveryMethod + + +enumeration +can +be +extended +by +the + +Thing +Description + +with +values +that +are +not +specified +here. +This +extensibility +of + + +DiscoveryMethod + + +by +proprietary +or +private +methods +is +a +working +assumption +until +consensus +is +formed +and +may +be +removed +later. +

+
+
+
+ +Editor's +note + +
+

+The + + +ThingFilter + + +dictionary +may +be +extended +later +with +further +attributes. +

+
+
+
+

+ +3.1.2 + +The + + +DiscoveryMethod + + +enumeration +

+
+
enum DiscoveryMethod {
+    "any",
+    "local",
+    "nearby",
+    "directory",
+    "broadcast",
+    "other"
+};
+
+
+
+

+The + + +DiscoveryMethod + + +enumeration +represents +the +discovery +type +to +be +used: +

+
    +
  • +" + + +any + + +" +does +not +provide +any +restriction +
  • +
  • +" + + +local + + +" +for +discovering + +Thing + +s +defined +in +the +same +device +
  • +
  • +" + + +nearby + + +" +for +discovering + +Thing + +s +nearby +the +device, +e.g. +by +Bluetooth +or +NFC +
  • +
  • +" + + +directory + + +" +for +discovery +based +on +a +service +provided +by +a +directory +or +repository +of + +Thing + +s +
  • +
  • +" + + +broadcast + + +" +for +an +open +ended +discovery +based +on +sending +a +request +to +a +broadcast +address +
  • +
  • +" + + +other + + +" +for +a +proprietary +method +defined +by +the +solution. +
  • +
+
+
+
+

+ +3.2 + +The + + +consume() + + +method +

+

+Accepts +an + +url + +argument +and +returns +a + + +Promise + + +of +a + + +ConsumedThing + +. +

+
+
+

+ +3.3 + +The + + +expose() + + +method +

+

+Returns +a + + +Promise + + +of +a +locally +created + + +ExposedThing + + +based +on +the +provided +initialization +parameters. +

+
+
+ +Editor's +note + +
+

+The +reason + + +ExposedThing + + +s +are +created +by +a +factory +method +instead +of +a +constructor +is +that +an + + +ExposedThing + + +may +be +created +in +the +local + +WoT +Runtime + +or +in +a +remote +runtime. +Even +though +currently +only +local +creation +is +supported, +the +method +is +designed +with +this +possible +future +compatibility +in +mind. +

+
+
+

+ +3.3.1 + +The + + +ThingInit + + +dictionary +

+
+
dictionary ThingInit {
+    DOMString  name;
+    USVString  url;
+    Dictionary description;
+};
+
+
+
+

+The + + +ThingInit + + +dictionary +contains +properties +to +initialize +a + +Thing +: +

+
    +
  • +The + + +name + + +attribute +represents +the +user +given +name +of +the + +Thing +. +
  • +
  • +The + + +url + + +attribute +represents +the +address +of +the + +Thing +. +
  • +
  • +The + + +description + + +attribute +represents +the + +Thing +Description + +of +the + +Thing +. +
  • +
+
+
+
+

+ +3.4 + +Examples +

+
+
+ +Example +1 + +: +Discover +Things +via +directory + +
+
let discoveryType = { method: "directory", url: "http://directory.wotservice.org" };
+let subscription = wot.discover(discoveryType).subscribe(
+  thing => { console.log("Found Thing " + thing.url); },
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout(
+  () => { subscription.unsubscribe(); console.log("Discovery timeout"); },
+
+5000
+
+);
+
+
+
+
+ +Note + +
+

+Note +that +canceling +a +discovery +(through +unsubscribe) +may +not +be +successful +in +all +cases, +for +instance +when +discovery +is +based +on +open +ended +broadcast +requests. +However, +once + +unsubscribe() + +has +been +called, +implementations + +MUST + +suppress +further +event +handling +( +i.e. +further +discoveries +and +errors) +on +the +Observable. +Also, +a +discovery +error +may +not +mean +the +end +of +the +discovery +process. +However, +in +order +to +respect +Observable +semantics +(error +always +terminates +processing), +implementations + +MUST + +close +or +suppress +further +event +handling +on +the +Observable. +

+
+
+
+ +Example +2 + +: +Discover +Things +exposed +by +local +hardware + +
+
let subscription = wot.discover({ method: "local" }).subscribe(
+  thing => { console.log("Found local Thing " + thing.url); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +Example +3 + +: +Discover +Things +exposed +nearby, +e.g. +via +Bluetooth + +
+
let subscription = wot.discover({ method: "nearby", description: {protocol: "BLE4.2"} }).subscribe(
+  thing => { console.log("Found nearby Thing " + thing.url); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +Example +4 + +: +Discover +Things +exposed +in +a +proprietary +way + +
+
let subscription = wot.discover({ method: "other", description: { solution: "XYZ123", key: "..."} }).subscribe(
+  thing => { console.log("Found Thing " + thing.url); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+
+

+ +4. + +The + + +ConsumedThing + + +interface +

+

+The + + +ConsumedThing + + +interface +is +a +client +API +for +sending +requests +to +servers +in +order +to +retrieve +or +update +properties, +invoke + +Actions +, +and +observe +properties, + +Actions + +and + +Events +. +

+
+
interface ConsumedThing {
+    readonly attribute DOMString        name;
+    readonly attribute USVString        url;
+    readonly attribute ThingDescription description;
+    Promise<any>  invokeAction(DOMString name, any parameters);
+    Promise<void> setProperty(DOMString name, any value);
+    Promise<any>  getProperty(DOMString name);
+    ConsumedThing addListener(DOMString eventName, ThingEventListener listener);
+    ConsumedThing removeListener(DOMString eventName,
+                                 ThingEventListener listener);
+    ConsumedThing removeAllListeners(optional DOMString eventName);
+    Observable    observe(DOMString name, RequestType requestType);
+};
+
+callback
+
+
+
+ThingEventListener
+
+
+
+=
+
+void
+
+(
+
+
+
+Event
+
+
+
+event
+
+
+);
+
+
+
+

+Represents +a +local +proxy +object +of +the +remote + +Thing +. +

+ +
+

+ +4.1 + +The + + +invokeAction() + + +method +

+

+Takes +the + +Action + +name +from +the + +name + +argument +and +the +list +of +parameters, +then +requests +from +the +underlying +platform +and +the + +Protocol +Bindings + +to +invoke +the + +Action + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + + +Promise + + +that +resolves +with +the +return +value +or +rejects +with +an + +Error +. +

+
+
+

+ +4.2 + +The + + +setProperty() + + +method +

+

+Takes +the + +Property + +name +as +the + +name + +argument +and +the +new +value +as +the + +value + +argument, +then +requests +from +the +underlying +platform +and +the + +Protocol +Bindings + +to +update +the + +Property + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + + +Promise + + +that +resolves +on +success +or +rejects +with +an + +Error +. +

+
+
+

+ +4.3 + +The + + +getProperty() + + +method +

+

+Takes +the + +Property + +name +as +the + +name + +argument, +then +requests +from +the +underlying +platform +and +the + +Protocol +Bindings + +to +retrieve +the + +Property + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + + +Promise + + +that +resolves +with +the + +Property + +value +or +rejects +with +an + +Error +. +

+
+
+

+ +4.4 + +The + + +addListener() + + +method +

+

+Adds +the +listener +provided +in +the +argument + +listener + +to +the + +Event + +name +provided +in +the +argument + +eventName +. +

+
+
+

+ +4.5 + +The + + +removeListener() + + +method +

+

+Removes +a +listener +from +the + +Event + +identified +by +the +provided + +eventName + +and + +listener + +argument. +

+
+
+

+ +4.6 + +The + + +removeAllListeners() + + +method +

+

+Removes +all +listeners +for +the + +Event + +provided +by +the + +eventName + +optional +argument, +or +if +that +was +not +provided, +then +removes +all +listeners +from +all + +Events +. +

+
+
+

+ +4.7 + +The + + +observe() + + +method +

+

+Returns +an + +Observable + +for +the + +Property +, + +Event + +or + +Action + +specified +in +the + +name + +argument, +allowing +subscribing +and +unsubscribing +to +notifications. +The + +requestType + +specifies +whether +a + +Property +, +an + +Event + +or +an + +Action + +is +observed. +

+
+
+ +Editor's +note + +
+

+The + +observe() + +method +could +replace + +addListener() + +and + +removeListener() +, +though +they +could +be +kept +for +convenience. +

+
+
+
+

+ +4.8 + +The + + +ThingEventListener + + +callback +

+

+A +function +called +with +an + +Event + +object +when +an +event +is +emitted. +

+
+
+

+ +4.9 + +Events +

+

+Clients +can +subscribe +to +the + +Events + +defined +in + +ExposedThing +events +. +The +event +types +are +described +in +this +section. +

+
+

+ +4.9.1 + +The + + +PropertyChangeEvent + + +interface +

+
+
[Constructor(PropertyChangeEventInit init)]
+interface PropertyChangeEvent : Event {
+    readonly attribute PropertyChangeEventInit data;
+};
+
+
+
+

+The + + +data + + +attribute +represents +the +changed + +Property +. +

+
+
+ +4.9.1.1 + +The + + +PropertyChangeEventInit + + +dictionary +
+
+
dictionary PropertyChangeEventInit {
+    DOMString name;
+    any       value;
+};
+
+
+
+

+The + + +name + + +> +attribute +represents +the + +Property + +name. +

+

+The + + +value + + +attribute +represents +the +new +value +of +the + +Property +. +

+
+
+
+

+ +4.9.2 + +The + + +ActionInvocationEvent + + +interface +

+
+
[Constructor(ActionInvocationEventInit init)]
+interface ActionInvocationEvent : Event {
+    readonly attribute ActionInvocationEventInit data;
+};
+
+
+
+

+The + + +data + + +attribute +represents +the +notification +data +from +the + +Action + +invocation. +

+
+
+ +4.9.2.1 + +The + + +ActionInvocationEventInit + + +dictionary +
+
+
dictionary ActionInvocationEventInit {
+    DOMString actionName;
+    any       returnValue;
+};
+
+
+
+
+
+ +Editor's +note + +
+

+Action +parameters +could +be +also +included, +but +it's +debatable +because +privacy +reasons. +

+
+

+The + + +actionName + + +attribute +represents +the +name +of +the + +Action + +that +has +been +invoked. +

+

+The + + +returnValue + + +attribute +represents +the +return +value +of +the + +Action +. +

+
+
+
+

+ +4.9.3 + +The + + +ThingDescriptionChangeEvent + + +interface +

+
+
[Constructor(ThingDescriptionChangeEventInit init)]
+interface ThingDescriptionChangeEvent : Event {
+    readonly attribute ThingDescriptionChangeEventInit data;
+};
+
+
+
+

+The + + +data + + +attribute +represents +the +changes +that +occurred +to +the + +Thing +Description +. +

+
+
+ +4.9.3.1 + +The + + +ThingDescriptionChangeEventInit + + +dictionary +
+
+
dictionary ThingDescriptionChangeEventInit {
+    TDChangeType     type;
+    TDChangeMethod   method;
+    DOMString        name;
+    TDChangeData     data;
+    ThingDescription description;
+};
+
+
+
+
    +
  • +The + + +type + + +attribute +represents +the +change +type, +whether +has +it +been +applied +on +properties, + +Actions + +or + +Events +. +
  • +
  • +The + + +method + + +attribute +tells +what +operation +has +been +applied, +addition, +removal +or +change. +
  • +
  • +The + + +name + + +attribute +represents +the +name +of +the + +Property +, + +Action + +or +event +that +has +changed. +
  • +
  • +The + + +description + + +attribute +is +defined +for +the +addition +and +change +methods, +and +represents +the +new +description. +
  • +
  • +The + + +data + + +attribute +provides +the +initialization +data +for +the +added +or +changed +elements. +
  • +
+
+
+ +4.9.3.1.1 + +The + + +TDChangeMethod + + +enumeration +
+
+
enum TDChangeMethod {
+    "add",
+    "remove",
+    "change"
+};
+
+
+
+ +
+
+
+ +4.9.3.1.2 + +The + + +TDChangeType + + +enumeration +
+ +
    +
  • +The + + +property + + +value +tells +the +operation +was +applied +on +a + +Property + +definition. +
  • +
  • +The + + +action + + +value +tells +the +operation +was +applied +on +a +action +definition. +
  • +
  • +The + + +event + + +value +tells +the +operation +was +applied +on +an +event +definition. +
  • +
+
+
+
+ +4.9.3.1.3 + +The + + +TDChangeData + + +type +
+

+Represents +the +new +description +of +the +changed +element. +Depending +on +the +change +type, +it +can +be +either +a + + +ThingPropertyInit + +, + + +ThingActionInit + +, +or + + +ThingEventInit + +. +

+
+
+
+
+
+

+ +4.10 + +Examples +

+

+Below +a + + + +ConsumedThing + + + +interface +example +is +given. +

+
+
+ +Example +5 + +: +Consume +a +Thing + +
+
wot.consume("http://mmyservice.org/mySensor").then( thing => {
+    console.log("Thing " + thing.name + " has been consumed.");
+    console.log("{ " + JSON.serialize(thing) + " }");
+    thing.addListener("onchange", function(event) {
+        if (event instanceof PropertyChangeEvent) {
+            console.log("Property " + event.name + " value has changed to " + event.value);
+        }
+    }).invokeAction("startMeasurement", ["Celsius"]);
+  },
+).catch(error => {
+  console.log("Discovery finished because an error: " + error.message);
+});
+
+
+
+
+
+

+ +5. + +The + + +ExposedThing + + +interface +

+

+The + + +ExposedThing + + +interface +is +the +server +API +that +allows +defining +request +handlers, +properties, + +Actions +, +and + +Events + +to +a + +Thing +. +

+
+
typedef USVString ThingDescription;
+callback RequestHandler = any (Request request);
+interface ExposedThing {
+    // define Thing Description modifiers
+    ExposedThing  addProperty(ThingPropertyInit property);
+    ExposedThing  removeProperty(DOMString name);
+    ExposedThing  addAction(ThingActionInit action);
+    ExposedThing  removeAction(DOMString name);
+    ExposedThing  addEvent(ThingEventInit event);
+    ExposedThing  removeEvent(DOMString name);
+    // define request handlers
+    ExposedThing  onRetrieveProperty(RequestHandler handler);
+    ExposedThing  onUpdateProperty(RequestHandler handler);
+    ExposedThing  onInvokeAction(RequestHandler handler);
+    ExposedThing  onObserve(RequestHandler handler);
+    // define how to expose and run the Thing
+    Promise<void> register(optional USVString directory);
+    Promise<void> unregister(optional USVString directory);
+    Promise<void> start();
+    Promise<void> stop();
+    Promise<void> emitEvent(DOMString eventName, any payload);
+};
+
+
+
+ExposedThing
+
+
+implements
+
+
+ConsumedThing
+
+
+;
+
+
+
+
+

+ +5.1 + +The + + +ThingDescription + + +type +

+

+WoT +provides +a +unified +representation +for +data +exchange +between + +Thing + +s, +standardized +in +the + +Wot +Things +Description + +specification. +

+
+
+ +Note + +
+

+In +this +version +of +the +API, + +Thing +Description + +s +are +represented +as +opaque +strings, +denoting +a +serialized +form, +for +instance +JSON +or +JSON-LD. +See + +Issue +38 + +and + +Issue +45 +. +Parsing +and +composing + +Thing +Description + +s +is +left +for +external +libraries +until +standardized +here. +

+
+
+
+

+ +5.2 + +The + + +Request + + +interface +

+
+
interface Request {
+    readonly attribute RequestType type;
+    readonly attribute USVString   from;
+    readonly attribute DOMString   name;
+    readonly attribute Dictionary  options;
+    readonly attribute any         data;
+    Promise respond(any response);
+    void    respondWithError(Error error);
+};
+
+
+
+

+Represents +an +incoming +request +the + + +ExposedThing + + +is +supposed +to +handle, +for +instance +retrieving +and +updating +properties, +invoking + +Actions + +and +observing + +Events + +(WoT +interactions). +

+ +
+

+ +5.2.1 + +The + + +RequestType + + +enumeration +

+
+
enum RequestType {
+    "property",
+    "action",
+    "event",
+    "td"
+};
+
+
+
+
    +
  • +The +value +" + + +property + + +" +represents +requests +to +retrieve +or +update +a + +Property +. +
  • +
  • +The +value +" + + +action + + +" +represents +requests +to +invoke +an + +Action +. +
  • +
  • +The +value +" + + +event + + +" +represents +requests +to +emit +an +event. +
  • +
  • +The +value +" + + +td + + +" +represents +requests +to +change +the + +Thing +Description +, +i.e. +to +add, +remove +or +modify +properties, + +Actions + +or + +Events +. +
    +
    + +Editor's +note + +
    +

    +This +functionality +is +here +for +the +sake +of +completeness +for +future +versions +of +the +API. +Currently +there +is +no +corresponding +functionality +at +the + + +ConsumedThing + + +level +and +it +is +not +guaranteed +that +a +Thing +Description +could +be +remotely +changed +by +scripting. +

    +
    +
  • +
+
+
+

+ +5.2.2 + +The + + +respond() + + +method +

+

+Sends +a +positive +response +to +the + + +Request + + +based +on +the + +Protocol +Bindings + +and +includes +the +data +specified +by +the + +data + +argument. +

+
+
+

+ +5.2.3 + +The + + +respondWithError() + + +method +

+

+Sends +a +negative +response +to +the + + +Request + + +based +on +the + +Protocol +Bindings + +and +includes +the +error +specified +by +the + +error + +argument. +

+
+
+
+

+ +5.3 + +The + + +RequestHandler + + +callback +

+

+Callback +function +for +handling +interaction +requests. +Receives +an +argument + +request + +of +type + + + +Request + + + +and +should +return +an +object +or +value +that +is +used +by + +Protocol +Bindings + +to +reply +to +the +request. +The +returned +type +is +defined +by +the + +Thing +Description +. +

+
+
+

+ +5.4 + +The + + +addProperty() + + +method +

+

+Adds +a + +Property + +defined +by +the +argument +and +updates +the + +Thing +Description +. +

+
+

+ +5.4.1 + +The + + +ThingPropertyInit + + +dictionary +

+
+
dictionary ThingPropertyInit {
+    DOMString              name;
+    boolean                configurable = true;
+    boolean                enumerable = true;
+    boolean                writable = true;
+    sequence<SemanticType> semanticTypes;
+    ThingDescription       description;
+    any                    value;
+};
+
+
+
+

+Represents +the + +Thing + + +Property + +description. +

+
    +
  • +The + + +name + + +attribute +represents +the +name +of +the + +Property +. +
  • +
  • +The + + +value + + +attribute +represents +the +value +of +the + +Property +. +
  • +
  • +The + + +configurable + + +attribute +defines +whether +the + +Property + +can +be +deleted +from +the +object +and +whether +its +properties +can +be +changed. +The +default +value +is + +false +. +
  • +
  • +The + + +enumerable + + +attribute +defines +whether +the + +Property + +can +be +listed +and +iterated. +The +default +value +is + +true +. +
  • +
  • +The + + +writable + + +attribute +defines +whether +the + +Property + +can +be +updated. +The +default +value +is + +true +. +
  • +
  • +The + + +semanticTypes + + +attribute +represents +a +list +of +semantic +type +annotations +(e.g. +labels, +classifications +etc) +relevant +to +the + +Property +, +represented +as + + +SemanticType + + +dictionaries. +
  • +
  • +The + + +description + + +attribute +represents +the + +Property + +description +to +be +added +to +the + +Thing +Description +. +
  • +
+
+
+

+ +5.4.2 + +The + + +SemanticType + + +dictionary +

+
+
dictionary SemanticType {
+    DOMString name;
+    USVString context;
+};
+
+
+
+

+Represents +a +semantic +type +annotation, +containing +a +name +and +a +context. +

+
    +
  • +The + + +name + + +attribute +represents +the +name +of +the +semantic +type +in +the +given +context. +
  • +
  • +The + + +context + + +attribute +represents +an +URL +link +to +the +context +of +the +semantic +classification. +
  • +
+
+
+ +Editor's +note + +
+

+Semantic +type +examples +to +be +added. +

+
+
+
+
+

+ +5.5 + +The + + +removeProperty() + + +method +

+

+Removes +the + +Property + +specified +by +the + +name + +argument, +updates +the + +Thing +Description + +and +returns +the +object. +

+
+
+

+ +5.6 + +The + + +addAction() + + +method +

+

+Adds +an + +Action + +to +the + +Thing + +object +as +defined +by +the + +action + +argument +of +type + + +ThingActionInit + + +and +updates +the + +Thing +Description +. +

+
+

+ +5.6.1 + +The + + +ThingActionInit + + +dictionary +

+
+
dictionary ThingActionInit {
+    DOMString              name;
+    ThingDescription       inputDataDescription;
+    ThingDescription       outputDataDescription;
+    sequence<SemanticType> semanticTypes;
+    Function               action;
+};
+
+
+
+

+The + + +ThingActionInit + + +dictionary +describes +the +arguments +and +the +return +value. +

+
    +
  • +The + + +name + + +attribute +provides +the + +Action + +name. +
  • +
  • +The + + +action + + +attribute +provides +a +function +that +defines +the + +Action +. +
  • +
  • +The + + +inputDataDescription + + +attribute +provides +the +description +of +the +input +arguments. +
  • +
  • +The + + +outputDataDescription + + +attribute +provides +the +description +of +the +returned +data. +
  • +
  • +The + + +semanticTypes + + +attribute +provides +a +list +of +semantic +type +annotations +(e.g. +labels, +classifications +etc) +relevant +to +the + +Action +, +represented +as + + +SemanticType + + +dictionaries. +
  • +
+
+
+
+

+ +5.7 + +The + + +removeAction() + + +method +

+

+Removes +the + +Action + +specified +by +the + +name + +argument, +updates +the + +Thing +Description + +and +returns +the +object. +

+
+
+

+ +5.8 + +The + + +addEvent() + + +method +

+

+Adds +an +event +to +the + +Thing + +object +as +defined +by +the + +event + +argument +of +type + + +ThingEventInit + + +and +updates +the + +Thing +Description +. +

+
+

+ +5.8.1 + +The + + +ThingEventInit + + +dictionary +

+
+
dictionary ThingEventInit {
+    DOMString              name;
+    sequence<SemanticType> semanticTypes;
+    ThingDescription       dataDescription;
+};
+
+
+
+
    +
  • +The + + +name + + +attribute +represents +the +event +name. +
  • +
  • +The + + +semanticTypes + + +attribute +represent +a +list +of +semantic +type +annotations +attached +to +the +event. +
  • +
  • +The + + +dataDescription + + +attribute +represents +the +description +of +the +data +that +is +attached +to +the +event. +
  • +
+
+
+
+

+ +5.9 + +The + + +removeEvent() + + +method +

+

+Removes +the +event +specified +by +the + +name + +argument, +updates +the + +Thing +Description + +and +returns +the +object. +

+
+
+

+ +5.10 + +The + + +onRetrieveProperty() + + +method +

+

+Registers +the +handler +function +for + +Property + +retrieve +requests +received +for +the + +Thing +, +as +defined +by +the + +handler + +property +of +type + + + +RequestHandler + + +. +The +handler +will +receive +an +argument + +request + +of +type + + + +Request + + + +where +at +least + +request.name + +is +defined +and +represents +the +name +of +the + +Property + +to +be +retrieved. +

+
+
+

+ +5.11 + +The + + +onUpdateProperty() + + +method +

+

+Defines +the +handler +function +for + +Property + +update +requests +received +for +the + +Thing +, +as +defined +by +the + +handler + +property +of +type + + + +RequestHandler + + +. +The +handler +will +receive +an +argument + +request + +of +type + + + +Request + + + +where + +request.name + +defines +the +name +of +the + +Property + +to +be +retrieved +and + +request.data + +defines +the +new +value +of +the + +Property +. +

+
+
+

+ +5.12 + +The + + +onInvokeAction() + + +method +

+

+Defines +the +handler +function +for + +Action + +invocation +requests +received +for +the + +Thing +, +as +defined +by +the + +handler + +property +of +type + + + +RequestHandler + + +. +The +handler +will +receive +an +argument + +request + +of +type + + + +Request + + + +where + +request.name + +defines +the +name +of +the + +Action + +to +be +invoked +and + +request.data + +defines +the +input +arguments +for +the + +Action + +as +defined +by +the + +Thing +Description +. +

+
+
+

+ +5.13 + +The + + +onObserve() + + +method +

+

+Defines +the +handler +function +for +observe +requests +received +for +the + +Thing +, +as +defined +by +the + +handler + +property +of +type + + + +RequestHandler + + +. +The +handler +will +receive +an +argument + +request + +of +type + + + +Request + + + +where +

+ +
+
+

+ +5.14 + +The + + +register() + + +method +

+

+Generates +the + +Thing +Description + +given +the +properties, + +Actions + +and + +Event + +defined +for +this +object. +If +a + +directory + +argument +is +given, +make +a +request +to +register +the + +Thing +Description + +with +the +given +WoT +repository +by +invoking +its + +register + + +Action +. +

+
+
+

+ +5.15 + +The + + +unregister() + + +method +

+

+If +a + +directory + +argument +is +given, +make +a +request +to +unregister +the + +Thing +Description + +with +the +given +WoT +repository +by +invoking +its + +unregister + + +Action +. +Then, +and +in +the +case +no +arguments +were +provided +to +this +function, +stop +the + +Thing + +and +remove +the + +Thing +Description +. +

+
+
+

+ +5.16 + +The + + +start() + + +method +

+

+Start +serving +external +requests +for +the + +Thing +. +

+
+
+

+ +5.17 + +The + + +stop() + + +method +

+

+Stop +serving +external +requests +for +the + +Thing +. +

+
+
+

+ +5.18 + +The + + +emitEvent() + + +method +

+

+Emits +an +the +event +initialized +with +the +event +name +specified +by +the + +eventName + +argument +and +data +specified +by +the + +payload + +argument. +

+
+
+

+ +5.19 + +Events +supported +by +ExposedThing +

+

+The +following +default +events + +SHOULD + +be +supported +by + + +ExposedThing + + +implementations: +

+ +

+In +addition, +user +defined +events +are +specified +by +the + +Thing +Description +. +

+
+
+

+ +5.20 + +Examples +

+

+Below +some + + + +ExposedThing + + + +interface +examples +are +given. +

+
+
+ +Example +6 + +: +Create +a +new +blank +exposed +Thing + +
+
WoT.createExposedThing(thingDescription)
+  .then(function(thing) {
+    // manually add properties, actions, and events
+    thing.addProperty({
+      name: "temperature",
+      value: "0",
+      writable: false
+      // use default values for the rest
+    }).addEvent({
+      name: "onchange",
+      outputDataDescription: {
+        type: "float32"
+      }
+    }).addAction({
+      name: "reset",
+      action: () => { this.temperature = 0; }
+    })
+    // add server functionality
+    .onRetrieveProperty( request => {
+      console.log("Handling read request");
+      return this.temperature;
+    }).onObserve( request => {
+      console.log("Handling observe request");
+      // add listener identified by request.from
+    }).onInvokeAction( request => {
+      console.log("Handling action request");
+    }).start();
+});
+
+
+
+
+ +Example +7 + +: +Create +a +new +exposed +Thing +from +a +TD +URI + +
+
let thingDescription = '{
+  "name": "mySensor",
+  "url": "http://myservice.org/mySensor/description"
+}';
+WoT.createExposedThing(thingDescription)
+  .then(function(thing) {
+    // properties, actions and events are added based on the TD
+    console.log("created " + thing.name });
+    // now add the requests handlers
+    thing.onRetrieveProperty(function(request) {
+        console.log("Sending property '" + request.property + "' to " + request.from);
+    }).onUpdateProperty(function(request) {
+        console.log("Updating property '" + request.property + "' by " + request.from);
+    }).onObserve(function(request) {
+        console.log("Adding listener " + request.from);
+        console.log("Observing " + request.type + " " + request.name +
+            (request.subscribe? " recursively" : ""));
+    }).start().then(function() {
+       console.log("Thing started serving requests");
+    });
+})
+
+
+
+
+ +Example +8 + +: +Create +a +new +exposed +Thing +from +a +Thing +Description + +
+
let thingDescription = '{
+  "name": "mySensor",
+  "description": {
+    "@context": [
+      "http://w3c.github.io/wot/w3c-wot-td-context.jsonld",
+      "http://w3c.github.io/wot/w3c-wot-common-context.jsonld",
+    ],
+    "@type": [ "Thing" ],
+    "interaction": [
+      // ...
+    ]
+    // ...
+  }'
+};
+WoT.createExposedThing(thingDescription)
+  .then(function(thing) {
+    // properties, actions and events are added based on the TD
+    // ...
+});
+
+
+
+
+
+

+ +6. + +Security +and +Privacy +

+
+
+ +Editor's +note + +
+

+Please +see +the + +WoT +Security +and +Privacy + +repository +for +work +in +progress +regarding +threat +models, +assets, +risks, +recommended +mitigations, +and +best +practices +for +security +and +privacy +for +systems +using +the +Web +of +Things. +Once +complete, +security +and +privacy +considerations +relevant +to +the +Scripting +API +will +be +summarized +in +this +section. +

+
+
+
+

+ +7. + +Terminology +and +conventions +

+

+The +generic +WoT +terminology +is +defined +in +[ + + +WOT-ARCHITECTURE + + +]: + +Thing +, + +Thing +Description + +(in +short + +TD + +), + +Web +of +Things + +(in +short + + +WoT + + +), + +WoT +Interface +, + +Protocol +Bindings +, + +WoT +Runtime +, + +Consuming +a +Thing +Description +, + +Thing +Directory +, + +Property +, + +Action +, + +Event + +etc. +

+
+
+ +Note + +
+

+In +this +version +of +the +specification, +a + +WoT +Runtime + +is +assumed +to +run +scripts +that +uses +this +API +to +define +one +or +more + +Thing + +s +that +share +a +common +event +loop. +Script +deployment +methods +are +out +of +scope +of +this +version. +In +future +versions, +running +multiple +scripts +(as +modules) +may +be +possible, +and +script +deployment + +MAY + +be +implemented +using +a +manager + +Thing + +whose + +Actions + +permit +script +lifecycle +management +operations. +

+
+

+ +JSON-LD + +is +defined +in +[ + + +JSON-LD + + +] +as +a +JSON +document +that +is +augmented +with +support +for +Linked +Data +by +providing +a + +@context + +property +with +a +defining +URI +. +

+

+The +terms + + +URL + + +and + + +URL +path + + +are +defined +in +[ + + +URL + + +]. +

+

+The +following +terms +are +defined +in +[ + + +HTML5 + + +] +and +are +used +in +the +context +of +browser +implementations: + + +browsing +context + +, + + +top-level +browsing +context + +, + + +global +object + +, + + +incumbent +settings +object + +, + + +Document + +, + + +document +base +URL + +, + + +Window + +, + + +WindowProxy + +, + + +origin + +, + + +ASCII +serialized +origin + +, +executing +algorithms + + +in +parallel + +, + + +queue +a +task + +, + + +task +source + +, + + +iframe + +, + + +valid +MIME +type + +. +

+

+A + +browsing +context + +refers +to +the +environment +in +which + +Document + +objects +are +presented +to +the +user. +A +given + +browsing +context + +has +a +single + + +WindowProxy + + +object, +but +it +can +have +many + + +Document + + +objects, +with +their +associated + + +Window + + +objects. +The + +script +execution +context + +associated +with +the + +browsing +context + +identifies +the +entity +which +invokes +this +API, +which +can +be +a + +web +app +, +a + +web +page +, +or +an + +iframe +. +

+

+The +term + + +secure +context + + +is +defined +in +[ + + +WEBAPPSEC + + +]. +

+

+ + +Error +, + +EvalError +, + +RangeError +, + +ReferenceError +, + +SyntaxError +, + +TypeError +, + +URIError + +, + + +script +execution +context + +, + + +Promise + +, + + +JSON + +, + + +JSON.stringify + + +and + + +JSON.parse + + +are +defined +in +[ + + +ECMASCRIPT + + +]. +

+

+ + +DOMString + +, + + +USVString + +, + + +ArrayBuffer + +, + + +BufferSource + + +and + + +any + + +are +defined +in +[ + + +WEBIDL + + +]. +

+

+The +term + + +event + + +and +the + + +Event + + +object +are +defined +in + +DOM + +and + +Node.js +. +

+
+
+ +Note + +
+

+This +specification +uses +the +convention +that +an +event +listener +will +receive +an + +Event + +object. +This +should +work +both +in +a +browser +environment +and +in +a +Node.js +like +environment. +

+
+

+ + +Observable + +s + +are +proposed +to +be +included +in +ECMAScript. +

+

+The +algorithms + + +utf-8 +encode + +, +and + + +utf-8 +decode + + +are +defined +in +[ + + +ENCODING + + +]. +

+

+ +IANA +media +type + +s +(formerly +known +as +MIME +types) +are +defined +in + +RFC2046 +. +

+
+
+

+ +8. + +Conformance +

+

+As +well +as +sections +marked +as +non-normative, +all +authoring +guidelines, +diagrams, +examples, +and +notes +in +this +specification +are +non-normative. +Everything +else +in +this +specification +is +normative. +

+

+The +key +words + +MAY +, + +MUST +, +and + +SHOULD + +are +to +be +interpreted +as +described +in +[ + + +RFC2119 + + +]. +

+

+This +document +defines +conformance +criteria +that +apply +to +a +single +product: +the + +UA + +(user +agent) +that +implements +the +interfaces +it +contains. +

+

+This +specification +can +be +used +for +implementing +the +WoT +Scripting +API +in +multiple +programming +languages. +The +interface +definitions +are +specified +in +[ + + +WEBIDL + + +]. +

+

+The +user +agent +(UA) +may +be +implemented +in +the +browser, +or +in +a +separate +runtime +environment, +such +as + +Node.js + +or +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 + + +]. +

+

+This +document +serves +a +general +description +of +the +WoT +Scripting +API. +Language +and +runtime +specific +issues +are +discussed +in +separate +extensions +of +this +document. +

+
+
+

+ +A. + +Changes +

+

+The +following +is +a +list +of +major +changes +to +the +document. +For +a +complete +list +of +changes, +see +the + +github +change +log +. +You +can +also +view +the + +recently +closed +bugs +. +

+
+
+

+ +B. + +Open +issues +

+

+The +following +problems +are +being +discussed +and +need +most +attention: +

+ +
+
+

+ +C. + +Acknowledgements +

+

+Special +thanks +to +former +editor +Johannes +Hund +(until +August +2017, +when +at +Siemens +AG) + +for +developing +this +specification. +Also, +the +editors +would +like +to +thank +Dave +Raggett, +Matthias +Kovatsch, +Michael +Koster +and +Michael +McCool +for +their +comments +and +guidance. +

+
+
+

+ +D. + +References +

+
+

+ +D.1 + +Normative +references +

+
+
+[ECMASCRIPT] +
+
+ + +ECMAScript +Language +Specification + +. +Ecma +International. +URL: + +https://tc39.github.io/ecma262/ + +
+
+[ENCODING] +
+
+ + +Encoding +Standard + +. +Anne +van +Kesteren. +WHATWG. +Living +Standard. +URL: + +https://encoding.spec.whatwg.org/ + +
+
+[HTML5] +
+
+ + +HTML5 + +. +Ian +Hickson; +Robin +Berjon; +Steve +Faulkner; +Travis +Leithead; +Erika +Doyle +Navara; +Theresa +O'Connor; +Silvia +Pfeiffer. +W3C. +28 +October +2014. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/html5/ + +
+
+[JSON-LD] +
+
+ + +JSON-LD +1.0 + +. +Manu +Sporny; +Gregg +Kellogg; +Markus +Lanthaler. +W3C. +16 +January +2014. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/json-ld/ + +
+
+[RFC2119] +
+
+ + +Key +words +for +use +in +RFCs +to +Indicate +Requirement +Levels + +. +S. +Bradner. +IETF. +March +1997. +Best +Current +Practice. +URL: + +https://tools.ietf.org/html/rfc2119 + +
+
+[TYPESCRIPT] +
+
+ + +TypeScript +Language +Specification + +. +Microsoft. +1 +October +2012. +URL: + +https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md + +
+
+[URL] +
+
+ + +URL +Standard + +. +Anne +van +Kesteren. +WHATWG. +Living +Standard. +URL: + +https://url.spec.whatwg.org/ + +
+
+[WEBAPPSEC] +
+
+ + +Secure +Contexts + +. +W3C. +17 +July +2015. +URL: + +https://w3c.github.io/webappsec/specs/powerfulfeatures + +
+
+[WEBIDL] +
+
+ + +Web +IDL + +. +Cameron +McCormack; +Boris +Zbarsky; +Tobie +Langel. +W3C. +15 +December +2016. +W3C +Editor's +Draft. +URL: + +https://heycam.github.io/webidl/ + +
+
+[WOT-ARCHITECTURE] +
+
+ + +Web +of +Things +Architecture + +. +W3C. +20 +August +2017. +URL: + +https://w3c.github.io/wot-architecture/ + +
+
+
+
+ + + + diff --git a/releases/wd2/Overview.html b/releases/wd2/Overview.html new file mode 100644 index 00000000..9d8eb7cf --- /dev/null +++ b/releases/wd2/Overview.html @@ -0,0 +1,4805 @@ + + + + + + + + + + + Web of Things (WoT) Scripting API + + + + + + + + +
+ +

Web of Things (WoT) + Scripting API

+

W3C Working Draft +

+
+
This version:
+
+ + https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ +
+
Latest published version:
+
+ https://www.w3.org/TR/wot-scripting-api/ +
+
Latest editor's draft:
+
+ https://w3c.github.io/wot-scripting-api/ +
+
Previous version:
+
+ + https://www.w3.org/TR/2017/WD-wot-scripting-api-20170914/ +
+
Editors:
+
+ Zoltan Kis (Intel) +
+
+ Kazuaki Nimura (Fujitsu Ltd.) +
+
+ Daniel Peintner (Siemens AG) +
+
Johannes Hund (Former Editor, when at + Siemens AG)
+
Contributors:
+
+ + In the GitHub repository +
+
Repository:
+
+ We are + on GitHub +
+
+ File a + bug +
+
+ +
+
+
+

Abstract

+

The Web of Things (WoT) provides layered + interoperability between Things by using the + WoT Interfaces.

+

This specification describes a programming interface + representing the WoT Interface that + allows scripts run on a Thing to discover and + consume (retrieve) other Things and to expose + Things characterized by WoT Interactions, i.e. Properties, + Actions and Events.

+

Scripting is an optional "convenience" building block in WoT + and it is typically used in gateways 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 like + Thing Directory.

+
+
+

Status of This Document

+

This section describes the status of this document at + the time of its publication. Other documents may supersede this + document. A list of current W3C publications and the + latest revision of this technical report can be found in the + W3C technical reports + 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.

+
+
+ Editor's note: The W3C WoT WG is asking for + feedback +
+

Please contribute to this draft using the + GitHub + Issue feature 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 + a Working Draft. + This document is intended to become a W3C Recommendation. + Comments regarding this document are + welcome. Please send them to public-wot-wg@w3.org + (subscribe, + archives).

+

Changes from the previous publication can be found in + Appendix A. A diff-marked version of this document is also + available for comparison purposes.

+

Publication as a Working Draft does not imply endorsement by + the W3C + Membership. This is a draft document and may be updated, + replaced or obsoleted by other documents at any time. It is + inappropriate to cite this document as other than work in + progress.

+

This document was produced by a group operating under the + 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 1 February 2018 + W3C Process + Document.

+
+ +
+ +

1. + Introduction

+

The overall WoT concepts are described in the + + WoT Architecture document. The Web of Things is made of entities (Things) that can describe their capabilities in a + machine-interpretable format, the Thing Description (TD) and expose these capabilities + through the WoT Interface. Support for scripting + is optional for WoT devices.

+

By consuming a TD, a client Thing creates a runtime resource model that allows + accessing the Properties, Actions and + Events exposed by the server Thing.

+

Exposing a Thing requires defining a Thing Description (TD) and instantiating a software + stack needed to serve requests for accessing the exposed + Properties, Actions and Events. This specification describes how to expose + and consume Things by a script.

+
+
+ Note +
+

Typically scripts are meant to be used on devices + able to provide resources (with a WoT interface) for managing (installing, updating, + running) scripts, such as bridges or gateways that expose and + control simpler devices as WoT Things.

+
+
+
+ Note +
+

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.

+
+

For an introduction on how scripts could be used in Web of Things, check the Primer + document. For some background on API design decisions check the + Rationale + document.

+
+
+ +

2. Use + Cases

+

This section is non-normative.

+

The following scripting use cases are supported in this + specification:

+
+

2.1 + Discovery

+ +
+
+

2.2 Consuming a Thing

+ +
+
+

2.3 + Exposing a Thing

+ +
+
+
+ +

3. The + WoT object

+

The WoT object is the API entry point and it is exposed by + an implementation of the WoT Runtime. The + WoT object + does not expose properties, only methods for discovering, + consuming and exposing a Thing.

+
+
+ Note +
+

Browser implementations SHOULD use a namespace object such as + wot, and Node.js-like runtimes MAY provide the API object through + the require() + or + import mechanism.

+
+
+
interface WoT {
+    Observable<ConsumedThing> discover(optional ThingFilter filter);
+    Promise<ThingDescription> fetch(USVString url);
+    ConsumedThing             consume(ThingDescription td);
+    ExposedThing              produce(ThingModel model);
+};
+
+typedef USVString ThingDescription;
+
+typedef (ThingTemplate or ThingDescription) ThingModel;
+
+
+
+ Editor's note +
+

The algorithms for the WoT methods will be + specified later, including error handling and security + considerations.

+
+
+

3.1 The discover() + method

+

Starts the discovery process that will provide + ConsumedThing + objects that match the optional argument ThingFilter. When the argument + is not provided, starts the widest discovery the Thing Description and Protocol Bindings allow and support. Returns an + Observable + object that can be subscribed to and unsubscribed from.

+
+

+ 3.1.1 The DiscoveryMethod + enumeration

+
+
typedef DOMString DiscoveryMethod;
+
+

DiscoveryMethod + represents the discovery type to be used:

+
    +
  • "any" + does not provide any restriction
  • +
  • + "local" + for discovering Things defined + in the same device +
  • +
  • + "nearby" + for discovering Things nearby + the device, e.g. by Bluetooth or NFC +
  • +
  • + "directory" for discovery based + on a service provided by a directory or repository of + Things +
  • +
  • "broadcast" for an open ended + discovery based on sending a request to a broadcast + address
  • +
  • "other" + for a proprietary method defined by the solution.
  • +
+
+
+

3.1.2 The ThingFilter + dictionary

+

The ThingFilter + dictionary that represents the constraints for discovering + Things as key-value pairs.

+
+
dictionary ThingFilter {
+    DiscoveryMethod      method = "any";
+    USVString            url;
+    USVString            query;
+    sequence<Dictionary> constraints;
+};
+
+

The method property represents the + discovery type that should be used in the discovery + process. The possible values are defined by the + DiscoveryMethod enumeration + that can be extended by string values defined by solutions + (with no guarantee of interoperability).

+
+
+ Editor's note +
+

The DiscoveryMethod enumeration can be + extended by the Thing Description + with values that are not specified here. This + extensibility of DiscoveryMethod by proprietary or + private methods is a working assumption until consensus + is formed and may be removed later.

+
+

The url property represents additional + information for the discovery method, such as the URL of + the target entity serving the discovery request, such as a + Thing Directory or a Thing.

+

The query property represents a + query string accepted by the implementation, for instance a + SPARQL query.

+

The constraints property + represents additional information for the discovery method + in the form of a list of sets of property-value pairs + (dictionaries). The list elements (dictionaries) are in OR + relationship, and within a constraint dictionary the + key-value pairs are in AND relationship. Implementations + SHOULD make the + following mapping from the constraint dictionaries to + SemanticAnnotations: + for each property-value pair in a constraint + dictionary,

+
    +
  • Each property name in the constraint dictionary + SHOULD match the + either the name property of a defined + SemanticType on the + target Thing object, or the name of a + Property on the target + Thing. +
  • +
  • When the name matches, the values are compared. If + the values match, the constraint is matched.
  • +
+
+
+ Editor's note +
+

Constraints are experimental feature, + implementations are not required to support them.

+
+
+
+ Editor's note +
+

Semantic annotations need revisiting in order + to simplify their representation. In the [WOT-TD] + specification they represent the @type + construct. At the moment only @context, + @type and @id constructs are + used in the TD.

+
+
+
+
+

3.2 + The fetch() method

+

Accepts an url argument and returns a + Promise that resolves with a + ThingDescription.

+
+
+

3.3 The ThingDescription + type

+

Representation of the Thing + Description, standardized in the + + Wot Things Description specification.

+
+
+ Note +
+

In this version of the API, Thing Descriptions are represented + as opaque strings, denoting a serialized form, for instance + JSON or JSON-LD. See Issue + 38 and Issue + 45.

+
+
+
+

3.4 The consume() + method

+

Accepts an td argument of type ThingDescription and returns a + ConsumedThing object + instantiated based on that description.

+
+
+

3.5 The produce() method

+

Accepts a model argument of type + ThingModel and + returns an ExposedThing object, + locally created based on the provided initialization + parameters. An ExposedThing can be created in the + following ways:

+
    +
  1. from an initial model (including a user given name and + semantic + annotations), then adding properties, actions, events + and request handlers; +
  2. +
  3. from a Thing Description + (possibly of a ConsumedThing object), then adding + request handlers. +
  4. +
+
+
+

3.6 The ThingModel type

+

A Thing model is used for producing a new ExposedThing and can be either a + ThingTemplate, or a + ThingDescription.

+
+
+

3.7 The SemanticAnnotations + dictionary

+

A dictionary that provides the semantic types and semantic + metadata.

+
+
dictionary SemanticAnnotations {
+    sequence<SemanticType>     semanticType;
+    sequence<SemanticMetadata> metadata;
+};
+
+

The semanticType + property denotes a list of SemanticType objects that define the + semantic types that can be used in semantic metadata + type-value pairs.

+

The metadata property + denotes a list of SemanticMetadata objects (type-value + pairs).

+
+
+

3.8 The SemanticType + dictionary

+
+
dictionary SemanticType {
+    required DOMString name;
+    required USVString context;
+             DOMString prefix;
+};
+
+

Represents a semantic type annotation, containing a name, + a context and a prefix.

+ +
+
+ Editor's note +
+

Semantic type examples to be added.

+
+
+
+

3.9 The SemanticMetadata + dictionary

+
+
dictionary SemanticMetadata {
+    SemanticType type;
+    any          value;
+};
+
+

The SemanticMetadata + dictionary describes a pair of semantic type and value:

+ +
+
+

3.10 The ThingTemplate + dictionary

+

A Thing Template is a dictionary that provides a user + given name, and the semantic types and semantic metadata + attached to the ExposedThing Thing Description's root level.

+
+
dictionary ThingTemplate : SemanticAnnotations {
+    required DOMString name;
+};
+
+

The ThingTemplate + dictionary extends SemanticAnnotations and contains + properties to initialize a Thing:

+ +
+
+ Editor's note +
+

Support for configuration and security data + might be added later.

+
+
+
+

3.11 + Examples

+
+
+ Example 1: Discover Things via + directory +
+
let discoveryFilter = {
+  method: "directory",
+  url: "http://directory.wotservice.org"
+};
+let subscription = wot.discover(discoveryFilter).subscribe(
+  thing => { console.log("Found Thing " + thing.name); },
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout( () => {
+    subscription.unsubscribe();
+    console.log("Discovery timeout");
+  },
+  5000);
+
+
+
+ Note +
+

Note that canceling a discovery (through + unsubscribe()) may not be successful in all + cases, for instance when discovery is based on open ended + broadcast requests. However, once + unsubscribe() has been called, implementations + MUST suppress further + event handling ( i.e. further discoveries and errors) on + the Observable. Also, a discovery error may not mean the + end of the discovery process. However, in order to respect + Observable semantics (error always terminates processing), + implementations MUST + close or suppress further event handling on the + Observable.

+
+
+
+ Example 2: Discover Things exposed by local + hardware +
+
let subscription = wot.discover({ method: "local" }).subscribe(
+  thing => { console.log("Found local Thing " + thing.name); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+ Example 3: Same as above but with different + Observable syntax +
+
let subscription = wot.discover({ method: "local" }).subscribe({
+  thing => { console.log("Found local Thing " + thing.name); },
+  error: err => { console.log("Discovery error: " + err.message); },
+  complete: () => { console.log("Discovery finished successfully");}
+});
+
+
+
+ Example 4: Discover Things exposed nearby, + via Bluetooth or NFC +
+
let subscription = wot.discover({
+  method: "nearby",
+  constraints: [{ protocol: "BLE-4.2" }, { protocol: "NFC"}]
+}).subscribe(
+  thing => { console.log("Found nearby Thing " + thing.name); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+ Example 5: Discover Things exposed in a + proprietary way +
+
let subscription = wot.discover({
+  method: "other",
+  constraints: [{ solution: "XYZ123", key: "..."}]
+}).subscribe(
+  thing => { console.log("Found Thing " + thing.name); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +

4. The ConsumedThing interface

+

The ConsumedThing interface + is a client API for sending requests to servers in order to + retrieve or update Properties, invoke + Actions, and observe Properties and Events.

+
+
interface ConsumedThing {
+    readonly attribute DOMString name;
+    ThingDescription getThingDescription();
+    Promise<any>     readProperty(DOMString name);
+    Promise<void>    writeProperty(DOMString name, any value);
+    Promise<any>     invokeAction(DOMString name, any parameters);
+    Observable       onPropertyChange(DOMString name);
+    Observable       onEvent(DOMString name);
+    Observable       onTDChange();
+};
+
+

ConsumedThing represents a local proxy object + of the remote Thing.

+
+

4.1 The name property

+

The name property represents the name of the + Thing as specified in the TD. In this version it + is read only.

+
+
+

4.2 The getThingDescription() + method

+

Returns the Thing Description of + the Thing.

+
+
+ Editor's note +
+

In this version, introspection based on + TD is out of scope. Parsing and exposing Thing Descriptions is discussed in + Issue + 38.

+
+
+
+

4.3 The readProperty() + method

+

Takes the Property name as the name + argument, then requests from the underlying platform and the + Protocol Bindings to retrieve the + Property on the remote Thing and return the + result. Returns a Promise that + resolves with the Property value or + rejects with an Error.

+
+
+

4.4 The writeProperty() + method

+

Takes the Property name as the name + argument and the new value as the value argument, + then requests from the underlying platform and the Protocol Bindings to update the Property on the remote Thing and return the + result. Returns a Promise that + resolves on success or rejects with an Error.

+
+
+

4.5 The invokeAction() + method

+

Takes the Action name from the name + argument and the list of parameters, then requests from the + underlying platform and the Protocol + Bindings to invoke the Action on the remote + Thing and return the result. Returns a + Promise that resolves with + the return value or rejects with an Error.

+
+
+

4.6 The onPropertyChange() + method

+

Returns an Observable for the + Property specified in the name argument, + allowing subscribing to and unsubscribing from + notifications.

+

The callback function passed to the + subscribe() method when invoked on the returned + observer will receive the new property value each time it is + changed.

+
+
+

4.7 The onEvent() method

+

Returns an Observable for the + Event specified in the name argument, + allowing subscribing to and unsubscribing from + notifications.

+

The callback function passed to the + subscribe() method when invoked on the returned + observer will receive the event data each time the event is + fired.

+
+
+

4.8 The onTDChange() + method

+

Returns an Observable, allowing + subscribing to and unsubscribing from notifications to the + Thing Description.

+

The callback function passed to the + subscribe() method when invoked on the returned + observer will receive the new Thing Description each time it is changed.

+
+
+

4.9 + Examples

+

Below a ConsumedThing interface example + is given.

+
+
+ Example 6: Consume a Thing +
+
try {
+  let td = await wot.fetch("http://mmyservice.org/mySensor");
+  let thing = wot.consume(td);
+  console.log("Thing " + thing.name + " has been consumed.");
+  let subscription = thing.onPropertyChange("temperature")
+    .subscribe(function(value) {
+      console.log("Temperature + " has changed to " + value);
+    });
+  thing.invokeAction("startMeasurement", { units: "Celsius" })
+    .then(() => { console.log("Temperature measurement started."); })
+    .catch(e => {
+       console.log("Error starting measurement.");
+       subscription.unsubscribe();
+     })
+} catch(error) {
+  console.log("Error during fetch or consume: " + error.message);
+};
+
+
+
+
+ +

5. The ExposedThing interface

+

The ExposedThing interface is + the server API that allows defining request handlers, + properties, Actions, and Events to a + Thing. It also implements the ConsumedThing interface. An ExposedThing is created by the produce() method.

+
+
+ Editor's note +
+

It is under consideration to use a constructor + for ExposedThing instead of + a factory method.

+
+
+
ExposedThing implements ConsumedThing;
+
+interface ExposedThing {
+    // define how to expose and run the Thing
+    Promise<void> start();
+    Promise<void> stop();
+    Promise<void> register(optional USVString directory);
+    Promise<void> unregister(optional USVString directory);
+    Promise<void> emitEvent(DOMString eventName, any payload);
+    // define Thing Description modifiers
+    ExposedThing  addProperty(ThingProperty property);
+    ExposedThing  removeProperty(DOMString name);
+    ExposedThing  addAction(ThingAction action);
+    ExposedThing  removeAction(DOMString name);
+    ExposedThing  addEvent(ThingEvent event);
+    ExposedThing  removeEvent(DOMString name);
+    // define request handlers
+    ExposedThing  setPropertyReadHandler(DOMString name,
+                                         PropertyReadHandler readHandler);
+    ExposedThing  setPropertyWriteHandler(DOMString name,
+                                          PropertyWriteHandler writeHandler);
+    ExposedThing  setActionHandler(DOMString name, ActionHandler action);
+};
+
+callback PropertyReadHandler = Promise<any> ();
+
+callback PropertyWriteHandler = Promise<void> (any value);
+
+callback ActionHandler = Promise<any> (any parameters);
+
+
+

5.1 + The start() + method

+

Start serving external requests for the Thing.

+
+
+

5.2 + The stop() method

+

Stop serving external requests for the Thing.

+
+
+

5.3 The register() + method

+

Generates the Thing Description + given the properties, Actions and Event defined for this object. If a + directory argument is given, make a request to + register the Thing Description with + the given WoT repository by invoking its + register Action.

+
+
+

5.4 The unregister() + method

+

If a directory argument is given, make a + request to unregister the Thing + Description with the given WoT repository by invoking its + unregister Action. Then, and in + the case no arguments were provided to this function, stop + the Thing and remove the Thing Description.

+
+
+

5.5 The emitEvent() + method

+

Emits an the event initialized with the event name + specified by the eventName argument and data + specified by the payload argument.

+
+
+

5.6 The DataSchema type

+
+
typedef USVString DataSchema;
+
+

The DataSchema type + represents a data type + + specified + in the Thing Description in a serialized + form.

+
+
+ Editor's note +
+

DataSchema is under + development, currently it can denote any type supported by + the Thing Description and the WoT Runtime.

+
+
+
+

5.7 The addProperty() + method

+

Adds a Property defined by the argument and + updates the Thing Description. + Throws on error. Returns a reference to the same object for + supporting chaining.

+
+

5.7.1 The ThingProperty + dictionary

+
+
dictionary ThingProperty : SemanticAnnotations {
+    required DOMString  name;
+    required DataSchema schema;
+             any        value;
+             boolean    writable = false;
+             boolean    observable = false;
+};
+
+

Represents the Thing Property + description.

+
    +
  • The name + attribute represents the name of the Property. +
  • +
  • The schema attribute represents + the data type for the Property + described by DataSchema. +
  • +
  • The value + attribute represents the value of the Property. +
  • +
  • The writable attribute + defines whether the Property can be + updated. The default value is false. +
  • +
  • The observable attribute + defines whether the Property changes + can be observed by an external client. The default + value is false. +
  • +
+
+
+
+

5.8 The removeProperty() + method

+

Removes the Property specified by the + name argument and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.9 The addAction() + method

+

Adds an Action to the Thing object as + defined by the action argument of type ThingAction and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+

5.9.1 The ThingAction + dictionary

+
+
dictionary ThingAction : SemanticAnnotations {
+    required DOMString  name;
+             DataSchema inputSchema;
+             DataSchema outputSchema;
+};
+
+

The ThingAction + dictionary describes the arguments and the return + value.

+
    +
  • The name attribute provides the + Action name. +
  • +
  • The inputSchema + attribute provides the description of the input arguments + (argument list is represented by an object). If missing, + it means the action does not accept arguments.
  • +
  • The outputSchema + attribute provides the description of the returned data. + If missing, it means the action does not return + data.
  • +
+
+
+
+

5.10 The removeAction() + method

+

Removes the Action specified by the + name argument and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.11 The addEvent() + method

+

Adds an event to the Thing object as + defined by the event argument of type ThingEvent and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+

5.11.1 The ThingEvent + dictionary

+
+
dictionary ThingEvent : SemanticAnnotations {
+    required DOMString  name;
+             DataSchema schema;
+};
+
+
    +
  • The name attribute represents the + event name.
  • +
  • The schema attribute represents + the type of the data that is attached to the event. If + missing, it means the event does not carry data.
  • +
+
+
+
+

5.12 The removeEvent() + method

+

Removes the event specified by the name + argument and updates the Thing + Description. Returns a reference to the same object for + supporting chaining.

+
+
+

5.13 The PropertyReadHandler + callback

+

A function that returns a Promise and resolves it with the + value of the Property matching the + name argument to the + setPropertyReadHandler function, or rejects with + an error if the property is not found or the value cannot be + retrieved.

+
+
+

5.14 The PropertyWriteHandler + callback

+

A function called with value as argument that + returns a Promise which is resolved when the value of the + Property matching the name argument to + the setPropertyReadHandler function is updated + with value, or rejects with an error if the + property is not found or the value cannot be updated.

+
+
+ Editor's note +
+

Note that this function is invoked by + implementations before the property is updated, so the code + in this callback function can invoke the + readProperty() method to find out the old + value of the property, if needed. Therefore the old value + is not provided to this method.

+
+
+
+

5.15 The ActionHandler + callback

+

A function called with a parameters + dictionary argument assembled by the WoT runtime based on the Thing Description and the external client request. + It returns a Promise that rejects with an error or resolves + if the action is successful or ongoing (may also resolve with + a control object such as an Observable for actions that need + progress notifications or that can be canceled).

+
+
+

5.16 The setPropertyReadHandler() + method

+

Takes name as string argument and + readHandler as argument of type PropertyReadHandler. + Sets the handler function for reading the specified Property matched by name. Throws on + error. Returns a reference to the same object for supporting + chaining.

+

The readHandler callback function will + implement reading a Property and + SHOULD be called by + implementations when a request for reading a Property is received from the underlying + platform.

+

There SHOULD be at + most one handler for any given Property and + newly added handlers replace the old handlers. If no handler + is initialized for any given Property, + implementations SHOULD implement a default property read + handler.

+
+
+

+ 5.17 The setPropertyWriteHandler() + method

+

Takes name as string argument and + writeHandler as argument of type PropertyWriteHandler. + Sets the handler function for writing the specified Property matched by name. Throws on + error. Returns a reference to the same object for supporting + chaining.

+

There SHOULD be at + most one write handler for any given Property and newly added handlers replace the old + handlers. If no write handler is initialized for any given + Property, implementations SHOULD implement default property update + and notifying observers on change.

+
+
+

5.18 The setActionHandler() + method

+

Takes name as string argument and + action as argument of type ActionHandler. Sets the handler + function for the specified Action matched by + name. Throws on error. Returns a reference to + the same object for supporting chaining.

+

If provided, this callback function will implement + invoking an Action and SHOULD be called by implementations when + a request for invoking a Action is received + from the underlying platform. The callback will receive a + parameters dictionary argument.

+

There SHOULD be + exactly one handler for any given Action. If no + handler is initialized for any given Action, + implementations SHOULD return error if the action is invoked by + any client.

+
+
+

5.19 + Examples

+

Below some ExposedThing interface examples + are given.

+
+
+ Example 7: Create a new blank exposed + Thing +
+
+        try {
+  var thing = WoT.produce({ name: "tempSensor" });
+  // manually add Interactions
+  thing.addProperty({
+    name: "temperature",
+    value: 0.0,
+    schema: '{ "type": "number" }'
+    // use default values for the rest
+  }).addProperty({
+    name: "max",
+    value: 0.0,
+    schema: '{ "type": "number" }'
+    // use default values for the rest
+  }).addAction({
+    name: "reset",
+    // no input, no output
+  }).addEvent({
+    name: "onchange",
+    schema: '{ "type": "number" }'
+  });
+  // add server functionality
+  thing.setActionHandler("reset", () => {
+    console.log("Resetting maximum");
+    thing.writeProperty("max", 0.0);
+  });
+  thing.start().then(() => {
+      thing.register();
+  });
+  // define Thing business logic
+  setInterval( async () => {
+    let mock = Math.random()*100;
+    thing.writeProperty("temperature", mock);
+    let old = await thing.readProperty("max");
+    if (old < mock) {
+      thing.writeProperty("max", mock);
+      thing.emitEvent("onchange");
+    }
+  }, 1000);
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ Example 8: Create a new exposed Thing from + a Thing Description +
+
+        let thingDescription = '{ "@context": [ "https://w3c.github.io/wot/w3c-wot-td-context.jsonld", "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ], "@type": [ "Thing", "Sensor" ], "name": "mySensor", "geo:location": "testspace", "interaction": [ { "@type": [ "Property", "Temperature" ], "name": "prop1", "schema": { "type": "number" }, "saref:TemperatureUnit": "degree_Celsius" } ] }';
+try {
+  // note that produce() fails if thingDescription contains error
+  let thing = WoT.produce(thingDescription);
+  // Interactions were added from TD
+  // WoT adds generic handler for reading any property
+  // define a specific handler for one property
+  let name = "examplePropertyName";
+  thing.setPropertyReadHandler(name, () => {
+    console.log("Handling read request for " + name);
+    return new Promise((resolve, reject) => {
+        let examplePropertyValue = 5;
+        resolve(examplePropertyValue);
+      },
+      e => {
+        console.log("Error");
+      });
+  });
+  thing.start();
+} catch(err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ Example 9: Create a new exposed Thing from + a TD URI +
+
+        // fetch an external TD, e.g., to set up a proxy for that Thing
+WoT.fetch("http://myservice.org/mySensor/description").then(td => {
+  // WoT.produce() ignores instance-specific metadata (security, form)
+  let thing = WoT.produce(td);
+  // Interactions were added from TD
+  // add server functionality
+  // ...
+});
+
+
+
+
+ +

+ 6. Experimental extensions to the + ConsumedThing interface

+

This section is non-normative.

+

The ThingDescription related + functionality, such as enumerating Properties, + Actions, Events and links (introspection) is an + API extension that is out of scope for this specification. + However, the draft interfaces are defined here for informative + purposes.

+
+
partial interface ConsumedThing {
+    sequence<ThingProperty> getProperties();
+    sequence<ThingAction>   getActions();
+    sequence<ThingEvent>    getEvents();
+    sequence<TDLink>        getLinks();
+};
+
+
+

6.1 The getProperties() + method

+

Returns the list of Properties defined in + the Thing Description of the Thing in the form of a list of ThingProperty objects.

+
+
+

6.2 The getActions() + method

+

Returns the list of Actions defined in the + Thing Description of the Thing in the form of a list of ThingAction objects.

+
+
+

6.3 The getEvents() + method

+

Returns the list of Events defined in the + Thing Description of the Thing in the form of a list of ThingEvent objects.

+
+ +
+
+ +

7. + Observables

+

This section is non-normative.

+

Observables are proposed to + be included in ECMAScript and are used for handling pushed data + associated with various possible sources, for instance events, + timers, streams, etc. A minimal required implementation is + described here.

+
+
+ Editor's note +
+

This section is informal and contains rather + laconic information for implementations on what to support + for interoperability.

+
+
+
interface Observable {
+    Subscription subscribe((Observer or OnNext) next,
+                           optional OnError error,
+                           optional OnComplete complete);
+};
+
+interface Subscription {
+    void unsubscribe();
+    readonly attribute boolean closed;
+};
+
+interface Observer {
+    void next(any value);
+    void error(Error error);
+    void complete();
+};
+
+callback OnNext = void (any value);
+
+callback OnError = void (Error error);
+
+callback OnComplete = void ();
+
+
+

7.1 The Observer interface

+

The Observer interface + defines the callbacks needed to handle an Observable:

+ +
+
+

7.2 The Subscription interface

+

Contains the closed property of + type boolean that tells if the subscription is + closed or active.

+

Also, contains the unsubscribe() + method that cancels the subscription, i.e. makes a request to + the underlying platform to stop receiving data from the + source, and sets the closed property to + false.

+
+
+

7.3 The Observable interface

+

The Observable interface + enabled subscribing to pushed data notifications by the + subscribe() + method:

+ +
+
+
+ +

8. Security and + Privacy

+
+
+ Editor's note +
+

Please see the WoT Security and + Privacy repository for work in progress regarding threat + models, assets, risks, recommended mitigations, and best + practices for security and privacy for systems using the Web + of Things. Once complete, security and privacy considerations + relevant to the Scripting API will be summarized in this + section.

+
+
+
+ +

9. Terminology and conventions

+

The generic WoT terminology is defined in [WOT-ARCHITECTURE]: + Thing, Thing Description (in short + TD), + Web of + Things (in short WoT), WoT Interface, + Protocol + Bindings, WoT Runtime, Consuming a Thing + Description, Thing Directory, + WoT + Interactions, Property, + Action, Event etc.

+

JSON-LD is + defined in [JSON-LD] as a JSON document that is + augmented with support for Linked Data by providing a + @context property with a defining URI .

+

The terms URL and URL path are defined in + [URL].

+ +

The following terms are defined in [HTML52] and are used in the context + of browser implementations: + + + browsing + context, + + + top-level browsing + context, + + + global + object, + + + incumbent settings + object, + + + Document, + + + document + base URL, + + + Window, + + + WindowProxy, + + + origin, + + + ASCII + serialized origin, + + executing algorithms + + + in parallel, + + + queue a task, + + + task source, + + + iframe, + + + valid MIME type.

+ +

A browsing context refers to the + environment in which Document objects are + presented to the user. A given browsing context + has a single WindowProxy + object, but it can have many Document + objects, with their associated Window + objects. The script execution context + associated with the browsing context identifies the + entity which invokes this API, which can be a web app, a + web page, or an iframe.

+

The term + secure + context is defined in [WEBAPPSEC].

+

Error, EvalError, RangeError, ReferenceError, SyntaxError, + TypeError, + URIError , + script execution + context, + Promise, + + JSON, + JSON.stringify and + JSON.parse are defined in + [ECMASCRIPT].

+

DOMString, USVString, ArrayBuffer, BufferSource and any are defined in + [WEBIDL].

+

The algorithms utf-8 encode, and utf-8 decode are defined in + [ENCODING].

+

IANA media + types (formerly known as MIME types) are defined in + RFC2046.

+

The terms hyperlink reference and + relation + type are defined in [HTML52] and RFC8288.

+
+
+ +

10. + Conformance

+

As well as sections marked as non-normative, all authoring + guidelines, diagrams, examples, and notes in this specification + are non-normative. Everything else in this specification is + normative.

+

The key words MAY, MUST, and + SHOULD are to be interpreted as + described in [RFC2119].

+

This document defines conformance criteria that apply to a + single product: the UA (user agent) that implements the interfaces + it contains.

+

This specification can be used for implementing the WoT + Scripting API in multiple programming languages. The interface + definitions are specified in [WEBIDL].

+

The user agent (UA) may be implemented in the browser, or in + a separate runtime environment, such as Node.js or 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].

+

This document serves a general description of the WoT + Scripting API. Language and runtime specific issues are + discussed in separate extensions of this document.

+
+
+ +

A. Changes

+

The following is a list of major changes to the document. + For a complete list of changes, see the github + change log. You can also view the + recently closed bugs.

+ +
+
+ +

B. Open issues

+

The following problems are being discussed and need most + attention:

+ +
+
+ +

C. + Acknowledgements

+

Special thanks to former editor Johannes Hund (until August + 2017, when at Siemens AG) for developing this specification. + Also, the editors would like to thank Dave Raggett, Matthias + Kovatsch, Michael Koster and Michael McCool for their comments + and guidance.

+
+
+ +

D. + References

+
+

D.1 Normative references

+
+
[ECMASCRIPT]
+
+ ECMAScript + Language Specification. Ecma International. + URL: https://tc39.github.io/ecma262/ +
+
[ENCODING]
+
+ Encoding. + Anne van Kesteren; Joshua Bell; Addison Phillips. W3C. 15 + December 2016. W3C Candidate Recommendation. URL: + https://www.w3.org/TR/encoding/ +
+
[HTML52]
+
+ HTML 5.2. + Steve Faulkner; + Arron Eicholz; + Travis Leithead; + Alex Danilo; + Sangwhan Moon; + Erika Doyle Navara; + Theresa O'Connor; + Robin Berjon. + W3C. 14 December 2017. W3C Recommendation. URL: + https://www.w3.org/TR/html52/ +
+
[JSON-LD]
+
+ JSON-LD + 1.0. Manu Sporny; Gregg Kellogg; Markus + Lanthaler. W3C. 16 January 2014. W3C Recommendation. URL: + https://www.w3.org/TR/json-ld/ +
+
[RFC2119]
+
+ Key + words for use in RFCs to Indicate Requirement + Levels. S. Bradner. IETF. March 1997. Best + Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
+
[TYPESCRIPT]
+
+ + TypeScript Language Specification. + Microsoft. 1 October 2012. URL: + https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md +
+
[URL]
+
+ URL + Standard. Anne van Kesteren. WHATWG. Living + Standard. URL: https://url.spec.whatwg.org/ +
+
[WEBAPPSEC]
+
+ + Secure Contexts. W3C. 17 July 2015. URL: + https://w3c.github.io/webappsec/specs/powerfulfeatures/ +
+
[WEBIDL]
+
+ Web + IDL. Cameron McCormack; Boris Zbarsky; Tobie + Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: + https://heycam.github.io/webidl/ +
+
[WOT-ARCHITECTURE]
+
+ + Web of Things Architecture. W3C. 14 September 2017. URL: + https://www.w3.org/TR/2017/WD-wot-architecture-20170914/ +
+
+
+
+

D.2 Informative references

+
+
[WOT-TD]
+
+ + WoT Thing Description . W3C. 20 August 2017. URL: + + https://www.w3.org/TR/2018/WD-wot-thing-description-20180405/ +
+
+
+
+ + + + diff --git a/releases/wd2/diff.html b/releases/wd2/diff.html new file mode 100644 index 00000000..168ffb23 --- /dev/null +++ b/releases/wd2/diff.html @@ -0,0 +1,15059 @@ + + + + + + + + + + + + +Web of Things (WoT) Scripting API + + + + + + + + + + + +"false"> + +
+ +

+Web +of +Things +(WoT) +Scripting +API +

+

+ +W3C + +First +Public + +Working +Draft +14 +September +2017 + + +

+
+
+This +version: +
+
+https://www.w3.org/TR/2017/WD-wot-scripting-api-20170914/ + + +https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ + + +
+
+Latest +published +version: +
+
+ +https://www.w3.org/TR/wot-scripting-api/ + +
+
+Latest +editor's +draft: +
+
+ +https://w3c.github.io/wot-scripting-api/ + +
+
+Previous +version: +
+https://www.w3.org/TR/2017/WD-wot-scripting-api-20170914/ +
+Editors: +
+
+ +Zoltan +Kis +, + + +( + + +Intel + +) + +
+
+ +Kazuaki +Nimura +, + + +( + + +Fujitsu +Ltd. + +) + +
+
+ +Daniel +Peintner +, + + +( + + +Siemens +AG + +) +
+ +Johannes +Hund + +(Former +Editor, +when +at +Siemens +AG) + +
+
+Contributors: +
+
+ +In +the +GitHub +repository + +
+
+Repository: +
+
+ +We +are +on +GitHub + +
+
+ +File +a +bug + +
+
+ +
+
+
+

+Abstract +

+

+The + +Web +of +Things + +(WoT) +provides +layered +interoperability +between + +Things + +by +using +the + +WoT +Interface + +s. +

+

+This +specification +describes +a +programming +interface +representing +the + +WoT +Interface + +that +allows +scripts +run +on +a + +Thing + +to +discover +and +consume +(retrieve) +other + +Thing + +s +and +to +expose + +Things + +characterized +by +properties, + + +WoT +Interactions +, +i.e. + +Properties +, +Actions + +and + +Events +. +

+

+Scripting +is +an +optional +"convenience" +building +block +in +WoT +and +it +is +typically +used +in +gateways +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 +like + +Thing +Directory +. +

+
+
+

+Status +of +This +Document +

+

+ +This +section +describes +the +status +of +this +document +at +the +time +of +its +publication. +Other +documents +may +supersede +this +document. +A +list +of +current + +W3C + +publications +and +the +latest +revision +of +this +technical +report +can +be +found +in +the + + +W3C + +technical +reports +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. +

+
+
+ +Editor's +note + +: +The +W3C +WoT +WG +is +asking +for +feedback + +
+

+Please +contribute +to +this +draft +using +the + +GitHub +Issue + +feature +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 +a +First +Public + +Working +Draft. +This +document +is +intended +to +become +a + +W3C + +Recommendation. +Comments +regarding +this +document +are +welcome. +Please +send +them +to + +public-wot-wg@w3.org + +( + +subscribe +, + +archives + +). +

+

+Changes +from +the +previous +publication +can +be +found +in + +Appendix +A +. +A + +diff-marked +version + +of +this +document +is +also +available +for +comparison +purposes. +

+Publication +as +a +First +Public + +Working +Draft +does +not +imply +endorsement +by +the + +W3C + +Membership. +This +is +a +draft +document +and +may +be +updated, +replaced +or +obsoleted +by +other +documents +at +any +time. +It +is +inappropriate +to +cite +this +document +as +other +than +work +in +progress. +

+

+This +document +was +produced +by +a +group +operating +under +the +5 +February +2004 + + + +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 + +1 +March +2017 + +February +2018 + + +W3C + +Process +Document +. +

+
+ +
+

+ +1. + +Introduction +

+

+The +overall +WoT +concepts +are +described +in +the + +WoT +Architecture + +document. +The +Web +of +Things +is +made +of +entities +( + +Thing + +s) +that +can +describe +their +capabilities +in +a +machine-interpretable +format, +the + +Thing +Description + +(TD) +and +expose +these +capabilities +through +the + +WoT +Interface +. +Support +for +scripting +is +optional +for +WoT +devices. +

+

+By + +consuming +a +TD +, +a +client + +Thing + +creates +a +runtime +resource +model +that +allows +accessing +the +properties, + + +Properties +, +Actions + +and + +Events + +exposed +by +the +server + +Thing +. +

+

+Exposing +a + +Thing + +requires +defining +a + +Thing +Description + +(TD) + +and +instantiating +a +software +stack +needed +to +serve +requests +for +accessing +the +exposed +properties, + + +Properties +, +Actions + +and + +Events +. +This +specification +describes +how +to +expose +and +consume + +Thing + +s +by +a +script. +

+
+
+ +Note + +
+

+Typically +scripts +are +meant +to +be +used +on +devices +able +to +provide +resources +(with +a + +WoT +interface + +) +for +managing +(installing, +updating, +running) +scripts, +such +as +bridges +or +gateways +that +expose +and +control +simpler +devices +as +WoT + +Thing + +s. +

+
+
+
+ +Note +

+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. +

+

+For +an +introduction +on +how +scripts +could +be +used +in + +Web +of +Things +, +check +the + +Primer + +document. +For +some +background +on +API +design +decisions +check +the + +Rationale + +document. +

+
+
+

+ +2. + +Use +Cases +

+

+ +This +section +is +non-normative. + +

+

+The +following +scripting +use +cases +are +covered + +supported + +in +this +specification: +

+
+

+ +2.1 + +Discovery +

+

+2.2 + +Consuming +a +Thing +

+Consume + +
+
+

+ +2.3 + +Exposing + +a +thing. + +Thing +

+
+
+
+

+ +3. + +The + + +WoT + + +object +

+

+The +WoT +object +is +the +main + +API +entry +point +and +it +is +exposed +by +an +implementation +of +the + +WoT +Runtime +. +The + +WoT +object + +has +no +internal +state +and +provides + +does +not +expose +properties, +only + +methods +for +discovering, +consuming +and +exposing +a + +Thing +. +

+
+
+ +Note + +
+

+Browser +implementations + +SHOULD + +use +a +namespace +object +such +as + +wot +, +and + +Node.js + +-like +runtimes + +MAY + +provide +the +API +object +through +the + + +require() + + +or + + +import + + +mechanism. +

+
+
+
interface "idlInterfaceID"><a data-lt="WoT" href="#dom-wot" class=
+"internalDFN" data-link-type="dfn" data-for=
+""> {
+<span class="idlMethod" id="idl-def-wot-discover(filter)" data-idl=
+
+"idlInterfaceID">WoT {
+    "idlMethType"><a href="#dfn-observable" class="internalDFN"
+data-link-type="dfn">Observable<<a href="#dom-consumedthing"
+class="internalDFN" data-link-type=
+
+"idlMethType">Observable<
+"dfn">ConsumedThing> "idlMethName"><a data-lt="discover()|discover()|discover"
+data-lt-nodefault="" href="#dom-wot-discover()" class="internalDFN"
+data-link-type="dfn" data-for=
+"WoT">discover<a href="#dom-thingfilter"
+class="internalDFN" data-link-type=
+
+"idlMethName">discover(optional 
+"dfn">ThingFilter filter);
+<span class="idlMethod" id="idl-def-wot-consume(url)" data-idl=""
+data-title="consume" data-dfn-for="wot">    <span class=
+
+data-title="fetch" data-dfn-for="wot">    
+"idlMethType">"https://heycam.github.io/webidl/#idl-promise">Promise<<a href="#dom-consumedthing"
+
+"https://heycam.github.io/webidl/#idl-promise">Promise<
+class="internalDFN" data-link-type=
+"dfn">    <span class=
+"idlMethName"><a data-lt="consume()|consume()|consume"
+data-lt-nodefault="" href="#dom-wot-consume()" class="internalDFN"
+data-link-type="dfn" data-for="WoT">consume(<span class=
+
+"dfn">ThingDescription> fetch(
+"idlParam">USVString url);
+<span class="idlMethod" id="idl-def-wot-expose(init)" data-idl=""
+data-title="expose" data-dfn-for="wot">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<<a href="#dom-exposedthing"
+class="internalDFN" data-link-type=
+"dfn">     <span class=
+"idlMethName"><a data-lt="expose()|expose()|expose"
+data-lt-nodefault="" href="#dom-wot-expose()" class="internalDFN"
+data-link-type="dfn" data-for="WoT">expose(<span class=
+"idlParam"><a href="#dom-thinginit"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">init
+};
+
+data-title="consume" data-dfn-for="wot">    ConsumedThing             consume(ThingDescription td);
+
+data-title="produce" data-dfn-for="wot">    ExposedThing              produce(ThingModel model);
+};
+
+data-title="ThingDescription">typedef USVString ThingDescription;
+
+data-title="ThingModel">typedef (ThingTemplate or ThingDescription) 
+
+ThingModel
+
+;
+
+
+
+
+
+
+ +Editor's +note + +
+

+The +algorithms +for +the +WoT +methods +will +be +specified +later. + +later, +including +error +handling +and +security +considerations. + +

+
+
+

+ +3.1 + +The + + +discover() + + +method +

+

+Starts +the +discovery +process +that +will +provide + + + +ConsumedThing + + + +objects +that +match +the +optional +argument + + + +ThingFilter + + +. + +. +When +the +argument +is +not +provided, +starts +the +widest +discovery +the + +Thing +Description + +and + +Protocol +Bindings + +allow. + +allow +and +support. + +Returns +an + + +Observable + + +object +that +can +be +subscribed +to + +and +unsubscribed +to. + +from. + +

+
+

+ +3.1.1 + +The + + +DiscoveryMethod + +enumeration +


+"idl-def-discoverymethod" data-idl="" data-title=
+"DiscoveryMethod">typedef DOMString 
+
+DiscoveryMethod
+
+;
+

+DiscoveryMethod + +represents +the +discovery +type +to +be +used: +

  • +"any" + +does +not +provide +any +restriction +
  • +"local" + +for +discovering + +Thing + +s +defined +in +the +same +device +
  • +"nearby" + +for +discovering + +Thing + +s +nearby +the +device, +e.g. +by +Bluetooth +or +NFC +
  • +"directory" + +for +discovery +based +on +a +service +provided +by +a +directory +or +repository +of + +Thing + +s +
  • +"broadcast" + +for +an +open +ended +discovery +based +on +sending +a +request +to +a +broadcast +address +
  • +"other" + +for +a +proprietary +method +defined +by +the +solution. +

+3.1.2 + +The + + + +ThingFilter + + +dictionary +

+

+The + + +ThingFilter + + +dictionary +that +represents +the +constraints +for +discovering + +Thing + +s +as +key-value +pairs. +

+
+
"ThingFilter">dictionary <a data-lt=
+"ThingFilter" href="#dom-thingfilter" class="internalDFN"
+data-link-type="dfn" data-for=
+""> {
+
+"ThingFilter">dictionary ThingFilter {
+
+    "idlMemberType">(DiscoveryType or <a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="method"
+href="#dom-thingfilter-method" class="internalDFN" data-link-type=
+"dfn" data-for=
+"ThingFilter"> = <span class=
+
+"idlMemberType">DiscoveryMethod      method = 
+"idlMemberValue">"any";
+    "https://heycam.github.io/webidl/#idl-USVString">USVString<a data-lt="url"
+href="#dom-thingfilter-url" class="internalDFN" data-link-type=
+"dfn" data-for="ThingFilter">
+<span class="idlMember" id="idl-def-thingfilter-description"
+data-idl="" data-title="description" data-dfn-for=
+"thingfilter">    <span class=
+"idlMemberType">Dictionary                   <span class=
+"idlMemberName"><a data-lt="description" href=
+"#dom-thingfilter-description" class="internalDFN" data-link-type=
+"dfn" data-for=
+"ThingFilter">
+
+"https://heycam.github.io/webidl/#idl-USVString">USVString            url;
+
+data-title="query" data-dfn-for="thingfilter">    USVString            query;
+
+data-idl="" data-title="constraints" data-dfn-for=
+"thingfilter">    sequence<Dictionary> constraints;
+
+};
+
+
+
+

+The + + +method + + +property +represents +the +discovery +type +that +should +be +used +in +the +discovery +process. +The +possible +values +are +defined +by +the + + + +DiscoveryMethod + + + +enumeration +that +can +be +extended +by +string +values +defined +by +solutions +(with +no +guarantee +of +interoperability). +

+The +url +property +represents +additional +information +for +the +discovery +method, +such +as +the +URL +of +the +Thing +Directory +server +to +be +used. +The +description +property +represents +additional +information +for +the +discovery +method +in +the +form +of +a +set +of +key-value +pairs, +as +defined +in +the +Thing +Description +. + +
+
+ +Editor's +note + +
+

+The + + +DiscoveryMethod + + +enumeration +can +be +extended +by +the + +Thing +Description + +with +values +that +are +not +specified +here. +This +extensibility +of + + +DiscoveryMethod + + +by +proprietary +or +private +methods +is +a +working +assumption +until +consensus +is +formed +and +may +be +removed +later. +

+
+Editor's +note + +

+The + + +ThingFilter + +url + + + +property +represents +additional +information +for +the +discovery +method, +such +as +the +URL +of +the +target +entity +serving +the +discovery +request, +such +as +a + +Thing +Directory + + +dictionary +may +be +extended +later +with +further +attributes. + +or +a +Thing. + +

+3.1.2 + +

+The + + +DiscoveryMethod + +query + + + +enumeration +<span class="idlEnum" id= +"idl-def-discoverymethod" data-idl="" data-title= +"DiscoveryMethod">enum <a data-lt= +"DiscoveryMethod" href="#dom-discoverymethod" class="internalDFN" +data-link-type="dfn" data-for= +""> { + <a href="#dom-discoverymethod-any" class= +"idlEnumItem">"any", + <a href="#dom-discoverymethod-local" class= +"idlEnumItem">"local", + <a href="#dom-discoverymethod-nearby" class= +"idlEnumItem">"nearby", + <a href="#dom-discoverymethod-directory" class= +"idlEnumItem">"directory", + <a href="#dom-discoverymethod-broadcast" class= +"idlEnumItem">"broadcast", + <a href="#dom-discoverymethod-other" class= +"idlEnumItem">"other" +}; + +property +represents +a +query +string +accepted +by +the +implementation, +for +instance +a +SPARQL +query. +

+

+The + + +DiscoveryMethod + +constraints + + +enumeration + + +property + +represents +additional +information +for + +the +discovery +type + +method +in +the +form +of +a +list +of +sets +of +property-value +pairs +(dictionaries). +The +list +elements +(dictionaries) +are +in +OR +relationship, +and +within +a +constraint +dictionary +the +key-value +pairs +are +in +AND +relationship. +Implementations + +SHOULD + +make +the +following +mapping +from +the +constraint +dictionaries + +to +be +used: +" + + + +any + +SemanticAnnotations + + +" +does +not +provide +any +restriction + +: +for +each +property-value +pair +in +a +constraint +dictionary, +

    +
  • +" + +Each +property +name +in +the +constraint +dictionary + +SHOULD + +match +the +either +the + + +local + +name + + +" +for +discovering +Thing +s + +property +of +a + +defined +in +the +same +device +" + + + +nearby + +SemanticType + + +" +for +discovering +Thing + + +s +nearby + +on + +the +device, +e.g. +by +Bluetooth + +target + +Thing + +object, + +or +NFC + +the +name +of +a + +Property + +on +the +target + +Thing +. +
  • +
  • +" + +When +the +name +matches, +the +values +are +compared. +If +the +values +match, +the +constraint +is +matched. +
+Editor's +note +

+Constraints +are +experimental +feature, +implementations +are +not +required +to +support +them. +

+Editor's +note +

+Semantic +annotations +need +revisiting +in +order +to +simplify +their +representation. +In +the +[ + +WOT-TD + + +] +specification +they +represent +the + + +directory + +@type + +construct. +At +the +moment +only + +@context +, +@type + +and + +@id + + +constructs +are +used +in +the + +TD +.

+" +for +discovery +based +on +a +service +provided +by +a +directory +or +repository +of +Thing +s +" + + +3.2 + +The + + +broadcast + +fetch() + + + +" +for + +method +

+Accepts + +an +open +ended +discovery +based +on +sending + + +url + +argument +and +returns + +a +request +to + + + +Promise + +that +resolves +with + +a +broadcast +address +" + + + +other + +ThingDescription +.

+3.3 + +The + +ThingDescription + + + +" +for +a +proprietary +method +defined +by + +type +

+Representation +of + +the +solution. + + +Thing +Description +, +standardized +in +the + +Wot +Things +Description + +specification. +

+Note +

+In +this +version +of +the +API, + +Thing +Description + +s +are +represented +as +opaque +strings, +denoting +a +serialized +form, +for +instance +JSON +or +JSON-LD. +See + +Issue +38 + +and + +Issue +45 +.

+
+
+

+ +3.2 + +3.4 + + +The + + +consume() + + +method +

+

+Accepts +an + +url + +td + + +argument +and +returns +a + +of +type + + +Promise + + + +ThingDescription + + + +of + +and +returns + +a + + +ConsumedThing + +. + + +object +instantiated +based +on +that +description. + +

+
+
+

+ +3.3 + +3.5 + + +The + + +expose() + +produce() + + + +method +

+

+Returns + +Accepts + +a + +model + +argument +of +type + +ThingModel + +Promise + + + +of +a +locally +created + +and +returns +an + + +ExposedThing + + +object, +locally +created + +based +on +the +provided +initialization +parameters. +Editor's +note +The +reason + +An + + +ExposedThing + + +s +are + +can +be + +created +by + +in +the +following +ways: +

  1. +from +an +initial +model +(including + +a +factory +method +instead + +user +given +name +and + +semantic +annotations + +), +then +adding +properties, +actions, +events +and +request +handlers; +
  2. +from +a + +Thing +Description + +(possibly + +of +a +constructor + + + +ConsumedThing + +object), +then +adding +request +handlers. +

+3.6 + +The + +ThingModel + +type +

+A +Thing +model + +is +that +an + +used +for +producing +a +new + + +ExposedThing + + +may + +and +can + +be +created +in +the +local +WoT +Runtime + +either +a + +ThingTemplate +, +or +in + +a +remote +runtime. +Even +though +currently +only +local +creation +is +supported, +the +method +is +designed +with +this +possible +future +compatibility +in +mind. + + + +ThingDescription +. +

+
+
+

+ +3.3.1 + +3.7 + + +The + + +ThingInit + +SemanticAnnotations + + + +dictionary +

+

+A +dictionary +that +provides +the +semantic +types +and +semantic +metadata. +

+
+
"idl-def-thinginit" data-idl="" data-title=
+"ThingInit">dictionary <a data-lt=
+"ThingInit" href="#dom-thinginit" class="internalDFN"
+data-link-type="dfn" data-for=
+""> {
+<span class="idlMember" id="idl-def-thinginit-name" data-idl=""
+data-title="name" data-dfn-for="thinginit">    <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name"
+href="#dom-thinginit-name" class="internalDFN" data-link-type="dfn"
+data-for="ThingInit">
+<span class="idlMember" id="idl-def-thinginit-url" data-idl=""
+data-title="url" data-dfn-for="thinginit">    <span class=
+
+"idl-def-semanticannotations" data-idl="" data-title=
+"SemanticAnnotations">dictionary SemanticAnnotations {
+
+"idl-def-semanticannotations-semantictype" data-idl="" data-title=
+"semanticType" data-dfn-for="semanticannotations">    
+"idlMemberType">"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-lt="url"
+href="#dom-thinginit-url" class="internalDFN" data-link-type="dfn"
+data-for="ThingInit">
+<span class="idlMember" id="idl-def-thinginit-description"
+data-idl="" data-title="description" data-dfn-for=
+"thinginit">    <span class=
+"idlMemberType">Dictionary <span class=
+"idlMemberName"><a data-lt="description" href=
+"#dom-thinginit-description" class="internalDFN" data-link-type=
+"dfn" data-for=
+"ThingInit">
+
+"https://heycam.github.io/webidl/#idl-sequence">sequence<SemanticType>     semanticType;
+
+data-idl="" data-title="metadata" data-dfn-for=
+"semanticannotations">    sequence<SemanticMetadata> metadata;
+
+};
+
+
+
+

+The + + +ThingInit + +semanticType + +property +denotes +a +list +of + +SemanticType + +objects +that +define +the +semantic +types +that +can +be +used +in +semantic +metadata +type-value +pairs. +

+The + +metadata + +property +denotes +a +list +of + +SemanticMetadata + + + +objects +(type-value +pairs). +

+3.8 + +The + +SemanticType + +dictionary +contains +properties +to +initialize + +

+
+
"idl-def-semantictype" data-idl="" data-title=
+"SemanticType">dictionary SemanticType {
+
+data-title="name" data-dfn-for=
+"semantictype">    required DOMString name;
+
+"" data-title="context" data-dfn-for=
+"semantictype">    required USVString context;
+
+"" data-title="prefix" data-dfn-for=
+"semantictype">             DOMString prefix;
+};
+

+Represents + +a +Thing +: + +semantic +type +annotation, +containing +a +name, +a +context +and +a +prefix. + +

+
+Editor's +note +

+Semantic +type +examples +to +be +added. +

+3.9 + +The + +SemanticMetadata + +dictionary +


+"idl-def-semanticmetadata" data-idl="" data-title=
+"SemanticMetadata">dictionary SemanticMetadata {
+
+data-idl="" data-title="type" data-dfn-for=
+"semanticmetadata">    SemanticType type;
+
+data-idl="" data-title="value" data-dfn-for=
+"semanticmetadata">    any          value;
+};
+

+The + +SemanticMetadata + +dictionary +describes +a +pair +of +semantic +type +and +value: +

+3.10 + +The + +ThingTemplate + +dictionary +

+A +Thing +Template +is +a +dictionary +that +provides +a +user +given +name, +and +the +semantic +types +and +semantic +metadata +attached +to +the + +ExposedThing + +Thing +Description + +'s +root +level. +


+"idl-def-thingtemplate" data-idl="" data-title=
+"ThingTemplate">dictionary ThingTemplate : SemanticAnnotations {
+
+data-title="name" data-dfn-for=
+"thingtemplate">    required DOMString name;
+};
+

+The + +ThingTemplate + +dictionary +extends + +SemanticAnnotations + +and +contains +properties +to +initialize +a + +Thing +:

+
+
+ +Editor's +note +

+Support +for +configuration +and +security +data +might +be +added +later. +

+
+
+

+ +3.4 + +3.11 + + +Examples +

+
+
+ +Example +1 + +: +Discover +Things +via +directory + +
+<span class= +"hljs-keyword">let }; + +
"hljs-keyword">let discoveryFilter = {
+  method: 
+"hljs-string">"directory",
+  url: 
+"hljs-string">"http://directory.wotservice.org"
+};
+
+"hljs-keyword">let subscription = wot.discover(discoveryType).subscribe(
+
+"hljs-keyword">let subscription = wot.discover(discoveryFilter).subscribe(
+
+  thing => { console.log("hljs-string">"Found Thing " + thing.url); },
+
+"hljs-string">"Found Thing " + thing.name); },
+
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout(
+  <span class=
+"hljs-params">()); },
+
+setTimeout( () => {
+    subscription.unsubscribe();
+    console.log(
+"hljs-string">"Discovery timeout");
+  },
+
+
+5000
+
+);
+
+
+
+
+ +Note + +
+

+Note +that +canceling +a +discovery +(through +unsubscribe) + + +unsubscribe() + +) + +may +not +be +successful +in +all +cases, +for +instance +when +discovery +is +based +on +open +ended +broadcast +requests. +However, +once + +unsubscribe() + +has +been +called, +implementations + +MUST + +suppress +further +event +handling +( +i.e. +further +discoveries +and +errors) +on +the +Observable. +Also, +a +discovery +error +may +not +mean +the +end +of +the +discovery +process. +However, +in +order +to +respect +Observable +semantics +(error +always +terminates +processing), +implementations + +MUST + +close +or +suppress +further +event +handling +on +the +Observable. +

+
+
+
+ +Example +2 + +: +Discover +Things +exposed +by +local +hardware + +
+<span class= + +
let subscription = wot.discover({ method: "local" }).subscribe(
+  thing => { console.log("hljs-string">"Found local Thing " + thing.url); },
+
+"hljs-string">"Found local Thing " + thing.name); },
+
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +Example +3 + +: +Same +as +above +but +with +different +Observable +syntax +

+"hljs-keyword">let subscription = wot.discover({ method: "local" }).subscribe({
+  thing => { console.log("Found local Thing " + thing.name); },
+  error: 
+"hljs-function">err => { console.log("Discovery error: " + err.message); },
+  complete: 
+"hljs-function">() => { console.log("Discovery finished successfully");}
+});
+
+Example +4 +: +Discover +Things +exposed +nearby, +e.g. + +via +Bluetooth +or +NFC + + +
+<span class= +"hljs-keyword">let} }).subscribe( + +
"hljs-keyword">let subscription = wot.discover({
+  method: 
+"hljs-string">"nearby",
+  constraints: [{ 
+"hljs-attr">protocol: "BLE-4.2" }, { protocol: "NFC"}]
+}).subscribe(
+
+  thing => { console.log("hljs-string">"Found nearby Thing " + thing.url); },
+
+"hljs-string">"Found nearby Thing " + thing.name); },
+
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +Example +4 + +5 + + +: +Discover +Things +exposed +in +a +proprietary +way + +
+<span class= +"hljs-keyword">let} }).subscribe( + +
"hljs-keyword">let subscription = wot.discover({
+  method: 
+"hljs-string">"other",
+  constraints: [{ 
+"hljs-attr">solution: "XYZ123", key: "..."}]
+}).subscribe(
+
+  thing => { console.log("hljs-string">"Found Thing " + thing.url); },
+
+"hljs-string">"Found Thing " + thing.name); },
+
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+
+

+ +4. + +The + + +ConsumedThing + + +interface +

+

+The + + +ConsumedThing + + +interface +is +a +client +API +for +sending +requests +to +servers +in +order +to +retrieve +or +update +properties, + + +Properties +, +invoke + +Actions +, +and +observe +properties, +Actions + + +Properties + + +and + +Events +. +

+
+
"ConsumedThing">interface <a data-lt=
+"ConsumedThing" href="#dom-consumedthing" class="internalDFN"
+data-link-type="dfn" data-for=
+""> {
+
+"ConsumedThing">interface ConsumedThing {
+
+    readonly attribute "https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name"
+href="#dom-consumedthing-name" class="internalDFN" data-link-type=
+"dfn" data-for="ConsumedThing">
+<span class="idlAttribute" id="idl-def-consumedthing-url" data-idl=
+"" data-title="url" data-dfn-for=
+"consumedthing">    readonly attribute <span class=
+"idlAttrType"><a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-lt="url"
+href="#dom-consumedthing-url" class="internalDFN" data-link-type=
+"dfn" data-for="ConsumedThing">
+<span class="idlAttribute" id="idl-def-consumedthing-description"
+data-idl="" data-title="description" data-dfn-for=
+"consumedthing">    readonly attribute <span class=
+"idlAttrType"><a href="#dom-thingdescription" class="internalDFN"
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name;
+
+"idl-def-consumedthing-getthingdescription" data-idl="" data-title=
+"getThingDescription" data-dfn-for="consumedthing">    
+data-link-type=
+"dfn">ThingDescription "idlAttrName"><a data-lt="description" href=
+"#dom-consumedthing-description" class="internalDFN"
+data-link-type="dfn" data-for=
+"ConsumedThing">
+<span class="idlMethod" id=
+"idl-def-consumedthing-invokeaction(name,parameters)" data-idl=""
+data-title="invokeAction" data-dfn-for=
+"consumedthing">    <a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="invokeAction()|invokeaction()|invokeAction"
+data-lt-nodefault="" href="#dom-consumedthing-invokeaction()"
+class="internalDFN" data-link-type="dfn" data-for=
+"ConsumedThing">invokeAction(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-setproperty(name,value)" data-idl=""
+data-title="setProperty" data-dfn-for=
+"consumedthing">    <a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="setProperty()|setproperty()|setProperty"
+data-lt-nodefault="" href="#dom-consumedthing-setproperty()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ConsumedThing">setProperty(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+
+"idlMethName">getThingDescription();
+
+"idl-def-consumedthing-getproperty(name)" data-idl="" data-title=
+"getProperty" data-dfn-for="consumedthing">    <span class=
+
+"idl-def-consumedthing-readproperty-name" data-idl="" data-title=
+"readProperty" data-dfn-for="consumedthing">    
+"idlMethType">"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="getProperty()|getproperty()|getProperty"
+data-lt-nodefault="" href="#dom-consumedthing-getproperty()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ConsumedThing">getProperty(<span class=
+
+"https://heycam.github.io/webidl/#idl-promise">Promise<any>     readProperty(
+"idlParam">DOMString name);
+"idl-def-consumedthing-addlistener(eventname,listener)" data-idl=""
+data-title="addListener" data-dfn-for=
+
+"idl-def-consumedthing-writeproperty-name-value" data-idl=""
+data-title="writeProperty" data-dfn-for=
+
+"consumedthing">    "#dom-consumedthing" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMethName"><a data-lt="addListener()|addlistener()|addListener"
+data-lt-nodefault="" href="#dom-consumedthing-addlistener()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ConsumedThing">addListener(<span class=
+
+"https://heycam.github.io/webidl/#idl-promise">Promise<void>    writeProperty(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a href="#dom-thingeventlistener"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">listener
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, any value);
+
+"idl-def-consumedthing-removelistener(eventname,listener)"
+data-idl="" data-title="removeListener" data-dfn-for=
+
+"idl-def-consumedthing-invokeaction-name-parameters" data-idl=""
+data-title="invokeAction" data-dfn-for=
+
+"consumedthing">    "#dom-consumedthing" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMethName"><a data-lt=
+"removeListener()|removelistener()|removeListener"
+data-lt-nodefault="" href="#dom-consumedthing-removelistener()"
+class="internalDFN" data-link-type="dfn" data-for=
+"ConsumedThing">removeListener(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString,
+                                 <span class=
+
+"https://heycam.github.io/webidl/#idl-promise">Promise<any>     invokeAction(
+"idlParam">"#dom-thingeventlistener" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">listener
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, any parameters);
+
+"idl-def-consumedthing-removealllisteners(eventname)" data-idl=""
+data-title="removeAllListeners" data-dfn-for=
+
+"idl-def-consumedthing-onpropertychange-name" data-idl=""
+data-title="onPropertyChange" data-dfn-for=
+
+"consumedthing">    "#dom-consumedthing" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMethName"><a data-lt=
+"removeAllListeners()|removealllisteners()|removeAllListeners"
+data-lt-nodefault="" href="#dom-consumedthing-removealllisteners()"
+class="internalDFN" data-link-type="dfn" data-for=
+"ConsumedThing">removeAllListeners(<span class=
+"idlParam">optional <a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-observe(name,requesttype)" data-idl=""
+data-title="observe" data-dfn-for="consumedthing">    <span class=
+"idlMethType"><a href="#dfn-observable" class="internalDFN"
+data-link-type="dfn">Observable    <span class=
+"idlMethName"><a data-lt="observe()|observe()|observe"
+data-lt-nodefault="" href="#dom-consumedthing-observe()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ConsumedThing">observe(<span class=
+
+"#dom-observable" class="internalDFN" data-link-type=
+"dfn">Observable       onPropertyChange(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a href="#dom-requesttype"
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name);
+
+data-idl="" data-title="onEvent" data-dfn-for=
+"consumedthing">    Observable       
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">requestType
+};
+<span class="idlCallback" id="idl-def-thingeventlistener" data-idl=
+"" data-title="ThingEventListener">callback <span class=
+"idlCallbackID"><a data-lt="ThingEventListener" href=
+"#dom-thingeventlistener" class="internalDFN" data-link-type="dfn"
+data-for=
+""> = <span class=
+"idlCallbackType">void<span class=
+"idlParamType"><a href="#dfn-event" class="internalDFN"
+data-link-type="dfn">Event <span class=
+"idlParamName">
+event
+);
+
+"dfn">onEvent(DOMString name);
+
+data-idl="" data-title="onTDChange" data-dfn-for=
+"consumedthing">    Observable       onTDChange();
+};
+
+
+
+
+

+Represents + + +ConsumedThing + +represents + +a +local +proxy +object +of +the +remote + +Thing +. +

+
+

+ +4.1 + +The + + +name + + +read-only +attribute +represents +the +name +of +the +Thing +. + +property +

+The + +url + +name + + +read-only +attribute + +property + +represents +the +URL + +name + +of +the + +Thing + +as +specified +in +the + +TD + +. +In +this +version +it +is +read +only. +

+4.2 + +The + + +description + +getThingDescription() + + + +attribute +read-only +attribute +represents + +method +

+Returns + +the +description + + +Thing +Description + +of +the + +Thing +. +

+
+
+ +Editor's +note + +
+

+In +this +version, +introspection +based +on + +TD + +is +out +of +scope. + +Parsing +and +exposing + +Thing +Description + +s +is +discussed +in + +Issue +38 +. +

+
+
+
+

+ +4.1 + +4.3 + + +The + + +invokeAction() + +readProperty() + + + +method +

+

+Takes +the +Action + + +Property + + +name +from + +as + +the + +name + +argument +and +the +list +of +parameters, + +argument, + +then +requests +from +the +underlying +platform +and +the + +Protocol +Bindings + +to +invoke + +retrieve + +the +Action + + +Property + + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + + +Promise + + +that +resolves +with +the +return + + +Property + +value +or +rejects +with +an + +Error +. +

+
+
+

+ +4.2 + +4.4 + + +The + + +setProperty() + +writeProperty() + + + +method +

+

+Takes +the + +Property + +name +as +the + +name + +argument +and +the +new +value +as +the + +value + +argument, +then +requests +from +the +underlying +platform +and +the + +Protocol +Bindings + +to +update +the + +Property + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + + +Promise + + +that +resolves +on +success +or +rejects +with +an + +Error +. +

+
+
+

+ +4.3 + +4.5 + + +The + + +getProperty() + +invokeAction() + + + +method +

+

+Takes +the +Property + + +Action + + +name +as + +from + +the + +name + +argument, + +argument +and +the +list +of +parameters, + +then +requests +from +the +underlying +platform +and +the + +Protocol +Bindings + +to +retrieve + +invoke + +the +Property + + +Action + + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + + +Promise + + +that +resolves +with +the +Property + +return + +value +or +rejects +with +an + +Error +. +

+
+
+

+ +4.4 + +4.6 + + +The + + +addListener() + +onPropertyChange() + + + +method +

+

+Adds +the +listener +provided +in +the +argument +listener +to +the +Event +name +provided +in +the +argument +eventName +. +4.5 +The + +Returns +an + + +removeListener() + +Observable + + +method +Removes +a +listener +from + + +for + +the +Event + + +Property + + +identified +by + +specified +in + +the +provided + + +eventName + +name + + +argument, +allowing +subscribing +to + +and +listener +argument. + +unsubscribing +from +notifications. + +

+4.6 + +

+The +callback +function +passed +to +the + + +removeAllListeners() + +subscribe() + + +method +Removes +all +listeners +for + +when +invoked +on + +the +Event +provided +by + +returned +observer +will +receive + +the +eventName +optional +argument, +or +if +that +was +not +provided, +then +removes +all +listeners +from +all +Events +. + +new +property +value +each +time +it +is +changed. + +

+
+
+

+ +4.7 + +The + + +observe() + +onEvent() + + + +method +

+

+Returns +an + + +Observable + + +for +the +Property +, + + +Event + +or +Action + +specified +in +the + +name + +argument, +allowing +subscribing +to + +and +unsubscribing +to + +from + +notifications. +The +requestType +specifies +whether +a +Property +, +an +Event +or +an +Action +is +observed. +Editor's +note +The +observe() +method +could +replace +addListener() +and +removeListener() +, +though +they +could +be +kept +for +convenience. + +

+4.8 + +

+The +ThingEventListener + +callback +A + +function +called +with +an +Event +object +when +an +event +is +emitted. +4.9 +Events +Clients +can +subscribe + +passed + +to +the +Events +defined +in +ExposedThing +events +. +The +event +types +are +described +in +this +section. +4.9.1 +The +PropertyChangeEvent +interface +<span class="idlInterface" id= +"idl-def-propertychangeevent" data-idl="" data-title= +"PropertyChangeEvent">[<span class= +"extAttrName"><a href= +"https://heycam.github.io/webidl/#Constructor">Constructor<a href="#dom-propertychangeeventinit" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">init] +interface <a data-lt= +"PropertyChangeEvent" href="#dom-propertychangeevent" class= +"internalDFN" data-link-type="dfn" data-for= +""> : <span class= +"idlSuperclass"><a href="#dfn-event" class="internalDFN" +data-link-type="dfn">Event { +<span class="idlAttribute" id="idl-def-propertychangeevent-data" +data-idl="" data-title="data" data-dfn-for= +"propertychangeevent"> readonly attribute <span class= +"idlAttrType"><a href="#dom-propertychangeeventinit" class= +"internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-lt="data" href= +"#dom-propertychangeevent-data" class="internalDFN" data-link-type= +"dfn" data-for= +"PropertyChangeEvent"> +}; +The +data +attribute +represents +the +changed +Property +. +4.9.1.1 +The +PropertyChangeEventInit +dictionary +<span class="idlDictionary" id= +"idl-def-propertychangeeventinit" data-idl="" data-title= +"PropertyChangeEventInit">dictionary <span class= +"idlDictionaryID"><a data-lt="PropertyChangeEventInit" href= +"#dom-propertychangeeventinit" class="internalDFN" data-link-type= +"dfn" data-for=""> { +<span class="idlMember" id="idl-def-propertychangeeventinit-name" +data-idl="" data-title="name" data-dfn-for= +"propertychangeeventinit"> <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name" +href="#dom-propertychangeeventinit-name" class="internalDFN" +data-link-type="dfn" data-for= +"PropertyChangeEventInit"> +<span class="idlMember" id="idl-def-propertychangeeventinit-value" +data-idl="" data-title="value" data-dfn-for= +"propertychangeeventinit"> <a href= +"https://heycam.github.io/webidl/#idl-any">any<a data-lt="value" +href="#dom-propertychangeeventinit-value" class="internalDFN" +data-link-type="dfn" data-for= +"PropertyChangeEventInit"> +}; +The + + +name +> +attribute +represents +the +Property +name. +The +value + +subscribe() + + +attribute +represents +the +new +value +of + +method +when +invoked +on + +the +Property +. +4.9.2 +The +ActionInvocationEvent +interface +<span class="idlInterface" id= +"idl-def-actioninvocationevent" data-idl="" data-title= +"ActionInvocationEvent">[<span class= +"extAttrName"><a href= +"https://heycam.github.io/webidl/#Constructor">Constructor<a href="#dom-actioninvocationeventinit" +class="internalDFN" data-link-type= +"dfn">] +interface <a data-lt= +"ActionInvocationEvent" href="#dom-actioninvocationevent" class= +"internalDFN" data-link-type="dfn" data-for= +""> : <span class= +"idlSuperclass"><a href="#dfn-event" class="internalDFN" +data-link-type="dfn">Event { +<span class="idlAttribute" id="idl-def-actioninvocationevent-data" +data-idl="" data-title="data" data-dfn-for= +"actioninvocationevent"> readonly attribute <span class= +"idlAttrType"><a href="#dom-actioninvocationeventinit" class= +"internalDFN" data-link-type= +"dfn"><a data-lt="data" +href="#dom-actioninvocationevent-data" class="internalDFN" +data-link-type="dfn" data-for= +"ActionInvocationEvent"> +}; +The +data +attribute +represents + +returned +observer +will +receive + +the +notification + +event + +data +from +the +Action +invocation. +4.9.2.1 +The +ActionInvocationEventInit +dictionary +<span class="idlDictionary" id= +"idl-def-actioninvocationeventinit" data-idl="" data-title= +"ActionInvocationEventInit">dictionary <span class= +"idlDictionaryID"><a data-lt="ActionInvocationEventInit" href= +"#dom-actioninvocationeventinit" class="internalDFN" +data-link-type="dfn" data-for= +""> { +<span class="idlMember" id= +"idl-def-actioninvocationeventinit-actionname" data-idl="" +data-title="actionName" data-dfn-for= +"actioninvocationeventinit"> <span class= +"idlMemberType"><a data-lt="actionName" +href="#dom-actioninvocationeventinit-actionname" class= +"internalDFN" data-link-type="dfn" data-for= +"ActionInvocationEventInit"> +<span class="idlMember" id= +"idl-def-actioninvocationeventinit-returnvalue" data-idl="" +data-title="returnValue" data-dfn-for= +"actioninvocationeventinit"> <span class= +"idlMemberType"><a data-lt="returnValue" +href="#dom-actioninvocationeventinit-returnvalue" class= +"internalDFN" data-link-type="dfn" data-for= +"ActionInvocationEventInit"> +}; +Editor's +note +Action +parameters +could +be +also +included, +but +it's +debatable +because +privacy +reasons. +The +actionName +attribute +represents +the +name +of +the +Action +that +has +been +invoked. +The +returnValue +attribute +represents +the +return +value +of + +each +time + +the +Action +. + +event +is +fired. + +

+
+
+

+ +4.9.3 + +4.8 + + +The + + +ThingDescriptionChangeEvent + +onTDChange() + + + +interface +<span class="idlInterface" id= +"idl-def-thingdescriptionchangeevent" data-idl="" data-title= +"ThingDescriptionChangeEvent">[<span class= +"extAttrName"><a href= +"https://heycam.github.io/webidl/#Constructor">Constructor<a href="#dom-thingdescriptionchangeeventinit" +class="internalDFN" data-link-type= +"dfn">] +interface <a data-lt= +"ThingDescriptionChangeEvent" href= +"#dom-thingdescriptionchangeevent" class="internalDFN" +data-link-type="dfn" data-for= +""><a href="#dfn-event" +class="internalDFN" data-link-type="dfn">Event { +<span class="idlAttribute" id= +"idl-def-thingdescriptionchangeevent-data" data-idl="" data-title= +"data" data-dfn-for= +"thingdescriptionchangeevent"> readonly attribute <span class= +"idlAttrType"><a href="#dom-thingdescriptionchangeeventinit" class= +"internalDFN" data-link-type= +"dfn"><a data-lt="data" +href="#dom-thingdescriptionchangeevent-data" class="internalDFN" +data-link-type="dfn" data-for= +"ThingDescriptionChangeEvent"> +}; + +method +

+

+The + +Returns +an + + +data + +Observable + + +attribute +represents +the +changes +that +occurred + +, +allowing +subscribing +to +and +unsubscribing +from +notifications + +to +the + +Thing +Description +. +

+4.9.3.1 +The +ThingDescriptionChangeEventInit +dictionary +<span class="idlDictionary" id= +"idl-def-thingdescriptionchangeeventinit" data-idl="" data-title= +"ThingDescriptionChangeEventInit">dictionary <span class= +"idlDictionaryID"><a data-lt="ThingDescriptionChangeEventInit" +href="#dom-thingdescriptionchangeeventinit" class="internalDFN" +data-link-type="dfn" data-for= +""> { +<span class="idlMember" id= +"idl-def-thingdescriptionchangeeventinit-type" data-idl="" +data-title="type" data-dfn-for= +"thingdescriptionchangeeventinit"> <span class= +"idlMemberType"><a href="#dom-tdchangetype" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-lt="type" href= +"#dom-thingdescriptionchangeeventinit-type" class="internalDFN" +data-link-type="dfn" data-for= +"ThingDescriptionChangeEventInit"> +<span class="idlMember" id= +"idl-def-thingdescriptionchangeeventinit-method" data-idl="" +data-title="method" data-dfn-for= +"thingdescriptionchangeeventinit"> <span class= +"idlMemberType"><a href="#dom-tdchangemethod" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-lt="method" href= +"#dom-thingdescriptionchangeeventinit-method" class="internalDFN" +data-link-type="dfn" data-for= +"ThingDescriptionChangeEventInit"> +<span class="idlMember" id= +"idl-def-thingdescriptionchangeeventinit-name" data-idl="" +data-title="name" data-dfn-for= +"thingdescriptionchangeeventinit"> <span class= +"idlMemberType"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name" +href="#dom-thingdescriptionchangeeventinit-name" class= +"internalDFN" data-link-type="dfn" data-for= +"ThingDescriptionChangeEventInit"> +<span class="idlMember" id= +"idl-def-thingdescriptionchangeeventinit-data" data-idl="" +data-title="data" data-dfn-for= +"thingdescriptionchangeeventinit"> <span class= +"idlMemberType"><a href="#dom-tdchangedata" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-lt="data" href= +"#dom-thingdescriptionchangeeventinit-data" class="internalDFN" +data-link-type="dfn" data-for= +"ThingDescriptionChangeEventInit"> +<span class="idlMember" id= +"idl-def-thingdescriptionchangeeventinit-description" data-idl="" +data-title="description" data-dfn-for= +"thingdescriptionchangeeventinit"> <span class= +"idlMemberType"><a href="#dom-thingdescription" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-lt="description" href= +"#dom-thingdescriptionchangeeventinit-description" class= +"internalDFN" data-link-type="dfn" data-for= +"ThingDescriptionChangeEventInit"> +}; +The +type +attribute +represents +the +change +type, +whether +has +it +been +applied +on +properties, +Actions +or +Events +. +The +method +attribute +tells +what +operation +has +been +applied, +addition, +removal +or +change. +The +name +attribute +represents +the +name +of +the +Property +, +Action +or +event +that +has +changed. +The +description +attribute +is +defined +for +the +addition +and +change +methods, +and +represents +the +new +description. +The +data +attribute +provides +the +initialization +data +for +the +added +or +changed +elements. +4.9.3.1.1 +The +TDChangeMethod +enumeration +<span class="idlEnum" id= +"idl-def-tdchangemethod" data-idl="" data-title= +"TDChangeMethod">enum <a data-lt= +"TDChangeMethod" href="#dom-tdchangemethod" class="internalDFN" +data-link-type="dfn" data-for= +""> { + <a href="#dom-tdchangemethod-add" class= +"idlEnumItem">"add", + <a href="#dom-tdchangemethod-remove" class= +"idlEnumItem">"remove", + <a href="#dom-tdchangemethod-change" class= +"idlEnumItem">"change" +}; +The +add +value +denotes +addition +of +a +Property +, +Action +or +event. +The +remove +value +denotes +removal +of +a +Property +, +Action +or +event. +The +change +value +denotes +a +change +applied +on +a +Property +, +Action +or +event. +4.9.3.1.2 +The +TDChangeType +enumeration +<span class="idlEnum" id= +"idl-def-tdchangetype" data-idl="" data-title= +"TDChangeType">enum <a data-lt= +"TDChangeType" href="#dom-tdchangetype" class="internalDFN" +data-link-type="dfn" data-for= +""> { + <a href="#dom-tdchangetype-property" class= +"idlEnumItem">"property", + <a href="#dom-tdchangetype-action" class= +"idlEnumItem">"action", + <a href="#dom-tdchangetype-event" class= +"idlEnumItem">"event" +}; +<span class="idlTypedef" id="idl-def-tdchangedata" data-idl="" +data-title="TDChangeData">typedef <span class= +"idlTypedefType">(<a href="#dom-thingpropertyinit" class= +"internalDFN" data-link-type= +"dfn"> or <a href= +"#dom-thingactioninit" class="internalDFN" data-link-type= +"dfn"> or <a href= +"#dom-thingeventinit" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlTypedefID"><a data-lt="TDChangeData" href="#dom-tdchangedata" +class="internalDFN" data-link-type="dfn" data-for= +""> +TDChangeData +; + +

+The +property +value +tells + +callback +function +passed +to + +the +operation +was +applied +on +a +Property +definition. +The + + +action + +subscribe() + + +value +tells +the +operation +was +applied + +method +when +invoked + +on +a +action +definition. +The +event +value +tells + +the +operation +was +applied +on +an +event +definition. +4.9.3.1.3 +The +TDChangeData +type +Represents + +returned +observer +will +receive + +the +new +description +of +the +changed +element. +Depending +on +the +change +type, + + +Thing +Description + +each +time + +it +can +be +either +a +ThingPropertyInit +, +ThingActionInit +, +or +ThingEventInit +. + +is +changed. + +

+
+
+

+ +4.10 + +4.9 + + +Examples +

+

+Below +a + + + +ConsumedThing + + + +interface +example +is +given. +

+
+
+ +Example +5 + +6 + + +: +Consume +a +Thing + +
+wot.consume(<span class= +"hljs-string">"http://mmyservice.org/mySensor" { + .log(<span class= +"hljs-string">"Thing " + thing.name + <span class= +"hljs-string">" has been consumed."); + .log(<span class= +"hljs-string">"{ " + <span class= +"hljs-built_in">JSON.serialize(thing) + <span class= +"hljs-string">" }"); + thing.addListener(<span class= +"hljs-string">"onchange", <span class= +"hljs-function"><span class= +"hljs-keyword">function(<span class= +"hljs-params">event{ + (event <span class= +"hljs-keyword">instanceof PropertyChangeEvent) { + <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Property " + event.name + <span class= +"hljs-string">" value has changed to " + event.value); + } + }).invokeAction(<span class= +"hljs-string">"startMeasurement", [<span class= +"hljs-string">"Celsius"]); + }, +).catch(<span class= +"hljs-params">error { + .log(<span class= +"hljs-string">"Discovery finished because an error: " + error.message); +}); + +
try {
+  let td = await wot.fetch("http://mmyservice.org/mySensor");
+  let thing = wot.consume(td);
+  console.log("Thing " + thing.name + " has been consumed.");
+  let subscription = thing.onPropertyChange("temperature")
+    .subscribe(function(value) {
+      console.log("Temperature + " has changed to " + value);
+    });
+  thing.invokeAction("startMeasurement", { units: "Celsius" })
+    .then(() => { console.log("Temperature measurement started."); })
+    .catch(e => {
+       console.log("Error starting measurement.");
+       subscription.unsubscribe();
+     })
+} catch(error) {
+  console.log("Error during fetch or consume: " + error.message);
+};
+
+
+
+
+
+
+

+ +5. + +The + + +ExposedThing + + +interface +

+

+The + + +ExposedThing + + +interface +is +the +server +API +that +allows +defining +request +handlers, +properties, + +Actions +, +and + +Events + +to +a + +Thing +. +It +also +implements +the + +ConsumedThing + +interface. +An + +ExposedThing + +is +created +by +the + +produce() + +method. + +

+<span class="idlTypedef" id= +"idl-def-thingdescription" data-idl="" data-title= +"ThingDescription">typedef <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-lt="ThingDescription" +href="#dom-thingdescription" class="internalDFN" data-link-type= +"dfn" data-for=""> + +
+
+<span class="idlCallback" id="idl-def-requesthandler" data-idl="" +data-title="RequestHandler">callback <span class= +"idlCallbackID"><a data-lt="RequestHandler" href= +"#dom-requesthandler" class="internalDFN" data-link-type="dfn" +data-for=""> = <span class= +"idlCallbackType"><a href= +"https://heycam.github.io/webidl/#idl-any">any<a href="#dom-request" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">request + + +Editor's +note +

+It +is +under +consideration +to +use +a +constructor +for + +ExposedThing + +instead +of +a +factory +method. +


+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">ExposedThing implements ConsumedThing;
+
+interface "idlInterfaceID"><a data-lt="ExposedThing" href="#dom-exposedthing"
+class="internalDFN" data-link-type="dfn" data-for=
+""> {
+
+"idlInterfaceID">ExposedThing {
+
+"idlSectionComment">    // define how to expose and run the Thing
+
+data-title="start" data-dfn-for="exposedthing">    Promise<void> start();
+
+data-title="stop" data-dfn-for="exposedthing">    Promise<void> stop();
+
+"idl-def-exposedthing-register-directory" data-idl="" data-title=
+"register" data-dfn-for="exposedthing">    Promise<void> register(optional USVString directory);
+
+"idl-def-exposedthing-unregister-directory" data-idl="" data-title=
+"unregister" data-dfn-for="exposedthing">    Promise<void> unregister(optional USVString directory);
+
+"idl-def-exposedthing-emitevent-eventname-payload" data-idl=""
+data-title="emitEvent" data-dfn-for="exposedthing">    Promise<void> emitEvent(DOMString eventName, any payload);
+
+    // define Thing Description modifiers
+"idl-def-exposedthing-addproperty(property)" data-idl=""
+data-title="addProperty" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+
+"idl-def-exposedthing-addproperty-property" data-idl="" data-title=
+"addProperty" data-dfn-for="exposedthing">    
+"dfn">ExposedThing  "idlMethName"><a data-lt="addProperty()|addproperty()|addProperty"
+data-lt-nodefault="" href="#dom-exposedthing-addproperty()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">addProperty(<span class=
+"idlParam"><a href=
+"#dom-thingpropertyinit" class="internalDFN" data-link-type=
+"dfn"> <span class=
+
+"idlMethName">addProperty(ThingProperty 
+"idlParamName">property);
+"idl-def-exposedthing-removeproperty(name)" data-idl="" data-title=
+
+"idl-def-exposedthing-removeproperty-name" data-idl="" data-title=
+
+"removeProperty" data-dfn-for="exposedthing">    ExposedThing  "idlMethName"><a data-lt=
+"removeProperty()|removeproperty()|removeProperty"
+data-lt-nodefault="" href="#dom-exposedthing-removeproperty()"
+class="internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">removeProperty(<span class=
+
+"idlMethName">removeProperty(
+"idlParam">DOMString name);
+<span class="idlMethod" id="idl-def-exposedthing-addaction(action)"
+
+    ExposedThing  "idlMethName"><a data-lt="addAction()|addaction()|addAction"
+data-lt-nodefault="" href="#dom-exposedthing-addaction()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">addAction(<span class=
+"idlParam"><a href=
+"#dom-thingactioninit" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">action
+<span class="idlMethod" id=
+"idl-def-exposedthing-removeaction(name)" data-idl="" data-title=
+"removeAction" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+
+"idlMethName">addAction(
+data-link-type=
+"dfn">ThingAction action);
+
+data-idl="" data-title="removeAction" data-dfn-for=
+"exposedthing">    
+"dfn">ExposedThing  "idlMethName"><a data-lt=
+"removeAction()|removeaction()|removeAction" data-lt-nodefault=""
+href="#dom-exposedthing-removeaction()" class="internalDFN"
+data-link-type="dfn" data-for=
+"ExposedThing">removeAction(<span class=
+
+"idlMethName">removeAction(
+"idlParam">DOMString name);
+<span class="idlMethod" id="idl-def-exposedthing-addevent(event)"
+
+    ExposedThing  "idlMethName"><a data-lt="addEvent()|addevent()|addEvent"
+data-lt-nodefault="" href="#dom-exposedthing-addevent()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">addEvent(<span class=
+"idlParam"><a href="#dom-thingeventinit"
+
+"idlMethName">
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">event
+<span class="idlMethod" id="idl-def-exposedthing-removeevent(name)"
+
+"dfn">addEvent(ThingEvent event);
+    ExposedThing  "idlMethName"><a data-lt="removeEvent()|removeevent()|removeEvent"
+data-lt-nodefault="" href="#dom-exposedthing-removeevent()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">removeEvent(<span class=
+"idlParam"><a href=
+
+"idlMethName">removeEvent(
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name);
+    // define request handlers
+"idl-def-exposedthing-onretrieveproperty(handler)" data-idl=""
+data-title="onRetrieveProperty" data-dfn-for=
+
+"idl-def-exposedthing-setpropertyreadhandler-name-readhandler"
+data-idl="" data-title="setPropertyReadHandler" data-dfn-for=
+
+"exposedthing">    ExposedThing  "idlMethName"><a data-lt=
+"onRetrieveProperty()|onretrieveproperty()|onRetrieveProperty"
+data-lt-nodefault="" href="#dom-exposedthing-onretrieveproperty()"
+class="internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">onRetrieveProperty(<span class=
+"idlParam"><a href="#dom-requesthandler"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">handler
+
+"idlMethName">setPropertyReadHandler(DOMString name,
+                                         
+"idlParam">PropertyReadHandler readHandler);
+
+"idl-def-exposedthing-onupdateproperty(handler)" data-idl=""
+data-title="onUpdateProperty" data-dfn-for=
+
+"idl-def-exposedthing-setpropertywritehandler-name-writehandler"
+data-idl="" data-title="setPropertyWriteHandler" data-dfn-for=
+
+"exposedthing">    ExposedThing  "idlMethName"><a data-lt=
+"onUpdateProperty()|onupdateproperty()|onUpdateProperty"
+data-lt-nodefault="" href="#dom-exposedthing-onupdateproperty()"
+class="internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">onUpdateProperty(<span class=
+"idlParam"><a href="#dom-requesthandler"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">handler
+
+"idlMethName">setPropertyWriteHandler(DOMString name,
+                                          
+"idlParam">PropertyWriteHandler writeHandler);
+
+"idl-def-exposedthing-oninvokeaction(handler)" data-idl=""
+data-title="onInvokeAction" data-dfn-for=
+
+"idl-def-exposedthing-setactionhandler-name-action" data-idl=""
+data-title="setActionHandler" data-dfn-for=
+
+"exposedthing">    ExposedThing  "idlMethName"><a data-lt=
+"onInvokeAction()|oninvokeaction()|onInvokeAction"
+data-lt-nodefault="" href="#dom-exposedthing-oninvokeaction()"
+class="internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">onInvokeAction(<span class=
+"idlParam"><a href="#dom-requesthandler"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">handler
+<span class="idlMethod" id=
+"idl-def-exposedthing-onobserve(handler)" data-idl="" data-title=
+"onObserve" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+data-link-type=
+"dfn">  <span class=
+"idlMethName"><a data-lt="onObserve()|onobserve()|onObserve"
+data-lt-nodefault="" href="#dom-exposedthing-onobserve()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">onObserve(<span class=
+"idlParam"><a href="#dom-requesthandler"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">handler
+<span class=
+"idlSectionComment">    // define how to expose and run the Thing
+<span class="idlMethod" id=
+"idl-def-exposedthing-register(directory)" data-idl="" data-title=
+"register" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="register()|register()|register"
+data-lt-nodefault="" href="#dom-exposedthing-register()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">register(<span class=
+"idlParam">optional <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id=
+"idl-def-exposedthing-unregister(directory)" data-idl=""
+data-title="unregister" data-dfn-for=
+"exposedthing">    <a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="unregister()|unregister()|unregister"
+data-lt-nodefault="" href="#dom-exposedthing-unregister()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">unregister(<span class=
+"idlParam">optional <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id="idl-def-exposedthing-start()" data-idl=
+"" data-title="start" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="start()|start()|start"
+data-lt-nodefault="" href="#dom-exposedthing-start()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">start
+<span class="idlMethod" id="idl-def-exposedthing-stop()" data-idl=
+"" data-title="stop" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="stop()|stop()|stop"
+data-lt-nodefault="" href="#dom-exposedthing-stop()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">stop
+<span class="idlMethod" id=
+"idl-def-exposedthing-emitevent(eventname,payload)" data-idl=""
+data-title="emitEvent" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="emitEvent()|emitevent()|emitEvent"
+data-lt-nodefault="" href="#dom-exposedthing-emitevent()" class=
+"internalDFN" data-link-type="dfn" data-for=
+"ExposedThing">emitEvent(<span class=
+
+"idlMethName">setActionHandler(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, ActionHandler action);
+
+};
+<a href="#dom-exposedthing" class=
+"internalDFN" data-link-type=
+"dfn"> implements <a href=
+"#dom-consumedthing" class="internalDFN" data-link-type=
+"dfn">
+
+data-idl="" data-title="PropertyReadHandler">callback PropertyReadHandler = Promise<any> ();
+
+ConsumedThing
+
+data-idl="" data-title="PropertyWriteHandler">callback PropertyWriteHandler = Promise<void> (any value);
+
+data-title="ActionHandler">callback ActionHandler = 
+Promise
+
+
+;
+
+<
+
+href="https://heycam.github.io/webidl/#idl-any">
+any
+
+>
+
+(
+
+any
+
+parameters
+
+);
+
+
+
+
+
+

+ +5.1 + +The + + +ThingDescription + +start() + + + +type + +method + +

+

+WoT +provides +a +unified +representation + +Start +serving +external +requests + +for +data +exchange +between +Thing +s, +standardized +in +the +Wot +Things +Description +specification. +Note +In +this +version +of + +the +API, + + +Thing +Description +s +are +represented +as +opaque +strings, +denoting +a +serialized +form, +for +instance +JSON +or +JSON-LD. +See +Issue +38 +and +Issue +45 + +. +Parsing +and +composing +Thing +Description +s +is +left +for +external +libraries +until +standardized +here. + +

+
+
+

+ +5.2 + +The + + +Request + +stop() + + + +interface + +method + +

+<span class="idlInterface" id= +"idl-def-request" data-idl="" data-title= +"Request">interface <a data-lt= +"Request" href="#dom-request" class="internalDFN" data-link-type= +"dfn" data-for=""> { +<span class="idlAttribute" id="idl-def-request-type" data-idl="" +data-title="type" data-dfn-for= +"request"> readonly attribute <a href= +"#dom-requesttype" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-lt="type" href="#dom-request-type" class= +"internalDFN" data-link-type="dfn" data-for= +"Request"> +<span class="idlAttribute" id="idl-def-request-from" data-idl="" +data-title="from" data-dfn-for= +"request"> readonly attribute <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-lt="from" +href="#dom-request-from" class="internalDFN" data-link-type="dfn" +data-for="Request"> +<span class="idlAttribute" id="idl-def-request-name" data-idl="" +data-title="name" data-dfn-for= +"request"> readonly attribute <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name" +href="#dom-request-name" class="internalDFN" data-link-type="dfn" +data-for="Request"> +<span class="idlAttribute" id="idl-def-request-options" data-idl="" +data-title="options" data-dfn-for= +"request"> readonly attribute <span class= +"idlAttrType">Dictionary <span class= +"idlAttrName"><a data-lt="options" href="#dom-request-options" +class="internalDFN" data-link-type="dfn" data-for= +"Request"> +<span class="idlAttribute" id="idl-def-request-data" data-idl="" +data-title="data" data-dfn-for= +"request"> readonly attribute <a href= +"https://heycam.github.io/webidl/#idl-any">any<a data-lt="data" +href="#dom-request-data" class="internalDFN" data-link-type="dfn" +data-for="Request"> +<span class="idlMethod" id="idl-def-request-respond(response)" +data-idl="" data-title="respond" data-dfn-for= +"request"> <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<a data-lt="respond()|respond()|respond" +data-lt-nodefault="" href="#dom-request-respond()" class= +"internalDFN" data-link-type="dfn" data-for= +"Request">respond<span class= +"idlParamType"><a href= +"https://heycam.github.io/webidl/#idl-any">any +<span class="idlMethod" id= +"idl-def-request-respondwitherror(error)" data-idl="" data-title= +"respondWithError" data-dfn-for="request"> <span class= +"idlMethType">void<a data-lt= +"respondWithError()|respondwitherror()|respondWithError" +data-lt-nodefault="" href="#dom-request-respondwitherror()" class= +"internalDFN" data-link-type="dfn" data-for= +"Request">respondWithError(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-Error">Error +}; + +

+Represents +an +incoming +request + +Stop +serving +external +requests +for + +the + +Thing +.

+5.3 + +The + + +ExposedThing + +register() + + + +method +

+Generates +the + +Thing +Description + + +is +supposed +to +handle, +for +instance +retrieving +and +updating + +given +the + +properties, +invoking + + +Actions + +and +observing +Events + + +Event + + +(WoT +interactions). +The +type +attribute +represents +the +type +of +the +request +as + +defined +in +RequestType +. +The + +for +this +object. +If +a + + +from + +directory + + +attribute +represents +the +address +of +the +client +device +issuing +the +request. +The +type +of +the +address +(URL, +UUID +or +other) + +argument + +is +defined +by + +given, +make +a +request +to +register + +the + +Thing +Description +. +The +name +attribute +represents +the +name +of +the +Property + + +to +be +retrieved +or +updated, +or +the +name +of +the +invoked +Action +, +or +the +event +name +to +be +observed. +The +options +attribute +represents +the +options +relevant +to +the +request +(e.g. +the +format +or +measurement +units +for + +with + +the +returned +value) +as +key-value +pairs. +The +exact +format +is +specified + +given +WoT +repository + +by +the +Thing +Description +. +The + +invoking +its + + +data + +register + + +attribute +represents +the +value +of +the +Property +, +or +the +input +data +(arguments) +of +an + + +Action +. +It +is +not +used +for +retrieve +requests +and +event +requests, +only +for +Property +update +and +Action +invocation +requests. +5.2.1 +The +RequestType + +

+
+
+

+enumeration +<span class="idlEnum" id="idl-def-requesttype" +data-idl="" data-title="RequestType">enum <span class= +"idlEnumID"><a data-lt="RequestType" href="#dom-requesttype" class= +"internalDFN" data-link-type="dfn" data-for= +""> { + <a href="#dom-requesttype-property" class= +"idlEnumItem">"property", + <a href="#dom-requesttype-action" class= +"idlEnumItem">"action", + <a href="#dom-requesttype-event" class= +"idlEnumItem">"event", + +}; + + +5.4 + + +The +value +" + + + +property + +unregister() + + + +" +represents +requests +to +retrieve +or +update + +method +

+If + +a +Property +. +The +value +" +action +" +represents +requests +to +invoke +an +Action +. +The +value +" +event +" +represents +requests +to +emit +an +event. +The +value +" + + +td + +directory + + +" +represents +requests + +argument +is +given, +make +a +request + +to +change + +unregister + +the + +Thing +Description +, +i.e. +to +add, +remove +or +modify +properties, +Actions + + +or +Events +. +Editor's +note +This +functionality +is +here +for + +with + +the +sake +of +completeness +for +future +versions +of + +given +WoT +repository +by +invoking +its + +unregister + +Action +. +Then, +and +in + +the +API. +Currently +there +is + +case + +no +corresponding +functionality +at + +arguments +were +provided +to +this +function, +stop + +the +ConsumedThing + + +Thing + + +level + +and +it +is +not +guaranteed +that +a + +remove +the + +Thing +Description +could +be +remotely +changed +by +scripting. + +. +

+
+
+

+5.2.2 + + +5.5 + + +The + + +respond() + +emitEvent() + + + +method +

+

+Sends +a +positive +response +to + +Emits +an +the +event +initialized +with +the +event +name +specified +by + +the + +Request + +eventName + + +based +on +the +Protocol +Bindings + +argument + +and +includes +the + +data +specified +by +the +data + + +payload + +argument. +

+
+
+

+5.2.3 + + +5.6 + + +The + + +respondWithError() + +DataSchema + + + +method +Sends +a +negative +response +to +the + +type +


+"idl-def-dataschema" data-idl="" data-title=
+"DataSchema">typedef USVString 
+
+
+Request
+
+DataSchema
+
+
+
+based
+on
+the
+Protocol
+Bindings
+and
+includes
+the
+error
+specified
+by
+the
+error
+argument.
+
+5.3
+
+
+;
+

+The + + +RequestHandler + +DataSchema + + +callback +Callback +function +for +handling +interaction +requests. +Receives +an +argument +request +of + + +type +represents +a +data +type + +specified + +in +the + +Thing +Description + +in +a +serialized +form. +

+ +Editor's +note +

+ +Request + +DataSchema + + + +and +should +return +an +object +or +value +that + +is +used +by +Protocol +Bindings +to +reply +to +the +request. +The +returned + +under +development, +currently +it +can +denote +any + +type +is +defined + +supported + +by +the + +Thing +Description + +and +the + +WoT +Runtime + +. +

+
+
+
+

+5.4 + + +5.7 + + +The + + +addProperty() + + +method +

+

+Adds +a + +Property + +defined +by +the +argument +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. + +

+
+

+ +5.4.1 + +5.7.1 + + +The + + +ThingPropertyInit + +ThingProperty + + + +dictionary +

+
+
"idl-def-thingpropertyinit" data-idl="" data-title=
+"ThingPropertyInit">dictionary <span class=
+"idlDictionaryID"><a data-lt="ThingPropertyInit" href=
+"#dom-thingpropertyinit" class="internalDFN" data-link-type="dfn"
+data-for=""> {
+<span class="idlMember" id="idl-def-thingpropertyinit-name"
+data-idl="" data-title="name" data-dfn-for=
+"thingpropertyinit">    <a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name"
+href="#dom-thingpropertyinit-name" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingPropertyInit">
+<span class="idlMember" id="idl-def-thingpropertyinit-configurable"
+data-idl="" data-title="configurable" data-dfn-for=
+"thingpropertyinit">    <a href=
+"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-lt="configurable"
+href="#dom-thingpropertyinit-configurable" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingPropertyInit">
+<span class="idlMember" id="idl-def-thingpropertyinit-enumerable"
+data-idl="" data-title="enumerable" data-dfn-for=
+"thingpropertyinit">    <a href=
+"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-lt="enumerable"
+href="#dom-thingpropertyinit-enumerable" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingPropertyInit">
+<span class="idlMember" id="idl-def-thingpropertyinit-writable"
+
+"idl-def-thingproperty" data-idl="" data-title=
+"ThingProperty">dictionary ThingProperty : SemanticAnnotations {
+
+data-title="name" data-dfn-for=
+"thingproperty">    required DOMString  name;
+
+"" data-title="schema" data-dfn-for=
+"thingproperty">    required DataSchema schema;
+
+"" data-title="value" data-dfn-for=
+"thingproperty">             any        value;
+"thingpropertyinit">    <a href=
+"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-lt="writable"
+href="#dom-thingpropertyinit-writable" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingPropertyInit"> = <span class=
+"idlMemberValue">true
+<span class="idlMember" id=
+"idl-def-thingpropertyinit-semantictypes" data-idl="" data-title=
+"semanticTypes" data-dfn-for="thingpropertyinit">    <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-semantictype"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMemberName"><a data-lt="semanticTypes" href=
+"#dom-thingpropertyinit-semantictypes" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingPropertyInit">
+<span class="idlMember" id="idl-def-thingpropertyinit-description"
+data-idl="" data-title="description" data-dfn-for=
+"thingpropertyinit">    <a href=
+"#dom-thingdescription" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMemberName"><a data-lt="description" href=
+"#dom-thingpropertyinit-description" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingPropertyInit">
+<span class="idlMember" id="idl-def-thingpropertyinit-value"
+data-idl="" data-title="value" data-dfn-for=
+"thingpropertyinit">    <a href=
+"https://heycam.github.io/webidl/#idl-any">any<a data-lt="value"
+href="#dom-thingpropertyinit-value" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingPropertyInit">
+
+"thingproperty">             boolean    writable = false;
+
+data-idl="" data-title="observable" data-dfn-for=
+"thingproperty">             boolean    observable = false;
+
+};
+
+
+
+

+Represents +the + +Thing + + +Property + +description. +

+
    +
  • +The + + +name + + +attribute +represents +the +name +of +the + +Property +. +
  • +
  • +The + + +value + +schema + + + +attribute +represents +the +value +of + +data +type +for + +the + +Property + +described +by + +DataSchema + +. +
  • +
  • +The + + +configurable + +value + + + +attribute +defines +whether +the +Property +can +be +deleted +from + +represents + +the +object +and +whether +its +properties +can +be +changed. +The +default + +value +is +false +. + +of +the + +Property +. +
  • +
  • +The + + +enumerable + +writable + + + +attribute +defines +whether +the + +Property + +can +be +listed +and +iterated. + +updated. + +The +default +value +is + +true + +false + +. +
  • +
  • +The + + +writable + +observable + + + +attribute +defines +whether +the + +Property + +changes + +can +be +updated. + +observed +by +an +external +client. + +The +default +value +is + +true + +false + +. +
  • +The +semanticTypes +attribute +represents +a +list +of +semantic +type +annotations +(e.g. +labels, +classifications +etc) +relevant +to +the +Property +, +represented +as +SemanticType +dictionaries. +The +description +attribute +represents +the +Property +description +to +be +added +to +the +Thing +Description +. +5.4.2 +The +SemanticType +dictionary +<span class="idlDictionary" id= +"idl-def-semantictype" data-idl="" data-title= +"SemanticType">dictionary <a data-lt= +"SemanticType" href="#dom-semantictype" class="internalDFN" +data-link-type="dfn" data-for= +""> { +<span class="idlMember" id="idl-def-semantictype-name" data-idl="" +data-title="name" data-dfn-for="semantictype"> <span class= +"idlMemberType"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name" +href="#dom-semantictype-name" class="internalDFN" data-link-type= +"dfn" data-for="SemanticType"> +<span class="idlMember" id="idl-def-semantictype-context" data-idl= +"" data-title="context" data-dfn-for= +"semantictype"> <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-lt="context" +href="#dom-semantictype-context" class="internalDFN" +data-link-type="dfn" data-for= +"SemanticType"> +}; +Represents +a +semantic +type +annotation, +containing +a +name +and +a +context. +The +name +attribute +represents +the +name +of +the +semantic +type +in +the +given +context. +The +context +attribute +represents +an +URL +link +to +the +context +of +the +semantic +classification. + +
+Editor's +note +Semantic +type +examples +to +be +added. + +
+
+
+

+ +5.5 + +5.8 + + +The + + +removeProperty() + + +method +

+

+Removes +the + +Property + +specified +by +the + +name + +argument, + +argument +and + +updates +the + +Thing +Description +and +returns + +. +Throws +on +error. +Returns +a +reference +to + +the +object. + +same +object +for +supporting +chaining. + +

+
+
+

+ +5.6 + +5.9 + + +The + + +addAction() + + +method +

+

+Adds +an + +Action + +to +the + +Thing + +object +as +defined +by +the + +action + +argument +of +type + + +ThingActionInit + +ThingAction + + + +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. + +

+
+

+ +5.6.1 + +5.9.1 + + +The + + +ThingActionInit + +ThingAction + + + +dictionary +

+
+
"idl-def-thingactioninit" data-idl="" data-title=
+"ThingActionInit">dictionary <span class=
+"idlDictionaryID"><a data-lt="ThingActionInit" href=
+"#dom-thingactioninit" class="internalDFN" data-link-type="dfn"
+data-for=""> {
+<span class="idlMember" id="idl-def-thingactioninit-name" data-idl=
+"" data-title="name" data-dfn-for=
+"thingactioninit">    <a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name"
+href="#dom-thingactioninit-name" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingActionInit">
+<span class="idlMember" id=
+"idl-def-thingactioninit-inputdatadescription" data-idl=""
+data-title="inputDataDescription" data-dfn-for=
+"thingactioninit">    <a href=
+"#dom-thingdescription" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMemberName"><a data-lt="inputDataDescription" href=
+"#dom-thingactioninit-inputdatadescription" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingActionInit">
+<span class="idlMember" id=
+"idl-def-thingactioninit-outputdatadescription" data-idl=""
+data-title="outputDataDescription" data-dfn-for=
+"thingactioninit">    <a href=
+"#dom-thingdescription" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMemberName"><a data-lt="outputDataDescription" href=
+"#dom-thingactioninit-outputdatadescription" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingActionInit">
+<span class="idlMember" id="idl-def-thingactioninit-semantictypes"
+data-idl="" data-title="semanticTypes" data-dfn-for=
+"thingactioninit">    <a href=
+"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-semantictype"
+
+"idl-def-thingaction" data-idl="" data-title=
+"ThingAction">dictionary ThingAction : SemanticAnnotations {
+
+data-title="name" data-dfn-for=
+"thingaction">    required DOMString  
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMemberName"><a data-lt="semanticTypes" href=
+"#dom-thingactioninit-semantictypes" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingActionInit">
+<span class="idlMember" id="idl-def-thingactioninit-action"
+data-idl="" data-title="action" data-dfn-for=
+"thingactioninit">    <span class=
+"idlMemberType">Function               <span class=
+"idlMemberName"><a data-lt="action" href=
+"#dom-thingactioninit-action" class="internalDFN" data-link-type=
+"dfn" data-for=
+"ThingActionInit">
+
+"dfn">name;
+
+data-idl="" data-title="inputSchema" data-dfn-for=
+"thingaction">             DataSchema inputSchema;
+
+data-idl="" data-title="outputSchema" data-dfn-for=
+"thingaction">             DataSchema outputSchema;
+
+};
+
+
+
+

+The + + +ThingActionInit + +ThingAction + + + +dictionary +describes +the +arguments +and +the +return +value. +

+
    +
  • +The + + +name + + +attribute +provides +the + +Action + +name. +
  • +
  • +The +action +attribute +provides +a +function +that +defines +the +Action +. +The + + + +inputDataDescription + +inputSchema + + + +attribute +provides +the +description +of +the +input +arguments +(argument +list +is +represented +by +an +object). +If +missing, +it +means +the +action +does +not +accept + +arguments. +
  • +
  • +The + + +outputDataDescription + +outputSchema + + + +attribute +provides +the +description +of +the +returned +data. +The +semanticTypes +attribute +provides +a +list +of +semantic +type +annotations +(e.g. +labels, +classifications +etc) +relevant +to + +If +missing, +it +means + +the +Action +, +represented +as +SemanticType +dictionaries. + +action +does +not +return +data. + +
  • +
+
+
+
+

+ +5.7 + +5.10 + + +The + + +removeAction() + + +method +

+

+Removes +the + +Action + +specified +by +the + +name + +argument, + +argument +and + +updates +the + +Thing +Description +and +returns + +. +Throws +on +error. +Returns +a +reference +to + +the +object. + +same +object +for +supporting +chaining. + +

+
+
+

+ +5.8 + +5.11 + + +The + + +addEvent() + + +method +

+

+Adds +an +event +to +the + +Thing + +object +as +defined +by +the + +event + +argument +of +type + + +ThingEventInit + +ThingEvent + + + +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. + +

+
+

+ +5.8.1 + +5.11.1 + + +The + + +ThingEventInit + +ThingEvent + + + +dictionary +

+
+
"idl-def-thingeventinit" data-idl="" data-title=
+"ThingEventInit">dictionary <span class=
+"idlDictionaryID"><a data-lt="ThingEventInit" href=
+"#dom-thingeventinit" class="internalDFN" data-link-type="dfn"
+data-for=""> {
+<span class="idlMember" id="idl-def-thingeventinit-name" data-idl=
+"" data-title="name" data-dfn-for="thingeventinit">    <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-lt="name"
+href="#dom-thingeventinit-name" class="internalDFN" data-link-type=
+"dfn" data-for=
+"ThingEventInit">
+<span class="idlMember" id="idl-def-thingeventinit-semantictypes"
+data-idl="" data-title="semanticTypes" data-dfn-for=
+"thingeventinit">    <a href=
+"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-semantictype"
+
+"idl-def-thingevent" data-idl="" data-title=
+"ThingEvent">dictionary ThingEvent : SemanticAnnotations {
+
+data-title="name" data-dfn-for=
+"thingevent">    required DOMString  
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMemberName"><a data-lt="semanticTypes" href=
+"#dom-thingeventinit-semantictypes" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingEventInit">
+<span class="idlMember" id="idl-def-thingeventinit-datadescription"
+data-idl="" data-title="dataDescription" data-dfn-for=
+"thingeventinit">    <a href=
+"#dom-thingdescription" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMemberName"><a data-lt="dataDescription" href=
+"#dom-thingeventinit-datadescription" class="internalDFN"
+data-link-type="dfn" data-for=
+"ThingEventInit">
+
+"dfn">name;
+
+data-title="schema" data-dfn-for=
+"thingevent">             DataSchema schema;
+
+};
+
+
+
+
    +
  • +The + + +name + + +attribute +represents +the +event +name. +
  • +
  • +The +semanticTypes +attribute +represent +a +list +of +semantic +type +annotations +attached +to +the +event. +The + + + +dataDescription + +schema + + + +attribute +represents +the +description + +type + +of +the +data +that +is +attached +to +the +event. +If +missing, +it +means +the +event +does +not +carry +data. + +
  • +
+
+
+
+

+ +5.9 + +5.12 + + +The + + +removeEvent() + + +method +

+

+Removes +the +event +specified +by +the + +name + +argument, + +argument +and + +updates +the + +Thing +Description +and +returns + +. +Returns +a +reference +to + +the +object. + +same +object +for +supporting +chaining. + +

+
+
+

+ +5.10 + +5.13 + + +The + + +onRetrieveProperty() + +PropertyReadHandler + + + +method + +callback + +

+

+Registers +the +handler + +A + +function +for + +that +returns +a +Promise +and +resolves +it +with +the +value +of +the + +Property + +retrieve +requests +received +for + +matching + +the +Thing +, +as +defined +by + + +name + +argument +to + +the + +handler + +setPropertyReadHandler + + +function, +or +rejects +with +an +error +if +the + +property +of +type + +is +not +found +or +the +value +cannot +be +retrieved. +

+ +5.14 + +The + + +RequestHandler + +PropertyWriteHandler + + + +callback +

+A +function +called +with + +value + + +. +The +handler +will +receive +an + +as + +argument +request + +that +returns +a +Promise +which +is +resolved +when +the +value + +of +type + +the + +Property + +matching +the + + +name + +argument +to +the + + +Request + +setPropertyReadHandler + + +function +is +updated +with + +value +, +or +rejects +with +an +error +if +the +property +is +not +found +or +the +value +cannot +be +updated. +

+ +Editor's +note + +where +at +least +request.name + +
+

+Note +that +this +function + +is +defined +and +represents + +invoked +by +implementations +before + +the +name + +property +is +updated, +so +the +code +in +this +callback +function +can +invoke +the + +readProperty() + +method +to +find +out +the +old +value + +of +the +Property + +property, +if +needed. +Therefore +the +old +value +is +not +provided + +to +be +retrieved. + +this +method. + +

+
+
+
+

+ +5.11 + +5.15 + + +The + + +onUpdateProperty() + +ActionHandler + + + +method + +callback + +

+

+Defines +the +handler + +A + +function +for +Property + +called +with +a + +parameters + +dictionary +argument +assembled +by +the + +WoT +runtime + + +update +requests +received +for + +based +on + +the + +Thing +, +as +defined +by + +Description + +and +the +external +client +request. +It +returns +a +Promise +that +rejects +with +an +error +or +resolves +if + +the +action +is +successful +or +ongoing +(may +also +resolve +with +a +control +object +such +as +an + + +handler + +Observable + + +property +of +type + + +for +actions +that +need +progress +notifications +or +that +can +be +canceled). +

+5.16 + +The + + +RequestHandler + +setPropertyReadHandler() + + + +method +

+Takes + +name + + +. +The +handler +will +receive +an + +as +string +argument +and + +readHandler + +as + +argument +request + +of +type + + +Request + +PropertyReadHandler + + +where +request.name +defines + +. +Sets + +the +name +of + +handler +function +for +reading + +the +specified + +Property + +matched +by + +name +. +Throws +on +error. +Returns +a +reference + +to +be +retrieved + +the +same +object +for +supporting +chaining. +

+The + +readHandler + +callback +function +will +implement +reading +a + +Property + +and +request.data +defines + + +SHOULD + +be +called +by +implementations +when +a +request +for +reading +a + +Property + +is +received +from + +the +new +value +of + +underlying +platform. +

+There + +SHOULD + +be +at +most +one +handler +for +any +given + +Property + +and +newly +added +handlers +replace + +the +old +handlers. +If +no +handler +is +initialized +for +any +given + +Property +. + +, +implementations + +SHOULD + +implement +a +default +property +read +handler. + +

+
+
+

+ +5.12 + +5.17 + + +The + + +onInvokeAction() + +setPropertyWriteHandler() + + + +method +

+

+Defines +the +handler +function +for +Action +invocation +requests +received +for +the +Thing +, +as +defined +by +the + +Takes + + +handler + +name + + +property +of +type + +as +string +argument +and + + +RequestHandler + +writeHandler + + +. +The +handler +will +receive +an + +as + +argument +request + +of +type + + +Request + +PropertyWriteHandler + + +where +request.name +defines + +. +Sets + +the +name +of + +handler +function +for +writing + +the +Action + +specified + +Property + + +matched +by + +name +. +Throws +on +error. +Returns +a +reference + +to +be +invoked +and +request.data +defines + +the +input +arguments + +same +object + +for +the +Action + +supporting +chaining. +

+There + +SHOULD + +be +at +most +one +write +handler +for +any +given + +Property + + +as +defined +by + +and +newly +added +handlers +replace + +the +Thing +Description +. + +old +handlers. +If +no +write +handler +is +initialized +for +any +given + +Property +, +implementations + +SHOULD + +implement +default +property +update +and +notifying +observers +on +change. + +

+
+
+

+ +5.13 + +5.18 + + +The + + +onObserve() + +setActionHandler() + + + +method +

+

+Defines +the +handler +function +for +observe +requests +received +for +the +Thing +, + +Takes + +name + +as +defined +by +the + +string +argument +and + + +handler + +action + + +property + +as +argument + +of +type + + +RequestHandler + +ActionHandler + + +. +The + +. +Sets +the + +handler +function +for +the +specified + +Action + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+If +provided, +this +callback +function + +will +receive + +implement +invoking + +an +argument + + +Action + +and + +SHOULD + +be +called +by +implementations +when +a + +request +of +type + +for +invoking +a + +Action + +is +received +from +the +underlying +platform. +The +callback +will +receive +a + +parameters + +dictionary +argument. +

+There + +SHOULD + +be +exactly +one +handler +for +any +given + +Action +. +If +no +handler +is +initialized +for +any +given + +Action +, +implementations + +SHOULD + +return +error +if +the +action +is +invoked +by +any +client. +

+5.19 + +Examples +

+Below +some + + + + +Request + +ExposedThing + + + + +where + +interface +examples +are +given. + +

+
+
+request.name +defines +the +name +of +the +Property +or +Action +or +event + + +Example +7 +: +Create +a +new +blank +exposed +Thing +
        try {  
+"hljs-keyword">var thing = WoT.produce({ name: "tempSensor" });
+  // manually add Interactions
+  thing.addProperty({
+    name: 
+"hljs-string">"temperature",
+    value: 
+"hljs-number">0.0,
+    schema: 
+"hljs-string">'{ "type": "number" }'
+    
+"hljs-comment">// use default values for the rest
+  }).addProperty({
+    name: 
+"hljs-string">"max",
+    value: 
+"hljs-number">0.0,
+    schema: 
+"hljs-string">'{ "type": "number" }'
+    
+"hljs-comment">// use default values for the rest
+  }).addAction({
+    name: 
+"hljs-string">"reset",
+    // no input, no output
+  }).addEvent({
+    name: 
+"hljs-string">"onchange",
+    schema: 
+"hljs-string">'{ "type": "number" }'
+  });
+  // add server functionality
+  thing.setActionHandler("reset", () => {
+    console.log(
+"hljs-string">"Resetting maximum");
+    thing.writeProperty("max", 0.0);
+  });
+  thing.start().then(() => {
+      thing.register();
+  });
+  // define Thing business logic
+  setInterval( async () => {
+    let mock = 
+"hljs-built_in">Math.random()*100;
+    thing.writeProperty("temperature", mock);
+    let old = 
+"hljs-keyword">await thing.readProperty("max");
+    if (old < mock) {
+      thing.writeProperty("max", mock);
+      thing.emitEvent("onchange");
+    }
+  }, 1000);
+} catch (err) {
+   console.log(
+"hljs-string">"Error creating ExposedThing: " + err);
+}
+
+Example +8 +: +Create +a +new +exposed +Thing +from +a +Thing +Description +
        
+"hljs-keyword">let thingDescription = '{ "@context": [ "https://w3c.github.io/wot/w3c-wot-td-context.jsonld", "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ], "@type": [ "Thing", "Sensor" ], "name": "mySensor", "geo:location": "testspace", "interaction": [ { "@type": [ "Property", "Temperature" ], "name": "prop1", "schema": { "type": "number" }, "saref:TemperatureUnit": "degree_Celsius" } ] }';
+try {  
+"hljs-comment">// note that produce() fails if thingDescription contains error
+  
+"hljs-keyword">let thing = WoT.produce(thingDescription);
+  
+"hljs-comment">// Interactions were added from TD
+  
+"hljs-comment">// WoT adds generic handler for reading any property
+  
+"hljs-comment">// define a specific handler for one property
+  let name = 
+"hljs-string">"examplePropertyName";
+  thing.setPropertyReadHandler(name, () => {
+    console.log(
+"hljs-string">"Handling read request for " + name);
+    return 
+"hljs-keyword">new Promise((resolve, reject) => {
+        
+"hljs-keyword">let examplePropertyValue = 5;
+        resolve(examplePropertyValue);
+      },
+      e => {
+        console.log(
+"hljs-string">"Error");
+      });
+  });
+  thing.start();
+} catch(err) {
+   console.log(
+"hljs-string">"Error creating ExposedThing: " + err);
+}
+
+Example +9 +: +Create +a +new +exposed +Thing +from +a +TD +URI +
        
+"hljs-comment">// fetch an external TD, e.g., to set up a proxy for that Thing
+WoT.fetch("http://myservice.org/mySensor/description").then(td => {
+  
+"hljs-comment">// WoT.produce() ignores instance-specific metadata (security, form)
+  let thing = WoT.produce(td);  
+"hljs-comment">// Interactions were added from TD
+  // add server functionality  // ...
+});
+

+6. + +Experimental +extensions + +to +be +observed. + +the + +ConsumedThing + +interface +

+request.options.observeType + + +This +section + +is +of +type + +non-normative. +

+The + + +RequestType + +ThingDescription + + + +and +defines +whether +a +Property +change +or + +related +functionality, +such +as +enumerating + +Properties +, +Action + +invocation +or +event +emitting +is +observed, +or +the +changes +to +the +Thing +Description + +s, + +Event + + +are +observed. +request.options.subscribe +is +true +if +subscription +is +turned +or +kept +being +turned +on, + +s + +and +it + +links +(introspection) + +is +false +when +subscription + +an +API +extension +that + +is +turned +off. + +out +of +scope +for +this +specification. +However, +the +draft +interfaces +are +defined +here +for +informative +purposes. +


+"idl-def-consumedthing-partial-1" data-idl="" data-title=
+"ConsumedThing">partial interface ConsumedThing {
+
+data-idl="" data-title="getProperties" data-dfn-for=
+"consumedthing">    sequence<ThingProperty> getProperties();
+
+data-idl="" data-title="getActions" data-dfn-for=
+"consumedthing">    sequence<ThingAction>   getActions();
+
+data-idl="" data-title="getEvents" data-dfn-for=
+"consumedthing">    sequence<ThingEvent>    getEvents();
+
+data-idl="" data-title="getLinks" data-dfn-for=
+"consumedthing">    sequence<TDLink>        getLinks();
+};
+

+ +5.14 + +6.1 + + +The + + +register() + +getProperties() + + + +method +

+

+Generates +the +Thing +Description +given + +Returns + +the +properties, +Actions +and +Event + +list +of + +Properties + + +defined +for +this +object. +If +a +directory +argument +is +given, +make +a +request +to +register + +in + +the + +Thing +Description + +with + +of + +the +given +WoT +repository +by +invoking +its + + +Thing + +in +the +form +of +a +list +of + + +register + +ThingProperty + + +Action +. + + +objects. + +

+
+
+

+5.15 + + +6.2 + + +The + + +unregister() + +getActions() + + + +method +

+

+If +a +directory +argument +is +given, +make +a +request +to +unregister +the +Thing +Description +with + +Returns + +the +given +WoT +repository +by +invoking +its +unregister + +list +of + +Action +. +Then, +and + + +s +defined + +in +the +case +no +arguments +were +provided +to +this +function, +stop +the + + +Thing +Description + + +and +remove + +of + +the + +Thing +Description +. + + +in +the +form +of +a +list +of + +ThingAction + +objects. + +

+
+
+

+ +5.16 + +6.3 + + +The + + +start() + +getEvents() + + + +method +

+

+Start +serving +external +requests +for + +Returns + +the +list +of + +Event + +s +defined +in +the + +Thing +. + +Description + +of +the + +Thing + +in +the +form +of +a +list +of + +ThingEvent + +objects. + +

+
+ +
+
+

+ +5.20 + +7. + + +Examples + +Observables +

+

+Below +some + + +This +section +is +non-normative. + +ExposedThing + +

+

+ +Observables + +are + +proposed + + +interface +examples + +to +be +included +in +ECMAScript +and + +are +given. + +used +for +handling +pushed +data +associated +with +various +possible +sources, +for +instance +events, +timers, +streams, +etc. +A +minimal +required +implementation +is +described +here. + +

+
+
+ +Example +6 + +Editor's +note + + +: +Create +a +new +blank +exposed +Thing + +
+

+This +section +is +informal +and +contains +rather +laconic +information +for +implementations +on +what +to +support +for +interoperability. +


+"idl-def-observable" data-idl="" data-title=
+"Observable">interface Observable {
+
+"idl-def-observable-subscribe-next-error-complete" data-idl=""
+data-title="subscribe" data-dfn-for="observable">    Subscription subscribe((Observer or OnNext) next,
+                           
+"idlParam">optional OnError error,
+                           
+"idlParam">optional OnComplete complete);
+};
+
+data-title="Subscription">interface Subscription {
+
+data-idl="" data-title="unsubscribe" data-dfn-for=
+"subscription">    void unsubscribe();
+
+data-idl="" data-title="closed" data-dfn-for=
+"subscription">    readonly attribute boolean closed;
+};
+
+data-title="Observer">interface Observer {
+
+"" data-title="next" data-dfn-for="observer">    void next(any value);
+
+"" data-title="error" data-dfn-for="observer">    void error(Error error);
+
+data-title="complete" data-dfn-for="observer">    void complete();
+};
+
+data-title="OnNext">callback OnNext = void (any value);
+
+data-title="OnError">callback OnError = void (Error error);
+
+data-title="OnComplete">callback OnComplete = 
+void
+
+();
+
+
+<pre class="highlight hljs javascript" aria-busy="false" aria-live=
+"polite">WoT.createExposedThing(thingDescription)
+  .then(<span class=
+"hljs-keyword">function(<span class=
+"hljs-params">thing{
+    <span class=
+"hljs-comment">// manually add properties, actions, and events
+    thing.addProperty({
+      : <span class=
+"hljs-string">"temperature",
+      : <span class=
+"hljs-string">"0",
+      : <span class=
+"hljs-literal">false
+      <span class=
+"hljs-comment">// use default values for the rest
+    }).addEvent({
+      : <span class=
+"hljs-string">"onchange",
+      : {
+        : <span class=
+"hljs-string">"float32"
+      }
+    }).addAction({
+      : <span class=
+"hljs-string">"reset",
+      : <span class=
+"hljs-function"><span class=
+"hljs-params">() { <span class=
+"hljs-keyword">this.temperature = <span class=
+"hljs-number">0; }
+    })
+    
+    .onRetrieveProperty( <span class=
+"hljs-params">request {
+      .log(<span class=
+"hljs-string">"Handling read request");
+       <span class=
+"hljs-keyword">this.temperature;
+    }).onObserve( <span class=
+"hljs-params">request {
+      .log(<span class=
+"hljs-string">"Handling observe request");
+      <span class=
+"hljs-comment">// add listener identified by request.from
+    }).onInvokeAction( <span class=
+"hljs-params">request {
+      .log(<span class=
+"hljs-string">"Handling action request");
+    }).start();
+});
+
+
+
+
+

+Example +7 + + +7.1 + + +The + +: +Create +a +new +exposed +Thing +from +a +TD +URI + + +Observer + +let thingDescription = '{ + "name": "mySensor", + "url": "http://myservice.org/mySensor/description" +}'; +WoT.createExposedThing(thingDescription) + .then(function(thing) { + // properties, actions and events are added based on the TD + console.log("created " + thing.name }); + // now add the requests handlers + thing.onRetrieveProperty(function(request) { + console.log("Sending property '" + request.property + "' to " + request.from); + }).onUpdateProperty(function(request) { + console.log("Updating property '" + request.property + "' by " + request.from); + }).onObserve(function(request) { + console.log("Adding listener " + request.from); + console.log("Observing " + request.type + " " + request.name + + (request.subscribe? " recursively" : "")); + }).start().then(function() { + console.log("Thing started serving requests"); + }); +}) + + +interface +

+The + + +Observer + +Example +8 + + +interface +defines +the +callbacks +needed +to +handle +an + +Observable +:

+7.2 + + +The + +: +Create + + +Subscription + +interface +

+Contains +the + +closed + +property +of +type + +boolean + +that +tells +if +the +subscription +is +closed +or +active. +

+Also, +contains +the + +unsubscribe + +() +method +that +cancels +the +subscription, +i.e. +makes + +a +new +exposed +Thing + +request +to +the +underlying +platform +to +stop +receiving +data + +from +a +Thing +Description + +the +source, +and +sets +the + +closed + +property +to + +false +.

+7.3 + + +The + +let thingDescription = '{ + "name": "mySensor", + "description": { + "@context": [ + "http://w3c.github.io/wot/w3c-wot-td-context.jsonld", + "http://w3c.github.io/wot/w3c-wot-common-context.jsonld", + ], + "@type": [ "Thing" ], + "interaction": [ + // ... + ] + // ... + }' +}; +WoT.createExposedThing(thingDescription) + .then(function(thing) { + // properties, actions and events are added based on the TD + // ... +}); + + +Observable + + +interface +

+The + +Observable + +interface +enabled +subscribing +to +pushed +data +notifications +by +the + +subscribe + +() +method: +

+
+
+
+

+ +6. + +8. + + +Security +and +Privacy +

+
+
+ +Editor's +note + +
+

+Please +see +the + +WoT +Security +and +Privacy + +repository +for +work +in +progress +regarding +threat +models, +assets, +risks, +recommended +mitigations, +and +best +practices +for +security +and +privacy +for +systems +using +the +Web +of +Things. +Once +complete, +security +and +privacy +considerations +relevant +to +the +Scripting +API +will +be +summarized +in +this +section. +

+
+
+
+

+ +7. + +9. + + +Terminology +and +conventions +

+

+The +generic +WoT +terminology +is +defined +in +[ + + +WOT-ARCHITECTURE + + +]: + +Thing +, + +Thing +Description + +(in +short + +TD + +), + +Web +of +Things + +(in +short + + +WoT + + +), + +WoT +Interface +, + +Protocol +Bindings +, + +WoT +Runtime +, + +Consuming +a +Thing +Description +, + +Thing +Directory +, + +WoT +Interactions +, +Property +, + +Action +, + +Event + +etc. +

+Note +In +this +version +of +the +specification, +a +WoT +Runtime +is +assumed +to +run +scripts +that +uses +this +API +to +define +one +or +more +Thing +s +that +share +a +common +event +loop. +Script +deployment +methods +are +out +of +scope +of +this +version. +In +future +versions, +running +multiple +scripts +(as +modules) +may +be +possible, +and +script +deployment +MAY +be +implemented +using +a +manager +Thing +whose +Actions +permit +script +lifecycle +management +operations. + +

+ +JSON-LD + +is +defined +in +[ + + +JSON-LD + + +] +as +a +JSON +document +that +is +augmented +with +support +for +Linked +Data +by +providing +a + +@context + +property +with +a +defining +URI +. +

+

+The +terms + + +URL + + +and + + +URL +path + + +are +defined +in +[ + + +URL + + +]. +

+

+The +following +terms +are +defined +in +[ + +HTML5 + + +HTML52 + + + +] +and +are +used +in +the +context +of +browser +implementations: + + +browsing +context + +, + + +top-level +browsing +context + +, + + +global +object + +, + + +incumbent +settings +object + +, + + +Document + +, + + +document +base +URL + +, + + +Window + +, + + +WindowProxy + +, + + +origin + +, + + +ASCII +serialized +origin + +, +executing +algorithms + + +in +parallel + +, + + +queue +a +task + +, + + +task +source + +, + + +iframe + +, + + +valid +MIME +type + +. +

+

+A + +browsing +context + +refers +to +the +environment +in +which + +Document + +objects +are +presented +to +the +user. +A +given + +browsing +context + +has +a +single + + +WindowProxy + + +object, +but +it +can +have +many + + +Document + + +objects, +with +their +associated + + +Window + + +objects. +The + +script +execution +context + +associated +with +the + +browsing +context + +identifies +the +entity +which +invokes +this +API, +which +can +be +a + +web +app +, +a + +web +page +, +or +an + +iframe +. +

+

+The +term + + +secure +context + + +is +defined +in +[ + + +WEBAPPSEC + + +]. +

+

+ + +Error +, + +EvalError +, + +RangeError +, + +ReferenceError +, + +SyntaxError +, + +TypeError +, + +URIError + + +, + + +script +execution +context + +, + + +Promise + +, + + +JSON + +, + + +JSON.stringify + + +and + + +JSON.parse + + +are +defined +in +[ + + +ECMASCRIPT + + +]. +

+

+ + +DOMString + +, + + +USVString + +, + + +ArrayBuffer + +, + + +BufferSource + + +and + + +any + + +are +defined +in +[ + + +WEBIDL + + +]. +

+

+The +term +event +and +the +Event +object +are +defined +in +DOM +and +Node.js +. +Note +This +specification +uses +the +convention +that +an +event +listener +will +receive +an +Event +object. +This +should +work +both +in +a +browser +environment +and +in +a +Node.js +like +environment. +Observable +s +are +proposed +to +be +included +in +ECMAScript. +The + +algorithms + + +utf-8 +encode + +, +and + + +utf-8 +decode + + +are +defined +in +[ + + +ENCODING + + +]. +

+

+ +IANA +media +type + +s +(formerly +known +as +MIME +types) +are +defined +in + +RFC2046 +. +

+

+The +terms + +hyperlink +reference + +and + +relation +type + +are +defined +in +[ + +HTML52 + +] +and + +RFC8288 +.

+
+
+

+ +8. + +10. + + +Conformance +

+

+As +well +as +sections +marked +as +non-normative, +all +authoring +guidelines, +diagrams, +examples, +and +notes +in +this +specification +are +non-normative. +Everything +else +in +this +specification +is +normative. +

+

+The +key +words + +MAY +, + +MUST +, +and + +SHOULD + +are +to +be +interpreted +as +described +in +[ + + +RFC2119 + + +]. +

+

+This +document +defines +conformance +criteria +that +apply +to +a +single +product: +the + +UA + +(user +agent) +that +implements +the +interfaces +it +contains. +

+

+This +specification +can +be +used +for +implementing +the +WoT +Scripting +API +in +multiple +programming +languages. +The +interface +definitions +are +specified +in +[ + + +WEBIDL + + +]. +

+

+The +user +agent +(UA) +may +be +implemented +in +the +browser, +or +in +a +separate +runtime +environment, +such +as + +Node.js + +or +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 + + +]. +

+

+This +document +serves +a +general +description +of +the +WoT +Scripting +API. +Language +and +runtime +specific +issues +are +discussed +in +separate +extensions +of +this +document. +

+
+
+

+ +A. + +Changes +

+

+The +following +is +a +list +of +major +changes +to +the +document. +For +a +complete +list +of +changes, +see +the + +github +change +log +. +You +can +also +view +the + +recently +closed +bugs +. +

+ +
+
+

+ +B. + +Open +issues +

+

+The +following +problems +are +being +discussed +and +need +most +attention: +

+ +
+
+

+ +C. + +Acknowledgements +

+

+Special +thanks +to +former +editor +Johannes +Hund +(until +August +2017, +when +at +Siemens +AG) + +for +developing +this +specification. +Also, +the +editors +would +like +to +thank +Dave +Raggett, +Matthias +Kovatsch, +Michael +Koster +and +Michael +McCool +for +their +comments +and +guidance. +

+
+
+

+ +D. + +References +

+
+

+ +D.1 + +Normative +references +

+
+
+[ECMASCRIPT] +
+
+ + +ECMAScript +Language +Specification + +. +Ecma +International. +URL: + +https://tc39.github.io/ecma262/ + +
+
+[ENCODING] +
+
+ + +Encoding +Standard + + +. +Anne +van +Kesteren. +WHATWG. +Living +Standard. + +Kesteren; +Joshua +Bell; +Addison +Phillips. +W3C. +15 +December +2016. +W3C +Candidate +Recommendation. + +URL: +https://encoding.spec.whatwg.org/ + + +https://www.w3.org/TR/encoding/ + + +
+[HTML5] + +
+[HTML52] + +
+
+ + +HTML5 + +HTML +5.2 + + +. +Ian +Hickson; +Robin +Berjon; + +Steve +Faulkner; +Arron +Eicholz; + +Travis +Leithead; +Alex +Danilo; +Sangwhan +Moon; + +Erika +Doyle +Navara; +Theresa +O'Connor; +Silvia +Pfeiffer. + +Robin +Berjon. + +W3C. +28 +October +2014. + +14 +December +2017. + +W3C +Recommendation. +URL: +https://www.w3.org/TR/html5/ + + +https://www.w3.org/TR/html52/ + + +
+
+[JSON-LD] +
+
+ + +JSON-LD +1.0 + +. +Manu +Sporny; +Gregg +Kellogg; +Markus +Lanthaler. +W3C. +16 +January +2014. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/json-ld/ + +
+
+[RFC2119] +
+
+ + +Key +words +for +use +in +RFCs +to +Indicate +Requirement +Levels + +. +S. +Bradner. +IETF. +March +1997. +Best +Current +Practice. +URL: + +https://tools.ietf.org/html/rfc2119 + +
+
+[TYPESCRIPT] +
+
+ + +TypeScript +Language +Specification + +. +Microsoft. +1 +October +2012. +URL: + +https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md + +
+
+[URL] +
+
+ + +URL +Standard + +. +Anne +van +Kesteren. +WHATWG. +Living +Standard. +URL: + +https://url.spec.whatwg.org/ + +
+
+[WEBAPPSEC] +
+
+ + +Secure +Contexts + +. +W3C. +17 +July +2015. +URL: +https://w3c.github.io/webappsec/specs/powerfulfeatures + + +https://w3c.github.io/webappsec/specs/powerfulfeatures/ + + +
+
+[WEBIDL] +
+
+ + +Web +IDL + +. +Cameron +McCormack; +Boris +Zbarsky; +Tobie +Langel. +W3C. +15 +December +2016. +W3C +Editor's +Draft. +URL: + +https://heycam.github.io/webidl/ + +
+
+[WOT-ARCHITECTURE] +
+
+ + +Web +of +Things +Architecture + +. +W3C. +14 +September +2017. +URL: + +https://www.w3.org/TR/2017/WD-wot-architecture-20170914/ +

+D.2 + +Informative +references +

+[WOT-TD] +
+WoT +Thing +Description + +. +W3C. + +20 +August +2017. +URL: +https://w3c.github.io/wot-architecture/ + + +https://www.w3.org/TR/2018/WD-wot-thing-description-20180405/ + + +
+
+
+
+ + + + diff --git a/releases/wd3/Overview.html b/releases/wd3/Overview.html new file mode 100644 index 00000000..60d57b03 --- /dev/null +++ b/releases/wd3/Overview.html @@ -0,0 +1,5747 @@ + + + + + + + + + + + Web of Things (WoT) Scripting API + + + + + + + + +
+ +

Web of Things (WoT) + Scripting API

+

W3C Working + Draft

+
+
This version:
+
+ + https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/ +
+
Latest published version:
+
+ https://www.w3.org/TR/wot-scripting-api/ +
+
Latest editor's draft:
+
+ https://w3c.github.io/wot-scripting-api/ +
+
Previous version:
+
+ + https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ +
+
Editors:
+
+ Zoltan Kis (Intel) +
+
+ Kazuaki Nimura (Fujitsu Ltd.) +
+
+ Daniel Peintner (Siemens AG) +
+
Johannes Hund (Former Editor, when at + Siemens AG)
+
Contributors:
+
+ + In the GitHub repository +
+
Repository:
+
+ We are + on GitHub +
+
+ File a + bug +
+
+ +
+
+
+

Abstract

+

The overall Web of Things (WoT) concepts are + described in the WoT Architecture + document. The Web of Things is made of entities (Things) that can describe their capabilities in a + machine-interpretable format, the 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.

+

This specification describes a programming interface + representing the WoT Interface that + allows scripts run on a Thing to discover and + consume (retrieve) other Thing Descriptions + and to expose Things characterized by WoT Interactions specified by a script.

+

Scripting is an optional "convenience" building block in WoT + and it is typically used in gateways 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 like + Thing Directory.

+
+
+

Status of This Document

+

This section describes the status of this document at + the time of its publication. Other documents may supersede this + document. A list of current W3C publications and the + latest revision of this technical report can be found in the + W3C technical reports + 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.

+
+
+ Editor's note: The W3C WoT WG is asking for + feedback +
+

Please contribute to this draft using the + GitHub + Issue feature 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 + a Working Draft. This document is intended to become a W3C + Recommendation.

+

Comments regarding this document are welcome. Please send + them to public-wot-wg@w3.org + (subscribe, + archives).

+

Changes from the previous publication can be found in + Appendix A. A diff-marked version of this document is also + available for comparison purposes.

+

Publication as a Working Draft does not imply endorsement by + the W3C + Membership. This is a draft document and may be updated, + replaced or obsoleted by other documents at any time. It is + inappropriate to cite this document as other than work in + progress.

+

This document was produced by a group operating under the + 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 1 February 2018 + W3C Process + Document.

+
+ +
+ +

1. + Introduction

+

WoT provides layered interoperability based on how Things are modeled: as being "consumed" and + "exposed".

+

By consuming a TD, a client Thing creates a runtime resource model that allows + accessing the Properties, Actions and + Events exposed by the server Thing exposed on a + remote device.

+

Exposing a Thing requires defining a Thing Description (TD) and instantiating a software + stack to serve requests for accessing the exposed Properties, Actions and Events. This specification describes how to expose + and consume Things by a script.

+
+
+ Note +
+

Typically scripts are meant to be used on devices + able to provide resources (with a WoT Interface) for managing (installing, updating, + running) scripts, such as bridges or gateways that expose and + control simpler devices as WoT Things.

+
+
+
+ Note +
+

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.

+
+

For an introduction on how scripts could be used in Web of Things, check the Primer + document. For some background on API design decisions check the + Rationale + document.

+
+
+ +

2. Use + Cases

+

This section is non-normative.

+

The following scripting use cases are supported in this + specification:

+
+

2.1 + Discovery

+ +
+
+

2.2 Consuming a Thing

+ +
+
+

2.3 + Exposing a Thing

+ +
+
+
+ +

3. The + WoT + object

+

The WoT object is the API entry point and it is exposed by + an implementation of the WoT Runtime. The + WoT object + does not expose properties, only methods for discovering, + consuming and exposing a Thing.

+
+
+ Note +
+

Browser implementations SHOULD use a namespace object such as + navigator.wot. Node.js-like runtimes MAY provide the API object through + the require() or + + import mechanism.

+
+
+
// [SecureContext]
+// [NamespaceObject]
+interface WoT {
+  Observable discover(optional ThingFilter filter);
+  Promise<ThingDescription> fetch(USVString url);
+  ConsumedThing consume(ThingDescription td);
+  ExposedThing produce(ThingModel model);
+  Promise<void> register(USVString directory, ExposedThing thing);
+  Promise<void> unregister(USVString directory, ExposedThing thing);
+};
+typedef object ThingFragment;
+typedef object PropertyFragment;
+typedef object ActionFragment;
+typedef object EventFragment;
+typedef object DataSchema;
+typedef object SecurityScheme;
+typedef object Link;
+typedef object Form;
+typedef USVString ThingDescription;
+typedef (ThingFragment or ThingDescription) ThingModel;
+
+
+
+ Editor's note +
+

The algorithms for the WoT methods will be + specified later, including error handling and security + considerations.

+
+

The ThingModel type represents + either a ThingFragment, or a + ThingDescription.

+
+

3.1 The discover() + method

+

Starts the discovery process that will provide ThingDescriptions that match the + optional argument filter of type ThingFilter. Returns an + [Observable](https://github.com/tc39/proposal-observable) + object that can be subscribed to and unsubscribed from. The + handler function provided to the Observable during + subscription will receive an argument of type + USVString representing a ThingDescription.

+
+

+ 3.1.1 The DiscoveryMethod + enumeration

+
+
typedef DOMString DiscoveryMethod;
+
+

DiscoveryMethod + represents the discovery type to be used:

+
    +
  • "any" + does not provide any restriction
  • +
  • + "local" + for discovering Things defined + in the same device or connected to the device by wired + or wireless means. +
  • +
  • + "directory" for discovery based + on a service provided by a Thing Directory. +
  • +
  • + "multicast" for discovering + Things in the device's network + by using a supported multicast protocol. +
  • +
+
+
+

3.1.2 The ThingFilter + dictionary

+

The ThingFilter + dictionary that represents the constraints for discovering + Things as key-value pairs.

+
+
dictionary ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  USVString? url;
+  USVString? query;
+  ThingFragment? fragment;
+};
+
+

The method + property represents the discovery type that should be used + in the discovery process. The possible values are defined + by the DiscoveryMethod enumeration + that MAY be extended + by string values defined by solutions (with no guarantee of + interoperability).

+

The url property + represents additional information for the discovery method, + such as the URL of the target entity serving the discovery + request, for instance a Thing + Directory (if method is + "directory") or a Thing (otherwise).

+

The query + property represents a query string accepted by the + implementation, for instance a SPARQL or JSON query. + Support may be implemented locally in the WoT Runtime or remotely as a service in a + Thing Directory.

+

The fragment property + represents a ThingFragment dictionary used for + matching property by property against discovered Things.

+
+

The discover(filter) method MUST run the following steps:

+
    +
  1. If invoking discover() is not allowed for + the current scripting context for security reasons, throw + SecurityError and terminate these steps.
  2. +
  3. Return an Observable obs and + execute the next steps in parallel. +
  4. +
  5. If obs.subscribe(handler, errorHandler, + complete) is called, execute the following + sub-steps: +
      +
    1. If the first argument handler is not + defined or it is not a function, throw + TypeError and terminate the algorithm. + Otherwise configure handler to be invoked + when a discovery hit happens.
    2. +
    3. If the second argument errorHandler is + defined, but it is not a function, throw + TypeError and terminate these steps. + Otherwise if defined, save it to be invoked in error + conditions.
    4. +
    5. If the third argument onComplete is + defined, but it is not a function, throw + TypeError and terminate these steps. + Otherwise if defined, save it to be invoked when the + discovery process finished for other reasons than + having been canceled.
    6. +
    7. If filter.query is defined, pass it as + an opaque string to the underlying implementation to be + matched against discovered items. The underlying + implementation is responsible to parse it e.g. as a + SPARQL or JSON query and match it against the + Thing Descriptions found + during the discovery process. If queries are not + supported, implementations SHOULD throw a + NotSupported error and terminate these + steps. +
    8. +
    9. If filter.fragment is defined, and if it + contains other properties than the ones defined in + ThingFragment, + throw TypeError and terminate these steps. + Otherwise save the object for matching the discovered + items against it. +
    10. +
    11. Request the underlying platform to start the + discovery process, with the following parameters: +
        +
      • If filter.method is not defined or + the value is "any", use the widest + discovery method supported by the underlying + platform.
      • +
      • Otherwise if filter.method is + "local", use the local Thing Directory for + discovery. Usually that defines Things deployed in the same device, or + connected to the device in slave mode (e.g. + sensors connected via Bluetooth or a serial + connection). +
      • +
      • Otherwise if filter.method is + "directory", use the remote Thing Directory + specified in filter.url. +
      • +
      • Otherwise if filter.method is + "multicast", use all the multicast + discovery protocols supported by the underlying + platform.
      • +
      +
    12. +
    +
  6. +
  7. Whenever a new item td is discovered by the + underlying platform, run the following sub-steps: +
      +
    1. If filter.query is defined, check if + td is a match for the query. The matching + algorithm is encapsulated by implementations. If that + returns false, discard td and + continue the discovery process.
    2. +
    3. If filter.fragment is defined, for each + property defined in it, check if that property exists + in td and has the same value. If this is + false in any checks, discard td + and continue the discovery process.
    4. +
    5. Otherwise if td has not been discarded + in the previous steps, invoke the handler + function with td as parameter.
    6. +
    +
  8. +
  9. Whenever an error occurs during the discovery process, + and if errorHandler is defined, invoke it with + an argument of type Error whose + message property is set to + UnknownError unless there was an error code + provided by the Protocol Bindings, + in which case set it to that value. +
  10. +
  11. When the discovery process is finished, and if + onComplete is defined, invoke it run the + cancel discovery steps. +
  12. +
  13. When the obs.unsubscribe() method is + called, run the following cancel discovery steps: +
      +
    1. Request the underlying platform to stop the + discovery process. If this returns an error, or if it + is not possible, for instance when discovery is based + on open ended multicast requests, the implementation + SHOULD discard + subsequent discovered items.
    2. +
    3. Set obs.closed to + false.
    4. +
    +
  14. +
+
+
+

3.2 + The fetch() + method

+

Accepts an url argument of type + USVString that represents a URL (e.g. + "file://..." or "https://...") and + returns a Promise that resolves with a + ThingDescription (a + serialized JSON-LD document of type + USVString).

+

The fetch(url) method MUST run the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If invoking fetch() is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. If the argument url is not a URL, reject + promise with TypeError and + terminate these steps.
  6. +
  7. Make a request to fetch the content of url + as described by the Protocol + Bindings and wait for the reply. Implementations + encapsulate the fetching process and the accepted media + types (such as application/td+json), as far + as a valid Thing Description + can be obtained as defined in [WOT-TD]. Let td + be the Thing Description + string-serialized from the returned content, as specified + in the + Thing Description serialization. +
  8. +
  9. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  10. +
  11. Otherwise resolve promise with td + and terminate these steps.
  12. +
+
+
+

3.3 The consume() + method

+

Accepts an td argument of type ThingDescription and returns a + ConsumedThing object + instantiated based on parsing that description.

+

The consume(td) method must run the following + steps:

+
    +
  1. If the argument td is not a string, throw a + TypeError and terminate these steps.
  2. +
  3. Let stub be the result of running the + TD parsing algorithm with + td as argument. If that throws an error, + re-throw the error and terminate these steps. +
  4. +
  5. If stub does not have an own property that + is defined in ThingFragment with a default value, + add that property and value to stub. +
  6. +
  7. Create a ConsumedThing object + thing initialized from stub that + implements Observable. +
  8. +
  9. Add the read() and write() + methods to the ThingProperty elements so that they + make requests to access the remote Things and + wait for the reply, as defined by the Protocol Bindings. Also, all + ThingProperty + elements SHOULD + implement Observable, i.e. + define a subscribe() method that should make + request to observe the given Properties + as defined by the Protocol Bindings. +
  10. +
  11. Add the invoke() methods to the ThingAction elements so that they + make requests to the remote Thing to invoke its + actions, as defined by the Protocol + Bindings. +
  12. +
  13. Add the subscribe() method to all + ThingEvent elements + so that they make requests to subscribe to the events + defined by the remote Thing, as defined + by the Protocol Bindings. +
  14. +
  15. Return thing.
  16. +
+
+
+

3.4 The produce() + method

+

Accepts a model argument of type + ThingModel and + returns an ExposedThing + object.

+

The produce(model) method MUST run the following steps:

+
    +
  1. If invoking produce() is not allowed for + the current scripting context for security reasons, throw + SecurityError and terminate these steps.
  2. +
  3. If the argument model is a string, then run + the TD parsing algorithm with model + passed as parameter. If it throws an error, re-throw that + error and terminate this algorithm. Otherwise let + model be the returned value.
  4. +
  5. If model is not an object, throw + TypeError and terminate these steps.
  6. +
  7. If model does not have an own property that + is defined in ThingFragment with a default value, + add that property and value to model. +
  8. +
  9. Create an ExposedThing object thing + initialized from model. +
  10. +
  11. For each property of ExposedThing defined in ThingFragment, initialize the + property based on the provided initial or default values + provided to the local WoT Runtime + implementation, for instance initialize: +
      +
    1. the id property to be the final unique + identifier of the Thing, +
    2. +
    3. the security object of type SecurityScheme to + represent the actual security scheme and its properties + as set up by the implementation, +
    4. +
    5. the properties property to be an + object with all properties being ThingProperty + objects in which the read() and + write() methods are provided to define + local methods to get and set the Property values, +
    6. +
    7. the actions property to be an object + with all properties being ThingAction objects in which the + invoke() method is provided to define a + local method to run the defined Actions, +
    8. +
    9. the events property to be an object + with all properties being ExposedEvent objects in which + the emit() method is provided to define a + local way to trigger sending notifications to all + subscribed clients, +
    10. +
    11. and initialize the other properties as initialized + from model.
    12. +
    13. Return thing.
    14. +
    +

    The TD parsing algorithm + takes a string td as argument and runs the + following steps:

    +
      +
    1. Parse td according to the + WoT Thing Description in order to produce a + JSON + object json. Update thing + with the properties and values defined in + json. +
    2. +
    3. If there was an error during the parsing, throw + that error and terminate these steps.
    4. +
    5. Otherwise return json.
    6. +
    +
  12. +
+
+
+

3.5 The register() + method

+

Takes two mandatory arguments:

+ +

Generate the Thing Description as + td, given the Properties, Actions and Events defined for + this ExposedThing object. + Then make a request to register td to the given + WoT Thing Directory.

+
+
+

3.6 The + unregister() method

+

Takes two mandatory arguments:

+ +

Makes a request to unregister the thing from + the given WoT Thing Directory.

+
+
+

3.7 + Examples

+
+
+ Example + 1: Discover Things via + directory +
+
let discoveryFilter = {
+  method: "directory",
+  url: "http://directory.wotservice.org"
+};
+let subscription = wot.discover(discoveryFilter).subscribe(
+  td => {
+    console.log("Found Thing " + td.name);
+    // fetch the TD and create a ConsumedThing
+    let thing = wot.consume(td);
+  },
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout( () => {
+    subscription.unsubscribe();
+    console.log("Discovery timeout");
+  },
+  5000);
+
+
+
+ Example + 2: Discover Things + exposed by local hardware +
+
let subscription = wot.discover({ method: "local" }).subscribe(
+  td => { console.log("Found local Thing " + td.name); },
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+ + Example 3: Same as above + but with different Observable syntax +
+
let subscription = wot.discover({ method: "local" }).subscribe({
+  td => { console.log("Found local Thing " + td.name); },
+  error: err => { console.log("Discovery error: " + err.message); },
+  complete: () => { console.log("Discovery finished successfully");}
+});
+
+
+
+
+ +

4. The ConsumedThing + interface

+

Represents an object that extends a ThingFragment with methods for client + interactions (send request for reading and writing Properties), invoke Actions, subscribe and + unsubscribe for Property changes and Events.

+
+
interface ConsumedThing : ThingFragment {
+  readonly attribute DOMString id;
+  readonly attribute DOMString name;
+  readonly attribute DOMString? base;
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute EventMap events;
+  // getter for ThingFragment properties
+  getter any (DOMString name);
+};
+[NoInterfaceObject]
+interface PropertyMap {
+  readonly maplike<DOMString, ThingProperty>;
+};
+[NoInterfaceObject]
+interface ActionMap {
+  readonly maplike<DOMString, ThingAction>;
+};
+[NoInterfaceObject]
+interface EventMap {
+  readonly maplike<DOMString, ThingEvent>;
+};
+ConsumedThing includes Observable;  // for TD changes
+
+

The id attribute + represents the unique identifier of the Thing instance, + typically a URI, IRI, or URN as USVString.

+

The name attribute + represents the name of the Thing as + DOMString.

+

The base attribute + represents the base URI that is valid for all defined local + interaction resources.

+

The properties + attribute represents a dictionary of ThingProperty items. The + PropertyMap interface + represents a maplike dictionary where all values are ThingProperty objects. The + read() and write() methods make a + request to access the Properties on the remote + Thing represented by this ConsumedThing proxy object.

+

The actions + attribute represents a dictionary of ThingAction items. The + ActionMap interface represents a + maplike dictionary where all values are ThingAction objects. The + invoke() method represents a request to invoke the + Action on the remote Thing.

+

The events + attribute represents a dictionary of ThingEvent items. The EventMap interface + represents a maplike dictionary where all values are ThingEvent objects. Subscribing to the + events involves setting up an observation (subscription) + mechanism on the remote object.

+
+

4.1 + Examples

+

Below a ConsumedThing interface example + is given.

+
+
+ Example + 4: Consume a Thing +
+
try {
+  let subscription = wot.discover({ method: "local" }).subscribe(
+    td => {
+      let thing = wot.consume(td);
+      console.log("Thing " + thing.name + " has been consumed.");
+      let subscription = thing["temperature"].subscribe(function(value) {
+          console.log("Temperature: " + value);
+        });
+      thing.actions["startMeasurement"].invoke({ units: "Celsius" })
+        .then(() => { console.log("Temperature measurement started."); })
+        .catch(e => {
+           console.log("Error starting measurement.");
+           subscription.unsubscribe();
+         })
+    },
+    error => { console.log("Discovery error: " + error.message); },
+    () => { console.log("Discovery finished successfully");}
+  );
+} catch(error) {
+  console.log("Error: " + error.message);
+};
+
+
+
+
+ +

5. The ExposedThing + interface

+

The ExposedThing interface is + the server API that allows defining request handlers, + properties, Actions, and Events to a + Thing. It also implements the Observable interface. An ExposedThing is created by the produce() method.

+
+
interface ExposedThing : ThingFragment {
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute ExposedEvents events;
+  // getter for ThingFragment properties
+  getter any (DOMString name);
+  // setter for ThingFragment properties
+  setter void (DOMString name, any value);
+  // methods to expose and destroy the Thing
+  Promise<void> expose();
+  Promise<void> destroy();
+  // define Properties
+  ExposedThing addProperty(DOMString name, PropertyFragment property, optional any initValue);
+  ExposedThing setPropertyReadHandler(DOMString name, PropertyReadHandler readHandler);
+  ExposedThing setPropertyWriteHandler(DOMString name, PropertyWriteHandler writeHandler);
+  ExposedThing removeProperty(DOMString name);
+  // define Actions
+  ExposedThing addAction(DOMString name, ActionFragment init, ActionHandler action);
+  ExposedThing removeAction(DOMString name);
+  ExposedThing setActionHandler(DOMString name, ActionHandler action);
+  // define Events
+  ExposedThing addEvent(DOMString name, EventFragment event);
+  ExposedThing removeEvent(DOMString name);
+};
+[NoInterfaceObject]
+interface ExposedEvents {
+  maplike<DOMString, ExposedEvent>;
+};
+callback PropertyReadHandler = Promise<any> ();
+callback PropertyWriteHandler = Promise<void> (any value);
+callback ActionHandler = Promise<any> (any parameters);
+
+

The properties + attribute represents a dictionary of ThingProperty items in which the + read() and write() methods define + local methods that access the physical representations of the + Properties.

+

The actions + attribute represents a dictionary of ThingAction items in which the + invoke() method represents a local method to + invoke the Action.

+

The events + attribute represents a dictionary of ExposedEvent items that add the + emit() method to the ThingEvent definition. The + ExposedEvents interface + represents a maplike dictionary where all values are ExposedEvent objects.

+
+

5.1 The + expose() method

+

Start serving external requests for the Thing, so that WoT Interactions + using Properties, Actions and + Events will be possible.

+

The expose() method MUST run the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If invoking expose() is not allowed for + the current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform to attach + protocol handlers and start serving external requests for + WoT Interactions (read, write and + observe Properties, invoke Actions and manage Event + subscriptions), based on the Protocol Bindings. +
  6. +
  7. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  8. +
  9. Otherwise resolve promise with td + and terminate these steps.
  10. +
+
+
+

5.2 The + destroy() method

+

Stop serving external requests for the Thing and destroy the object. Note that eventual + unregistering should be done before invoking this method.

+

The destroy() method MUST run the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If invoking destroy() is not allowed for + the current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform to stop + serving external requests for WoT Interactions, based on the + Protocol Bindings. +
  6. +
  7. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  8. +
  9. Otherwise resolve promise with td + and terminate these steps.
  10. +
+
+
+

5.3 The + addProperty() method

+

Adds a Property with name defined by the + name argument, the data schema provided by the + property argument of type PropertyFragment, and optionally an + initial value provided in the argument initValue + whose type should match the one defined in the + type property according to the value-matching algorithm. If + initValue is not provided, it SHOULD be initialized as + undefined. Implementations SHOULD update the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.4 The + removeProperty() method

+

Removes the Property specified by the + name argument and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.5 The + addAction() method

+

Adds to the actions property of a Thing object an Action with name + defined by the name argument, defines input and + output data format by the init argument of type + ActionFragment, and + adds the function provided in the action argument + as a handler, then updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+

The provided action callback function will + implement invoking an Action and SHOULD be called by + implementations when a request for invoking the Action is received from the underlying platform. + The callback will receive a parameters + dictionary argument according to the definition in the + init.input argument and will return a value of + type defined by the init.output argument according + to the value-matching + algorithm.

+

There SHOULD be + exactly one handler for any given Action. If no + handler is initialized for any given Action, + implementations SHOULD throw a TypeError.

+
+
+

5.6 The + removeAction() method

+

Removes the Action specified by the + name argument and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.7 The + addEvent() method

+

Adds an event with name defined by the name + argument and qualifiers and initialization value provided by + the event argument of type EventFragmentto the Thing object and updates the Thing Description. Throws on error. Returns a + reference to the same object for supporting chaining.

+
+
+

5.8 The + removeEvent() method

+

Removes the event specified by the name + argument and updates the Thing + Description. Returns a reference to the same object for + supporting chaining.

+
+
+

5.9 The PropertyReadHandler + callback

+

A function that is called when an external request for + reading a Property is received. It should + return a Promise and resolves it with the value of the + Property matching the name argument to + the setPropertyReadHandler function, or rejects + with an error if the property is not found or the value + cannot be retrieved.

+
+
+

5.10 The PropertyWriteHandler + callback

+

A function that is called when an external request for + writing a Property is received. It is given + the requested new value as argument and should + return a Promise which is resolved when the value of the + Property that matches the name + argument has been updated with value, or rejects + with an error if the property is not found or the value + cannot be updated.

+
+
+ Editor's note +
+

Note that this function is invoked by + implementations before the property is updated and it + actually defines what to do when a write request is + received. The code in this callback function can invoke the + read() method to find out the old value of the + property, if needed. Therefore the old value is not + provided to this function.

+
+
+
+

5.11 The ActionHandler + callback

+

A function called with a parameters + dictionary argument assembled by the WoT runtime based on the Thing Description and the external client request. + It returns a Promise that rejects with an error or resolves + if the action is successful or ongoing (may also resolve with + a control object such as an Observable for actions that need + progress notifications or that can be canceled).

+
+
+

5.12 The + setPropertyReadHandler() method

+

Takes name as string argument and + readHandler as argument of type PropertyReadHandler. + Sets the handler function for reading the specified Property matched by name. Throws on + error. Returns a reference to the same object for supporting + chaining.

+

The readHandler callback function will + implement reading a Property and + SHOULD be called by + implementations when a request for reading a Property is received from the underlying + platform.

+

There SHOULD be at + most one handler for any given Property and + newly added handlers replace the old handlers. If no handler + is initialized for any given Property, + implementations SHOULD implement a default property read + handler.

+

When an external request for reading Property propertyName is received, the + runtime SHOULD + execute the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If a Property with + propertyName does not exist, reject promise with a ReferenceError and + terminate these steps. +
  4. +
  5. Otherwise, if no read handler has been defined for + propertyName, resolve promise with + the value of the Property named + propertyName provided by the runtime implementation + and terminate these steps. +
  6. +
  7. Otherwise, invoke the read handler associated with + propertyName. If it rejects, then reject + promise with the same error, and resolve + promise with the same value. +
  8. +
+
+
+

+ 5.13 The + setPropertyWriteHandler() method

+

Takes name as string argument and + writeHandler as argument of type PropertyWriteHandler. + Sets the handler function for writing the specified Property matched by name. Throws on + error. Returns a reference to the same object for supporting + chaining.

+

There SHOULD be at + most one write handler for any given Property and newly added handlers replace the old + handlers. If no write handler is initialized for any given + Property, implementations SHOULD implement default property update + and notifying observers on change.

+

When an external request for writing a Property propertyName with a new value + value is received, the runtime SHOULD execute the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If a Property with + propertyName does not exist, reject promise with a ReferenceError and + terminate these steps. +
  4. +
  5. Otherwise, if no write handler has been defined for + propertyName, the runtime implementation + SHOULD update the + Property value with + value, resolve promise and terminate + these steps. +
  6. +
  7. Otherwise, invoke the write handler associated with + propertyName providing value as + argument. If it rejects, then reject promise + with the same error, and resolve promise with + the same value. +
  8. +
+
+
+

5.14 The + setActionHandler() method

+

Takes name as string argument and + action as argument of type ActionHandler. Sets the handler + function for the specified Action matched by + name. Throws on error. Returns a reference to + the same 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 SHOULD be at + most one handler for any given Action and newly added + handlers replace the old handlers.

+

When an external request for invoking the Action identified by name is received, + the runtime SHOULD + execute the following steps:

+
    +
  1. Return a Promise promise and + execute the next steps in parallel. +
  2. +
  3. If an Action identified by + name does not exist, reject promise with a ReferenceError and + terminate these steps. +
  4. +
  5. Otherwise, if no action handler has been defined for + name, reject promise with a + ReferenceError and terminate these steps. +
  6. +
  7. Otherwise, invoke the Action handler + associated with name. If it rejects with + error, then reject promise with the + same error, otherwise if it resolves with + value, then resolve promise with the + same value. +
  8. +
+
+
+

5.15 + Examples

+

Below some ExposedThing interface examples + are given.

+
+
+ + Example 5: Create a new + exposed Thing with a simple property +
+
+        try {
+  var temperatureValueDefinition = {
+    type: "number",
+    minimum: -50,
+    maximum: 10000
+  };
+  var temperaturePropertyDefinition = temperatureValueDefinition;
+  // add the 'forms' property
+  temperaturePropertyDefinition.forms = [ ... ];
+  var thing = WoT.produce({
+    name: "tempSensor",
+    properties: {
+      temperature: temperaturePropertyDefinition
+    },
+    actions: {
+      reset: {
+        description: "Reset the temperature sensor",
+        input: {
+          temperature: temperatureValueDefinition
+        },
+        output: null,
+        forms: []
+      },
+    },
+    events: {
+      onchange: temperatureValueDefinition
+    },
+    links: []
+  });
+  await thing.expose();
+  await wot.register("https://mydirectory.org", thing);
+  // define Thing business logic
+  setInterval( async () => {
+    let mock = Math.random()*100;
+    let old = await thing["temperature"].read();
+    if (old < mock) {
+      await thing["temperature"].write(mock);
+      thing.emitEvent("onchange", mock);
+    }
+  }, 1000);
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ Example + 6: Create a new exposed + Thing with object property +
+
+        try {
+  var 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
+        }
+      }
+  };
+  var statusPropertyDefinition = statusValueDefinition;
+  // add the 'forms' property
+  statusPropertyDefinition["forms"] = [];
+  var thing = WoT.produce({
+    name: "mySensor",
+    properties: {
+      brightness: {
+        type: "number",
+        minimum: 0.0,
+        maximum: 100.0,
+        required: true,
+      },
+      status: statusPropertyDefinition
+    },
+    actions: {
+      status: {
+        description: "Get status object",
+        input: null,
+        output: {
+          status : statusValueDefinition;
+        },
+        forms: []
+      },
+    },
+    events: {
+      onstatuschange: statusValueDefinition;
+    },
+    links: []
+  });
+  thing.expose().then(() => {
+      thing.register();
+  });
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ + Example 7: Create a new + exposed Thing from a Thing Description +
+
+        let thingDescription = '{ \
+  "name": "mySensor", \
+  "@context": [ "http://www.w3.org/ns/td",\
+     "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ],\
+  "@type": [ "Thing", "Sensor" ], \
+  "geo:location": "testspace", \
+  "properties": { \
+    "prop1": { \
+      "type": "number",\
+      "@type": [ "Property", "Temperature" ], \
+      "saref:TemperatureUnit": "degree_Celsius" \
+  } } }';
+try {
+  // note that produce() fails if thingDescription contains error
+  let thing = WoT.produce(thingDescription);
+  // Interactions were added from TD
+  // WoT adds generic handler for reading any property
+  // define a specific handler for one property
+  let name = "examplePropertyName";
+  thing.setPropertyReadHandler(name, () => {
+    console.log("Handling read request for " + name);
+    return new Promise((resolve, reject) => {
+        let examplePropertyValue = 5;
+        resolve(examplePropertyValue);
+      },
+      e => {
+        console.log("Error");
+      });
+  });
+  thing.expose();
+} catch(err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+ Example + 8: Create a new exposed + Thing from a TD URI +
+
+        // fetch an external TD, e.g., to set up a proxy for that Thing
+WoT.fetch("http://myservice.org/mySensor/description").then(td => {
+  // WoT.produce() ignores instance-specific metadata (security, form)
+  let thing = WoT.produce(td);
+  // Interactions were added from TD
+  // add server functionality
+  // ...
+});
+
+
+
+
+ +

6. Data types and structures

+

The [WOT-TD] specification defines the + + WoT information model, i.e. the data types and data + structures used in WoT Interactions. In + this API these definitions translate to dictionary objects that + are extended with methods by the interfaces defined in this + specification.

+

In order to avoid duplication of definitions, references to + these data types and structures is defined in this section, but + for their full description please refer to the Thing + Description specification.

+
+

+ 6.1 The DataSchema + dictionary and its subclasses

+

Value types basically represent types that may be used in + JSON object definitions and are used in ThingFragment to define Properties, Events and Action parameters. Value types are represented as + dictionary objects whose properties and possible sub-classes + are defined in the + DataSchema section of [WOT-TD].

+

One property of all DataSchema dictionary is the + type property whose value is from a set of + enumerated strings defined in the DataSchema + section of [WOT-TD] and is referred as + DataType in + this specification.

+

Based on type, the following sub-classes of + DataSchema are defined in + [WOT-TD]: BooleanSchema, NumberSchema, IntegerSchema, StringSchema, ObjectSchema, ArraySchema.

+
+
+

+ 6.2 The SecurityScheme dictionary + and its subclasses

+

Security metadata is represented as dictionary objects + whose properties and sub-classes are defined in the + SecurityScheme section of [WOT-TD].

+

One property of the SecurityScheme dictionary is the + scheme property whose value is from a set of + enumerated strings defined in the + SecurityScheme section of [WOT-TD]. Based on type, + multiple subclasses of SecurityScheme are defined.

+
+ +
+

6.4 The Form dictionary

+

Represents metadata describing service details, with + properties defined in the Form + section of [WOT-TD].

+
+
+

6.5 The InteractionFragment + dictionary

+

Represents the common properties of WoT Interactions, one of Property, + Action or Event, as defined in the + InteractionPattern section of [WOT-TD]. Its subclasses are + referred as PropertyFragment, ActionFragment and EventFragment.

+
+
+

6.6 The PropertyFragment + dictionary

+

Represents the Property interaction + data that initializes a ThingProperty object. Its properties + are defined in the Property + and + InteractionPattern sections of [WOT-TD].

+
+
+

6.7 The ActionFragment + dictionary

+

Represents the Action interaction data that + initializes a ThingAction object. Its + properties are defined in the Action + and + InteractionPattern sections of [WOT-TD].

+
+
+

6.8 The EventFragment + dictionary

+

Represents the Event interaction data that + initializes a ThingEvent object. Its + properties are defined in the Event + section of [WOT-TD].

+
+
+

6.9 The ThingFragment + dictionary

+

The ThingFragment + dictionary is defined as Thing + in [WOT-TD]. It is a dictionary that + contains properties representing semantic metadata and + interactions (Properties, Actions and + Events). It is used for initializing an internal + representation of a Thing Description and + its properties may be used in ThingFilter.

+
+
+

6.10 The ThingDescription + type

+

Serialized representation of the Thing Description (a JSON-LD document).

+
+
+ Note +
+

In this version of the API, Thing Descriptions are represented + as an opaque USVString that can be transmitted + between devices.

+
+
+
+
+ +

7. Interfaces for WoT Interactions

+

The data types and structures imported from [WOT-TD] are extended by + this specification in order to provide the interfaces for + WoT Interactions.

+

Every Thing describes its metadata as + defined in ThingFragment, and basic + interactions defined as Properties, Actions and Events. The following interfaces are + used for representing these interactions.

+
+

7.1 The Interaction + interface

+

The Interaction interface + is an abstract class to represent Thing + interactions: Properties, Actions and + Events.

+

The InteractionFragment + dictionary holds the common properties of PropertyFragment, ActionFragment and EventFragment dictionaries used for + initializing ThingProperty, ThingAction and ThingEvent objects in a ThingFragment dictionary used for + creating an ExposedThing + object.

+
+
interface Interaction {
+  readonly attribute (Form or FrozenArray<Form>) forms;
+};
+Interaction includes InteractionFragment;
+
+

The forms read-only + property represents the protocol bindings initialization data + and is initialized by the WoT Runtime.

+
+
+

7.2 The ThingProperty + interface

+

The ThingProperty interface + is used in ConsumedThing and + ExposedThing objects to + represent Thing Property + interactions.

+

The PropertyFragment + dictionary is used for initializing Property objects + in a ThingFragment + dictionary used for creating an ExposedThing object. It MUST implement one of the + DataSchema dictionaries.

+
+
interface ThingProperty : Interaction {
+  // getter for PropertyFragment properties
+  getter any (DOMString name);
+  // get and set interface for the Property
+  Promise<any> read();
+  Promise<void> write(any value);
+};
+ThingProperty includes PropertyFragment;
+ThingProperty includes Observable;
+
+

The ThingProperty interface + contains all the properties defined on PropertyFragment as read-only + properties.

+

The type + read-only property represents the type definition for the + Property as a DataSchema dictionary object.

+

The writable read-only property tells + whether the Property value can be updated. If it + is false, then the set(value) + method SHOULD always + reject.

+

The observable read-only + property tells whether the Property supports + subscribing to value change notifications. If it is + false, then the subscribe() method + SHOULD always + fail.

+

The constant read-only property + - defined in DataSchema - tells + whether the Property value is a constant. If + true, the set() and + subscribe() methods SHOULD always fail.

+

The required read-only property + - defined in DataSchema - tells + whether the Property should be always present on + the ExposedThing + object.

+

The read() + method will fetch the value of the Property. + Returns a Promise that resolves with the + value, or rejects with an error.

+

The + write() method will attempt to set the value of + the Propertyspecified in the + value argument whose type SHOULD match the one specified by the + type property. Returns a Promise that + resolves on success, or rejects on an error.

+
+
+

7.3 The ThingAction + interface

+
+
interface ThingAction : Interaction {
+  Promise<any> invoke(optional any inputValue);
+};
+ThingAction includes ActionFragment;
+
+

The + invoke() method when invoked, starts the + Action interaction with the input value provided by + the inputValue argument. If inputValue + is null, the action does not take any arguments + and rejects if any arguments are provided. If the value is + undefined, the action will ignore any arguments + provided. Otherwise the type of inputValue + SHOULD match the + DataSchema definition in the + input property. Returns a Promise that + will reject with an error or will resolve with a value of + type defined by the output property.

+
+
+

7.4 The ThingEvent interface

+
+
interface ThingEvent : Interaction {
+};
+ThingEvent includes EventFragment;
+ThingEvent includes ThingProperty;
+
+

Since ThingEvent implements + Observable through the ThingProperty interface, event + subscription is done by invoking the subscribe() + method on the event object that returns a cancelable Subscription.

+
+
+

7.5 The ExposedEvent + interface

+
+
interface ExposedEvent : ThingEvent {
+  void emit(any payload);
+};
+
+
+

7.5.1 The emit() + method

+

Emits an event that carries data specified by the + payload argument.

+
+
+
+

7.6 The value-matching + algorithm

+

The value-matching algorithm is applied to a + value input in relation to a valueType + property of type DataSchema, for instance the + value and type properties of a + PropertyFragment + object, or the inputValue parameter to the + invoke() method of a ThingAction object in relation to the + same object. It executes the following steps:

+
    +
  1. If valueType.type is not defined, or does + not fully match a string enumerated in DataType, return false. +
  2. +
  3. Otherwise, if valueType.type is + "null": if value is + null, return true, otherwise + return false.
  4. +
  5. Otherwise, if valueType.type is + "boolean": if value is either + true or false, then return + true, otherwise return + false.
  6. +
  7. Otherwise, if valueType.type is + "integer": if value is not an + integer type defined by the underlying platform (such as + long or long long), then return + false, otherwise execute the following + sub-steps: +
      +
    1. If valueType.minimum is defined and + value is not greater or equal than that + value, return false.
    2. +
    3. If valueType.maximum is defined and + value is not less or equal than that value, + return false.
    4. +
    5. Return true.
    6. +
    +
  8. +
  9. Otherwise, if valueType.type is + "number", if value is not an + integer or floating point type defined by the underlying + platform (such as long or long + long or double), then return + false, otherwise otherwise execute the + following sub-steps: +
      +
    1. If valueType.minimum is defined and + value is not greater or equal than that + value, return false.
    2. +
    3. If valueType.maximum is defined and + value is not less or equal than that value, + return false.
    4. +
    5. Return true.
    6. +
    +
  10. +
  11. Otherwise, if valueType.type is + "string": if value is not a string + type defined by the underlying platform, then return + false, otherwise return true. In this + case the algorithm expects a third parameter + valueType.enum and runs the following + sub-steps: +
      +
    • If valueType.enum is an array of + strings, then if value fully matches one of + the strings defined in the array, return + true.
    • +
    • Otherwise, return false.
    • +
    +
  12. +
  13. Otherwise, if valueType.type is + "array", execute the following sub-steps: +
      +
    1. If value is not an array, return + false.
    2. +
    3. If valueType.minItems is defined, and + value does not contain at least + valueType.minItems elements, return + false.
    4. +
    5. If valueType.maxItems is defined, and + value contains more than + valueType.maxItems elements, return + false.
    6. +
    7. Otherwise, if valueType.items is + undefined, return false.
    8. +
    9. Otherwise, if valueType.items is + null, return true (i.e. any + type is accepted as array element, including + heterogenous arrays).
    10. +
    11. Otherwise, for each element of the array + value run the value-matching algorithm + against the valueType.items object. If any + of these runs returns false, then return + false. +
    12. +
    13. Otherwise, return true.
    14. +
    +
  14. +
  15. Otherwise, if type is "object", + execute the following sub-steps: +
      +
    1. If value is not an Object, + return false.
    2. +
    3. If valueType.properties is not defined, + return false.
    4. +
    5. If valueType.properties is + null, return true (i.e. + accept any object value).
    6. +
    7. For each string in the + valueType.required array, if it does not + match a property name in the + value.properties object or in the + value object, then return + false.
    8. +
    9. For each property with name propName and + value propDataSchema found in + valueType.properties, run the following + sub-steps: +
        +
      1. If the result of applying the value-matching algorithm + on the value value[propName] and + propDataSchema is false, + then return false. +
      2. +
      +
    10. +
    11. Return true.
    12. +
    +
  16. +
+
+
+
+ +

8. + Observables

+

This section is non-normative.

+

Observables are proposed to + be included in ECMAScript and are used for handling pushed data + associated with various possible sources, for instance events, + timers, streams, etc. A minimal required implementation is + described here.

+
+
+ Editor's note +
+

This section is informal and contains rather + laconic information for implementations on what to support + for interoperability.

+
+
+
interface Observable {
+  Subscription subscribe(EventHandler handler,
+                         optional ErrorHandler errorHandler,
+                         optional OnComplete onComplete);
+};
+interface Subscription {
+  void unsubscribe();
+  readonly attribute boolean closed;
+};
+callback EventHandler = void (any value);
+callback ErrorHandler = void (Error error);
+callback OnComplete = void ();
+
+

The following callbacks can be provided when subscribing to + an Observable:

+ +
+

8.1 The Subscription + interface

+

Contains the closed + property of type boolean that tells if the + subscription is closed or active.

+

Also, contains the unsubscribe() + method that cancels the subscription, i.e. makes a request to + the underlying platform to stop receiving data from the + source, and sets the closed property to + false.

+
+
+

8.2 The Observable interface

+

The Observable interface + enabled subscribing to pushed data notifications by the + subscribe() + method:

+ +
+
+
+ +

9. Security and + Privacy

+

In general the security measures taken to protect a WoT + system will depend on the threats and attackers that system may + face and the value of the assets needs to protect. 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-CONSIDERATIONS]. + This section includes only normative recommendations relevant + to the WoT Thing Description.

+

When designing new devices and services + for use with the WoT, we have documented a set of best + practices in [WOT-SECURITY-BEST-PRACTICES] + that SHOULD be + followed. This best-practices document may be updated as + security measures evolve. Following these practices does not + guarantee security, but it at least will help to avoid common + known vulnerabilities and pitfalls.

+

Below are specific recommendations related to WoT runtime + implementations:

+ +

Some additional specific recommendations relevant for WoT + script developers:

+ +
+
+ +

10. Terminology and conventions

+

The generic WoT terminology is defined in [WOT-ARCHITECTURE]: + Thing, Thing Description (in short + TD), + Web of + Things (in short WoT), WoT Interface, + Protocol + Bindings, WoT Runtime, Consuming a Thing + Description, Thing Directory, + WoT + Interactions, Property, + Action, Event etc.

+

JSON-LD is + defined in [JSON-LD] as a JSON document that is + augmented with support for Linked Data.

+

The terms URL and URL path are defined in + [URL].

+

The following terms are defined in [HTML52] and are used in the context + of browser implementations: + + + browsing + context, + + + top-level browsing + context, + + + global + object, + + + incumbent settings + object, + + + Document, + + + document base URL, + + + Window, + + + WindowProxy, + + + origin, + + + ASCII + serialized origin, + + executing algorithms + + + in parallel, + + + queue a task, + + + task source, + + + iframe, + + + valid MIME type.

+ +

A browsing context refers to the + environment in which Document objects are + presented to the user. A given browsing context + has a single WindowProxy + object, but it can have many Document + objects, with their associated Window + objects. The script execution context + associated with the browsing context identifies the + entity which invokes this API, which can be a web app, a + web page, or an iframe.

+

The term + secure + context is defined in [WEBAPPSEC].

+

Error, EvalError, RangeError, ReferenceError, SyntaxError, + TypeError, + URIError , + script execution + context, + Promise, + + JSON, + JSON.stringify and + JSON.parse are defined in + [ECMASCRIPT].

+

DOMString, USVString, ArrayBuffer, BufferSource and any are defined in + [WEBIDL].

+

The algorithms utf-8 encode, and utf-8 decode are defined in + [ENCODING].

+

IANA media + types (formerly known as MIME types) are defined in + RFC2046.

+

The terms hyperlink reference and + relation + type are defined in [HTML52] and RFC8288.

+
+
+ +

11. + Conformance

+

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, SHOULD, and SHOULD NOT + are to be interpreted as described in [RFC2119].

+

This document defines conformance criteria that apply to a + single product: the UA (user agent) that implements the interfaces + it contains.

+

This specification can be used for implementing the WoT + Scripting API in multiple programming languages. The interface + definitions are specified in [WEBIDL].

+

The user agent (UA) may be implemented in the browser, or in + a separate runtime environment, such as Node.js or 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].

+

This document serves a general description of the WoT + Scripting API. Language and runtime specific issues are + discussed in separate extensions of this document.

+
+
+ +

A. + Changes

+

The following is a list of major changes to the document. + For a complete list of changes, see the github + change log. You can also view the + recently closed issues.

+ +
+
+ +

B. Open issues

+

The following problems are being discussed and need most + attention:

+ +
+
+ +

C. + Acknowledgments

+

Special thanks to former editor Johannes Hund (until August + 2017, when at Siemens AG) for developing this specification. + Also, the editors would like to thank Dave Raggett, Matthias + Kovatsch, Michael Koster and Michael McCool for their comments + and guidance.

+
+
+ +

D. + References

+
+

D.1 Normative references

+
+
[ECMASCRIPT]
+
+ ECMAScript + Language Specification. Ecma International. + URL: https://tc39.github.io/ecma262/ +
+
[ENCODING]
+
+ Encoding. + Anne van Kesteren; Joshua Bell; Addison Phillips. W3C. 15 + December 2016. W3C Candidate Recommendation. URL: + https://www.w3.org/TR/encoding/ +
+
[HTML52]
+
+ HTML 5.2. + Steve Faulkner; + Arron Eicholz; + Travis Leithead; + Alex Danilo; + Sangwhan Moon; + Erika Doyle Navara; + Theresa O'Connor; + Robin Berjon. + W3C. 14 December 2017. W3C Recommendation. URL: + https://www.w3.org/TR/html52/ +
+
[JSON-LD]
+
+ JSON-LD + 1.0. Manu Sporny; Gregg Kellogg; Markus + Lanthaler. W3C. 16 January 2014. W3C Recommendation. URL: + https://www.w3.org/TR/json-ld/ +
+
[RFC2119]
+
+ Key + words for use in RFCs to Indicate Requirement + Levels. S. Bradner. IETF. March 1997. Best + Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
+
[TYPESCRIPT]
+
+ + TypeScript Language Specification. + Microsoft. 1 October 2012. URL: + https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md +
+
[URL]
+
+ URL + Standard. Anne van Kesteren. WHATWG. Living + Standard. URL: https://url.spec.whatwg.org/ +
+
[WEBAPPSEC]
+
+ + Secure Contexts. W3C. 17 July 2015. URL: + https://w3c.github.io/webappsec/specs/powerfulfeatures +
+
[WEBIDL]
+
+ Web + IDL. Cameron McCormack; Boris Zbarsky; Tobie + Langel. W3C. 15 December 2016. W3C Editor's Draft. URL: + https://heycam.github.io/webidl/ +
+
[WOT-ARCHITECTURE]
+
+ Web of + Things Architecture. W3C. 20 August 2017. URL: + https://w3c.github.io/wot-architecture/ +
+
+ [WOT-SECURITY-BEST-PRACTICES]
+
+ + Web of Things Security and Privacy Best Practices + (WIP). W3C. WIP. URL: + https://github.com/w3c/wot-security/blob/master/wot-security-best-practices.md +
+
+ [WOT-SECURITY-CONSIDERATIONS]
+
+ Web + of Things Security and Privacy Considerations. + W3C. 28 August 2017. URL: https://w3c.github.io/wot-security/ +
+
+ [WOT-SECURITY-TESTING]
+
+ + Web of Things Security Testing and + Validation. W3C. WIP. URL: + https://github.com/w3c/wot-security/blob/master/wot-security-testing.md +
+
[WOT-TD]
+
+ WoT + Thing Description . W3C. 21 October 2018. URL: + https://www.w3.org/TR/2018/WD-wot-thing-description-20181021/ +
+
+
+
+

D.2 Informative references

+
+
[HTML]
+
+ HTML + Standard. Anne van Kesteren; Domenic Denicola; + Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. + Living Standard. URL: https://html.spec.whatwg.org/multipage/ +
+
+
+
+ + + + diff --git a/releases/wd3/diff.html b/releases/wd3/diff.html new file mode 100644 index 00000000..dd07b8ae --- /dev/null +++ b/releases/wd3/diff.html @@ -0,0 +1,19154 @@ + + + + + + + + + + + + +Web of Things (WoT) Scripting API + + + + + + + + + + + +
+ +

+Web +of +Things +(WoT) +Scripting +API +

+

+ +W3C + +Working +Draft +5 +April + + +

+
+
+This +version: +
+
+https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ + + +https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/ + + +
+
+Latest +published +version: +
+
+ +https://www.w3.org/TR/wot-scripting-api/ + +
+
+Latest +editor's +draft: +
+
+ +https://w3c.github.io/wot-scripting-api/ + +
+
+Previous +version: +
+
+https://www.w3.org/TR/2017/WD-wot-scripting-api-20170914/ + + +https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ + + +
+
+Editors: +
+
+ +Zoltan +Kis + +( + +Intel + +) +
+
+ +Kazuaki +Nimura + +( + +Fujitsu +Ltd. + +) +
+
+ +Daniel +Peintner + +( + +Siemens +AG + +) +
+
+ +Johannes +Hund + +(Former +Editor, +when +at +Siemens +AG) +
+
+Contributors: +
+
+ +In +the +GitHub +repository + +
+
+Repository: +
+
+ +We +are +on +GitHub + +
+
+ +File +a +bug + +
+
+ +
+
+
+

+Abstract +

+

+The +overall + + +Web +of +Things + +(WoT) +provides +layered +interoperability +between + +concepts +are +described +in +the + +WoT +Architecture + +document. +The +Web +of + +Things +is +made +of +entities +( + +Thing + + +by +using + +s) +that +can +describe +their +capabilities +in +a +machine-interpretable +format, +the + +Thing +Description + +(TD) +and +expose +these +capabilities +through + +the + +WoT +Interface +, +that +is, +network +interactions +modeled +as + +Properties + + +s. + +for +reading +and +writing +values, + +Action + +s +to +execute +remote +procedures +with +or +without +return +values +and + +Event + +s +for +signaling +notifications. + +

+

+This +specification +describes +a +programming +interface +representing +the + +WoT +Interface + +that +allows +scripts +run +on +a + +Thing + +to +discover +and +consume +(retrieve) +other + +Thing +Description + + +s +and +to +expose + +Things + +characterized +by + +WoT +Interactions +, +i.e. +Properties +, +Actions + + +and +Events +. + +specified +by +a +script. + +

+

+Scripting +is +an +optional +"convenience" +building +block +in +WoT +and +it +is +typically +used +in +gateways +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 +like + +Thing +Directory +. +

+
+
+

+Status +of +This +Document +

+

+ +This +section +describes +the +status +of +this +document +at +the +time +of +its +publication. +Other +documents +may +supersede +this +document. +A +list +of +current + +W3C + +publications +and +the +latest +revision +of +this +technical +report +can +be +found +in +the + + +W3C + +technical +reports +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. +

+
+
+ +Editor's +note + +: +The +W3C +WoT +WG +is +asking +for +feedback + +
+

+Please +contribute +to +this +draft +using +the + +GitHub +Issue + +feature +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 +a +Working +Draft. +This +document +is +intended +to +become +a +W3C +Recommendation. +

+

+Comments +regarding +this +document +are +welcome. +Please +send +them +to + +public-wot-wg@w3.org + +( + +subscribe +, + +archives + +). +

+

+Changes +from +the +previous +publication +can +be +found +in + +Appendix +A +. +A + +diff-marked +version + +of +this +document +is +also +available +for +comparison +purposes. +

+

+Publication +as +a +Working +Draft +does +not +imply +endorsement +by +the + +W3C + +Membership. +This +is +a +draft +document +and +may +be +updated, +replaced +or +obsoleted +by +other +documents +at +any +time. +It +is +inappropriate +to +cite +this +document +as +other +than +work +in +progress. +

+

+This +document +was +produced +by +a +group +operating +under +the + + +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 + +1 +February +2018 + +W3C + +Process +Document +. +

+
+ +
+

+ +1. + +Introduction + + +

+

+The +overall + +WoT +concepts +are +described +in +the +WoT +Architecture +document. +The +Web +of +Things +is +made +of +entities +( +Thing +s) +that +can +describe +their +capabilities +in +a +machine-interpretable +format, +the + +provides +layered +interoperability +based +on +how + +Thing +Description + + +(TD) + +s +are +modeled: +as +being +"consumed" + +and +expose +these +capabilities +through +the +WoT +Interface +. +Support +for +scripting +is +optional +for +WoT +devices. + +"exposed". + +

+

+By + +consuming +a +TD +, +a +client + +Thing + +creates +a +runtime +resource +model +that +allows +accessing +the + +Properties +, + +Actions + +and + +Events + +exposed +by +the +server + +Thing +. + + +exposed +on +a +remote +device. + +

+

+Exposing +a + +Thing + +requires +defining +a + +Thing +Description + +(TD) +and +instantiating +a +software +stack +needed + +to +serve +requests +for +accessing +the +exposed + +Properties +, + +Actions + +and + +Events +. +This +specification +describes +how +to +expose +and +consume + +Thing + +s +by +a +script. +

+
+
+ +Note + +
+

+Typically +scripts +are +meant +to +be +used +on +devices +able +to +provide +resources +(with +a + +WoT +interface + +Interface + + +) +for +managing +(installing, +updating, +running) +scripts, +such +as +bridges +or +gateways +that +expose +and +control +simpler +devices +as +WoT + +Thing + +s. +

+
+
+
+ +Note + +
+

+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. +

+
+

+For +an +introduction +on +how +scripts +could +be +used +in + +Web +of +Things +, +check +the + +Primer + +document. +For +some +background +on +API +design +decisions +check +the + +Rationale + +document. +

+
+
+

+ +2. + +Use +Cases + + +

+

+ +This +section +is +non-normative. + +

+

+The +following +scripting +use +cases +are +supported +in +this +specification: +

+
+

+ +2.1 + +Discovery + + +

+ +
+
+

+ +2.2 + +Consuming +a +Thing + + +

+ +
+
+

+ +2.3 + +Exposing +a +Thing + + +

+ +
+
+
+

+ +3. + +The + + +WoT + + +object + + +

+

+The +WoT +object +is +the +API +entry +point +and +it +is +exposed +by +an +implementation +of +the + +WoT +Runtime +. +The + +WoT +object + +does +not +expose +properties, +only +methods +for +discovering, +consuming +and +exposing +a + +Thing +. +

+
+
+ +Note + +
+

+Browser +implementations + +SHOULD + +use +a +namespace +object +such +as + +wot +, +and + +navigator.wot +. + +Node.js + +-like +runtimes + +MAY + +provide +the +API +object +through +the + +require() + +or + +import + +mechanism. +

+
+
+
data-idl="" data-title="WoT">interface <span class=
+"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-wot" class="internalDFN" data-link-type=
+"dfn"> {
+<span class="idlMethod" id="idl-def-wot-discover-filter" data-idl=
+"" data-title="discover" data-dfn-for="wot">    <span class=
+"idlMethType"><a href="#dom-observable" class="internalDFN"
+data-link-type="dfn"><<a href=
+"#dom-consumedthing" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlMethName"><a data-no-default="" data-link-for="wot" data-lt=
+"discover()|discover" href="#dom-wot-discover" class="internalDFN"
+data-link-type="dfn">discover(<span class=
+"idlParam">optional <a href=
+"#dom-thingfilter" class="internalDFN" data-link-type=
+
+data-idl="" data-title="WoT">// [SecureContext]
+// [NamespaceObject]
+interface 
+data-link-for="" data-lt="" href="#dom-wot" class="internalDFN"
+data-link-type="dfn">WoT {
+  
+data-link-type=
+"dfn">Observable discover(optional 
+"dfn">ThingFilter "idlParamName">filter
+<span class="idlMethod" id="idl-def-wot-fetch-url" data-idl=""
+data-title="fetch" data-dfn-for="wot">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<<a href="#dom-thingdescription"
+class="internalDFN" data-link-type=
+
+"idlParamName">filter);
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<
+"dfn">ThingDescription> "fetch()|fetch" href="#dom-wot-fetch" class="internalDFN"
+data-link-type="dfn">fetch(<span class=
+
+"wot.fetch()|wot.fetch|fetch()|fetch" href="#dom-wot-fetch" class=
+"internalDFN" data-link-type=
+"dfn">fetch(
+"idlParam">"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id="idl-def-wot-consume-td" data-idl=""
+data-title="consume" data-dfn-for="wot">    <span class=
+"idlMethType"><a href="#dom-consumedthing" class="internalDFN"
+
+"https://heycam.github.io/webidl/#idl-USVString">USVString url);
+  "dfn"><a data-no-default=""
+data-link-for="wot" data-lt="consume()|consume" href=
+
+"dfn">ConsumedThing 
+"#dom-wot-consume" class="internalDFN" data-link-type=
+"dfn">consume<span class=
+"idlParamType"><a href="#dom-thingdescription" class="internalDFN"
+data-link-type=
+
+"dfn">consume(
+"dfn">ThingDescription "idlParamName">td
+<span class="idlMethod" id="idl-def-wot-produce-model" data-idl=""
+data-title="produce" data-dfn-for="wot">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+
+"idlParamName">td);
+  "dfn"><a data-no-default=""
+data-link-for="wot" data-lt="produce()|produce" href=
+"#dom-wot-produce" class="internalDFN" data-link-type=
+"dfn">produce<span class=
+"idlParamType"><a href="#dom-thingmodel" class="internalDFN"
+
+"dfn">ExposedThing produce(ThingModel model);
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> register(USVString directory, ExposedThing thing);
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> unregister(USVString directory, ExposedThing thing);
+};
+typedef object ThingFragment;
+typedef object PropertyFragment;
+typedef object ActionFragment;
+typedef object EventFragment;
+typedef object DataSchema;
+typedef object SecurityScheme;
+typedef object 
+data-link-type=
+"dfn">
+};
+<span class="idlTypedef" id="idl-def-thingdescription" data-idl=""
+data-title="ThingDescription">typedef <span class=
+"idlTypedefType"><a href=
+
+"dfn">Link;
+typedef object Form;
+typedef 
+"https://heycam.github.io/webidl/#idl-USVString">USVString "dfn">
+<span class="idlTypedef" id="idl-def-thingmodel" data-idl=""
+data-title="ThingModel">typedef <span class=
+"idlTypedefType">(<a href="#dom-thingtemplate" class="internalDFN"
+data-link-type="dfn"> or <a href=
+
+"dfn">ThingDescription;
+typedef (ThingFragment or 
+"#dom-thingdescription" class="internalDFN" data-link-type=
+"dfn">ThingDescription) 
+
+ThingModel
+
+
+
+;
+
+
+
+
+
+ +Editor's +note + +
+

+The +algorithms +for +the +WoT +methods +will +be +specified +later, +including +error +handling +and +security +considerations. +

+
+

+The + +ThingModel + +type +represents +either +a + +ThingFragment +, +or +a + +ThingDescription +.

+
+

+ +3.1 + +The + + +discover() + + +method + + +

+

+Starts +the +discovery +process +that +will +provide + + +ConsumedThing + +ThingDescription + + + +objects + +s + +that +match +the +optional +argument + +filter + +of +type + + + + +ThingFilter + + +. +When +the +argument +is +not +provided, +starts +the +widest +discovery +the +Thing +Description +and +Protocol +Bindings +allow +and +support. + +Returns +an +[ + + +Observable + +](https://github.com/tc39/proposal-observable) + +object +that +can +be +subscribed +to +and +unsubscribed +from. +The +handler +function +provided +to +the +Observable +during +subscription +will +receive +an +argument +of +type + +USVString + +representing +a + +ThingDescription +. +

+
+

+ +3.1.1 + +The + + +DiscoveryMethod + + +enumeration + + +

+
+
"DiscoveryMethod">typedef <a href=
+
+"DiscoveryMethod">typedef 
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString 
+
+DiscoveryMethod
+
+
+
+;
+
+
+
+

+ + +DiscoveryMethod + + +represents +the +discovery +type +to +be +used: +

+ +
+
+

+ +3.1.2 + +The + + +ThingFilter + + +dictionary + + +

+

+The + + +ThingFilter + + +dictionary +that +represents +the +constraints +for +discovering + +Thing + +s +as +key-value +pairs. +

+
+
dictionary "dfn"> {
+<span class="idlMember" id="idl-def-thingfilter-method" data-idl=""
+data-title="method" data-dfn-for="thingfilter">    <span class=
+"idlMemberType"><a href="#dom-discoverymethod" class="internalDFN"
+data-link-type=
+"dfn">      <span class=
+"idlMemberName"><a data-no-default="" data-link-for="thingfilter"
+data-lt="" href="#dom-thingfilter-method" class="internalDFN"
+data-link-type="dfn"> = <span class=
+"idlMemberValue">"any"
+<span class="idlMember" id="idl-def-thingfilter-url" data-idl=""
+data-title="url" data-dfn-for="thingfilter">    <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default=""
+
+"dfn">ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  
+"https://heycam.github.io/webidl/#idl-USVString">USVString? 
+data-link-for="thingfilter" data-lt="" href="#dom-thingfilter-url"
+class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMember" id="idl-def-thingfilter-query" data-idl=""
+data-title="query" data-dfn-for="thingfilter">    <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default=""
+
+"dfn">url;
+  
+"https://heycam.github.io/webidl/#idl-USVString">USVString? 
+data-link-for="thingfilter" data-lt="" href=
+"#dom-thingfilter-query" class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMember" id="idl-def-thingfilter-constraints"
+data-idl="" data-title="constraints" data-dfn-for=
+"thingfilter">    <a href=
+"https://heycam.github.io/webidl/#idl-sequence">sequence<a data-no-default=""
+data-link-for="thingfilter" data-lt="" href=
+"#dom-thingfilter-constraints" class="internalDFN" data-link-type=
+"dfn">
+
+"dfn">query;
+  
+data-link-type=
+"dfn">ThingFragment? fragment;
+
+};
+
+
+
+

+The + + +method + + +property +represents +the +discovery +type +that +should +be +used +in +the +discovery +process. +The +possible +values +are +defined +by +the + + + +DiscoveryMethod + + + +enumeration +that +can + + +MAY + +be +extended +by +string +values +defined +by +solutions +(with +no +guarantee +of +interoperability). +

+Editor's +note +The +DiscoveryMethod +enumeration +can +be +extended +by +the +Thing +Description +with +values +that +are +not +specified +here. +This +extensibility +of +DiscoveryMethod +by +proprietary +or +private +methods +is +a +working +assumption +until +consensus +is +formed +and +may +be +removed +later. + +

+The + + +url + + +property +represents +additional +information +for +the +discovery +method, +such +as +the +URL +of +the +target +entity +serving +the +discovery +request, +such +as + +for +instance + +a + +Thing +Directory + +(if + +method + +is + +"directory" + +) + +or +a +Thing. + +Thing +(otherwise). + +

+

+The + + +query + + +property +represents +a +query +string +accepted +by +the +implementation, +for +instance +a +SPARQL +or +JSON + +query. +Support +may +be +implemented +locally +in +the + +WoT +Runtime + +or +remotely +as +a +service +in +a + +Thing +Directory +. +

+

+The + + +constraints + +fragment + + + +property +represents +additional +information + +a + +ThingFragment + +dictionary +used + +for +the +discovery + +matching +property +by +property +against +discovered + +Thing + +s. +

+The + +discover(filter) + +method +in + + +MUST + +run + +the +form +of +a +list +of +sets +of +property-value +pairs +(dictionaries). +The +list +elements +(dictionaries) +are +in +OR +relationship, + +following +steps: +

  1. +If +invoking + +discover() + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +throw + +SecurityError + +and +within +a +constraint +dictionary + +terminate +these +steps. +
  2. +Return +an + +Observable + +obs + +and +execute + +the +key-value +pairs +are + +next +steps + +in +AND +relationship. +Implementations +SHOULD +make + +parallel +.
  3. +If + +obs.subscribe(handler, +errorHandler, +complete) + +is +called, +execute + +the +following +mapping +from + +sub-steps: +
    1. +If + +the +constraint +dictionaries + +first +argument + +handler + +is +not +defined +or +it +is +not +a +function, +throw + +TypeError + +and +terminate +the +algorithm. +Otherwise +configure + +handler + +to +be +invoked +when +a +discovery +hit +happens. +
    2. +If +the +second +argument + +errorHandler + +is +defined, +but +it +is +not +a +function, +throw + + +SemanticAnnotations + +TypeError + + +: +for +each +property-value +pair + +and +terminate +these +steps. +Otherwise +if +defined, +save +it +to +be +invoked + +in +error +conditions. +
    3. +If +the +third +argument + +onComplete + +is +defined, +but +it +is +not + +a +constraint +dictionary, + +function, +throw + +TypeError + +and +terminate +these +steps. +Otherwise +if +defined, +save +it +to +be +invoked +when +the +discovery +process +finished +for +other +reasons +than +having +been +canceled. +
    4. +
    5. +Each +property +name +in + +If + +filter.query + +is +defined, +pass +it +as +an +opaque +string +to + +the +constraint +dictionary +SHOULD + +underlying +implementation +to +be +matched +against +discovered +items. +The +underlying +implementation +is +responsible +to +parse +it +e.g. +as +a +SPARQL +or +JSON +query +and + +match +it +against + +the +either + + +Thing +Description + +s +found +during + +the +discovery +process. +If +queries +are +not +supported, +implementations + +SHOULD + +throw +a + + +name + +NotSupported + + +property +of +a + +error +and +terminate +these +steps. +
    6. +If + +filter.fragment + +is +defined, +and +if +it +contains +other +properties +than +the +ones + +defined +in + + +SemanticType + +ThingFragment + + +on + +, +throw + +TypeError + +and +terminate +these +steps. +Otherwise +save + +the +target + +object +for +matching +the +discovered +items +against +it. +
    7. +Request +the +underlying +platform +to +start +the +discovery +process, +with +the +following +parameters: +
      • +If + +filter.method + +is +not +defined +or +the +value +is + +"any" +, +use +the +widest +discovery +method +supported +by +the +underlying +platform. +
      • +Otherwise +if + +filter.method + +is + +"local" +, +use +the +local + +Thing +Directory + + +object, + +for +discovery. +Usually +that +defines + +Thing + +s +deployed +in +the +same +device, + +or +connected +to + +the +name +of + +device +in +slave +mode +(e.g. +sensors +connected +via +Bluetooth +or + +a +Property +on + +serial +connection). +
      • +Otherwise +if + +filter.method + +is + +"directory" +, +use + +the +target + +remote + +Thing +. + +Directory + +specified +in + +filter.url +. +
      • +
      • +When + +Otherwise +if + +filter.method + +is + +"multicast" +, +use +all + +the +name +matches, + +multicast +discovery +protocols +supported +by + +the +values +are +compared. + +underlying +platform. +
  4. +Whenever +a +new +item + +td + +is +discovered +by +the +underlying +platform, +run +the +following +sub-steps: +
    1. +If + +filter.query + +is +defined, +check +if + +td + +is +a +match +for + +the +values +match, + +query. +The +matching +algorithm +is +encapsulated +by +implementations. +If +that +returns + +false +, +discard + +td + +and +continue + +the +constraint + +discovery +process. +
    2. +If + +filter.fragment + +is +matched. + +defined, +for +each +property +defined +in +it, +check +if +that +property +exists +in + +td + +and +has +the +same +value. +If +this +is + +false + +in +any +checks, +discard + +td + +and +continue +the +discovery +process. + +
    3. +Editor's +note +Constraints +are +experimental +feature, +implementations +are + +
    4. +Otherwise +if + +td + +has + +not +required +to +support +them. +Editor's +note +Semantic +annotations +need +revisiting + +been +discarded + +in +order +to +simplify +their +representation. +In + +the +[ +WOT-TD +] +specification +they +represent + +previous +steps, +invoke + +the + +handler + +function +with + +td + +as +parameter. +
  5. +Whenever +an +error +occurs +during +the +discovery +process, +and +if + +errorHandler + +is +defined, +invoke +it +with +an +argument +of +type + + +@type + +Error + + +construct. +At +the +moment +only + +whose + + +@context +, + +message + +property +is +set +to + + +@type + +UnknownError + + +unless +there +was +an +error +code +provided +by +the + +Protocol +Bindings +, +in +which +case +set +it +to +that +value. +
  6. +When +the +discovery +process +is +finished, + +and +if + +onComplete + +is +defined, +invoke +it +run +the + +cancel +discovery + +steps. +
  7. +When +the + + +@id + +obs.unsubscribe() + + +constructs +are +used +in + +method +is +called, +run + +the +TD +. + +following + +cancel +discovery + +steps: +
    1. +Request +the +underlying +platform +to +stop +the +discovery +process. +If +this +returns +an +error, +or +if +it +is +not +possible, +for +instance +when +discovery +is +based +on +open +ended +multicast +requests, +the +implementation + +SHOULD + +discard +subsequent +discovered +items. +
    2. +Set + +obs.closed + +to + +false +.
+
+
+

+ +3.2 + +The + + +fetch() + + +method + + +

+

+Accepts +an + +url + +argument +of +type + +USVString + +that +represents +a +URL +(e.g. + +"file://..." + +or + +"https://..." + +) + +and +returns +a + + +Promise + + +that +resolves +with +a + + +ThingDescription + +. + + +(a +serialized + +JSON-LD + +document +of +type + +USVString + +). + +

+3.3 + +

+The + +ThingDescription + +fetch(url) + + +type +Representation +of + +method + +MUST + +run + +the +Thing +Description +, +standardized + +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +invoking + +fetch() + +is +not +allowed +for + +the +Wot +Things + +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  3. +If +the +argument + +url + +is +not +a +URL, +reject + +promise + +with + +TypeError + +and +terminate +these +steps. +
  4. +Make +a +request +to +fetch +the +content +of + +url + +as +described +by +the + +Protocol +Bindings + +and +wait +for +the +reply. +Implementations +encapsulate +the +fetching +process +and +the +accepted +media +types +(such +as + +application/td+json + +), +as +far +as +a +valid + +Thing + +Description + +specification. + +can +be +obtained +as +defined +in +[ + +Note + + +WOT-TD + +In +this +version +of + + +]. +Let + +td + +be + +the +API, + + +Thing +Description + +s +are +represented + +string-serialized +from +the +returned +content, + +as +opaque +strings, +denoting +a +serialized +form, +for +instance +JSON +or +JSON-LD. +See +Issue +38 + +specified +in +the + +Thing +Description +serialization +.
  5. +If +there +was +an +error +during +the +request, +reject + +promise + +with +an + +Error + +object + +error + +with + +error.message + +set +to +the +error +code +seen +by +the + +Protocol +Bindings + + +and +Issue +45 +. + +terminate +these +steps. +
  6. +Otherwise +resolve + +promise + +with + +td + +and +terminate +these +steps. +
+
+
+

+ +3.4 + +3.3 + + +The + + +consume() + + +method + + +

+

+Accepts +an + +td + +argument +of +type + + + +ThingDescription + + + +and +returns +a + + +ConsumedThing + + +object +instantiated +based +on +parsing + +that +description. +

+

+The + +consume(td) + +method +must +run +the +following +steps: +

  1. +If +the +argument + +td + +is +not +a +string, +throw +a + +TypeError + +and +terminate +these +steps. +
  2. +Let + +stub + +be +the +result +of +running +the + +TD +parsing +algorithm + +with + +td + +as +argument. +If +that +throws +an +error, +re-throw +the +error +and +terminate +these +steps. +
  3. +If + +stub + +does +not +have +an +own +property +that +is +defined +in + +ThingFragment + +with +a +default +value, +add +that +property +and +value +to + +stub +.
  4. +Create +a + +ConsumedThing + +object + +thing + +initialized +from + +stub + +that +implements + +Observable +.
  5. +Add +the + +read() + +and + +write() + +methods +to +the + +ThingProperty + +elements +so +that +they +make +requests +to +access +the +remote + +Thing + +s +and +wait +for +the +reply, +as +defined +by +the + +Protocol +Bindings +. +Also, +all + +ThingProperty + +elements + +SHOULD + +implement + +Observable +, +i.e. +define +a + +subscribe() + +method +that +should +make +request +to +observe +the +given + +Properties + +as +defined +by +the + +Protocol +Bindings +.
  6. +Add +the + +invoke() + +methods +to +the + +ThingAction + +elements +so +that +they +make +requests +to +the +remote + +Thing + +to +invoke +its +actions, +as +defined +by +the + +Protocol +Bindings +.
  7. +Add +the + +subscribe() + +method +to +all + +ThingEvent + +elements +so +that +they +make +requests +to +subscribe +to +the +events +defined +by +the +remote + +Thing +, +as +defined +by +the + +Protocol +Bindings +.
  8. +Return + +thing +.
+
+
+

+ +3.5 + +3.4 + + +The + + +produce() + + +method + + +

+

+Accepts +a + +model + +argument +of +type + + + +ThingModel + + + +and +returns +an + + +ExposedThing + + +object, +locally +created +based +on +the +provided +initialization +parameters. +An + +object. +

+The + + +ExposedThing + +produce(model) + + +can +be +created +in + +method + +MUST + +run + +the +following +ways: + +steps: + +

+
    +
  1. +from +an +initial + +If +invoking + +produce() + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +throw + +SecurityError + +and +terminate +these +steps. +
  2. +If +the +argument + +model +(including + + +is + +a +user +given +name +and +semantic +annotations +), + +string, + +then +adding +properties, +actions, +events + +run +the + +TD +parsing +algorithm + +with + +model + +passed +as +parameter. +If +it +throws +an +error, +re-throw +that +error + +and +request +handlers; + +terminate +this +algorithm. +Otherwise +let + +model + +be +the +returned +value. + +
  3. +
  4. +from +a +Thing +Description +(possibly +of +a + +If + +model + +is +not +an +object, +throw + +TypeError + +and +terminate +these +steps. +
  5. +If + +model + +does +not +have +an +own +property +that +is +defined +in + + +ConsumedThing + +ThingFragment + + + +object), +then +adding +request +handlers. + +with +a +default +value, +add +that +property +and +value +to + +model +. +
  6. +3.6 +The + +
  7. +Create +an + + +ThingModel + +ExposedThing + + +type +A +Thing + + +object + +thing + +initialized +from + +model +is +used +for +producing +a +new + +. +
  8. +
  9. +For +each +property +of + + +ExposedThing + + +and +can +be +either +a + +defined +in + + +ThingTemplate + +ThingFragment + + +, +initialize +the +property +based +on +the +provided +initial + +or +a + +default +values +provided +to +the +local + +WoT +Runtime + +implementation, +for +instance +initialize: +
    1. +the + + +ThingDescription + +id + + +. +3.7 +The + +property +to +be +the +final +unique +identifier +of +the + +Thing +,
    2. +the + +security + +object +of +type + + +SemanticAnnotations + +SecurityScheme + + +dictionary +A +dictionary +that +provides + + +to +represent + +the +semantic +types + +actual +security +scheme + +and +semantic +metadata. +<span class="idlDictionary" id= +"idl-def-semanticannotations" data-idl="" data-title= +"SemanticAnnotations">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-semanticannotations" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id= +"idl-def-semanticannotations-semantictype" data-idl="" data-title= +"semanticType" data-dfn-for="semanticannotations"> <span class= +"idlMemberType"><a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-semantictype" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for= +"semanticannotations" data-lt="" href= +"#dom-semanticannotations-semantictype" class="internalDFN" +data-link-type="dfn"> +<span class="idlMember" id="idl-def-semanticannotations-metadata" +data-idl="" data-title="metadata" data-dfn-for= +"semanticannotations"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-semanticmetadata" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for= +"semanticannotations" data-lt="" href= +"#dom-semanticannotations-metadata" class="internalDFN" +data-link-type="dfn"> +}; +The + +its +properties +as +set +up +by +the +implementation, +
    3. +the + + +semanticType + +properties + + +property +denotes +a +list +of + +to +be +an +object +with +all +properties +being + + +SemanticType + +ThingProperty + + + +objects +that + +in +which +the + +read() + +and + +write() + +methods +are +provided +to + +define +local +methods +to +get +and +set +the + +Property + +values, +
    4. +the +semantic +types +that +can +be +used +in +semantic +metadata +type-value +pairs. +The + + +metadata + +actions + + +property +denotes +a +list +of + +to +be +an +object +with +all +properties +being + + +SemanticMetadata + +ThingAction + + + +objects +(type-value +pairs). +3.8 +The + +in +which +the + + +SemanticType + +invoke() + + +dictionary +<span class="idlDictionary" id= +"idl-def-semantictype" data-idl="" data-title= +"SemanticType">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-semantictype" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-semantictype-name" data-idl="" +data-title="name" data-dfn-for= +"semantictype"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="semantictype" data-lt="" href= +"#dom-semantictype-name" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-semantictype-context" data-idl= +"" data-title="context" data-dfn-for= +"semantictype"> required <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="semantictype" data-lt="" href= +"#dom-semantictype-context" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-semantictype-prefix" data-idl= +"" data-title="prefix" data-dfn-for= +"semantictype"> <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="semantictype" data-lt="" href= +"#dom-semantictype-prefix" class="internalDFN" data-link-type= +"dfn"> +}; +Represents +a +semantic +type +annotation, +containing +a +name, +a +context +and + +method +is +provided +to +define + +a +prefix. + +local +method +to +run +the +defined + +Action + +s, +
    5. +
    6. +The + +the + +events + +property +to +be +an +object +with +all +properties +being + + +name + +ExposedEvent + + +attribute +represents +the +name +of +the +semantic +type + + +objects + +in +which + +the +given +context. +The + + +context + +emit() + + +attribute +represents +an +URL +link + +method +is +provided + +to +define +a +local +way +to +trigger +sending +notifications +to +all +subscribed +clients, +
    7. +and +initialize + +the +context +of +the +semantic +classification. + +other +properties +as +initialized +from + +model +. +
    8. +
    9. +Return + +thing +.

    +The +prefix + + +TD +parsing +algorithm + + +attribute +represents + +takes + +a +short +prefix +associated +with + +string + +td + +as +argument +and +runs +the +following +steps: +

    1. +Parse + +td + +according +to +the + +WoT +Thing +Description + +in +order +to +produce + +a +context. + + +JSON +object + +json +. +Update + +thing + +with +the +properties +and +values +defined +in + +json +. +
    2. +Editor's +note +Semantic +type +examples +to +be +added. + +
    3. +If +there +was +an +error +during +the +parsing, +throw +that +error +and +terminate +these +steps. +
    4. +Otherwise +return + +json +.
+
+
+

+3.9 + + +3.5 + + +The + + +SemanticMetadata + +register() + + + +dictionary +<span class="idlDictionary" id= +"idl-def-semanticmetadata" data-idl="" data-title= +"SemanticMetadata">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-semanticmetadata" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-semanticmetadata-type" +data-idl="" data-title="type" data-dfn-for= +"semanticmetadata"> <a href= +"#dom-semantictype" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for= +"semanticmetadata" data-lt="" href="#dom-semanticmetadata-type" +class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-semanticmetadata-value" +data-idl="" data-title="value" data-dfn-for= +"semanticmetadata"> <a href= +"https://heycam.github.io/webidl/#idl-any">any<a data-no-default="" +data-link-for="semanticmetadata" data-lt="" href= +"#dom-semanticmetadata-value" class="internalDFN" data-link-type= +"dfn"> +}; + +method + + +

+

+The + +Takes +two +mandatory +arguments: +

+3.10 +The +ThingTemplate +dictionary + +

+A + +Generate +the + +Thing +Template +is +a +dictionary +that +provides +a +user + +Description + +as + +td +, +given +name, +and + +the +semantic +types + + +Properties +, +Action + +s + +and +semantic +metadata +attached +to +the + + +Event + +s +defined +for +this + + + +ExposedThing + + +object. +Then +make +a +request +to +register + +td + +to +the +given +WoT + +Thing +Description +'s +root +level. + +Directory +. +

+<span class="idlDictionary" id= +"idl-def-thingtemplate" data-idl="" data-title= +"ThingTemplate">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingtemplate" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingtemplate-name" data-idl="" +data-title="name" data-dfn-for= +"thingtemplate"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingtemplate" data-lt="" href= +"#dom-thingtemplate-name" class="internalDFN" data-link-type= +"dfn"> +}; + +
+
+

+ +3.6 + +The + + +ThingTemplate + +unregister() + + + +method + + +dictionary +extends + +

+

+Takes +two +mandatory +arguments: +

+Makes +a +request +to +unregister + +the +user +given +name +of + + +thing + +from + +the +given +WoT + +Thing +Directory + +. +Editor's +note +Support +for +configuration +and +security +data +might +be +added +later. + +

+
+
+

+ +3.11 + +3.7 + + +Examples + + +

+
+
+ +Example +1 + +: + +: +Discover +Things +via +directory + +
+
let discoveryFilter = {
+  method: "directory",
+  url: "http://directory.wotservice.org"
+};
+let subscription = wot.discover(discoveryFilter).subscribe(
+  "hljs-params">thing { <span class=
+"hljs-built_in">console.log(<span class=
+"hljs-string">"Found Thing " + thing.name); },
+
+"hljs-params">td => {
+    console.log(
+"hljs-string">"Found Thing " + td.name);
+    
+"hljs-comment">// fetch the TD and create a ConsumedThing
+    let thing = wot.consume(td);
+  },
+
+  error => { console.log("Discovery finished because an error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+setTimeout( () => {
+    subscription.unsubscribe();
+    console.log("Discovery timeout");
+  },
+
+5000
+
+);
+
+
+Note +Note +that +canceling +a +discovery +(through +unsubscribe() +) +may +not +be +successful +in +all +cases, +for +instance +when +discovery +is +based +on +open +ended +broadcast +requests. +However, +once +unsubscribe() +has +been +called, +implementations +MUST +suppress +further +event +handling +( +i.e. +further +discoveries +and +errors) +on +the +Observable. +Also, +a +discovery +error +may +not +mean +the +end +of +the +discovery +process. +However, +in +order +to +respect +Observable +semantics +(error +always +terminates +processing), +implementations +MUST +close +or +suppress +further +event +handling +on +the +Observable. + +
+
+ +Example +2 + +: + +: +Discover +Things +exposed +by +local +hardware + +
+
let subscription = wot.discover({ method: "local" }).subscribe(
+  "hljs-params">thing { <span class=
+
+"hljs-params">td => { 
+"hljs-built_in">console.log("hljs-string">"Found local Thing " + thing.name); },
+
+"hljs-string">"Found local Thing " + td.name); },
+
+  error => { console.log("Discovery error: " + error.message); },
+  () => { console.log("Discovery finished successfully");}
+);
+
+
+
+
+ +Example +3 + +: + +: +Same +as +above +but +with +different +Observable +syntax + +
+
let subscription = wot.discover({ method: "local" }).subscribe({
+  thing => { <span class=
+
+  td => { 
+"hljs-built_in">console.log("hljs-string">"Found local Thing " + thing.name); },
+
+"hljs-string">"Found local Thing " + td.name); },
+
+  error: err => { console.log("Discovery error: " + err.message); },
+  complete: () => { console.log("Discovery finished successfully");}
+});
+
+
+Example +4 +: +Discover +Things +exposed +nearby, +via +Bluetooth +or +NFC +<span class= +"hljs-keyword">let subscription = wot.discover({ + : <span class= +"hljs-string">"nearby", + : [{ <span class= +"hljs-attr">protocol: <span class= +"hljs-string">"BLE-4.2" }, { <span class= +"hljs-attr">protocol: <span class= +"hljs-string">"NFC"}] +}).subscribe( + <span class= +"hljs-params">thing { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Found nearby Thing " + thing.name); }, + error => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery error: " + error.message); }, + () => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} +); +Example +5 +: +Discover +Things +exposed +in +a +proprietary +way +<span class= +"hljs-keyword">let subscription = wot.discover({ + : <span class= +"hljs-string">"other", + : [{ <span class= +"hljs-attr">solution: <span class= +"hljs-string">"XYZ123", <span class= +"hljs-attr">key}] +}).subscribe( + <span class= +"hljs-params">thing { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Found Thing " + thing.name); }, + error => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery error: " + error.message); }, + () => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} +); + +
+
+
+

+ +4. + +The + + +ConsumedThing + + +interface + + +

+

+The + +Represents +an +object +that +extends +a + + +ConsumedThing + +ThingFragment + + + +interface +is +a + +with +methods +for + +client +API + +interactions +(send +request + +for +sending +requests +to +servers +in +order +to +retrieve +or +update + +reading +and +writing + +Properties +, + + +), + +invoke +Actions +, + + +Action + +s, +subscribe + +and +observe +Properties + +unsubscribe +for + +Property + + +changes + +and + +Events +. + +Event + +s. + +

+
+
interface "dfn"> {
+<span class="idlAttribute" id="idl-def-consumedthing-name"
+data-idl="" data-title="name" data-dfn-for=
+"consumedthing">    readonly attribute <span class=
+"idlAttrType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default=""
+data-link-for="consumedthing" data-lt="" href=
+"#dom-consumedthing-name" class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMethod" id=
+"idl-def-consumedthing-getthingdescription" data-idl="" data-title=
+"getThingDescription" data-dfn-for="consumedthing">    <span class=
+"idlMethType"><a href="#dom-thingdescription" class="internalDFN"
+
+"dfn">ConsumedThing : 
+data-link-type=
+"dfn"> <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="getthingdescription()|getThingDescription" href=
+"#dom-consumedthing-getthingdescription" class="internalDFN"
+data-link-type="dfn">getThingDescription
+<span class="idlMethod" id=
+"idl-def-consumedthing-readproperty-name" data-idl="" data-title=
+"readProperty" data-dfn-for="consumedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="consumedthing" data-lt="readproperty()|readProperty"
+href="#dom-consumedthing-readproperty" class="internalDFN"
+data-link-type="dfn">readProperty(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-writeproperty-name-value" data-idl=""
+data-title="writeProperty" data-dfn-for=
+"consumedthing">    <a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="consumedthing" data-lt=
+"writeproperty()|writeProperty" href=
+"#dom-consumedthing-writeproperty" class="internalDFN"
+data-link-type="dfn">writeProperty(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-invokeaction-name-parameters" data-idl=""
+data-title="invokeAction" data-dfn-for=
+"consumedthing">    <a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="consumedthing" data-lt="invokeaction()|invokeAction"
+href="#dom-consumedthing-invokeaction" class="internalDFN"
+data-link-type="dfn">invokeAction(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id=
+"idl-def-consumedthing-onpropertychange-name" data-idl=""
+data-title="onPropertyChange" data-dfn-for=
+"consumedthing">    <a href=
+"#dom-observable" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="onpropertychange()|onPropertyChange" href=
+"#dom-consumedthing-onpropertychange" class="internalDFN"
+data-link-type="dfn">onPropertyChange(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-consumedthing-onevent-name"
+data-idl="" data-title="onEvent" data-dfn-for=
+"consumedthing">    <a href=
+"#dom-observable" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="onevent()|onEvent" href="#dom-consumedthing-onevent"
+class="internalDFN" data-link-type=
+"dfn">onEvent<span class=
+"idlParamType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-consumedthing-ontdchange"
+data-idl="" data-title="onTDChange" data-dfn-for=
+"consumedthing">    <a href=
+
+"dfn">ThingFragment {
+  readonly attribute DOMString id;
+  readonly attribute DOMString name;
+  readonly attribute DOMString? base;
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute EventMap events;
+  // getter for ThingFragment properties
+  getter 
+"https://heycam.github.io/webidl/#idl-any">any (DOMString name);
+};
+[NoInterfaceObject]
+interface PropertyMap {
+  readonly maplike<DOMString, ThingProperty>;
+};
+[NoInterfaceObject]
+interface ActionMap {
+  readonly maplike<DOMString, ThingAction>;
+};
+[NoInterfaceObject]
+interface EventMap {
+  readonly maplike<DOMString, ThingEvent>;
+};
+
+"dfn">ConsumedThing includes 
+"#dom-observable" class="internalDFN" data-link-type=
+"dfn">       <span class=
+"idlMethName"><a data-no-default="" data-link-for="consumedthing"
+data-lt="ontdchange()|onTDChange" href=
+"#dom-consumedthing-ontdchange" class="internalDFN" data-link-type=
+"dfn">onTDChange
+};
+
+"dfn">Observable;
+//
+for
+TD
+changes
+
+
+
+
+

+The + + +ConsumedThing + +id + + + +attribute + +represents +a +local +proxy +object + +the +unique +identifier + +of +the +remote + + +Thing +. + + +instance, +typically +a +URI, +IRI, +or +URN +as + +USVString +. +

+4.1 + +

+The + + +name + + +property +The +name +property + +attribute + +represents +the +name +of +the + +Thing + +as +specified +in +the +TD +. +In +this +version +it +is +read +only. + + +DOMString +. +

+4.2 + +

+The + + +getThingDescription() + +base + + + +method +Returns +the +Thing +Description +of + +attribute +represents + +the +Thing +. +Editor's +note +In +this +version, +introspection +based +on +TD +is +out +of +scope. +Parsing +and +exposing +Thing +Description +s + +base +URI +that + +is +discussed +in +Issue +38 +. + +valid +for +all +defined +local +interaction +resources. + +

+4.3 + +

+The + + +readProperty() + +properties + + + +method +Takes +the +Property +name +as +the +name +argument, +then +requests +from +the +underlying +platform +and +the +Protocol +Bindings +to +retrieve +the +Property +on +the +remote +Thing +and +return +the +result. +Returns + +attribute +represents + +a +dictionary +of + + +ThingProperty + +Promise + + +items. +The + + +PropertyMap + + +that +resolves +with +the +Property +value +or +rejects +with +an +Error +. + +4.4 +The + + +interface +represents +a +maplike +dictionary +where +all +values +are + + +writeProperty() + +ThingProperty + + +method +Takes +the +Property + + +name +as +the +name +argument +and +the +new +value +as +the +value +argument, +then +requests +from +the +underlying +platform + +objects. +The + +read() + +and +the +Protocol +Bindings + + +write() + +methods +make +a +request + +to +update + +access + +the + +Property + +Properties + + +on +the +remote + +Thing + +and +return +the +result. +Returns +a + +represented +by +this + + +ConsumedThing + +Promise + + +that +resolves +on +success +or +rejects +with +an +Error +. + +proxy +object. + +

+4.5 + +

+The + + +invokeAction() + +actions + + + +method +Takes +the +Action +name +from +the +name +argument +and +the +list +of +parameters, +then +requests +from +the +underlying +platform +and +the +Protocol +Bindings +to +invoke +the +Action +on +the +remote +Thing +and +return +the +result. +Returns + +attribute +represents + +a +Promise + +dictionary +of + + +ThingAction + + +that +resolves +with +the +return +value +or +rejects +with +an +Error +. + +4.6 + + +items. + +The + + +onPropertyChange() + +ActionMap + + + +method +Returns +an + +interface +represents +a +maplike +dictionary +where +all +values +are + + +Observable + +ThingAction + + + +for +the +Property +specified +in +the +name +argument, +allowing +subscribing +to +and +unsubscribing +from +notifications. + +objects. + +The +callback +function +passed +to +the + + +subscribe() + +invoke() + + +method +when +invoked +on + +represents +a +request +to +invoke + +the +returned +observer +will +receive + + +Action + +on + +the +new +property +value +each +time +it +is +changed. + +remote + +Thing +. +

+4.7 + +

+The + + +onEvent() + +events + + + +method +Returns +an + +attribute +represents +a +dictionary +of + + +Observable + +ThingEvent + + + +for +the +Event +specified +in +the +name +argument, +allowing +subscribing +to +and +unsubscribing +from +notifications. +The +callback +function +passed +to +the +subscribe() +method +when +invoked +on +the +returned +observer +will +receive +the +event +data +each +time +the +event +is +fired. +4.8 + +items. + +The + + +onTDChange() + +EventMap + + + +method +Returns +an + +interface +represents +a +maplike +dictionary +where +all +values +are + + +Observable + +ThingEvent + + +, +allowing +subscribing +to +and +unsubscribing +from +notifications +to +the +Thing +Description +. +The +callback +function +passed + + +objects. +Subscribing + +to +the +subscribe() +method +when +invoked + +events +involves +setting +up +an +observation +(subscription) +mechanism + +on +the +returned +observer +will +receive +the +new +Thing +Description +each +time +it +is +changed. + +remote +object. + +

+
+

+ +4.9 + +4.1 + + +Examples + + +

+

+Below +a + + + +ConsumedThing + + + +interface +example +is +given. +

+
+
+ +Example +6 + +4 + +: + +: +Consume +a +Thing + +
+try { + let td = await wot.fetch("http://mmyservice.org/mySensor"); + let thing = wot.consume(td); + console.log("Thing " + thing.name + " has been consumed."); + let subscription = thing.onPropertyChange("temperature") + .subscribe(function(value) { + console.log("Temperature + " has changed to " + value); + }); + thing.invokeAction("startMeasurement", { units: "Celsius" }) + .then(() => { console.log("Temperature measurement started."); }) + .catch(e => { + console.log("Error starting measurement."); + subscription.unsubscribe(); + }) +} catch(error) { + console.log("Error during fetch or consume: " + error.message); + +
"hljs-keyword">try {
+  
+"hljs-keyword">let subscription = wot.discover({ method: "local" }).subscribe(
+    
+"hljs-params">td => {
+      
+"hljs-keyword">let thing = wot.consume(td);
+      console.log(
+"hljs-string">"Thing " + thing.name + " has been consumed.");
+      
+"hljs-keyword">let subscription = thing["temperature"].subscribe(function(value) {
+          
+"hljs-built_in">console.log("Temperature: " + value);
+        });
+      thing.actions["startMeasurement"].invoke({ units: "Celsius" })
+        .then(() => { console.log("Temperature measurement started."); })
+        .catch(e => {
+           
+"hljs-built_in">console.log("Error starting measurement.");
+           subscription.unsubscribe();
+         })
+    },
+    error => { console.log("Discovery error: " + error.message); },
+    () => { console.log("Discovery finished successfully");}
+  );
+} catch(error) {
+  console.log(
+"hljs-string">"Error: " + error.message);
+
+};
+
+
+
+
+
+

+ +5. + +The + + +ExposedThing + + +interface + + +

+

+The + + +ExposedThing + + +interface +is +the +server +API +that +allows +defining +request +handlers, +properties, + +Actions +, +and + +Events + +to +a + +Thing +. +It +also +implements +the + + +ConsumedThing + +Observable + + + +interface. +An + + +ExposedThing + + +is +created +by +the + +produce() + +method. +

+Editor's +note +It +is +under +consideration +to +use +a +constructor +for +ExposedThing +instead +of +a +factory +method. + +
+<a href= +"#dom-exposedthing" class="internalDFN" data-link-type= +"dfn"> implements <a href= +"#dom-consumedthing" class="internalDFN" data-link-type= +"dfn"> +<span class="idlInterface" id="idl-def-exposedthing" data-idl="" +data-title="ExposedThing">interface <span class= + +
"idl-def-exposedthing" data-idl="" data-title=
+"ExposedThing">interface 
+"idlInterfaceID">"dfn"> {
+<span class=
+"idlSectionComment">    // define how to expose and run the Thing
+<span class="idlMethod" id="idl-def-exposedthing-start" data-idl=""
+data-title="start" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="exposedthing" data-lt="start()|start" href=
+"#dom-exposedthing-start" class="internalDFN" data-link-type=
+"dfn">start
+<span class="idlMethod" id="idl-def-exposedthing-stop" data-idl=""
+data-title="stop" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="exposedthing" data-lt="stop()|stop" href=
+"#dom-exposedthing-stop" class="internalDFN" data-link-type=
+"dfn">stop
+<span class="idlMethod" id=
+"idl-def-exposedthing-register-directory" data-idl="" data-title=
+"register" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default=""
+data-link-for="exposedthing" data-lt="register()|register" href=
+"#dom-exposedthing-register" class="internalDFN" data-link-type=
+"dfn">register(<span class=
+"idlParam">optional <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id=
+"idl-def-exposedthing-unregister-directory" data-idl="" data-title=
+"unregister" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+
+"dfn">ExposedThing : ThingFragment {
+  readonly attribute PropertyMap properties;
+  readonly attribute ActionMap actions;
+  readonly attribute ExposedEvents events;
+  // getter for ThingFragment properties
+  getter 
+"https://heycam.github.io/webidl/#idl-any">any (DOMString name);
+  // setter for ThingFragment properties
+  setter void (
+"idlParam">DOMString name, any value);
+  // methods to expose and destroy the Thing
+  Promise<void> data-link-for="exposedthing" data-lt="unregister()|unregister"
+href="#dom-exposedthing-unregister" class="internalDFN"
+data-link-type="dfn">unregister(<span class=
+"idlParam">optional <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString
+<span class="idlMethod" id=
+"idl-def-exposedthing-emitevent-eventname-payload" data-idl=""
+data-title="emitEvent" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href=
+
+data-link-for="exposedthing" data-lt=
+"exposedthing.expose()|exposedthing.expose|expose()|expose" href=
+"#dom-exposedthing-expose" class="internalDFN" data-link-type=
+"dfn">expose();
+  Promise<void> data-link-for="exposedthing" data-lt="emitevent()|emitEvent" href=
+"#dom-exposedthing-emitevent" class="internalDFN" data-link-type=
+"dfn">emitEvent<span class=
+"idlParamType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class=
+"idlSectionComment">    // define Thing Description modifiers
+<span class="idlMethod" id=
+"idl-def-exposedthing-addproperty-property" data-idl="" data-title=
+"addProperty" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+data-link-type=
+"dfn">  <span class=
+
+data-link-for="exposedthing" data-lt=
+"exposedthing.destroy()|exposedthing.destroy|destroy()|destroy"
+href="#dom-exposedthing-destroy" class="internalDFN"
+data-link-type="dfn">destroy();
+  // define Properties
+  
+"internalDFN" data-link-type=
+"dfn">ExposedThing 
+"idlMethName">data-lt="addproperty()|addProperty" href=
+"#dom-exposedthing-addproperty" class="internalDFN" data-link-type=
+"dfn">addProperty<span class=
+"idlParamType"><a href="#dom-thingproperty" class="internalDFN"
+
+data-lt=
+"exposedthing.addproperty()|exposedthing.addproperty|addproperty()|addproperty"
+href="#dom-exposedthing-addproperty" class="internalDFN"
+
+data-link-type=
+"dfn"> <span class=
+"idlParamName">property
+<span class="idlMethod" id=
+"idl-def-exposedthing-removeproperty-name" data-idl="" data-title=
+"removeProperty" data-dfn-for="exposedthing">    <span class=
+"idlMethType"><a href="#dom-exposedthing" class="internalDFN"
+
+"dfn">addProperty(DOMString name, PropertyFragment property, optional any initValue);
+  "dfn">  <span class=
+
+"dfn">ExposedThing 
+"idlMethName">data-lt="removeproperty()|removeProperty" href=
+"#dom-exposedthing-removeproperty" class="internalDFN"
+data-link-type="dfn">removeProperty(<span class=
+
+data-lt=
+"exposedthing.setpropertyreadhandler()|exposedthing.setpropertyreadhandler|setpropertyreadhandler()|setpropertyreadhandler"
+href="#dom-exposedthing-setpropertyreadhandler" class="internalDFN"
+data-link-type=
+"dfn">setPropertyReadHandler(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-exposedthing-addaction-action"
+data-idl="" data-title="addAction" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+"idlMethName"><a data-no-default="" data-link-for="exposedthing"
+data-lt="addaction()|addAction" href="#dom-exposedthing-addaction"
+class="internalDFN" data-link-type=
+"dfn">addAction<span class=
+"idlParamType"><a href="#dom-thingaction" class="internalDFN"
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, PropertyReadHandler readHandler);
+  "dfn"> <span class=
+"idlParamName">action
+<span class="idlMethod" id="idl-def-exposedthing-removeaction-name"
+data-idl="" data-title="removeAction" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"dfn">ExposedThing 
+"idlMethName">data-lt="removeaction()|removeAction" href=
+"#dom-exposedthing-removeaction" class="internalDFN"
+data-link-type="dfn">removeAction(<span class=
+
+data-lt=
+"exposedthing.setpropertywritehandler()|exposedthing.setpropertywritehandler|setpropertywritehandler()|setpropertywritehandler"
+href="#dom-exposedthing-setpropertywritehandler" class=
+"internalDFN" data-link-type=
+"dfn">setPropertyWriteHandler(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class="idlMethod" id="idl-def-exposedthing-addevent-event"
+data-idl="" data-title="addEvent" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+"idlMethName"><a data-no-default="" data-link-for="exposedthing"
+data-lt="addevent()|addEvent" href="#dom-exposedthing-addevent"
+class="internalDFN" data-link-type=
+"dfn">addEvent<span class=
+"idlParamType"><a href="#dom-thingevent" class="internalDFN"
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, PropertyWriteHandler writeHandler);
+  "dfn">
+<span class="idlMethod" id="idl-def-exposedthing-removeevent-name"
+data-idl="" data-title="removeEvent" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+"idlMethName"><a data-no-default="" data-link-for="exposedthing"
+data-lt="removeevent()|removeEvent" href=
+"#dom-exposedthing-removeevent" class="internalDFN" data-link-type=
+"dfn">removeEvent<span class=
+"idlParamType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString
+<span class=
+"idlSectionComment">    // define request handlers
+<span class="idlMethod" id=
+"idl-def-exposedthing-setpropertyreadhandler-name-readhandler"
+data-idl="" data-title="setPropertyReadHandler" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"dfn">ExposedThing 
+"idlMethName">data-lt="setpropertyreadhandler()|setPropertyReadHandler" href=
+"#dom-exposedthing-setpropertyreadhandler" class="internalDFN"
+data-link-type="dfn">setPropertyReadHandler(<span class=
+
+data-lt=
+"exposedthing.removeproperty()|exposedthing.removeproperty|removeproperty()|removeproperty"
+href="#dom-exposedthing-removeproperty" class="internalDFN"
+data-link-type=
+"dfn">removeProperty(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString,
+                                         <span class=
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name);
+  // define Actions
+  
+"internalDFN" data-link-type=
+"dfn">ExposedThing addAction(
+"idlParam">"#dom-propertyreadhandler" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">readHandler
+<span class="idlMethod" id=
+"idl-def-exposedthing-setpropertywritehandler-name-writehandler"
+data-idl="" data-title="setPropertyWriteHandler" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, ActionFragment init, ActionHandler action);
+  
+data-link-type=
+"dfn">ExposedThing 
+"idlMethName">data-lt="setpropertywritehandler()|setPropertyWriteHandler" href=
+"#dom-exposedthing-setpropertywritehandler" class="internalDFN"
+
+data-lt=
+"exposedthing.removeaction()|exposedthing.removeaction|removeaction()|removeaction"
+href="#dom-exposedthing-removeaction" class="internalDFN"
+
+data-link-type=
+"dfn">setPropertyWriteHandler,
+                                          <span class=
+
+"dfn">removeAction(
+"idlParam">"#dom-propertywritehandler" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">writeHandler
+<span class="idlMethod" id=
+"idl-def-exposedthing-setactionhandler-name-action" data-idl=""
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name);
+data-title="setActionHandler" data-dfn-for=
+"exposedthing">    <a href=
+"#dom-exposedthing" class="internalDFN" data-link-type=
+"dfn">  <span class=
+
+"exposedthing">
+  
+data-link-type=
+"dfn">ExposedThing 
+"idlMethName">data-lt="setactionhandler()|setActionHandler" href=
+"#dom-exposedthing-setactionhandler" class="internalDFN"
+data-link-type="dfn">setActionHandler(<span class=
+
+data-lt=
+"exposedthing.setactionhandler()|exposedthing.setactionhandler|setactionhandler()|setactionhandler"
+href="#dom-exposedthing-setactionhandler" class="internalDFN"
+data-link-type=
+"dfn">setActionHandler(
+"idlParam">"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a href="#dom-actionhandler"
+class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">action
+};
+<span class="idlCallback" id="idl-def-propertyreadhandler"
+data-idl="" data-title="PropertyReadHandler">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-propertyreadhandler" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType"><a href=
+"https://heycam.github.io/webidl/#idl-promise">Promise
+<span class="idlCallback" id="idl-def-propertywritehandler"
+data-idl="" data-title="PropertyWriteHandler">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-propertywritehandler" class="internalDFN"
+data-link-type="dfn">
+<span class="idlCallback" id="idl-def-actionhandler" data-idl=""
+data-title="ActionHandler">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString name, 
+href="#dom-actionhandler" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType"><a href=
+
+"dfn">ActionHandler action);
+  // define Events
+  
+"internalDFN" data-link-type=
+"dfn">ExposedThing addEvent(DOMString name, EventFragment event);
+  
+data-link-type=
+"dfn">ExposedThing removeEvent(DOMString name);
+};
+[NoInterfaceObject]
+interface ExposedEvents {
+  maplike<DOMString, ExposedEvent>;
+};
+callback PropertyReadHandler = Promise<any> ();
+callback PropertyWriteHandler = Promise<void> (any value);
+callback ActionHandler = 
+"https://heycam.github.io/webidl/#idl-promise">
+Promise
+
+<
+
+any
+
+>
+
+(
+
+
+
+any
+
+
+
+parameters
+
+
+);
+
+
+
+5.1 +The +start() +method + +

+Start +serving +external +requests +for +the +Thing +. +5.2 + +The + + +stop() + +properties + + + +method +Stop +serving +external +requests +for +the +Thing +. +5.3 +The + +attribute +represents +a +dictionary +of + + +register() + +ThingProperty + + +method +Generates +the +Thing +Description + + +given + +items +in +which + +the +properties, +Actions + + +read() + +and +Event +defined +for +this +object. +If +a + + +directory + +write() + + +argument +is +given, +make +a +request +to +register + +methods +define +local +methods +that +access + +the +Thing +Description +with + +physical +representations +of + +the +given +WoT +repository +by +invoking +its +register +Action + + +Properties + +. +

+5.4 + +

+The + + +unregister() + +actions + + + +method +If + +attribute +represents + +a +dictionary +of + + +directory + +ThingAction + + +argument +is +given, +make +a +request +to +unregister +the +Thing +Description + + +with + +items +in +which + +the +given +WoT +repository +by +invoking +its + + +unregister + +invoke() + + +Action +. +Then, +and +in +the +case +no +arguments +were +provided + +method +represents +a +local +method + +to +this +function, +stop +the +Thing +and +remove + +invoke + +the +Thing +Description + + +Action + +. +

+5.5 + +

+The + + +emitEvent() + +events + + + +method +Emits +an +the +event +initialized +with +the +event +name +specified +by + +attribute +represents +a +dictionary +of + +ExposedEvent + +items +that +add + +the + +eventName + +emit() + + +argument +and +data +specified +by + +method +to + +the + + +payload + +ThingEvent + + +argument. + +5.6 + + +definition. + +The + + +DataSchema + +ExposedEvents + + + +type +<span class="idlTypedef" id= +"idl-def-dataschema" data-idl="" data-title= +"DataSchema">typedef <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="" data-lt="" href="#dom-dataschema" class= +"internalDFN" data-link-type= +"dfn"> + +interface +represents +a +maplike +dictionary +where +all +values +are + + +DataSchema + +ExposedEvent + + + +objects. +

+ +5.1 + + +; + +The + + +DataSchema + +expose() + + + +method + + +type +represents +a +data +type +specified +in + +

+

+Start +serving +external +requests +for + +the + +Thing +Description + +, +so +that + +WoT +Interactions + + +in +a +serialized +form. + +using + +Properties +, +Action + +s +and + +Event + +s +will +be +possible. + +

+Editor's +note + +

+The + + +DataSchema + +expose() + + +is +under +development, +currently +it +can +denote +any +type +supported +by + +method + +MUST + +run + +the +Thing +Description + +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute + +the +WoT +Runtime + +next +steps + +in +parallel + +. +5.7 +The + +
  2. +
  3. +If +invoking + + +addProperty() + +expose() + + +method +Adds + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  4. +Make + +a +Property +defined +by + +request +to + +the +argument + +underlying +platform +to +attach +protocol +handlers + +and +updates + +start +serving +external +requests +for + +WoT +Interactions + +(read, +write +and +observe + +Properties +, +invoke + +Action + +s +and +manage + +Event + +subscriptions), +based +on + +the +Thing +Description + + +Protocol +Bindings + +. +Throws +on +error. +Returns +a +reference +to + +
  5. +
  6. +If +there +was +an +error +during + +the +same + +request, +reject + +promise + +with +an + +Error + +object +for +supporting +chaining. + + +error + +with + +error.message + +set +to +the +error +code +seen +by +the + +Protocol +Bindings + +and +terminate +these +steps. +
  7. +Otherwise +resolve + +promise + +with + +td + +and +terminate +these +steps. +

+5.7.1 + + +5.2 + + +The + + +ThingProperty + +destroy() + + + +dictionary +<span class="idlDictionary" id= +"idl-def-thingproperty" data-idl="" data-title= +"ThingProperty">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingproperty" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingproperty-name" data-idl="" +data-title="name" data-dfn-for= +"thingproperty"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-name" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingproperty-schema" data-idl= +"" data-title="schema" data-dfn-for= +"thingproperty"> required <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingproperty" +data-lt="" href="#dom-thingproperty-schema" class="internalDFN" +data-link-type="dfn"> +<span class="idlMember" id="idl-def-thingproperty-value" data-idl= +"" data-title="value" data-dfn-for= +"thingproperty"> <a href= +"https://heycam.github.io/webidl/#idl-any">any<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-value" class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingproperty-writable" +data-idl="" data-title="writable" data-dfn-for= +"thingproperty"> <a href= +"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-writable" class="internalDFN" data-link-type= +"dfn"> = <span class= +"idlMemberValue">false +<span class="idlMember" id="idl-def-thingproperty-observable" +data-idl="" data-title="observable" data-dfn-for= +"thingproperty"> <a href= +"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-no-default="" +data-link-for="thingproperty" data-lt="" href= +"#dom-thingproperty-observable" class="internalDFN" data-link-type= +"dfn"> = <span class= +"idlMemberValue">false +}; + +method + + +

+

+Represents + +Stop +serving +external +requests +for + +the + +Thing + +Property +description. + +and +destroy +the +object. +Note +that +eventual +unregistering +should +be +done +before +invoking +this +method. + +

+

+The + +name + +destroy() + + +attribute +represents + +method + +MUST + +run + +the +name +of + +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute + +the +Property + +next +steps + +in +parallel + +. +
  2. +
  3. +The + +If +invoking + + +schema + +destroy() + + +attribute +represents +the +data +type + +is +not +allowed + +for +the +Property +described +by + +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +DataSchema + +SecurityError + + +. + +and +terminate +these +steps. + +
  4. +
  5. +The +value +attribute +represents + +Make +a +request +to + +the +value +of + +underlying +platform +to +stop +serving +external +requests +for + +WoT +Interactions +, +based +on + +the +Property + + +Protocol +Bindings + +. +
  6. +
  7. +The + +If +there +was +an +error +during +the +request, +reject + +promise + +with +an + + +writable + +Error + + +attribute +defines +whether + +object + +error + +with + +error.message + +set +to + +the +Property + +error +code +seen +by +the + +Protocol +Bindings + + +can +be +updated. +The +default +value +is +false +. + +and +terminate +these +steps. + +
  8. +
  9. +The + +Otherwise +resolve + +promise + +with + +td + +and +terminate +these +steps. +

+ +5.3 + +The + + +observable + +addProperty() + + + +attribute +defines +whether +the + +method +

+Adds +a + + +Property + +changes +can +be +observed + +with +name +defined +by +the + +name + +argument, +the +data +schema +provided + +by +the + +property + +argument +of +type + +PropertyFragment +, +and +optionally + +an +external +client. +The +default + +initial + +value +provided +in +the +argument + +initValue + +whose +type +should +match +the +one +defined +in +the + +type + +property +according +to +the + +value-matching +algorithm +. +If + +initValue + +is +not +provided, +it + +SHOULD + +be +initialized +as + + +false + +undefined + +. +Implementations + +SHOULD + +update +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.8 + +5.4 + + +The + + +removeProperty() + + +method + + +

+

+Removes +the + +Property + +specified +by +the + +name + +argument +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.9 + +5.5 + + +The + + +addAction() + + +method + + +

+

+Adds +an +Action + +to +the + +actions + +property +of +a + +Thing + +object +as + +an + +Action + +with +name + +defined +by +the +action + + +name + +argument, +defines +input +and +output +data +format +by +the + +init + +argument +of +type + + +ThingAction + +ActionFragment + + +, +and +adds +the +function +provided +in +the + +action + +argument +as +a +handler, +then + +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+5.9.1 +The +ThingAction +dictionary +<span class="idlDictionary" id= +"idl-def-thingaction" data-idl="" data-title= +"ThingAction">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingaction" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingaction-name" data-idl="" +data-title="name" data-dfn-for= +"thingaction"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingaction" data-lt="" href="#dom-thingaction-name" +class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingaction-inputschema" +data-idl="" data-title="inputSchema" data-dfn-for= +"thingaction"> <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingaction" +data-lt="" href="#dom-thingaction-inputschema" class="internalDFN" +data-link-type="dfn"> +<span class="idlMember" id="idl-def-thingaction-outputschema" +data-idl="" data-title="outputSchema" data-dfn-for= +"thingaction"> <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingaction" +data-lt="" href="#dom-thingaction-outputschema" class="internalDFN" +data-link-type="dfn"> +}; + +

+The +ThingAction + +provided + +action + +callback +function +will +implement +invoking +an + +Action + + +dictionary +describes +the +arguments + +and + +SHOULD + +be +called +by +implementations +when +a +request +for +invoking + +the +return +value. +The +name +attribute +provides +the + + +Action + +name. +The +inputSchema +attribute +provides +the +description +of +the +input +arguments +(argument +list + +is +represented +by +an +object). +If +missing, +it +means + +received +from + +the +action +does +not +accept +arguments. + +underlying +platform. + +The +callback +will +receive +a + + +outputSchema + +parameters + + +attribute +provides + +dictionary +argument +according +to + +the +description + +definition +in +the + +init.input + +argument +and +will +return +a +value + +of +type +defined +by + +the +returned +data. +If +missing, +it +means + + +init.output + +argument +according +to + +the +action +does +not +return +data. + + +value-matching +algorithm +.

+There + +SHOULD + +be +exactly +one +handler +for +any +given + +Action +. +If +no +handler +is +initialized +for +any +given + +Action +, +implementations + +SHOULD + +throw +a + +TypeError +.

+
+
+

+ +5.10 + +5.6 + + +The + + +removeAction() + + +method + + +

+

+Removes +the + +Action + +specified +by +the + +name + +argument +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.11 + +5.7 + + +The + + +addEvent() + + +method + + +

+

+Adds +an +event +to +the +Thing +object +as + +with +name + +defined +by +the + +name + +argument +and +qualifiers +and +initialization +value +provided +by +the + +event + +argument +of +type + + +ThingEvent + +EventFragment + + + +to +the + +Thing + +object + +and +updates +the + +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+5.11.1 +The +ThingEvent +dictionary +<span class="idlDictionary" id= +"idl-def-thingevent" data-idl="" data-title= +"ThingEvent">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingevent" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-semanticannotations" class= +"internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-thingevent-name" data-idl="" +data-title="name" data-dfn-for= +"thingevent"> required <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="thingevent" data-lt="" href="#dom-thingevent-name" +class="internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-thingevent-schema" data-idl="" +data-title="schema" data-dfn-for= +"thingevent"> <a href= +"#dom-dataschema" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMemberName"><a data-no-default="" data-link-for="thingevent" +data-lt="" href="#dom-thingevent-schema" class="internalDFN" +data-link-type="dfn"> +}; +The +name +attribute +represents +the +event +name. +The +schema +attribute +represents +the +type +of +the +data +that +is +attached +to +the +event. +If +missing, +it +means +the +event +does +not +carry +data. + +
+
+

+5.12 + + +5.8 + + +The + + +removeEvent() + + +method + + +

+

+Removes +the +event +specified +by +the + +name + +argument +and +updates +the + +Thing +Description +. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+
+
+

+ +5.13 + +5.9 + + +The + + +PropertyReadHandler + + +callback + + +

+

+A +function +that +returns + +is +called +when +an +external +request +for +reading +a + +Property + +is +received. +It +should +return + +a +Promise +and +resolves +it +with +the +value +of +the + +Property + +matching +the + +name + +argument +to +the + +setPropertyReadHandler + +function, +or +rejects +with +an +error +if +the +property +is +not +found +or +the +value +cannot +be +retrieved. +

+
+
+

+ +5.14 + +5.10 + + +The + + +PropertyWriteHandler + + +callback + + +

+

+A +function +that +is + +called +with + +when +an +external +request +for +writing +a + +Property + +is +received. +It +is +given +the +requested +new + + +value + +as +argument +that +returns + +and +should +return + +a +Promise +which +is +resolved +when +the +value +of +the + +Property + +matching + +that +matches + +the + +name + +argument +to +the +setPropertyReadHandler +function +is + +has +been + +updated +with + +value +, +or +rejects +with +an +error +if +the +property +is +not +found +or +the +value +cannot +be +updated. +

+
+
+ +Editor's +note + +
+

+Note +that +this +function +is +invoked +by +implementations +before +the +property +is +updated, +so +the + +updated +and +it +actually +defines +what +to +do +when +a +write +request +is +received. +The + +code +in +this +callback +function +can +invoke +the + +readProperty() + +read() + + +method +to +find +out +the +old +value +of +the +property, +if +needed. +Therefore +the +old +value +is +not +provided +to +this +method. + +function. + +

+
+
+
+

+ +5.15 + +5.11 + + +The + + +ActionHandler + + +callback + + +

+

+A +function +called +with +a + +parameters + +dictionary +argument +assembled +by +the + +WoT +runtime + +based +on +the + +Thing +Description + +and +the +external +client +request. +It +returns +a +Promise +that +rejects +with +an +error +or +resolves +if +the +action +is +successful +or +ongoing +(may +also +resolve +with +a +control +object +such +as +an + + +Observable + + +for +actions +that +need +progress +notifications +or +that +can +be +canceled). +

+
+
+

+ +5.16 + +5.12 + + +The + + +setPropertyReadHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +readHandler + +as +argument +of +type + + +PropertyReadHandler + +. +Sets +the +handler +function +for +reading +the +specified + +Property + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+

+The + +readHandler + +callback +function +will +implement +reading +a + +Property + +and + +SHOULD + +be +called +by +implementations +when +a +request +for +reading +a + +Property + +is +received +from +the +underlying +platform. +

+

+There + +SHOULD + +be +at +most +one +handler +for +any +given + +Property + +and +newly +added +handlers +replace +the +old +handlers. +If +no +handler +is +initialized +for +any +given + +Property +, +implementations + +SHOULD + +implement +a +default +property +read +handler. +

+

+When +an +external +request +for +reading + +Property + +propertyName + +is +received, +the +runtime + +SHOULD + +execute +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +a + +Property + +with + +propertyName + +does +not +exist, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  3. +Otherwise, +if +no +read +handler +has +been +defined +for + +propertyName +, +resolve + +promise + +with +the +value +of +the + +Property + +named + +propertyName + +provided +by +the +runtime +implementation +and +terminate +these +steps. +
  4. +Otherwise, +invoke +the +read +handler +associated +with + +propertyName +. +If +it +rejects, +then +reject + +promise + +with +the +same +error, +and +resolve + +promise + +with +the +same +value. +
+
+
+

+ +5.17 + +5.13 + + +The + + +setPropertyWriteHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +writeHandler + +as +argument +of +type + + +PropertyWriteHandler + +. +Sets +the +handler +function +for +writing +the +specified + +Property + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+

+There + +SHOULD + +be +at +most +one +write +handler +for +any +given + +Property + +and +newly +added +handlers +replace +the +old +handlers. +If +no +write +handler +is +initialized +for +any +given + +Property +, +implementations + +SHOULD + +implement +default +property +update +and +notifying +observers +on +change. +

+

+When +an +external +request +for +writing +a + +Property + +propertyName + +with +a +new +value + +value + +is +received, +the +runtime + +SHOULD + +execute +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +a + +Property + +with + +propertyName + +does +not +exist, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  3. +Otherwise, +if +no +write +handler +has +been +defined +for + +propertyName +, +the +runtime +implementation + +SHOULD + +update +the + +Property + +value +with + +value +, +resolve + +promise + +and +terminate +these +steps. +
  4. +Otherwise, +invoke +the +write +handler +associated +with + +propertyName + +providing + +value + +as +argument. +If +it +rejects, +then +reject + +promise + +with +the +same +error, +and +resolve + +promise + +with +the +same +value. +
+
+
+

+ +5.18 + +5.14 + + +The + + +setActionHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +action + +as +argument +of +type + + +ActionHandler + +. +Sets +the +handler +function +for +the +specified + +Action + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. +

+

+If +provided, +this + +The + +action + +callback +function +will +implement +invoking + +an + +Action + +and + +SHOULD + +be +called +by +implementations +when +a +request +for +invoking +a + +the + +Action + +is +received +from +the +underlying +platform. +The +callback +will +receive +a +parameters +dictionary +argument. + +

+

+There + +SHOULD + +be +exactly + +at +most + +one +handler +for +any +given + +Action + +and +newly +added +handlers +replace +the +old +handlers. +

+When +an +external +request +for +invoking +the + +Action + +identified +by + +name + +is +received, +the +runtime + +SHOULD + +execute +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel + +. +
  2. +
  3. +If +an + +Action + +identified +by + +name + +does +not +exist, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  4. +Otherwise, +if + +no +action + +handler +is +initialized + +has +been +defined + +for +any +given + + +name +, +reject + +promise + +with +a + +ReferenceError + +and +terminate +these +steps. +
  5. +Otherwise, +invoke +the + + +Action +, +implementations +SHOULD +return + + +handler +associated +with + +name +. +If +it +rejects +with + +error +, +then +reject + +promise + +with +the +same + +error +, +otherwise + +if +it +resolves +with + +value +, +then +resolve + +promise + +with + +the +action +is +invoked +by +any +client. + +same + +value +.
+
+
+

+ +5.19 + +5.15 + + +Examples + + +

+

+Below +some + + + +ExposedThing + + + +interface +examples +are +given. +

+
+
+ +Example +7 + +5 + +: + +: +Create +a +new +blank + +exposed +Thing +with +a +simple +property + + +
+
+        try {
+  "hljs-keyword">var thing = WoT.produce({ <span class=
+"hljs-attr">name: <span class=
+"hljs-string">"tempSensor" });
+  
+  thing.addProperty({
+    : <span class=
+"hljs-string">"temperature",
+    : <span class=
+"hljs-number">0.0,
+    : <span class=
+"hljs-string">'{ "type": "number" }'
+    <span class=
+"hljs-comment">// use default values for the rest
+  }).addProperty({
+    : <span class=
+"hljs-string">"max",
+    : <span class=
+"hljs-number">0.0,
+    : <span class=
+"hljs-string">'{ "type": "number" }'
+    <span class=
+"hljs-comment">// use default values for the rest
+  }).addAction({
+    : <span class=
+"hljs-string">"reset",
+    
+  }).addEvent({
+
+"hljs-keyword">var temperatureValueDefinition = {
+    type: 
+"hljs-string">"number",
+    minimum: 
+"hljs-number">-50,
+    maximum: 
+"hljs-number">10000
+  };
+  
+"hljs-keyword">var temperaturePropertyDefinition = temperatureValueDefinition;
+  // add the 'forms' property
+  temperaturePropertyDefinition.forms = [ ... ];
+  var thing = WoT.produce({
+    name: "hljs-string">"onchange",
+    : <span class=
+"hljs-string">'{ "type": "number" }'
+  });
+  
+  thing.setActionHandler(<span class=
+"hljs-string">"reset", () => {
+    .log(<span class=
+"hljs-string">"Resetting maximum");
+    thing.writeProperty(<span class=
+"hljs-string">"max");
+  });
+  thing.start().then(<span class=
+"hljs-params">() {
+      thing.register();
+
+"hljs-string">"tempSensor",
+    properties: {      
+"hljs-attr">temperature: temperaturePropertyDefinition
+    },
+    actions: {      reset: {        description: 
+"hljs-string">"Reset the temperature sensor",
+        input: {          
+"hljs-attr">temperature: temperatureValueDefinition
+        },
+        output: 
+"hljs-literal">null,
+        forms: []
+      },
+    },
+    events: {      
+"hljs-attr">onchange: temperatureValueDefinition
+    },
+    links: []
+  });
+  await thing.expose();
+  await wot.register("hljs-string">"https://mydirectory.org", thing);
+
+  // define Thing business logic
+  setInterval( async () => {
+    let mock = Math.random()*100;
+    thing.writeProperty(<span class=
+"hljs-string">"temperature", mock);
+
+    let old = "hljs-keyword">await thing.readProperty(<span class=
+"hljs-string">"max");
+
+"hljs-keyword">await thing["temperature"].read();
+
+    if (old < mock) {
+      thing.writeProperty(<span class=
+"hljs-string">"max", mock);
+      thing.emitEvent();
+
+      await thing["hljs-string">"temperature"].write(mock);
+      thing.emitEvent("onchange", mock);
+
+    }
+  }, 1000);
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+
+ +Example +8 + +6 +: +Create +a +new +exposed +Thing +with +object +property + + +: + +
+
+        try {
+  var statusValueDefinition = {
+    type: "hljs-string">"object",
+    properties: {      brightness: {        type: 
+"hljs-string">"number",
+        minimum: 
+"hljs-number">0.0,
+        maximum: 
+"hljs-number">100.0,
+        required: 
+"hljs-literal">true
+      },
+      rgb: {        type: 
+"hljs-string">"array",
+        "minItems": 
+"hljs-number">3,
+        "maxItems": 
+"hljs-number">3,
+        items : {            "type" : 
+"hljs-string">"number",
+            
+"hljs-string">"minimum": 0,
+            
+"hljs-string">"maximum": 255
+        }
+      }
+  };
+  
+"hljs-keyword">var statusPropertyDefinition = statusValueDefinition;
+  // add the 'forms' property
+  statusPropertyDefinition["forms"] = [];
+  var thing = WoT.produce({    name: 
+"hljs-string">"mySensor",
+    properties: {      brightness: {        type: 
+"hljs-string">"number",
+        minimum: 
+"hljs-number">0.0,
+        maximum: 
+"hljs-number">100.0,
+        required: 
+"hljs-literal">true,
+      },
+      
+"hljs-attr">status: statusPropertyDefinition
+    },
+    actions: {      status: {        description: 
+"hljs-string">"Get status object",
+        input: 
+"hljs-literal">null,
+        output: {          
+"hljs-attr">status : statusValueDefinition;
+        },
+        forms: []
+      },
+    },
+    events: {      
+"hljs-attr">onstatuschange: statusValueDefinition;
+    },
+    links: []
+  });
+  thing.expose().then(() => {
+      thing.register();
+  });
+} catch (err) {
+   console.log(
+"hljs-string">"Error creating ExposedThing: " + err);
+}
+
+Example +7 +: +Create +a +new +exposed +Thing +from +a +Thing +Description + +
+
+        let thingDescription = "hljs-string">'{ "@context": [ "https://w3c.github.io/wot/w3c-wot-td-context.jsonld", "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ], "@type": [ "Thing", "Sensor" ], "name": "mySensor", "geo:location": "testspace", "interaction": [ { "@type": [ "Property", "Temperature" ], "name": "prop1", "schema": { "type": "number" }, "saref:TemperatureUnit": "degree_Celsius" } ] }';
+
+"hljs-string">'{ \
+  "name": "mySensor", \
+  "@context": [ "http://www.w3.org/ns/td",\
+     "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ],\
+  "@type": [ "Thing", "Sensor" ], \
+  "geo:location": "testspace", \
+  "properties": { \
+    "prop1": { \
+      "type": "number",\
+      "@type": [ "Property", "Temperature" ], \
+      "saref:TemperatureUnit": "degree_Celsius" \
+  } } }';
+
+try {
+  // note that produce() fails if thingDescription contains error
+  let thing = WoT.produce(thingDescription);
+  // Interactions were added from TD
+  // WoT adds generic handler for reading any property
+  // define a specific handler for one property
+  let name = "examplePropertyName";
+  thing.setPropertyReadHandler(name, () => {
+    console.log("Handling read request for " + name);
+    return new Promise((resolve, reject) => {
+        let examplePropertyValue = 5;
+        resolve(examplePropertyValue);
+      },
+      e => {
+        console.log("Error");
+      });
+  });
+  thing.start();
+
+  thing.expose();
+
+} catch(err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+
+
+
+
+ +Example +9 + +8 + +: + +: +Create +a +new +exposed +Thing +from +a +TD +URI + +
+
+        // fetch an external TD, e.g., to set up a proxy for that Thing
+WoT.fetch("http://myservice.org/mySensor/description").then(td => {
+  // WoT.produce() ignores instance-specific metadata (security, form)
+  let thing = WoT.produce(td);
+  // Interactions were added from TD
+  // add server functionality
+  // ...
+});
+
+
+
+
+
+

+ +6. + +Experimental +extensions +to +the +ConsumedThing +interface + +Data +types +and +structures + +

+

+The +[ + +This +section +is +non-normative. + + +WOT-TD + + +] +specification +defines +the + +WoT +information +model +, +i.e. +the +data +types +and +data +structures +used +in + +WoT +Interactions +. +In +this +API +these +definitions +translate +to +dictionary +objects +that +are +extended +with +methods +by +the +interfaces +defined +in +this +specification. + +

+

+In +order +to +avoid +duplication +of +definitions, +references +to +these +data +types +and +structures +is +defined +in +this +section, +but +for +their +full +description +please +refer +to +the + +Thing +Description +specification +.

+6.1 + +The + + +ThingDescription + +DataSchema + + + +dictionary +and +its +subclasses + + +related +functionality, +such +as +enumerating + +

+

+Value +types +basically +represent +types +that +may +be +used +in + +JSON + +object +definitions +and +are +used +in + +ThingFragment + +to +define + +Properties +, +Action +s, + + +Event + +s +and +links +(introspection) + + +Action + +parameters. +Value +types +are +represented +as +dictionary +objects +whose +properties +and +possible +sub-classes +are +defined +in +the + +DataSchema + +section +of +[ + +WOT-TD + +]. +

+One +property +of +all + +DataSchema + +dictionary + +is +an +API +extension +that + +the + +type + +property +whose +value + +is +out + +from +a +set + +of +scope +for + +enumerated +strings +defined +in +the + +DataSchema + +section +of +[ + +WOT-TD + +] +and +is +referred +as + +DataType + +in + +this +specification. +However, + +

+

+Based +on + +type +, +the +draft +interfaces + +following +sub-classes +of + +DataSchema + +are +defined +here +for +informative +purposes. +<span class="idlInterface" id= +"idl-def-consumedthing-partial-1" data-idl="" data-title= +"ConsumedThing">partial interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-consumedthing" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMethod" id="idl-def-consumedthing-getproperties" +data-idl="" data-title="getProperties" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-thingproperty" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getproperties()|getProperties" href= +"#dom-consumedthing-getproperties" class="internalDFN" +data-link-type="dfn">getProperties +<span class="idlMethod" id="idl-def-consumedthing-getactions" +data-idl="" data-title="getActions" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-thingaction" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getactions()|getActions" href= +"#dom-consumedthing-getactions" class="internalDFN" data-link-type= +"dfn">getActions +<span class="idlMethod" id="idl-def-consumedthing-getevents" +data-idl="" data-title="getEvents" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-thingevent" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getevents()|getEvents" href="#dom-consumedthing-getevents" +class="internalDFN" data-link-type= +"dfn">getEvents +<span class="idlMethod" id="idl-def-consumedthing-getlinks" +data-idl="" data-title="getLinks" data-dfn-for= +"consumedthing"> <a href= +"https://heycam.github.io/webidl/#idl-sequence">sequence<<a href="#dom-tdlink" +class="internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="consumedthing" +data-lt="getlinks()|getLinks" href="#dom-consumedthing-getlinks" +class="internalDFN" data-link-type= +"dfn">getLinks +}; + +in +[ + + +WOT-TD + + +]: + +BooleanSchema + +6.1 + +, + + +NumberSchema +, +IntegerSchema +, +StringSchema +, +ObjectSchema +, +ArraySchema +.

+6.2 + + +The + + +getProperties() + +SecurityScheme + + + +method + +dictionary +and +its +subclasses + +

+

+Returns +the +list +of +Properties + +Security +metadata +is +represented +as +dictionary +objects +whose +properties +and +sub-classes +are + +defined +in +the +Thing +Description + + +SecurityScheme + + +section +of +[ + +WOT-TD + +]. +

+One +property + +of +the +Thing + + + +SecurityScheme + + +dictionary +is +the + +scheme + +property +whose +value +is +from +a +set +of +enumerated +strings +defined + +in +the +form + + +SecurityScheme + +section + +of +a +list + +[ + +WOT-TD + +]. +Based +on + +type +, +multiple +subclasses + +of + + +ThingProperty + +SecurityScheme + + + +objects. + +are +defined. + +

+
+

+6.4 + +The + +Form + +dictionary +

+Represents +metadata +describing +service +details, +with +properties + +defined +in +the +Thing +Description + + +Form + + +section + +of +[ + +WOT-TD + +]. +

+6.5 + +The + +InteractionFragment + +dictionary +

+Represents + +the +Thing + +common +properties +of + +WoT +Interactions +, +one +of + +Property +, +Action + + +or + +Event +, +as +defined + +in +the +form + + +InteractionPattern + +section + +of +[ + +WOT-TD + +]. +Its +subclasses +are +referred +as + +PropertyFragment +, +ActionFragment + +and + +EventFragment +.

+6.6 + +The + +PropertyFragment + +dictionary +

+Represents +the + +Property + +interaction +data +that +initializes + +a +list + + + +ThingProperty + +object. +Its +properties +are +defined +in +the + +Property + +and + +InteractionPattern + +sections + +of +[ + +WOT-TD + +]. +

+6.7 + +The + +ActionFragment + +dictionary +

+Represents +the + +Action + +interaction +data +that +initializes +a + + + +ThingAction + + +objects. + +object. +Its +properties +are +defined +in +the + +Action + +and + +InteractionPattern + +sections +of +[ + +WOT-TD + +]. + +

+
+
+

+6.3 + + +6.8 + + +The + + +getEvents() + +EventFragment + + + +method + +dictionary + +

+

+Returns + +Represents + +the +list +of + + +Event + +s + +interaction +data +that +initializes +a + +ThingEvent + +object. +Its +properties +are + +defined +in +the +Thing +Description + + +Event + + +section + +of +the + +[ + +WOT-TD + +]. +

+6.9 + +The + +ThingFragment + +dictionary +

+The + +ThingFragment + +dictionary +is +defined +as + +Thing + + +in +the +form +of + +[ + +WOT-TD + +]. +It +is + +a +list + +dictionary +that +contains +properties +representing +semantic +metadata +and +interactions +( + +Properties +, +Action + +s +and + +Event + +s). +It +is +used +for +initializing +an +internal +representation + +of +a + +Thing +Description + +and +its +properties +may +be +used +in + + +ThingEvent + +ThingFilter + + +objects. + +. +

+
+
+

+6.4 + + +6.10 + + +The + + +getLinks() + +ThingDescription + + + +method + +type + +

+

+Returns +the +list + +Serialized +representation + +of +linked +resources +in + +the + + +Thing +Description + +(a + +JSON-LD + +document). +

+Note +

+In +this +version + +of +the +API, + +Thing +Description + +s +are +represented +as +an +opaque + +USVString + +that +can +be +transmitted +between +devices. +

+7. + +Interfaces +for + +WoT +Interactions + + + + +

+

+The +data +types +and +structures +imported +from +[ + +WOT-TD + +] +are +extended +by +this +specification + +in +order +to +provide + +the +form +of +a +list +of + +interfaces +for + +WoT +Interactions +.

+Every + +Thing + +describes +its +metadata +as +defined +in + + +TDLink + +ThingFragment + + +, +and +basic +interactions +defined +as + +Properties +, +Action + + +objects. + +s +and + +Event + +s. +The +following +interfaces +are +used +for +representing +these +interactions. + +

+
+

+ +6.4.1 + +7.1 + + +The + + +TDLink + +Interaction + + + +dictionary + +interface +

+

+Contains +a +hyperlink +reference, +a +relation +type + +The + +Interaction + +interface +is +an +abstract +class +to +represent + +Thing + +interactions: + +Properties +, +Actions + +and + +Events +.

+The + +InteractionFragment + +dictionary +holds +the +common +properties +of + +PropertyFragment +, +ActionFragment + +and + +EventFragment + +dictionaries +used +for +initializing + +ThingProperty +, +ThingAction + +and + +ThingEvent + +objects +in + +a +media +type. + + + +ThingFragment + +dictionary +used +for +creating +an + +ExposedThing + +object. + +

+
+<span class="idlDictionary" id= +"idl-def-tdlink" data-idl="" data-title= +"TDLink">dictionary <span class= +"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-tdlink" class="internalDFN" data-link-type= +"dfn"> { +<span class="idlMember" id="idl-def-tdlink-href" data-idl="" +data-title="href" data-dfn-for="tdlink"> required <span class= +"idlMemberType"><a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="tdlink" data-lt="" href="#dom-tdlink-href" class= +"internalDFN" data-link-type= +"dfn"> +<span class="idlMember" id="idl-def-tdlink-mediatype" data-idl="" +data-title="mediaType" data-dfn-for= +"tdlink"> <a href= +"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default="" +data-link-for="tdlink" data-lt="" href="#dom-tdlink-mediatype" + +
"idl-def-interaction" data-idl="" data-title=
+"Interaction">interface Interaction {
+  readonly attribute (Form or FrozenArray<Form>) 
+class="internalDFN" data-link-type=
+"dfn">
+<span class="idlMember" id="idl-def-tdlink-rel" data-idl=""
+data-title="rel" data-dfn-for="tdlink">             <span class=
+"idlMemberType"><a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default=""
+data-link-for="tdlink" data-lt="" href="#dom-tdlink-rel" class=
+"internalDFN" data-link-type=
+"dfn">
+};
+
+"dfn">forms;
+};
+
+"dfn">Interaction includes 
+
+InteractionFragment
+
+;
+
+
+
+
+

+The + + +TDLink + +forms + +read-only +property +represents +the +protocol +bindings +initialization +data +and +is +initialized +by +the + +WoT +Runtime +.

+7.2 + +The + +ThingProperty + +interface +

+The + +ThingProperty + +interface +is +used +in + +ConsumedThing + +and + +ExposedThing + +objects +to +represent + +Thing + +Property + +interactions. +

+The + +PropertyFragment + + + +dictionary +contains + +is +used +for +initializing + +Property + +objects +in +a + +ThingFragment + +dictionary +used +for +creating +an + +ExposedThing + +object. +It + +MUST + +implement +one +of + +the +following +properties: + + + +DataSchema + +dictionaries. + +

+
+
"idl-def-thingproperty" data-idl="" data-title=
+"ThingProperty">interface ThingProperty : Interaction {
+  // getter for PropertyFragment properties
+  getter 
+"https://heycam.github.io/webidl/#idl-any">any (DOMString name);
+  // get and set interface for the Property
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> read();
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> write(any value);
+};
+
+"dfn">ThingProperty includes PropertyFragment;
+
+"dfn">ThingProperty includes 
+
+Observable
+
+;
+

+The + + +href + +ThingProperty + + + +interface +contains +all +the +properties +defined +on + +PropertyFragment + +as +read-only +properties. +

+The + +type + + +attribute + +read-only +property + +represents +the +type +definition +for +the + +Property + +as + +a +hyperlink +reference + + + +DataSchema + +dictionary +object. +

+The + +writable + +read-only +property +tells +whether +the + +Property + +value +can +be +updated. +If +it +is + +false +, +then +the + +set(value) + +method + +SHOULD + +always +reject. +

+The + +observable + +read-only +property +tells +whether +the + +Property + +supports +subscribing +to +value +change +notifications. +If +it +is + +false +, +then +the + +subscribe() + +method + +SHOULD + +always +fail. +

+The + +constant + +read-only +property +- +defined +in + +DataSchema + +- +tells +whether +the + +Property + +value +is +a +constant. +If + +true +, +the + +set() + +and + +subscribe() + +methods + +SHOULD + +always +fail. +

+The + +required + +read-only +property +- +defined +in + +DataSchema + +- +tells +whether +the + +Property + +should +be +always +present +on +the + +ExposedThing + +object. +

+The + +read() + +method +will +fetch +the +value +of +the + +Property + +. +Returns +a + +Promise + +that +resolves +with +the +value, +or +rejects +with +an +error. +

+The + + +rel + +write() + + + +attribute +represents + +method +will +attempt +to +set +the +value +of +the + +Property + +specified +in +the + +value + +argument +whose +type + +SHOULD + +match +the +one +specified +by +the + +type + +property. +Returns + +a +relation + + +Promise + +that +resolves +on +success, +or +rejects +on +an +error. +

+7.3 + +The + +ThingAction + +interface +


+"idl-def-thingaction" data-idl="" data-title=
+"ThingAction">interface ThingAction : Interaction {
+  
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> invoke(optional any inputValue);
+};
+
+"dfn">ThingAction includes 
+
+ActionFragment
+
+;
+

+The + +invoke() + +method +when +invoked, +starts +the + +Action + +interaction +with +the +input +value +provided +by +the + +inputValue + +argument. +If + +inputValue + +is + +null +, +the +action +does +not +take +any +arguments +and +rejects +if +any +arguments +are +provided. +If +the +value +is + +undefined +, +the +action +will +ignore +any +arguments +provided. +Otherwise +the + +type +of + +inputValue + +SHOULD + +match +the + +DataSchema + +definition +in +the + +input + +property. +Returns +a + +Promise + +that +will +reject +with +an +error +or +will +resolve +with +a +value +of +type +defined +by +the + +output + +property. +

+7.4 + +The + +ThingEvent + +interface +


+"idl-def-thingevent" data-idl="" data-title=
+"ThingEvent">interface ThingEvent : Interaction {
+};
+
+"dfn">ThingEvent includes EventFragment;
+
+"dfn">ThingEvent includes 
+
+ThingProperty
+
+;
+

+Since + +ThingEvent + +implements + +Observable + +through +the + +ThingProperty + +interface, +event +subscription +is +done +by +invoking +the + +subscribe() + +method +on +the +event +object +that +returns +a +cancelable + +Subscription + +. +

+
+
+

+ +7.5 + +The + + +mediaType + +ExposedEvent + + + +attribute +represents + +interface +


+"idl-def-exposedevent" data-idl="" data-title=
+"ExposedEvent">interface ExposedEvent : ThingEvent {
+  void emit(any payload);
+};
+

+7.5.1 + +The + +emit() + +method +

+Emits +an +event +that +carries +data +specified +by +the + +payload + +argument. +

+7.6 + +The + +value-matching +algorithm +

+The +value-matching +algorithm +is +applied +to + +a +IANA +media + + +value + +input +in +relation +to +a + +valueType + +property +of + +type +. +For +TD + + + +DataSchema +, +for +instance +the + +value + +and + +type + +properties +of +a + +PropertyFragment + + +s +there +will +be +registered +media +types, +so +applications +will +be +able + +object, +or +the + +inputValue + +parameter + +to +check +whether +an + +the + + +href + +invoke() + + +link +points + +method +of +a + +ThingAction + +object +in +relation + +to +the +same +object. +It +executes +the +following +steps: +

  1. +If + +valueType.type + +is +not +defined, +or +does +not +fully +match + +a +TD + +string +enumerated +in + +DataType + +, +i.e. +whether + +return + +false +.
  2. +Otherwise, +if + +valueType.type + +is + +"null" +: +if + +value + +is + +null +, +return + +true +, +otherwise +return + +false +.
  3. +Otherwise, +if + +valueType.type + +is + +"boolean" +: +if + +value + +is +either + +true + +or + +false +, +then +return + +true +, +otherwise +return + +false +.
  4. +Otherwise, +if + +valueType.type + +is + +"integer" +: +if + +value + +is +not +an +integer +type +defined +by + +the +link + +underlying +platform +(such +as + +long + +or + +long +long + +), +then +return + +false +, +otherwise +execute +the +following +sub-steps: +
    1. +If + +valueType.minimum + +is +fetcheable +with + +defined +and + +value + +is +not +greater +or +equal +than +that +value, +return + +false +.
    2. +If + +valueType.maximum + +is +defined +and + +value + +is +not +less +or +equal +than +that +value, +return + +false +.
    3. +Return + +true +.
  5. +Otherwise, +if + +valueType.type + +is + +"number" +, +if + +value + +is +not +an +integer +or +floating +point +type +defined +by +the +underlying +platform +(such +as + +long + +or + +long +long + +or + +double + +), +then +return + +false +, +otherwise +otherwise +execute +the +following +sub-steps: +
    1. +If + +valueType.minimum + +is +defined +and + +value + +is +not +greater +or +equal +than +that +value, +return + +false +.
    2. +If + +valueType.maximum + +is +defined +and + +value + +is +not +less +or +equal +than +that +value, +return + +false +.
    3. +Return + +true +.
  6. +Otherwise, +if + +valueType.type + +is + +"string" +: +if + +value + +is +not +a +string +type +defined +by +the +underlying +platform, +then +return + +false +, +otherwise +return + +true +. +In + +this +API. + +case +the +algorithm +expects +a +third +parameter + +valueType.enum + +and +runs +the +following +sub-steps: +
    • +If + +valueType.enum + +is +an +array +of +strings, +then +if + +value + +fully +matches +one +of +the +strings +defined +in +the +array, +return + +true +.
    • +Otherwise, +return + +false +. +
    • +
    +
  7. +
  8. +Otherwise, +if + +valueType.type + +is + +"array" +, +execute +the +following +sub-steps: +
    1. +If + +value + +is +not +an +array, +return + +false +.
    2. +If + +valueType.minItems + +is +defined, +and + +value + +does +not +contain +at +least + +valueType.minItems + +elements, +return + +false +.
    3. +If + +valueType.maxItems + +is +defined, +and + +value + +contains +more +than + +valueType.maxItems + +elements, +return + +false +.
    4. +Otherwise, +if + +valueType.items + +is + +undefined +, +return + +false +.
    5. +Otherwise, +if + +valueType.items + +is + +null +, +return + +true + +(i.e. +any +type +is +accepted +as +array +element, +including +heterogenous +arrays). +
    6. +Otherwise, +for +each +element +of +the +array + +value + +run +the + +value-matching +algorithm + +against +the + +valueType.items + +object. +If +any +of +these +runs +returns + +false +, +then +return + +false +.
    7. +Otherwise, +return + +true +.
  9. +Otherwise, +if + +type + +is + +"object" +, +execute +the +following +sub-steps: +
    1. +If + +value + +is +not +an + +Object +, +return + +false +.
    2. +If + +valueType.properties + +is +not +defined, +return + +false +.
    3. +If + +valueType.properties + +is + +null +, +return + +true + +(i.e. +accept +any +object +value). +
    4. +For +each +string +in +the + +valueType.required + +array, +if +it +does +not +match +a +property +name +in +the + +value.properties + +object +or +in +the + +value + +object, +then +return + +false +.
    5. +For +each +property +with +name + +propName + +and +value + +propDataSchema + +found +in + +valueType.properties +, +run +the +following +sub-steps: +
      1. +If +the +result +of +applying +the + +value-matching +algorithm + +on +the +value + +value[propName] + +and + +propDataSchema + +is + +false +, +then +return + +false +.
    6. +Return + +true +.
+
+
+
+

+ +7. + +8. + + +Observables + + +

+

+ +This +section +is +non-normative. + +

+

+ +Observables + +are + +proposed + +to +be +included +in +ECMAScript +and +are +used +for +handling +pushed +data +associated +with +various +possible +sources, +for +instance +events, +timers, +streams, +etc. +A +minimal +required +implementation +is +described +here. +

+
+
+ +Editor's +note + +
+

+This +section +is +informal +and +contains +rather +laconic +information +for +implementations +on +what +to +support +for +interoperability. +

+
+
+
interface "dfn"> {
+<span class="idlMethod" id=
+"idl-def-observable-subscribe-next-error-complete" data-idl=""
+data-title="subscribe" data-dfn-for="observable">    <span class=
+"idlMethType"><a href="#dom-subscription" class="internalDFN"
+
+"dfn">Observable {
+  Subscription subscribe("idlParam">(<a href="#dom-observer"
+class="internalDFN" data-link-type=
+"dfn"> or <a href="#dom-onnext" class=
+
+"idlParam">EventHandler handler,
+                         optional ErrorHandler errorHandler,
+                         optional 
+"internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">next,
+                           <span class=
+"idlParam">optional <a href=
+"#dom-onerror" class="internalDFN" data-link-type=
+"dfn"> <span class=
+"idlParamName">error,
+                           <span class=
+"idlParam">optional <a href=
+"#dom-oncomplete" class="internalDFN" data-link-type=
+
+"dfn">OnComplete "idlParamName">complete
+};
+<span class="idlInterface" id="idl-def-subscription" data-idl=""
+data-title="Subscription">interface <span class=
+"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-subscription" class="internalDFN" data-link-type=
+"dfn"> {
+<span class="idlMethod" id="idl-def-subscription-unsubscribe"
+data-idl="" data-title="unsubscribe" data-dfn-for=
+"subscription">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="subscription"
+data-lt="unsubscribe|unsubscribe()" href=
+"#dom-subscription-unsubscribe" class="internalDFN" data-link-type=
+"dfn">
+<span class="idlAttribute" id="idl-def-subscription-closed"
+data-idl="" data-title="closed" data-dfn-for=
+"subscription">    readonly attribute <span class=
+"idlAttrType"><a href=
+
+"idlParamName">onComplete);
+};
+interface Subscription {
+  void unsubscribe();
+  readonly attribute 
+"https://heycam.github.io/webidl/#idl-boolean">boolean data-link-for="subscription" data-lt="" href=
+"#dom-subscription-closed" class="internalDFN" data-link-type=
+
+data-link-for="subscription" data-lt="subscription.closed|closed"
+href="#dom-subscription-closed" class="internalDFN" data-link-type=
+
+"dfn">closed;
+};
+<span class="idlInterface" id="idl-def-observer" data-idl=""
+data-title="Observer">interface <span class=
+"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-observer" class="internalDFN" data-link-type=
+"dfn"> {
+<span class="idlMethod" id="idl-def-observer-next-value" data-idl=
+"" data-title="next" data-dfn-for="observer">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="observer"
+data-lt="next()|next" href="#dom-observer-next" class="internalDFN"
+data-link-type="dfn">next(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-any">any
+<span class="idlMethod" id="idl-def-observer-error-error" data-idl=
+"" data-title="error" data-dfn-for="observer">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="observer"
+data-lt="error()|error" href="#dom-observer-error" class=
+"internalDFN" data-link-type="dfn">error(<span class=
+"idlParam"><a href=
+"https://heycam.github.io/webidl/#idl-Error">Error
+<span class="idlMethod" id="idl-def-observer-complete" data-idl=""
+data-title="complete" data-dfn-for="observer">    <span class=
+"idlMethType">void <span class=
+"idlMethName"><a data-no-default="" data-link-for="observer"
+data-lt="complete()|complete" href="#dom-observer-complete" class=
+"internalDFN" data-link-type="dfn">complete
+};
+<span class="idlCallback" id="idl-def-onnext" data-idl=""
+data-title="OnNext">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-onnext" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType">void<span class=
+
+};
+callback EventHandler = void (
+"idlParamType">"https://heycam.github.io/webidl/#idl-any">any
+<span class="idlCallback" id="idl-def-onerror" data-idl=""
+data-title="OnError">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-onerror" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlCallbackType">void<span class=
+
+"https://heycam.github.io/webidl/#idl-any">any value);
+callback ErrorHandler = void (
+"idlParamType">"https://heycam.github.io/webidl/#idl-Error">Error
+<span class="idlCallback" id="idl-def-oncomplete" data-idl=""
+data-title="OnComplete">callback <span class=
+"idlCallbackID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-oncomplete" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+
+"https://heycam.github.io/webidl/#idl-Error">Error error);
+callback OnComplete =
+"idlCallbackType">
+void
+
+();
+
+
+
+7.1 +The +Observer +interface + +

+The +Observer +interface +defines +the + +following + +callbacks +needed + +can +be +provided +when +subscribing + +to +handle + +an + + +Observable + +: +

+ +
+

+ +7.2 + +8.1 + + +The + + +Subscription + + +interface + + +

+

+Contains +the + + +closed + + +property +of +type + +boolean + +that +tells +if +the +subscription +is +closed +or +active. +

+

+Also, +contains +the + + +unsubscribe + + +() +method +that +cancels +the +subscription, +i.e. +makes +a +request +to +the +underlying +platform +to +stop +receiving +data +from +the +source, +and +sets +the + +closed + +property +to + +false +. +

+
+
+

+ +7.3 + +8.2 + + +The + + +Observable + + +interface + + +

+

+The + + +Observable + + +interface +enabled +subscribing +to +pushed +data +notifications +by +the + + +subscribe + + +() +method: +

+ +
+
+
+

+ +8. + +9. + + +Security +and +Privacy + +Editor's +note + + +Please +see + +

+

+In +general + +the +security +measures +taken +to +protect +a + +WoT +Security + +system +will +depend +on +the +threats + +and +Privacy +repository + +attackers +that +system +may +face +and +the +value +of +the +assets +needs +to +protect. +A +detailed +discussion +of +security +and +privacy +considerations + +for +work +in +progress +regarding + +the +Web +of +Things, +including +a + +threat +models, +assets, +risks, +recommended +mitigations, + +model +that +can +be +adapted +to +various +circumstances, +is +presented +in +the +informative +document +[ + +WOT-SECURITY-CONSIDERATIONS + +]. +This +section +includes +only +normative +recommendations +relevant +to +the +WoT +Thing +Description. +

+When +designing +new +devices + +and +services +for +use +with +the +WoT, +we +have +documented +a +set +of + +best +practices +for + +in +[ + +WOT-SECURITY-BEST-PRACTICES + +] +that + +SHOULD + +be +followed. + +This +best-practices +document +may +be +updated +as + +security +measures +evolve. +Following +these +practices +does +not +guarantee +security, +but +it +at +least +will +help +to +avoid +common +known +vulnerabilities + +and +privacy +for +systems + +pitfalls. +

+Below +are +specific +recommendations +related +to +WoT +runtime +implementations: +

+Some +additional +specific +recommendations +relevant +for +WoT +script +developers: + +

+ +
+
+

+ +9. + +10. + + +Terminology +and +conventions + + +

+

+The +generic +WoT +terminology +is +defined +in +[ + + +WOT-ARCHITECTURE + + +]: + +Thing +, + +Thing +Description + +(in +short + +TD + +), + +Web +of +Things + +(in +short + + +WoT + + +), + +WoT +Interface +, + +Protocol +Bindings +, + +WoT +Runtime +, + +Consuming +a +Thing +Description +, + +Thing +Directory +, + +WoT +Interactions +, + +Property +, + +Action +, + +Event + +etc. +

+

+ +JSON-LD + +is +defined +in +[ + + +JSON-LD + + +] +as +a +JSON +document +that +is +augmented +with +support +for +Linked +Data +by +providing +a +@context +property +with +a +defining +URI +. + +Data. + +

+

+The +terms + + +URL + + +and + + +URL +path + + +are +defined +in +[ + + +URL + + +]. +

+

+The +following +terms +are +defined +in +[ + + +HTML52 + + +] +and +are +used +in +the +context +of +browser +implementations: + + +browsing +context + +, + + +top-level +browsing +context + +, + + +global +object + +, + + +incumbent +settings +object + +, + + +Document + +, + + +document +base +URL + +, + + +Window + +, + + +WindowProxy + +, + + +origin + +, + + +ASCII +serialized +origin + +, +executing +algorithms + + +in +parallel + +, + + +queue +a +task + +, + + +task +source + +, + + +iframe + +, + + +valid +MIME +type + +. +

+

+A + +browsing +context + +refers +to +the +environment +in +which + +Document + +objects +are +presented +to +the +user. +A +given + +browsing +context + +has +a +single + + +WindowProxy + + +object, +but +it +can +have +many + + +Document + + +objects, +with +their +associated + + +Window + + +objects. +The + +script +execution +context + +associated +with +the + +browsing +context + +identifies +the +entity +which +invokes +this +API, +which +can +be +a + +web +app +, +a + +web +page +, +or +an + +iframe +. +

+

+The +term + + +secure +context + + +is +defined +in +[ + + +WEBAPPSEC + + +]. +

+

+ + +Error +, + +EvalError +, + +RangeError +, + +ReferenceError +, + +SyntaxError +, + +TypeError +, + +URIError + + +, + + +script +execution +context + +, + + +Promise + +, + + +JSON + +, + + +JSON.stringify + + +and + + +JSON.parse + + +are +defined +in +[ + + +ECMASCRIPT + + +]. +

+

+ + +DOMString + +, + + +USVString + +, + + +ArrayBuffer + +, + + +BufferSource + + +and + + +any + + +are +defined +in +[ + + +WEBIDL + + +]. +

+

+The +algorithms + + +utf-8 +encode + +, +and + + +utf-8 +decode + + +are +defined +in +[ + + +ENCODING + + +]. +

+

+ +IANA +media +type + +s +(formerly +known +as +MIME +types) +are +defined +in + +RFC2046 +. +

+

+The +terms + +hyperlink +reference + +and + +relation +type + +are +defined +in +[ + + +HTML52 + + +] +and + +RFC8288 +. +

+
+
+

+ +10. + +11. + + +Conformance + + +

+

+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 +, + +SHOULD +, +and + +SHOULD +NOT + + +are +to +be +interpreted +as +described +in +[ + + +RFC2119 + + +]. +

+

+This +document +defines +conformance +criteria +that +apply +to +a +single +product: +the + +UA + +(user +agent) +that +implements +the +interfaces +it +contains. +

+

+This +specification +can +be +used +for +implementing +the +WoT +Scripting +API +in +multiple +programming +languages. +The +interface +definitions +are +specified +in +[ + + +WEBIDL + + +]. +

+

+The +user +agent +(UA) +may +be +implemented +in +the +browser, +or +in +a +separate +runtime +environment, +such +as + +Node.js + +or +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 + + +]. +

+

+This +document +serves +a +general +description +of +the +WoT +Scripting +API. +Language +and +runtime +specific +issues +are +discussed +in +separate +extensions +of +this +document. +

+
+
+

+ +A. + +Changes + + +

+

+The +following +is +a +list +of +major +changes +to +the +document. +For +a +complete +list +of +changes, +see +the + +github +change +log +. +You +can +also +view +the + +recently +closed +bugs + +issues + +. +

+ +
+
+

+ +B. + +Open +issues + + +

+

+The +following +problems +are +being +discussed +and +need +most +attention: +

+ +
+
+

+ +C. + +Acknowledgements + +Acknowledgments + +

+

+Special +thanks +to +former +editor +Johannes +Hund +(until +August +2017, +when +at +Siemens +AG) +for +developing +this +specification. +Also, +the +editors +would +like +to +thank +Dave +Raggett, +Matthias +Kovatsch, +Michael +Koster +and +Michael +McCool +for +their +comments +and +guidance. +

+
+
+

+ +D. + +References + + +

+
+

+ +D.1 + +Normative +references + + +

+
+
+[ECMASCRIPT] +
+
+ + +ECMAScript +Language +Specification + +. +Ecma +International. +URL: + +https://tc39.github.io/ecma262/ + +
+
+[ENCODING] +
+
+ + +Encoding + +. +Anne +van +Kesteren; +Joshua +Bell; +Addison +Phillips. +W3C. +15 +December +2016. +W3C +Candidate +Recommendation. +URL: + +https://www.w3.org/TR/encoding/ + +
+
+[HTML52] +
+
+ + +HTML +5.2 + +. +Steve +Faulkner; +Arron +Eicholz; +Travis +Leithead; +Alex +Danilo; +Sangwhan +Moon; +Erika +Doyle +Navara; +Theresa +O'Connor; +Robin +Berjon. +W3C. +14 +December +2017. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/html52/ + +
+
+[JSON-LD] +
+
+ + +JSON-LD +1.0 + +. +Manu +Sporny; +Gregg +Kellogg; +Markus +Lanthaler. +W3C. +16 +January +2014. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/json-ld/ + +
+
+[RFC2119] +
+
+ + +Key +words +for +use +in +RFCs +to +Indicate +Requirement +Levels + +. +S. +Bradner. +IETF. +March +1997. +Best +Current +Practice. +URL: + +https://tools.ietf.org/html/rfc2119 + +
+
+[TYPESCRIPT] +
+
+ + +TypeScript +Language +Specification + +. +Microsoft. +1 +October +2012. +URL: + +https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md + +
+
+[URL] +
+
+ + +URL +Standard + +. +Anne +van +Kesteren. +WHATWG. +Living +Standard. +URL: + +https://url.spec.whatwg.org/ + +
+
+[WEBAPPSEC] +
+
+ + +Secure +Contexts + +. +W3C. +17 +July +2015. +URL: +https://w3c.github.io/webappsec/specs/powerfulfeatures/ + + +https://w3c.github.io/webappsec/specs/powerfulfeatures + + +
+
+[WEBIDL] +
+
+ + +Web +IDL + +. +Cameron +McCormack; +Boris +Zbarsky; +Tobie +Langel. +W3C. +15 +December +2016. +W3C +Editor's +Draft. +URL: + +https://heycam.github.io/webidl/ + +
+
+[WOT-ARCHITECTURE] +
+
+ + +Web +of +Things +Architecture + +. +W3C. +14 +September + +20 +August + +2017. +URL: +https://www.w3.org/TR/2017/WD-wot-architecture-20170914/ + + +https://w3c.github.io/wot-architecture/ +
+[WOT-SECURITY-BEST-PRACTICES] +
+Web +of +Things +Security +and +Privacy +Best +Practices +(WIP) +. +W3C. +WIP. +URL: + +https://github.com/w3c/wot-security/blob/master/wot-security-best-practices.md +
+[WOT-SECURITY-CONSIDERATIONS] +
+Web +of +Things +Security +and +Privacy +Considerations +. +W3C. +28 +August +2017. +URL: + +https://w3c.github.io/wot-security/ +
+[WOT-SECURITY-TESTING] +
+Web +of +Things +Security +Testing +and +Validation +. +W3C. +WIP. +URL: + +https://github.com/w3c/wot-security/blob/master/wot-security-testing.md +
+[WOT-TD] +
+WoT +Thing +Description + +. +W3C. +21 +October +2018. +URL: + +https://www.w3.org/TR/2018/WD-wot-thing-description-20181021/ + + +
+
+
+
+

+ +D.2 + +Informative +references + + +

+
+[WOT-TD] + +
+[HTML] + +
+
+ + +WoT +Thing +Description + +HTML +Standard + + +. +W3C. +20 +August +2017. + +. +Anne +van +Kesteren; +Domenic +Denicola; +Ian +Hickson; +Philip +Jägenstedt; +Simon +Pieters. +WHATWG. +Living +Standard. + +URL: +https://www.w3.org/TR/2018/WD-wot-thing-description-20180405/ + + +https://html.spec.whatwg.org/multipage/ + + +
+
+
+
+ + + + diff --git a/releases/wd3/manifest.txt b/releases/wd3/manifest.txt new file mode 100644 index 00000000..578b5801 --- /dev/null +++ b/releases/wd3/manifest.txt @@ -0,0 +1,2 @@ +Overview.html +diff.html diff --git a/releases/wd4/Overview.html b/releases/wd4/Overview.html new file mode 100644 index 00000000..c0269318 --- /dev/null +++ b/releases/wd4/Overview.html @@ -0,0 +1,6961 @@ + + + + + + + + + + + Web of Things (WoT) Scripting API + + + + + + + + + + + + +
+ +

Web of Things (WoT) + Scripting API

+

W3C Working Draft

+
+
This version:
+
+ + https://www.w3.org/TR/2019/WD-wot-scripting-api-20191028/ +
+
Latest published version:
+
+ https://www.w3.org/TR/wot-scripting-api/ +
+
Latest editor's draft:
+
+ https://w3c.github.io/wot-scripting-api/ +
+
Previous version:
+
+ + https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/ +
+
Editors:
+
+ Zoltan Kis (Intel) +
+
+ Daniel Peintner (Siemens AG) +
+
Johannes Hund (Former Editor, when at + Siemens AG)
+
Kazuaki Nimura (Former Editor, at Fujitsu + Ltd.)
+
Repository:
+
+ On + GitHub +
+
+ File a + bug +
+
Contributors:
+
+ + Contributors on GitHub +
+
+ +
+
+
+

Abstract

+

The main Web of Things (WoT) concepts are + described in the WoT Architecture + document. 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).

+

Scripting is an optional "convenience" building block in WoT + and it is typically used in gateways 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 + Thing Directory.

+

This specification describes a programming interface + 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 specification deliberately follows the WoT Thing + Description specification closely. It is possible to + implement simpler APIs on top of this API, or implementing + directly the WoT network facing interface (i.e. the WoT Interface).

+
+
+ Editor's note +
+

This specification is implemented at least by the + Thingweb project also + known as node-wot, + which is considered the reference open source implementation + at the moment. Check its source + code, including examples. + Other, closed source implementations have been made by WG + member companies and tested against node-wot + in plug-fests.

+
+
+
+

Status of This Document

+

This section describes the status of this document at + the time of its publication. Other documents may supersede this + document. A list of current W3C publications and the + latest revision of this technical report can be found in the + W3C technical reports + 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.

+
+
+ Editor's note: The + W3C WoT WG is asking for feedback +
+

Please contribute to this draft using the + GitHub + Issue feature 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 + a Working Draft. This document is intended to become a W3C + Recommendation.

+

Comments regarding this document are welcome. Please send + them to public-wot-wg@w3.org + (archives).

+

Publication as a Working Draft does not imply endorsement + by the W3C + Membership. This is a draft document and may be updated, + replaced or obsoleted by other documents at any time. It is + inappropriate to cite this document as other than work in + progress.

+

This document was produced by a group operating under the + 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 1 March 2019 + W3C Process + Document.

+
+ +
+

1. + Introduction

+

WoT provides layered interoperability based on how Things are used: "consumed" and "exposed", as + defined + in [WOT-ARCHITECTURE].

+

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.

+
+

Exposing a Thing requires:

+ This specification describes how to expose and consume + Things by a script. Also, it defines a generic API + for Thing discovery. +
+
+
+ Note +
+

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.

+
+
+
+ Note +
+

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.

+
+
+
+

2. Use + Cases

+

This section is non-normative.

+

The following scripting use cases are supported in this + specification:

+
+

2.1 + Consuming a Thing

+ +
+
+

2.2 + Exposing a Thing

+ +
+
+

2.3 + Discovery

+ +
+
+
+

3. + Conformance

+

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 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.

+
+
+ WoT + Consumer UA +
+
+

Implementations of this conformance class MUST implement the + ConsumedThing + interface and the consume() method on the + WoT API object.

+
+
+ WoT + Producer UA +
+
+

Implementations of this conformance class MUST implement ExposedThing interface and + the produce() method on the WoT API object.

+
+
+ WoT + Discovery UA +
+
+

Implementations of this conformance class MUST implement the + ThingDiscovery + interface and the discover() 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].

+
+
+

4. The ThingDescription + type

+
typedef object ThingDescription;
+

Represents a Thing Description + (TD) as defined in [WOT-TD]. It is expected to be a parsed + JSON object that is validated using + JSON schema validation.

+
+

4.1 Fetching a Thing Description

+

Fetching a TD given a URL should be done with + an external method, such as the Fetch API or a + HTTP client library, which offer already standardized options + on specifying fetch details.

+
+
+ Example + 1: Fetching a + Thing Description +
+
try {
+  let res = await fetch('https://tds.mythings.biz/sensor11');
+  // ... additional checks possible on res.headers
+  let td = await res.json();
+  let thing = new ConsumedThing(td);
+  console.log("Thing name: " + thing.getThingDescription().title);
+} catch (err) {
+  console.log("Fetching TD failed", err.message);
+}
+
+
+
+

4.2 Expanding a Thing Description

+

Note that [WOT-TD] allows using a shortened Thing Description by the means of + defaults and requiring clients to expand them with + default values specified in [WOT-TD] for the properties that are not + explicitly defined in a given TD.

+
+

To expand + a TD given td, run the following + steps:

+
    +
  1. For each item in the + TD default values table from [WOT-TD], if the term is not defined + in td, add the term definition + with the default value specified in [WOT-TD]. +
  2. +
+
+
+
+

4.3 Validating a Thing Description

+

The [WOT-TD] 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.

+
+

To validate a TD given + td, run the following steps:

+
    +
  1. If td is not an object, throw + "TypeError" and terminate these steps.
  2. +
  3. If any of the mandatory properties defined in + [WOT-TD] for Thing + that don't have + default definitions are missing from td, + throw "TypeError" and terminate these + steps. +
  4. +
  5. If + JSON schema validation fails on td, + throw "TypeError" and terminate these + steps. +
  6. +
+
+
+
+
+

5. The + WoT API + object

+

Defines the API entry point exposed as a singleton and + contains the API methods.

+
+

5.1 + The WOT interface

+
[SecureContext, Exposed=(Window,Worker)]
+interface WOT {
+  // methods defined in UA conformance classes
+};
+
+
+ Note +
+

Browser implementations should use a namespace + object such as navigator.wot. Standalone + runtimes may expose the API object through mechanisms like + require() + or + import.

+
+
+
+

5.2 + The consume() + method

+
partial interface WOT {
+  Promise<ConsumedThing> consume(ThingDescription td);
+};
+
+

Belongs to the WoT Consumer + conformance class. Expects an td argument and + returns a Promise + that resolves with a ConsumedThing object that represents + a client interface to operate with the Thing. The method MUST run the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Run the validate a TD + steps on td. If that throws, reject + promise with the error and terminate these + steps. +
  6. +
  7. Let thing be a new ConsumedThing + object constructed from td. +
  8. +
  9. Set up the WoT Interactions + based on introspecting td as explained in + [WOT-TD] and [WOT-PROTOCOL-BINDINGS]. Make a + request to the underlying platform to initialize the + Protocol Bindings. The details + are private to the implementations and out of scope of + this specification. +
  10. +
  11. Resolve promise with + thing.
  12. +
+
+
+
+

5.3 + The produce() + method

+
partial interface WOT {
+  Promise<ExposedThing> produce(ThingDescription td);
+};
+
+

Belongs to the WoT Producer + conformance class. Expects a td argument and + returns a Promise + that resolves with an ExposedThing object that extends + ConsumedThing with a + server interface, i.e. the ability to define request + handlers. The method MUST run the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise + with SecurityError and terminate these + steps. +
  4. +
  5. Let thing be a new ExposedThing object constructed + with td. +
  6. +
  7. Resolve promise with + thing.
  8. +
+
+
+
+

5.4 The discover() + method

+
partial interface WOT {
+  ThingDiscovery discover(optional ThingFilter filter = null);
+};
+
+

Belongs to the WoT Discovery + conformance class. Starts the discovery process that will + provide ThingDescription + objects for Thing Descriptions + that match an optional filter argument. The + method MUST run the + following steps:

+
    +
  1. If invoking this method is not allowed for the + current scripting context for security reasons, throw + SecurityError and terminate these + steps.
  2. +
  3. Construct a ThingDiscovery object + discovery with filter. +
  4. +
  5. Invoke the discovery.start() method. +
  6. +
  7. Return discovery.
  8. +
+
+

Refer to the ThingDiscovery section for how + discovery should be implemented.

+
+
+
+

6. The ConsumedThing + interface

+

Represents a client API to operate a Thing. Belongs to + the WoT Consumer conformance class.

+
[SecureContext, Exposed=(Window,Worker)]
+interface ConsumedThing {
+  constructor(ThingDescription td);
+  Promise<any> readProperty(DOMString propertyName,
+                            optional InteractionOptions options = null);
+  Promise<PropertyMap> readAllProperties(optional InteractionOptions options = null);
+  Promise<PropertyMap> readMultipleProperties(
+                            sequence<DOMString> propertyNames,
+                            optional InteractionOptions options = null);
+  Promise<void> writeProperty(DOMString propertyName,
+                              any value,
+                              optional InteractionOptions options = null);
+  Promise<void> writeMultipleProperties(PropertyMap valueMap,
+                              optional InteractionOptions options = null);
+  Promise<any> invokeAction(DOMString actionName,
+                              optional any params = null,
+                              optional InteractionOptions options = null);
+  Promise<void> observeProperty(DOMString name,
+                              WotListener listener,
+                              optional InteractionOptions options = null);
+  Promise<void> unobserveProperty(DOMString name);
+  Promise<void> subscribeEvent(DOMString name,
+                              WotListener listener,
+                              optional InteractionOptions options = null);
+  Promise<void> unsubscribeEvent(DOMString name);
+  ThingDescription getThingDescription();
+};
+dictionary InteractionOptions {
+  object uriVariables;
+};
+typedef object PropertyMap;
+callback WotListener = void(any data);
+
+

6.1 Constructing + ConsumedThing

+

After fetching + a Thing Description as a JSON object, + one can create a ConsumedThing object.

+
+

To create ConsumedThing with the ThingDescription td, run + the following steps:

+
    +
  1. Run the expand a TD steps + on td. If that fails, re-throw the error and + terminate these steps. +
  2. +
  3. Let thing be a new ConsumedThing + object. +
  4. +
  5. Let |td| be an internal slot of + thing and let td be its value.
  6. +
  7. Return thing.
  8. +
+
+
+
+

6.2 The + getThingDescription() method

+

Returns the internal slot |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.

+
+
+

6.3 The InteractionOptions + dictionary

+

Holds the interaction options that need to be exposed for + application scripts according to the Thing Description. In this version of the + specification only URI template variables are used, + represented as parsed + JSON objects defined in [WOT-TD].

+
+
+ Editor's note +
+

The support for URI variables comes from the + need exposed by [WOT-TD] to be able to describe existing + TDs that use them, but it should be possible to + write a Thing Description + that would use Actions for representing the + interactions that need URI variables and represent the URI + variables as parameters to the Action and in + that case that could be encapsulated by the implementations + and the options parameter could be dismissed + from the methods exposed by this API.

+
+
+
+

6.4 The PropertyMap + type

+

Represents a map of Property names as + strings to a value that the Property can take. It + is used as a property bag for interactions that involve + multiple Properties at once.

+
+
+ Editor's note +
+

It could be defined in Web IDL (as well as + ThingDescription) as + a maplike + interface from string to any.

+
+
+
+

6.5 The + readProperty() method

+
+

Reads a Property value. Takes a string + argument propertyName and and an optional + InteractionOptions + options argument. It returns a Property value represented as any + type. The method MUST + run the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform (via the + Protocol Bindings) to retrieve + the value of the Property given by + propertyName with optional URI templates given + in options.uriVariables. +
  6. +
  7. If the request fails, reject promise with + the error received from the Protocol Bindings and terminate + these steps. +
  8. +
  9. Let value be the result of the + request.
  10. +
  11. Run the validate Property + value sub-steps on value: +
      +
    1. Based on the + DataSchema definition, value + MUST be a + JSON value and comply to the data schema defined + for the Property + that is found in + this.getThingDescription().properties[propertyName]. +
    2. +
    3. If this fails, throw SyntaxError, + otherwise return value.
    4. +
    +
  12. +
  13. If these above steps failed, reject + promise with SyntaxError and + terminate these steps.
  14. +
  15. Otherwise resolve promise with + value.
  16. +
+
+
+
+

6.6 The + readMultipleProperties() method

+
+

Reads multiple Property values with + one or multiple requests. Takes the + propertyNames argument as a sequence of strings + and an optional InteractionOptions + options argument. It returns an object with keys + from propertyNames and values returned by this + algorithm. The method MUST run the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Let result be an object and for each + string name in propertyNames add a + property with key name and the value + null.
  6. +
  7. Make a request to the underlying platform (via the + Protocol Bindings) to retrieve + the Property values given by + propertyNames with optional URI templates + given in options.uriVariables. +
  8. +
  9. If this cannot be done with a single request with the + Protocol Bindings of the + Thing, then reject + promise with NotSupportedError + and terminate these steps. +
  10. +
  11. Process the reply and update all properties in + result with the values obtained in the + reply.
  12. +
  13. If the above step fails at any point, reject + promise with SyntaxError and + terminate these steps.
  14. +
  15. Resolve promise with + result.
  16. +
+
+
+
+

6.7 The + readAllProperties() method

+
+

Reads all properties of the Thing with one or + multiple requests. Takes an optional InteractionOptions + options argument. It returns an object with keys + from Property names and values returned + by this algorithm. The method MUST run the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Let result be an object and for each + string name in propertyNames add a + property with key name and the value + null.
  6. +
  7. Make a request to the underlying platform (via the + Protocol Bindings) to retrieve + the value of the all the Property + definitions from the TD with optional + URI templates given in options.uriVariables. +
  8. +
  9. If this cannot be done with a single request with the + Protocol Bindings of the + Thing, then reject + promise with NotSupportedError + and terminate these steps. +
  10. +
  11. If the request fails, reject promise with + the error received from the Protocol Bindings and terminate + these steps. +
  12. +
  13. Process the reply and update all properties in + result with the values obtained in the + reply.
  14. +
  15. Resolve promise with + result.
  16. +
+
+
+
+

6.8 The + writeProperty() method

+
+

Writes a single Property. Takes a + string argument propertyName, a value argument + value and an optional InteractionOptions + options argument. It returns success or failure. + The method MUST run + the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Run the validate + Property value steps on value. If that + fails, reject promise + with SyntaxError and terminate these + steps. +
  6. +
  7. Make a request to the underlying platform (via the + Protocol Bindings) to write + value to the Property + given by propertyName with optional URI + templates given in options.uriVariables. +
  8. +
  9. If the request fails, reject promise with + the error received from the Protocol Bindings and terminate + these steps. +
  10. +
  11. Otherwise resolve promise.
  12. +
+
+
+
+

6.9 The + writeMultipleProperties() method

+
+

Writes a multiple Property values with + one request. Takes a properties argument as an + object with keys being Property names and + values as Property values and an optional + InteractionOptions + options argument. It returns success or failure. + The method MUST run + the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. For each key name on + properties, take its value as value + and run the validate + Property value steps on value. If that + fails in for any name, reject + promise + with SyntaxError and terminate these + steps. +
  6. +
  7. Make a single request to the underlying platform (via + the Protocol Bindings) to write + the each Property provided in + properties with optional URI templates given + in options.uriVariables. +
  8. +
  9. If this cannot be done with a single request with the + Protocol Bindings of the + Thing, then reject + promise with NotSupportedError + and terminate these steps. +
  10. +
  11. If the request fails, return the error received from + the Protocol Bindings and + terminate these steps. +
  12. +
  13. Otherwise resolve promise.
  14. +
+
+
+
+

6.10 The WotListener + callback

+

User provided callback that takes any + argument and is used for observing Property changes + and handling Event notifications. Since + subscribing to these are WoT interactions, they are not + modelled with software events.

+
+
+

6.11 The + observeProperty() method

+
+

Makes a request for Property value + change notifications. Takes a string argument + propertyName, a WotListener callback function + listener and an optional InteractionOptions + options argument. It returns success or failure. + The method MUST run + the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. If listener is not a function, reject + promise with "TypeError" and + terminate these steps.
  6. +
  7. Make a request to the underlying platform (via the + Protocol Bindings) to observe + Property identified by + propertyName with optional URI templates given + in options.uriVariables. +
  8. +
  9. If the request fails, reject promise with + the error received from the Protocol Bindings and terminate + these steps. +
  10. +
  11. Otherwise resolve promise.
  12. +
  13. Whenever the underlying platform receives a + notification for this subscription with new Property value value, run the + following sub-steps: +
      +
    • If running the validate Property value + steps on value fails, terminate these + steps. +
    • +
    • Invoke listener with value + as parameter.
    • +
    +
  14. +
+
+
+
+

6.12 The + unobserveProperty() method

+
+

Makes a request for unsubscribing from Property value change notifications. Takes a + string argument propertyName and returns success + or failure. The method MUST run the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform (via the + Protocol Bindings) to stop + observing the Property + identified by propertyName. +
  6. +
  7. If the request fails, reject promise with + the error received from the Protocol Bindings and terminate + these steps. +
  8. +
  9. Otherwise resolve promise.
  10. +
+
+
+
+

6.13 The + invokeAction() method

+
+

Makes a request for invoking an Action and + return the result. Takes a string argument + actionName, an optional argument + params of type any and an optional + InteractionOptions + options argument. It returns the result of the + Action or an error. The method MUST run the following + steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform (via the + Protocol Bindings) to invoke the + Action identified by + actionName with parameters provided in + params with optional URI templates given in + options.uriVariables. +
  6. +
  7. If the request fails locally or returns an error over + the network, reject promise with the error + received from the Protocol + Bindings and terminate these steps. +
  8. +
  9. Otherwise let value be the result returned + in the reply and run the validate Property value steps on + it. If that fails, reject promise with + SyntaxError and terminate these steps. +
  10. +
  11. Reject promise with value.
  12. +
+
+
+
+

6.14 The + subscribeEvent() method

+
+

Makes a request for subscribing to Event + notifications. Takes a string argument + eventName, a WotListener callback function + listener and an optional InteractionOptions + options argument. It returns success or failure. + The method MUST run + the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. If listener is not a function, reject + promise with "TypeError" and + terminate these steps.
  6. +
  7. Make a request to the underlying platform (via the + Protocol Bindings) to subscribe + to an Event identified by + eventNamewith optional URI templates given in + options.uriVariables. +
  8. +
  9. If the request fails, reject promise with + the error received from the Protocol Bindings and terminate + these steps. +
  10. +
  11. Otherwise resolve promise.
  12. +
  13. Whenever the underlying platform receives a + notification for this Event + subscription, implementations SHOULD invoke listener, + giving the data provided with the Event as + parameter. +
  14. +
+
+
+
+

6.15 The + unsubscribeEvent() method

+
+

Makes a request for unsubscribing from Event notifications. Takes a string argument + eventName and returns success or failure. The + method MUST run the + following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform (via the + Protocol Bindings) to + unsubscribe from the Event identified + by eventName. +
  6. +
  7. If the request fails, reject promise with + the error received from the Protocol Bindings and terminate + these steps. +
  8. +
  9. Otherwise resolve promise.
  10. +
+
+
+
+

6.16 ConsumedThing Examples

+

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.

+
+
+ Example + 2: Thing + Client API example +
+
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", value => {
+    console.log("Temperature changed to: " + value);
+  });
+  // subscribe to the “ready” event defined in the TD
+  await thing.subscribeEvent("ready", eventData => {
+    console.log("Ready; index: " + eventData);
+    // run the “startMeasurement” action defined by TD
+    await thing.invokeAction("startMeasurement", { units: "Celsius" });
+    console.log("Measurement started.");
+  });
+} catch(e) {
+  console.log("Error starting measurement.");
+}
+setTimeout( () => {
+  console.log(“Temperature: “ + await thing.readProperty(“temperature”));
+  await thing.unsubscribe(“ready”);
+  console.log("Unsubscribed from the ‘ready’ event.");
+},
+10000);
+
+
+
+
+

7. The ExposedThing + interface

+

The ExposedThing interface is + the server API to operate the Thing that allows + defining request handlers, Property, Action, and Event interactions.

+
[SecureContext, Exposed=(Window,Worker)]
+interface ExposedThing: ConsumedThing {
+  ExposedThing setPropertyReadHandler(DOMString name,
+          PropertyReadHandler readHandler);
+  ExposedThing setPropertyWriteHandler(DOMString name,
+          PropertyWriteHandler writeHandler);
+  ExposedThing setActionHandler(DOMString name, ActionHandler action);
+  void emitEvent(DOMString name, any data);
+  Promise<void> expose();
+  Promise<void> destroy();
+};
+callback PropertyReadHandler = Promise<any>(
+        optional InteractionOptions options = null);
+callback PropertyWriteHandler = Promise<void>(any value,
+        optional InteractionOptions options = null);
+callback ActionHandler = Promise<any>(any params,
+        optional InteractionOptions options = null);
+
+

7.1 Constructing + ExposedThing

+

The ExposedThing interface extends ConsumedThing. It is constructed from + a full or partial ThingDescription object.

+
+
+ Note +
+

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 constructing an ExposedThing object. This is the + current way of adding and removing Property, Action and Event definitions, as illustrated in the examples.

+
+
+
+ Note +
+

Before invoking expose(), the ExposedThing object does not serve + any requests. This allows first constructing ExposedThing and then initialize its + Properties and service handlers + before starting serving requests.

+
+
+

To construct an ExposedThing with the ThingDescription td, run + the following steps:

+
    +
  1. If invoking this method is not allowed for the + current scripting context for security reasons, throw + SecurityError and terminate these + steps.
  2. +
  3. Run the expand a TD steps + on td. If that fails, re-throw the error and + terminate these steps. +
  4. +
  5. Let thing be a new ExposedThing object. +
  6. +
  7. Let |td| be an internal slot of + thing and let td be its value.
  8. +
  9. Return thing.
  10. +
+
+
+
+

+ 7.2 Methods inherited from ConsumedThing

+

The readProperty(), + readMultipleProperties(), + readAllProperties(), + writeProperty(), + writeMultipleProperties(), + writeAllProperties() methods have the same + algorithmic steps as described in ConsumedThing, + with the difference that making a request to the underlying + platform MAY be + implemented with local methods or libraries and don't + necessarily need to involve network operations.

+

The implementation of ConsumedThing interface in an ExposedThing provide the + default methods to interact with the ExposedThing.

+

After constructing an ExposedThing, a script can initialize + its Properties and can set up the + optional read, write and action request handlers (the default + ones are provided by the implementation). The script provided + handlers MAY use the + default handlers, thereby extending the default behavior, but + they can also bypass them, overriding the default behavior. + Finally, the script would call expose() on the + ExposedThing in order + to start serving external requests.

+
+
+

7.3 The PropertyReadHandler + callback

+

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 + Promise + and resolves it when the value of the Property matching the name argument is + obtained, or rejects with an error if the property is not + found or the value cannot be retrieved.

+
+
+

7.4 The + setPropertyReadHandler() method

+

Takes name as string argument and + readHandler as argument of type PropertyReadHandler. + Sets the service handler for reading the specified Property matched by name. Throws on + error. Returns a reference to this object for + supporting chaining.

+

The readHandler 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.

+
+
+

7.5 Handling Property read + requests

+
+

When a network request for reading Property propertyName is received by + the implementation, run the following steps:

+
    +
  1. If a Property with + propertyName does not exist, return + ReferenceError in the reply and terminate + these steps. +
  2. +
  3. If there is a user provided read handler registered + with setPropertyReadHandler(), invoke that + wih propertyName, return the value with the + reply and terminate these steps.
  4. +
  5. Otherwise, if there is a default read handler + provided by the implementation, invoke it with + propertyName, return the value with the reply + and terminate these steps.
  6. +
  7. if there is no default handler defined by the + implementation, return + NotSupportedError with the reply and + terminate these steps. +
  8. +
+
+
+
+

7.6 Handling Property observe + requests

+
+

When a network request for observing a Property propertyName is received by + the implementation, run the following steps:

+
    +
  1. If a Property with + propertyName does not exist, return an error + in the reply (as defined in the Thing Description) and terminate + these steps. +
  2. +
  3. Save the request sender information to the Property's internal observer list in order + to be able to notify about Property + value changes. +
  4. +
+
+
+
+

7.7 The PropertyWriteHandler + callback

+

A function that is called when an external request for + writing a Property is received and defines + what to do with such requests. It expects the requested new + value as argument and returns a + Promise + which is resolved when the value of the Property that matches the name + argument has been updated with value, or rejects + with an error if the property is not found or the value + cannot be updated.

+
+
+ Editor's note +
+

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.

+
+
+
+

7.8 The + setPropertyWriteHandler() method

+

Takes name as string argument and + writeHandler as argument of type PropertyWriteHandler. + Sets the service handler for writing the specified Property matched by name. Throws on + error. Returns a reference to this object for + supporting chaining.

+

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 + and notifying observers on change, based on the Thing Description.

+
+
+

7.9 Handling Property write + requests

+
+

When a network request for writing a Property propertyName with a new value + value is received, implementations SHOULD run the following + update property steps, + given propertyName, value and + mode set to "single":

+
    +
  1. If a Property with + propertyName does not exist, return + ReferenceError in the reply and terminate + these steps. +
  2. +
  3. If there is a user provided write handler registered + with setPropertyWriteHandler(), or if there + is a default write handler, +
      +
    1. Invoke the handler with propertyName. + If it fails, return the error in the reply and + terminate these steps.
    2. +
    3. Otherwise, if mode is + "single", reply to the request with the + new value, following to the Protocol Bindings. +
    4. +
    5. For each item stored in the internal observer list of + the Property with + propertyName, send an observe reply with + the new value attached. +
    6. +
    +
  4. +
  5. If there is no handler to handle the request, return + + NotSupportedError in the reply and terminate + these steps. +
  6. +
+
+
+

When a network request for writing multiple Properties given in an object + propertyNames is received, run the following + steps:

+
    +
  1. For each property with key name and value + value defined in propertyNames, run + the update property + steps with name, value and + mode set to "multiple". +
  2. +
  3. Reply to the request (by sending a single or multiple + replies) according to the Protocol Bindings defined for + the Property. +
  4. +
+
+
+
+

7.10 The ActionHandler + callback

+

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 with a + params dictionary argument. It returns a + Promise + that rejects with an error or resolves if the action is + successful.

+
+
+

7.11 The + setActionHandler() method

+

Takes name as string argument and + action as argument of type ActionHandler. Sets the handler + function for the specified 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.

+
+
+

7.12 Handling Action + requests

+
+

When a network request for invoking the Action identified by name is received, + the runtime SHOULD + execute the following steps:

+
    +
  1. If an Action identified by + name does not exist, return + ReferenceError in the reply and terminate + these steps. +
  2. +
  3. If there is a user provided action handler registered + with setActionHandler(), invoke that wih + name, return the resulting value with the + reply and terminate these steps.
  4. +
  5. Otherwise return + NotSupportedError with the reply and + terminate these steps. +
  6. +
+
+
+
+

7.13 The + emitEvent() method

+
+

Takes name as string argument denoting an + Event name, and a data argument of + any type. The method MUST run the following steps:

+
    +
  1. If invoking this method is not allowed for the + current scripting context for security reasons, throw + SecurityError and terminate these + steps.
  2. +
  3. If an Event with the name + name is not found in + this.getThingDescription().events, throw + NotFoundError and terminate these steps. +
  4. +
  5. Make a request to the underlying platform to send an + Event with data + attached as property, using the Protocol Bindings, then + terminate these steps. +
  6. +
+
+
+
+

7.14 The + expose() method

+
+

Start serving external requests for the Thing, so that WoT + Interactions using Properties, Actions and Events will be + possible. The method MUST run the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Run the expand a TD steps + on the internal slot |td|. +
  6. +
  7. Run the validate a TD on + |td|. If that fails, reject promise + with "TypeError" and terminate these steps. +
  8. +
  9. For each Property + definition in this.instance.properties + initialize an |internal observer + list| internal slot in order to store observe + request data needed to notify the observers on value + changes. +
  10. +
  11. Set up the WoT Interactions + based on introspecting td as explained in + [WOT-TD] and [WOT-PROTOCOL-BINDINGS]. 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. The details + are private to the implementations and out of scope of + this specification. +
  12. +
  13. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  14. +
  15. Otherwise resolve promise and terminate + these steps.
  16. +
+
+
+
+

7.15 The + destroy() method

+
+

Stop serving external requests for the Thing and destroy the object. Note that eventual + unregistering should be done before invoking this method. + The method MUST run + the following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If invoking this method is not allowed for the + current scripting context for security reasons, reject + promise with SecurityError and + terminate these steps.
  4. +
  5. Make a request to the underlying platform to stop + serving external requests for WoT Interactions, based on the + Protocol Bindings. +
  6. +
  7. If there was an error during the request, reject + promise with an Error object + error with error.message set to + the error code seen by the Protocol Bindings and terminate + these steps. +
  8. +
  9. Otherwise resolve promise and terminate + these steps.
  10. +
+
+
+
+

7.16 ExposedThing Examples

+

The next example illustrates how to create an + ExposedThing + based on a partial TD object constructed + beforehands.

+
+
+ Example + 3: Create + ExposedThing with a simple Property +
+
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.

+
+
+ Example + 4: Add an + object Property +
+
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);
+}
+
+
+
+
+

8. The ThingDiscovery + interface

+

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 ThingDiscovery object is + constructed given a filter and provides the properties and + methods controlling the discovery process.

+
[SecureContext, Exposed=(Window,Worker)]
+interface ThingDiscovery {
+  constructor(optional ThingFilter filter = null);
+  readonly attribute ThingFilter? filter;
+  readonly attribute boolean active;
+  readonly attribute boolean done;
+  readonly attribute Error? error;
+  void start();
+  Promise<ThingDescription> next();
+  void stop();
+};
+
+
+ Editor's note +
+

The ThingDiscovery interface has a + next() method and a done property, + but it is not an Iterable. Look into Issue + 177 for rationale.

+
+

The discovery results internal slot + is an internal queue for temporarily storing the found ThingDescription objects until they are + consumed by the application using the next() method. Implementations MAY optimize the size of this queue + based on e.g. the available resources and the frequency of + invoking the next() method.

+

The filter + property represents the discovery filter of type ThingFilter specified for the + discovery.

+

The active + property is true when the discovery is actively + ongoing on protocol level (i.e. new TDs may still arrive) + and false otherwise.

+

The done + property is true if the discovery has been + completed with no more results to report and discovery results is also empty.

+

The error + property represents the last error that occured during the + discovery process. Typically used for critical errors that stop + discovery.

+
+

8.1 Constructing + ThingDiscovery

+
+

To create ThingDiscovery with the ThingFilter filter, run + the following steps:

+
    +
  1. If filter is not an object or + null, throw "TypeError" and + terminate these steps.
  2. +
  3. Let discovery be a new ThingDiscovery + object. +
  4. +
  5. Set the filter property to + filter. +
  6. +
  7. Set active + and done to + false. Set error to + null. +
  8. +
  9. Return discovery.
  10. +
+
+

The start() method sets + active to + true. The stop() + method sets active + to false, but done may be still + false if there are ThingDescription objects in the + discovery results not yet consumed + with next().

+

During successive calls of next(), active may be + true or false, but done is set to + false by next() + only when both active is false + and discovery results is empty.

+
+
+

8.2 The DiscoveryMethod + enumeration

+
typedef DOMString DiscoveryMethod;
+

Represents the discovery type to be used:

+ +
+
+

8.3 The ThingFilter + dictionary

+

Represents an object containing the constraints for + discovering Things as key-value pairs.

+
dictionary ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  USVString? url;
+  USVString? query;
+  object? fragment;
+};
+

The method + property represents the discovery type that should be used in + the discovery process. The possible values are defined by the + DiscoveryMethod + enumeration that MAY be + extended by string values defined by solutions (with no + guarantee of interoperability).

+

The url property represents + additional information for the discovery method, such as the + URL of the target entity serving the discovery request, for + instance the URL of a Thing Directory (if + method is "directory") or that of a + Thing (otherwise).

+

The query property represents a + query string accepted by the implementation, for instance a + SPARQL or JSON query. Support may be implemented locally in + the WoT Runtime or remotely as a service + in a Thing Directory.

+

The fragment property represents a + template object used for matching property by property + against discovered Things.

+
+
+

8.4 + The + start() method

+
+

Starts the discovery process. The method MUST run the following + steps:

+
    +
  1. If invoking this method is not allowed for the + current scripting context for security reasons, set + this.error to SecurityError and + terminate these steps.
  2. +
  3. If discovery is not supported by the implementation, + set this.error to + NotSupportedError and terminate these + steps.
  4. +
  5. If this.filter is defined, +
      +
    • Let filter denote + this.filter.
    • +
    • If filter.query is defined, pass it as + an opaque string to the underlying implementation to + be matched against discovered items. The underlying + implementation is responsible to parse it e.g. as a + SPARQL or JSON query and match it against the + Thing + Descriptions found during the discovery + process. If queries are not supported, set + this.error to + NotSupportedError and terminate these + steps. +
    • +
    +
  6. +
  7. Create the discovery results + internal slot for storing discovered ThingDescription + objects. +
  8. +
  9. Request the underlying platform to start the + discovery process, with the following parameters: +
      +
    • If filter.method is not defined or the + value is "any", use the widest discovery + method supported by the underlying platform.
    • +
    • Otherwise if filter.method is + "local", use the local Thing Directory for + discovery. Usually that defines Things + deployed in the same device, or connected to the + device in slave mode (e.g. sensors connected via + Bluetooth or a serial connection). +
    • +
    • Otherwise if filter.method is + "directory", use the remote Thing Directory specified in + filter.url. +
    • +
    • Otherwise if filter.method is + "multicast", use all the multicast + discovery protocols supported by the underlying + platform.
    • +
    +
  10. +
  11. When the underlying platform has started the + discovery process, set the active property + to true.
  12. +
  13. Whenever a new Thing + Description td is discovered by the + underlying platform, run the following sub-steps: +
      +
    1. + Fetch + td as a JSON object json. If + that fails, set this.error to + SyntaxError, discard td and + continue the discovery process. +
    2. +
    3. If filter.query is defined, check if + json is a match for the query. The + matching algorithm is encapsulated by + implementations. If that returns false, + discard td and continue the discovery + process.
    4. +
    5. If filter.fragment is defined, for + each property defined in it, check if that property + exists in json.properties and has the same + value. If this is false in any checks, + discard td and continue the discovery + process.
    6. +
    7. Otherwise add td to the discovery results. +
    8. +
    9. At this point implementations MAY control the flow of the + discovery process (depending on memory constraints, + for instance temporarily stop discovery if the queue + is getting too large, or resume discovery when the + queue is emptied sufficiently).
    10. +
    +
  14. +
  15. Whenever an error occurs during the discovery + process, +
      +
    1. Set this.error to a new + Error object error. Set + error.name to + 'DiscoveryError'.
    2. +
    3. If there was an error code or message provided by + the Protocol + Bindings, set error.message to that + value as string. +
    4. +
    5. If the error is irrecoverable and discovery has + been stopped by the underlying platform, set + this.active to false.
    6. +
    +
  16. +
  17. When the underlying platform reports the discovery + process has completed, set this.active to + false.
  18. +
+
+
+
+

8.5 + The + next() method

+
+

Provides the next discovered ThingDescription object. The method + MUST run the + following steps:

+
    +
  1. Return a Promise + promise and execute the next steps + in + parallel. +
  2. +
  3. If this.active is true, wait + until the discovery results + internal slot is not empty. +
  4. +
  5. If discovery results + is empty and this.active is + false, set this.done to + true and reject promise. +
  6. +
  7. Remove the first ThingDescription object + td from discovery + results. +
  8. +
  9. Resolve promise with td and + terminate these steps.
  10. +
+
+
+
+

8.6 + The + stop() method

+
+

Stops or suppresses the discovery process. It might not + be supported by all discovery methods and endpoints, + however, any further discovery results or errors will be + discarded and the discovery is marked inactive. The method + MUST run the + following steps:

+
    +
  1. Request the underlying platform to stop the discovery + process. If this returns an error, or if it is not + possible, for instance when discovery is based on open + ended multicast requests, the implementation SHOULD discard subsequent + discovered items.
  2. +
  3. Set this.active to + false.
  4. +
+
+
+
+

8.7 + Discovery Examples

+

The following example finds ThingDescription objects of Things that are exposed by local hardware, + regardless how many instances of WoT Runtime it + is running. Note that the discovery can end (become inactive) + before the internal discovery results + queue is emptied, so we need to continue reading ThingDescription objects until done. + This is typical with local and directory type + discoveries.

+
+
+ Example + 5: Discover + Things exposed by local hardware +
+
let discovery = new ThingDiscovery({ method: "local" });
+do {
+  let td = await discovery.next();
+  console.log("Found Thing Description for " + td.title);
+  let thing = new ConsumedThing(td);
+  console.log("Thing name: " + thing.getThingDescription().title);
+} while (!discovery.done);
+
+

The next example finds ThingDescription objects of Things listed in a Thing Directory + service. We set a timeout for safety.

+
+
+ Example + 6: Discover + Things via directory +
+
let discoveryFilter = {
+  method: "directory",
+  url: "http://directory.wotservice.org"
+};
+let discovery = new ThingDiscovery(discoveryFilter);
+setTimeout( () => {
+    discovery.stop();
+    console.log("Discovery stopped after timeout.");
+  },
+  3000);
+do {
+  let td = await discovery.next();
+  console.log("Found Thing Description for " + td.title);
+  let thing = new ConsumedThing(td);
+  console.log("Thing name: " + thing.getThingDescription().title);
+} while (!discovery.done);
+if (discovery.error) {
+  console.log("Discovery stopped because of an error: " + error.message);
+}
+
+

The next example is for an open-ended multicast discovery, + which likely won't complete soon (depending on the underlying + protocol), so stopping it with a timeout is a good idea. It + will likely deliver results one by one.

+
+
+ Example + 7: Discover + Things in a network +
+
let discovery = new ThingDiscovery({ method: "multicast" });
+setTimeout( () => {
+    discovery.stop();
+    console.log("Stopped open-ended discovery");
+  },
+  10000);
+do {
+  let td = await discovery.next();
+  let thing = new ConsumedThing(td);
+  console.log("Thing name: " + thing.getThingDescription().title);
+} while (!discovery.done);
+
+
+
+
+

9. Security and + Privacy

+

A detailed discussion of security and privacy considerations + for the Web of Things, including a threat model that can be + adapted to various circumstances, is presented in the + informative document [WOT-SECURITY-GUIDELINES]. 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-BEST-PRACTICES]. That document + may be updated as security measures evolve. Following these + practices does not guarantee security, but it might help avoid + common known vulnerabilities.

+
+

The WoT security risks and possible mitigations are + concerning the following groups:

+ +
+
+

+ 9.1 Scripting Runtime Security and + Privacy Risks

+

This section is normative and contains specific risks + relevant for the WoT Scripting Runtime.

+
+

+ 9.1.1 Corrupted Input Security and + Privacy Risk

+

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.

+
+
Mitigation:
+
+ Implementors of this API SHOULD perform validation on all script + inputs. In addition to input validation, fuzzing + should be used to verify that the input processing is + done correctly. There are many tools and techniques in + existence to do such validation. More details can be + found in [WOT-SECURITY-TESTING]. +
+
+
+
+

+ 9.1.2 Physical Device Direct + Access Security and Privacy Risk

+

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).

+
+
Mitigation:
+
The WoT Scripting Runtime SHOULD avoid directly exposing the native + device interfaces to the script developers. Instead, a + WoT Scripting Runtime should provide a hardware + abstraction layer for accessing the native device + interfaces. Such hardware abstraction layer should refuse + to execute commands that might put the device (or + environment) to an unsafe state. Additionally, in order + to reduce the damage to a physical WoT device in cases a + script gets compromised, it is important to minimize the + number of interfaces that are exposed or accessible to a + particular script based on its functionality.
+
+
+
+

+ 9.1.3 Provisioning and Update + Security Risk

+

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.

+
+
Mitigation:
+
Post-manufacturing provisioning or update of scripts, + WoT Scripting Runtime or any related data should be done + in a secure fashion. A set of recommendations for secure + update and post-manufacturing provisioning can be found + in [WOT-SECURITY-GUIDELINES].
+
+
+
+

+ 9.1.4 Security Credentials Storage + Security and Privacy Risk

+

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.

+
+
Mitigation:
+
The WoT Scripting Runtime should securely store the + provisioned security credentials, guaranteeing their + integrity and confidentiality. In case there are more + than one tenant on a single WoT-enabled device, a WoT + Scripting Runtime should guarantee isolation of each + tenant provisioned security credentials. Additionally, in + order to minimize a risk that provisioned security + credentials get compromised, the WoT Scripting Runtime + should not expose any API for scripts to query the + provisioned security credentials.
+
+
+
+
+

9.2 Script Security and Privacy Risks

+

This section is non-normative.

+

This section describes specific risks relevant for script + developers.

+
+

+ 9.2.1 Corrupted Script Input + Security and Privacy Risk

+

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.

+
+
Mitigation:
+
+ Script developers should perform validation on all + application defined script inputs. In addition to input + validation, fuzzing + could be used to verify that the input processing is + done correctly. There are many tools and techniques in + existence to do such validation. More details can be + found in [WOT-SECURITY-TESTING]. +
+
+
+
+

9.2.2 Denial Of Service Security + Risk

+

If a script performs a heavy functional processing on + received requests before the request is authenticated, it + presents a great risk for Denial-Of-Service (DOS) + attacks.

+
+
Mitigation:
+
Scripts should avoid heavy functional processing + without prior successful authentication of requestor. The + set of recommended authentication mechanisms can be found + in [WOT-SECURITY-BEST-PRACTICES].
+
+
+
+

9.2.3 Stale TD Security Risk

+

During the lifetime of a WoT network, a content of a TD + can change. This includes its identifier, which might not + be an immutable one and might be updated periodically.

+
+
Mitigation:
+
Scripts should use this API to subscribe for + notifications on TD changes and do not rely on TD values + to remain persistent.
+
+
+
+ Editor's note +
+

While stale TDs can present a potential + problem for WoT network operation, it might not be a + security risk.

+
+
+
+
+
+

10. Terminology and conventions

+

The generic WoT terminology is defined in [WOT-ARCHITECTURE]: Thing, Thing Description (in short + TD), + Web of + Things (in short WoT), WoT Interface (same as + WoT + network interface), Protocol Bindings, + WoT + Runtime, Consuming a Thing + Description, Thing Directory, + WoT + Interactions, Property, Action, Event etc.

+

JSON-LD is + defined in [JSON-LD] as a + JSON document that is augmented with support for Linked + Data.

+

The terms URL, + URL + scheme, URL + host, URL + path, URL + record, parse a + URL, absolute-URL + string, path-absolute-URL + string, basic + URL parser are defined in [URL].

+

The terms MIME + type, Parsing + a MIME type, Serializing + a MIME type, valid MIME + type string, JSON MIME + type are defined in [MIMESNIFF].

+

The terms UTF-8 + encoding, UTF-8 + decode, encode, + decode are + defined in [ENCODING].

+

string, + parse + JSON from bytes and serialize + JSON to bytes, are defined in [INFRA].

+

The terms throw, + creating, + DOMString, + Dictionary, + ArrayBuffer, + BufferSource, + any, + not + present, DOMException, + AbortError, + SyntaxError, + NotSupportedError, + NetworkError, + + TypeError, NotReadableError, + TimeoutError, + + NoModificationAllowedError, + SecurityError, + are defined in [WEBIDL].

+

Promise, + Error, + JSON, + JSON.stringify, + JSON.parse + and + internal slots are defined in [ECMASCRIPT].

+

The terms browsing + context, + top-level browsing context, global + object, + current settings object, executing algorithms + in + parallel are defined in [HTML5] and are used in the context of + browser implementations.

+

The term + secure + context is defined in [WEBAPPSEC].

+

IANA media + types (formerly known as MIME types) are defined in + RFC2046.

+

The terms hyperlink reference and + relation + type are defined in [HTML5] and RFC8288.

+
+
+

A. API + design rationale

+

API rationale usually belongs to a separate document, but in + the WoT case the complexity of the context justifies including + basic rationale here.

+
+

+ A.1 Approaches to WoT application + development

+

The WoT Interest Group and Working Group have explored + different approaches to application development for WoT that + have been all implemented and tested.

+
+

A.1.1 No Scripting API

+

It is possible to develop WoT applications that only use + the WoT network + interface, typically exposed by a WoT gateway that + presents a REST-ful API towards clients and implements IoT + protocol plugins that communicate with supported IoT + deployments. One such implementation is the Mozilla WebThings + platform.

+
+
+

A.1.2 Simple Scripting API

+

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.

+
+
+ Example + 8: Open a + lock with a simple API +
+
let lock = await WoT.consume(‘https://td.my.com/lock-00123’);
+console.log(lock.status);
+lock.open('withThisKey');
+
+
+
+

A.1.3 This API, aligned with [WOT-TD]

+

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 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.

+
+
+ Example + 9: Open a + lock +
+
let res = await fetch(‘https://td.my.com/lock-00123’);
+let td = await res.json();
+let lock = new ConsumedThing(td);
+console.log(lock.readProperty(‘status’));
+lock.invokeAction(‘open’, 'withThisKey');
+
+
+

In conclusion, the WoT WG decided to explore the third + option that closely follows the [WOT-TD] 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 + [WOT-TD].

+

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.

+
+
+

A.2 Fetching and validating a TD

+

The fetch(url) method has been part of this + API in earlier versions. However, now fetching a TD + given a URL should be done with an external method, such as + the Fetch + API or a HTTP client library, which offer already + standardized options on specifying fetch details. The reason + is that while simple fetch operations (covering most use + cases) could be done in this API, when various fetch options + were needed, there was no point in duplicating existing work + to re-expose those options in this API.

+

Since fetching a TD has been scoped out, and TD + validation is defined externally in [WOT-TD], that is scoped + out, too. This specification expects a TD as parsed + JSON object that has been validated according to the + [WOT-TD] specification.

+
+
+

A.3 Factory vs constructors

+

The factory methods for consuming and exposing Things are asynchronous and fully validate the + input TD. In addition, one can also construct ConsumedThing and ExposedThing by providing a parsed and + validated TD. Platform initialization is then + done when needed during the WoT interactions. So applications + that prefer validating a TD themselves, may use + the constructors, whereas applications that leave validation + to implementations and prefer interactions initialized up + front SHOULD use the + factory methods on the WoT API object.

+
+
+

A.4 + Observers

+

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.

+
+
+

A.5 Using + Events

+
+

This API ended up not using software events at all, for + the following reasons:

+
    +
  • Subscription to WoT Events may be + different from handling software events (subscription + might need parameters, might involve security tokens + etc). +
  • +
  • Most implementations are for Node.js and browser + implementations will likely be libraries (because + possible dependency management issues in native + implementations), using Events has been challenging.
  • +
  • Observing Property changes + and handling WoT Events is done + with the solution above. +
  • +
+
+
+
+

A.6 Polymorphic functions

+

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 [WOT-TD].

+
+
+
+

B. Changes

+
+

The following is a list of major changes to the document. + Major versions of this specification are the following:

+ +
+

For a complete list of changes, see the github + change log. You can also view the + recently closed issues.

+
+
+

C. Open issues

+
+

The following problems are being discussed and need most + attention:

+ +
+
+
+

D. Full Web + IDL

+
typedef object ThingDescription;
+
+[SecureContext, Exposed=(Window,Worker)]
+interface WOT {
+  // methods defined in UA conformance classes
+};
+
+partial interface WOT {
+  Promise<ConsumedThing> consume(ThingDescription td);
+};
+
+partial interface WOT {
+  Promise<ExposedThing> produce(ThingDescription td);
+};
+
+partial interface WOT {
+  ThingDiscovery discover(optional ThingFilter filter = null);
+};
+
+[SecureContext, Exposed=(Window,Worker)]
+interface ConsumedThing {
+  constructor(ThingDescription td);
+  Promise<any> readProperty(DOMString propertyName,
+                            optional InteractionOptions options = null);
+  Promise<PropertyMap> readAllProperties(optional InteractionOptions options = null);
+  Promise<PropertyMap> readMultipleProperties(
+                            sequence<DOMString> propertyNames,
+                            optional InteractionOptions options = null);
+  Promise<void> writeProperty(DOMString propertyName,
+                              any value,
+                              optional InteractionOptions options = null);
+  Promise<void> writeMultipleProperties(PropertyMap valueMap,
+                              optional InteractionOptions options = null);
+  Promise<any> invokeAction(DOMString actionName,
+                              optional any params = null,
+                              optional InteractionOptions options = null);
+  Promise<void> observeProperty(DOMString name,
+                              WotListener listener,
+                              optional InteractionOptions options = null);
+  Promise<void> unobserveProperty(DOMString name);
+  Promise<void> subscribeEvent(DOMString name,
+                              WotListener listener,
+                              optional InteractionOptions options = null);
+  Promise<void> unsubscribeEvent(DOMString name);
+  ThingDescription getThingDescription();
+};
+dictionary InteractionOptions {
+  object uriVariables;
+};
+typedef object PropertyMap;
+callback WotListener = void(any data);
+
+[SecureContext, Exposed=(Window,Worker)]
+interface ExposedThing: ConsumedThing {
+  ExposedThing setPropertyReadHandler(DOMString name,
+          PropertyReadHandler readHandler);
+  ExposedThing setPropertyWriteHandler(DOMString name,
+          PropertyWriteHandler writeHandler);
+  ExposedThing setActionHandler(DOMString name, ActionHandler action);
+  void emitEvent(DOMString name, any data);
+  Promise<void> expose();
+  Promise<void> destroy();
+};
+callback PropertyReadHandler = Promise<any>(
+        optional InteractionOptions options = null);
+callback PropertyWriteHandler = Promise<void>(any value,
+        optional InteractionOptions options = null);
+callback ActionHandler = Promise<any>(any params,
+        optional InteractionOptions options = null);
+
+[SecureContext, Exposed=(Window,Worker)]
+interface ThingDiscovery {
+  constructor(optional ThingFilter filter = null);
+  readonly attribute ThingFilter? filter;
+  readonly attribute boolean active;
+  readonly attribute boolean done;
+  readonly attribute Error? error;
+  void start();
+  Promise<ThingDescription> next();
+  void stop();
+};
+
+typedef DOMString DiscoveryMethod;
+
+dictionary ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  USVString? url;
+  USVString? query;
+  object? fragment;
+};
+
+
+

E. + Acknowledgements

+

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.

+
+
+

F. + References

+
+

F.1 Normative references

+
+
[ECMASCRIPT]
+
+ ECMAScript + Language Specification. Ecma International. + URL: https://tc39.github.io/ecma262/ +
+
[ENCODING]
+
+ Encoding + Standard. Anne van Kesteren. WHATWG. Living + Standard. URL: https://encoding.spec.whatwg.org/ +
+
[HTML]
+
+ HTML + Standard. Anne van Kesteren; Domenic Denicola; + Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. + Living Standard. URL: https://html.spec.whatwg.org/multipage/ +
+
[HTML5]
+
+ HTML5. + Ian Hickson; Robin Berjon; Steve Faulkner; Travis + Leithead; Erika Doyle Navara; Theresa O'Connor; Silvia + Pfeiffer. W3C. 27 March 2018. W3C Recommendation. URL: + https://www.w3.org/TR/html5/ +
+
[INFRA]
+
+ Infra + Standard. Anne van Kesteren; Domenic Denicola. + WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/ +
+
[JSON-LD]
+
+ JSON-LD + 1.0. Manu Sporny; Gregg Kellogg; Markus + Lanthaler. W3C. 16 January 2014. W3C Recommendation. URL: + https://www.w3.org/TR/json-ld/ +
+
[MIMESNIFF]
+
+ MIME + Sniffing Standard. Gordon P. Hemsley. WHATWG. + Living Standard. URL: https://mimesniff.spec.whatwg.org/ +
+
[RFC2119]
+
+ Key + words for use in RFCs to Indicate Requirement + Levels. S. Bradner. IETF. March 1997. Best + Current Practice. URL: https://tools.ietf.org/html/rfc2119 +
+
[RFC8174]
+
+ Ambiguity of + Uppercase vs Lowercase in RFC 2119 Key Words. + B. Leiba. IETF. May 2017. Best Current Practice. URL: + https://tools.ietf.org/html/rfc8174 +
+
[TYPESCRIPT]
+
+ + TypeScript Language Specification. + Microsoft. 1 October 2012. URL: + https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md +
+
[URL]
+
+ URL + Standard. Anne van Kesteren. WHATWG. Living + Standard. URL: https://url.spec.whatwg.org/ +
+
[WEBAPPSEC]
+
+ + Secure Contexts. W3C. 17 July 2015. URL: + https://w3c.github.io/webappsec/specs/powerfulfeatures +
+
[WEBIDL]
+
+ Web + IDL. Boris Zbarsky. W3C. 15 December 2016. W3C + Editor's Draft. URL: https://heycam.github.io/webidl/ +
+
[WOT-ARCHITECTURE]
+
+ Web of + Things Architecture. W3C. 16 May 2019. URL: + https://www.w3.org/TR/2019/CR-wot-architecture-20190516/ +
+
+ [WOT-PROTOCOL-BINDINGS]
+
+ Web + of Things Protocol Binding Templates. W3C. 20 + August 2017. URL: https://w3c.github.io/wot-binding-templates/ +
+
+ [WOT-SECURITY-BEST-PRACTICES]
+
+ + Web of Things Security and Privacy Best + Practices. W3C. WIP. URL: + https://github.com/w3c/wot-security/blob/master/wot-security-best-practices.md +
+
+ [WOT-SECURITY-GUIDELINES]
+
+ Web + of Things Security and Privacy Guidelines. + W3C. 28 August 2017. URL: https://w3c.github.io/wot-security/ +
+
+ [WOT-SECURITY-TESTING]
+
+ + Web of Things Security Testing and + Validation. W3C. WIP. URL: + https://github.com/w3c/wot-security/blob/master/wot-security-testing.md +
+
[WOT-TD]
+
+ WoT + Thing Description . W3C. 16 May 2019. URL: + https://www.w3.org/TR/2019/CR-wot-thing-description-20190516/ +
+
+
+
+ + + + diff --git a/releases/wd4/README.md b/releases/wd4/README.md new file mode 100644 index 00000000..c1a29281 --- /dev/null +++ b/releases/wd4/README.md @@ -0,0 +1,15 @@ +# WoT Scripting API - Release Notes + +The changes compared to [previous version](https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/) are also enumerated in the +[Changes](https://w3c.github.io/wot-scripting-api/#Changes) section of the spec. + +This version, introducing the following major changes: +- Remove fetch() for fetching a TD (delegated to external API). +- Remove Observer and use W3C TAG recommended design patterns. +- Align the discovery API to other similar APIs (such as W3C Generic Sensor API). +-Remove the large data definition API for constructing TDs and leverage using ThingDescription instead. +- Add missing algorithms and rework most existing ones. +- Allow constructors for ConsumedThing and ExposedThing. +- Add API rationale as an appendix to this document. + +For a complete list of changes, see the [github change log](https://github.com/w3c/wot-scripting-api/commits/master). \ No newline at end of file diff --git a/releases/wd4/diff.html b/releases/wd4/diff.html new file mode 100644 index 00000000..f9ea198e --- /dev/null +++ b/releases/wd4/diff.html @@ -0,0 +1,26927 @@ + + + + + + + + + + + + +Web of Things (WoT) Scripting API + + + + + + + + + + + + + + + + + + + +
+ +

+Web +of +Things +(WoT) +Scripting +API +

+

+W3C +Working +Draft +29 +November +2018 + + +

+
+
+This +version: +
+
+https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/ + + +https://www.w3.org/TR/2019/WD-wot-scripting-api-20191028/ + + +
+
+Latest +published +version: +
+
+ +https://www.w3.org/TR/wot-scripting-api/ + +
+
+Latest +editor's +draft: +
+
+ +https://w3c.github.io/wot-scripting-api/ + +
+
+Previous +version: +
+
+https://www.w3.org/TR/2018/WD-wot-scripting-api-20180405/ + + +https://www.w3.org/TR/2018/WD-wot-scripting-api-20181129/ + + +
+
+Editors: +
+
+ +Zoltan +Kis + +( + +Intel + +) +
+Kazuaki +Nimura +( +Fujitsu +Ltd. +) + +
+ +Daniel +Peintner + +( + +Siemens +AG + +) +
+
+ +Johannes +Hund + +(Former +Editor, +when +at +Siemens +AG) +
+Contributors: +In +the +GitHub +repository + +
+ +Kazuaki +Nimura + +(Former +Editor, +at +Fujitsu +Ltd.) + +
+
+Repository: +
+
+ +We +are +on + +On + +GitHub + +
+
+ +File +a +bug + +
+
+Contributors: +
+Contributors +on +GitHub +
+
+ +
+
+
+

+Abstract +

+

+The +overall + +main + + +Web +of +Things + +(WoT) +concepts +are +described +in +the + +WoT +Architecture + +document. +The +Web +of +Things +is +made +of +entities +( + +Thing + +s) +that +can +describe +their +capabilities +in +a +machine-interpretable +format, +the + + +Thing +Description + +(TD) +and +expose +these +capabilities +through +the + +WoT +Interface +, +that +is, +network +interactions +modeled +as + +Properties + +for + +(for + +reading +and +writing +values, + +values), + +Action + +s +to + +(to + +execute +remote +procedures +with +or +without +return +values + +values) + +and + +Event + +s +for + +(for + +signaling +notifications. +This +specification +describes +a +programming +interface +representing +the +WoT +Interface +that +allows +scripts +run +on +a +Thing +to +discover +and +consume +(retrieve) +other +Thing +Description +s +and +to +expose +Things +characterized +by +WoT +Interactions +specified +by +a +script. + +notifications). + +

+

+Scripting +is +an +optional +"convenience" +building +block +in +WoT +and +it +is +typically +used +in +gateways +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 +like + +such +as + + +Thing +Directory +. +

+

+This +specification +describes +a +programming +interface +representing +the + +WoT +Interface + +that +allows +scripts +to +discover, +operate + +Thing + +s +and +to +expose +locally +defined + +Things + +characterized +by + +WoT +Interactions + +specified +by +a +script. +

+The +specification +deliberately +follows +the + +WoT +Thing +Description +specification + +closely. +It +is +possible +to +implement +simpler +APIs +on +top +of +this +API, +or +implementing +directly +the +WoT +network +facing +interface +(i.e. +the + +WoT +Interface + +). +

+Editor's +note +

+This +specification +is +implemented +at +least +by +the + +Thingweb + +project +also +known +as + +node-wot +, +which +is +considered +the +reference +open +source +implementation +at +the +moment. +Check +its + +source +code +, +including + +examples +. +Other, +closed +source +implementations +have +been +made +by +WG +member +companies +and +tested +against + +node-wot + +in +plug-fests. +

+
+
+

+Status +of +This +Document +

+

+ +This +section +describes +the +status +of +this +document +at +the +time +of +its +publication. +Other +documents +may +supersede +this +document. +A +list +of +current + +W3C + +publications +and +the +latest +revision +of +this +technical +report +can +be +found +in +the + + +W3C + +technical +reports +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. +

+
+
+ +Editor's +note + +: + +: +The +W3C +WoT +WG +is +asking +for +feedback + +
+

+Please +contribute +to +this +draft +using +the + +GitHub +Issue + +feature +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 +a +Working +Draft. +This +document +is +intended +to +become +a +W3C +Recommendation. +

+

+Comments +regarding +this +document +are +welcome. +Please +send +them +to + +public-wot-wg@w3.org + +( +subscribe +, + + +archives + +). +

+

+Changes +from +the +previous +publication +can +be +found +in +Appendix +A +. +A +diff-marked +version +of +this +document +is +also +available +for +comparison +purposes. + +Publication +as +a +Working +Draft +does +not +imply +endorsement +by +the + +W3C + +Membership. +This +is +a +draft +document +and +may +be +updated, +replaced +or +obsoleted +by +other +documents +at +any +time. +It +is +inappropriate +to +cite +this +document +as +other +than +work +in +progress. +

+

+This +document +was +produced +by +a +group +operating +under +the + + +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 + +1 +February +2018 + +March +2019 + + +W3C + +Process +Document +. +

+
+ +
+

+ +1. + +Introduction + + +

+

+WoT +provides +layered +interoperability +based +on +how + +Thing + +s +are +modeled: +as +being + +used: + +"consumed" +and +"exposed". + +"exposed", +as + +defined + +in +[ + +WOT-ARCHITECTURE + +]. + +

+

+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 + +exposed + +on +a +remote +device. +

+
+

+Exposing +a + +Thing + +requires + +requires: +

+This +specification +describes +how +to +expose +and +consume + +Thing + +s +by +a +script. +Also, +it +defines +a +generic +API +for + +Thing + +discovery. +
+
+ +Note + +
+

+Typically +scripts +are +meant +to +be +used +on +devices +able +to +provide +resources +(with +a +WoT +Interface +) +for +managing +(installing, +updating, +running) +scripts, +such +as + +bridges +or +gateways +that +expose +and +control +simpler +devices +as +WoT + +Thing + +s. + +s +and +have +means +to +handle +(e.g. +install, +uninstall, +update +etc.) +and +run +scripts. + +

+
+
+
+ +Note + +
+

+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. +

+
+For +an +introduction +on +how +scripts +could +be +used +in +Web +of +Things +, +check +the +Primer +document. +For +some +background +on +API +design +decisions +check +the +Rationale +document. + +
+
+

+ +2. + +Use +Cases + + +

+

+ +This +section +is +non-normative. + +

+

+The +following +scripting +use +cases +are +supported +in +this +specification: +

+2.1 +Discovery +Discover +all +Thing +s +in +the +WoT +network +by +sending +a +broadcast +request. +Discover +Thing +s +running +in +the +local +WoT +Runtime +. +Discover +nearby +Thing +s, +for +instance +connected +by +NFC +or +Bluetooth. +Discover +Thing +s +by +sending +a +discovery +request +to +a +given +registry. +Discover +Thing +s +by +filters +defined +on +Thing +Description +s +Discover +Thing +s +by +semantic +queries. +Stop +or +suppress +an +ongoing +discovery +process. +Optionally +specify +a +timeout +to +the +discovery +process +after +which +it +is +stopped/suppressed. + +
+

+2.2 + + +2.1 + +Consuming +a +Thing + + +

+ +
+
+

+2.3 + + +2.2 + +Exposing +a +Thing + + +

+ +
+3. +The +WoT + +
+

+object + + +2.3 + +Discovery + + +The +WoT +object +is +the +API +entry +point +and +it +is +exposed + +

+

+ThingModel + + +3. + +Conformance + + +; + +

+

+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 + + +] +[ + +Editor's +note + + +RFC8174 + +The +algorithms +for +the +WoT +methods +will +be +specified +later, +including +error +handling + + +] +when, + +and +security +considerations. + +only +when, +they +appear +in +all +capitals, +as +shown +here. + +

+

+The +ThingModel + +This +specification +describes +the +conformance +criteria +for +the +following +classes +of + +user +agent + + +type +represents +either + +( + +UA + +). +

+Due +to +requirements +of +small +embedded +implementations, +splitting +WoT +client +and +server +interfaces +was +needed. +Then, +discovery +is + +a +ThingFragment +, +or + +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 + + +ThingDescription + +consume() +, +produce() + + +. +3.1 +The + +and + + +discover() + +methods +on +the + +WoT +API +object + +in +order +to +determine +which +conformance +class +the + +UA + +implements. +

+ +WoT +Consumer + + +method + + +UA + + +
+
+

+Starts +the +discovery +process +that +will +provide +ThingDescription +s +that +match +the +optional +argument +filter + +Implementations + +of +type + +this +conformance +class + +MUST + +implement +the + + + + +ThingFilter + +ConsumedThing + + + +. +Returns +an +[ +Observable + + +](https://github.com/tc39/proposal-observable) +object +that +can +be +subscribed +to + +interface + +and +unsubscribed +from. +The +handler +function +provided +to + +the +Observable +during +subscription +will +receive +an +argument +of +type +USVString +representing +a + + +ThingDescription + +consume() + + +method +on +the + +WoT +API +object + +. +

+3.1.1 +The +DiscoveryMethod + +
+
+ +WoT +Producer + + +enumeration + + +UA + + +<span class="idlTypedef" id= +"idl-def-discoverymethod" data-idl="" data-title= +"DiscoveryMethod">typedef <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="" data-lt="" href="#dom-discoverymethod" class= +"internalDFN" data-link-type= +"dfn"> + +
+
+

+Implementations +of +this +conformance +class + +MUST + +implement + + +DiscoveryMethod + +ExposedThing + + + +; + + +interface +and +the + +produce() + +method +on +the + +WoT +API +object +.

+ +WoT +Discovery + +UA + +
+
+

+Implementations +of +this +conformance +class + +MUST + +implement +the + + + +DiscoveryMethod + +ThingDiscovery + + + +represents + + +interface +and + +the +discovery +type +to + + +discover() + +method +on +the + +WoT +API +object +.

+These +conformance +classes + +MAY + +be +used: + +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 +[ + +"any" +does +not +provide +any +restriction + + +WEBIDL + +"local" +for +discovering +Thing + + +]. +

+The + +UA + + +s +defined + +may +be +implemented + +in +the +same +device + +browser, + +or +connected +to +the +device +by +wired + +in +a +separate +runtime +environment, +such +as + +Node.js + +or +wireless +means. +"directory" +for +discovery +based +on + +in +small +embedded +runtimes. +

+Implementations +that +use +ECMAScript +executed +in + +a +service +provided +by + +browser +to +implement +the +APIs +defined +in +this +document + +MUST + +implement +them +in + +a +Thing +Directory +. + +manner +consistent +with +the +ECMAScript +Bindings +defined +in +the +Web +IDL +specification +[ + +"multicast" +for +discovering +Thing + + +WEBIDL + + +s + + +]. +

+Implementations +that +use +TypeScript +or +ECMAScript + +in +a +runtime +to +implement + +the +device's +network +by +using + +APIs +defined +in +this +document + +MUST + +implement +them +in + +a +supported +multicast +protocol. + +manner +consistent +with +the +TypeScript +Bindings +defined +in +the +TypeScript +specification +[ + +TYPESCRIPT + +]. +

+
+
+

+3.1.2 + + +4. + +The + + +ThingFilter + +ThingDescription + + + +dictionary + +type + + +The + +

+
"idl-def-thingdescription" data-title=
+"ThingDescription">typedef object 
+
+
+ThingFilter
+
+ThingDescription
+
+
+
+dictionary
+that
+represents
+the
+constraints
+for
+discovering
+Thing
+s
+as
+key-value
+pairs.
+<span class="idlDictionary" id=
+"idl-def-thingfilter" data-idl="" data-title=
+"ThingFilter">dictionary <span class=
+"idlDictionaryID"><a data-no-default="" data-link-for="" data-lt=""
+href="#dom-thingfilter" class="internalDFN" data-link-type=
+"dfn"> {<span class="idlMember"
+id="idl-def-thingfilter-method" data-idl="" data-title="method"
+data-dfn-for="thingfilter">
+  (<a data-link-for="" href="#dom-discoverymethod" class=
+"internalDFN" data-link-type=
+"dfn"> or <a href=
+"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default=""
+data-link-for="thingfilter" data-lt="" href=
+"#dom-thingfilter-method" class="internalDFN" data-link-type=
+"dfn"> = <span class=
+"idlMemberValue">"any"<span class="idlMember" id=
+"idl-def-thingfilter-url" data-idl="" data-title="url"
+data-dfn-for="thingfilter">
+  <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default=""
+data-link-for="thingfilter" data-lt="" href="#dom-thingfilter-url"
+class="internalDFN" data-link-type=
+"dfn"><span class="idlMember"
+id="idl-def-thingfilter-query" data-idl="" data-title="query"
+data-dfn-for="thingfilter">
+  <a href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString<a data-no-default=""
+data-link-for="thingfilter" data-lt="" href=
+"#dom-thingfilter-query" class="internalDFN" data-link-type=
+"dfn"><span class="idlMember"
+id="idl-def-thingfilter-fragment" data-idl="" data-title="fragment"
+data-dfn-for="thingfilter">
+  <a data-link-for="" href="#dom-thingfragment" class="internalDFN"
+data-link-type=
+"dfn"> <span class=
+"idlMemberName"><a data-no-default="" data-link-for="thingfilter"
+data-lt="" href="#dom-thingfilter-fragment" class="internalDFN"
+data-link-type="dfn">
+};
+
+;
+
+
+
+

+The +method +property +represents +the +discovery +type +that +should +be +used +in +the +discovery +process. +The +possible +values +are + +Represents +a + +Thing +Description + +( + +TD + +) +as + +defined +by +the +DiscoveryMethod + +in +[ + + +WOT-TD + + +enumeration +that +MAY + + +]. +It +is +expected +to + +be +extended +by +string +values +defined +by +solutions +(with +no +guarantee +of +interoperability). +The +url +property +represents +additional +information +for +the +discovery +method, +such +as +the +URL +of +the +target +entity +serving +the +discovery +request, +for +instance + +a +Thing +Directory + + +parsed +JSON +object + + +(if +method + +that + +is +"directory" +) +or + +validated +using + +JSON +schema +validation +.

+4.1 + +Fetching + +a +Thing +(otherwise). +The + +Description + +query + + +property +represents + +

+

+Fetching + +a +query +string +accepted +by +the +implementation, +for +instance + + +TD + +given + +a +SPARQL +or +JSON +query. +Support +may + +URL +should + +be +implemented +locally +in + +done +with +an +external +method, +such +as + +the +WoT +Runtime + + +Fetch +API + + +or +remotely +as + +a +service +in + +HTTP +client +library, +which +offer +already +standardized +options +on +specifying +fetch +details. +

+Example + +1 +: +Fetching + +a +Thing +Directory +. +The + +Description + +fragment + +
+
"hljs-keyword">try {
+  let res = 
+"hljs-keyword">await fetch('https://tds.mythings.biz/sensor11');
+  
+"hljs-comment">// ... additional checks possible on res.headers
+  let td = 
+"hljs-keyword">await res.json();
+  let thing = 
+"hljs-keyword">new ConsumedThing(td);
+  console.log(
+"hljs-string">"Thing name: " + thing.getThingDescription().title);
+} catch (err) {
+  console.log(
+"hljs-string">"Fetching TD failed", err.message);
+}
+
+
+property
+represents
+
+
+
+
+
+

+ +4.2 + +Expanding + +a +Thing +Description + +ThingFragment + + +

+

+Note +that +[ + +WOT-TD + + +dictionary +used +for +matching +property +by +property +against +discovered + + +] +allows +using +a +shortened + +Thing +Description + + +s. + +by +the +means +of + +defaults + +and +requiring +clients +to +expand +them +with +default +values +specified +in +[ + +WOT-TD + +] +for +the +properties +that +are +not +explicitly +defined +in +a +given + +TD +. +

+
+

+The +discover(filter) +method +MUST + +To + +expand +a +TD + +given + +td +, +run +the +following +steps: +

+
    +
  1. +If +invoking +discover() + +For +each +item +in +the + +TD +default +values + +table +from +[ + +WOT-TD + +], +if +the +term + +is +not +allowed +for + +defined +in + +td +, +add + +the +current +scripting +context +for +security +reasons, +throw +SecurityError +and +terminate +these +steps. + +term +definition +with +the +default +value +specified +in +[ + +WOT-TD + +]. + +
  2. +Return +an + +
+
+
+
+

+ +4.3 + +Validating +a +Thing +Description + +Observable + + +

+

+The +[ + + +WOT-TD + + +obs +and +execute + + +] +specification +defines +how +a + +TD + +should +be +validated. +Therefore, +this +API +expects + +the +next +steps +in +parallel +. +If + + + +obs.subscribe(handler, +errorHandler, +complete) + +ThingDescription + + +is +called, +execute + + +objects +be +validated +before +used +as +parameters. +This +specification +defines +a +basic + +TD + +validation +as +follows. +

+To + +validate +a +TD + +given + +td +, +run + +the +following +sub-steps: + +steps: +

+
    +
  1. +If +the +first +argument + + +handler + +td + + +is +not +defined +or +it +is +not +a +function, + +an +object, + +throw + +TypeError + +"TypeError" + + +and +terminate +the +algorithm. +Otherwise +configure +handler +to +be +invoked +when +a +discovery +hit +happens. + +these +steps. + +
  2. +
  3. +If +any +of + +the +second +argument + +mandatory +properties +defined +in +[ + +WOT-TD + +] +for + +Thing + +that +don't +have + +default +definitions + +are +missing +from + + +errorHandler +is +defined, +but +it +is +not +a +function, + +td +, +throw + +TypeError + +"TypeError" + + +and +terminate +these +steps. +Otherwise +if +defined, +save +it +to +be +invoked +in +error +conditions. + +
  4. +
  5. +If +the +third +argument + + +JSON +schema +validation + +fails +on + + +onComplete +is +defined, +but +it +is +not +a +function, + +td +, +throw + +TypeError + +"TypeError" + + +and +terminate +these +steps. +Otherwise +if +defined, +save +it +to +be +invoked +when +the +discovery +process +finished +for +other +reasons +than +having +been +canceled. + +
  6. +If +filter.query +is +defined, +pass +it +as +an +opaque +string +to +the +underlying +implementation +to +be +matched +against +discovered +items. + +
+
+
+
+
+

+ +5. + +The +underlying +implementation +is +responsible +to +parse +it +e.g. +as +a +SPARQL +or +JSON +query +and +match +it +against +the +Thing +Description + + +WoT +API +object + + +s +found +during + +

+

+Defines + +the +discovery +process. +If +queries +are +not +supported, +implementations +SHOULD +throw + +API +entry +point +exposed +as + +a +NotSupported +error +and +terminate +these +steps. +If +filter.fragment +is +defined, + +singleton + +and +if +it + +contains +other +properties +than + +the +ones +defined +in + +API +methods. +

+5.1 + +The + + +ThingFragment + +WOT + + +, +throw + + +interface +


+"idl-def-wot" data-title="WOT">[SecureContext, Exposed=(Window,Worker)]
+interface WOT {
+  // methods defined in UA conformance classes
+
+};
+
+Note +

+Browser +implementations +should +use +a +namespace +object +such +as + + +TypeError +and +terminate +these +steps. +Otherwise +save + +navigator.wot +. +Standalone +runtimes +may +expose + +the +API + +object +for +matching +the +discovered +items +against +it. +Request +the +underlying +platform +to +start +the +discovery +process, +with +the +following +parameters: +If +filter.method +is +not +defined + +through +mechanisms +like + +require() + +or +the +value +is + + +import +.

+5.2 + +The + + +"any" +, +use +the +widest +discovery + +consume() + +method +supported +by + + + +

+
"idl-def-wot-partial-1" data-title=
+"WOT">partial interface WOT {
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<ConsumedThing> consume(ThingDescription td);
+};
+

+Belongs +to + +the +underlying +platform. +Otherwise +if + + +WoT +Consumer + +conformance +class. +Expects +an + + +filter.method + +td + + +is +"local" +, +use +the +local +Thing +Directory + +argument +and +returns +a + +Promise + + +for +discovery. +Usually + +that +defines +Thing +s +deployed +in +the +same +device, +or +connected +to +the +device +in +slave +mode +(e.g. +sensors +connected +via +Bluetooth +or + +resolves +with + +a +serial +connection). +Otherwise +if +filter.method +is + + + +"directory" +, +use +the +remote +Thing +Directory + +ConsumedThing + + +specified +in +filter.url +. +Otherwise +if +filter.method +is +"multicast" +, +use +all +the +multicast +discovery +protocols +supported +by +the +underlying +platform. +Whenever + +object +that +represents + +a +new +item +td +is +discovered +by + +client +interface +to +operate +with + +the +underlying +platform, + + +Thing +. +The +method + +MUST + +run +the +following +sub-steps: + +steps: +

+
    +
  1. +If +filter.query +is +defined, +check +if +td +is + +Return + +a +match +for +the +query. +The +matching +algorithm +is +encapsulated +by +implementations. +If +that +returns +false +, +discard + + +Promise + + +td + +promise + + +and +continue + +execute + +the +discovery +process. + +next +steps + +in +parallel +. +
  2. +
  3. +If +filter.fragment + +invoking +this +method + +is +defined, + +not +allowed + +for +each +property +defined +in +it, +check +if +that +property +exists +in + +the +current +scripting +context +for +security +reasons, +reject + + +td + +promise + + +and +has +the +same +value. +If +this +is + +with + + +false + +SecurityError + + +in +any +checks, +discard +td + +and +continue +the +discovery +process. + +terminate +these +steps. + +
  4. +
  5. +Otherwise +if + +Run +the + +validate +a +TD + +steps +on + + +td +has +not +been +discarded +in +the +previous +steps, +invoke +the + +. +If +that +throws, +reject + + +handler + +promise + + +function + +with +td +as +parameter. +Whenever +an +error +occurs +during + +the +discovery +process, + +error + +and +if + +terminate +these +steps. +
  6. +Let + + +errorHandler + +thing + + +is +defined, +invoke +it +with +an +argument +of +type +Error +whose +message +property +is +set +to + +be +a +new + + +UnknownError + +ConsumedThing + + +unless +there +was +an +error +code +provided +by +the +Protocol +Bindings +, +in +which +case +set +it +to +that +value. + + +object +constructed +from + +td +. +
  7. +
  8. +When + +Set +up + +the +discovery +process +is +finished, + + +WoT +Interactions + +based +on +introspecting + +td + +as +explained +in +[ + +WOT-TD + +] + +and +if +onComplete +is +defined, +invoke +it +run +the +cancel +discovery + +[ + +WOT-PROTOCOL-BINDINGS + + +steps. +When +the +obs.unsubscribe() +method +is +called, +run +the +following +cancel +discovery +steps: +Request + + +]. +Make +a +request +to + +the +underlying +platform +to +stop + +initialize + +the +discovery +process. +If +this +returns +an +error, +or +if +it +is +not +possible, +for +instance +when +discovery +is +based +on +open +ended +multicast +requests, + + +Protocol +Bindings +. +The +details +are +private +to + +the +implementation +SHOULD +discard +subsequent +discovered +items. + +implementations +and +out +of +scope +of +this +specification. + +
  9. +
  10. +Set + +Resolve + + +obs.closed + +promise + + +to +false +. + +with + +thing +. +
  11. +
+
+
+
+

+3.2 + + +5.3 + +The + + +fetch() + +produce() + + + +method + + +

+
"idl-def-wot-partial-2" data-title=
+"WOT">partial interface WOT {
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<ExposedThing> produce(ThingDescription td);
+};
+
+

+Accepts +an +url +argument +of +type +USVString +that +represents + +Belongs +to +the + +WoT +Producer + +conformance +class. +Expects + +a +URL +(e.g. +"file://..." +or + + +"https://..." + +td + + +) + +argument + +and +returns +a + +Promise + +that +resolves +with +a + +an + + +ThingDescription + +ExposedThing + + + +(a +serialized +JSON-LD +document +of +type + +object +that +extends + + +USVString + +ConsumedThing + + +). + + +with +a +server +interface, +i.e. +the +ability +to +define +request +handlers. + +The +fetch(url) + +method + +MUST + +run +the +following +steps: +

+
    +
  1. +Return +a + +Promise + + +promise + +and +execute +the +next +steps + +in +parallel +. +
  2. +
  3. +If +invoking +fetch() + +this +method + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  4. +
  5. +If +the +argument + +Let + + +url + +thing + + +is +not + +be + +a +URL, +reject + +new + +ExposedThing + +object +constructed +with + +td +.
  6. +Resolve + + +promise + +with + +thing +.

+5.4 + +The + + +TypeError + +discover() + + +and +terminate +these +steps. +Make +a +request + + +method +


+"idl-def-wot-partial-3" data-title=
+"WOT">partial interface WOT {
+  
+"internalDFN" data-link-type=
+"idl">ThingDiscovery discover(optional ThingFilter filter = null);
+};
+

+Belongs + +to +fetch +the +content +of +url +as +described +by + +the +Protocol +Bindings + + +WoT +Discovery + + +and +wait +for +the +reply. +Implementations +encapsulate + +conformance +class. +Starts + +the +fetching + +discovery + +process +and +the +accepted +media +types +(such +as + +that +will +provide + + +application/td+json + +ThingDescription + + +), +as +far +as +a +valid + + +objects +for + + +Thing +Description + +can +be +obtained +as +defined +in +[ +WOT-TD +]. +Let + +s +that +match +an +optional + + +td + +filter + + +be +the +Thing +Description +string-serialized +from +the +returned +content, +as +specified +in + +argument. +The +method + +MUST + +run + +the +Thing +Description +serialization +. + +following +steps: +

    +
  1. +If +there +was +an +error +during + +invoking +this +method +is +not +allowed +for + +the +request, +reject +promise +with +an +Error +object +error +with + +current +scripting +context +for +security +reasons, +throw + + +error.message + +SecurityError + + +set +to +the +error +code +seen +by +the +Protocol +Bindings + +and +terminate +these +steps. +
  2. +
  3. +Otherwise +resolve + +Construct +a + +ThingDiscovery + +object + + +promise + +discovery + + +with + +td +and +terminate +these +steps. + +filter +.
  4. +Invoke +the + +discovery.start() + +method. +
  5. +Return + +discovery +. +
  6. +
+
+

+Refer +to +the + +ThingDiscovery + +section +for +how +discovery +should +be +implemented. +

+
+
+
+

+3.3 + + +6. + +The + + +consume() + +ConsumedThing + + + +method + +interface + + +

+

+Accepts +an + +Represents +a +client +API +to +operate +a + +Thing +. +Belongs +to +the + +WoT +Consumer + +conformance +class. +


+"idl-def-consumedthing" data-title="ConsumedThing">[SecureContext, Exposed=(Window,Worker)]
+interface ConsumedThing {
+  
+"dom-consumedthing-constructor" data-idl="constructor" data-title=
+"constructor" data-dfn-for="ConsumedThing" data-lt=
+"ConsumedThing.constructor()|ConsumedThing.constructor|constructor()|constructor">constructor(ThingDescription td);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> readProperty(DOMString propertyName,
+                            optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<PropertyMap> readAllProperties(optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<PropertyMap> readMultipleProperties(
+                            
+"" data-type="dfn" href=
+"https://heycam.github.io/webidl/#idl-sequence">sequence<DOMString> propertyNames,
+                            optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> writeProperty(DOMString propertyName,
+                              
+data-link-type="dfn" href=
+"https://heycam.github.io/webidl/#idl-any">any value,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> writeMultipleProperties(PropertyMap valueMap,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> invokeAction(DOMString actionName,
+                              optional any params = null,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> observeProperty(DOMString name,
+                              
+"#dom-wotlistener" class="internalDFN" data-link-type=
+"idl">WotListener listener,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> unobserveProperty(DOMString name);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> subscribeEvent(DOMString name,
+                              
+"#dom-wotlistener" class="internalDFN" data-link-type=
+"idl">WotListener listener,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> unsubscribeEvent(DOMString name);
+  
+"internalDFN" data-link-type=
+"idl">ThingDescription getThingDescription();
+};
+dictionary InteractionOptions {
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-object">object uriVariables;
+};
+typedef object PropertyMap;
+callback WotListener = void(
+
+
+td
+
+any
+
+
+argument
+of
+type
+
+
+
+
+data
+
+);
+
+
+
+

+ +6.1 + +Constructing + + +ThingDescription + +ConsumedThing + + + + +and +returns + +

+

+After + +fetching + +a + +Thing +Description + +as +a +JSON +object, +one +can +create +a + + +ConsumedThing + + +object +instantiated +based +on +parsing +that +description. + +object. + +

+
+

+The + +To +create + + +consume(td) + +ConsumedThing + + +method +must + + +with +the + +ThingDescription + +td +, +run +the +following +steps: +

+
    +
  1. +If + +Run + +the +argument +td +is +not +a +string, +throw + + +expand + +a +TypeError +and +terminate +these +steps. +Let +stub +be +the +result +of +running +the + +TD +parsing +algorithm + + +with + +steps +on + + +td +as +argument. + +. +If +that +throws +an +error, + +fails, + +re-throw +the +error +and +terminate +these +steps. +
  2. +
  3. +If + +Let + + +stub + +thing + + +does +not +have +an +own +property +that +is +defined +in +ThingFragment +with +a +default +value, +add +that +property +and +value +to +stub +. +Create + +be + +a +new + + +ConsumedThing + + +object + +object. +
  4. +Let +| + +td + +| +be +an +internal +slot +of + + +thing + +initialized +from + +and +let + + +stub + +td + + +that +implements + +be +its +value. +
  5. +Return + +thing +.

+ +6.2 + +The + + +Observable + +getThingDescription() + + +. +Add + + +method +

+Returns + +the +read() +and +write() +methods +to + +internal +slot +| + +td + +| +of + +the + + +ThingProperty + +ConsumedThing + + + +elements +so + +object + +that +they +make +requests +to +access + +represents + +the +remote + + +Thing +Description + + +s +and +wait +for +the +reply, +as +defined +by + +of + +the +Protocol +Bindings +. +Also, +all + + + +ThingProperty + +ConsumedThing + + +. +Applications +may +consult +the + +Thing + + +elements +SHOULD +implement + +metadata +stored +in +| + +td + +| +in +order +to +introspect +its +capabilities +before +interacting +with +it. +

+Observable + + +6.3 + +The + +, +i.e. +define +a + + +subscribe() + +InteractionOptions + + +method + + +dictionary +

+Holds +the +interaction +options + +that +should +make +request + +need +to +be +exposed +for +application +scripts +according + +to +observe +the +given +Properties +as +defined +by + +the +Protocol +Bindings + + +Thing +Description + +. +Add + +In +this +version +of + +the +invoke() +methods +to + +specification +only +URI +template +variables +are +used, +represented +as + +parsed +JSON +objects + +defined +in +[ + +WOT-TD + +]. +

+Editor's +note +

+The +support +for +URI +variables +comes +from + +the +need +exposed +by +[ + +ThingAction + + +WOT-TD + + +] +to +be +able +to +describe +existing + +TD + + +elements +so + +s + +that +they +make +requests + +use +them, +but +it +should +be +possible + +to +the +remote + +write +a + +Thing +Description + + +to +invoke +its +actions, +as +defined +by + +that +would +use + +Action + +s +for +representing + +the +Protocol +Bindings +. +Add + +interactions +that +need +URI +variables +and +represent + +the +subscribe() +method + +URI +variables +as +parameters + +to +all +ThingEvent + +the + +Action + + +elements +so + +and +in + +that +they +make +requests +to +subscribe +to +the +events +defined + +case +that +could +be +encapsulated + +by +the +remote +Thing +, +as +defined +by + +implementations +and + +the +Protocol +Bindings +. +Return + + +thing +. + +options + +parameter +could +be +dismissed +from +the +methods +exposed +by +this +API. +

+
+
+

+3.4 + + +6.4 + +The + + +produce() + +PropertyMap + + + +method + +type + + +

+

+Accepts + +Represents + +a +model +argument + +map + +of +type + + +Property + +names +as +strings +to +a +value +that +the + +Property + +can +take. +It +is +used +as +a +property +bag +for +interactions +that +involve +multiple + +Properties + +at +once. +

+ +Editor's +note +

+It +could +be +defined +in +Web +IDL +(as +well +as + + +ThingModel + +ThingDescription + + + +) +as +a + +maplike + +interface +from + +string + +to + +any +.

+ +6.5 + +The + +readProperty() + + + +method +

+Reads +a + +Property + +value. +Takes +a +string +argument + +propertyName + +and + +and +returns + +an +optional + + +ExposedThing + +InteractionOptions + + + +object. +The + + +options + +argument. +It +returns +a + +Property + +value +represented +as + + +produce(model) + +any + + +type. +The + +method + +MUST + +run +the +following +steps: +

+
    +
  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +invoking +produce() + +this +method + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +throw + +reject + +promise + +with + + +SecurityError + +and +terminate +these +steps. +
  3. +
  4. +If + +Make +a +request +to + +the +argument + +underlying +platform +(via +the + +Protocol +Bindings + +) +to +retrieve +the +value +of +the + +Property + +given +by + + +model + +propertyName + + +is +a +string, +then +run +the +TD +parsing +algorithm + +with +optional +URI +templates +given +in + + +model +passed +as +parameter. + +options.uriVariables +.
  5. +If +it +throws +an +error, +re-throw +that + +the +request +fails, +reject + +promise + +with +the + +error +received +from +the + +Protocol +Bindings + +and +terminate +this +algorithm. +Otherwise +let + +these +steps. +
  6. +Let + + +model + +value + + +be +the +returned +value. + +result +of +the +request. + +
  7. +
  8. +If + +Run +the + +validate +Property +value + +sub-steps +on + + +model + +value +:
    1. +Based +on +the + +DataSchema +definition +, +value + + + +MUST + +be +a +JSON +value +and +comply +to +the +data +schema +defined +for +the + +Property + +that + +is +not +an +object, + +found +in + +this.getThingDescription().properties[ + +propertyName + +] +.
    2. +If +this +fails, + +throw + +TypeError + +SyntaxError +, +otherwise +return + +value +.
  9. +If +these +above +steps +failed, +reject + +promise + +with + +SyntaxError + + +and +terminate +these +steps. +
  10. +
  11. +If + +Otherwise +resolve + + +model + +promise + + +does +not +have +an +own +property +that +is +defined +in + +with + +value +.

+ +6.6 + +The + + +ThingFragment + +readMultipleProperties() + + + +method + + +

+
+

+Reads +multiple + +Property + +values + +with +one +or +multiple +requests. +Takes +the + +propertyNames + +argument +as + +a +default +value, +add +that +property + +sequence +of +strings + +and +value +to +model +. +Create + +an +optional + + +ExposedThing + +InteractionOptions + + + +object + + +thing + +options + + +initialized + +argument. +It +returns +an +object +with +keys + +from + +model +. + +propertyNames + +and +values +returned +by +this +algorithm. +The +method + +MUST + +run +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +. +
  2. +
  3. +For +each +property +of + +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +ExposedThing + +SecurityError + + +defined + +and +terminate +these +steps. +
  4. +Let + +result + +be +an +object +and +for +each +string + +name + +in + +propertyNames + +add +a +property +with +key + +name + +and +the +value + + +ThingFragment +, +initialize + +null +.
  5. +Make +a +request +to + +the +property +based +on + +underlying +platform +(via + +the +provided +initial +or +default +values +provided + + +Protocol +Bindings + +) + +to +retrieve + +the +local +WoT +Runtime + + +Property + + +implementation, +for +instance +initialize: + +values +given +by + +propertyNames + +with +optional +URI +templates +given +in + +options.uriVariables +.
  6. +
  7. +the +id +property +to + +If +this +cannot + +be +done +with +a +single +request +with + +the +final +unique +identifier + + +Protocol +Bindings + +of +the + +Thing +, +the +security +object +of +type + +then +reject + +promise + +with + + +SecurityScheme + +NotSupportedError + + +to +represent + +and +terminate +these +steps. +
  8. +Process + +the +actual +security +scheme + +reply + +and +its + +update +all + +properties +as +set +up +by + +in + +result + +with + +the +implementation, + +values +obtained +in +the +reply. + +
  9. +
  10. +If + +the +above +step +fails +at +any +point, +reject + +promise + +with + + +properties + +SyntaxError + + +property +to +be +an +object + +and +terminate +these +steps. +
  11. +Resolve + +promise + +with +all +properties +being + + +result +.

+ +6.7 + +The + + +ThingProperty + +readAllProperties() + + + +method + + +objects +in +which + +

+
+

+Reads +all +properties +of + +the + +Thing + +with +one +or +multiple +requests. +Takes +an +optional + + +read() +and +write() + +InteractionOptions + + +methods +are +provided +to +define +local +methods +to +get +and +set +the + + + +options + +argument. +It +returns +an +object +with +keys +from + + +Property + +values, + +names +and +values +returned +by +this +algorithm. +The +method + +MUST + +run +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +. +
  2. +
  3. +If +invoking +this +method +is +not +allowed +for + +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +actions + +SecurityError + + +property +to + +and +terminate +these +steps. +
  4. +Let + +result + +be +an +object +with +all +properties +being +ThingAction +objects + +and +for +each +string + +name + +in +which + + +propertyNames + +add +a +property +with +key + +name + +and + +the +value + + +invoke() +method +is +provided +to +define + +null +.
  5. +Make + +a +local +method + +request + +to +run + +the +defined +Action + +underlying +platform +(via +the + +Protocol +Bindings + + +s, + +) +to +retrieve +the +value +of +the +all +the + +Property + +definitions +from +the + +TD + +with +optional +URI +templates +given +in + +options.uriVariables +. +
  6. +
  7. +the +events +property +to + +If +this +cannot + +be +an +object + +done + +with +all +properties +being +ExposedEvent + +a +single +request +with +the + +Protocol +Bindings + + +objects +in +which + +of + +the + +Thing +, +then +reject + +promise + +with + + +emit() + +NotSupportedError + + +method +is +provided +to +define +a +local +way +to +trigger +sending +notifications +to +all +subscribed +clients, + +and +terminate +these +steps. + +
  8. +
  9. +If +the +request +fails, +reject + +promise + +with +the +error +received +from +the + +Protocol +Bindings + +and +initialize + +terminate +these +steps. +
  10. +Process + +the +other + +reply +and +update +all + +properties +as +initialized +from + +in + + +model +. + +result + +with +the +values +obtained +in +the +reply. + +
  11. +
  12. +Return + +Resolve + + +thing + +promise + +with + +result + +. +
  13. +
+
+
+
+

+ +6.8 + +The +TD +parsing +algorithm + + + +writeProperty() + + +takes + +method +

+Writes +a +single + +Property +. +Takes + +a +string +argument + + +td +as + +propertyName +, +a +value + +argument + +value + +and +runs + +an +optional + +InteractionOptions + +options + +argument. +It +returns +success +or +failure. +The +method + +MUST + +run + +the +following +steps: +

+
    +
  1. +Parse + +Return +a + +Promise + + +td + +promise + + +according +to + +and +execute + +the +WoT +Thing +Description + +next +steps + +in +order +to +produce +a +JSON +object + +parallel +.
  2. +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  3. +Run +the + +validate +Property +value + + +steps +on + + +json + +value + +. +Update + +If +that +fails, +reject + +promise + +with + +SyntaxError + +and +terminate +these +steps. +
  4. +Make +a +request +to +the +underlying +platform +(via +the + +Protocol +Bindings + +) +to +write + + +thing + +value + + +with + +to + +the +properties +and +values +defined + + +Property + +given +by + +propertyName + +with +optional +URI +templates +given + +in + +json + +options.uriVariables + +. +
  5. +
  6. +If +there +was +an +error +during + +the +parsing, +throw +that + +request +fails, +reject + +promise + +with +the + +error +received +from +the + +Protocol +Bindings + +and +terminate +these +steps. +
  7. +
  8. +Otherwise +return + +resolve + + +json + +promise + +. +
  9. +
+
+
+
+

+3.5 + + +6.9 + +The + + +register() + +writeMultipleProperties() + + + +method + + +

+
+

+Writes +a +multiple + +Property + +values +with +one +request. + +Takes +two +mandatory +arguments: +directory +denoting + +a +Thing +Directory +, +and +thing +denoting + + +properties + +argument +as + +an +ExposedThing +object. +Generate +the +Thing +Description + +object +with +keys +being + +Property + + +names +and +values + +as +td +, +given +the +Properties +, +Action + + +Property + + +s + +values + +and +Event +s +defined +for +this + +an +optional + + +ExposedThing + +InteractionOptions + + + +object. +Then +make +a +request +to +register + + +td + +options + + +to +the +given +WoT +Thing +Directory +. +3.6 + +argument. +It +returns +success +or +failure. + +The +unregister() + +method +Takes +two +mandatory +arguments: + + +MUST + +run +the +following +steps: + +

+
    +
  1. +directory +denoting + +Return + +a +Thing +Directory +, + + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +. +
  2. +
  3. +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +thing + +SecurityError + + +denoting +an + +and +terminate +these +steps. +
  4. +For +each +key + +name + +on + +properties +, +take +its +value +as + +value + +and +run +the + +validate +Property +value + +steps +on + +value +. +If +that +fails +in +for +any + +name +, +reject + +promise + +with + + +ExposedThing + +SyntaxError + + +object. + +and +terminate +these +steps. + +
  5. +Makes + +
  6. +Make + +a +single + +request +to +unregister + +the +thing +from + +underlying +platform +(via + +the +given +WoT +Thing +Directory +. +3.7 +Examples +Example +1 + + +Protocol +Bindings + + +: +Discover +Things +via +directory +<span class= +"hljs-keyword">let discoveryFilter = { + : <span class= +"hljs-string">"directory", + : <span class= +"hljs-string">"http://directory.wotservice.org" +}; +<span class= +"hljs-keyword">let subscription = wot.discover(discoveryFilter).subscribe( + <span class= +"hljs-params">td { + .log(<span class= +"hljs-string">"Found Thing " + td.name); + <span class= +"hljs-comment">// fetch the TD and create a ConsumedThing + thing = wot.consume(td); + }, + error => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished because an error: " + error.message); }, + () => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} +); +setTimeout( <span class= +"hljs-params">() { + subscription.unsubscribe(); + .log(<span class= +"hljs-string">"Discovery timeout"); + }, +5000 +); +Example +2 + +) +to +write +the +each + +Property + + +: +Discover +Things +exposed +by +local +hardware +<span class= +"hljs-keyword">let }).subscribe( + <span class= +"hljs-params">td { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Found local Thing " + td.name); }, + error => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery error: " + error.message); }, + () => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} +); +Example +3 + +provided +in + +properties + +with +optional +URI +templates +given +in + +options.uriVariables +.
  7. +If +this +cannot +be +done +with +a +single +request +with +the + +Protocol +Bindings + + +: +Same +as +above +but + +of +the + +Thing +, +then +reject + +promise + +with +different +Observable +syntax +<span class= +"hljs-keyword">let }).subscribe({ + td => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Found local Thing " + td.name); }, + : <span class= +"hljs-function"><span class= +"hljs-params">err { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery error: " + err.message); }, + : <span class= +"hljs-function"><span class= +"hljs-params">() { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} +}); + + +NotSupportedError + +and +terminate +these +steps. +
  8. +If +the +request +fails, +return +the +error +received +from +the + +Protocol +Bindings + +and +terminate +these +steps. +
  9. +Otherwise +resolve + +promise +.
+
+
+
+

+4. + + +6.10 + +The + + +ConsumedThing + +WotListener + + + +interface + +callback + + +

+

+Represents +an +object + +User +provided +callback + +that +extends +a + +takes + + +ThingFragment + +any + + +with +methods +for +client +interactions +(send +request +for +reading +and +writing +Properties +), +invoke +Action +s, +subscribe + +argument + +and +unsubscribe + +is +used + +for +observing + + +Property + +changes +and +handling + +Event + +s. + +notifications. +Since +subscribing +to +these +are +WoT +interactions, +they +are +not +modelled +with +software +events. + +

+<span class="idlInterface" id= +"idl-def-consumedthing" data-idl="" data-title= +"ConsumedThing">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-consumedthing" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-thingfragment" class="internalDFN" +data-link-type= +"dfn"> {<span class= +"idlAttribute" id="idl-def-consumedthing-id" data-idl="" +data-title="id" data-dfn-for="consumedthing"> + readonly attribute <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="consumedthing" data-lt="consumedthing.id|id" href= +"#dom-consumedthing-id" class="internalDFN" data-link-type= +"dfn"><span class="idlAttribute" +id="idl-def-consumedthing-name" data-idl="" data-title="name" +data-dfn-for="consumedthing"> + readonly attribute <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="consumedthing" data-lt="consumedthing.name|name" +href="#dom-consumedthing-name" class="internalDFN" data-link-type= +"dfn"><span class= +"idlAttribute" id="idl-def-consumedthing-base" data-idl="" +data-title="base" data-dfn-for="consumedthing"> + readonly attribute <a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<a data-no-default="" +data-link-for="consumedthing" data-lt="consumedthing.base|base" +href="#dom-consumedthing-base" class="internalDFN" data-link-type= +"dfn"><span class= +"idlAttribute" id="idl-def-consumedthing-properties" data-idl="" +data-title="properties" data-dfn-for="consumedthing"> + readonly attribute <a data-link-for="" +href="#dom-propertymap" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-no-default="" data-link-for="consumedthing" +data-lt="consumedthing.properties|properties" href= +"#dom-consumedthing-properties" class="internalDFN" data-link-type= +"dfn"><span class= +"idlAttribute" id="idl-def-consumedthing-actions" data-idl="" +data-title="actions" data-dfn-for="consumedthing"> + readonly attribute <a data-link-for="" +href="#dom-actionmap" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-no-default="" data-link-for="consumedthing" +data-lt="consumedthing.actions|actions" href= +"#dom-consumedthing-actions" class="internalDFN" data-link-type= +"dfn"><span class= +"idlAttribute" id="idl-def-consumedthing-events" data-idl="" +data-title="events" data-dfn-for="consumedthing"> + readonly attribute <a data-link-for="" +href="#dom-eventmap" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-no-default="" data-link-for="consumedthing" +data-lt="consumedthing.events|events" href= +"#dom-consumedthing-events" class="internalDFN" data-link-type= +"dfn"><span class="idlMethod" +id="idl-def-consumedthing--name" data-idl="" data-title="" +data-dfn-for="consumedthing"> + // getter for ThingFragment properties + <a href= +"https://heycam.github.io/webidl/#idl-any">any +};<span class="idlInterface" id="idl-def-propertymap" +data-idl="" data-title="PropertyMap"> +[<a href= +"https://heycam.github.io/webidl/#NoInterfaceObject">NoInterfaceObject] +interface <a data-no-default="" +data-link-for="" data-lt="" href="#dom-propertymap" class= +"internalDFN" data-link-type= +"dfn"> {<span class="idlMaplike" +id="idl-def-propertymap-maplike" data-idl="" data-title="iterable" +data-dfn-for="propertymap"> + readonly maplike<<a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString, <a data-link-for="" +href="#dom-thingproperty" class="internalDFN" data-link-type= +"dfn"> +};<span class="idlInterface" id="idl-def-actionmap" +data-idl="" data-title="ActionMap"> +[<a href= +"https://heycam.github.io/webidl/#NoInterfaceObject">NoInterfaceObject] +interface <a data-no-default="" +data-link-for="" data-lt="" href="#dom-actionmap" class= +"internalDFN" data-link-type= +"dfn"> {<span class="idlMaplike" +id="idl-def-actionmap-maplike" data-idl="" data-title="iterable" +data-dfn-for="actionmap"> + readonly maplike<<a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString, <a data-link-for="" +href="#dom-thingaction" class="internalDFN" data-link-type= +"dfn"> +};<span class="idlInterface" id="idl-def-eventmap" data-idl= +"" data-title="EventMap"> +[<a href= +"https://heycam.github.io/webidl/#NoInterfaceObject">NoInterfaceObject] +interface <a data-no-default="" +data-link-for="" data-lt="" href="#dom-eventmap" class= +"internalDFN" data-link-type= +"dfn"> {<span class="idlMaplike" +id="idl-def-eventmap-maplike" data-idl="" data-title="iterable" +data-dfn-for="eventmap"> + readonly maplike<<a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString, <a data-link-for="" +href="#dom-thingevent" class="internalDFN" data-link-type= +"dfn"> +}; +<a href="#dom-consumedthing" class="internalDFN" data-link-type= +"dfn"> includes <a href= +"#dom-observable" class="internalDFN" data-link-type= +"dfn"><span class= +"idlSectionComment"> +// +for +TD +changes + +
+
+

+ +6.11 + +The + + +id + +observeProperty() + + + +attribute +represents +the +unique +identifier +of +the +Thing +instance, +typically +a +URI, +IRI, +or +URN +as +USVString +. +The +name + +method + +attribute +represents +the +name +of +the +Thing + + +as +DOMString +. +The +base + +attribute +represents +the +base +URI +that +is +valid +for +all +defined +local +interaction +resources. + +

+
+

+The +properties +attribute +represents + +Makes + +a +dictionary +of +ThingProperty + +request +for + +Property + + +items. +The + +value +change +notifications. +Takes +a +string +argument + +propertyName +, +a + + +PropertyMap + +WotListener + + +interface +represents +a +maplike +dictionary +where +all +values +are + + +callback +function + +listener + +and +an +optional + + +ThingProperty + +InteractionOptions + + + +objects. + + +options + +argument. +It +returns +success +or +failure. + +The +method + +MUST + +run +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +read() + +SecurityError + + +and +terminate +these +steps. +
  3. +If + +listener + +is +not +a +function, +reject + +promise + +with + + +write() + +"TypeError" + + +methods +make + +and +terminate +these +steps. +
  4. +Make + +a +request +to +access + +the +underlying +platform +(via +the + +Protocol +Bindings + +) +to +observe + + +Properties + +Property + + +on + +identified +by + +propertyName + +with +optional +URI +templates +given +in + +options.uriVariables +.
  5. +If + +the +remote +Thing + +request +fails, +reject + +promise + +with +the +error +received +from +the + +Protocol +Bindings + + +represented +by + +and +terminate +these +steps. +
  6. +Otherwise +resolve + +promise +.
  7. +Whenever +the +underlying +platform +receives +a +notification +for + +this +ConsumedThing + +subscription +with +new + +Property + + +proxy +object. +The + +value + +value +, +run +the +following +sub-steps: +
    • +If +running +the + +validate +Property +value + +steps +on + +value + +fails, +terminate +these +steps. +
    • +Invoke + +listener + +with + +value + +as +parameter. +

+ +6.12 + +The + + +actions + +unobserveProperty() + + + +attribute +represents +a +dictionary +of +ThingAction + +method + + +items. +The +ActionMap + +interface +represents + +

+
+

+Makes + +a +maplike +dictionary +where +all +values +are +ThingAction + +request +for +unsubscribing +from + +Property + + +objects. + +value +change +notifications. +Takes +a +string +argument + +propertyName + +and +returns +success +or +failure. + +The +invoke() + +method +represents +a +request +to +invoke +the +Action +on + + +MUST + +run + +the +remote +Thing +. + +following +steps: + +

+The +events +attribute +represents + +
    +
  1. +Return + +a +dictionary +of +ThingEvent + + +Promise + + +items. +The + + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +EventMap + +SecurityError + + +interface +represents + +and +terminate +these +steps. +
  3. +Make + +a +maplike +dictionary +where +all +values +are +ThingEvent +objects. +Subscribing + +request + +to +the +events +involves +setting +up +an +observation +(subscription) +mechanism +on + +underlying +platform +(via + +the +remote +object. +4.1 +Examples + + +Protocol +Bindings + + +Below +a +ConsumedThing + +) +to +stop +observing +the + +Property + + +interface +example +is +given. +Example +4 + +identified +by + +propertyName +.
  4. +If +the +request +fails, +reject + +promise + +with +the +error +received +from +the + +Protocol +Bindings + + +: +Consume +a +Thing +<span class= +"hljs-keyword">try { + <span class= +"hljs-keyword">let }).subscribe( + <span class= +"hljs-params">td { + <span class= +"hljs-keyword">let thing = wot.consume(td); + .log(<span class= +"hljs-string">"Thing " + thing.name + <span class= +"hljs-string">" has been consumed."); + <span class= +"hljs-keyword">let subscription = thing[<span class= +"hljs-string">"temperature"].subscribe(<span class= +"hljs-function"><span class= +"hljs-keyword">function(<span class= +"hljs-params">value{ + <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Temperature: " + value); + }); + thing.actions[<span class= +"hljs-string">"startMeasurement"].invoke({ <span class= +"hljs-attr">units: <span class= +"hljs-string">"Celsius" }) + .then(<span class= +"hljs-params">() { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Temperature measurement started."); }) + .catch(<span class= +"hljs-params">e { + <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Error starting measurement."); + subscription.unsubscribe(); + }) + }, + error => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery error: " + error.message); }, + () => { <span class= +"hljs-built_in">console.log(<span class= +"hljs-string">"Discovery finished successfully");} + ); +} (error) { + .log(<span class= +"hljs-string">"Error: " + error.message); +}; + +and +terminate +these +steps. +
  5. +Otherwise +resolve + +promise +.
+
+
+
+

+5. + + +6.13 + +The + + +ExposedThing + +invokeAction() + + + +interface + +method + + +

+
+

+The +ExposedThing +interface +is +the +server +API +that +allows +defining + +Makes +a + +request +handlers, +properties, +Actions +, +and +Events + +for +invoking +an + +Action + + +to +a +Thing +. +It +also +implements + +and +return + +the +result. +Takes +a +string +argument + +actionName +, +an +optional +argument + +params + +of +type + + +Observable + +any + + +interface. +An + +and +an +optional + + +ExposedThing + +InteractionOptions + + + +is +created +by + + +options + +argument. +It +returns + +the +produce() +method. +<span class="idlInterface" id= +"idl-def-exposedthing" data-idl="" data-title= +"ExposedThing">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-exposedthing" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-thingfragment" class="internalDFN" +data-link-type= +"dfn"> {<span class= +"idlAttribute" id="idl-def-exposedthing-properties" data-idl="" +data-title="properties" data-dfn-for="exposedthing"> + readonly attribute <a data-link-for="" +href="#dom-propertymap" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-no-default="" data-link-for="exposedthing" +data-lt="exposedthing.properties|properties" href= +"#dom-exposedthing-properties" class="internalDFN" data-link-type= +"dfn"><span class= +"idlAttribute" id="idl-def-exposedthing-actions" data-idl="" +data-title="actions" data-dfn-for="exposedthing"> + readonly attribute <a data-link-for="" +href="#dom-actionmap" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-no-default="" data-link-for="exposedthing" +data-lt="exposedthing.actions|actions" href= +"#dom-exposedthing-actions" class="internalDFN" data-link-type= +"dfn"><span class= +"idlAttribute" id="idl-def-exposedthing-events" data-idl="" +data-title="events" data-dfn-for="exposedthing"> + readonly attribute <a data-link-for="" +href="#dom-exposedevents" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-no-default="" data-link-for="exposedthing" +data-lt="exposedthing.events|events" href= +"#dom-exposedthing-events" class="internalDFN" data-link-type= +"dfn"><span class="idlMethod" +id="idl-def-exposedthing--name" data-idl="" data-title="" +data-dfn-for="exposedthing"> + // getter for ThingFragment properties + <a href= +"https://heycam.github.io/webidl/#idl-any">any<span class="idlMethod" +id="idl-def-exposedthing--name-value" data-idl="" data-title="" +data-dfn-for="exposedthing"> + // setter for ThingFragment properties + (<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<span class="idlMethod" +id="idl-def-exposedthing-expose" data-idl="" data-title="expose" +data-dfn-for="exposedthing"><span class= +"idlSectionComment"> + // methods to expose and destroy the Thing + <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default="" +data-link-for="exposedthing" data-lt= +"exposedthing.expose()|exposedthing.expose|expose()|expose" href= +"#dom-exposedthing-expose" class="internalDFN" data-link-type= +"dfn"><span class= +"idlMethod" id="idl-def-exposedthing-destroy" data-idl="" +data-title="destroy" data-dfn-for="exposedthing"><span class= +"idlMethType"> + <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default="" +data-link-for="exposedthing" data-lt= +"exposedthing.destroy()|exposedthing.destroy|destroy()|destroy" +href="#dom-exposedthing-destroy" class="internalDFN" +data-link-type="dfn"><span class="idlMethod" +id="idl-def-exposedthing-addproperty-name-property-initvalue" +data-idl="" data-title="addProperty" data-dfn-for= +"exposedthing"><span class= +"idlSectionComment"> + // define Properties + <a data-link-for="" href="#dom-exposedthing" class= +"internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.addproperty()|exposedthing.addproperty|addproperty()|addproperty" +href="#dom-exposedthing-addproperty" class="internalDFN" +data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString <a data-link-for="" +href="#dom-propertyfragment" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">property,<span class= +"idlParam"> optional <a href= +"https://heycam.github.io/webidl/#idl-any">any<span class="idlMethod" +id="idl-def-exposedthing-setpropertyreadhandler-name-readhandler" +data-idl="" data-title="setPropertyReadHandler" data-dfn-for= +"exposedthing"> + <a data-link-for="" href="#dom-exposedthing" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.setpropertyreadhandler()|exposedthing.setpropertyreadhandler|setpropertyreadhandler()|setpropertyreadhandler" +href="#dom-exposedthing-setpropertyreadhandler" class="internalDFN" +data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString <a data-link-for="" +href="#dom-propertyreadhandler" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">readHandler<span class= +"idlMethod" id= +"idl-def-exposedthing-setpropertywritehandler-name-writehandler" +data-idl="" data-title="setPropertyWriteHandler" data-dfn-for= +"exposedthing"> + <a data-link-for="" href="#dom-exposedthing" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.setpropertywritehandler()|exposedthing.setpropertywritehandler|setpropertywritehandler()|setpropertywritehandler" +href="#dom-exposedthing-setpropertywritehandler" class= +"internalDFN" data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString <a data-link-for="" +href="#dom-propertywritehandler" class="internalDFN" +data-link-type="dfn"><span class="idlMethod" +id="idl-def-exposedthing-removeproperty-name" data-idl="" +data-title="removeProperty" data-dfn-for= +"exposedthing"> + <a data-link-for="" href="#dom-exposedthing" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.removeproperty()|exposedthing.removeproperty|removeproperty()|removeproperty" +href="#dom-exposedthing-removeproperty" class="internalDFN" +data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<span class="idlMethod" +id="idl-def-exposedthing-addaction-name-init-action" data-idl="" +data-title="addAction" data-dfn-for="exposedthing"><span class= +"idlMethType"> + // define Actions + <a data-link-for="" href="#dom-exposedthing" class= +"internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.addaction()|exposedthing.addaction|addaction()|addaction" +href="#dom-exposedthing-addaction" class="internalDFN" +data-link-type="dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString <a data-link-for="" +href="#dom-actionfragment" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">init,<span class= +"idlParam"> <a data-link-for="" href= +"#dom-actionhandler" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">action<span class="idlMethod" +id="idl-def-exposedthing-removeaction-name" data-idl="" data-title= +"removeAction" data-dfn-for="exposedthing"><span class= +"idlMethType"> + <a data-link-for="" href="#dom-exposedthing" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.removeaction()|exposedthing.removeaction|removeaction()|removeaction" +href="#dom-exposedthing-removeaction" class="internalDFN" +data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString<span class="idlMethod" +id="idl-def-exposedthing-setactionhandler-name-action" data-idl="" +data-title="setActionHandler" data-dfn-for= +"exposedthing"> + <a data-link-for="" href="#dom-exposedthing" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.setactionhandler()|exposedthing.setactionhandler|setactionhandler()|setactionhandler" +href="#dom-exposedthing-setactionhandler" class="internalDFN" +data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString <a data-link-for="" +href="#dom-actionhandler" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">action<span class="idlMethod" +id="idl-def-exposedthing-addevent-name-event" data-idl="" +data-title="addEvent" data-dfn-for="exposedthing"><span class= +"idlMethType"> + // define Events + <a data-link-for="" href="#dom-exposedthing" class= +"internalDFN" data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.addevent()|exposedthing.addevent|addevent()|addevent" +href="#dom-exposedthing-addevent" class="internalDFN" +data-link-type="dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString <a data-link-for="" +href="#dom-eventfragment" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">event<span class="idlMethod" +id="idl-def-exposedthing-removeevent-name" data-idl="" data-title= +"removeEvent" data-dfn-for="exposedthing"><span class= +"idlMethType"> + <a data-link-for="" href="#dom-exposedthing" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="exposedthing" +data-lt= +"exposedthing.removeevent()|exposedthing.removeevent|removeevent()|removeevent" +href="#dom-exposedthing-removeevent" class="internalDFN" +data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString +};<span class="idlInterface" id="idl-def-exposedevents" +data-idl="" data-title="ExposedEvents"> +[<a href= +"https://heycam.github.io/webidl/#NoInterfaceObject">NoInterfaceObject] +interface <a data-no-default="" +data-link-for="" data-lt="" href="#dom-exposedevents" class= +"internalDFN" data-link-type= +"dfn"> {<span class= +"idlMaplike" id="idl-def-exposedevents-maplike" data-idl="" +data-title="iterable" data-dfn-for="exposedevents"> + maplike<<a href= +"https://heycam.github.io/webidl/#idl-DOMString">DOMString, <a data-link-for="" +href="#dom-exposedevent" class="internalDFN" data-link-type= +"dfn"> +};<span class="idlCallback" id="idl-def-propertyreadhandler" +data-idl="" data-title="PropertyReadHandler"> +callback <a data-no-default="" +data-link-for="" data-lt="" href="#dom-propertyreadhandler" class= +"internalDFN" data-link-type= +"dfn"> =<span class= +"idlCallbackType"> <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<span class="idlCallback" +id="idl-def-propertywritehandler" data-idl="" data-title= +"PropertyWriteHandler"> +callback <a data-no-default="" +data-link-for="" data-lt="" href="#dom-propertywritehandler" class= +"internalDFN" data-link-type= +"dfn"> =<span class= +"idlCallbackType"> <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<span class="idlCallback" +id="idl-def-actionhandler" data-idl="" data-title="ActionHandler"> +callback <a data-no-default="" +data-link-for="" data-lt="" href="#dom-actionhandler" class= +"internalDFN" data-link-type= +"dfn"> =<span class= +"idlCallbackType"> <a href= +"https://heycam.github.io/webidl/#idl-promise"> +Promise +< +<a +href="https://heycam.github.io/webidl/#idl-any"> +any +> +( +any + +result +of +the + +Action + + +parameters +); + +or +an +error. + +The +properties +attribute +represents + +method + +MUST + +run +the +following +steps: +

  1. +Return + +a +dictionary +of +ThingProperty + + +Promise + + +items + + +promise + +and +execute +the +next +steps + +in +which + +parallel +.
  2. +If +invoking +this +method +is +not +allowed +for + +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + + +read() + +SecurityError + + +and +write() +methods +define +local +methods +that +access + +terminate +these +steps. +
  3. +Make +a +request +to + +the +physical +representations +of + +underlying +platform +(via + +the +Properties +. +The +actions +attribute +represents +a +dictionary +of +ThingAction + + +Protocol +Bindings + + +items +in +which +the +invoke() +method +represents +a +local +method + +) + +to +invoke +the + +Action +. +The +events +attribute +represents +a +dictionary +of +ExposedEvent + + +items +that +add + +identified +by + +actionName + +with +parameters +provided +in + +params + +with +optional +URI +templates +given +in + +options.uriVariables +.
  4. +If + +the +emit() +method +to + +request +fails +locally +or +returns +an +error +over + +the +ThingEvent + +network, +reject + +promise + +with +the +error +received +from +the + +Protocol +Bindings + + +definition. +The +ExposedEvents +interface +represents +a +maplike +dictionary +where +all +values +are + +and +terminate +these +steps. +
  5. +Otherwise +let + +value + +be +the +result +returned +in +the +reply +and +run +the + +validate +Property +value + +steps +on +it. +If +that +fails, +reject + +promise + +with + + +ExposedEvent + +SyntaxError + + +and +terminate +these +steps. +
  6. +Reject + +promise + +with + +value +.

+objects. +5.1 + + +6.14 + +The + + +expose() + +subscribeEvent() + + + +method + + +

+
+

+Start +serving +external +requests + +Makes +a +request + +for +the +Thing +, +so +that +WoT +Interactions + +subscribing +to + +Event + + +using +Properties +, +Action + +notifications. +Takes +a +string +argument + +eventName +, +a + +WotListener + + +s + +callback +function + +listener + +and +Event +s +will +be +possible. +The + +an +optional + + +expose() + +InteractionOptions + + + + +options + +argument. +It +returns +success +or +failure. +The + +method + +MUST + +run +the +following +steps: +

+
    +
  1. +Return +a + +Promise + + +promise + +and +execute +the +next +steps + +in +parallel +. +
  2. +
  3. +If +invoking +expose() + +this +method + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  4. +
  5. +If + +listener + +is +not +a +function, +reject + +promise + +with + +"TypeError" + +and +terminate +these +steps. +
  6. +Make +a +request +to +the +underlying +platform +to +attach +protocol +handlers +and +start +serving +external +requests +for +WoT +Interactions +(read, +write +and +observe +Properties +, +invoke +Action + +(via +the + +Protocol +Bindings + + +s +and +manage + +) +to +subscribe +to +an + + +Event + +subscriptions), +based +on +the +Protocol +Bindings +. + +identified +by + +eventName + +with +optional +URI +templates +given +in + +options.uriVariables +. +
  7. +
  8. +If +there +was +an +error +during + +the +request, + +request +fails, + +reject + +promise + +with +an +Error +object +error +with +error.message +set +to + +the +error +code +seen +by + +received +from + +the + +Protocol +Bindings + +and +terminate +these +steps. +
  9. +
  10. +Otherwise +resolve + +promise +with + +. +
  11. +
  12. +Whenever +the +underlying +platform +receives +a +notification +for +this + +Event + +subscription, +implementations + +SHOULD + +invoke + + +td +and +terminate +these +steps. + +listener +, +giving +the +data +provided +with +the + +Event + +as +parameter. + +
  13. +
+
+
+
+

+5.2 + + +6.15 + +The + + +destroy() + +unsubscribeEvent() + + + +method + + +

+
+

+Stop +serving +external +requests + +Makes +a +request + +for +the +Thing + +unsubscribing +from + +Event + + +notifications. +Takes +a +string +argument + +eventName + +and +destroy +the +object. +Note +that +eventual +unregistering +should +be +done +before +invoking +this +method. + +returns +success +or +failure. + +The +destroy() + +method + +MUST + +run +the +following +steps: +

+
    +
  1. +Return +a + +Promise + + +promise + +and +execute +the +next +steps + +in +parallel +. +
  2. +
  3. +If +invoking +destroy() + +this +method + +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  4. +
  5. +Make +a +request +to +the +underlying +platform +to +stop +serving +external +requests +for +WoT +Interactions +, +based +on + +(via + +the + +Protocol +Bindings +. + + +) +to +unsubscribe +from +the + +Event + +identified +by + +eventName +. +
  6. +
  7. +If +there +was +an +error +during + +the +request, + +request +fails, + +reject + +promise + +with +an +Error +object +error +with +error.message +set +to + +the +error +code +seen +by + +received +from + +the + +Protocol +Bindings + +and +terminate +these +steps. +
  8. +
  9. +Otherwise +resolve + +promise +with +td +and +terminate +these +steps. + +. +
  10. +
+
+
+5.3 +The +addProperty() + +
+

+method + + +6.16 + +ConsumedThing +Examples + + +

+

+Adds + +The +next +example +illustrates +how +to +fetch + +a +Property + + +TD + + +with +name +defined +by +the +name +argument, +the +data +schema +provided + +by +the +property +argument +of +type + +URL, +create +a + + +PropertyFragment + +ConsumedThing + + +, +and +optionally +an +initial +value +provided +in +the +argument +initValue +whose +type +should +match +the +one +defined +in +the +type + +read +metadata +(title), +read + +property +according + +value, +subscribe + +to +the +value-matching +algorithm +. +If +initValue +is +not +provided, +it +SHOULD +be +initialized +as +undefined +. +Implementations +SHOULD +update +the +Thing +Description +. +Throws +on +error. +Returns +a +reference + +property +change, +subscribe + +to +the +same +object +for +supporting +chaining. + +a +WoT +event, +unsubscribe. + +

+
+
+5.4 + + +Example + +2 +: +Thing +Client +API +example +

+"hljs-keyword">try {
+  let res = 
+"hljs-keyword">await fetch("https://tds.mythings.org/sensor11");
+  let td = res.json();  let thing = 
+"hljs-keyword">new ConsumedThing(td);
+  console.log(
+"hljs-string">"Thing " + thing.getThingDescription().title + " consumed.");
+} catch(e) {
+  console.log(
+"hljs-string">"TD fetch error: " + e.message); },
+};
+try {  
+"hljs-comment">// subscribe to property change for “temperature”
+  
+"hljs-keyword">await thing.observeProperty("temperature", value => {
+    console.log(
+"hljs-string">"Temperature changed to: " + value);
+  });
+  
+"hljs-comment">// subscribe to the “ready” event defined in the TD
+  
+"hljs-keyword">await thing.subscribeEvent("ready", eventData => {
+    console.log(
+"hljs-string">"Ready; index: " + eventData);
+    
+"hljs-comment">// run the “startMeasurement” action defined by TD
+    
+"hljs-keyword">await thing.invokeAction("startMeasurement", { units: "Celsius" });
+    console.log(
+"hljs-string">"Measurement started.");
+  });
+} catch(e) {
+  console.log(
+"hljs-string">"Error starting measurement.");
+}
+setTimeout( () => {
+  
+"hljs-built_in">console.log(“Temperature: “ + await thing.readProperty(“temperature”));
+  
+"hljs-keyword">await thing.unsubscribe(“ready”);
+  console.log(
+"hljs-string">"Unsubscribed from the ‘ready’ event.");
+},
+
+10000
+
+
+);
+

+7. + +The + + +removeProperty() + +ExposedThing + + + +method + +interface + + +

+

+Removes +the +Property +specified +by +the + +The + + +name + +ExposedThing + + +argument +and +updates + + +interface +is + +the +Thing +Description +. +Throws +on +error. +Returns +a +reference + +server +API + +to +operate + +the +same +object +for +supporting +chaining. + + +Thing + +that +allows +defining +request +handlers, + +Property +, +Action +, +and + +Event + +interactions. + +

+5.5 + +
"idl-def-exposedthing" data-title="ExposedThing">[SecureContext, Exposed=(Window,Worker)]
+interface ExposedThing: ConsumedThing {
+  
+"internalDFN" data-link-type=
+"idl">ExposedThing setPropertyReadHandler(DOMString name,
+          
+class="internalDFN" data-link-type=
+"idl">PropertyReadHandler readHandler);
+  
+"internalDFN" data-link-type=
+"idl">ExposedThing setPropertyWriteHandler(DOMString name,
+          
+"#dom-propertywritehandler" class="internalDFN" data-link-type=
+"idl">PropertyWriteHandler writeHandler);
+  
+"internalDFN" data-link-type=
+"idl">ExposedThing setActionHandler(DOMString name, ActionHandler action);
+  
+href=
+"https://heycam.github.io/webidl/#idl-void">void emitEvent(DOMString name, any data);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> expose();
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> destroy();
+};
+callback PropertyReadHandler = Promise<any>(
+        optional InteractionOptions options = null);
+callback PropertyWriteHandler = Promise<void>(any value,
+        optional InteractionOptions options = null);
+callback ActionHandler = Promise<any>(any params,
+        optional InteractionOptions 
+options
+
+
+The
+
+=
+null);
+

+7.1 + +Constructing + + +addAction() + +ExposedThing + + +method + + + +

+

+Adds +to +the + +The + + +actions + +ExposedThing + + +property +of + +interface +extends + +ConsumedThing +. +It +is +constructed +from + +a +Thing + +full +or +partial + +ThingDescription + + +object + +object. +

+Note +

+Note +that + +an +Action + +existing + +ThingDescription + + +with +name +defined + +object +can +be +optionally +modified +(for +instance + +by +the + +adding +or +removing +elements +on +its + + +name + +properties +, +actions + + +argument, +defines +input + +and +output +data +format +by +the + + +init + +events + + +argument +of +type + +internal +properties) +and +the +resulting +object +can +used +for +constructing +an + + +ActionFragment + +ExposedThing + + + +object. +This +is +the +current +way +of +adding +and +removing + +Property + +, + +Action + +and +adds +the +function +provided +in +the +action +argument + + +Event + +definitions, + +as +a +handler, +then +updates + +illustrated +in + +the +Thing +Description + + +examples + +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. + +

+The +provided +action +callback +function +will +implement +invoking +an +Action +and +SHOULD +be +called +by +implementations +when +a +request +for + +
+
+
+ +Note +

+Before + +invoking + +expose() +, +the +Action + + + +ExposedThing + + +is +received +from +the +underlying +platform. +The +callback +will +receive +a + +object +does +not +serve +any +requests. +This +allows +first +constructing + + +parameters + +ExposedThing + + +dictionary +argument +according +to +the +definition +in +the +init.input +argument + + +and +will +return +a +value +of +type +defined +by +the +init.output +argument +according +to +the +value-matching +algorithm +. + +then +initialize +its + +Properties + +and +service +handlers +before +starting +serving +requests. + +

+
+
+

+There +SHOULD +be +exactly +one +handler +for +any +given +Action +. +If +no +handler +is +initialized +for +any +given +Action +, +implementations +SHOULD +throw +a +TypeError +. + +To +construct +an + +5.6 +The + + +removeAction() + +ExposedThing + + +method + + +Removes + +with + +the +Action + + + +ThingDescription + + +specified +by + + +td +, +run +the +following +steps: +

  1. +If +invoking +this +method +is +not +allowed +for + +the +current +scripting +context +for +security +reasons, +throw + + +name + +SecurityError + + +argument + +and +updates + +terminate +these +steps. +
  2. +Run + +the +Thing +Description +. +Throws +on +error. +Returns + + +expand + +a +reference +to + +TD + +steps +on + +td +. +If +that +fails, +re-throw + +the +same +object +for +supporting +chaining. + +error +and +terminate +these +steps. +
  3. +Let + +thing + +be +a +new + +5.7 +The + + +addEvent() + +ExposedThing + + +method + + +Adds + +object. +
  4. +Let +| + +td + +| +be + +an +event +with +name +defined +by +the + +internal +slot +of + + +name + +thing + + +argument + +and +qualifiers +and +initialization +value +provided +by +the + +let + + +event + +td + + +argument +of +type + +be +its +value. +
  5. +Return + +thing +.

+7.2 + +Methods +inherited +from + + +EventFragment + +ConsumedThing + + + +to +the +Thing +object +and +updates +the +Thing +Description +. +Throws +on +error. +Returns +a +reference +to +the +same +object +for +supporting +chaining. + +5.8 +The +removeEvent() +method + + + +

+

+Removes +the +event +specified +by + +The + +readProperty() +, +readMultipleProperties() +, +readAllProperties() +, +writeProperty() +, +writeMultipleProperties() +, +writeAllProperties() + +methods +have + +the +same +algorithmic +steps +as +described +in + + +name + +ConsumedThing + + +argument +and +updates + +, +with + +the +Thing +Description +. +Returns + +difference +that +making + +a +reference + +request + +to +the +same +object +for +supporting +chaining. + +underlying +platform + +MAY + +be +implemented +with +local +methods +or +libraries +and +don't +necessarily +need +to +involve +network +operations. + +

+5.9 + +

+The +implementation +of + + +PropertyReadHandler + +ConsumedThing + + +callback + + +interface +in +an + +ExposedThing + + +provide +the + +default + +methods +to +interact +with +the + + +ExposedThing +.

+

+A +function +that +is +called +when + +After +constructing + +an +external +request +for +reading + + + +ExposedThing +, +a +Property + +script +can +initialize +its + +Properties + + +is +received. +It +should +return +a +Promise + +and +resolves +it +with + +can +set +up + +the +value +of + +optional +read, +write +and +action +request +handlers +(the +default +ones +are +provided +by + +the +Property +matching + +implementation). +The +script +provided +handlers + +MAY + +use +the +default +handlers, +thereby +extending +the +default +behavior, +but +they +can +also +bypass +them, +overriding +the +default +behavior. +Finally, + +the +script +would +call + + +name + +expose() + + +argument +to + + +on + +the + + +setPropertyReadHandler + +ExposedThing + + +function, +or +rejects +with +an +error +if +the +property +is +not +found +or +the +value +cannot +be +retrieved. + + +in +order +to +start +serving +external +requests. + +

+
+
+

+5.10 + + +7.3 + +The + + +PropertyWriteHandler + +PropertyReadHandler + + + +callback + + +

+

+A +function +that +is +called +when +an +external +request +for +writing + +reading + +a + +Property + +is +received. +It +is +given +the +requested +new +value +as +argument + +received + +and +should +return + +defines +what +to +do +with +such +requests. +It +returns + +a + +Promise +which +is +resolved + + +and +resolves +it + +when +the +value +of +the + +Property + +that +matches + +matching + +the + +name + +argument +has +been +updated +with +value +, + +is +obtained, + +or +rejects +with +an +error +if +the +property +is +not +found +or +the +value +cannot +be +updated. +Editor's +note +Note +that +this +function +is +invoked +by +implementations +before +the +property +is +updated +and +it +actually +defines +what +to +do +when +a +write +request +is +received. +The +code +in +this +callback +function +can +invoke +the +read() +method +to +find +out +the +old +value +of +the +property, +if +needed. +Therefore +the +old +value +is +not +provided +to +this +function. +5.11 +The +ActionHandler +callback +A +function +called +with +a +parameters +dictionary +argument +assembled +by +the +WoT +runtime +based +on +the +Thing +Description +and +the +external +client +request. +It +returns +a +Promise +that +rejects +with +an +error +or +resolves +if +the +action +is +successful +or +ongoing +(may +also +resolve +with +a +control +object +such +as +an +Observable +for +actions +that +need +progress +notifications +or +that +can +be +canceled). + +retrieved. + +

+
+
+

+5.12 + + +7.4 + +The + + +setPropertyReadHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +readHandler + +as +argument +of +type + + +PropertyReadHandler + +. +Sets +the +service + +handler +function + +for +reading +the +specified + +Property + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same + + +this + +object +for +supporting +chaining. +

+

+The + +readHandler + +callback +function +will + +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 +SHOULD + + +MUST + + +be +at +most +one +handler +for +any +given + +Property +and + +, +so + +newly +added +handlers + +MUST + +replace +the +old + +previous + +handlers. +If +no +handler +is +initialized +for +any +given + +Property +, +implementations + +SHOULD + +implement +a +default +property +read +handler. + +handler +based +on +the + +Thing +Description +. +

+
+
+

+ +7.5 + +Handling + +Property + +read +requests +

+

+When +an +external + +a +network + +request +for +reading + +Property + + +propertyName + +is +received, + +received +by + +the +runtime +SHOULD +execute + +implementation, +run + +the +following +steps: +

+
    +
  1. +Return +a +Promise +promise +and +execute +the +next +steps +in +parallel +. + +If +a + +Property + +with + +propertyName + +does +not +exist, +reject +promise +with +a + +return + + +ReferenceError + +in +the +reply +and +terminate +these +steps. +
  2. +If +there +is +a +user +provided +read +handler +registered +with + +setPropertyReadHandler() +, +invoke +that +wih + +propertyName +, +return +the +value +with +the +reply + +and +terminate +these +steps. +
  3. +
  4. +Otherwise, +if +no + +there +is +a +default + +read +handler +has +been +defined +for + +provided +by +the +implementation, +invoke +it +with + + +propertyName +, +resolve +promise +with + +return + +the +value +of + +with +the +reply +and +terminate +these +steps. +
  5. +if +there +is +no +default +handler +defined +by +the +implementation, +return + +NotSupportedError + +with + +the +reply +and +terminate +these +steps. +

+7.6 + +Handling + +Property + +observe +requests +

+When +a +network +request +for +observing +a + + +Property + +named + + +propertyName + +provided + +is +received + +by +the +runtime +implementation + +implementation, +run +the +following +steps: +

  1. +If +a + +Property + +with + +propertyName + +does +not +exist, +return +an +error +in +the +reply +(as +defined +in +the + +Thing +Description + +) + +and +terminate +these +steps. +
  2. +
  3. +Otherwise, +invoke + +Save + +the +read +handler +associated +with +propertyName +. +If +it +rejects, +then +reject +promise + +request +sender +information +to +the + +Property + +'s + +internal +observer +list + +in +order +to +be +able +to +notify +about + +Property + +value +changes. +

+7.7 + +The + +PropertyWriteHandler + +callback +

+A +function +that +is +called +when +an +external +request +for +writing +a + +Property + +is +received +and +defines +what +to +do + +with +such +requests. +It +expects + +the +same +error, + +requested +new + +value + +as +argument + +and +resolve +promise + +returns +a + +Promise + +which +is +resolved +when +the +value +of +the + +Property + + +that +matches +the + +name + +argument +has +been +updated + +with + +value +, +or +rejects +with +an +error +if + +the +same +value. + +property +is +not +found +or +the +value +cannot +be +updated. +

+Editor's +note +

+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. +

+
+
+

+5.13 + + +7.8 + +The + + +setPropertyWriteHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +writeHandler + +as +argument +of +type + + +PropertyWriteHandler + +. +Sets +the +service + +handler +function + +for +writing +the +specified + +Property + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same + + +this + +object +for +supporting +chaining. +

+

+There +SHOULD + + +MUST + + +be +at +most +one +write +handler +for +any +given + +Property +and + +, +so + +newly +added +handlers + +MUST + +replace +the +old + +previous + +handlers. +If +no +write +handler +is +initialized +for +any +given + +Property +, +implementations + +SHOULD + +implement +default +property +update +and +notifying +observers +on +change. + +change, +based +on +the + +Thing +Description +. +

+
+
+

+ +7.9 + +Handling + +Property + +write +requests +

+

+When +an +external + +a +network + +request +for +writing +a + +Property + + +propertyName + +with +a +new +value + +value + +is +received, +the +runtime + +implementations + + +SHOULD + +execute + +run + +the +following +steps: + + +update +property +steps +, +given + +propertyName +, +value + +and + +mode + +set +to + +"single" +: +

+
    +
  1. +Return +a +Promise +promise +and +execute +the +next +steps +in +parallel +. + +If +a + +Property + +with + +propertyName + +does +not +exist, +reject +promise +with +a + +return + + +ReferenceError + +in +the +reply + +and +terminate +these +steps. +
  2. +
  3. +Otherwise, + +If +there +is +a +user +provided +write +handler +registered +with + +setPropertyWriteHandler() +, +or + +if +no + +there +is +a +default + +write +handler, +
    1. +Invoke +the + +handler +has +been +defined +for + +with + + +propertyName +, + +. +If +it +fails, +return + +the +runtime +implementation +SHOULD +update + +error +in + +the +reply +and +terminate +these +steps. +
    2. +Otherwise, +if + +mode + +is + +"single" +, +reply +to +the +request +with +the +new +value, +following +to +the + +Protocol +Bindings +.
    3. +For +each +item +stored +in +the + +internal +observer +list + +of +the + +Property + +value + +with + +value + +propertyName + +, +resolve +promise + +send +an +observe +reply +with +the +new +value +attached. +
  4. +If +there +is +no +handler +to +handle +the +request, +return + +NotSupportedError + +in +the +reply + +and +terminate +these +steps. +
  5. +Otherwise, +invoke + +
+
+
+

+When +a +network +request +for +writing +multiple + +Properties + +given +in +an +object + +propertyNames + +is +received, +run + +the +write +handler +associated + +following +steps: +

  1. +For +each +property + +with +key + + +propertyName + +name + + +providing + +and +value + + +value + +as +argument. +If +it +rejects, +then +reject + +defined +in + + +promise +with + +propertyNames +, +run + +the +same +error, +and +resolve +promise + + +update +property +steps + + +with + +name +, +value + +and + +mode + +set +to + +"multiple" +.
  2. +Reply +to + +the +same +value. + +request +(by +sending +a +single +or +multiple +replies) +according +to +the + +Protocol +Bindings + +defined +for +the + +Property +. +
  3. +
+
+
+
+

+ +7.10 + +The + +ActionHandler + +callback +

+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 +with +a + +params + +dictionary +argument. +It +returns +a + +Promise + +that +rejects +with +an +error +or +resolves +if +the +action +is +successful. +

+
+
+

+5.14 + + +7.11 + +The + + +setActionHandler() + + +method + + +

+

+Takes + +name + +as +string +argument +and + +action + +as +argument +of +type + + +ActionHandler + +. +Sets +the +handler +function +for +the +specified + +Action + +matched +by + +name +. +Throws +on +error. +Returns +a +reference +to +the +same + + +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 +SHOULD + + +MUST + + +be +at +most +one +handler +for +any +given + +Action +and + +, +so + +newly +added +handlers + +MUST + +replace +the +old + +previous + +handlers. +

+
+
+

+ +7.12 + +Handling + +Action + +requests +

+

+When +an +external + +a +network + +request +for +invoking +the + +Action + +identified +by + +name + +is +received, +the +runtime + +SHOULD + +execute +the +following +steps: +

+
    +
  1. +Return +a +Promise +promise +and +execute +the +next +steps +in +parallel +. + +If +an + +Action + +identified +by + +name + +does +not +exist, +reject +promise +with +a + +return + + +ReferenceError + +in +the +reply + +and +terminate +these +steps. +
  2. +
  3. +Otherwise, +if +no + +If +there +is +a +user +provided + +action +handler +has +been +defined +for + +registered +with + +setActionHandler() +, +invoke +that +wih + + +name +, +reject +promise + +return +the +resulting +value +with +the +reply +and +terminate +these +steps. +
  4. +Otherwise +return + +NotSupportedError + + +with +the +reply +and +terminate +these +steps. +

+7.13 + +The + +emitEvent() + +method +

+Takes + +name + +as +string +argument +denoting +an + +Event + +name, +and + +a + +data + +argument +of + + +ReferenceError + +any + +type. +The +method + +MUST + +run +the +following +steps: +

  1. +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +throw + +SecurityError + + +and +terminate +these +steps. +
  2. +
  3. +Otherwise, +invoke +the +Action + +If +an + +Event + + +handler +associated + +with +the +name + + +name +. +If +it +rejects +with + + +is +not +found +in + + +error + +this.getThingDescription().events + +, +throw + +NotFoundError + +and +terminate +these +steps. +
  4. +Make +a +request +to +the +underlying +platform +to +send +an + +Event + +with + +data + +attached +as +property, +using +the + +Protocol +Bindings +, +then +terminate +these +steps. +

+7.14 + +The + +expose() + +method +

+Start +serving +external +requests +for +the + +Thing +, +so +that + +WoT +Interactions + +using + +Properties +, +Action + +s +and + +Event + +s +will +be +possible. +The +method + +MUST + +run +the +following +steps: +

  1. +Return +a + +Promise + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, + +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  3. +Run + +the +same + + +expand +a +TD + +steps +on +the +internal +slot +| + + +error +, +otherwise +if +it +resolves + +td + +|. +
  4. +Run +the + +validate +a +TD + +on +| + +td + +|. +If +that +fails, +reject + +promise + +with + +"TypeError" + +and +terminate +these +steps. +
  5. +For +each + +Property + +definition +in + + +this.instance.properties + +initialize +an +| + +internal +observer +list + +| +internal +slot +in +order +to +store +observe +request +data +needed +to +notify +the +observers +on + +value +, + +changes. +
  6. +Set +up +the + +WoT +Interactions + +based +on +introspecting + +td + +as +explained +in +[ + +WOT-TD + +] +and +[ + +WOT-PROTOCOL-BINDINGS + +]. +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 +. +The +details +are +private +to +the +implementations +and +out +of +scope +of +this +specification. +
  7. +If +there +was +an +error +during +the +request, +reject + +promise + +with +an + +Error + +object + +error + +with + +error.message + +set +to +the +error +code +seen +by +the + +Protocol +Bindings + +and +terminate +these +steps. +
  8. +Otherwise + +resolve + +promise + +and +terminate +these +steps. +

+7.15 + +The + +destroy() + +method +

+Stop +serving +external +requests +for +the + +Thing + +and +destroy +the +object. +Note +that +eventual +unregistering +should +be +done +before +invoking +this +method. +The +method + +MUST + +run +the +following +steps: +

  1. +Return +a + +Promise + + + +promise + +and +execute +the +next +steps + +in +parallel +.
  2. +If +invoking +this +method +is +not +allowed +for +the +current +scripting +context +for +security +reasons, +reject + +promise + +with + +SecurityError + +and +terminate +these +steps. +
  3. +Make +a +request +to +the +underlying +platform +to +stop +serving +external +requests +for + +WoT +Interactions +, +based +on +the + +Protocol +Bindings +.
  4. +If +there +was +an +error +during +the +request, +reject + +promise + +with +an + +Error + +object + +error + +with + +error.message + +set +to + +the +same + +error +code +seen +by +the + +Protocol +Bindings + +and +terminate +these +steps. +
  5. +Otherwise +resolve + + +value +. + +promise + +and +terminate +these +steps. + +
  6. +
+
+
+
+

+5.15 + + +7.16 + +ExposedThing + +Examples + + +

+

+Below +some + +The +next +example +illustrates +how +to +create +an + + + + +ExposedThing + + + +interface +examples +are +given. + +based +on +a +partial + +TD + +object +constructed +beforehands. + +

+
+
+ +Example +5 + + +3 + + +: +Create +a +new +exposed +Thing + +ExposedThing + +with +a +simple +property + +Property + + +
+ { + +
"hljs javascript">try {
+
+  "hljs-keyword">var temperatureValueDefinition = {
+
+"hljs-keyword">let temperaturePropertyDefinition = {
+
+    type: "number",
+    minimum: -50,
+    maximum: 10000
+  };
+  <span class=
+"hljs-keyword">var temperaturePropertyDefinition = temperatureValueDefinition;
+  
+  temperaturePropertyDefinition.forms = [ ... ];
+   thing = WoT.produce({
+    : <span class=
+"hljs-string">"tempSensor",
+
+  let tdFragment = {
+    properties: {
+      temperature: temperaturePropertyDefinition
+    },
+    actions: {
+      reset: {
+        description: "Reset the temperature sensor",
+        input: {
+          temperature: temperatureValueDefinition
+        },
+        output: null,
+        forms: []
+      },
+    },
+    events: {
+      onchange: temperatureValueDefinition
+    },
+    : []
+  });
+   thing.expose();
+   wot.register(<span class=
+"hljs-string">"https://mydirectory.org", thing);
+  
+  setInterval(  () => {
+     mock = <span class=
+"hljs-built_in">Math.random()*<span class=
+"hljs-number">100;
+     old = <span class=
+"hljs-keyword">await thing[<span class=
+"hljs-string">"temperature"].read();
+     (old < mock) {
+       thing[<span class=
+"hljs-string">"temperature"].write(mock);
+      thing.emitEvent(<span class=
+"hljs-string">"onchange", mock);
+
+    }
+  }, );
+
+  };
+  let thing1 = 
+"hljs-keyword">await WOT.produce(tdFragment);
+  // initialize Properties  
+"hljs-keyword">await thing1.writeProperty("temperature", 0);
+  // add service handlers
+  thing1.setPropertyReadHandler("temperature", () => {
+     
+"hljs-keyword">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. +

+
+ +Example +6 + + +4 + + +: +Create +a +new +exposed +Thing +with + +Add +an + +object +property + +Property + + +
+ { + statusValueDefinition = { + +
"hljs javascript">try {
+  
+"hljs-comment">// create a deep copy of thing1's TD
+  let instance = 
+"hljs-built_in">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
+        }
+      }
+  };
+  <span class=
+"hljs-keyword">var statusPropertyDefinition = statusValueDefinition;
+  
+  statusPropertyDefinition[<span class=
+"hljs-string">"forms"] = [];
+   thing = WoT.produce({
+    : <span class=
+"hljs-string">"mySensor",
+    : {
+      : {
+        : <span class=
+
+  instance["name"] = "mySensor";
+  instance.properties["brightness"] = {
+    type: "number",
+        : <span class=
+
+    minimum: 0.0,
+        : <span class=
+
+    maximum: 100.0,
+        : <span class=
+
+    required: true,
+      },
+      <span class=
+"hljs-attr">status: statusPropertyDefinition
+    },
+    : {
+      : {
+        : <span class=
+
+  };
+  instance.properties["status"] = statusValueDefinition;
+  instance.actions["getStatus"] = {
+    description: "Get status object",
+        : <span class=
+
+    input: null,
+        : {
+          <span class=
+"hljs-attr">status : statusValueDefinition;
+        },
+        : []
+      },
+    },
+    : {
+
+    output: {
+      "hljs-attr">onstatuschange: statusValueDefinition;
+
+"hljs-attr">status : statusValueDefinition;
+
+    },
+    : []
+  });
+  thing.expose().then(<span class=
+"hljs-params">() {
+      thing.register();
+
+    forms: [...]
+  };
+  instance.events["onstatuschange"] = statusValueDefinition;
+  instance.forms = [...];  // update
+  var thing2 = 
+"hljs-keyword">new ExposedThing(instance);
+  // 
+"hljs-doctag">TODO: add service handlers
+  await thing2.expose();
+  });
+} catch (err) {
+   console.log("Error creating ExposedThing: " + err);
+}
+Example
+7
+:
+Create
+a
+new
+exposed
+Thing
+from
+a
+Thing
+Description
+        <span class=
+"hljs-keyword">let thingDescription = <span class=
+"hljs-string">'{ \
+  "name": "mySensor", \
+  "@context": [ "http://www.w3.org/ns/td",\
+     "https://w3c.github.io/wot/w3c-wot-common-context.jsonld" ],\
+  "@type": [ "Thing", "Sensor" ], \
+  "geo:location": "testspace", \
+  "properties": { \
+    "prop1": { \
+      "type": "number",\
+      "@type": [ "Property", "Temperature" ], \
+      "saref:TemperatureUnit": "degree_Celsius" \
+  } } }';
+ {
+  <span class=
+"hljs-comment">// note that produce() fails if thingDescription contains error
+  <span class=
+"hljs-keyword">let thing = WoT.produce(thingDescription);
+  <span class=
+"hljs-comment">// Interactions were added from TD
+  <span class=
+"hljs-comment">// WoT adds generic handler for reading any property
+  <span class=
+"hljs-comment">// define a specific handler for one property
+   name = <span class=
+"hljs-string">"examplePropertyName";
+  thing.setPropertyReadHandler(name, () => {
+    .log(<span class=
+"hljs-string">"Handling read request for " + name);
+     <span class=
+"hljs-keyword">new <span class=
+"hljs-built_in">Promise(<span class=
+"hljs-function">(<span class=
+"hljs-params">resolve, reject {
+        <span class=
+"hljs-keyword">let examplePropertyValue = <span class=
+"hljs-number">5;
+        resolve(examplePropertyValue);
+      },
+      e => {
+        .log(<span class=
+"hljs-string">"Error");
+      });
+  });
+  thing.expose();
+} (err) {
+   .log(<span class=
+"hljs-string">"Error creating ExposedThing: " + err);
+}
+Example
+8
+:
+Create
+a
+new
+exposed
+Thing
+from
+a
+TD
+URI
+
+
+        <span class=
+"hljs-comment">// fetch an external TD, e.g., to set up a proxy for that Thing
+WoT.fetch(<span class=
+"hljs-string">"http://myservice.org/mySensor/description" {
+  <span class=
+"hljs-comment">// WoT.produce() ignores instance-specific metadata (security, form)
+   thing = WoT.produce(td);
+  <span class=
+"hljs-comment">// Interactions were added from TD
+  
+  
+});
+
+
+
+
+
+6. +Data +types +and +structures +The +[ +WOT-TD + +
+

+] +specification +defines +the +WoT +information +model +, +i.e. +the +data +types +and +data +structures +used +in +WoT +Interactions +. +In +this +API +these +definitions +translate +to +dictionary +objects +that +are +extended +with +methods +by +the +interfaces +defined +in +this +specification. +In +order +to +avoid +duplication +of +definitions, +references +to +these +data +types +and +structures +is +defined +in +this +section, +but +for +their +full +description +please +refer +to +the +Thing +Description +specification +. +6.1 + + +8. + +The + + +DataSchema + +ThingDiscovery + + + +dictionary +and +its +subclasses + +interface + + +

+

+Value +types +basically +represent +types + +Discovery +is +a +distributed +application + +that +may +be +used +in +JSON +object +definitions +and +are +used +in +ThingFragment +to +define +Properties +, +Event +s +and +Action +parameters. +Value +types +are +represented +as +dictionary +objects +whose +properties + +requires +provisioning + +and +possible +sub-classes +are +defined +in + +support +from +participating +network +nodes +(clients, +servers, +directory +services). +This +API +models + +the +DataSchema +section + +client +side + +of +[ +WOT-TD +]. + +typical +discovery +schemes +supported +by +various +IoT +deployments. + +

+

+One +property +of +all + +The + + +DataSchema + +ThingDiscovery + + + +dictionary +is +the +type +property +whose +value + +object + +is +from + +constructed +given + +a +set +of +enumerated +strings +defined +in + +filter +and +provides + +the +DataSchema +section +of +[ +WOT-TD +] + +properties + +and +is +referred +as +DataType +in +this +specification. +Based +on +type +, + +methods +controlling + +the +following +sub-classes +of +DataSchema +are +defined +in +[ +WOT-TD +]: +BooleanSchema +, +NumberSchema +, +IntegerSchema +, +StringSchema +, +ObjectSchema + +discovery +process. +


+"idl-def-thingdiscovery" data-title="ThingDiscovery">[SecureContext, Exposed=(Window,Worker)]
+interface ThingDiscovery {
+  
+"dom-thingdiscovery-constructor" data-idl="constructor" data-title=
+"constructor" data-dfn-for="ThingDiscovery" data-lt=
+"ThingDiscovery.constructor()|ThingDiscovery.constructor|constructor()|constructor">constructor(optional ThingFilter filter = null);
+  readonly attribute ThingFilter? filter;
+  readonly attribute boolean active;
+  readonly attribute boolean done;
+  readonly attribute Error? error;
+  
+href=
+"https://heycam.github.io/webidl/#idl-void">void start();
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<ThingDescription> next();
+  
+href=
+"https://heycam.github.io/webidl/#idl-void">void stop();
+};
+
+,
+ArraySchema
+
+
+
+
+. +6.2 + + +Editor's +note + + +
+

+The + + +SecurityScheme + +ThingDiscovery + + +dictionary +and +its +subclasses + + +Security +metadata +is +represented +as +dictionary +objects +whose +properties + +interface +has +a + +next() + +method + +and +sub-classes +are +defined +in +the +SecurityScheme +section +of +[ +WOT-TD + +a + +done + +property, +but +it +is +not +an + +Iterable +. +Look +into + +Issue +177 + + +]. + +for +rationale. + +

+
+

+One +property +of + +The + +discovery +results + +internal +slot +is +an +internal +queue +for +temporarily +storing + +the +found + + +SecurityScheme + +ThingDescription + + + +dictionary +is + +objects +until +they +are +consumed +by + +the +scheme +property +whose +value +is +from +a +set +of +enumerated +strings +defined +in + +application +using + +the +SecurityScheme + + +next() + + +section + +method. +Implementations + +MAY + +optimize +the +size + +of +[ +WOT-TD +]. +Based + +this +queue +based + +on +type +, +multiple +subclasses + +e.g. +the +available +resources +and +the +frequency + +of +SecurityScheme + +invoking +the + +next() + + +are +defined. + +method. + +

+6.3 + +

+The + + +Link + +filter + + + +dictionary +Represents +a +Web +Link +with +properties +defined +in + +property +represents + +the +Link +section + +discovery +filter + +of +[ +WOT-TD +]. +6.4 +The + +type + + +Form + +ThingFilter + + +dictionary + + +Represents +metadata +describing +service +details, +with +properties +defined +in + +specified +for + +the +Form +section +of +[ +WOT-TD +]. + +discovery. + +

+6.5 +The +InteractionFragment +dictionary + +

+Represents +the +common +properties +of +WoT +Interactions +, +one +of +Property +, +Action +or +Event +, +as +defined +in +the +InteractionPattern +section +of +[ +WOT-TD +]. +Its +subclasses +are +referred +as + +The + + +PropertyFragment + +active + + +, + + +property +is + + +ActionFragment + +true + + +when +the +discovery +is +actively +ongoing +on +protocol +level +(i.e. +new + +TD + + +s +may +still +arrive) + +and + +EventFragment + +false + + +. + +otherwise. + +

+6.6 + +

+The + + +PropertyFragment + +done + + + +dictionary +Represents +the +Property +interaction +data +that +initializes +a + +property +is + + +ThingProperty + +true + + +object. +Its +properties +are +defined +in + +if + +the +Property + +discovery +has +been +completed +with +no +more +results +to +report + +and +InteractionPattern +sections +of +[ +WOT-TD + + +discovery +results + + +]. + +is +also +empty. + +

+6.7 + +

+The + + +ActionFragment + +error + + + +dictionary +Represents + +property +represents + +the +Action +interaction +data + +last +error + +that +initializes +a +ThingAction +object. +Its +properties +are +defined +in + +occured +during + +the +Action +and +InteractionPattern +sections +of +[ +WOT-TD +]. + +discovery +process. +Typically +used +for +critical +errors +that +stop +discovery. + +

+6.8 +The + +
+

+ +8.1 + +Constructing + + +EventFragment + +ThingDiscovery + + +dictionary + + + +

+
+

+Represents +the +Event +interaction +data +that +initializes +a + +To +create + + +ThingEvent + +ThingDiscovery + + + +object. +Its +properties +are +defined +in + +with + +the +Event +section +of +[ +WOT-TD +]. +6.9 +The +ThingFragment +dictionary +The + + + +ThingFragment + +ThingFilter + + + +dictionary +is +defined +as +Thing +in +[ +WOT-TD +]. +It +is +a +dictionary +that +contains +properties +representing +semantic +metadata +and +interactions +( +Properties +, +Action +s +and +Event +s). +It + + +filter +, +run +the +following +steps: +

  1. +If + +filter + +is +used +for +initializing + +not + +an +internal +representation +of +a +Thing +Description +and +its +properties +may +be +used +in + +object +or + + +ThingFilter + +null +, +throw + +"TypeError" + + +. +6.10 +The + +and +terminate +these +steps. +
  2. +Let + +discovery + +be +a +new + + +ThingDescription + +ThingDiscovery + + +type + + +Serialized +representation +of + +object. +
  3. +Set + +the +Thing +Description + + +filter + + +(a +JSON-LD + +property +to + +filter +.
  4. +Set + +active + + +document). +Note +In +this +version +of +the +API, +Thing +Description + +and + +done + + +s +are +represented +as +an +opaque + +to + + +USVString +that +can +be +transmitted +between +devices. +7. +Interfaces +for +WoT +Interactions + +false +. +Set + +error + + +to + +null +.
  5. +Return + +discovery +.
+

+The +data +types +and +structures +imported +from +[ +WOT-TD + + +start() + + +] +are +extended +by +this +specification +in +order +to +provide +the +interfaces +for +WoT +Interactions +. +Every +Thing + +method +sets + +active + + +describes +its +metadata +as +defined +in + +to + + +ThingFragment +, +and +basic +interactions +defined +as +Properties +, +Action + +true +. +The + +stop() + + +s +and +Event + +method +sets + +active + + +s. +The +following +interfaces +are +used +for +representing +these +interactions. +7.1 +The + +to + +false +, +but + +done + +may +be +still + + +Interaction + +false + + +interface +The + +if +there +are + + +Interaction + +ThingDescription + + + +interface +is +an +abstract +class +to +represent +Thing +interactions: +Properties +, +Actions + +objects +in +the + +discovery +results + + +and +Events + +not +yet +consumed +with + +next() + +. +

+

+The +InteractionFragment +dictionary +holds +the +common +properties + +During +successive +calls + +of +PropertyFragment +, +ActionFragment +and +EventFragment +dictionaries +used +for +initializing +ThingProperty + + +next() + +, +ThingAction + + +active + + +and + +may +be + + +ThingEvent + +true + + +objects +in +a + +or + + +ThingFragment + +false +, +but + +done + + +dictionary +used +for +creating +an + +is +set +to + + +ExposedThing + +false + + +by + +next() + + +object. +<span class="idlInterface" id= +"idl-def-interaction" data-idl="" data-title= +"Interaction">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-interaction" class="internalDFN" data-link-type= +"dfn"> {<span class= +"idlAttribute" id="idl-def-interaction-forms" data-idl="" +data-title="forms" data-dfn-for="interaction"> + readonly attribute (<a data-link-for="" +href="#dom-form" class="internalDFN" data-link-type= +"dfn"> or <a href= +"https://heycam.github.io/webidl/#idl-frozen-array">FrozenArray<<a data-link-for="" +href="#dom-form" class="internalDFN" data-link-type= +"dfn"> <span class= +"idlAttrName"><a data-no-default="" data-link-for="interaction" +data-lt="interaction.forms|forms" href="#dom-interaction-forms" +class="internalDFN" data-link-type= +"dfn"> +}; +<a href="#dom-interaction" class="internalDFN" data-link-type= +"dfn"> includes <a href= +"#dfn-interactionfragment" class="internalDFN" data-link-type= +"dfn"> +InteractionFragment + +only +when +both + +active + + +; +The + +is + + +forms + +false + + +read-only +property +represents +the +protocol +bindings +initialization +data + +and + +discovery +results + +is +initialized +by +the +WoT +Runtime +. + +empty. + +

+
+
+

+7.2 + + +8.2 + +The + + +ThingProperty + +DiscoveryMethod + + + +interface + +enumeration + + +

+The + +
"idl-def-discoverymethod" data-title=
+"DiscoveryMethod">typedef DOMString 
+
+
+ThingProperty
+
+DiscoveryMethod
+
+
+
+interface
+is
+used
+in
+ConsumedThing
+
+;
+
+and
+
+
+

+Represents +the +discovery +type +to +be +used: +

+8.3 + +The + + +ThingFragment + +ThingFilter + + + +dictionary +used +for +creating +an +ExposedThing + + + +object. +It +MUST +implement +one +of +the +DataSchema + +

+

+Represents +an +object +containing +the +constraints +for +discovering + +Thing + + +dictionaries. + +s +as +key-value +pairs. + +

+<span class="idlInterface" id= +"idl-def-thingproperty" data-idl="" data-title= +"ThingProperty">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingproperty" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-interaction" class="internalDFN" +data-link-type= +"dfn"> {<span class="idlMethod" +id="idl-def-thingproperty--name" data-idl="" data-title="" +data-dfn-for="thingproperty"> + // getter for PropertyFragment properties + <a href= +"https://heycam.github.io/webidl/#idl-any">any<span class="idlMethod" +id="idl-def-thingproperty-read" data-idl="" data-title="read" +data-dfn-for="thingproperty"><span class= +"idlSectionComment"> + // get and set interface for the Property + <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default="" +data-link-for="thingproperty" data-lt= +"thingproperty.read()|thingproperty.read|read()|read" href= +"#dom-thingproperty-read" class="internalDFN" data-link-type= +"dfn"><span class="idlMethod" +id="idl-def-thingproperty-write-value" data-idl="" data-title= +"write" data-dfn-for="thingproperty"> + <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default="" +data-link-for="thingproperty" data-lt= +"thingproperty.write()|thingproperty.write|write()|write" href= +"#dom-thingproperty-write" class="internalDFN" data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-any">any +}; +<a href="#dom-thingproperty" class="internalDFN" data-link-type= +"dfn"> includes <a href= +"#dom-propertyfragment" class="internalDFN" data-link-type= +"dfn"><span class= +"idlIncludes"> +<a href="#dom-thingproperty" class="internalDFN" data-link-type= +"dfn"> includes <a href= +"#dom-observable" class="internalDFN" data-link-type= +"dfn"> +Observable +; + +
"idl-def-thingfilter" data-title="ThingFilter">dictionary ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  
+href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString? url;
+  
+href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString? query;
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-object">object? fragment;
+};
+
+
+
+

+The +ThingProperty +interface +contains +all +the +properties +defined +on + + + +PropertyFragment + +method + + +as +read-only +properties. +The +type + + +read-only + +property +represents +the +discovery + +type +definition +for +the +Property +as +a +DataSchema +dictionary +object. +The +writable +read-only +property +tells +whether +the +Property +value +can + +that +should + +be +updated. +If +it +is +false +, +then +the +set(value) +method +SHOULD +always +reject. +The +observable +read-only +property +tells +whether +the +Property +supports +subscribing +to +value +change +notifications. +If +it +is +false +, +then + +used +in + +the +subscribe() +method +SHOULD +always +fail. + +discovery +process. + +The +constant +read-only +property +- + +possible +values +are + +defined +in +DataSchema +- +tells +whether +the +Property +value +is +a +constant. +If +true +, + +by + +the + +set() +and +subscribe() +methods +SHOULD +always +fail. +The + +required +read-only +property +- +defined +in + + + +DataSchema + +DiscoveryMethod + + + +- +tells +whether +the +Property +should +be +always +present +on +the + +ExposedThing + + +object. + +enumeration +that + +MAY + +be +extended +by +string +values +defined +by +solutions +(with +no +guarantee +of +interoperability). + +

+

+The + + +read() + +url + + + +method +will +fetch + +property +represents +additional +information +for + +the +value + +discovery +method, +such +as +the +URL + +of +the +Property +. +Returns +a +Promise +that +resolves +with + +target +entity +serving + +the +value, +or +rejects +with +an +error. +The +write() +method +will +attempt +to +set + +discovery +request, +for +instance + +the +value + +URL + +of +the +Property + +a + +Thing +Directory + + +specified +in +the + +(if + + +value + +method + + +argument +whose +type +SHOULD +match +the +one +specified +by +the + +is + + +type + +"directory" + + +property. +Returns + +) +or +that +of + +a +Promise + + +Thing + + +that +resolves +on +success, +or +rejects +on +an +error. + +(otherwise). + +

+7.3 +The +ThingAction +interface +<span class="idlInterface" id= +"idl-def-thingaction" data-idl="" data-title= +"ThingAction">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingaction" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-interaction" class="internalDFN" +data-link-type= +"dfn"> {<span class="idlMethod" +id="idl-def-thingaction-invoke-inputvalue" data-idl="" data-title= +"invoke" data-dfn-for="thingaction"> + <a href= +"https://heycam.github.io/webidl/#idl-promise">Promise<a data-no-default="" +data-link-for="thingaction" data-lt= +"thingaction.invoke()|thingaction.invoke|invoke()|invoke" href= +"#dom-thingaction-invoke" class="internalDFN" data-link-type= +"dfn">(<span class= +"idlParam">optional <a href= +"https://heycam.github.io/webidl/#idl-any">any +}; +<a href="#dom-thingaction" class="internalDFN" data-link-type= +"dfn"> includes <a href= +"#dom-actionfragment" class="internalDFN" data-link-type= +"dfn"> +ActionFragment +; + +

+The + + +invoke() + +query + + + +method +when +invoked, +starts +the +Action +interaction +with +the +input +value +provided + +property +represents +a +query +string +accepted + +by +the +inputValue +argument. +If +inputValue +is +null +, +the +action +does +not +take +any +arguments +and +rejects +if +any +arguments +are +provided. +If +the +value +is +undefined +, +the +action +will +ignore +any +arguments +provided. +Otherwise +the +type +of +inputValue +SHOULD +match +the +DataSchema +definition + +implementation, +for +instance +a +SPARQL +or +JSON +query. +Support +may +be +implemented +locally + +in +the +input +property. +Returns +a +Promise + + +WoT +Runtime + + +that +will +reject +with +an +error + +or +will +resolve +with + +remotely +as + +a +value +of +type +defined +by +the +output +property. + +service +in +a + +Thing +Directory +. +

+7.4 + +

+The + + +ThingEvent + +fragment + + + +interface +<span class="idlInterface" id= +"idl-def-thingevent" data-idl="" data-title= +"ThingEvent">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-thingevent" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-interaction" class="internalDFN" +data-link-type="dfn"> { +}; +<a href="#dom-thingevent" class="internalDFN" data-link-type= +"dfn"> includes <a href= +"#dom-eventfragment" class="internalDFN" data-link-type= +"dfn"><span class= +"idlIncludes"> +<a href="#dom-thingevent" class="internalDFN" data-link-type= +"dfn"> includes <a href= +"#dom-thingproperty" class="internalDFN" data-link-type= +"dfn"> +ThingProperty +; +Since +ThingEvent +implements +Observable +through +the +ThingProperty +interface, +event +subscription +is +done +by +invoking +the +subscribe() +method +on +the +event +object +that +returns + +property +represents + +a +cancelable +Subscription +. + +template +object +used +for +matching +property +by +property +against +discovered + +Thing + +s. + +

+
+
+

+7.5 + + +8.4 + +The + + +ExposedEvent + +start() + + + +interface + +method + + +

+
+<span class="idlInterface" id= +"idl-def-exposedevent" data-idl="" data-title= +"ExposedEvent">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-exposedevent" class="internalDFN" data-link-type= +"dfn"> : <span class= +"idlSuperclass"><a href="#dom-thingevent" class="internalDFN" +data-link-type= +"dfn"> {<span class="idlMethod" +id="idl-def-exposedevent-emit-payload" data-idl="" data-title= +"emit" data-dfn-for="exposedevent"> + void<a data-no-default="" +data-link-for="exposedevent" data-lt= +"exposedevent.emit()|exposedevent.emit|emit()|emit" href= +"#dom-exposedevent-emit" class="internalDFN" data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://heycam.github.io/webidl/#idl-any">any +}; +7.5.1 + +

+Starts +the +discovery +process. + +The +emit() + +method +Emits +an +event +that +carries +data +specified +by + + +MUST + +run + +the +payload +argument. + +following +steps: + +

+7.6 +The +value-matching +algorithm +The +value-matching +algorithm + +
    +
  1. +If +invoking +this +method + +is +applied +to +a + +not +allowed +for +the +current +scripting +context +for +security +reasons, +set + + +value + +this.error + + +input +in +relation + +to +a +valueType +property +of +type + + +DataSchema + +SecurityError + + +, +for +instance + +and +terminate +these +steps. +
  2. +If +discovery +is +not +supported +by + +the +implementation, +set + +this.error + +to + + +value + +NotSupportedError + + +and +type +properties +of + +terminate +these +steps. +
  3. +If + +this.filter + +is +defined, +
    • +Let + +filter + +denote + +this.filter +.
    • +If + +filter.query + +is +defined, +pass +it +as +an +opaque +string +to +the +underlying +implementation +to +be +matched +against +discovered +items. +The +underlying +implementation +is +responsible +to +parse +it +e.g. +as + +a +PropertyFragment +object, + +SPARQL + +or +JSON +query +and +match +it +against + +the + +Thing +Description + +s +found +during +the +discovery +process. +If +queries +are +not +supported, +set + + +inputValue + +this.error + + +parameter + +to +the + + +invoke() + +NotSupportedError + + +method +of +a + +and +terminate +these +steps. +
  4. +Create +the + +discovery +results + +internal +slot +for +storing +discovered + + +ThingAction + +ThingDescription + + + +object +in +relation + +objects. +
  5. +Request +the +underlying +platform + +to +start + +the +same +object. +It +executes + +discovery +process, +with + +the +following +steps: + +parameters: +
      +
    • +If + +valueType.type + +filter.method + + +is +not +defined, + +defined + +or +does +not +fully +match +a +string +enumerated +in +DataType +, +return +false +. +Otherwise, +if +valueType.type +is +"null" +: +if + +the + +value +is + +null +, +return +true + +"any" + +, +otherwise +return +false +. + +use +the +widest +discovery +method +supported +by +the +underlying +platform. + +
    • +
    • +Otherwise, +if +valueType.type +is +"boolean" +: + +Otherwise + +if + +value + +filter.method + + +is +either +true +or + + +false +, +then +return +true + +"local" + +, +otherwise +return +false +. + +use +the +local + +Thing +Directory + +for +discovery. +Usually +that +defines + +Thing + +s +deployed +in +the +same +device, +or +connected +to +the +device +in +slave +mode +(e.g. +sensors +connected +via +Bluetooth +or +a +serial +connection). + +
    • +
    • +Otherwise, +if +valueType.type +is +"integer" +: + +Otherwise + +if + +value + +filter.method + + +is +not +an +integer +type +defined +by +the +underlying +platform +(such +as +long +or + + +long +long +), +then +return +false + +"directory" + +, +otherwise +execute + +use + +the +following +sub-steps: +If +valueType.minimum +is +defined +and +value +is +not +greater +or +equal +than +that +value, +return + +remote + +Thing +Directory + +specified +in + + +false + +filter.url + +. +
    • +
    • +If +valueType.maximum +is +defined +and + +Otherwise +if + + +value + +filter.method + + +is +not +less +or +equal +than +that +value, +return +false +. + + +"multicast" +, +use +all +the +multicast +discovery +protocols +supported +by +the +underlying +platform. +
    +
  6. +
  7. +Return + +When +the +underlying +platform +has +started +the +discovery +process, +set +the + +active + +property +to + + +true +. +
  8. +
  9. +Otherwise, +if +valueType.type +is +"number" +, +if + +Whenever +a +new + +Thing +Description + + +value + +td + + +is +not +an +integer +or +floating +point +type +defined + +discovered + +by +the +underlying +platform +(such +as +long +or +long +long +or +double +), +then +return +false +, +otherwise +otherwise +execute + +platform, +run + +the +following +sub-steps: +
      +
    1. +If +valueType.minimum +is +defined +and + + +Fetch + + +value + +td + + +is +not +greater +or +equal +than +that +value, +return + +as +a +JSON +object + + +false + +json + +. +If +that +fails, +set + + +valueType.maximum + +this.error + + +is +defined +and + +to + +SyntaxError +, +discard + + +value + +td + + +is +not +less +or +equal +than +that +value, +return +false +. +Return +true +. + +and +continue +the +discovery +process. + +
    2. +
    3. +Otherwise, +if + +If + + +valueType.type + +filter.query + + +is +"string" +: + +defined, +check + +if + +value + +json + + +is +not + +a +string +type +defined +by + +match +for + +the +underlying +platform, +then +return + +query. +The +matching +algorithm +is +encapsulated +by +implementations. +If +that +returns + + +false +, +otherwise +return +true +. +In +this +case +the +algorithm +expects +a +third +parameter + +discard + + +valueType.enum + +td + + +and +runs + +continue + +the +following +sub-steps: + +discovery +process. +
    4. +
    5. +If + +valueType.enum + +filter.fragment + + +is +an +array +of +strings, +then + +defined, +for +each +property +defined +in +it, +check + +if +that +property +exists +in + + +value + +json.properties + + +fully +matches +one +of + +and +has + +the +strings +defined + +same +value. +If +this +is + +false + +in +the +array, +return + +any +checks, +discard + + +true +. + +td + +and +continue +the +discovery +process. + +
    6. +
    7. +Otherwise, +return + +Otherwise +add + + +false +. + +td + +to +the + +discovery +results +. +
    8. +
    9. +Otherwise, + +At +this +point +implementations + +MAY + +control +the +flow +of +the +discovery +process +(depending +on +memory +constraints, +for +instance +temporarily +stop +discovery + +if +valueType.type + +the +queue + +is +"array" +, +execute + +getting +too +large, +or +resume +discovery +when + +the +following +sub-steps: +If +value + +queue + +is +not +an +array, +return +false +. + +emptied +sufficiently). +
    +
  10. +
  11. +If + +Whenever +an +error +occurs +during +the +discovery +process, +
    1. +Set + + +valueType.minItems + +this.error + + +is +defined, +and + +to +a +new + +Error + +object + + +value +does +not +contain +at +least + +error +. +Set + + +valueType.minItems + +error.name + + +elements, +return +false +. + +to + +'DiscoveryError' +. +
    2. +
    3. +If +there +was +an +error +code +or +message +provided +by +the + +Protocol +Bindings +, +set + + +valueType.maxItems + +error.message + + +is +defined, +and + +to +that + +value +contains +more +than +valueType.maxItems +elements, +return +false +. + +as +string. + +
    4. +
    5. +Otherwise, +if +valueType.items + +If +the +error + +is +irrecoverable +and +discovery +has +been +stopped +by +the +underlying +platform, +set + + +undefined +, +return + +this.active + +to + + +false +. +
    6. +Otherwise, +if +valueType.items +is +null +, +return +true +(i.e. +any +type +is +accepted +as +array +element, +including +heterogenous +arrays). + +
    +
  12. +
  13. +Otherwise, +for +each +element +of +the +array +value +run + +When + +the +value-matching +algorithm +against + +underlying +platform +reports + +the +discovery +process +has +completed, +set + + +valueType.items + +this.active + + +object. +If +any +of +these +runs +returns +false +, +then +return + +to + + +false +. +
  14. +Otherwise, +return +true +. + +
+Otherwise, +if +type +is + +
+
+
+

+ +8.5 + +The + + +"object" +, +execute + +next() + +method +

+Provides +the +next +discovered + +ThingDescription + +object. +The +method + +MUST + +run + +the +following +sub-steps: + +steps: +

+
    +
  1. +If + +Return +a + +Promise + + +value + +promise + + +is +not +an +Object +, +return +false +. + +and +execute +the +next +steps + +in +parallel +. +
  2. +
  3. +If + +valueType.properties + +this.active + + +is +not +defined, +return + + +false +. + +true +, +wait +until +the + +discovery +results + +internal +slot +is +not +empty. + +
  4. +
  5. +If + +discovery +results + +is +empty +and + + +valueType.properties + +this.active + + +is + +null + +false + +, +return + +set + +this.done + +to + + +true + +(i.e. +accept +any +object +value). + +and +reject + +promise +. +
  6. +
  7. +For +each +string +in +the +valueType.required +array, +if +it +does +not +match +a +property +name +in + +Remove + +the +value.properties + +first + +ThingDescription + +object +or +in +the + + +value + +td + + +object, +then +return +false +. + +from + +discovery +results +. +
  8. +
  9. +For +each +property +with +name +propName +and +value + +Resolve + + +propDataSchema + +promise + + +found +in +valueType.properties +, +run +the +following +sub-steps: +If +the +result +of +applying +the +value-matching +algorithm +on +the +value + +with + + +value[propName] + +td + + +and +propDataSchema +is +false +, +then +return +false +. +Return +true +. + +terminate +these +steps. + +
  10. +
+
+
+
+

+8. +Observables + + +8.6 + +The + + +stop() + + +method + +This +section +is +non-normative. + + +

+
+

+Observables +are +proposed +to + +Stops +or +suppresses +the +discovery +process. +It +might +not + +be +included +in +ECMAScript + +supported +by +all +discovery +methods + +and +are +used +for +handling +pushed +data +associated +with +various +possible +sources, +for +instance +events, +timers, +streams, +etc. +A +minimal +required +implementation +is +described +here. +Editor's +note +This +section +is +informal + +endpoints, +however, +any +further +discovery +results +or +errors +will +be +discarded + +and +contains +rather +laconic +information +for +implementations +on +what +to +support +for +interoperability. +<span class="idlInterface" id= +"idl-def-observable" data-idl="" data-title= +"Observable">interface <span class= +"idlInterfaceID"><a data-no-default="" data-link-for="" data-lt="" +href="#dom-observable" class="internalDFN" data-link-type= +"dfn"> {<span class="idlMethod" +id="idl-def-observable-subscribe-handler-errorhandler-oncomplete" +data-idl="" data-title="subscribe" data-dfn-for= +"observable"> + <a data-link-for="" href="#dom-subscription" class="internalDFN" +data-link-type= +"dfn"> <span class= +"idlMethName"><a data-no-default="" data-link-for="observable" +data-lt="subscribe|subscribe()" href="#dom-observable-subscribe" +class="internalDFN" data-link-type= +"dfn">(<span class= +"idlParam"><a href= +"https://www.w3.org/TR/html52/single-page.html#typedefdef-eventhandler">EventHandler + optional<span class= +"idlParamType"> <a data-link-for="" href="#dom-errorhandler" class= +"internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">errorHandler + optional<span class= +"idlParamType"> <a data-link-for="" href="#dom-oncomplete" class= +"internalDFN" data-link-type= +"dfn"> <span class= +"idlParamName">onComplete +};<span class="idlInterface" id="idl-def-subscription" +data-idl="" data-title="Subscription"> +interface <a data-no-default="" +data-link-for="" data-lt="" href="#dom-subscription" class= +"internalDFN" data-link-type= +"dfn"> {<span class="idlMethod" +id="idl-def-subscription-unsubscribe" data-idl="" data-title= +"unsubscribe" data-dfn-for="subscription"><span class= +"idlMethType"> + void<a data-no-default="" +data-link-for="subscription" data-lt="unsubscribe|unsubscribe()" +href="#dom-subscription-unsubscribe" class="internalDFN" +data-link-type= +"dfn"><span class= +"idlAttribute" id="idl-def-subscription-closed" data-idl="" +data-title="closed" data-dfn-for="subscription"> + readonly attribute <a href= +"https://heycam.github.io/webidl/#idl-boolean">boolean<a data-no-default="" +data-link-for="subscription" data-lt="subscription.closed|closed" +href="#dom-subscription-closed" class="internalDFN" data-link-type= +"dfn"> +};<span class="idlCallback" id="idl-def-eventhandler" +data-idl="" data-title="EventHandler"> +callback <a data-no-default="" +data-link-for="" data-lt="" href="#dom-eventhandler" class= +"internalDFN" data-link-type= +"dfn"> =<span class= +"idlCallbackType"> void<span class= +"idlParamType"><a href= +"https://heycam.github.io/webidl/#idl-any">any<span class="idlCallback" +id="idl-def-errorhandler" data-idl="" data-title="ErrorHandler"> +callback <a data-no-default="" +data-link-for="" data-lt="" href="#dom-errorhandler" class= +"internalDFN" data-link-type= +"dfn"> =<span class= +"idlCallbackType"> void<span class= +"idlParamType"><a href= +"https://heycam.github.io/webidl/#idl-Error">Error<span class="idlCallback" +id="idl-def-oncomplete" data-idl="" data-title="OnComplete"> +callback <a data-no-default="" +data-link-for="" data-lt="" href="#dom-oncomplete" class= +"internalDFN" data-link-type= +"dfn"> =<span class= +"idlCallbackType"> +void +(); + +the +discovery +is +marked +inactive. + +The +method + +MUST + +run +the + +following +callbacks +can +be +provided +when +subscribing +to +an +Observable +: + +steps: + +

+
    +
  1. +The +EventHandler +callback +takes +the +next +sample +for + +Request + +the +data +in + +underlying +platform +to +stop + +the +value +argument. +The +ErrorHandler +callback +takes + +discovery +process. +If +this +returns + +an +error +in +the +value +argument. +It + +error, +or +if +it + +is +called + +not +possible, +for +instance + +when +an +error +occurred +in +producing +the +data + +discovery +is +based +on +open +ended +multicast +requests, + +the +client +should +know +about. + +implementation + +SHOULD + +discard +subsequent +discovered +items. + +
  2. +
  3. +The + +Set + + +OnComplete + +this.active + + +callback +is +called +when +the +data +source +has +finished +sending +values. +8.1 +The + +to + + +Subscription + +false +.

+interface + + +8.7 + +Discovery +Examples + + +

+

+Contains +the + +The +following +example +finds + + +closed + +ThingDescription + + +property + + +objects + +of +type +boolean + + +Thing + +s + +that +tells +if +the +subscription + +are +exposed +by +local +hardware, +regardless +how +many +instances +of + +WoT +Runtime + +it + +is +closed +or +active. +Also, +contains +the +unsubscribe +() +method + +running. +Note + +that +cancels + +the +subscription, +i.e. +makes +a +request +to + +discovery +can +end +(become +inactive) +before + +the +underlying +platform + +internal + +discovery +results + +queue +is +emptied, +so +we +need + +to +stop +receiving +data +from +the +source, +and +sets +the + +continue +reading + + +closed + +ThingDescription + + +property +to +false +. + + +objects +until +done. +This +is +typical +with +local +and +directory +type +discoveries. + +

+
+
+8.2 + + +Example + +5 +: +Discover +Things +exposed +by +local +hardware + + +The + +Observable + +
+
"hljs-keyword">let discovery = new ThingDiscovery({ method: "local" });
+do {  let td = 
+"hljs-keyword">await discovery.next();
+  console.log(
+"hljs-string">"Found Thing Description for " + td.title);
+  let thing = 
+"hljs-keyword">new ConsumedThing(td);
+  console.log(
+"hljs-string">"Thing name: " + thing.getThingDescription().title);
+} 
+while
+
+(!discovery.done);
+
+
+interface
+
+
+
+

+The +next +example +finds + + +Observable + +ThingDescription + + + +interface +enabled +subscribing +to +pushed +data +notifications +by +the + +objects +of + +Thing + +s +listed +in +a + +Thing +Directory + +service. +We +set +a +timeout +for +safety. +

+subscribe + + +Example + +6 +: +Discover +Things +via +directory +

+"hljs-keyword">let discoveryFilter = {
+  method: 
+"hljs-string">"directory",
+  url: 
+"hljs-string">"http://directory.wotservice.org"
+};
+let discovery = 
+"hljs-keyword">new ThingDiscovery(discoveryFilter);
+setTimeout( () => {
+    discovery.stop();
+    console.log(
+"hljs-string">"Discovery stopped after timeout.");
+  },
+  3000);do {  let td = 
+"hljs-keyword">await discovery.next();
+  console.log(
+"hljs-string">"Found Thing Description for " + td.title);
+  let thing = 
+"hljs-keyword">new ConsumedThing(td);
+  console.log(
+"hljs-string">"Thing name: " + thing.getThingDescription().title);
+} while (!discovery.done);
+if (discovery.error) {  console.log(
+"hljs-string">"Discovery stopped because of an error: " + error.message);
+}
+
+
+()
+method:
+Initialize
+the
+data
+handler
+callback
+with
+the
+first
+function
+argument.
+If
+the
+
+
+
+

+The + +next +argument +is +provided +and + +example + +is +a +function, +initialize +the +error +handling +callback +with +that +function, +or +throw + +for +an +open-ended +multicast +discovery, +which +likely +won't +complete +soon +(depending + +on +error. +If + +the +third +argument +is +provided +and + +underlying +protocol), +so +stopping +it +with +a +timeout + +is +a +function, +initialize +the +completion +handler +with +that +function, +or +throw +on +error. +After +callback +initializations, +the +implementation +should +request +the +underlying +platform +to +provide +data, +error +and +completion +notifications +for +the +supported +data +source. + +good +idea. +It +will +likely +deliver +results +one +by +one. +

+Example + +7 +: +Discover +Things +in +a +network +

+"hljs-keyword">let discovery = new ThingDiscovery({ method: "multicast" });
+setTimeout( () => {
+    discovery.stop();
+    console.log(
+"hljs-string">"Stopped open-ended discovery");
+  },
+  10000);do {  let td = 
+"hljs-keyword">await discovery.next();
+  let thing = 
+"hljs-keyword">new ConsumedThing(td);
+  console.log(
+"hljs-string">"Thing name: " + thing.getThingDescription().title);
+} 
+while
+
+(!discovery.done);
+
+
+
+
+

+ +9. + +Security +and +Privacy + + +

+

+In +general +the +security +measures +taken +to +protect +a +WoT +system +will +depend +on +the +threats +and +attackers +that +system +may +face +and +the +value +of +the +assets +needs +to +protect. + +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-CONSIDERATIONS + + +WOT-SECURITY-GUIDELINES + + + +]. +This +section +includes + +discusses + +only +normative +recommendations + +security +and +privacy +risks +and +possible +mitigations +directly + +relevant +to +the +scripts +and + +WoT +Thing +Description. + +Scripting +API. + +

+

+When +designing +new +devices +and +services +for +use +with +the +WoT, +we +have +documented +a + +A +suggested + +set +of +best +practices +to +improve +security +for +WoT +devices +and +services +has +been +documented + +in +[ + + +WOT-SECURITY-BEST-PRACTICES + + +] +that +SHOULD +be +followed. +This +best-practices + +]. +That + +document +may +be +updated +as +security +measures +evolve. +Following +these +practices +does +not +guarantee +security, +but +it +at +least +will + +might + +help +to + +avoid +common +known +vulnerabilities +and +pitfalls. + +vulnerabilities. + +

+
+

+Below +are +specific +recommendations +related +to + +The + +WoT +runtime +implementations: + +security +risks +and +possible +mitigations +are +concerning +the +following +groups: + +

+

+9.1 + +Scripting +Runtime +Security +and +Privacy +Risks +

+This +section + +is +required. +Therefore + +normative +and +contains +specific +risks +relevant +for + +the +WoT +runtime +SHOULD +perform +isolation +of +WoT +runtime +instances + +Scripting +Runtime. +

+9.1.1 + +Corrupted +Input +Security + +and +their +data +if + +Privacy +Risk +

+A +typical +way +to +compromise +any +process +is +to +send +it + +a +WoT +device +has +more +than + +corrupted +input +via + +one +tenant. +Such +isolation + +of +the +exposed +interfaces. +This + +can +be +performed +within +the +WoT +Runtime + +done +to +a +script +instance + +using +platform +security +mechanisms +available + +WoT +interface +it +exposes. +

+Mitigation: +
+Implementors +of +this +API + +SHOULD + +perform +validation + +on +all +script +inputs. +In +addition +to +input +validation, + +fuzzing + +should +be +used +to +verify +that + +the +device. +For +more +information +see +Section +"WoT +Servient +Single-Tenant" + +input +processing +is +done +correctly. +There +are +many +tools + +and +"WoT +Servient +Multi-Tenant" +of + +techniques +in +existence +to +do +such +validation. +More +details +can +be +found +in + +[ + +WOT-SECURITY-CONSIDERATIONS + + +WOT-SECURITY-TESTING + + + +]. +WoT +scripts +are +using +WoT +Scripting +API +to +implement +the +functionality + +
+
+
+
+

+ +9.1.2 + +Physical +Device +Direct +Access +Security + +and +logic +for +WoT +Things. + +Privacy +Risk +

+In +addition +to +providing +the +isolation +between + +case +a + +script +and +runtime +instances, +the +WoT +runtime +needs +to +protect + +is +compromised +or +misbehaving, + +the +underlying +physical +device +from + +(and + +potentially +misbehaving +WoT +scripts. +Therefore + +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). +

+Mitigation: +
+The + +WoT +Scripting + +Runtime + +SHOULD + +avoid +directly +exposing +the +native +device +interfaces +to +the +script +developers. +Instead + +Instead, + +a +WoT +Scripting + +Runtime +should +provide +a +hardware +abstraction +layer +for +accessing +the +native +device +interfaces. +Such +hardware +abstraction +layer +should +refuse +to +execute +commands +that +might +put +the +device +(or +environment) +to +an +unsafe +state. + +Additionally, +in +order +to +reduce +the +damage +to +a +physical +WoT +device +in +cases +a +WoT + +script +gets +compromised, +it +is +important +to +minimize +the +number +of +interfaces +that +are +exposed +or +accessible +to +a +particular +WoT +script +based +on +its +functionality. +Therefore +the +WoT +Runtime +SHOULD +only +expose +a +minimal +set +of +interfaces +to +a +WoT + +script +based +on +its +intended + +functionality. +
+
+
+
+

+ +9.1.3 + +Provisioning +and +Update +Security +Risk +

+If +the +WoT +runtime + +Scripting +Runtime + +supports +post-manufacturing +provisioning +or +update + +updates + +of +WoT + +scripts, +WoT +runtime + +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 +part + +element + +during +the +update +or +provisioning +process +or +simply +provision +attacker's +code +and +data +directly. +Therefore, +if +WoT +Runtime +supports +post-manufacturing + +

+
+
+Mitigation: +
+Post-manufacturing + +provisioning +or +update +of +WoT + +scripts, +WoT +runtime + +Scripting +Runtime + +or +any +related +data, +such +operations +SHOULD + +data +should + +be +done +in +a +secure +fashion. +A +set +of +recommendations +for +secure +update +and +post-manufacturing +provisioning +can +be +found +in +[ + +WOT-SECURITY-BEST-PRACTICES + + +WOT-SECURITY-GUIDELINES + + + +]. +
+
+
+
+

+ +9.1.4 + +Security +Credentials +Storage +Security +and +Privacy +Risk +

+Typically +the +WoT +runtime + +Scripting +Runtime + +needs +to +store +the +security +credentials +that +are +provisioned +to +a +WoT +device +to +operate +in +WoT +network. +The + +If +an +attacker +can +compromise +the + +confidentiality +or +integrity +of +these +credentials +should +not +be +compromised. +Therefore + +credentials, +then +it +can +obtain +access +to + +the +WoT +runtime +SHOULD + +assets, +impersonate +WoT +things +or +devices +or +create +Denial-Of-Service +(DoS) +attacks. +

+Mitigation: +
+The +WoT +Scripting +Runtime +should + +securely +store +the +provisioned +security +credentials, +guaranteeing +their +integrity +and +confidentiality. +In +case +there +are +more +than +one +tenant +on +a +single +WoT-enabled +device, +a +WoT +Scripting + +Runtime +SHOULD + +should + +guarantee +isolation +of +each +tenant +provisioned +security +credentials. +Additionally, +in +order +to +minimize +a +risk +that +provisioned +security +credentials +get +compromised, +the +WoT +runtime + +Scripting +Runtime + +should +not +have +any +way +for +WoT +scripts +to +query +these +credentials. +Therefore, +the +WoT +Runtime +SHOULD +NOT + +expose +any +API +for +WoT + +scripts +to +query +the +provisioned +security +credentials. +
+
+
+
+
+

+ +9.2 + +Script +Security +and +Privacy +Risks +

+

+Some +additional + + +This +section +is +non-normative. +

+This +section +describes + +specific +recommendations + +risks + +relevant +for +WoT + +script +developers: + +developers. + +

+
+

+ +9.2.1 + +Corrupted +Script +Input +Security +and +Privacy +Risk +

+A +typical +way +to +compromise +any +process +is +to +send +it +a +corrupted +input +via +one +of + +script +instance +may +receive +data +formats +defined +by + +the +exposed +interfaces. +Therefore +developers + +TD, +or +data +formats +defined +by +the +applications. +While +the +WoT +Scripting +Runtime + + +SHOULD + +perform +validation +on +all +WoT + +input +fields +defined +by +the +TD, +scripts +may +be +still +exploited +by +input +data. +

+Mitigation: +
+Script +developers +should +perform +validation +on +all +application +defined + +script +inputs, +including + +inputs. +In +addition +to +input +validation, + + +fuzzing +. + + +could +be +used +to +verify +that +the +input +processing +is +done +correctly. + +There +are +many +tool + +tools + +and +techniques +in +existence +to +do +such +validation. +More +details +can +be +found +in +[ + + +WOT-SECURITY-TESTING + + +]. +As +any +software, +complex +scripts +with +a +lot +of +functionality +presents +a +higher +risk +of +development +mistakes. +Such +scripts +are +also +hard +to +verify +and +test +appropriately. +Therefore +developers +SHOUD +minimize +the +functionality +and +complexity +of +WoT +scripts. + +
+
+
+
+

+ +9.2.2 + +Denial +Of +Service +Security +Risk +

+If +a +WoT + +script +performs +a +heavy +functional +processing +on +received +requests +before +the +request +is +authenticated, +it +presents +a +great +risk +for +Denial-Of-Service +(DOS) +attacks. +Therefore +WoT +scripts +SHOULD + +

+
+
+Mitigation: +
+Scripts +should + +avoid +heavy +functional +processing +without +prior +successful +authentication +of +requestor. +The +set +of +recommended +authentication +mechanisms +can +be +found +in +[ + + +WOT-SECURITY-BEST-PRACTICES + + +]. +
+
+
+
+

+ +9.2.3 + +Stale +TD +Security +Risk +

+During +the +lifetime +of +a + +WoT +developers +should +remember +that + +network, + +a +content +of +a +TD +can +change, +including + +change. +This +includes + +its +identified, +id, + +identifier, + +which +is + +might + +not +be + +an +immutable +identifier. +Therefore +WoT +scripts +SHOULD + +one +and +might +be +updated +periodically. +

+Mitigation: +
+Scripts +should + +use +the +provided +WoT +script + +this + +API +to +subscribe +for +notifications +on +TD +changes. + +changes +and +do +not +rely +on +TD +values +to +remain +persistent. +
+Editor's +note + + +
+

+While +stale +TDs +can +present +a +potential +problem +for +WoT +network +operation, +it +might +not +be +a +security +risk. +

+
+
+

+ +10. + +Terminology +and +conventions + + +

+

+The +generic +WoT +terminology +is +defined +in +[ + + +WOT-ARCHITECTURE + + +]: + +Thing +, + +Thing +Description + +(in +short + +TD + +), + +Web +of +Things + +(in +short + + +WoT + + +), + +WoT +Interface +, + + +(same +as + +WoT +network +interface + +), + +Protocol +Bindings +, + +WoT +Runtime +, + +Consuming +a +Thing +Description +, + +Thing +Directory +, + +WoT +Interactions +, + +Property +, + +Action +, + +Event + +etc. +

+

+ +JSON-LD + +is +defined +in +[ + + +JSON-LD + + +] +as +a +JSON +document +that +is +augmented +with +support +for +Linked +Data. +

+

+The +terms + + +URL + +, + + +URL +scheme + + +and + +, + + +URL +host +, +URL +path + +, + + +URL +record +, +parse +a +URL +, +absolute-URL +string +, +path-absolute-URL +string +, + +basic +URL +parser + + + +are +defined +in +[ + + +URL + + +]. +

+

+The +following + +terms + + +MIME +type +, +Parsing +a +MIME +type +, +Serializing +a +MIME +type +, +valid +MIME +type +string +, +JSON +MIME +type + +are +defined +in +[ + +HTML52 + + +MIMESNIFF + + + +] +and + +]. +

+The +terms + +UTF-8 +encoding +, +UTF-8 +decode +, +encode +, +decode + +are +used + +defined + +in +the +context +of +browser +implementations: + +[ + +browsing +context + + +ENCODING + +, +top-level +browsing +context + + +]. +

+, + + +global +object + + +string + +, +incumbent +settings +object + +, + +, + + +parse +JSON +from +bytes + +Document + + +and + +, + + +serialize +JSON +to +bytes + +document +base +URL + +, +are +defined +in +[ + +, + + +INFRA + +Window + + +]. +

+The +terms + +, + + +WindowProxy + + +throw + +, + + +origin + +, + +, +ASCII +serialized +origin + + +, +executing +algorithms + + +creating + +in +parallel + + +, + +, + +queue +a +task + + +, + + +DOMString + +task +source + + +, + +, + +iframe + + +, + + +Dictionary + +valid +MIME +type + + +, + + + +ArrayBuffer + +. +A +browsing +context + + +refers +to +the +environment +in +which +Document + +, + + + +BufferSource + + +objects +are +presented +to +the +user. +A +given +browsing +context + +, + + + +any + + +has +a +single + +, + + +not +present +, + +DOMException + +WindowProxy + + +, + + + +AbortError + + +object, +but +it +can +have +many + + +, + + + +SyntaxError + +Document + + +, + + + +NotSupportedError + + +objects, +with +their +associated + + +, + + + +NetworkError + +Window + + +, + + + +TypeError + + +objects. +The +script +execution +context + + +associated +with +the +browsing +context +identifies +the +entity +which +invokes +this +API, +which +can +be +a +web +app +, +a +web +page +, +or +an +iframe +. +The +term +secure +context + +, + + + +NotReadableError + + +is + +, + + + +TimeoutError +, +NoModificationAllowedError +, +SecurityError +, +are + +defined +in +[ + +WEBAPPSEC + + +WEBIDL + + + +]. +

+

+ +Error +, +EvalError +, +RangeError +, +ReferenceError +, +SyntaxError +, +TypeError +, +URIError + + + +, +script +execution +context + +, + + +Promise + +, + +, + + +Error +, +JSON + +, +JSON.stringify + +, + + +JSON.stringify + + +and + +, + + +JSON.parse + + +and + + +internal +slots + + + +are +defined +in +[ + + +ECMASCRIPT + + +]. +

+

+The +terms + + +browsing +context + +DOMString + +, + +, + + +top-level +browsing +context + +USVString + +, + +, + + +global +object + +ArrayBuffer + +, + +, + + +current +settings +object + +BufferSource + +, +executing +algorithms + + +in +parallel + + +and + +any + + +are +defined +in +[ + +WEBIDL + + +HTML5 + + + +]. + +] +and +are +used +in +the +context +of +browser +implementations. + +

+

+The +algorithms +utf-8 +encode +, +and +utf-8 +decode + +term + +secure +context + + + +are + +is + +defined +in +[ + +ENCODING + + +WEBAPPSEC + + + +]. +

+

+ +IANA +media +type + +s +(formerly +known +as +MIME +types) +are +defined +in + +RFC2046 +. +

+

+The +terms + +hyperlink +reference + +and + +relation +type + +are +defined +in +[ + +HTML52 + + +HTML5 + + + +] +and + +RFC8288 +. +

+
+
+

+11. +Conformance + + +A. + +API +design +rationale + + +

+

+As +well +as +sections +marked +as +non-normative, +all +authoring +guidelines, +diagrams, +examples, +and +notes +in +this +specification +are +non-normative. +Everything +else + +API +rationale +usually +belongs +to +a +separate +document, +but + +in +this +specification +is +normative. + +the +WoT +case +the +complexity +of +the +context +justifies +including +basic +rationale +here. + +

+
+

+ +A.1 + +Approaches +to +WoT +application +development +

+The +key +words +MAY +, +MUST +, +SHOULD +, + +WoT +Interest +Group + +and +SHOULD +NOT +are + +Working +Group +have +explored +different +approaches +to +application +development +for +WoT +that +have +been +all +implemented +and +tested. +

+A.1.1 + +No +Scripting +API +

+It +is +possible + +to +develop +WoT +applications +that +only +use +the + +WoT +network +interface +, +typically +exposed +by +a +WoT +gateway +that +presents +a +REST-ful +API +towards +clients +and +implements +IoT +protocol +plugins +that +communicate +with +supported +IoT +deployments. +One +such +implementation +is +the + +Mozilla +WebThings + +platform. +

+A.1.2 + +Simple +Scripting +API +

+WoT + +Thing + +s +show +good +synergy +with +software +objects, +so +a + +Thing + +can + +be +interpreted + +represented + +as +described + +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. +

+Example + +8 +: +Open +a +lock +with +a +simple +API +

+"hljs-keyword">let lock = await WoT.consume(‘https://td.my.com/lock-00123’);
+console.log(lock.status);
+lock.open(
+'withThisKey'
+
+);
+

+A.1.3 + +This +API, +aligned +with + +[ + +RFC2119 + + +WOT-TD + + + +]. + +] +

+

+This +document +defines +conformance +criteria + +Since +the +direct +mapping +of + +Thing + +s +to +software +objects +have +had +some +challenges, +this +specification +takes +another +approach + +that +apply + +exposes +software +objects + +to +a +single +product: + +represent + +the +UA +(user +agent) +that +implements + + +Thing + +metadata +as +data +property +and + +the +interfaces +it +contains. + +WoT +interactions +as +methods. +One +implementation +is + +node-wot + +in +the +the + +Eclipse +ThingWeb + +project, +which +is +the +current +reference +implementation +of +the +API +specified +in +this +document. + +

+

+This +specification + +The +same +example +now +would +look +like +the +following: +the + +status + +property +and +the + +open() + +method +are +represented +indirectly. +

+Example + +9 +: +Open +a +lock +

+"hljs-keyword">let res = await fetch(‘https://td.my.com/lock-00123’);
+let td = 
+"hljs-keyword">await res.json();
+let lock = 
+"hljs-keyword">new ConsumedThing(td);
+
+"hljs-built_in">console.log(lock.readProperty(‘status’));
+lock.invokeAction(‘open’, 
+'withThisKey'
+
+);
+

+In +conclusion, +the +WoT +WG +decided +to +explore +the +third +option +that +closely +follows +the +[ + +WOT-TD + +] +specification. +Based +on +this, +a +simple +API + +can +also + +be +used + +implemented. +Since +Scripting +is +an +optional +module +in +WoT, +this +leaves +room + +for +implementing + +applications +that +only +use + +the +WoT +Scripting +API +in +multiple +programming +languages. +The +interface +definitions + +network +interface. +Therefore +all +three +approaches +above + +are +specified +in + +supported +by + +[ + +WEBIDL + + +WOT-TD + + + +]. +

+

+The +user +agent +(UA) +may + +Moreover, +the +WoT +network +interface +can + +be +implemented +in +the +browser, +or + +many +languages +and +runtimes. +Consider +this +API +an +example +for +what +needs +to +be +taken +into +consideration +when +designing +a +Scripting +API +for +WoT. +

+A.2 + +Fetching +and +validating +a +TD +

+The + +fetch(url) + +method +has +been +part +of +this +API + +in +earlier +versions. +However, +now +fetching + +a +separate +runtime +environment, + + +TD + +given +a +URL +should +be +done +with +an +external +method, + +such +as +Node.js + +the + +Fetch +API + + +or +small +embedded +runtimes. +Implementations + +a +HTTP +client +library, +which +offer +already +standardized +options +on +specifying +fetch +details. +The +reason +is + +that +while +simple +fetch +operations +(covering +most + +use +ECMAScript +executed + +cases) +could +be +done + +in +a +browser + +this +API, +when +various +fetch +options +were +needed, +there +was +no +point +in +duplicating +existing +work + +to +implement +the +APIs +defined + +re-expose +those +options + +in +this +document +MUST +implement +them +in + +API. +

+Since +fetching + +a +manner +consistent +with +the +ECMAScript +Bindings + + +TD + +has +been +scoped +out, +and + +TD + +validation +is + +defined +externally + +in +the +Web +IDL + +[ + +WOT-TD + +], +that +is +scoped +out, +too. +This + +specification +expects +a + +TD + +as + +parsed +JSON +object + +that +has +been +validated +according +to +the + +[ + +WEBIDL + + +WOT-TD + + + +]. + +] +specification. + +

+
+
+

+ +A.3 + +Factory +vs +constructors +

+

+Implementations + +The +factory +methods +for +consuming +and +exposing + +Thing + +s +are +asynchronous +and +fully +validate +the +input + +TD +. +In +addition, +one +can +also +construct + +ConsumedThing + +and + +ExposedThing + +by +providing +a +parsed +and +validated + +TD +. +Platform +initialization +is +then +done +when +needed +during +the +WoT +interactions. +So +applications + +that +use +TypeScript +or +ECMAScript +in + +prefer +validating + +a +runtime +to +implement + + +TD + +themselves, +may +use + +the +APIs +defined +in +this +document +MUST + +constructors, +whereas +applications +that +leave +validation +to +implementations +and +prefer +interactions +initialized +up +front + +SHOULD + + +implement +them +in +a +manner +consistent +with + +use + +the +TypeScript +Bindings +defined +in + +factory +methods +on + +the +TypeScript +specification +[ + + +WoT +API +object +.

+A.4 + +Observers + +TYPESCRIPT + + +]. + +

+

+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. + +

+
+
+

+ +A.5 + +Using +Events +

+

+This +document +serves +a +general +description +of + +API +ended +up +not +using +software +events +at +all, +for + +the +following +reasons: +

  • +Subscription +to + +WoT +Scripting +API. +Language + + +Event + +s +may +be +different +from +handling +software +events +(subscription +might +need +parameters, +might +involve +security +tokens +etc). +
  • +Most +implementations +are +for +Node.js + +and +runtime +specific + +browser +implementations +will +likely +be +libraries +(because +possible +dependency +management + +issues +are +discussed + +in +separate +extensions + +native +implementations), +using +Events +has +been +challenging. +
  • +Observing + +Property + +changes +and +handling +WoT + +Event + +s +is +done +with +the +solution +above. +

+A.6 + +Polymorphic +functions +

+The +reason +to +use +function +names +like + +readProperty() +, +readMultipleProperties() + +etc. +instead + +of +this +document. + +a +generic +polymorphic + +read() + +function +is +that +the +current +names +map +exactly +to +the + +"op" + +vocabulary +from +the + +Form + +definition +in +[ + +WOT-TD + +]. + +

+
+
+
+

+A. + + +B. + +Changes + + +

+
+

+The +following +is +a +list +of +major +changes +to +the +document. +Major +versions +of +this +specification +are +the +following: +

+For +a +complete +list +of +changes, +see +the + +github +change +log +. +You +can +also +view +the + +recently +closed +issues +. +

+Make +the +Scripting +API +refer +to +(rather +then +locally +re-define) +the +data +structures +defined +in +the +Thing +Description +specification +. + +
+
+

+B. + + +C. + +Open +issues + + +

+
+

+The +following +problems +are +being +discussed +and +need +most +attention: +

+ +
+
+
+

+C. + + +D. + +Full +Web +IDL +


+"idlTypedef" data-title="ThingDescription">typedef object ThingDescription;
+
+"WOT">[SecureContext, Exposed=(Window,Worker)]
+interface WOT {
+  // methods defined in UA conformance classes
+};
+"WOT">partial interface WOT {
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<ConsumedThing> consume(ThingDescription td);
+};
+
+"WOT">partial interface WOT {
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<ExposedThing> produce(ThingDescription td);
+};
+
+"WOT">partial interface WOT {
+  
+"internalDFN" data-link-type=
+"idl">ThingDiscovery discover(optional ThingFilter filter = null);
+};
+
+"ConsumedThing">[SecureContext, Exposed=(Window,Worker)]
+interface ConsumedThing {
+  
+"constructor" data-title="constructor" data-dfn-for="ConsumedThing"
+data-lt=
+"ConsumedThing.constructor()|ConsumedThing.constructor|constructor()|constructor">constructor(ThingDescription td);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> readProperty(DOMString propertyName,
+                            optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<PropertyMap> readAllProperties(optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<PropertyMap> readMultipleProperties(
+                            
+"" data-type="dfn" href=
+"https://heycam.github.io/webidl/#idl-sequence">sequence<DOMString> propertyNames,
+                            optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> writeProperty(DOMString propertyName,
+                              
+data-link-type="dfn" href=
+"https://heycam.github.io/webidl/#idl-any">any value,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> writeMultipleProperties(PropertyMap valueMap,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<any> invokeAction(DOMString actionName,
+                              optional any params = null,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> observeProperty(DOMString name,
+                              
+"#dom-wotlistener" class="internalDFN" data-link-type=
+"idl">WotListener listener,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> unobserveProperty(DOMString name);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> subscribeEvent(DOMString name,
+                              
+"#dom-wotlistener" class="internalDFN" data-link-type=
+"idl">WotListener listener,
+                              optional InteractionOptions options = null);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> unsubscribeEvent(DOMString name);
+  
+"internalDFN" data-link-type=
+"idl">ThingDescription getThingDescription();
+};
+dictionary InteractionOptions {
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-object">object uriVariables;
+};
+typedef object PropertyMap;
+callback WotListener = void(any data);
+
+"ExposedThing">[SecureContext, Exposed=(Window,Worker)]
+interface ExposedThing: ConsumedThing {
+  
+"internalDFN" data-link-type=
+"idl">ExposedThing setPropertyReadHandler(DOMString name,
+          
+class="internalDFN" data-link-type=
+"idl">PropertyReadHandler readHandler);
+  
+"internalDFN" data-link-type=
+"idl">ExposedThing setPropertyWriteHandler(DOMString name,
+          
+"#dom-propertywritehandler" class="internalDFN" data-link-type=
+"idl">PropertyWriteHandler writeHandler);
+  
+"internalDFN" data-link-type=
+"idl">ExposedThing setActionHandler(DOMString name, ActionHandler action);
+  
+href=
+"https://heycam.github.io/webidl/#idl-void">void emitEvent(DOMString name, any data);
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> expose();
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<void> destroy();
+};
+callback PropertyReadHandler = Promise<any>(
+        optional InteractionOptions options = null);
+callback PropertyWriteHandler = Promise<void>(any value,
+        optional InteractionOptions options = null);
+callback ActionHandler = Promise<any>(any params,
+        optional InteractionOptions options = null);
+
+"ThingDiscovery">[SecureContext, Exposed=(Window,Worker)]
+interface ThingDiscovery {
+  
+"constructor" data-title="constructor" data-dfn-for=
+"ThingDiscovery" data-lt=
+"ThingDiscovery.constructor()|ThingDiscovery.constructor|constructor()|constructor">constructor(optional ThingFilter filter = null);
+  readonly attribute ThingFilter? filter;
+  readonly attribute boolean active;
+  readonly attribute boolean done;
+  readonly attribute Error? error;
+  
+href=
+"https://heycam.github.io/webidl/#idl-void">void start();
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-promise">Promise<ThingDescription> next();
+  
+href=
+"https://heycam.github.io/webidl/#idl-void">void stop();
+};
+
+"DiscoveryMethod">typedef DOMString DiscoveryMethod;
+
+"ThingFilter">dictionary ThingFilter {
+  (DiscoveryMethod or DOMString) method = "any";
+  
+href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString? url;
+  
+href=
+"https://heycam.github.io/webidl/#idl-USVString">USVString? query;
+  
+"interface" href=
+"https://heycam.github.io/webidl/#idl-object">object? fragment;
+};
+
+
+Acknowledgments
+
+
+
+
+

+ +E. + +Acknowledgements + + + +

+

+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 +and + +Koster, +Elena +Reshetova, + +Michael +McCool +as +well +as +the +other +WoT +WG +members + +for +their +comments + +comments, +contributions + +and +guidance. +

+
+
+

+D. + + +F. + +References + + +

+
+

+D.1 + + +F.1 + +Normative +references + + +

+
+
+[ECMASCRIPT] +
+
+ + +ECMAScript +Language +Specification + +. +Ecma +International. +URL: + +https://tc39.github.io/ecma262/ + +
+
+[ENCODING] +
+
+ + +Encoding +Standard + + +. +Anne +van +Kesteren; +Joshua +Bell; +Addison +Phillips. +W3C. +15 +December +2016. +W3C +Candidate +Recommendation. + +Kesteren. +WHATWG. +Living +Standard. + +URL: +https://www.w3.org/TR/encoding/ + + +https://encoding.spec.whatwg.org/ + + +
+[HTML52] + +
+[HTML] + +
+
+ + +HTML +5.2 + +Standard +. +Anne +van +Kesteren; +Domenic +Denicola; +Ian +Hickson; +Philip +Jägenstedt; +Simon +Pieters. +WHATWG. +Living +Standard. +URL: + +https://html.spec.whatwg.org/multipage/ +
+[HTML5] +
+HTML5 + + +. +Ian +Hickson; +Robin +Berjon; + +Steve +Faulkner; +Arron +Eicholz; + +Travis +Leithead; +Alex +Danilo; +Sangwhan +Moon; + +Erika +Doyle +Navara; +Theresa +O'Connor; +Robin +Berjon. + +Silvia +Pfeiffer. + +W3C. +14 +December +2017. + +27 +March +2018. + +W3C +Recommendation. +URL: +https://www.w3.org/TR/html52/ + + +https://www.w3.org/TR/html5/ +
+[INFRA] +
+Infra +Standard +. +Anne +van +Kesteren; +Domenic +Denicola. +WHATWG. +Living +Standard. +URL: + +https://infra.spec.whatwg.org/ + + +
+
+[JSON-LD] +
+
+ + +JSON-LD +1.0 + +. +Manu +Sporny; +Gregg +Kellogg; +Markus +Lanthaler. +W3C. +16 +January +2014. +W3C +Recommendation. +URL: + +https://www.w3.org/TR/json-ld/ + +
+
+[MIMESNIFF] +
+MIME +Sniffing +Standard +. +Gordon +P. +Hemsley. +WHATWG. +Living +Standard. +URL: + +https://mimesniff.spec.whatwg.org/ +
+
+[RFC2119] +
+
+ + +Key +words +for +use +in +RFCs +to +Indicate +Requirement +Levels + +. +S. +Bradner. +IETF. +March +1997. +Best +Current +Practice. +URL: + +https://tools.ietf.org/html/rfc2119 + +
+
+[RFC8174] +
+Ambiguity +of +Uppercase +vs +Lowercase +in +RFC +2119 +Key +Words +. +B. +Leiba. +IETF. +May +2017. +Best +Current +Practice. +URL: + +https://tools.ietf.org/html/rfc8174 +
+
+[TYPESCRIPT] +
+
+ + +TypeScript +Language +Specification + +. +Microsoft. +1 +October +2012. +URL: + +https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md + +
+
+[URL] +
+
+ + +URL +Standard + +. +Anne +van +Kesteren. +WHATWG. +Living +Standard. +URL: + +https://url.spec.whatwg.org/ + +
+
+[WEBAPPSEC] +
+
+ + +Secure +Contexts + +. +W3C. +17 +July +2015. +URL: + +https://w3c.github.io/webappsec/specs/powerfulfeatures + +
+
+[WEBIDL] +
+
+ + +Web +IDL + +. +Cameron +McCormack; + +Boris +Zbarsky; +Tobie +Langel. + +Zbarsky. + +W3C. +15 +December +2016. +W3C +Editor's +Draft. +URL: + +https://heycam.github.io/webidl/ + +
+
+[WOT-ARCHITECTURE] +
+
+ + +Web +of +Things +Architecture + +. +W3C. +16 +May +2019. +URL: + +https://www.w3.org/TR/2019/CR-wot-architecture-20190516/ +
+[WOT-PROTOCOL-BINDINGS] +
+Web +of +Things +Protocol +Binding +Templates +. +W3C. + +20 +August +2017. +URL: +https://w3c.github.io/wot-architecture/ + + +https://w3c.github.io/wot-binding-templates/ + + +
+
+[WOT-SECURITY-BEST-PRACTICES] +
+
+ + +Web +of +Things +Security +and +Privacy +Best +Practices +(WIP) + + +. +W3C. +WIP. +URL: + +https://github.com/w3c/wot-security/blob/master/wot-security-best-practices.md + +
+[WOT-SECURITY-CONSIDERATIONS] + +
+[WOT-SECURITY-GUIDELINES] + +
+
+ + +Web +of +Things +Security +and +Privacy +Considerations + +Guidelines + + +. +W3C. +28 +August +2017. +URL: + +https://w3c.github.io/wot-security/ + +
+
+[WOT-SECURITY-TESTING] +
+
+ + +Web +of +Things +Security +Testing +and +Validation + +. +W3C. +WIP. +URL: + +https://github.com/w3c/wot-security/blob/master/wot-security-testing.md + +
+
+[WOT-TD] +
+
+ + +WoT +Thing +Description + + +. +W3C. +21 +October +2018. +URL: +https://www.w3.org/TR/2018/WD-wot-thing-description-20181021/ +D.2 +Informative +references +[HTML] +HTML +Standard +. +Anne +van +Kesteren; +Domenic +Denicola; +Ian +Hickson; +Philip +Jägenstedt; +Simon +Pieters. +WHATWG. +Living +Standard. + +16 +May +2019. + +URL: +https://html.spec.whatwg.org/multipage/ + + +https://www.w3.org/TR/2019/CR-wot-thing-description-20190516/ + + +
+
+
+
+ + + + diff --git a/releases/wd4/manifest.txt b/releases/wd4/manifest.txt new file mode 100644 index 00000000..b251fbe6 --- /dev/null +++ b/releases/wd4/manifest.txt @@ -0,0 +1 @@ +Overview.html diff --git a/typescript/README.md b/typescript/README.md new file mode 100644 index 00000000..5232751c --- /dev/null +++ b/typescript/README.md @@ -0,0 +1,13 @@ +# wot-typescript-definitions + +A TypeScript definition file for the WoT Scripting API to be used by implementations such as [Eclipse Thingweb](https://projects.eclipse.org/projects/iot.thingweb). + +## Notes on usage + +These definitions are imported using npm. +Once we reach conclusion on the API in the W3C Web of Things Working Group, it is planned to add them to DefinitelyTyped. + +## ES5 targets + +As consumers are using TypeScript we target ES6. +When implementing for ES5 targets, be sure to provide a polyfill for ES6 Promises, either ``es6-promise`` from npm or add the lib ``es2015.promise`` to your tsc command when transpiling TypeScript. diff --git a/typescript/index.d.ts b/typescript/index.d.ts new file mode 100644 index 00000000..26d79b94 --- /dev/null +++ b/typescript/index.d.ts @@ -0,0 +1,300 @@ +declare namespace WoT { + /** + * Starts the discovery process that will provide ConsumedThing + * + * @param filter represents the constraints for discovering Things as key-value pairs + */ + export function discover(filter?: ThingFilter): ThingDiscovery; + + /** + * Accepts a ThingDescription and returns a ConsumedThing + * @param td thing description + */ + export function consume(td: ThingDescription): Promise; + + /** + * Accepts a ThingDescription and returns a ExposedThing + * + * @param td thing description + */ + export function produce(td: ThingDescription): Promise; + + /** + * Dictionary that represents the constraints for discovering Things as key-value pairs. + */ + export interface ThingFilter { + /** + * The method field represents the discovery type that should be used in the discovery process. The possible values are defined by the DiscoveryMethod enumeration that can be extended by string values defined by solutions (with no guarantee of interoperability). + */ + method?: DiscoveryMethod | string; // default value "any", DOMString + /** + * The url field represents additional information for the discovery method, such as the URL of the target entity serving the discovery request, such as a Thing Directory or a Thing. + */ + url?: string; + /** + * The query field represents a query string accepted by the implementation, for instance a SPARQL query. + */ + query?: string; + /** + * The fragment field represents a template object used for matching against discovered Things. + */ + fragment?: object; + } + + /** The DiscoveryMethod enumeration represents the discovery type to be used */ + export enum DiscoveryMethod { + /** does not restrict */ + "any", + /** for discovering Things defined in the same Servient */ + "local", + /** for discovery based on a service provided by a Thing Directory */ + "directory", + /** for discovering Things in the same/reachable network by using a supported multicast protocol */ + "multicast" + } + + /** + * The ThingDiscovery object is constructed given a filter and provides the properties and methods + * controlling the discovery process. + */ + export interface ThingDiscovery { + filter?: ThingFilter; + active: boolean; + done: boolean; + error?: Error; + start(): void; + next(): Promise; + stop(): void; + } + + + /** + * WoT provides a unified representation for data exchange between Things, standardized in the Wot Things Description specification. + * In this version of the API, Thing Descriptions is expected to be a parsed JSON object. + */ + export type ThingDescription = { [key: string]: any; }; + + + export type DataSchemaValue = any; + export type InteractionInput = (ReadableStream | DataSchemaValue); + + export interface InteractionOutput { + data?: ReadableStream; + dataUsed: boolean; + form?: Form; + schema?: DataSchema; + arrayBuffer(): Promise; + value(): Promise; + } + + /** + * The ConsumedThing interface instance represents a client API to operate a Thing. + */ + export interface ConsumedThing { + /** + * Reads a Property value. + * Takes as arguments propertyName and optionally options. + * It returns a Promise that resolves with a Property value represented as an + * InteractionOutput object or rejects on error. + */ + readProperty(propertyName: string, options?: InteractionOptions): Promise; + + /** + * Reads all properties of the Thing with one or multiple requests. + * Takes options as optional argument. + * It returns a Promise that resolves with a PropertyMap object that + * maps keys from Property names to values. + */ + readAllProperties(options?: InteractionOptions): Promise; + + /** + * Reads multiple Property values with one or multiple requests. + * Takes as arguments propertyNames and optionally options. + * It returns a Promise that resolves with a PropertyMap object that + * maps keys from propertyNames to values + */ + readMultipleProperties(propertyNames: string[], options?: InteractionOptions): Promise; + + /** + * Writes a single Property. + * Takes as arguments propertyName, value and optionally options. + * It returns a Promise that resolves on success and rejects on failure. + */ + writeProperty(propertyName: string, value: InteractionInput, options?: InteractionOptions): Promise; + + /** + * Writes a multiple Property values with one request. + * Takes as arguments properties - as an object with keys being Property names + * and values as Property values - and optionally options. + * It returns a Promise that resolves on success and rejects on failure. + */ + writeMultipleProperties(valueMap: PropertyMap, options?: InteractionOptions): Promise; + + /** + * Makes a request for invoking an Action and return the result. + * Takes as arguments actionName, optionally params and optionally options. + * It returns a Promise that resolves with the result of the Action represented + * as an InteractionOutput object, or rejects with an error. + */ + invokeAction(actionName: string, params?: InteractionInput, options?: InteractionOptions): Promise; + + /** + * Makes a request for Property value change notifications. + * Takes as arguments propertyName, listener and optionally options. + * It returns a Promise that resolves on success and rejects on failure. + */ + observeProperty(name: string, listener: WotListener, options?: InteractionOptions): Promise; + + /** + * Makes a request for Property value change notifications. + * Takes as arguments propertyName, listener and optionally options. + * It returns a Promise that resolves on success and rejects on failure. + */ + unobserveProperty(name: string): Promise; + + /** + * Makes a request for subscribing to Event notifications. + * Takes as arguments eventName, listener and optionally options. + * It returns a Promise to signal success or failure. + */ + subscribeEvent(name: string, listener: WotListener, options?: InteractionOptions): Promise; + + /** + * Makes a request for unsubscribing from Event notifications. + * Takes as arguments eventName and optionally options. + * It returns a Promise to signal success or failure. + */ + unsubscribeEvent(name: string): Promise; + + /** + * Returns the the object that represents the Thing Description. + */ + getThingDescription(): ThingDescription; + } + + export interface InteractionOptions { + formIndex?: number; + uriVariables?: object; + data?: any; + } + + export type PropertyMap = object | { [key: string]: any; }; + + export type WotListener = (data: InteractionOutput) => void; + + export interface InteractionData { + data?: ReadableStream; + dataUsed: boolean; + form?: Form; + schema?: DataSchema; + arrayBuffer(): Promise; + value(): Promise; + } + + export type Form = { [key: string]: any; }; + export type DataSchema = { [key: string]: any; }; + + /** + * The ExposedThing interface is the server API to operate the Thing that allows defining request handlers, Property, Action, and Event interactions. + **/ + export interface ExposedThing extends ConsumedThing { + /** + * Start serving external requests for the Thing, so that WoT Interactions using Properties, Actions and Events will be possible. + */ + expose(): Promise; + + /** + * Stop serving external requests for the Thing and destroy the object. Note that eventual unregistering should be done before invoking this method. + */ + destroy(): Promise; + + /** + * Takes name as string argument and handler as argument of type PropertyReadHandler. + * Sets the handler function for reading the specified Property matched by name. + * Throws on error. + * Returns a reference to the same object for supporting chaining. + */ + setPropertyReadHandler(name: string, handler: PropertyReadHandler): ExposedThing; + + /** + * Takes name as string argument and handler as argument of type PropertyWriteHandler. + * Sets the handler function for writing the specified Property matched by name. + * Throws on error. + * Returns a reference to the same object for supporting chaining. + */ + setPropertyWriteHandler(name: string, handler: PropertyWriteHandler): ExposedThing; + + /** + * 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 the same object for supporting chaining. + */ + setPropertyObserveHandler(name: string, handler: PropertyReadHandler): ExposedThing; + + /** + * 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 the same object for supporting chaining. + */ + setPropertyUnobserveHandler(name: string, handler: PropertyReadHandler): ExposedThing; + + /** + * Takes name as string argument and handler as argument of type ActionHandler. + * Sets the handler function for the specified Action matched by name. + * Throws on error. + * Returns a reference to the same object for supporting chaining. + */ + setActionHandler(name: string, handler: ActionHandler): ExposedThing; + + /** + * 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 the same object for supporting chaining. + */ + setEventSubscribeHandler(name: string, handler: EventSubscriptionHandler): ExposedThing; + + /** + * 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 the same object for supporting chaining. + */ + setEventUnsubscribeHandler(name: string, handler: EventSubscriptionHandler): ExposedThing; + + /** + * Takes as arguments name and eventHandler. + * Sets the event handler function for the specified Event matched by name. + * Throws on error. + * Returns a reference to the same object for supporting chaining. + */ + setEventHandler(name: string, handler: EventListenerHandler): ExposedThing; + + /** + * Takes as arguments name denoting an Event name and data. + * Triggers emitting the Event with the given data. + */ + emitEvent(name: string, data: InteractionInput): void; + } + + export type PropertyReadHandler = (options?: InteractionOptions) => Promise; + + export type PropertyWriteHandler = (value: InteractionOutput, options?: InteractionOptions) => Promise; + + export type ActionHandler = (params: InteractionOutput, options?: InteractionOptions) => Promise; + + export type EventSubscriptionHandler = (options?: InteractionOptions) => Promise; + + export type EventListenerHandler = () => Promise; + +} + +declare module "wot-typescript-definitions" { + export = WoT; +} \ No newline at end of file diff --git a/typescript/package.json b/typescript/package.json new file mode 100644 index 00000000..0429a603 --- /dev/null +++ b/typescript/package.json @@ -0,0 +1,26 @@ +{ + "name": "wot-typescript-definitions", + "version": "0.8.0-SNAPSHOT.5", + "description": "TypeScript definitions for the W3C WoT Scripting API", + "author": "W3C Web of Things Working Group", + "license": "W3C-20150513", + "repository": "https://github.com/w3c/wot-scripting-api/tree/master/typescript", + "keywords": [ + "Web", + "W3C", + "WoT", + "IoT", + "things", + "scripting", + "typescript", + "types" + ], + "publishConfig": { + "access": "public" + }, + "types": "index.d.ts", + "dependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } +} diff --git a/typescript/tsconfig.json b/typescript/tsconfig.json new file mode 100644 index 00000000..0c45cdf0 --- /dev/null +++ b/typescript/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es6", + "lib" : ["es2015","dom"], + "module": "commonjs", + "outDir": "dist", + "sourceMap": true, + "noImplicitAny": true, + "removeComments": true, + "noLib": false, + "preserveConstEnums": true, + "experimentalDecorators": true, + "declaration": true + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/w3c.json b/w3c.json new file mode 100644 index 00000000..2420b7e8 --- /dev/null +++ b/w3c.json @@ -0,0 +1,10 @@ +{ + "group": [ + "95969" + ], + "contacts": [ + "ashimura" + ], + "shortName": "wot-scripting-api", + "repo-type": "rec-track" +} \ No newline at end of file