From a7f163b4bfe3dd5e5efa30f923e78320c9ae478b Mon Sep 17 00:00:00 2001 From: Patricia Kimmerle <159075491+PFKimmerle@users.noreply.github.com> Date: Thu, 17 Apr 2025 21:19:00 -0700 Subject: [PATCH 1/2] Add Node-WoT client example to README Adds a README section showing how to use Node-WoT to consume Thing Descriptions from a hololinked server. Includes examples for reading/writing properties, invoking actions, and subscribing to events. Based on verified examples. --- README.md | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 43d24e04..24dd1dc9 100644 --- a/README.md +++ b/README.md @@ -338,11 +338,78 @@ If there are errors in generation of Thing Description - run direct ZMQ-TCP server without HTTP details - serve multiple objects with the same HTTP server, run HTTP Server & python object in separate processes or the same process -Again, please check examples or the code for explanations. Documentation is being activety improved. +Again, please check examples or the code for explanations. Documentation is being actively improved. + +### Consuming Thing Descriptions using Node-WoT + +`hololinked` servers expose Thing Descriptions (TDs) which are compatible with Web of Things clients like [Node-WoT](https://github.com/eclipse-thingweb/node-wot). A TD is automatically generated and can be fetched from: + +``` +http://localhost:8000//resources/wot-td +http://localhost:8000//resources/wot-td?ignore_errors=true +``` + +Example TD for a device instance named `spectrometer`: + +``` +http://localhost:8000/spectrometer/resources/wot-td +``` + +Consume this TD in a Node.js script using Node-WoT: + +```js +const { Servient } = require("@node-wot/core"); +const HttpClientFactory = require("@node-wot/binding-http").HttpClientFactory; + +const servient = new Servient(); +servient.addClientFactory(new HttpClientFactory()); + +servient.start().then((WoT) => { + fetch("http://localhost:8000/spectrometer/resources/wot-td") + .then((res) => res.json()) + .then((td) => WoT.consume(td)) + .then((thing) => { + thing.readProperty("integration_time").then(console.log); + }); +}); + +``` +This works with both http:// and https:// URLs. If you're using HTTPS, just make sure the server certificate is valid or trusted by the client. + +After consuming the TD, you can: + +
+Read Property +thing.readProperty("integration_time").then(value => { + console.log("Integration Time:", value); +}); +
+
Write Property +thing.writeProperty("integration_time", 2000).then(() => { + console.log("Integration Time updated"); +}); +
+
+Invoke Action +thing.invokeAction("connect", { serial_number: "S14155" }).then(() => { + console.log("Device connected"); +}); +
+
+Subscribe to Event +thing.subscribeEvent("intensity_measurement_event", (data) => { + console.log("Received event:", data); +}); +
+ +> Based on verified examples from the [hololinked examples repository](https://github.com/hololinked-dev/examples/tree/main/client-examples/node-wot) +> and the [ThingWeb node-wot project](https://github.com/eclipse-thingweb/node-wot). + +In React, these calls can be placed inside `useEffect` and the client passed via `useContext`. ### Contributing See [organization info](https://github.com/hololinked-dev) for details regarding contributing to this package. There is: - discord group - [![Discord](https://img.shields.io/discord/1265289049783140464?label=Discord%20Members&logo=discord)](https://discord.com/invite/kEz87zqQXh) - [weekly meetings](https://github.com/hololinked-dev/#monthly-meetings) and -- [project planning](https://github.com/orgs/hololinked-dev/projects/4) to discuss activities around this repository. \ No newline at end of file +- [project planning](https://github.com/orgs/hololinked-dev/projects/4) to discuss activities around this repository. From 9b0d4aa37e85a53bebdfb4f6a4b9db7dd6f736c7 Mon Sep 17 00:00:00 2001 From: Patricia Kimmerle <159075491+PFKimmerle@users.noreply.github.com> Date: Fri, 18 Apr 2025 16:06:51 -0700 Subject: [PATCH 2/2] Update README.md - Section renamed & reordered - Thing Description URLs added - Online example URL + buffer warning - Example code with details block - React useEffect/useContext usage + links - HTTPS self-signed example added - readProperty async/await fix + explanation --- README.md | 76 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 24dd1dc9..04fc77fb 100644 --- a/README.md +++ b/README.md @@ -317,7 +317,12 @@ See a list of currently supported possibilities while using this package [below] > You may use a script deployment/automation tool to remote stop and start servers, in an attempt to remotely control your hardware scripts. -### A little more about Usage +### Using APIs and Thing Descriptions + +``` +http://localhost:8000//resources/wot-td +http://localhost:8000//resources/wot-td?ignore_errors=true +``` The HTTP API may be autogenerated or adjusted by the user. If your plan is to develop a truly networked system, it is recommended to learn more and use [Thing Descriptions](https://www.w3.org/TR/wot-thing-description11) to describe your hardware (This is optional and one can still use a classic HTTP client). A Thing Description will be automatically generated if absent as shown in JSON examples above or can be supplied manually. The default end point to fetch thing descriptions are:
`http(s):////resources/wot-td`
@@ -326,29 +331,10 @@ If there are errors in generation of Thing Description (client docs will be updated here next, also check official docs) -### Currently Supported - -- control method execution and property write with a custom finite state machine. -- database (Postgres, MySQL, SQLite - based on SQLAlchemy) support for storing and loading properties when the object dies and restarts. -- auto-generate Thing Description for Web of Things applications. -- use serializer of your choice (except for HTTP) - MessagePack, JSON, pickle etc. & extend serialization to suit your requirement. HTTP Server will support only JSON serializer to maintain comptibility with Javascript (MessagePack may be added later). Default is JSON serializer based on msgspec. -- asyncio compatible - async RPC server event-loop and async HTTP Server - write methods in async -- choose from multiple ZeroMQ transport methods which offers some possibilities like the following without changing the code: - - expose only a dashboard or web page on the network without exposing the hardware itself - - run direct ZMQ-TCP server without HTTP details - - serve multiple objects with the same HTTP server, run HTTP Server & python object in separate processes or the same process - -Again, please check examples or the code for explanations. Documentation is being actively improved. - -### Consuming Thing Descriptions using Node-WoT +### Consuming Thing Descriptions using Node-WoT (Javascript) `hololinked` servers expose Thing Descriptions (TDs) which are compatible with Web of Things clients like [Node-WoT](https://github.com/eclipse-thingweb/node-wot). A TD is automatically generated and can be fetched from: -``` -http://localhost:8000//resources/wot-td -http://localhost:8000//resources/wot-td?ignore_errors=true -``` - Example TD for a device instance named `spectrometer`: ``` @@ -369,44 +355,66 @@ servient.start().then((WoT) => { .then((res) => res.json()) .then((td) => WoT.consume(td)) .then((thing) => { - thing.readProperty("integration_time").then(console.log); - }); + thing.readProperty("integration_time").then(async(interactionOutput) => { + console.log("Integration Time: ", await interactionOutput.value()); }); ``` This works with both http:// and https:// URLs. If you're using HTTPS, just make sure the server certificate is valid or trusted by the client. +``` +servient.addClientFactory(new Wot.Http.HttpsClientFactory({ allowSelfSigned : true })) +``` +You can see an example [here](https://gitlab.com/hololinked/examples/clients/node-clients/phymotion-controllers-app/-/blob/main/src/App.tsx?ref_type=heads#L77). + After consuming the TD, you can:
-Read Property + thing.readProperty("integration_time").then(value => { console.log("Integration Time:", value); }); -
-
Write Property + thing.writeProperty("integration_time", 2000).then(() => { console.log("Integration Time updated"); }); -
-
-Invoke Action + thing.invokeAction("connect", { serial_number: "S14155" }).then(() => { console.log("Device connected"); }); -
-
-Subscribe to Event + thing.subscribeEvent("intensity_measurement_event", (data) => { console.log("Received event:", data); });
-> Based on verified examples from the [hololinked examples repository](https://github.com/hololinked-dev/examples/tree/main/client-examples/node-wot) -> and the [ThingWeb node-wot project](https://github.com/eclipse-thingweb/node-wot). +> Based on verified examples from the [hololinked examples repository](https://github.com/hololinked-dev/examples/tree/main/client-examples/node-wot) and the [ThingWeb node-wot project](https://github.com/eclipse-thingweb/node-wot). + +> Note: due to reverse proxy buffering, subscribeEvent may take up to 1 minute to receive data. All other operations work fine. In React, these calls can be placed inside `useEffect` and the client passed via `useContext`. +
+ +For React examples using Node-WoT, refer to: +- [example1](https://gitlab.com/hololinked/examples/clients/node-clients/phymotion-controllers-app/-/blob/main/src/App.tsx?ref_type=heads#L96) +- [example2](https://gitlab.com/hololinked/examples/clients/node-clients/phymotion-controllers-app/-/blob/main/src/components/movements.tsx?ref_type=heads#L54) +
+ +### Currently Supported + +- control method execution and property write with a custom finite state machine. +- database (Postgres, MySQL, SQLite - based on SQLAlchemy) support for storing and loading properties when the object dies and restarts. +- auto-generate Thing Description for Web of Things applications. +- use serializer of your choice (except for HTTP) - MessagePack, JSON, pickle etc. & extend serialization to suit your requirement. HTTP Server will support only JSON serializer to maintain comptibility with Javascript (MessagePack may be added later). Default is JSON serializer based on msgspec. +- asyncio compatible - async RPC server event-loop and async HTTP Server - write methods in async +- choose from multiple ZeroMQ transport methods which offers some possibilities like the following without changing the code: + - expose only a dashboard or web page on the network without exposing the hardware itself + - run direct ZMQ-TCP server without HTTP details + - serve multiple objects with the same HTTP server, run HTTP Server & python object in separate processes or the same process + +Again, please check examples or the code for explanations. Documentation is being actively improved. + ### Contributing See [organization info](https://github.com/hololinked-dev) for details regarding contributing to this package. There is: