From 9cf49fce70e23b00d399d823b84be654cff76c07 Mon Sep 17 00:00:00 2001 From: Jan Romann Date: Fri, 12 Jan 2024 12:07:40 +0100 Subject: [PATCH 1/5] refactor: use type-checked JS instead of TS for quickstart examples --- examples/quickstart/presence-sensor.js | 17 +- examples/quickstart/simple-coffee-machine.js | 29 ++- examples/quickstart/smart-clock.js | 28 ++- packages/examples/src/quickstart/README.md | 10 - .../src/quickstart/presence-sensor.ts | 64 ------ .../src/quickstart/simple-coffee-machine.ts | 213 ------------------ .../examples/src/quickstart/smart-clock.ts | 97 -------- 7 files changed, 55 insertions(+), 403 deletions(-) delete mode 100644 packages/examples/src/quickstart/README.md delete mode 100644 packages/examples/src/quickstart/presence-sensor.ts delete mode 100644 packages/examples/src/quickstart/simple-coffee-machine.ts delete mode 100644 packages/examples/src/quickstart/smart-clock.ts diff --git a/examples/quickstart/presence-sensor.js b/examples/quickstart/presence-sensor.js index 72670855f..b278094d8 100644 --- a/examples/quickstart/presence-sensor.js +++ b/examples/quickstart/presence-sensor.js @@ -1,4 +1,3 @@ -"use strict"; /******************************************************************************** * Copyright (c) 2023 Contributors to the Eclipse Foundation * @@ -13,13 +12,21 @@ * * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ + +// @ts-check + +"use strict"; + // This is an example Thing script which is a simple presence detector // It fires an event when it detects a person (mocked as every 5 second) -const core_1 = require("@node-wot/core"); -const binding_mqtt_1 = require("@node-wot/binding-mqtt"); + +const { Servient } = require("@node-wot/core"); +const { MqttBrokerServer } = require("@node-wot/binding-mqtt"); + // create Servient add MQTT binding with port configuration -const servient = new core_1.Servient(); -servient.addServer(new binding_mqtt_1.MqttBrokerServer({ uri: "mqtt://test.mosquitto.org" })); +const servient = new Servient(); +servient.addServer(new MqttBrokerServer({ uri: "mqtt://test.mosquitto.org" })); + servient.start().then((WoT) => { WoT.produce({ title: "PresenceSensor", diff --git a/examples/quickstart/simple-coffee-machine.js b/examples/quickstart/simple-coffee-machine.js index 136e3ee1f..d3652c7dd 100644 --- a/examples/quickstart/simple-coffee-machine.js +++ b/examples/quickstart/simple-coffee-machine.js @@ -1,4 +1,3 @@ -"use strict"; /******************************************************************************** * Copyright (c) 2023 Contributors to the Eclipse Foundation * @@ -13,25 +12,39 @@ * * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ + +// @ts-check + +"use strict"; + // This is an example Thing script which is a simple coffee machine. // You can order coffee and see the status of the resources -const core_1 = require("@node-wot/core"); -const binding_http_1 = require("@node-wot/binding-http"); + +const { Servient, Helpers } = require("@node-wot/core"); +const { HttpServer } = require("@node-wot/binding-http"); + // create Servient add HTTP binding with port configuration -const servient = new core_1.Servient(); +const servient = new Servient(); // const staticAddress = "plugfest.thingweb.io"; const staticAddress = "localhost"; // use this for testing locally const httpPort = 8081; servient.addServer( - new binding_http_1.HttpServer({ - port: httpPort, + new HttpServer({ + port: 8081, }) ); -core_1.Helpers.setStaticAddress(staticAddress); + +Helpers.setStaticAddress(staticAddress); + let waterAmount = 1000; let beansAmount = 1000; let milkAmount = 1000; -// promisify timeout since it does not return a promise + +/** + * Function to promisify timeout since it does not return a promise + * + * @param {number} ms + */ function timeout(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } diff --git a/examples/quickstart/smart-clock.js b/examples/quickstart/smart-clock.js index b235c4356..0a7e9e3ab 100644 --- a/examples/quickstart/smart-clock.js +++ b/examples/quickstart/smart-clock.js @@ -1,4 +1,3 @@ -"use strict"; /******************************************************************************** * Copyright (c) 2023 Contributors to the Eclipse Foundation * @@ -13,15 +12,28 @@ * * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 ********************************************************************************/ + +// @ts-check + +"use strict"; + // This is an example Thing which is a smart clock that runs 60 times faster than real time, where 1 hour happens in 1 minute. -const core_1 = require("@node-wot/core"); -const binding_coap_1 = require("@node-wot/binding-coap"); + +const { Servient, Helpers } = require("@node-wot/core"); +const { CoapServer } = require("@node-wot/binding-coap"); + // create Servient add CoAP binding with port configuration -const servient = new core_1.Servient(); -servient.addServer(new binding_coap_1.CoapServer(5686)); -core_1.Helpers.setStaticAddress("plugfest.thingweb.io"); // comment this out if you are testing locally +const servient = new Servient(); +servient.addServer(new CoapServer({ port: 5686 })); + +Helpers.setStaticAddress("plugfest.thingweb.io"); // comment this out if you are testing locally + let minuteCounter = 0; let hourCounter = 0; + +/** + * @param {WoT.ExposedThing} thing + */ async function timeCount(thing) { for (minuteCounter = 0; minuteCounter < 59; minuteCounter++) { // if we have <60, we can get a 15:60. @@ -32,11 +44,13 @@ async function timeCount(thing) { hour: hourCounter, minute: minuteCounter, }); + hourCounter++; if (hourCounter === 24) { hourCounter = 0; } } + servient.start().then((WoT) => { WoT.produce({ title: "Smart Clock", @@ -71,11 +85,13 @@ servient.start().then((WoT) => { minute: minuteCounter, }; }); + timeCount(thing); setInterval(async () => { timeCount(thing); thing.emitPropertyChange("time"); }, 61000); // if this is 60s, we never leave the for loop + // expose the thing thing.expose().then(() => { console.info(thing.getThingDescription().title + " ready"); diff --git a/packages/examples/src/quickstart/README.md b/packages/examples/src/quickstart/README.md deleted file mode 100644 index 0183dad5f..000000000 --- a/packages/examples/src/quickstart/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Quick Start Things - -This set of Things can be used to build mashup applications for a smart home scenario. -These Things are: - -- Simple coffee machine that can take an order to brew a coffee. -- Presence sensor that emits an event when a person is detected. -- Smart clock that runs 60 times faster than real time, where 1 hour happens in 1 minute. - -These Things are hosted on plugfest.thingweb.io but can be also self-hosted. diff --git a/packages/examples/src/quickstart/presence-sensor.ts b/packages/examples/src/quickstart/presence-sensor.ts deleted file mode 100644 index cb6614e01..000000000 --- a/packages/examples/src/quickstart/presence-sensor.ts +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and - * Document License (2015-05-13) which is available at - * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. - * - * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 - ********************************************************************************/ - -// This is an example Thing script which is a simple presence detector -// It fires an event when it detects a person (mocked as every 5 second) - -import { Servient } from "@node-wot/core"; -import { MqttBrokerServer } from "@node-wot/binding-mqtt"; - -// create Servient add MQTT binding with port configuration -const servient = new Servient(); -servient.addServer(new MqttBrokerServer({ uri: "mqtt://test.mosquitto.org" })); - -servient.start().then((WoT) => { - WoT.produce({ - title: "PresenceSensor", - description: "Thing that can detect presence of human nearby", - support: "https://github.com/eclipse-thingweb/node-wot/", - "@context": "https://www.w3.org/2022/wot/td/v1.1", - events: { - presenceDetected: { - title: "Presence Detected", - description: - "An event that is emitted when a person is detected in the room. It is mocked and emitted every 5 seconds", - data: { - type: "number", - title: "Distance", - minimum: 55, - maximum: 1200, - }, - }, - }, - }) - .then((thing) => { - console.log("Produced " + thing.getThingDescription().title); - - // expose the thing - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - - // mocking the detection with an event sent every 5 seconds, with a random distance - setInterval(() => { - const distance: number = Math.random() * (1200 - 55) + 55; - thing.emitEvent("presenceDetected", distance); - console.info("Emitted presence with distance ", distance); - }, 5000); - }); - }) - .catch((e) => { - console.log(e); - }); -}); diff --git a/packages/examples/src/quickstart/simple-coffee-machine.ts b/packages/examples/src/quickstart/simple-coffee-machine.ts deleted file mode 100644 index 69fdc7c2f..000000000 --- a/packages/examples/src/quickstart/simple-coffee-machine.ts +++ /dev/null @@ -1,213 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and - * Document License (2015-05-13) which is available at - * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. - * - * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 - ********************************************************************************/ - -// This is an example Thing script which is a simple coffee machine. -// You can order coffee and see the status of the resources - -import { Servient, Helpers } from "@node-wot/core"; -import { HttpServer } from "@node-wot/binding-http"; - -// create Servient add HTTP binding with port configuration -const servient = new Servient(); - -// const staticAddress = "plugfest.thingweb.io"; -const staticAddress = "localhost"; // use this for testing locally -const httpPort = 8081; -servient.addServer( - new HttpServer({ - port: httpPort, - }) -); -Helpers.setStaticAddress(staticAddress); - -let waterAmount = 1000; -let beansAmount = 1000; -let milkAmount = 1000; - -// promisify timeout since it does not return a promise -function timeout(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -servient.start().then((WoT) => { - WoT.produce({ - title: "Coffee Machine", - description: "A simple coffee machine that can be interacted over the Internet", - support: "https://github.com/eclipse-thingweb/node-wot/", - "@context": "https://www.w3.org/2022/wot/td/v1.1", - properties: { - resources: { - readOnly: true, - observable: true, - type: "object", - properties: { - water: { - type: "integer", - minimum: 0, - maximum: 1000, - }, - beans: { - type: "integer", - minimum: 0, - maximum: 1000, - }, - milk: { - type: "integer", - minimum: 0, - maximum: 1000, - }, - }, - }, - }, - actions: { - brew: { - synchronous: true, - input: { - type: "string", - enum: ["espresso", "cappuccino", "americano"], - }, - }, - refill: { - synchronous: true, - input: { - type: "array", - items: { - type: "string", - enum: ["water", "beans", "milk"], - }, - }, - }, - }, - events: { - resourceEmpty: { - data: { - type: "array", - items: { - type: "string", - enum: ["water", "beans", "milk"], - }, - }, - }, - }, - }) - .then((thing) => { - console.log("Produced " + thing.getThingDescription().title); - - thing.setPropertyReadHandler("resources", async () => { - return { - water: waterAmount, - beans: beansAmount, - milk: milkAmount, - }; - }); - - thing.setActionHandler("brew", async (params, options) => { - const coffeeType = await params.value(); - console.info("received coffee order of ", coffeeType); - if (coffeeType === "espresso") { - if (waterAmount <= 10 || beansAmount <= 10) { - throw new Error("Not enough water or beans"); - } else { - await timeout(1000); - waterAmount = waterAmount - 10; - beansAmount = beansAmount - 10; - thing.emitPropertyChange("resources"); - const resourceEvent: Array = []; - if (waterAmount <= 10) { - resourceEvent.push("water"); - } - if (beansAmount <= 10) { - resourceEvent.push("beans"); - } - if (resourceEvent.length > 0) { - thing.emitEvent("resourceEmpty", resourceEvent); - } - return undefined; - } - } else if (coffeeType === "cappuccino") { - if (waterAmount <= 20 || beansAmount <= 25 || milkAmount <= 15) { - throw new Error("Not enough water or beans"); - } else { - await timeout(2000); - waterAmount = waterAmount - 15; - beansAmount = beansAmount - 20; - milkAmount = milkAmount - 10; - thing.emitPropertyChange("resources"); - const resourceEvent: Array = []; - if (waterAmount <= 10) { - resourceEvent.push("water"); - } - if (beansAmount <= 10) { - resourceEvent.push("beans"); - } - if (milkAmount <= 10) { - resourceEvent.push("milk"); - } - if (resourceEvent.length > 0) { - thing.emitEvent("resourceEmpty", resourceEvent); - } - return undefined; - } - } else if (coffeeType === "americano") { - if (waterAmount <= 35 || beansAmount <= 10) { - throw new Error("Not enough water or beans"); - } else { - await timeout(2000); - waterAmount = waterAmount - 30; - beansAmount = beansAmount - 10; - thing.emitPropertyChange("resources"); - const resourceEvent: Array = []; - if (waterAmount <= 10) { - resourceEvent.push("water"); - } - if (beansAmount <= 10) { - resourceEvent.push("beans"); - } - if (resourceEvent.length > 0) { - thing.emitEvent("resourceEmpty", resourceEvent); - } - return undefined; - } - } else { - throw new Error("Wrong coffee input"); - } - }); - - thing.setActionHandler("refill", async (params, options) => { - const selectedResource = (await params.value()) as Array<"water" | "beans" | "milk">; - console.info("received refill order of ", selectedResource); - if (selectedResource!.indexOf("water") !== -1) { - waterAmount = 1000; - } - if (selectedResource!.indexOf("beans") !== -1) { - beansAmount = 1000; - } - if (selectedResource!.indexOf("milk") !== -1) { - milkAmount = 1000; - } - thing.emitPropertyChange("resources"); - return undefined; - }); - - // expose the thing - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - console.info("TD available at http://" + staticAddress + ":" + httpPort); - }); - }) - .catch((e) => { - console.log(e); - }); -}); diff --git a/packages/examples/src/quickstart/smart-clock.ts b/packages/examples/src/quickstart/smart-clock.ts deleted file mode 100644 index 2043dbcb1..000000000 --- a/packages/examples/src/quickstart/smart-clock.ts +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and - * Document License (2015-05-13) which is available at - * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. - * - * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 - ********************************************************************************/ - -// This is an example Thing which is a smart clock that runs 60 times faster than real time, where 1 hour happens in 1 minute. - -import { Servient, Helpers } from "@node-wot/core"; -import { CoapServer } from "@node-wot/binding-coap"; - -// create Servient add CoAP binding with port configuration -const servient = new Servient(); -servient.addServer(new CoapServer({ port: 5686 })); - -Helpers.setStaticAddress("plugfest.thingweb.io"); // comment this out if you are testing locally - -let minuteCounter = 0; -let hourCounter = 0; - -async function timeCount(thing: WoT.ExposedThing) { - for (minuteCounter = 0; minuteCounter < 59; minuteCounter++) { - // if we have <60, we can get a 15:60. - await new Promise((resolve) => setTimeout(resolve, 1000)); // sleep - thing.emitPropertyChange("time"); - } - console.info({ - hour: hourCounter, - minute: minuteCounter, - }); - - hourCounter++; - if (hourCounter === 24) { - hourCounter = 0; - } -} - -servient.start().then((WoT) => { - WoT.produce({ - title: "Smart Clock", - description: "a smart clock that runs 60 times faster than real time, where 1 hour happens in 1 minute.", - support: "https://github.com/eclipse-thingweb/node-wot/", - "@context": "https://www.w3.org/2022/wot/td/v1.1", - properties: { - time: { - readOnly: true, - observable: true, - type: "object", - properties: { - minute: { - type: "integer", - minimum: 0, - maximum: 59, - }, - hour: { - type: "integer", - minimum: 0, - maximum: 23, - }, - }, - }, - }, - }) - .then(async (thing) => { - console.log("Produced " + thing.getThingDescription().title); - - thing.setPropertyReadHandler("time", async () => { - return { - hour: hourCounter, - minute: minuteCounter, - }; - }); - - timeCount(thing); - setInterval(async () => { - timeCount(thing); - thing.emitPropertyChange("time"); - }, 61000); // if this is 60s, we never leave the for loop - - // expose the thing - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - }); - }) - .catch((e) => { - console.log(e); - }); -}); From 332c6e2ef930c133435a0d99d4ab2e657203102e Mon Sep 17 00:00:00 2001 From: Jan Romann Date: Tue, 27 Feb 2024 11:39:49 +0100 Subject: [PATCH 2/5] fixup! refactor: use type-checked JS instead of TS for quickstart examples --- examples/quickstart/simple-coffee-machine.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/quickstart/simple-coffee-machine.js b/examples/quickstart/simple-coffee-machine.js index d3652c7dd..f3d3187bd 100644 --- a/examples/quickstart/simple-coffee-machine.js +++ b/examples/quickstart/simple-coffee-machine.js @@ -25,12 +25,14 @@ const { HttpServer } = require("@node-wot/binding-http"); // create Servient add HTTP binding with port configuration const servient = new Servient(); + // const staticAddress = "plugfest.thingweb.io"; const staticAddress = "localhost"; // use this for testing locally -const httpPort = 8081; +const port = 8081; + servient.addServer( new HttpServer({ - port: 8081, + port, }) ); @@ -207,7 +209,7 @@ servient.start().then((WoT) => { // expose the thing thing.expose().then(() => { console.info(thing.getThingDescription().title + " ready"); - console.info("TD available at http://" + staticAddress + ":" + httpPort); + console.info("TD available at http://" + staticAddress + ":" + port); }); }) .catch((e) => { From fcbc20fd90cfd1d9e163a3498e037af59bb11eb5 Mon Sep 17 00:00:00 2001 From: Jan Romann Date: Tue, 27 Feb 2024 12:06:15 +0100 Subject: [PATCH 3/5] =?UTF-8?q?fixup!=20refactor:=20use=20type-checked=20J?= =?UTF-8?q?S=20instead=20of=20TS=20for=20quickstart=20exampl=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/quickstart/simple-coffee-machine.js | 21 +++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/examples/quickstart/simple-coffee-machine.js b/examples/quickstart/simple-coffee-machine.js index f3d3187bd..2f73d2722 100644 --- a/examples/quickstart/simple-coffee-machine.js +++ b/examples/quickstart/simple-coffee-machine.js @@ -192,18 +192,29 @@ servient.start().then((WoT) => { } }); thing.setActionHandler("refill", async (params, options) => { - const selectedResource = await params.value(); - console.info("received refill order of ", selectedResource); - if (selectedResource.indexOf("water") !== -1) { + const selectedResources = await params.value(); + + if (!Array.isArray(selectedResources)) { + console.log(`Received invalid refill order of ${selectedResources}`); + return undefined; + } + + console.log(`Received refill order ${selectedResources}`); + + if (!selectedResources.includes("water")) { waterAmount = 1000; } - if (selectedResource.indexOf("beans") !== -1) { + + if (!selectedResources.includes("beans")) { beansAmount = 1000; } - if (selectedResource.indexOf("milk") !== -1) { + + if (!selectedResources.includes("milk")) { milkAmount = 1000; } + thing.emitPropertyChange("resources"); + return undefined; }); // expose the thing From 51d6393be39a4a5e50be3e9f287a34f87cda1115 Mon Sep 17 00:00:00 2001 From: Jan Romann Date: Tue, 27 Feb 2024 12:07:32 +0100 Subject: [PATCH 4/5] =?UTF-8?q?fixup!=20refactor:=20use=20type-checked=20J?= =?UTF-8?q?S=20instead=20of=20TS=20for=20quickstart=20exampl=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/quickstart/simple-coffee-machine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/quickstart/simple-coffee-machine.js b/examples/quickstart/simple-coffee-machine.js index 2f73d2722..9a040e284 100644 --- a/examples/quickstart/simple-coffee-machine.js +++ b/examples/quickstart/simple-coffee-machine.js @@ -220,7 +220,7 @@ servient.start().then((WoT) => { // expose the thing thing.expose().then(() => { console.info(thing.getThingDescription().title + " ready"); - console.info("TD available at http://" + staticAddress + ":" + port); + console.info(`TD available at http://${staticAddress}:${port}/coffee-machine`); }); }) .catch((e) => { From 5f123ea608346424d4bd055efd7b35c18e22ced3 Mon Sep 17 00:00:00 2001 From: Jan Romann Date: Tue, 27 Feb 2024 12:56:17 +0100 Subject: [PATCH 5/5] docs: update URL in quickstart examples README --- examples/quickstart/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/quickstart/README.md b/examples/quickstart/README.md index 0183dad5f..8eb1ea808 100644 --- a/examples/quickstart/README.md +++ b/examples/quickstart/README.md @@ -7,4 +7,4 @@ These Things are: - Presence sensor that emits an event when a person is detected. - Smart clock that runs 60 times faster than real time, where 1 hour happens in 1 minute. -These Things are hosted on plugfest.thingweb.io but can be also self-hosted. +These Things are hosted under https://www.thingweb.io/services, but can also be self-hosted.