-
Notifications
You must be signed in to change notification settings - Fork 28
/
index.html
4390 lines (4266 loc) · 192 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="color-scheme" content="light dark" />
<title>Web of Things (WoT) Scripting API</title>
<script src='https://www.w3.org/Tools/respec/respec-w3c' class='remove' defer></script>
<script class='remove'>
// See https://github.com/w3c/respec/wiki/ for how to configure ReSpec
var respecConfig = {
specStatus: "ED",
processVersion: 2023,
shortName: "wot-scripting-api",
copyrightStart: 2017,
group: "wg/wot",
noRecTrack: true,
noLegacyStyle: true,
wgPublicList: "public-wot-wg",
edDraftURI: "https://w3c.github.io/wot-scripting-api/",
github: "https://github.com/w3c/wot-scripting-api/",
issueBase: "https://www.github.com/w3c/wot-scripting-api/issues/",
crEnd: "",
inlineCSS: true,
noIDLIn: true,
noRecTrack: true,
editors: [
{ name: "Zoltan Kis", w3cid: "57789", company: "Intel Corp.", companyURL: "https://www.intel.com/" },
{ name: "Daniel Peintner", w3cid: "39497", company: "Siemens AG", companyURL: "https://www.siemens.com/" },
{ name: "Cristiano Aguzzi", w3cid: "105495", company: "Invited Expert", companyURL: "https://github.com/relu91" },
{ name: "Johannes Hund", w3cid: "74472", note: "Former Editor, when at Siemens AG" },
{ name: "Kazuaki Nimura", w3cid: "59208", note: "Former Editor, at Fujitsu Ltd." },
],
otherLinks: [
{
key: "Repository",
data: [{
value: "On GitHub",
href: "https://github.com/w3c/wot-scripting-api"
}, {
value: "File a bug",
href: "https://github.com/w3c/wot-scripting-api/issues"
},
]
},
{
key: "Contributors",
data: [
{
value: "Contributors on GitHub",
href: "https://github.com/w3c/wot-scripting-api/graphs/contributors"
}
]
},
],
xref: ["web-platform", "HTML", "INFRA", "URL", "WEBIDL", "DOM", "FETCH",
"ecmascript", "streams",
"wot-architecture11", "wot-thing-description11", "wot-binding-templates"],
localBiblio: {
"TYPESCRIPT": {
href: "https://www.typescriptlang.org/docs/handbook/intro.html",
title: "TypeScript Language Specification",
publisher: "Microsoft",
date: "1 October 2012"
},
"WEBAPPSEC": {
href:"https://w3c.github.io/webappsec/specs/powerfulfeatures",
title: "Secure Contexts",
publisher: "W3C",
date: "18 September 2021"
},
},
};
</script>
<script>
document.addEventListener("DOMContentLoaded", () => {
// Add example button selection logic
for (const button of document.querySelectorAll(".ds-selector-tabs .selectors button")) {
button.onclick = () => {
const ex = button.closest(".ds-selector-tabs");
ex.querySelector("button.selected").classList.remove("selected");
ex.querySelector(".selected").classList.remove("selected");
button.classList.add('selected');
ex.querySelector("." + button.dataset.selects).classList.add("selected");
}
}
});
</script>
<style>
/* example tab selection */
.ds-selector-tabs {
padding-bottom: 2em;
}
.ds-selector-tabs .selectors {
padding: 0;
border-bottom: 1px solid #ccc;
height: 28px;
}
.ds-selector-tabs .selectors button {
display: inline-block;
min-width: 54px;
text-align: center;
font-size: 11px;
font-weight: bold;
height: 27px;
padding: 0 8px;
line-height: 27px;
transition: all,0.218s;
border-top-right-radius: 2px;
border-top-left-radius: 2px;
color: #666;
border: 1px solid transparent;
}
.ds-selector-tabs .selectors button:first-child {
margin-left: 2px;
}
.ds-selector-tabs .selectors button.selected {
color: #202020 !important;
border: 1px solid #ccc;
border-bottom: 1px solid #fff !important;
}
.ds-selector-tabs .selectors button:hover {
background-color: transparent;
color: #202020;
cursor: pointer;
}
.ds-selector-tabs pre:not(.preserve), .ds-selector-tabs table:not(.preserve) {
display: none;
}
.ds-selector-tabs pre.selected, .ds-selector-tabs table.selected {
display: block;
}
</style>
</head>
<body>
<section id="abstract">
<p>
The Web of Things is made of entities (<a>Thing</a>s) that can describe their capabilities in a machine-interpretable <a>Thing Description</a> (TD) and expose these capabilities through the <a>WoT Interface</a>, that is, network interactions modeled as <a>Properties</a> (for reading and writing values), <a>Action</a>s (to execute remote procedures with or without return values) and <a>Event</a>s (for signaling notifications).
</p>
<p>
The main <a>Web of Things</a> (WoT) concepts are described in the [[[wot-architecture11]]] specification.
</p>
<p>
Scripting is an optional building block in WoT and it is typically used in gateways or browsers that are able to run a <a>WoT Runtime</a> and
<a href="https://github.com/w3c/wot-scripting-api/tree/master/applications/script-manager">script management</a>, providing a convenient way to extend WoT support to new types of endpoints and implement WoT applications such as <a href="https://github.com/w3c/wot-scripting-api/tree/master/applications/thing-directory">TD Directory</a>.
</p>
<p>
This specification describes an application programming interface (API) representing the <a>WoT Interface</a> that allows scripts to discover, operate <a>Thing</a>s and to expose locally defined <a>Thing</a>s characterized by <a> WoT Interactions</a> specified by a script.
</p>
<p>
The APIs defined in this document deliberately follow the [[[wot-thing-description11]]] 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 <a>WoT Interface</a>).
</p>
<p class="ednote">
This specification is implemented at least by the <a href="https://www.thingweb.io/">Eclipse Thingweb</a>
project also known as <a href="https://github.com/eclipse-thingweb/node-wot">node-wot</a>, which is considered the reference open source implementation at the moment. Check its <a href="https://github.com/eclipse-thingweb/node-wot"> source code</a>, including <a href="https://github.com/eclipse-thingweb/node-wot/tree/master/examples">examples</a>.
</p>
</section>
<section id="sotd">
<p>
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 <a href="https://github.com/w3c/wot-scripting-api">repository</a> and take part in the discussions.
</p>
<p class="ednote" title="The W3C WoT WG is asking for feedback">
Please contribute to this draft using the <a href="https://github.com/w3c/wot-scripting-api/issues">GitHub Issues</a> page of the <a href="https://github.com/w3c/wot-scripting-api/">WoT Scripting API</a> repository.
For feedback on security and privacy considerations, please use the <a href="https://github.com/w3c/wot-security/issues">WoT Security and Privacy</a> Issues.
</p>
</section>
<section id="introduction"> <h2>Introduction</h2>
<p>
WoT provides layered interoperability based on how <a>Thing</a>s are used:
"consumed" and "exposed", as defined in the [[[wot-architecture11]]] terminology.
</p>
<p>
By <a>consuming a TD</a>, a client <a>Thing</a> creates a local runtime resource model that allows accessing the <a>Properties</a>, <a>Actions</a> and <a>Events</a> exposed by the server <a>Thing</a> on a remote device.
</p>
<div>
Exposing a <a>Thing</a> requires:
<ul>
<li>
defining a <a>Thing Description</a> (TD),
</li>
<li>
then instantiating a software stack that implements the <a>WoT Interface</a> specified by the <a>TD</a> in order to serve requests for accessing the exposed <a>Properties</a>, <a>Actions</a> and <a>Events</a>,
</li>
<li>
then eventually publishing the <a>Thing Description</a> (for instance to a <a>TD Directory</a> for easier discovery).
</li>
</ul>
This specification describes how to expose and consume <a>Thing</a>s by a script. Also, it defines a generic API for <a>Thing</a> discovery.
</div>
<p class="note">
Typically scripts are meant to be used on bridges or gateways that expose and control simpler devices as WoT <a>Thing</a>s and have means to handle (e.g. install, uninstall, update etc.) and run scripts.
</p>
<p class="note">
This specification does not make assumptions on how the <a>WoT Runtime</a> 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 <a>Thing</a> whose <a>Actions</a> (action handlers) implement script lifecycle management operations.
</p>
<!--
<p>
For an introduction on how scripts could be used in <a>Web of Things</a>, check the <a href="https://w3c.github.io/wot-scripting-api/primer">Primer</a> document. For some background on API design decisions check the <a href="https://w3c.github.io/wot-scripting-api/rationale">Rationale</a> document.
</p>
-->
</section>
<section class="informative"> <h3>Use Case Scenarios</h3>
<p>
The business use cases listed in the [[wot-usecases]] document may be
implemented using this API, based on the scripting use case scenarios
described here.
</p>
<section><h4>Consuming a Thing</h4>
<ul>
<li>
<a>Consume a TD</a>, i.e. create a programmatic object from a
<a>Thing Description</a> that exposes <a>WoT Interactions</a>:
<ul>
<li>Read the value of a <a>Property</a> or a set of properties.</li>
<li>Set the value of a <a>Property</a> or a set of properties.</li>
<li>Observe value changes of a <a>Property</a>.</li>
<li>Invoke an <a>Action</a>.</li>
<li>Observe WoT <a>Events</a> emitted by the <a>Thing</a>.</li>
<li>
Introspect the <a>Thing Description</a>.
</li>
</ul>
</li>
</ul>
</section>
<section><h4>Exposing a Thing</h4>
<ul>
<li>
Exposing the <a>Thing</a> includes generating the protocol bindings in
order to access lower level functionality.
</li>
<li>
Create a local <a>Thing</a> to be exposed, based on <a>Thing Description</a>.
</li>
<li>
The following use cases can be implemented before creating the
<a>Thing</a> by editing the <a>Thing Description</a>:
<ul>
<li>Add a <a>Property</a> definition to the <a>Thing</a>.</li>
<li>Remove a <a>Property</a> definition from the <a>Thing</a>.</li>
<li>Add an <a>Action</a> definition to the <a>Thing</a>.</li>
<li>Remove an <a>Action</a> definition from the <a>Thing</a>.</li>
<li>Add a WoT <a>Event</a> definition to the <a>Thing</a>.</li>
<li>Remove a WoT <a>Event</a> definition from the <a>Thing</a>.</li>
</ul>
<p class="ednote">
After evaluating dynamic modifications to <a>Thing Descriptions</a>
through several versions of this API, the editors concluded that the
simplest way to represent these use cases is to take an existing
<a>TD</a>, modify it (i.e. add or remove definitions) and then create
a new <a>Thing</a> based on the modified <a>TD</a>.
</p>
</li>
<li>
Emit a WoT <a>Event</a>, i.e. notify all subscribed listeners.
</li>
<li>Register service handlers for external requests:
<ul>
<li>to retrieve a <a>Property</a> value;</li>
<li>to update a <a>Property</a> value;</li>
<li>to observe a <a>Property</a>;</li>
<li>to unobserve a <a>Property</a>;</li>
<li>
to invoke an <a>Action</a>: take the parameters from the request, execute the defined action, and return the result;
</li>
<li>to subscribe to an <a>Event</a>;</li>
<li>to unsubscribe from an <a>Event</a>.</li>
</ul>
</li>
</ul>
</section>
<section><h4>Discovery</h4>
<ul>
<li>Discover <a>Thing</a>s in a network by sending a broadcast request.</li>
<li>Discover <a>Thing</a>s running in the local <a>WoT Runtime</a>.</li>
<li>Discover nearby <a>Thing</a>s, for instance connected by NFC or Bluetooth,
or within a <a href="https://en.wikipedia.org/wiki/Geo-fence">geo-fence</a>.</li>
<li>Discover <a>Thing</a>s by sending a discovery request to a given <a>TD Directory</a>.</li>
<li>Discover <a>Thing</a>s filtered by filters defined on <a>Thing Description</a>s</li>
<li>Discover <a>Thing</a>s filtered by semantic queries.</li>
<li>Stop or suppress an ongoing discovery process.</li>
<li>
Optionally specify a timeout to the discovery process after which it is stopped/suppressed.
</li>
</ul>
</section>
</section>
<section id="conformance">
<p class="ednote">
This specification used to be a Working Draft which was expected to become a W3C Recommendation. However, it is now a WG Note which contains informative statements only. Therefore we need to consider how to deal with the description within this Conformance section.</p>
<p>
This specification describes the conformance criteria for the following classes of [= user agent =] (<dfn>UA</dfn>).
</p>
<p>
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 <a>UA</a> 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 <code>consume()</code>, <code>produce()</code> and <code>discover()</code> methods on the <a>WoT API object</a> in order to determine which conformance class the <a>UA</a> implements.
</p>
<dl>
<dt>
<dfn>WoT Consumer</dfn> <a>UA</a>
</dt>
<dd>
<p>
Implementations of this conformance class MUST implement the <code>{{ConsumedThing}}</code> interface and the <code>consume()</code> method on the <a>WoT API object</a>.
</p>
</dd>
<dt>
<dfn>WoT Producer</dfn> <a>UA</a>
</dt>
<dd>
<p>
Implementations of this conformance class MUST implement <code>{{ExposedThing}}</code> interface and the <code>produce()</code> method on the <a>WoT API object</a>.
</p>
</dd>
<dt>
<dfn>WoT Discovery</dfn> <a>UA</a>
</dt>
<dd>
<p>
Implementations of this conformance class MUST implement the
<code><a>ThingDiscoveryProcess</a></code> interface, the
<code>discover()</code> method, the <code>exploreDirectory()</code> method,
and the <code>requestThingDescription()</code> method on the
<a>WoT API object</a>.
</p>
</dd>
</dl>
<p>
These conformance classes MAY be implemented in a single <a>UA</a>.
</p>
<p>
This specification can be used for implementing the WoT Scripting API in multiple programming languages. The interface definitions are specified in [[!WEBIDL]].
</p>
<p>
The <a>UA</a> may be implemented in the browser, or in a separate runtime environment, such as <a href="https://nodejs.org/en/">Node.js</a> or in small embedded runtimes.
</p>
<p>
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]].
</p>
<p>
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]].
</p>
</section>
<section> <h2>Terminology and conventions</h2>
<p>
The generic WoT terminology is defined in [[!wot-architecture11]]: <dfn data-lt="Things">Thing</dfn>, <dfn data-lt="Thing Descriptions">Thing Description</dfn> (in short <dfn>TD</dfn>), <dfn>Partial TD</dfn>, <dfn>Web of Things</dfn> (in short <b><i>WoT</i></b>), <dfn>WoT Interface</dfn>, <dfn>Protocol Bindings</dfn>, <dfn>WoT Runtime</dfn>, <dfn data-lt="consume|consume a TD|consuming a TD">Consuming a Thing Description</dfn>, <dfn>TD Directory</dfn>, <dfn data-lt="Properties">Property</dfn>, <dfn data-lt="Actions">Action</dfn>, <dfn data-lt="Events|WoT-Event">Event</dfn>,
<a data-cite="wot-thing-description11#dataschema">
<dfn>DataSchema</dfn></a>, <a data-cite="wot-thing-description11#form"><dfn data-lt="Forms">Form</dfn></a>,
<a data-cite="wot-thing-description11#securityscheme"><dfn>SecurityScheme</dfn></a>, <a data-cite="wot-thing-description11#nosecurityscheme"><dfn>NoSecurityScheme</dfn></a> etc.
</p>
<p>
<dfn data-plurals="WoT Interactions">WoT Interaction</dfn> is a synonym for <a data-cite="wot-architecture11#dfn-interaction-affordance"><dfn>Interaction Affordance</dfn></a>.
An <a>Interaction Affordance</a> (or shortly, affordance) is the term used in [[!wot-thing-description11]]
when referring to <a>Thing</a> capabilities, as explained in
<a href="https://github.com/w3c/wot-thing-description/issues/282">TD issue 282</a>.
However, this term is not well understood outside the <a>TD</a> semantic context.
Hence for the sake of readability, this document will use the previous term
<a>WoT interaction</a> or, simply, <em>interaction</em> instead.
</p>
<p>
<dfn>WoT network interface</dfn> synonym for <a>WoT Interface</a>.
</p>
<p>
<dfn>JSON Schema</dfn> is defined in <a href="https://json-schema.org/specification.html">these specifications</a>.
</p>
<!--
<p>
The terms
<dfn data-cite="!URL#concept-url">URL</dfn>,
<dfn data-cite="!URL#concept-url-scheme">URL scheme</dfn>,
<dfn data-cite="!URL#concept-url-host">URL host</dfn>,
<dfn data-cite="!URL#concept-url-path">URL path</dfn>,
<dfn data-cite="!URL#concept-url">URL record</dfn>,
<dfn data-cite="!URL#url-parsing">parse a URL</dfn>,
<dfn data-cite="!URL#absolute-url-string">absolute-URL string</dfn>,
<dfn data-cite="!URL#path-absolute-url-string">path-absolute-URL string</dfn>,
<dfn data-cite="!URL#concept-basic-url-parser">basic URL parser</dfn>
are defined in [[!URL]].
</p>
<p>
The terms
<dfn data-cite="!MIMESNIFF#mime-type">MIME type</dfn>,
<dfn data-cite="!MIMESNIFF#parsing-a-mime-type">Parsing a MIME type</dfn>,
<dfn data-cite="!MIMESNIFF#serializing-a-mime-type">Serializing a MIME type</dfn>,
<dfn data-cite="!MIMESNIFF#valid-mime-type">valid MIME type string</dfn>,
<dfn data-cite="!MIMESNIFF#json-mime-type">JSON MIME type</dfn>
are defined in [[!MIMESNIFF]].
</p>
<p>
The terms
<dfn data-cite="!ENCODING#utf-8">UTF-8 encoding</dfn>,
<dfn data-cite="!ENCODING#utf-8-decode">UTF-8 decode</dfn>,
<dfn data-cite="!ENCODING#encode">encode</dfn>,
<dfn data-cite="!ENCODING#decode">decode</dfn>
are defined in [[!ENCODING]].
</p>
<p>
<dfn data-cite="!INFRA#string">string</dfn>,
<dfn data-cite="!INFRA#parse-json-bytes-to-a-javascript-value">parse JSON from bytes</dfn> and
<dfn data-cite="!INFRA#serialize-a-javascript-value-to-json-bytes">serialize JSON to bytes</dfn>,
are defined in [[!INFRA]].
</p>
-->
<p>
<dfn data-cite="!ECMASCRIPT#sec-promise-objects">{{Promise}}</dfn>,
<dfn data-cite="!ECMASCRIPT#sec-error-objects">Error</dfn>,
<dfn data-cite="!ECMASCRIPT#sec-json-object">JSON</dfn>,
<dfn data-cite="!ECMASCRIPT#sec-json.stringify">JSON.stringify</dfn>,
<dfn data-cite="!ECMASCRIPT#sec-json.parse">JSON.parse</dfn>,
<dfn data-cite="!ECMASCRIPT#sec-object-internal-methods-and-internal-slots">internal method</dfn> and
<dfn data-cite="!ECMASCRIPT#sec-object-internal-methods-and-internal-slots">internal slot</dfn> are defined in [[!ECMASCRIPT]].
</p>
<!--
<p>
The terms
<dfn data-cite="!HTML#browsing-context">browsing context</dfn>,
<dfn data-cite="!HTML#top-level-browsing-context">top-level browsing context</dfn>,
<dfn data-cite="!HTML#global-object">global object</dfn>,
<dfn data-cite="!HTML#current-settings-object">current settings object</dfn>,
executing algorithms <dfn data-cite="!HTML#in-parallel">in parallel</dfn>
are defined in [[!HTML5]] and are used in the context of browser implementations.
</p>
<p>
The term
<a href="https://w3c.github.io/webappsec/specs/powerfulfeatures/#secure-context">
<dfn>secure context</dfn></a> is defined in [[!WEBAPPSEC]].
</p>
<p>
<dfn>IANA media type</dfn>s (formerly known as MIME types) are defined in
<a href="http://tools.ietf.org/html/rfc2046">RFC2046</a>.
</p>
<p>
The terms <dfn>hyperlink reference</dfn> and <dfn>relation type</dfn> are defined in [[!HTML5]] and <a href="https://tools.ietf.org/html/rfc8288">RFC8288</a>.
</p>
-->
</section>
<section data-cite="webidl">
<h2>The <dfn>ThingDescription</dfn> type</h2>
<pre class="idl">
typedef object ThingDescription;
</pre>
<p>
Represents a <a>Thing Description</a> (<a>TD</a>) as
<a data-cite="wot-thing-description11#">defined</a> in
[[!wot-thing-description11]]. It is expected to be
a <a data-cite="infra#parse-json-bytes-to-a-javascript-value">parsed JSON object</a> that is validated using <a data-cite="wot-thing-description11#json-schema-for-validation">JSON Schema validation</a>.
</p>
<section> <h3> Requesting a Thing Description</h3>
<p>
Requesting a <a>TD</a> given a URL should be done with the
<a href="#dom-wot-requestthingdescription">requestThingDescription()</a>
method.
Alternatively, external methods, such as the <a data-cite="fetch#fetch-api">Fetch API</a> or an HTTP client library, can be used.
</p>
<pre class="example" title="Requesting a Thing Description">
try {
const td = await requestThingDescription('https://tds.mythings.biz/sensor11');
const thing = await WoT.consume(td);
console.log("Thing name: " + thing.getThingDescription().title);
} catch (err) {
console.log("Requesting TD failed", err.message);
}
</pre>
</section>
<section> <h3>Expanding a Thing Description</h3>
<p>
Note that the [[[wot-thing-description11]]] specification allows using a shortened <a>Thing Description</a>
by the means of <a data-cite="wot-thing-description11#sec-default-values">defaults</a> and requiring clients to expand them with default values specified in the
[[[wot-thing-description11]]] specification for the properties that are not explicitly defined in a given
<a>TD</a>.
</p>
<div>
To <dfn>expand a TD</dfn> given |td:ThingDescription|, run the following steps:
<ol>
<li>
For each item in the <a data-cite="wot-thing-description11#sec-default-values">TD default values</a> table from [[!wot-thing-description11]], if the term is not defined in |td|, add the term definition with the default value specified in [[!wot-thing-description11]].
</li>
</ol>
</div>
</section>
<section> <h3>Validating a Thing Description</h3>
<p>
The [[!wot-thing-description11]] specification defines how a <a>TD</a> should be validated.
Therefore, this API expects the {{ThingDescription}} objects be validated before used as parameters. This specification defines a basic <a>TD</a> validation as follows.
</p>
<div>
To <dfn>validate a TD</dfn> given |td:ThingDescription|, run the following steps:
<ol>
<li>
If <a data-cite="wot-thing-description11#json-schema-for-validation">JSON Schema
validation</a> fails on |td|, [= exception/throw =] a {{"TypeError"}} and stop.
</li>
</ol>
<p class="ednote" title="Handling default values">
Additional steps may be added to fill the default values of mandatory fields.
</p>
</div>
</section>
</section>
<section data-dfn-for="WOT" data-cite="webidl">
<h2>The <dfn>WOT</dfn> namespace</dfn></h2>
<p>
Defines the <dfn>WoT API object</dfn> as a singleton and contains the API
methods, grouped by conformance classes.
</p>
<pre class="idl">
[SecureContext, Exposed=(Window,Worker)]
namespace WOT {
// methods defined in UA conformance classes
};
</pre>
<section> <h3>The <dfn>consume()</dfn> method</h3>
<pre class="idl">
partial namespace WOT {
Promise<ConsumedThing> consume(ThingDescription td);
};
</pre>
<div>
Belongs to the <a>WoT Consumer</a> 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 <a>Thing</a>. The method MUST run the following steps:
<ol>
<li>
Return a {{Promise}} |promise:Promise| and execute the next steps [=in parallel=].
</li>
<li>
If invoking this method is not allowed for the current scripting context for security reasons, [=reject=] |promise| with a {{SecurityError}} and stop.
</li>
<li>
Let |thing:ConsumedThing| be a new {{ConsumedThing}} object constructed from |td|.
</li>
<li>
Set up the <a>WoT Interactions</a> based on introspecting <a>td</a> as explained in [[!wot-thing-description11]] and [[!wot-binding-templates]]. Make a request to the underlying platform to initialize the <a>Protocol Bindings</a>.
<p class="ednote">
Implementations encapsulate the complexity of how to use the
<a>Protocol Bindings</a> for implementing <a>WoT interactions</a>.
In the future elements of that could be standardized.
</p>
</li>
<li>
[=Resolve=] |promise| with |thing|.
</li>
</ol>
</div>
</section>
<section> <h3>The <dfn>produce()</dfn> method</h3>
<pre class="idl">
typedef object ExposedThingInit;
partial namespace WOT {
Promise<ExposedThing> produce(ExposedThingInit init);
};
</pre>
<div>
Belongs to the <a>WoT Producer</a> conformance class. Expects a |init:ExposedThingInit| 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 |init:ExposedThingInit| object is an instance of the <a>ExposedThingInit</a> type.
Specifically, an <a>ExposedThingInit</a> value is a dictionary used for the initialization of an <a>ExposedThing</a> and
it represents a <a>Partial TD</a> as described in the [[!wot-architecture11]]. As such, it has the same
structure of a <a>Thing Description</a> but it may omit some information.
The method MUST run the following steps:
<ol>
<li>
Return a {{Promise}} |promise:Promise| and execute the next steps [=in parallel=].
</li>
<li>
If invoking this method is not allowed for the current scripting context for security reasons, [=reject=] |promise| with a {{SecurityError}} and stop.
</li>
<li>
Let |thing:ExposedThing| be a new {{ExposedThing}} object constructed with |init|.
</li>
<li>
[=Resolve=] |promise| with |thing|.
</li>
</ol>
</div>
<section>
<h3>Expand an ExposedThingInit</h3>
To <dfn>expand an ExposedThingInit</dfn> given |init:ExposedThingInit| and obtain a valid |td:ThingDescription| as a result, run the following steps:
<ol class="algorithm">
<li>
Run <a>validate an ExposedThingInit</a> on |init|. If that fails,
[= exception/throw =] {{SyntaxError}} and stop.</li>
<li>
Let |td| be the result of running [=map/clone=] given |init|.
</li>
<li>
For each |scheme:SecurityScheme| in |td|.[<code>"securityDefinitions"</code>], make a request to the underlying platform to check if it is supported by at least one <a>Protocol Binding</a>. If not, then remove |scheme| from |td|.
</li>
<li>
If |td|.[<code>"security"</code>] does not [=map/exist=] in |td|.[<code>"securityDefinitions"</code>], then remove <code>security</code> from |td|.
</li>
<li>For each |affordance| in |td|.properties, |td|.actions and |td|.events, run the following sub-steps:
<ol>
<li>For each |form:Form| in |affordance|.forms:
<ol>
<li>
If |form|.|contentType:string| is not recognized by the runtime as valid remove |contentType:string| from |form|.
</li>
<li>
If |form|.|href:URL| has an unknown schema, remove |href| from |form|.
</li>
<li>
If |form|.|href:URL| is absolute and its <code>authority</code> it is not recognized by the runtime as valid, remove |href| from |form|.
</li>
<li>
If |form|.|href:URL| is already in use by other <a>ExposedThings</a>, remove |href| from |form|.
</li>
</ol>
</li>
</ol>
</li>
<li>Search for missing required properties in |td| accordingly to
<a data-cite="wot-thing-description11#json-schema-for-validation">TD JSON
Schema</a>.
<p class="ednote">The editors find this step vague. It will be improved or removed in the next iteration. </p>
</li>
<li>For each |missing| property run these sub-steps:
<ol>
<li>If |missing| is <code>title</code> generate a runtime unique name and assign to <code>title</code>.</li>
<li>If |missing| is <code>@context</code> assign the latest supported Thing Description context URI.</li>
<li>If |missing| is <code>instance</code> assign the string <code>1.0.0</code>.</li>
<li>If |missing| is <code>forms</code> generate a list of <a>Forms</a> using the available <a>Protocol Bindings</a> and content types
encoders. Then assign the obtained list to <code>forms</code>.</li>
<li>If |missing| is <code>security</code> assign the label of the first supported <a>SecurityScheme</a> in <code>securityDefinitions</code> field.
If no <a>SecurityScheme</a> is found generate a <a>NoSecurityScheme</a> called <code>nosec</code> and assign the string <code>nosec</code>
to <code>security</code>.
<p class="issue">The discussion about how to properly generate a value for <code>security</code> is still open.
See issue <a href="https://github.com/w3c/wot-scripting-api/issues/299">#299</a> </p>
</li>
<li>If |missing| is <code>href</code> define |formStub| as the partial <a>Form</a> that does not have <code>href</code>. Generate a valid |url:URL| using the first <a>Protocol Binding</a>
that satisfy the requirements of |formStub|. Assign |url| to <code>href</code>. If not <a>Protocol Binding</a> can be found remove |formStub| from |td|. </li>
<li>Add |missing| to |td| with |value| as value</li>
</ol>
</li>
<li>Run <a>validate a TD</a> on |td|. If that fails re-[= exception/throw =] the error and stop</li>
<li>Return |td|</li>
</ol>
</section>
<section>
<h3>Validating an ExposedThingInit</h3>
To <dfn>validate an ExposedThingInit</dfn> given |init:ExposedThingInit|, run the following steps:
<ol class="algorithm">
<li>
Parse <a data-cite="wot-thing-description11#json-schema-for-validation">TD JSON
Schema</a>
and load it in object called |exposedThingInitSchema:object|
</li>
<li>let |optional:Array| be a list containing the following strings: <code>title</code>, <code>@context</code>,
<code>instance</code>, <code>forms</code>, <code>security</code>, and <code>href</code>. </li>
<li>
For each property and sub-property |key| in |exposedThingInitSchema| equals to <code>required</code> execute the following steps:
<ol>
<li>if |key| |value| is an <code>Array</code> then remove all its elements equal to the elements in |optional|</li>
<li>if |key| |value| is a <code>string</code> then if |value| is equal to one of the elements in |optional| remove |key| from |exposedThingInitSchema|</li>
</ol>
</li>
<li>Return the result of <a>validating an object with JSON Schema</a> given |init| and |exposedThingInitSchema|.
<p class="ednote">The <dfn>validating an object with JSON Schema</dfn> steps are still under discussion.
Currently this specification reference to the validation process of JSONSchema. Please
follow this <a href="https://json-schema.org/draft/2019-09/json-schema-validation.html">document</a>
when validating |init| with |exposedThingInitSchema|. Notice that the working group is evaluating an alternative formal approach.
</p>
</li>
</ol>
</section>
</section>
<section> <h3>The <dfn>discover()</dfn> method</h3>
<pre class="idl">
partial namespace WOT {
Promise<ThingDiscoveryProcess> discover(optional ThingFilter filter = {});
};
</pre>
<div>
Belongs to the <a>WoT Discovery</a> conformance class. Starts the discovery process that will provide {{ThingDescription}} objects for <a>Thing Description</a>s that match an optional |filter:ThingFilter| argument of type {{ThingFilter}}. The method MUST run the following steps:
<ol>
<li>
Return a {{Promise}} |promise:Promise| and execute the next steps [=in parallel=].
</li>
<li>
If invoking this method is not allowed for the current scripting context for security reasons, [=reject=] |promise| with a {{SecurityError}} and stop.
</li>
<li>
If discovery is not supported by the implementation, [=reject=] |promise|
with {{NotSupportedError}} and stop.
</li>
<li>
Let |discovery:ThingDiscoveryProcess| be a new {{ThingDiscoveryProcess}} object.
</li>
<li>
Set |discovery|.{{ThingDiscoveryProcess/[[filter]]}} to |filter:ThingFilter|.
</li>
<li>
Set |discovery|.{{ThingDiscoveryProcess/[[url]]}} to `undefined`.
</li>
<li>
If filters in general are not supported by the implementation and
|filter| is not `undefined` or `null`, [=reject=] |promise|
with {{NotSupportedError}} and stop.
</li>
<li>
If discovery cannot be started by the underlying platform,
[=reject=] |promise| with {{OperationError}} and stop.
</li>
<li>
Request the underlying platform to start the <a>discovery process</a>
by any means supported and provisioned in the <a>WoT Runtime</a> for which
the script has access to, passing |discovery| to it.
</li>
<li>
[=Resolve=] |promise| with |discovery|.
</li>
</ol>
<p>
Note that the details of the <a>discovery process</a> depend on the
underlying implementation which needs to be preconfigured in order to
use, for example, the appropriate Introduction methods as defined in
the [[[wot-discovery]]] specification.
Since the <code>discover()</code> method outputs
<a>Thing Description</a>s and not URLs, it is expected to cover both the
Introduction and the Exploration phase.
</p>
</div>
</section>
<section> <h3>The <dfn>exploreDirectory()</dfn> method</h3>
<pre class="idl">
partial namespace WOT {
Promise<ThingDiscoveryProcess> exploreDirectory(USVString url,
optional ThingFilter filter = {});
};
</pre>
<div>
Belongs to the <a>WoT Discovery</a> conformance class. Starts the discovery process that given a <a>TD Directory</a> URL, will provide {{ThingDescription}} objects for <a>Thing Description</a>s that match an optional |filter:ThingFilter| argument of type {{ThingFilter}}. The method MUST run the following steps:
<ol>
<li>
Return a {{Promise}} |promise:Promise| and execute the next steps [=in parallel=].
</li>
<li>
If invoking this method is not allowed for the current scripting context for security reasons, [=reject=] |promise| with a {{SecurityError}} and stop.
</li>
<li>
If directory discovery is not supported by the implementation, [=reject=] |promise|
with {{NotSupportedError}} and stop.
</li>
<li>
Let |discovery:ThingDiscoveryProcess| be a new {{ThingDiscoveryProcess}} object.
</li>
<li>
Set |discovery|.{{ThingDiscoveryProcess/[[url]]}} to |url:USVString|.
</li>
<li>
Set |discovery|.{{ThingDiscoveryProcess/[[filter]]}} to |filter:ThingFilter|.
</li>
<li>
Request the underlying platform to start the directory discovery process.
<p class="note">
This is a placeholder for more details in the discovery algorithm.
Implementations should follow the procedures described in the
[[wot-discovery]] and [wot-binding-templates] specifications.
Some normative steps are indicated below.
</p>
<ol>
<li>
If |url| is not a <a>TD Directory</a> or if the underlying
implementation cannot support the <a>Protocol Binding</a>
indicated by |url|, [=reject=] |promise|
with {{NotSupportedError}} and terminate these steps.
</li>
<li>
If filters in general are not supported by the implementation and
|filter| is not `undefined` or `null`, [=reject=] |promise|
with {{NotSupportedError}} and stop.
</li>
<li>
Run the <a>discovery process</a> given |discovery|.
<p class="note">
From this point on, errors are recorded only on
{{ThingDiscoveryProcess/error}}, but don't affect |promise| any longer.
</p>
</li>
</ol>
</li>
<li>
[=Resolve=] |promise| with |discovery|.
</li>
</ol>
</div>
</section>
<section> <h3>The <dfn>requestThingDescription()</dfn> method</h3>
<pre class="idl">
partial namespace WOT {
Promise<ThingDescription> requestThingDescription(USVString url);
};
</pre>
<div>
Belongs to the <a>WoT Discovery</a> conformance class.
Requests a <a>Thing Description</a> from the given URL.
The method MUST run the following steps:
<ol>
<li>
Return a {{Promise}} |promise:Promise| and execute the next steps [=in parallel=].
</li>
<li>
If invoking this method is not allowed for the current scripting
context for security reasons, [=reject=] |promise| with a {{SecurityError}}
and stop.
</li>
<li>
If requesting a <a>Thing Description</a> is not supported by the
implementation, [=reject=] |promise| with {{NotSupportedError}} and
stop.
</li>
<li>
Let |td:ThingDescription| be the result of making a request to the underlying
platform to retrieve the <a>Thing Description</a> using the
<a>Protocol Binding</a> specified by |url|.
If retrieving |td| fails, [=reject=] |promise| with {{NotFoundError}} and
stop.
</li>
<li>
[=Resolve=] |promise| with |td|.
</li>
</ol>
</div>
</section>
</section> <!-- WoT -->
<section data-cite="webidl"> <h2>Handling interaction data</h2>
<p>
As specified in the [[[wot-thing-description11]]] specification, <a>WoT interactions</a> extend <a>DataSchema</a>
and include a number of possible <a>Form</a>s, out of which one is selected
for the interaction. The
<a data-cite="wot-thing-description11#form">
Form</a> contains a `contentType` to describe the data.
For certain content types, a <a>DataSchema</a> is defined, based on
<a>JSON Schema</a>, making possible to represent these contents as
JavaScript types and eventually set range constraints on the data.
</p>
<section data-dfn-for="InteractionInput">
<h2>The <dfn>InteractionInput</dfn> type</h2>
<pre class="idl">
typedef any DataSchemaValue;
typedef (ReadableStream or DataSchemaValue) InteractionInput;
</pre>
<p>
Belongs to the <a>WoT Consumer</a> conformance class and represents the
<a>WoT Interaction</a> data provided by application scripts to the UA.
</p>
<p>
<dfn>DataSchemaValue</dfn> is an
<a data-cite="ECMASCRIPT#sec-ecmascript-data-types-and-values">ECMAScript value</a> that is accepted for <a>DataSchema</a> defined in [[wot-thing-description11]].
The possible values MUST be of type <a data-cite="ECMASCRIPT#sec-ecmascript-language-types-null-type">null</a>, <a data-cite="ECMASCRIPT#sec-ecmascript-language-types-boolean-type">boolean</a>, <a data-cite="ECMASCRIPT#sec-ecmascript-language-types-number-type">number</a>, <a data-cite="ECMASCRIPT#sec-ecmascript-language-types-string-type">string</a>, <a data-cite="ECMASCRIPT#sec-array-objects">array</a>, or <a data-cite="ECMASCRIPT#sec-object-type">object</a>.
</p>
<p>
{{ReadableStream}} is meant to be used for <a>WoT Interactions</a> that
don't have a <a>DataSchema</a> in the <a>Thing Description</a>, only a
{{Form}}'s `contentType` that can be represented by a stream.
</p>
<p>
In practice, any
<a data-cite="ECMASCRIPT#sec-ecmascript-data-types-and-values">ECMAScript value</a> may be used for <a>WoT Interactions</a> that have a
<a>DataSchema</a> defined in the <a>Thing Description</a>,
or which can be mapped by implementations to the {{Form}}'s `contentType`
defined in the <a>Thing Description</a>.
</p>
<p>
The algorithms in this document specify how exactly input data is used in
<a>WoT Interactions</a>.
</p>
</section>
<section data-dfn-for="InteractionOutput">
<h2>The <dfn>InteractionOutput</dfn> interface</h2>
<p>
Belongs to the <a>WoT Consumer</a> conformance class.
An {{InteractionOutput}} object is always created by the implementations
and exposes the data returned from <a>WoT Interactions</a> to application
scripts.
</p>
<p>
This interface exposes a convenience function which should cover
the vast majority of IoT use cases: the
<a href="#the-value-function">value()</a> function. Its implementation
will inspect the data, parse it if adheres to a <a>DataSchema</a>, 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}}.
</p>
<pre class="idl">
[SecureContext, Exposed=(Window,Worker)]
interface InteractionOutput {
readonly attribute ReadableStream? data;
readonly attribute boolean dataUsed;
readonly attribute Form? form;
readonly attribute DataSchema? schema;
Promise<ArrayBuffer> arrayBuffer();
Promise<DataSchemaValue> value();
};
</pre>
<p>
The <dfn>data</dfn> property represents the raw payload in
<a>WoT Interactions</a> as a {{ReadableStream}}, initially `null`.
</p>
<p>
The <dfn>dataUsed</dfn> property tells whether the data stream has
been <a data-cite="streams#is-readable-stream-disturbed">
disturbed</a>. Initially `false`.
</p>
<p>
The <dfn>form</dfn> attribute represents the <a>Form</a> selected from
the <a>Thing Description</a> for this <a>WoT Interaction</a>,
initially `null`.
</p>
<p>
The <dfn>schema</dfn> attribute represents the <a>DataSchema</a>
(defined in [[wot-thing-description11]]) of the payload as a {{JSON}} object, initially `null`.
</p>
<p>
The <dfn data-lt="value">[[\value]]</dfn> internal slot represents the parsed value of
the <a>WoT Interaction</a>, initially `undefined` (note that `null` is a
valid value).
</p>
<section><h3>The <dfn>value()</dfn> function</h3>
Parses the data returned by the <a>WoT Interaction</a> and returns a
value with the type described by the interaction <a>DataSchema</a>
if that exists, or by the `contentType` of the interaction <a>Form</a>. The method MUST run the following steps:
<ol>
<li>
Return a {{Promise}} |promise:Promise| and execute the next steps
[=in parallel=].
</li>
<li>
If |this|.<a>[[\value]]</a> is not `undefined`, [=resolve=] |promise| with that value and stop.
</li>
<li>
If |this|.|data| is not a {{ReadableStream}} or if
|dataUsed| is `true`, or if |form| is not an {{object}} or if |schema|
is `null` or `undefined`, then
[=reject=] |promise| with {{NotReadableError}} and stop.
</li>
<li>
If |form|.|contentType| is not `application/json` and if a mapping is
not available in the <a>Protocol Bindings</a> from |form|.|contentType|
to [[!JSON-SCHEMA]], [=reject=] |promise| with {{NotSupportedError}} and
stop.
</li>
<li>
Let |reader| be the result of
<a data-cite="streams#readablestream-get-a-reader">
getting a reader</a> from |data|. If that threw an exception, [=reject=]
|promise| with that exception and stop.
</li>
<li>
Let |bytes| be the result of <a data-cite="streams#readablestream-get-a-reader">
reading all bytes</a> from |data| with |reader|.
</li>
<li>
Set |dataUsed| to `true`.
</li>
<li>
If |form|.|contentType| is not `application/json` and if a mapping is
available in the <a>Protocol Bindings</a> from |form|.|contentType|
to [[!JSON-SCHEMA]], transform |bytes| with that mapping.
</li>
<li>
Let |json| be the result of running <a>parse JSON from bytes</a> on
|bytes|. If that throws, [=reject=] |promise| with that exception and
stop.
</li>
<li>
Set <a>[[\value]]</a> to the result of running <a>check data schema</a>
on |json| and |schema|. If that throws, [=reject=] |promise| with that
exception and stop.
</li>
<li>
[=Resolve=] |promise| with <a>[[\value]]</a>.
</li>
</ol>
</section>
<section><h3>The <dfn>arrayBuffer()</dfn> function</h3>
When invoked, MUST run the following steps:
<ol>
<li>