From fe43a9c37e23f0183faa3a004b2572c63e71e2db Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Tue, 5 Dec 2023 10:30:23 +0100 Subject: [PATCH 1/6] refactor: favor WoT.requestThingDescription instead of general fetch --- examples/scripts/counter-client.js | 3 +-- examples/scripts/smart-coffee-machine-client.js | 3 +-- examples/security/oauth/consumer.js | 2 +- examples/testthing/testclient.js | 3 +-- packages/examples/src/bindings/coap/example-client.ts | 11 +++-------- packages/examples/src/bindings/http/example-client.ts | 11 +++-------- packages/examples/src/scripts/counter-client.ts | 10 ++-------- .../src/scripts/smart-coffee-machine-client.ts | 8 ++------ packages/examples/src/security/oauth/consumer.ts | 8 ++------ packages/examples/src/testthing/testclient.ts | 9 ++------- 10 files changed, 18 insertions(+), 50 deletions(-) diff --git a/examples/scripts/counter-client.js b/examples/scripts/counter-client.js index d98973408..24c317bc4 100644 --- a/examples/scripts/counter-client.js +++ b/examples/scripts/counter-client.js @@ -26,9 +26,8 @@ function getFormIndexForDecrementWithCoAP(thing) { // return formIndex: 0 if no CoAP target IRI found return 0; } -WoTHelpers.fetch("coap://localhost:5683/counter") +WoT.requestThingDescription("coap://localhost:5683/counter") .then(async (td) => { - // using await for serial execution (note 'async' in then() of fetch()) try { const thing = await WoT.consume(td); console.info("=== TD ==="); diff --git a/examples/scripts/smart-coffee-machine-client.js b/examples/scripts/smart-coffee-machine-client.js index a2ab64378..b8133e139 100644 --- a/examples/scripts/smart-coffee-machine-client.js +++ b/examples/scripts/smart-coffee-machine-client.js @@ -15,7 +15,6 @@ // This is an example of Web of Things consumer ("client" mode) Thing script. // It considers a fictional smart coffee machine in order to demonstrate the capabilities of Web of Things. // An accompanying tutorial is available at http://www.thingweb.io/smart-coffee-machine.html. - // Print data and an accompanying message in a distinguishable way function log(msg, data) { console.info("======================"); @@ -23,7 +22,7 @@ function log(msg, data) { console.dir(data); console.info("======================"); } -WoTHelpers.fetch("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) => { +WoT.requestThingDescription("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) => { try { const thing = await WoT.consume(td); log("Thing Description:", td); diff --git a/examples/security/oauth/consumer.js b/examples/security/oauth/consumer.js index 4fffe323d..c72f27a4d 100644 --- a/examples/security/oauth/consumer.js +++ b/examples/security/oauth/consumer.js @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ -WoTHelpers.fetch("https://localhost:8080/oauth").then((td) => { +WoT.requestThingDescription("https://localhost:8080/oauth").then((td) => { WoT.consume(td).then(async (thing) => { try { const resp = await thing.invokeAction("sayOk"); diff --git a/examples/testthing/testclient.js b/examples/testthing/testclient.js index c0815cd3c..772a2368e 100644 --- a/examples/testthing/testclient.js +++ b/examples/testthing/testclient.js @@ -39,9 +39,8 @@ async function testPropertyWrite(thing, name, value, shouldFail) { else console.info("PASS " + name + " WRITE (" + displayValue + "):", JSON.stringify(err)); } } -WoTHelpers.fetch("http://localhost:8080/testthing") +WoT.requestThingDescription("http://localhost:8080/testthing") .then(async (td) => { - // using await for serial execution (note 'async' in then() of fetch()) try { const thing = await WoT.consume(td); console.info("=== TD ==="); diff --git a/packages/examples/src/bindings/coap/example-client.ts b/packages/examples/src/bindings/coap/example-client.ts index b815f0aac..73b69ceaf 100644 --- a/packages/examples/src/bindings/coap/example-client.ts +++ b/packages/examples/src/bindings/coap/example-client.ts @@ -13,20 +13,15 @@ * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ -import { Servient, Helpers } from "@node-wot/core"; +import { Servient } from "@node-wot/core"; import { CoapClientFactory } from "@node-wot/binding-coap"; -import { ThingDescription } from "wot-typescript-definitions"; // create Servient and add CoAP binding const servient = new Servient(); servient.addClientFactory(new CoapClientFactory()); -const wotHelper = new Helpers(servient); -wotHelper - .fetch("coap://plugfest.thingweb.io:5683/testthing") - .then(async (fetched) => { - const td: ThingDescription = fetched as ThingDescription; - // using await for serial execution (note 'async' in then() of fetch()) +WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing") + .then(async (td) => { try { const WoT = await servient.start(); const thing = await WoT.consume(td); diff --git a/packages/examples/src/bindings/http/example-client.ts b/packages/examples/src/bindings/http/example-client.ts index bab479dda..44f680926 100644 --- a/packages/examples/src/bindings/http/example-client.ts +++ b/packages/examples/src/bindings/http/example-client.ts @@ -13,20 +13,15 @@ * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ -import { Servient, Helpers } from "@node-wot/core"; +import { Servient } from "@node-wot/core"; import { HttpClientFactory } from "@node-wot/binding-http"; -import { ThingDescription } from "wot-typescript-definitions"; // create Servient and add HTTP binding const servient = new Servient(); servient.addClientFactory(new HttpClientFactory()); -const wotHelper = new Helpers(servient); -wotHelper - .fetch("http://plugfest.thingweb.io:8083/testthing") - .then(async (fetched) => { - const td: ThingDescription = fetched as ThingDescription; - // using await for serial execution (note 'async' in then() of fetch()) +WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing") + .then(async (td) => { try { const WoT = await servient.start(); const thing = await WoT.consume(td); diff --git a/packages/examples/src/scripts/counter-client.ts b/packages/examples/src/scripts/counter-client.ts index 41200f950..6e143c617 100644 --- a/packages/examples/src/scripts/counter-client.ts +++ b/packages/examples/src/scripts/counter-client.ts @@ -13,11 +13,6 @@ * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ -import { Helpers } from "@node-wot/core"; -import { ThingDescription } from "wot-typescript-definitions"; - -let WoTHelpers!: Helpers; - function getFormIndexForDecrementWithCoAP(thing: WoT.ConsumedThing): number { const forms = thing.getThingDescription().actions?.decrement.forms; if (forms !== undefined) { @@ -31,11 +26,10 @@ function getFormIndexForDecrementWithCoAP(thing: WoT.ConsumedThing): number { return 0; } -WoTHelpers.fetch("coap://localhost:5683/counter") +WoT.requestThingDescription("coap://localhost:5683/counter") .then(async (td) => { - // using await for serial execution (note 'async' in then() of fetch()) try { - const thing = await WoT.consume(td as ThingDescription); + const thing = await WoT.consume(td); console.info("=== TD ==="); console.info(td); console.info("=========="); diff --git a/packages/examples/src/scripts/smart-coffee-machine-client.ts b/packages/examples/src/scripts/smart-coffee-machine-client.ts index cd51c3690..ab81b579b 100644 --- a/packages/examples/src/scripts/smart-coffee-machine-client.ts +++ b/packages/examples/src/scripts/smart-coffee-machine-client.ts @@ -17,10 +17,6 @@ // It considers a fictional smart coffee machine in order to demonstrate the capabilities of Web of Things. // An accompanying tutorial is available at http://www.thingweb.io/smart-coffee-machine.html. -import { ThingDescription } from "wot-typescript-definitions"; -import { Helpers } from "@node-wot/core"; -let WoTHelpers!: Helpers; - // Print data and an accompanying message in a distinguishable way function log(msg: string, data: unknown) { console.info("======================"); @@ -29,9 +25,9 @@ function log(msg: string, data: unknown) { console.info("======================"); } -WoTHelpers.fetch("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) => { +WoT.requestThingDescription("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) => { try { - const thing = await WoT.consume(td as ThingDescription); + const thing = await WoT.consume(td); log("Thing Description:", td); // Read property allAvailableResources diff --git a/packages/examples/src/security/oauth/consumer.ts b/packages/examples/src/security/oauth/consumer.ts index 8b18127bb..efc4ac090 100644 --- a/packages/examples/src/security/oauth/consumer.ts +++ b/packages/examples/src/security/oauth/consumer.ts @@ -12,13 +12,9 @@ * * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ -import { Helpers } from "@node-wot/core"; -import { ThingDescription } from "wot-typescript-definitions"; -let WoTHelpers!: Helpers; - -WoTHelpers.fetch("https://localhost:8080/oauth").then((td) => { - WoT.consume(td as ThingDescription).then(async (thing) => { +WoT.requestThingDescription("https://localhost:8080/oauth").then((td) => { + WoT.consume(td).then(async (thing) => { try { const resp = await thing.invokeAction("sayOk"); const result = await resp?.value(); diff --git a/packages/examples/src/testthing/testclient.ts b/packages/examples/src/testthing/testclient.ts index 11a7cc8b2..672c387f2 100644 --- a/packages/examples/src/testthing/testclient.ts +++ b/packages/examples/src/testthing/testclient.ts @@ -13,10 +13,6 @@ * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ -import { Helpers } from "@node-wot/core"; -import { ThingDescription } from "wot-typescript-definitions"; -let WoTHelpers!: Helpers; - console.log = () => { /* empty */ }; @@ -51,11 +47,10 @@ async function testPropertyWrite( } } -WoTHelpers.fetch("http://localhost:8080/testthing") +WoT.requestThingDescription("http://localhost:8080/testthing") .then(async (td) => { - // using await for serial execution (note 'async' in then() of fetch()) try { - const thing = await WoT.consume(td as ThingDescription); + const thing = await WoT.consume(td); console.info("=== TD ==="); console.info(td); console.info("=========="); From 598140cf8425ed215b783917906c4679d14a93c7 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Wed, 6 Dec 2023 10:55:04 +0100 Subject: [PATCH 2/6] docs: use requestThingDescription() instead of fetch in examples --- API.md | 10 +++++----- README.md | 5 ++--- packages/binding-coap/README.md | 7 ++----- packages/binding-http/README.md | 7 +------ 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/API.md b/API.md index 761ba12bd..7a9d39e6c 100644 --- a/API.md +++ b/API.md @@ -245,7 +245,7 @@ Interacting with another WoT Thing is called consuming a Thing and works by usin ##### Fetch a Thing Description of a Thing given its URL ```javascript -WoTHelpers.fetch("http://localhost:8080/counter").then(async(td) => { +WoT.requestThingDescription("http://localhost:8080/counter").then(async(td) => { // Do something with the TD } ``` @@ -255,13 +255,13 @@ URLs can have various schemes, including `file://` to read from the local filesy ##### Consume a TD of a Thing, including parsing the TD and generating the protocol bindings in order to access lower level functionality ```javascript -WoTHelpers.fetch("http://localhost:8080/counter").then(async (td) => { +WoT.requestThingDescription("http://localhost:8080/counter").then(async (td) => { let thing = WoT.consume(td); // Do something with the consumed Thing }); ``` -Things can be `consume`d no matter if they were fetched with WoTHelpers or not. +Things can be `consume`d no matter if they were fetched with `WoT.requestThingDescription()`, `WoTHelpers.fetch()` or any other mean. `consume` only requires a TD as an `Object`, so you could also use `fs.readFile` and `JSON.parse` or inline it into your code. As long at it results in a TD Object, you can receive it over Fax, Morse it or use smoke signals. @@ -298,10 +298,10 @@ It is an asynchronous function that will take some time to complete. So you should handle it explicitly. Here we use the `async`/`await` functionality of NodeJS. -Declare the surrounding function as `async`, e.g., the `WoTHelpers.fetch()` resolve handler: +Declare the surrounding function as `async`, e.g., the `WoT.requestThingDescription()` resolve handler: ```javascript -WoTHelpers.fetch(myURI).then(async(td) => { ... }); +WoT.requestThingDescription(myURI).then(async(td) => { ... }); ``` Use `await` to make Promises synchronous (blocking): diff --git a/README.md b/README.md index 7207935f1..e96c1a2a7 100644 --- a/README.md +++ b/README.md @@ -180,14 +180,13 @@ Now supposing you want to interact with the device, you have to consume its Thin ```JavaScript // client.js // Required steps to create a servient for a client -const { Servient, Helpers } = require("@node-wot/core"); +const { Servient } = require("@node-wot/core"); const { HttpClientFactory } = require('@node-wot/binding-http'); const servient = new Servient(); servient.addClientFactory(new HttpClientFactory(null)); -const WoTHelpers = new Helpers(servient); -WoTHelpers.fetch("http://localhost:8080/counter").then(async (td) => { +WoT.requestThingDescription("http://localhost:8080/counter").then(async (td) => { try { const WoT = await servient.start(); // Then from here on you can consume the thing diff --git a/packages/binding-coap/README.md b/packages/binding-coap/README.md index 1ae295e6b..ee72b3782 100644 --- a/packages/binding-coap/README.md +++ b/packages/binding-coap/README.md @@ -26,18 +26,15 @@ The Thing Description is located under the following CoAP URI `coap://plugfest.t ```js // example-client.js -const { Servient, Helpers } = require("@node-wot/core"); +const { Servient } = require("@node-wot/core"); const { CoapClientFactory } = require("@node-wot/binding-coap"); // create Servient and add CoAP binding const servient = new Servient(); servient.addClientFactory(new CoapClientFactory()); -const wotHelper = new Helpers(servient); -wotHelper - .fetch("coap://plugfest.thingweb.io:5683/testthing") +WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing") .then(async (td) => { - // using await for serial execution (note 'async' in then() of fetch()) try { const WoT = await servient.start(); const thing = await WoT.consume(td); diff --git a/packages/binding-http/README.md b/packages/binding-http/README.md index 7a8ae326d..47fce173c 100644 --- a/packages/binding-http/README.md +++ b/packages/binding-http/README.md @@ -29,17 +29,12 @@ The Thing Description is located under the following uri { - // using await for serial execution (note 'async' in then() of fetch()) try { const WoT = await servient.start(); const thing = await WoT.consume(td); From 7009aadccce909910db638fc8b72007a5cf67233 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 7 Dec 2023 10:48:30 +0100 Subject: [PATCH 3/6] docs: fix that WoT needs to be generated/started first --- README.md | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e96c1a2a7..9c0019601 100644 --- a/README.md +++ b/README.md @@ -186,20 +186,15 @@ const { HttpClientFactory } = require('@node-wot/binding-http'); const servient = new Servient(); servient.addClientFactory(new HttpClientFactory(null)); -WoT.requestThingDescription("http://localhost:8080/counter").then(async (td) => { - try { - const WoT = await servient.start(); - // Then from here on you can consume the thing - let thing = await WoT.consume(td); - thing.observeProperty("count", async (data) => { console.log("count:", await data.value()); }); - for (let i = 0; i < 5; i++) { - await thing.invokeAction("increment"); - } - } - catch (err) { - console.error("Script error:", err); +servient.start().then(async (WoT) => { + const td = await WoT.requestThingDescription("http://localhost:8080/counter"); + // Then from here on you can consume the thing + let thing = await WoT.consume(td); + thing.observeProperty("count", async (data) => { console.log("count:", await data.value()); }); + for (let i = 0; i < 5; i++) { + await thing.invokeAction("increment"); } -}).catch((err) => { console.error("Fetch error:", err); }); +}).catch((err) => { console.error("Error:", err); }); ``` If you execute both scripts you will see `count: ${count}` printed 5 times. We host a more complex version of this example at [http://plugfest.thingweb.io/examples/counter.html](http://plugfest.thingweb.io/examples/counter.html) and you can find the source code in the [counter example](./examples/browser) folder. You can also find more examples in the [examples folder](./examples/scripts) for JavaScript and in the [examples folder](./packages/examples/) for TypeScript. Finally, for your convenience, we host a set of online Things that you can use to test your applications. You can find more information about them in the [Online Things](#online-things) section. From 4c630a43f0b994ad8b5bb23cce09bb7444dd7e0e Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 7 Dec 2023 10:59:16 +0100 Subject: [PATCH 4/6] docs: fix examples for CoAP and HTTP w.r.t servient.start() --- packages/examples/src/bindings/coap/example-client.ts | 9 +++++---- packages/examples/src/bindings/http/example-client.ts | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/examples/src/bindings/coap/example-client.ts b/packages/examples/src/bindings/coap/example-client.ts index 73b69ceaf..6e03307fd 100644 --- a/packages/examples/src/bindings/coap/example-client.ts +++ b/packages/examples/src/bindings/coap/example-client.ts @@ -20,10 +20,11 @@ import { CoapClientFactory } from "@node-wot/binding-coap"; const servient = new Servient(); servient.addClientFactory(new CoapClientFactory()); -WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing") - .then(async (td) => { +servient + .start() + .then(async (WoT) => { try { - const WoT = await servient.start(); + const td = await WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing"); const thing = await WoT.consume(td); // read property @@ -34,5 +35,5 @@ WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing") } }) .catch((err) => { - console.error("Fetch error:", err); + console.error("Start error:", err); }); diff --git a/packages/examples/src/bindings/http/example-client.ts b/packages/examples/src/bindings/http/example-client.ts index 44f680926..417f83de3 100644 --- a/packages/examples/src/bindings/http/example-client.ts +++ b/packages/examples/src/bindings/http/example-client.ts @@ -20,10 +20,11 @@ import { HttpClientFactory } from "@node-wot/binding-http"; const servient = new Servient(); servient.addClientFactory(new HttpClientFactory()); -WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing") - .then(async (td) => { +servient + .start() + .then(async (WoT) => { try { - const WoT = await servient.start(); + const td = await WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing"); const thing = await WoT.consume(td); // read property @@ -34,5 +35,5 @@ WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing") } }) .catch((err) => { - console.error("Fetch error:", err); + console.error("Start error:", err); }); From 7bc7e889725f715e8c518c724a285db69d0f3dc9 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 7 Dec 2023 11:11:04 +0100 Subject: [PATCH 5/6] docs: fix missing start() --- packages/binding-coap/README.md | 9 +++++---- packages/binding-http/README.md | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/binding-coap/README.md b/packages/binding-coap/README.md index ee72b3782..1562f44ec 100644 --- a/packages/binding-coap/README.md +++ b/packages/binding-coap/README.md @@ -33,10 +33,11 @@ const { CoapClientFactory } = require("@node-wot/binding-coap"); const servient = new Servient(); servient.addClientFactory(new CoapClientFactory()); -WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing") - .then(async (td) => { +servient + .start() + .then(async (WoT) => { try { - const WoT = await servient.start(); + const td = await WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing"); const thing = await WoT.consume(td); // read property @@ -47,7 +48,7 @@ WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing") } }) .catch((err) => { - console.error("Fetch error:", err); + console.error("Start error:", err); }); ``` diff --git a/packages/binding-http/README.md b/packages/binding-http/README.md index 47fce173c..12eb3c3b6 100644 --- a/packages/binding-http/README.md +++ b/packages/binding-http/README.md @@ -33,10 +33,11 @@ HttpClientFactory = require("@node-wot/binding-http").HttpClientFactory; let servient = new Servient(); servient.addClientFactory(new HttpClientFactory(null)); -WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing") - .then(async (td) => { +servient + .start() + .then(async (WoT) => { try { - const WoT = await servient.start(); + const td = await WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing"); const thing = await WoT.consume(td); // read property @@ -47,7 +48,7 @@ WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing") } }) .catch((err) => { - console.error("Fetch error:", err); + console.error("Start error:", err); }); ``` From 237b02cdfffd223dc2d5672b99a24dc01a3526d6 Mon Sep 17 00:00:00 2001 From: danielpeintner Date: Thu, 7 Dec 2023 11:34:35 +0100 Subject: [PATCH 6/6] docs: remove error prefix as suggest by @JKRhb --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c0019601..1509eafbb 100644 --- a/README.md +++ b/README.md @@ -194,7 +194,7 @@ servient.start().then(async (WoT) => { for (let i = 0; i < 5; i++) { await thing.invokeAction("increment"); } -}).catch((err) => { console.error("Error:", err); }); +}).catch((err) => { console.error(err); }); ``` If you execute both scripts you will see `count: ${count}` printed 5 times. We host a more complex version of this example at [http://plugfest.thingweb.io/examples/counter.html](http://plugfest.thingweb.io/examples/counter.html) and you can find the source code in the [counter example](./examples/browser) folder. You can also find more examples in the [examples folder](./examples/scripts) for JavaScript and in the [examples folder](./packages/examples/) for TypeScript. Finally, for your convenience, we host a set of online Things that you can use to test your applications. You can find more information about them in the [Online Things](#online-things) section.