diff --git a/package-lock.json b/package-lock.json index ffa1eafb3..9c8ba8ee2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "./packages/core", "./packages/binding-!()", "./packages/cli", + "./packages/examples", "./packages/browser-bundle" ], "devDependencies": { @@ -324,6 +325,14 @@ "resolved": "packages/binding-http", "link": true }, + "node_modules/@node-wot/binding-mbus": { + "resolved": "packages/binding-mbus", + "link": true + }, + "node_modules/@node-wot/binding-modbus": { + "resolved": "packages/binding-modbus", + "link": true + }, "node_modules/@node-wot/binding-mqtt": { "resolved": "packages/binding-mqtt", "link": true @@ -396,6 +405,265 @@ "integrity": "sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA==", "license": "MIT" }, + "node_modules/@serialport/binding-abstract": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-9.2.3.tgz", + "integrity": "sha512-cQs9tbIlG3P0IrOWyVirqlhWuJ7Ms2Zh9m2108z6Y5UW/iVj6wEOiW8EmK9QX9jmJXYllE7wgGgvVozP5oCj3w==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/binding-mock": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-9.2.4.tgz", + "integrity": "sha512-dpEhACCs44oQhh6ajJfJdvQdK38Vq0N4W6iD/gdplglDCK7qXRQCMUjJIeKdS/HSEiWkC3bwumUhUufdsOyT4g==", + "license": "MIT", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-9.2.8.tgz", + "integrity": "sha512-hSLxTe0tADZ3LMMGwvEJWOC/TaFQTyPeFalUCsJ1lSQ0k6bPF04JwrtB/C81GetmDBTNRY0GlD0SNtKCc7Dr5g==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@serialport/binding-abstract": "9.2.3", + "@serialport/parser-readline": "9.2.4", + "bindings": "^1.5.0", + "debug": "^4.3.2", + "nan": "^2.15.0", + "prebuild-install": "^7.0.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/bindings/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@serialport/bindings/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/@serialport/bindings/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@serialport/bindings/node_modules/nan": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", + "license": "MIT" + }, + "node_modules/@serialport/bindings/node_modules/node-abi": { + "version": "3.65.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", + "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@serialport/bindings/node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@serialport/bindings/node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/@serialport/parser-byte-length": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-9.2.4.tgz", + "integrity": "sha512-sQD/iw4ZMU3xW9PLi0/GlvU6Y623jGeWecbMkO7izUo/6P7gtfv1c9ikd5h0kwL8AoAOpQA1lxdHIKox+umBUg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-cctalk": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-9.2.4.tgz", + "integrity": "sha512-T4TU5vQMwmo9AB3gQLFDWbfJXlW5jd9guEsB/nqKjFHTv0FXPdZ7DQ2TpSp8RnHWxU3GX6kYTaDO20BKzc8GPQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-delimiter": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-9.2.4.tgz", + "integrity": "sha512-4nvTAoYAgkxFiXrkI+3CA49Yd43CODjeszh89EK+I9c8wOZ+etZduRCzINYPiy26g7zO+GRAb9FoPCsY+sYcbQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-inter-byte-timeout": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-9.2.4.tgz", + "integrity": "sha512-SOAdvr0oBQIOCXX198hiTlxs4JTKg9j5piapw5tNq52fwDOWdbYrFneT/wN04UTMKaDrJuEvXq6T4rv4j7nJ5A==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-readline": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-9.2.4.tgz", + "integrity": "sha512-Z1/qrZTQUVhNSJP1hd9YfDvq0o7d87rNwAjjRKbVpa7Qi51tG5BnKt43IV3NFMyBlVcRe0rnIb3tJu57E0SOwg==", + "license": "MIT", + "dependencies": { + "@serialport/parser-delimiter": "9.2.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-ready": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-9.2.4.tgz", + "integrity": "sha512-Pyi94Itjl6qAURwIZr/gmZpMAyTmKXThm6vL5DoAWGQjcRHWB0gwv2TY2v7N+mQLJYUKU3cMnvnATXxHm7xjxw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/parser-regex": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-9.2.4.tgz", + "integrity": "sha512-sI/cVvPOYz+Dbv4ZdnW16qAwvXiFf/1pGASQdbveRTlgJDdz7sRNlCBifzfTN2xljwvCTZYqiudKvDdC1TepRQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, + "node_modules/@serialport/stream": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-9.2.4.tgz", + "integrity": "sha512-bLye8Ub4vUFQGmkh8qEqehr7SE7EJs2yDs0h9jzuL5oKi+F34CFmWkEErO8GAOQ8YNn7p6b3GxUgs+0BrHHDZQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, "node_modules/@servie/events": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@servie/events/-/events-1.0.0.tgz", @@ -1776,7 +2044,6 @@ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "license": "MIT", - "optional": true, "dependencies": { "file-uri-to-path": "1.0.0" } @@ -2533,8 +2800,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC", - "optional": true + "license": "ISC" }, "node_modules/cipher-base": { "version": "1.0.4", @@ -3163,7 +3429,6 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "license": "MIT", - "optional": true, "engines": { "node": ">=4.0.0" } @@ -4390,7 +4655,6 @@ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "license": "(MIT OR WTFPL)", - "optional": true, "engines": { "node": ">=6" } @@ -4632,8 +4896,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/fill-range": { "version": "7.1.1", @@ -4878,8 +5141,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -5109,8 +5371,7 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/glob": { "version": "7.2.0", @@ -5614,8 +5875,7 @@ "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "license": "ISC", - "optional": true + "license": "ISC" }, "node_modules/inline-source-map": { "version": "0.6.3", @@ -6592,7 +6852,6 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "devOptional": true, "license": "MIT" }, "node_modules/mlly": { @@ -6734,6 +6993,16 @@ "node": ">=10" } }, + "node_modules/modbus-serial": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/modbus-serial/-/modbus-serial-8.0.3.tgz", + "integrity": "sha512-ozrTOVPHEjof1JdVSwvtIe+qrkexoU4Xz/FiEcss81W1dngqfZqwnHu9WS+GOgM0Hu8I/nu08TFKbCefVUDh0w==", + "license": "ISC", + "dependencies": { + "debug": "^4.1.1", + "serialport": "^9.0.0" + } + }, "node_modules/module-deps": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz", @@ -7052,8 +7321,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -7191,6 +7459,27 @@ } } }, + "node_modules/node-mbus": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/node-mbus/-/node-mbus-2.2.4.tgz", + "integrity": "sha512-xFNx+tgLb7mxL3K1CX+LufoBYUq4Zmu/3NyTBV75tQXkk706+dgBloopm7Pnd0x4Cut/6e6lD4HVw/01qgpYog==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.19.0", + "xml2js": "^0.6.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/node-mbus/node_modules/nan": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", + "license": "MIT" + }, "node_modules/node-netconf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/node-netconf/-/node-netconf-1.1.2.tgz", @@ -7202,6 +7491,19 @@ "xml2js": "^0.4.23" } }, + "node_modules/node-netconf/node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/nofilter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", @@ -8015,7 +8317,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "devOptional": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -8162,7 +8463,6 @@ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "optional": true, "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", @@ -8178,7 +8478,6 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "license": "MIT", - "optional": true, "engines": { "node": ">=0.10.0" } @@ -8643,6 +8942,31 @@ "randombytes": "^2.1.0" } }, + "node_modules/serialport": { + "version": "9.2.8", + "resolved": "https://registry.npmjs.org/serialport/-/serialport-9.2.8.tgz", + "integrity": "sha512-FsWpMQgSJxi93JgWl5xM1f9/Z8IjRJuaUEoHqLf8FPBLw7gMhInuHOBhI2onQufWIYPGTz3H3oGcu1nCaK1EfA==", + "license": "MIT", + "dependencies": { + "@serialport/binding-mock": "9.2.4", + "@serialport/bindings": "9.2.8", + "@serialport/parser-byte-length": "9.2.4", + "@serialport/parser-cctalk": "9.2.4", + "@serialport/parser-delimiter": "9.2.4", + "@serialport/parser-inter-byte-timeout": "9.2.4", + "@serialport/parser-readline": "9.2.4", + "@serialport/parser-ready": "9.2.4", + "@serialport/parser-regex": "9.2.4", + "@serialport/stream": "9.2.4", + "debug": "^4.3.2" + }, + "engines": { + "node": ">=10.0.0" + }, + "funding": { + "url": "https://opencollective.com/serialport/donate" + } + }, "node_modules/serve-static": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", @@ -8805,7 +9129,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "devOptional": true, "funding": [ { "type": "github", @@ -9290,7 +9613,6 @@ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "license": "MIT", - "optional": true, "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", @@ -9303,7 +9625,6 @@ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", - "optional": true, "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -9320,7 +9641,6 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", - "optional": true, "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -9346,7 +9666,6 @@ } ], "license": "MIT", - "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -9841,7 +10160,6 @@ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "license": "Apache-2.0", - "optional": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -10511,9 +10829,9 @@ } }, "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", "license": "MIT", "dependencies": { "sax": ">=0.6.0", @@ -10688,6 +11006,29 @@ "timekeeper": "^2.2.0" } }, + "packages/binding-mbus": { + "name": "@node-wot/binding-mbus", + "version": "0.8.15", + "license": "EPL-2.0 OR W3C-20150513", + "dependencies": { + "@node-wot/core": "0.8.15", + "@node-wot/td-tools": "0.8.15", + "node-mbus": "^2.1.0", + "wot-typescript-definitions": "0.8.0-SNAPSHOT.29" + } + }, + "packages/binding-modbus": { + "name": "@node-wot/binding-modbus", + "version": "0.8.15", + "license": "EPL-2.0 OR W3C-20150513", + "dependencies": { + "@node-wot/core": "0.8.15", + "@node-wot/td-tools": "0.8.15", + "modbus-serial": "8.0.3", + "rxjs": "5.5.11", + "wot-typescript-definitions": "0.8.0-SNAPSHOT.29" + } + }, "packages/binding-mqtt": { "name": "@node-wot/binding-mqtt", "version": "0.8.15", @@ -10786,8 +11127,6 @@ }, "packages/cli/node_modules/commander": { "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "license": "MIT", "engines": { "node": "^12.20.0 || >=14" diff --git a/package.json b/package.json index c795cd2ed..d3bee8f0a 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@types/chai-as-promised": "^7.1.4", "@types/chai-spies": "^1.0.4", "@types/mocha": "^9.0.0", + "@types/multicast-dns": "^7.2.4", "@types/node": "16.18.35", "@types/readable-stream": "^4.0.15", "@types/sinon": "10.0.2", diff --git a/packages/examples/.eslintrc.json b/packages/examples/.eslintrc.json deleted file mode 100644 index c4237119e..000000000 --- a/packages/examples/.eslintrc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../.eslintrc.js" -} diff --git a/packages/examples/README.md b/packages/examples/README.md deleted file mode 100644 index 6f0bc04b0..000000000 --- a/packages/examples/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# node-wot Examples - -## Script Examples - -Script examples are located in - -- `src\scripts` -- `src\testthing` - -The idea of these folders is to use TypeScript to work on the examples which offers support in being up-to-date with the current API. - -see https://github.com/eclipse-thingweb/node-wot/issues/171. - -### Workflow - -1. Run `npm run build` -2. Remove the following 3/4 lines in JS files of folder `dist/` - -``` -Object.defineProperty(exports, "__esModule", { value: true }); -require("wot-typescript-definitions"); -let WoT; -let WoTHelpers; -``` - -3. Copy the according JS file(s) to - -- `/examples/scripts` -- `/examples/testthing` - -## Test Thing - -Test thing and client is located in `src\testthing`. diff --git a/packages/examples/package.json b/packages/examples/package.json deleted file mode 100644 index 8df22de40..000000000 --- a/packages/examples/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "@node-wot/examples", - "version": "0.8.15", - "private": true, - "description": "Examples for node-wot (not published)", - "author": "Eclipse Thingweb (https://thingweb.io/)", - "license": "EPL-2.0 OR W3C-20150513", - "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/examples", - "dependencies": { - "@node-wot/binding-coap": "0.8.15", - "@node-wot/binding-file": "0.8.15", - "@node-wot/binding-http": "0.8.15", - "@node-wot/binding-mqtt": "0.8.15", - "@node-wot/binding-opcua": "0.8.15", - "@node-wot/core": "0.8.15", - "@node-wot/td-tools": "0.8.15", - "rxjs": "5.5.11" - }, - "scripts": { - "build": "tsc -b", - "lint": "eslint .", - "lint:fix": "eslint . --fix", - "format": "prettier --write \"src/**/*.ts\" \"**/*.json\"" - }, - "bugs": { - "url": "https://github.com/eclipse-thingweb/node-wot/issues" - }, - "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/examples#readme", - "main": "index.js", - "keywords": [] -} diff --git a/packages/examples/src/bindings/coap/example-client.ts b/packages/examples/src/bindings/coap/example-client.ts deleted file mode 100644 index 6e03307fd..000000000 --- a/packages/examples/src/bindings/coap/example-client.ts +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -import { Servient } from "@node-wot/core"; -import { CoapClientFactory } from "@node-wot/binding-coap"; - -// create Servient and add CoAP binding -const servient = new Servient(); -servient.addClientFactory(new CoapClientFactory()); - -servient - .start() - .then(async (WoT) => { - try { - const td = await WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing"); - const thing = await WoT.consume(td); - - // read property - const read1 = await thing.readProperty("string"); - console.log("string value is: ", await read1.value()); - } catch (err) { - console.error("Script error:", err); - } - }) - .catch((err) => { - console.error("Start error:", err); - }); diff --git a/packages/examples/src/bindings/coap/example-server.ts b/packages/examples/src/bindings/coap/example-server.ts deleted file mode 100644 index 4e7f528f9..000000000 --- a/packages/examples/src/bindings/coap/example-server.ts +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -import { Servient } from "@node-wot/core"; -import { CoapServer } from "@node-wot/binding-coap"; - -// create Servient add HTTP binding -const servient = new Servient(); -servient.addServer(new CoapServer()); - -servient.start().then((WoT) => { - WoT.produce({ - title: "MyCounter", - properties: { - count: { - type: "integer", - }, - }, - }).then((thing) => { - let count = 0; - - console.log("Produced " + thing.getThingDescription().title); - - // set property handlers (using async-await) - thing.setPropertyReadHandler("count", async () => count); - thing.setPropertyWriteHandler("count", async (intOutput) => { - const value = await intOutput.value(); - if (typeof value === "number") { - count = value; - } - }); - - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - console.info("TD : " + JSON.stringify(thing.getThingDescription())); - }); - }); -}); diff --git a/packages/examples/src/bindings/http/example-client.ts b/packages/examples/src/bindings/http/example-client.ts deleted file mode 100644 index 417f83de3..000000000 --- a/packages/examples/src/bindings/http/example-client.ts +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -import { Servient } from "@node-wot/core"; -import { HttpClientFactory } from "@node-wot/binding-http"; - -// create Servient and add HTTP binding -const servient = new Servient(); -servient.addClientFactory(new HttpClientFactory()); - -servient - .start() - .then(async (WoT) => { - try { - const td = await WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing"); - const thing = await WoT.consume(td); - - // read property - const read1 = await thing.readProperty("string"); - console.log("string value is: ", await read1.value()); - } catch (err) { - console.error("Script error:", err); - } - }) - .catch((err) => { - console.error("Start error:", err); - }); diff --git a/packages/examples/src/bindings/http/example-server-secure.ts b/packages/examples/src/bindings/http/example-server-secure.ts deleted file mode 100644 index ee69cd675..000000000 --- a/packages/examples/src/bindings/http/example-server-secure.ts +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -import { Servient } from "@node-wot/core"; -import { HttpServer } from "@node-wot/binding-http"; - -// create secure Servient with username & password credentials -const servient = new Servient(); -servient.addCredentials({ - "urn:dev:wot:org:eclipse:thingweb:my-example-secure": { - username: "node-wot", - password: "hello", - // token: "1/mZ1edKKACtPAb7zGlwSzvs72PvhAbGmB8K1ZrGxpcNM" - }, -}); -const httpConfig = { - allowSelfSigned: true, // client configuration - serverKey: "privatekey.pem", - serverCert: "certificate.pem", - security: [ - { - scheme: "basic", // (username & password) - }, - ], -}; -// add HTTPS binding with configuration -servient.addServer(new HttpServer(httpConfig)); - -servient.start().then((WoT) => { - WoT.produce({ - title: "MyCounter", - properties: { - count: { - type: "integer", - }, - }, - }).then((thing) => { - // init property value - let count = 0; - - console.log("Produced " + thing.getThingDescription().title); - - // set property handlers (using async-await) - thing.setPropertyReadHandler("count", async () => count); - thing.setPropertyWriteHandler("count", async (intOutput) => { - const value = await intOutput.value(); - if (typeof value === "number") { - count = value; - } - }); - - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - console.info("TD : " + JSON.stringify(thing.getThingDescription())); - }); - }); -}); diff --git a/packages/examples/src/bindings/http/example-server.ts b/packages/examples/src/bindings/http/example-server.ts deleted file mode 100644 index a1441017e..000000000 --- a/packages/examples/src/bindings/http/example-server.ts +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -import { Servient } from "@node-wot/core"; -import { HttpServer } from "@node-wot/binding-http"; - -// create Servient add HTTP binding with port configuration -const servient = new Servient(); -servient.addServer( - new HttpServer({ - port: 8081, // (default 8080) - urlRewrite: { - "/myroot/foo/cnt": "/mycounter/properties/count", - "/mysecondURL/for/the/same/resource": "/mycounter/properties/count", - }, - }) -); - -servient.start().then((WoT) => { - WoT.produce({ - title: "MyCounter", - properties: { - count: { - type: "integer", - }, - }, - }).then((thing) => { - // init property value - let count = 0; - - console.log("Produced " + thing.getThingDescription().title); - - // set property handlers (using async-await) - thing.setPropertyReadHandler("count", async () => count); - thing.setPropertyWriteHandler("count", async (intOutput) => { - const value = await intOutput.value(); - if (typeof value === "number") { - count = value; - } - }); - - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - console.info("TD : " + JSON.stringify(thing.getThingDescription())); - }); - }); -}); diff --git a/packages/examples/src/bindings/opcua/demo-opcua-thing-description.ts b/packages/examples/src/bindings/opcua/demo-opcua-thing-description.ts deleted file mode 100644 index d015cef1d..000000000 --- a/packages/examples/src/bindings/opcua/demo-opcua-thing-description.ts +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -const endpointUrl = "opc.tcp://opcuademo.sterfive.com:26543"; -export const thingDescription: WoT.ThingDescription = { - "@context": "https://www.w3.org/2019/wot/td/v1", - "@type": ["Thing"], - securityDefinitions: { - nosec_sc: { - scheme: "nosec", - }, - }, - security: "nosec_sc", - title: "servient", - description: "node-wot CLI Servient", - properties: { - pumpSpeed: { - description: "the pump speed", - observable: true, - readOnly: true, - unit: "m/s", - type: "number", - forms: [ - { - href: endpointUrl, - op: ["readproperty", "observeproperty"], - "opcua:nodeId": "ns=1;s=PumpSpeed", - }, - ], - }, - temperature: { - description: "the temperature", - observable: true, - readOnly: true, - unit: "m/s", - type: "number", - forms: [ - { - href: endpointUrl, - op: ["readproperty", "observeproperty"], - "opcua:nodeId": "ns=1;s=Temperature", - }, - ], - }, - }, -}; diff --git a/packages/examples/src/bindings/opcua/demo-opcua1.ts b/packages/examples/src/bindings/opcua/demo-opcua1.ts deleted file mode 100644 index 3f58c1e34..000000000 --- a/packages/examples/src/bindings/opcua/demo-opcua1.ts +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -import { Servient } from "@node-wot/core"; -import { OPCUAClientFactory } from "@node-wot/binding-opcua"; - -import { thingDescription } from "./demo-opcua-thing-description"; -(async () => { - const servient = new Servient(); - servient.addClientFactory(new OPCUAClientFactory()); - - const wot = await servient.start(); - const thing = await wot.consume(thingDescription); - - const content = await thing.readProperty("pumpSpeed"); - const pumpSpeed = await content.value(); - - console.log("------------------------------"); - console.log("Pump Speed is : ", pumpSpeed, "m/s"); - console.log("------------------------------"); - - await servient.shutdown(); -})(); diff --git a/packages/examples/src/bindings/opcua/demo-opcua2.ts b/packages/examples/src/bindings/opcua/demo-opcua2.ts deleted file mode 100644 index c1a95981c..000000000 --- a/packages/examples/src/bindings/opcua/demo-opcua2.ts +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ -import { Servient } from "@node-wot/core"; -import { OPCUAClientFactory } from "@node-wot/binding-opcua"; -import { thingDescription } from "./demo-opcua-thing-description"; - -(async () => { - const servient = new Servient(); - servient.addClientFactory(new OPCUAClientFactory()); - - const wot = await servient.start(); - const thing = await wot.consume(thingDescription); - - thing.observeProperty("temperature", async (data) => { - const temperature = await data.value(); - console.log("------------------------------"); - console.log("temperature : ", temperature, "m/s"); - console.log("------------------------------"); - }); - - await new Promise((resolve) => setTimeout(resolve, 10000)); - - await servient.shutdown(); -})(); diff --git a/packages/examples/src/bindings/opcua/opcua-coffee-machine-demo.ts b/packages/examples/src/bindings/opcua/opcua-coffee-machine-demo.ts deleted file mode 100644 index 1596eac1a..000000000 --- a/packages/examples/src/bindings/opcua/opcua-coffee-machine-demo.ts +++ /dev/null @@ -1,50 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ -import { Servient } from "@node-wot/core"; -import { OPCUAClientFactory } from "@node-wot/binding-opcua"; -import { thingDescription } from "./opcua-coffee-machine-thing-description"; - -const pause = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); -(async () => { - const servient = new Servient(); - servient.addClientFactory(new OPCUAClientFactory()); - - const wot = await servient.start(); - const thing = await wot.consume(thingDescription); - - try { - thing.observeProperty("waterTankLevel", async (data) => { - const waterTankLevel = await data.value(); - console.log("------------------------------"); - console.log("tankLevel : ", waterTankLevel, "ml"); - console.log("------------------------------"); - }); - thing.observeProperty("coffeeBeanLevel", async (data) => { - const coffeBeanLevel = await data.value(); - console.log("------------------------------"); - console.log("bean level : ", coffeBeanLevel, "g"); - console.log("------------------------------"); - }); - await thing.invokeAction("brewCoffee", { CoffeeType: 1 }); - await pause(5000); - await thing.invokeAction("brewCoffee", { CoffeeType: 0 }); - await pause(5000); - - await thing.invokeAction("fillTank"); - await pause(5000); - } finally { - await servient.shutdown(); - } -})(); diff --git a/packages/examples/src/bindings/opcua/opcua-coffee-machine-thing-description.ts b/packages/examples/src/bindings/opcua/opcua-coffee-machine-thing-description.ts deleted file mode 100644 index 099a92566..000000000 --- a/packages/examples/src/bindings/opcua/opcua-coffee-machine-thing-description.ts +++ /dev/null @@ -1,112 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2022 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 - ********************************************************************************/ - -const endpointUrl = "opc.tcp://opcuademo.sterfive.com:26543"; -export const thingDescription: WoT.ThingDescription = { - "@context": "https://www.w3.org/2019/wot/td/v1", - "@type": ["Thing"], - securityDefinitions: { - nosec_sc: { - scheme: "nosec", - }, - }, - security: "nosec_sc", - title: "servient", - description: "node-wot CLI Servient", - properties: { - deviceHealth: { - // type: "number", - observable: true, - readOnly: true, - forms: [ - { - href: endpointUrl, - op: ["readproperty", "observeproperty"], - "opcua:nodeId": { - root: "i=84", - path: "/Objects/2:DeviceSet/2:DeviceHealth", - }, - }, - ], - }, - waterTankLevel: { - // type: "number", - observable: true, - readOnly: true, - forms: [ - { - href: endpointUrl, - op: ["readproperty", "observeproperty"], - "opcua:nodeId": { - root: "i=84", - path: "/Objects/2:DeviceSet/1:CoffeeMachine/2:ParameterSet/9:WaterTankLevel", - }, - }, - ], - }, - coffeeBeanLevel: { - // type: "number", - observable: true, - readOnly: true, - forms: [ - { - href: endpointUrl, - op: ["readproperty", "observeproperty"], - "opcua:nodeId": { - root: "i=84", - path: "/Objects/2:DeviceSet/1:CoffeeMachine/2:ParameterSet/9:CoffeeBeanLevel", - }, - }, - ], - }, - }, - actions: { - brewCoffee: { - forms: [ - { - type: "object", - href: endpointUrl, - op: ["invokeaction"], - "opcua:nodeId": { root: "i=84", path: "/Objects/2:DeviceSet/1:CoffeeMachine" }, - "opcua:method": { root: "i=84", path: "/Objects/2:DeviceSet/1:CoffeeMachine/2:MethodSet/9:Start" }, - }, - ], - input: { - type: "object", - properties: { - CoffeeType: { - title: "1 for Americano, 2 for Expressp", - type: "number", - }, - }, - required: ["CoffeeType"], - }, - }, - fillTank: { - forms: [ - { - type: "object", - href: endpointUrl, - op: ["invokeaction"], - "opcua:nodeId": { root: "i=84", path: "/Objects/2:DeviceSet/1:CoffeeMachine" }, - "opcua:method": { - root: "i=84", - path: "/Objects/2:DeviceSet/1:CoffeeMachine/2:MethodSet/9:FillTank", - }, - }, - ], - }, - }, -}; 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); - }); -}); diff --git a/packages/examples/src/scripts/countdown.ts b/packages/examples/src/scripts/countdown.ts deleted file mode 100644 index b1e4e70b1..000000000 --- a/packages/examples/src/scripts/countdown.ts +++ /dev/null @@ -1,194 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2021 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 - ********************************************************************************/ - -function uuidv4(): string { - return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { - const r = (Math.random() * 16) | 0; - const v = c === "x" ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); -} - -enum Status { - "pending", - "running", - "completed", - "failed", -} - -interface ActionStatus { - status: Status; - output?: number; // any - error?: Error; - href?: string; -} - -let countdowns: Map; - -WoT.produce({ - title: "countdown", - description: "Countdown example Thing", - support: "https://github.com/eclipse-thingweb/node-wot/", - properties: { - countdowns: { - type: "array", - items: { - type: "string", - }, - observable: true, - readOnly: true, - }, - }, - actions: { - startCountdown: { - description: "Start countdown in secs (default 100 secs)", - input: { - // optional init value - /* type: "integer" */ - oneOf: [{ type: "integer" }, {}], - }, - }, - stopCountdown: { - // SHOULD BE DELETE for WoT-Profile - description: "Stops countdown", - input: { - type: "string", - }, - }, - monitorCountdown: { - // SHOULD BE GET for WoT-Profile - description: "Reports current countdown status/value", - input: { - type: "string", - }, - output: { - type: "object", - }, - }, - }, -}) - .then((thing) => { - console.log("Produced " + thing.getThingDescription().title); - - // init property values and start update loop - countdowns = new Map(); - setInterval(() => { - if (countdowns.size > 0) { - console.log("Update countdowns"); - const listToDelete: string[] = []; - for (const id of countdowns.keys()) { - const as = countdowns.get(id); - if (as?.output !== undefined) { - const prev = as.output; - as.output--; - console.log("\t" + id + ", from " + prev + " to " + as.output); - - if (as.output > 0) { - as.status = Status.running; - } else { - as.status = Status.completed; - } - - if (as.output < -10) { - // remove from list after a while - listToDelete.push(id); - } - } - } - listToDelete.forEach((id) => { - console.log("Remove countdown for href = " + id); - countdowns.delete(id); - }); - } - }, 1000); - - // set property handlers (using async-await) - thing.setPropertyReadHandler("countdowns", async (options): Promise => { - const cts: string[] = []; - for (const id of countdowns.keys()) { - cts.push(id); - } - return cts; - }); - // set action handlers (using async-await) - thing.setActionHandler( - "startCountdown", - async (params: WoT.InteractionOutput, options): Promise => { - let initValue = 100; - if (params != null) { - const value = await params.value(); - if (typeof value === "number") { - initValue = value as number; - } - } - const resp: ActionStatus = { - href: uuidv4(), - output: initValue, - status: initValue > 0 ? Status.pending : Status.completed, - }; - const ii: WoT.InteractionInput = resp; - console.log("init countdown value = " + JSON.stringify(resp)); - countdowns.set(resp.href ?? "", resp); - return ii; - } - ); - thing.setActionHandler( - "stopCountdown", - async (params: WoT.InteractionOutput, options): Promise => { - if (params != null) { - const value = await params.value(); - if (typeof value === "string" && countdowns.has(value)) { - const as = countdowns.get(value); - if (as !== undefined) { - as.output = 0; - as.status = Status.completed; - console.log("Countdown stopped for href: " + value); - return null; - } else { - throw Error("Countdown value is undefined for href, " + value); - } - } else { - throw Error("Input provided for stopCountdown is no string or invalid href, " + value); - } - } else { - throw Error("No input specified for stopCountdown"); - } - } - ); - thing.setActionHandler( - "monitorCountdown", - async (params: WoT.InteractionOutput, options): Promise => { - if (params != null) { - const value = await params.value(); - if (typeof value === "string" && countdowns.has(value)) { - const as = countdowns.get(value); - return JSON.stringify(as); - } else { - throw Error("Input provided for monitorCountdown is no string or invalid href, " + value); - } - } else { - throw Error("No input specified for monitorCountdown"); - } - } - ); - - // expose the thing - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - }); - }) - .catch((e) => { - console.log(e); - }); diff --git a/packages/examples/src/scripts/counter-client.ts b/packages/examples/src/scripts/counter-client.ts deleted file mode 100644 index 6e143c617..000000000 --- a/packages/examples/src/scripts/counter-client.ts +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020 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 - ********************************************************************************/ - -function getFormIndexForDecrementWithCoAP(thing: WoT.ConsumedThing): number { - const forms = thing.getThingDescription().actions?.decrement.forms; - if (forms !== undefined) { - for (let i = 0; i < forms.length; i++) { - if (/^coaps?:\/\/.*/.test(forms[i].href)) { - return i; - } - } - } - // return formIndex: 0 if no CoAP target IRI found - return 0; -} - -WoT.requestThingDescription("coap://localhost:5683/counter") - .then(async (td) => { - try { - const thing = await WoT.consume(td); - console.info("=== TD ==="); - console.info(td); - console.info("=========="); - - // read property #1 - const read1 = await thing.readProperty("count"); - console.log("count value is", await read1.value()); - - // increment property #1 (without step) - await thing.invokeAction("increment"); - const inc1 = await thing.readProperty("count"); - console.info("count value after increment #1 is", await inc1.value()); - - // increment property #2 (with step) - await thing.invokeAction("increment", undefined, { uriVariables: { step: 3 } }); - const inc2 = await thing.readProperty("count"); - console.info("count value after increment #2 (with step 3) is", await inc2.value()); - - // look for the first form for decrement with CoAP binding - await thing.invokeAction("decrement", undefined, { - formIndex: getFormIndexForDecrementWithCoAP(thing), - }); - const dec1 = await thing.readProperty("count"); - console.info("count value after decrement is", await dec1.value()); - } catch (err) { - console.error("Script error:", err); - } - }) - .catch((err) => { - console.error("Fetch error:", err); - }); diff --git a/packages/examples/src/scripts/counter.ts b/packages/examples/src/scripts/counter.ts deleted file mode 100644 index 6b561b657..000000000 --- a/packages/examples/src/scripts/counter.ts +++ /dev/null @@ -1,283 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020 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. -// It has a count property that can be incremented or decremented via actions and its changes are reported via events. -// It also has two properties that return an image. The SVG property is also influenced by the increment and decrement actions. -// Features -// * basic properties, actions, events -// * local/global uriVariables -// * multi-language -// * image contentTypes for properties (Note: the contentType applies to all forms of the property) -// * links with entry containing rel and sizes - -let count: number; -let lastChange: string; - -WoT.produce({ - title: "Counter", - titles: { - en: "Counter", - de: "Zähler", - it: "Contatore", - }, - description: "Counter example Thing", - descriptions: { - en: "Counter example Thing", - de: "Zähler Beispiel Ding", - it: "Contatore di esempio", - }, - support: "https://github.com/eclipse-thingweb/node-wot/", - links: [ - { - href: "https://www.thingweb.io/img/favicon/favicon.png", - sizes: "16x14", - rel: "icon", - }, - ], - "@context": [ - "https://www.w3.org/2019/wot/td/v1", - "https://www.w3.org/2022/wot/td/v1.1", - { - iot: "http://example.org/iot", - }, - ], - uriVariables: { - step: { - type: "integer", - minimum: 1, - maximum: 250, - }, - }, - properties: { - count: { - title: "Count", - titles: { - en: "Count", - de: "Zähler", - it: "Valore", - }, - type: "integer", - description: "Current counter value", - descriptions: { - en: "Current counter value", - de: "Derzeitiger Zählerwert", - it: "Valore attuale del contatore", - }, - "iot:Custom": "example annotation", - observable: true, - readOnly: true, - }, - countAsImage: { - description: "Current counter value as SVG image", - descriptions: { - en: "Current counter value as SVG image", - de: "Aktueller Zählerwert als SVG-Bild", - it: "Valore attuale del contatore come immagine SVG", - }, - observable: false, - readOnly: true, - uriVariables: { - fill: { - type: "string", - }, - }, - forms: [ - { - contentType: "image/svg+xml", - }, - ], - }, - redDotImage: { - description: "Red dot image as PNG", - descriptions: { - en: "Red dot image as PNG", - de: "Rotes Punktbild als PNG", - it: "Immagine punto rosso come PNG", - }, - observable: false, - readOnly: true, - forms: [ - { - contentType: "image/png;base64", - }, - ], - }, - lastChange: { - title: "Last change", - titles: { - en: "Last change", - de: "Letzte Zählerwertänderung", - it: "Ultima modifica", - }, - type: "string", - description: "Last change of counter value", - descriptions: { - en: "Last change of counter value", - de: "Letzte Änderung", - it: "Ultima modifica del valore", - }, - observable: true, - readOnly: true, - }, - }, - actions: { - increment: { - title: "Increment", - titles: { - en: "Increment", - de: "Erhöhen", - it: "Incrementa", - }, - description: "Increment counter value", - descriptions: { - en: "Increment counter value", - de: "Zählerwert erhöhen", - it: "Incrementa il valore del contatore", - }, - }, - decrement: { - title: "Decrement", - titles: { - en: "Decrement", - de: "Verringern", - it: "Decrementa", - }, - description: "Decrementing counter value", - descriptions: { - en: "Decrementing counter value", - de: "Zählerwert verringern", - it: "Decrementare il valore del contatore", - }, - }, - reset: { - title: "Reset", - titles: { - en: "Reset", - de: "Zurücksetzen", - it: "Reset", - }, - description: "Resetting counter value", - descriptions: { - en: "Resetting counter value", - de: "Zählerwert zurücksetzen", - it: "Resettare il valore del contatore", - }, - }, - }, - events: { - change: { - title: "Changed", - titles: { - en: "Changed", - de: "Geändert", - it: "Valore modificato", - }, - description: "Change event", - descriptions: { - en: "Change event", - de: "Änderungsereignis", - it: "Valore modificato", - }, - }, - }, -}) - .then((thing) => { - console.log("Produced " + thing.getThingDescription().title); - - // init property values - count = 0; - lastChange = new Date().toISOString(); - - // set property handlers (using async-await) - thing.setPropertyReadHandler("count", async () => count); - thing.setPropertyReadHandler("lastChange", async () => lastChange); - thing.setPropertyReadHandler("countAsImage", async (options) => { - let fill = "black"; - if (options && typeof options === "object" && "uriVariables" in options) { - console.log("options = " + JSON.stringify(options)); - if (options.uriVariables && "fill" in options.uriVariables) { - const uriVariables = options.uriVariables as Record; - fill = uriVariables.fill; - } - } - return ( - "" + - "" + - count + - "" + - "" - ); - }); - thing.setPropertyReadHandler( - "redDotImage", - async () => - "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" - ); - - // set action handlers (using async-await) - thing.setActionHandler("increment", async (params, options) => { - let step = 1; - if (options && typeof options === "object" && "uriVariables" in options) { - console.log("options = " + JSON.stringify(options)); - if (options.uriVariables && "step" in options.uriVariables) { - const uriVariables = options.uriVariables as Record; - step = uriVariables.step as number; - } - } - const newValue = count + step; - console.log("Incrementing count from " + count + " to " + newValue + " (with step " + step + ")"); - count = newValue; - lastChange = new Date().toISOString(); - thing.emitEvent("change", count); - thing.emitPropertyChange("count"); - return undefined; - }); - thing.setActionHandler("decrement", async (params, options) => { - let step = 1; - if (options && typeof options === "object" && "uriVariables" in options) { - console.log("options = " + JSON.stringify(options)); - if (options.uriVariables && "step" in options.uriVariables) { - const uriVariables = options.uriVariables as Record; - step = uriVariables.step as number; - } - } - const newValue = count - step; - console.log("Decrementing count from " + count + " to " + newValue + " (with step " + step + ")"); - count = newValue; - lastChange = new Date().toISOString(); - thing.emitEvent("change", count); - thing.emitPropertyChange("count"); - return undefined; - }); - thing.setActionHandler("reset", async (params, options) => { - console.log("Resetting count"); - count = 0; - lastChange = new Date().toISOString(); - thing.emitEvent("change", count); - thing.emitPropertyChange("count"); - return undefined; - }); - - // expose the thing - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - }); - }) - .catch((e) => { - console.log(e); - }); diff --git a/packages/examples/src/scripts/smart-coffee-machine-client.ts b/packages/examples/src/scripts/smart-coffee-machine-client.ts deleted file mode 100644 index ab81b579b..000000000 --- a/packages/examples/src/scripts/smart-coffee-machine-client.ts +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020 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 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: string, data: unknown) { - console.info("======================"); - console.info(msg); - console.dir(data); - console.info("======================"); -} - -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); - - // Read property allAvailableResources - let allAvailableResources = await (await thing.readProperty("allAvailableResources")).value(); - log("allAvailableResources value is:", allAvailableResources); - - // Now let's change water level to 80 - await thing.writeProperty("availableResourceLevel", 80, { uriVariables: { id: "water" } }); - - // And see that the water level has changed - const waterLevel = await ( - await thing.readProperty("availableResourceLevel", { uriVariables: { id: "water" } }) - ).value(); - log("waterLevel value after change is:", waterLevel); - - // This can also be seen in allAvailableResources property - allAvailableResources = await (await thing.readProperty("allAvailableResources")).value(); - log("allAvailableResources value after change is:", allAvailableResources); - - // It's also possible to set a client-side handler for observable properties - thing.observeProperty("maintenanceNeeded", async (data) => { - log("maintenanceNeeded property has changed! New value is:", await data.value()); - }); - - // Now let's make 3 cups of latte! - const makeCoffee = await thing.invokeAction("makeDrink", undefined, { - uriVariables: { drinkId: "latte", size: "l", quantity: 3 }, - }); - const makeCoffeep = (await makeCoffee?.value()) as Record; - if (makeCoffeep.result != null) { - log("Enjoy your drink!", makeCoffeep); - } else { - log("Failed making your drink:", makeCoffeep); - } - - // See how allAvailableResources property value has changed - allAvailableResources = await (await thing.readProperty("allAvailableResources")).value(); - log("allAvailableResources value is:", allAvailableResources); - - // Let's add a scheduled task - const scheduledTask = await thing.invokeAction("setSchedule", { - drinkId: "espresso", - size: "m", - quantity: 2, - time: "10:00", - mode: "everyday", - }); - const scheduledTaskp = (await scheduledTask?.value()) as Record; - log(scheduledTaskp.message, scheduledTaskp); - - // See how it has been added to the schedules property - const schedules = await (await thing.readProperty("schedules")).value(); - log("schedules value: ", schedules); - - // Let's set up a handler for outOfResource event - thing.subscribeEvent("outOfResource", async (data) => { - // Here we are simply logging the message when the event is emitted - // But, of course, could have a much more sophisticated handler - log("outOfResource event:", await data.value()); - }); - - // fire property change for maintenanceNeeded - await thing.writeProperty("servedCounter", 1001); - } catch (err) { - console.error("Script error:", err); - } -}); diff --git a/packages/examples/src/scripts/smart-coffee-machine.ts b/packages/examples/src/scripts/smart-coffee-machine.ts deleted file mode 100644 index 977b1693a..000000000 --- a/packages/examples/src/scripts/smart-coffee-machine.ts +++ /dev/null @@ -1,420 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020 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 of Web of Things producer ("server" 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. - -let allAvailableResources: Record; -let possibleDrinks: string[]; -let maintenanceNeeded: boolean; -let schedules: unknown[]; -let servedCounter: number; - -function readFromSensor(sensorType: string): number { - // Actual implementation of reading data from a sensor can go here - // For the sake of example, let's just return a value - return 100; -} - -function notify(subscribers: unknown, msg: string) { - // Actual implementation of notifying subscribers with a message can go here - console.log(msg); -} - -WoT.produce({ - title: "Smart-Coffee-Machine", - description: `A smart coffee machine with a range of capabilities. -A complementary tutorial is available at http://www.thingweb.io/smart-coffee-machine.html.`, - support: "https://github.com/eclipse-thingweb/node-wot/", - properties: { - allAvailableResources: { - type: "object", - description: `Current level of all available resources given as an integer percentage for each particular resource. -The data is obtained from the machine's sensors but can be set manually via the availableResourceLevel property in case the sensors are broken.`, - readOnly: true, - properties: { - water: { - type: "integer", - minimum: 0, - maximum: 100, - }, - milk: { - type: "integer", - minimum: 0, - maximum: 100, - }, - chocolate: { - type: "integer", - minimum: 0, - maximum: 100, - }, - coffeeBeans: { - type: "integer", - minimum: 0, - maximum: 100, - }, - }, - }, - availableResourceLevel: { - type: "number", - description: `Current level of a particular resource. Requires resource id variable as uriVariables. -The property can also be overridden, which also requires resource id as uriVariables.`, - uriVariables: { - id: { - type: "string", - enum: ["water", "milk", "chocolate", "coffeeBeans"], - }, - }, - }, - possibleDrinks: { - type: "array", - description: `The list of possible drinks in general. Doesn't depend on the available resources.`, - readOnly: true, - items: { - type: "string", - }, - }, - servedCounter: { - type: "integer", - description: `The total number of served beverages.`, - minimum: 0, - }, - maintenanceNeeded: { - type: "boolean", - description: `Shows whether a maintenance is needed. The property is observable. Automatically set to true when the servedCounter property exceeds 1000.`, - observable: true, - }, - schedules: { - type: "array", - description: `The list of scheduled tasks.`, - readOnly: true, - items: { - type: "object", - properties: { - drinkId: { - type: "string", - description: `Defines what drink to make, drinkId is one of possibleDrinks property values, e.g. latte.`, - }, - size: { - type: "string", - description: `Defines the size of a drink, s = small, m = medium, l = large.`, - enum: ["s", "m", "l"], - }, - quantity: { - type: "integer", - description: `Defines how many drinks to make, ranging from 1 to 5.`, - minimum: 1, - maximum: 5, - }, - time: { - type: "string", - description: `Defines the time of the scheduled task in 24h format, e.g. 10:00 or 21:00.`, - }, - mode: { - type: "string", - description: `Defines the mode of the scheduled task, e.g. once or everyday. All the possible values are given in the enum field of this Thing Description.`, - enum: [ - "once", - "everyday", - "everyMo", - "everyTu", - "everyWe", - "everyTh", - "everyFr", - "everySat", - "everySun", - ], - }, - }, - }, - }, - }, - actions: { - makeDrink: { - description: `Make a drink from available list of beverages. Accepts drink id, size and quantity as uriVariables. -Brews one medium americano if no uriVariables are specified.`, - uriVariables: { - drinkId: { - type: "string", - description: `Defines what drink to make, drinkId is one of possibleDrinks property values, e.g. latte.`, - }, - size: { - type: "string", - description: `Defines the size of a drink, s = small, m = medium, l = large.`, - enum: ["s", "m", "l"], - }, - quantity: { - type: "integer", - description: `Defines how many drinks to make, ranging from 1 to 5.`, - minimum: 1, - maximum: 5, - }, - }, - output: { - type: "object", - description: `Returns true/false and a message when all invoked promises are resolved (asynchronous).`, - properties: { - result: { - type: "boolean", - }, - message: { - type: "string", - }, - }, - }, - }, - setSchedule: { - description: `Add a scheduled task to the schedules property. Accepts drink id, size, quantity, time and mode as body of a request. -Assumes one medium americano if not specified, but time and mode are mandatory fields.`, - input: { - type: "object", - properties: { - drinkId: { - type: "string", - description: `Defines what drink to make, drinkId is one of possibleDrinks property values, e.g. latte.`, - }, - size: { - type: "string", - description: `Defines the size of a drink, s = small, m = medium, l = large.`, - enum: ["s", "m", "l"], - }, - quantity: { - type: "integer", - description: `Defines how many drinks to make, ranging from 1 to 5.`, - minimum: 1, - maximum: 5, - }, - time: { - type: "string", - description: `Defines the time of the scheduled task in 24h format, e.g. 10:00 or 21:00.`, - }, - mode: { - type: "string", - description: `Defines the mode of the scheduled task, e.g. once or everyday. All the possible values are given in the enum field of this Thing Description.`, - enum: [ - "once", - "everyday", - "everyMo", - "everyTu", - "everyWe", - "everyTh", - "everyFr", - "everySat", - "everySun", - ], - }, - }, - required: ["time", "mode"], - }, - output: { - type: "object", - description: `Returns true/false and a message when all invoked promises are resolved (asynchronous).`, - properties: { - result: { - type: "boolean", - }, - message: { - type: "string", - }, - }, - }, - }, - }, - events: { - outOfResource: { - description: `Out of resource event. Emitted when the available resource level is not sufficient for a desired drink.`, - data: { - type: "string", - }, - }, - }, -}) - .then((thing) => { - // Initialize the property values - allAvailableResources = { - water: readFromSensor("water"), - milk: readFromSensor("milk"), - chocolate: readFromSensor("chocolate"), - coffeeBeans: readFromSensor("coffeeBeans"), - }; - possibleDrinks = ["espresso", "americano", "cappuccino", "latte", "hotChocolate", "hotWater"]; - maintenanceNeeded = false; - schedules = []; - - thing.setPropertyReadHandler("allAvailableResources", async () => allAvailableResources); - thing.setPropertyReadHandler("possibleDrinks", async () => possibleDrinks); - thing.setPropertyReadHandler("maintenanceNeeded", async () => maintenanceNeeded); - thing.setPropertyReadHandler("schedules", async () => schedules); - - // Override a write handler for servedCounter property, - // raising maintenanceNeeded flag when the value exceeds 1000 drinks - thing.setPropertyWriteHandler("servedCounter", async (val) => { - servedCounter = (await val.value()) as number; - if (servedCounter > 1000) { - maintenanceNeeded = true; - thing.emitPropertyChange("maintenanceNeeded"); - - // Notify a "maintainer" when the value has changed - // (the notify function here simply logs a message to the console) - notify( - "admin@coffeeMachine.com", - `maintenanceNeeded property has changed, new value is: ${maintenanceNeeded}` - ); - } - }); - - // Now initialize the servedCounter property - servedCounter = readFromSensor("servedCounter"); - - // Override a write handler for availableResourceLevel property, - // utilizing the uriVariables properly - thing.setPropertyWriteHandler("availableResourceLevel", async (val, options) => { - // Check if uriVariables are provided - if (options && typeof options === "object" && "uriVariables" in options) { - const uriVariables = options.uriVariables as Record; - if ("id" in uriVariables) { - const id = uriVariables.id; - allAvailableResources[id] = (await val.value()) as number; - return; - } - } - throw Error("Please specify id variable as uriVariables."); - }); - - // Override a read handler for availableResourceLevel property, - // utilizing the uriVariables properly - thing.setPropertyReadHandler("availableResourceLevel", async (options) => { - // Check if uriVariables are provided - if (options && typeof options === "object" && "uriVariables" in options) { - const uriVariables = options.uriVariables as Record; - if ("id" in uriVariables) { - const id = uriVariables.id; - return allAvailableResources[id]; - } - } - throw Error("Please specify id variable as uriVariables."); - }); - - // Set up a handler for makeDrink action - thing.setActionHandler("makeDrink", async (_params, options) => { - // Default values - let drinkId = "americano"; - let size = "m"; - let quantity = 1; - - // Size quantifiers - const sizeQuantifiers: Record = { s: 0.1, m: 0.2, l: 0.3 }; - - // Drink recipes showing the amount of a resource consumed for a particular drink - const drinkRecipes: Record> = { - espresso: { - water: 1, - milk: 0, - chocolate: 0, - coffeeBeans: 2, - }, - americano: { - water: 2, - milk: 0, - chocolate: 0, - coffeeBeans: 2, - }, - cappuccino: { - water: 1, - milk: 1, - chocolate: 0, - coffeeBeans: 2, - }, - latte: { - water: 1, - milk: 2, - chocolate: 0, - coffeeBeans: 2, - }, - hotChocolate: { - water: 0, - milk: 0, - chocolate: 1, - coffeeBeans: 0, - }, - hotWater: { - water: 1, - milk: 0, - chocolate: 0, - coffeeBeans: 0, - }, - }; - - // Check if uriVariables are provided - if (options && typeof options === "object" && "uriVariables" in options) { - const uriVariables = options.uriVariables as Record; - drinkId = "drinkId" in uriVariables ? (uriVariables.drinkId as string) : drinkId; - size = "size" in uriVariables ? (uriVariables.size as string) : size; - quantity = "quantity" in uriVariables ? (uriVariables.quantity as number) : quantity; - } - - // Calculate the new level of resources - const newResources = Object.assign({}, allAvailableResources); - newResources.water -= Math.ceil(quantity * sizeQuantifiers[size] * drinkRecipes[drinkId].water); - newResources.milk -= Math.ceil(quantity * sizeQuantifiers[size] * drinkRecipes[drinkId].milk); - newResources.chocolate -= Math.ceil(quantity * sizeQuantifiers[size] * drinkRecipes[drinkId].chocolate); - newResources.coffeeBeans -= Math.ceil(quantity * sizeQuantifiers[size] * drinkRecipes[drinkId].coffeeBeans); - - // Check if the amount of available resources is sufficient to make a drink - for (const resource in newResources) { - if (newResources[resource] <= 0) { - thing.emitEvent("outOfResource", `Low level of ${resource}: ${newResources[resource]}%`); - return { result: false, message: `${resource} level is not sufficient` }; - } - } - - // Now store the new level of allAvailableResources - allAvailableResources = newResources; - servedCounter = servedCounter + quantity; - - // Finally deliver the drink - return { result: true, message: `Your ${drinkId} is in progress!` }; - }); - - // Set up a handler for setSchedule action - thing.setActionHandler("setSchedule", async (params, options) => { - const paramsp = (await params.value()) as Record; // : any = await Helpers.parseInteractionOutput(params); - - // Check if uriVariables are provided - if (paramsp != null && typeof paramsp === "object" && "time" in paramsp && "mode" in paramsp) { - // Use default values if not provided - paramsp.drinkId = "drinkId" in paramsp ? paramsp.drinkId : "americano"; - paramsp.size = "size" in paramsp ? paramsp.size : "m"; - paramsp.quantity = "quantity" in paramsp ? paramsp.quantity : 1; - - // Now add a new schedule - schedules.push(paramsp); - - return { result: true, message: `Your schedule has been set!` }; - } - - return { result: false, message: `Please provide all the required parameters: time and mode.` }; - }); - - // Finally expose the thing - thing.expose().then(() => { - console.info(`${thing.getThingDescription().title} ready`); - }); - console.log(`Produced ${thing.getThingDescription().title}`); - }) - .catch((e) => { - console.log(e); - }); diff --git a/packages/examples/src/security/certificate.pem b/packages/examples/src/security/certificate.pem deleted file mode 100644 index 153d2789f..000000000 --- a/packages/examples/src/security/certificate.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICDDCCAXUCFEcgrATArZXi0508eBk873JbhNT5MA0GCSqGSIb3DQEBCwUAMEUx -CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl -cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjAwNTA3MTcwMzEwWhcNMjAwNjA2MTcw -MzEwWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE -CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQDB4USEKBahhOhznS3oF4C1hGi7K4j2zpJIxIKxJD8zvlV+MazQOsCv -4FtudE9Lf9JV4Cni8Ci/bLgSENgkMOK6JJrvYSZBmcO/soDoz6szzIuLJbQoZvM6 -wRxwKwXYP77qK+zbYhdFTZiESO77RPvnnAxU7e4Ym2bZXjghqB0GDQIDAQABMA0G -CSqGSIb3DQEBCwUAA4GBAJjPDHpmbfd4QMtARLyslQ8LpE+fk/OtF58eOFF/izko -DWRf3dXGGNnhZOESMbRYSgygEZR0dhbaUSdiGMrj+MapOwsmoYnvz44bSeGOHAgq -cutpTJ2oXeeiHsOo18/tNc5RgvRDJivlgrheaC4LSq4eb+hUFV0Zj6cR+GRauSsL ------END CERTIFICATE----- diff --git a/packages/examples/src/security/oauth/README.md b/packages/examples/src/security/oauth/README.md deleted file mode 100644 index de673f355..000000000 --- a/packages/examples/src/security/oauth/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# oAuth example - -The example is composed by two actors: one Thing that expose an action with oAuth2.0 client credential security constraint and a client who want to use that function. In the example, we are using an utility server to generate tokens and validate client credentials. Therefore, the **wot-consumer** force the action `href` to be the same as the utility server with the goal to validate the obtained oAuth2.0 token. In the feature the exposing servient could also play this role. - -## run the example - -Set the current working directory to this folder. Then execute: - -```bash -npm install -npm run build -``` - -After this follow the procedure described in [here](../../README.md) and remove the unwanted line of codes inside the scripts `./dist/consumer.js` and `./dist/exposer.js`. - -Now you are ready to run the example. - -```bash -# start the server -npm run server -``` - -in a different terminal - -```bash -# start the exposer -npm run start:exposer -``` - -Finally, in other terminal - -```bash -npm run start:consumer -``` - -you should see the following line at the end of consumer log: - -```bash -oAuth token was Ok! -``` - -This confirms that the oAuth flow was completed successfully. Now you can have fun revoking the access to the consumer script. Go -to `./exposer.ts` and try to remove the string `"user"` from the scopes. Run again the example and you will see that the action is not executed and an error is returned by the client. - -## Where is a JS version? - -See [here](../../../examples/security/oauth) diff --git a/packages/examples/src/security/oauth/consumer.ts b/packages/examples/src/security/oauth/consumer.ts deleted file mode 100644 index efc4ac090..000000000 --- a/packages/examples/src/security/oauth/consumer.ts +++ /dev/null @@ -1,26 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018 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 - ********************************************************************************/ - -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(); - console.log("oAuth token was", result); - } catch (error) { - console.log("It seems that I couldn't access the resource"); - } - }); -}); diff --git a/packages/examples/src/security/oauth/exposer.ts b/packages/examples/src/security/oauth/exposer.ts deleted file mode 100644 index 827f6323a..000000000 --- a/packages/examples/src/security/oauth/exposer.ts +++ /dev/null @@ -1,45 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018 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 - ********************************************************************************/ - -import { ExposedThingInit } from "wot-typescript-definitions"; - -const td: ExposedThingInit = { - "@context": "https://www.w3.org/2019/wot/td/v1", - title: "OAuth", - id: "urn:dev:wot:oauth:test", - securityDefinitions: { - oauth2_sc: { - scheme: "oauth2", - flow: "client", - token: "https://localhost:3000/token", - scopes: ["user", "admin"], - }, - }, - security: ["oauth2_sc"], - actions: { - sayOk: { - description: "A simple action protected with oauth", - idempotent: true, - }, - }, -}; -try { - WoT.produce(td).then((thing) => { - thing.setActionHandler("sayOk", async () => "Ok!"); - thing.expose(); - }); -} catch (err) { - console.error("Script error: " + err); -} diff --git a/packages/examples/src/security/oauth/memory-model.js b/packages/examples/src/security/oauth/memory-model.js deleted file mode 100644 index 079b27913..000000000 --- a/packages/examples/src/security/oauth/memory-model.js +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018 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 - ********************************************************************************/ - -/** - * oAuth server logic. See https://oauth2-server.readthedocs.io/en/latest/model/overview.html - */ -module.exports = class InMemoryModel { - /** - * - */ - constructor() { - this.clients = [ - { - clientId: "node-wot", - clientSecret: "isgreat!", - redirectUris: [""], - grants: ["client_credentials"], - scopes: ["user"], - }, - ]; - this.tokens = []; - this.users = [{ id: "123", username: "thomseddon", password: "nightworld" }]; - } - - dump() { - console.log("clients", this.clients); - console.log("tokens", this.tokens); - console.log("users", this.users); - } - - /* - * Get access token. - */ - - getAccessToken(bearerToken) { - var tokens = this.tokens.filter(function (token) { - return token.accessToken === bearerToken; - }); - - return tokens.length ? tokens[0] : false; - } - - /** - * Get refresh token. - */ - - getRefreshToken(bearerToken) { - var tokens = this.tokens.filter(function (token) { - return token.refreshToken === bearerToken; - }); - - return tokens.length ? tokens[0] : false; - } - - /** - * Get client. - */ - - getClient(clientId, clientSecret) { - var clients = this.clients.filter(function (client) { - return client.clientId === clientId && (!clientSecret || client.clientSecret === clientSecret); - }); - - return clients.length ? clients[0] : false; - } - - /** - * Save token. - */ - - saveToken(token, client, user) { - let { accessToken, accessTokenExpiresAt, refreshTokenExpiresAt, refreshToken } = token; - this.tokens.push({ - accessToken: accessToken, - accessTokenExpiresAt: accessTokenExpiresAt, - client: client, - refreshToken: refreshToken, - refreshTokenExpiresAt: refreshTokenExpiresAt, - user: user, - }); - return this.tokens[this.tokens.length - 1]; - } - - /* - * Get user. - */ - - getUser(username, password) { - var users = this.users.filter(function (user) { - return user.username === username && user.password === password; - }); - - return users.length ? users[0] : false; - } - - getUserFromClient(client) { - return this.users[0]; - } - - saveAuthorizationCode() {} - - expireAllTokens() { - for (const token of this.tokens) { - token.accessTokenExpiresAt = Date.now(); - } - } -}; diff --git a/packages/examples/src/security/oauth/package.json b/packages/examples/src/security/oauth/package.json deleted file mode 100644 index eb30f2694..000000000 --- a/packages/examples/src/security/oauth/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "oauth-test", - "version": "1.0.0", - "description": "Simple project setup to test oauth functionalities", - "main": "index.js", - "scripts": { - "build": "tsc -b", - "server": "node server.js", - "start:exposer": "node ../../../../cli/dist/cli.js -f ./wot-server-servient-conf.json ../../../dist/security/oauth/exposer.js", - "start:consumer": "node ../../../../cli/dist/cli.js -f ./wot-client-servient-conf.json ../../../dist/security/oauth/consumer.js", - "debug:consumer": "node --inspect-brk ../../../../cli/dist/cli.js -f ./wot-client-servient-conf.json ../../../dist/security/oauth/consumer.js" - }, - "author": "Eclipse Thingweb (https://thingweb.io/)", - "license": "EPL-2.0 OR W3C-20150513", - "devDependencies": { - "@node-oauth/express-oauth-server": "^3.0.0", - "@types/node": "16.18.35", - "cors": "^2.8.5", - "ts-node": "10.9.1", - "typescript": "4.7.4", - "typescript-standard": "^0.3.36", - "wot-typescript-definitions": "0.8.0-SNAPSHOT.29" - } -} diff --git a/packages/examples/src/security/oauth/server.js b/packages/examples/src/security/oauth/server.js deleted file mode 100644 index 717a2c1b8..000000000 --- a/packages/examples/src/security/oauth/server.js +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2018 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 - ********************************************************************************/ -/** - * A simple oAuth test server - */ -const OAuthServer = require("@node-oauth/express-oauth-server"); -const bodyParser = require("body-parser"); -const cors = require("cors"); -const https = require("https"); -const fs = require("fs"); -const express = require("express"); -const Memory = require("./memory-model"); - -var app = express(); -app.use(cors()); -app.options("*", cors()); - -const model = new Memory(); - -app.oauth = new OAuthServer({ - model: model, -}); - -app.use(bodyParser.json()); -app.use("/introspect", bodyParser.urlencoded({ extended: false })); -app.use("/introspect", (req, res, next) => { - if (req.method !== "POST" || !req.is("application/x-www-form-urlencoded")) { - return res.status(400).end(); - } - - // rewrite body authenticate method is not compliant to https://tools.ietf.org/html/rfc7662 - const token = req.body.token; - delete req.body.token; - req.body.access_token = token; - console.log("Body changed,"); - next(); -}); - -app.use("/introspect", async (req, res, next) => { - return app.oauth.authenticate()(req, res, next); -}); -app.use("/introspect", (req, res) => { - const token = res.locals.oauth.token; - console.log("Token was", token ? "Ok" : "not Ok"); - res.json({ - active: !!token, - scope: token.client.scopes.join(" "), - client_id: token.client.clientId, - }).end(); -}); - -app.use("/token", bodyParser.urlencoded({ extended: false })); -app.use("/token", app.oauth.token()); - -app.use("/resource", (req, res) => { - console.log("qui?"); - res.send("Ok!"); -}); - -https - .createServer( - { - key: fs.readFileSync("../privatekey.pem"), - cert: fs.readFileSync("../certificate.pem"), - }, - app - ) - .listen(3000, "localhost", () => { - console.log("listening"); - }); diff --git a/packages/examples/src/security/oauth/tsconfig.json b/packages/examples/src/security/oauth/tsconfig.json deleted file mode 100644 index eab64572b..000000000 --- a/packages/examples/src/security/oauth/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "outDir": "../../../dist" - }, - "extends": "../../../tsconfig.json", - "include": [], - "files": ["consumer.ts", "exposer.ts"] -} diff --git a/packages/examples/src/security/oauth/wot-client-servient-conf.json b/packages/examples/src/security/oauth/wot-client-servient-conf.json deleted file mode 100644 index d6e9a1529..000000000 --- a/packages/examples/src/security/oauth/wot-client-servient-conf.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "servient": { - "clientOnly": true - }, - "http": { - "allowSelfSigned": true - }, - "credentials": { - "urn:dev:wot:oauth:test": { - "clientId": "node-wot", - "clientSecret": "isgreat!" - } - } -} diff --git a/packages/examples/src/security/oauth/wot-server-servient-conf.json b/packages/examples/src/security/oauth/wot-server-servient-conf.json deleted file mode 100644 index b34eed731..000000000 --- a/packages/examples/src/security/oauth/wot-server-servient-conf.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "servient": {}, - "http": { - "allowSelfSigned": true, - "serverKey": "../privatekey.pem", - "serverCert": "../certificate.pem", - "security": [ - { - "scheme": "oauth2", - "method": { - "name": "introspection_endpoint", - "endpoint": "https://localhost:3000/introspect", - "allowSelfSigned": true - } - } - ] - }, - "credentials": { - "urn:dev:wot:oauth:test": { - "clientId": "node-wot", - "clientSecret": "isgreat!" - } - } -} diff --git a/packages/examples/src/security/privatekey.pem b/packages/examples/src/security/privatekey.pem deleted file mode 100644 index 1a65f9c28..000000000 --- a/packages/examples/src/security/privatekey.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQDB4USEKBahhOhznS3oF4C1hGi7K4j2zpJIxIKxJD8zvlV+MazQ -OsCv4FtudE9Lf9JV4Cni8Ci/bLgSENgkMOK6JJrvYSZBmcO/soDoz6szzIuLJbQo -ZvM6wRxwKwXYP77qK+zbYhdFTZiESO77RPvnnAxU7e4Ym2bZXjghqB0GDQIDAQAB -AoGBAIZCwXfjawifSXoGtuuqmu8Yqo4zL736f0L1EqwpNbtXa0zgiZQJm7Yv4CE1 -WlQmSDo/6cHGHfGyECYyk/s7/0VDdfS6jf5AMzpkCXP+32FZZegN7JxasgYsddZC -LlpYhxjUd1vnYEIvvAefJ7N3Y0jdp1gR1Iri9+7vJjuFXJoBAkEA6foaD4sFDJhO -/zYPPOJljtwtQz+ik4nXJCIvzLYAIKBcOgFirqLqcHfRnHh17DrumqVB3IhtjyoX -XAQ0+uFZnQJBANQg/Xpijb5NuK43cg1q/MLyR8vdp1AxvmpS0YnsObxJAqp79oT/ -EEU+WXEJKmxBWtVbwryraAnUamyUtG3rqzECQQCqUGSR9dcKEQBH47j5z66va/QC -pJqaHNcfNUdoEv9KwJABpSqJBovyrDVHWaQ0/bzbkvm7Jw/hC3mPgHx0Nn89AkBj -E+2QhguSQRbrODZrEfdwzly+WY7WJAW9/2SjONRWnvtByZiA0ek1jkOUSiWoXnYg -hTVVjfGP9cinYmVLmfFhAkA+L4iyT0uKjXoqugJU2wYDdLDNh3zPg4xu+Pg2Ua62 -SFr28bvOWI7g2DV6KX/gS1wKbSHbctUylJHQRxFaHSlX ------END RSA PRIVATE KEY----- diff --git a/packages/examples/src/testthing/testclient.ts b/packages/examples/src/testthing/testclient.ts deleted file mode 100644 index 672c387f2..000000000 --- a/packages/examples/src/testthing/testclient.ts +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020 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 - ********************************************************************************/ - -console.log = () => { - /* empty */ -}; -console.debug = () => { - /* empty */ -}; - -async function testPropertyRead(thing: WoT.ConsumedThing, name: string) { - try { - const res = await thing.readProperty(name); - const value = await res.value(); - console.info("PASS " + name + " READ:", value); - } catch (err) { - console.error("FAIL " + name + " READ:", JSON.stringify(err)); - } -} - -async function testPropertyWrite( - thing: WoT.ConsumedThing, - name: string, - value: WoT.InteractionInput, - shouldFail: boolean -) { - const displayValue = JSON.stringify(value); - try { - await thing.writeProperty(name, value); - if (!shouldFail) console.info("PASS " + name + " WRITE (" + displayValue + ")"); - else console.error("FAIL " + name + " WRITE: (" + displayValue + ")"); - } catch (err) { - if (!shouldFail) console.error("FAIL " + name + " WRITE (" + displayValue + "):", JSON.stringify(err)); - else console.info("PASS " + name + " WRITE (" + displayValue + "):", JSON.stringify(err)); - } -} - -WoT.requestThingDescription("http://localhost:8080/testthing") - .then(async (td) => { - try { - const thing = await WoT.consume(td); - console.info("=== TD ==="); - console.info(td); - console.info("=========="); - console.info(); - - console.info("========== bool"); - await testPropertyRead(thing, "bool"); - await testPropertyWrite(thing, "bool", true, false); - await testPropertyWrite(thing, "bool", false, false); - await testPropertyWrite(thing, "bool", "true", true); - - console.info("========== int"); - await testPropertyRead(thing, "int"); - await testPropertyWrite(thing, "int", 4711, false); - await testPropertyWrite(thing, "int", 3.1415, true); - await testPropertyWrite(thing, "int", "Pi", true); - - console.info("========== num"); - await testPropertyRead(thing, "num"); - await testPropertyWrite(thing, "num", 4711, false); - await testPropertyWrite(thing, "num", 3.1415, false); - await testPropertyWrite(thing, "num", "Pi", true); - - console.info("========== string"); - await testPropertyRead(thing, "string"); - await testPropertyWrite(thing, "string", "testclient", false); - await testPropertyWrite(thing, "string", 13, true); - await testPropertyWrite(thing, "string", null, true); - - console.info("========== array"); - await testPropertyRead(thing, "array"); - await testPropertyWrite(thing, "array", [23, "illuminated"], false); - await testPropertyWrite(thing, "array", { id: 24, name: "dark" }, true); - await testPropertyWrite(thing, "array", null, true); - - console.info("========== object"); - await testPropertyRead(thing, "object"); - await testPropertyWrite(thing, "object", { id: 23, name: "illuminated" }, false); - await testPropertyWrite(thing, "object", null, true); - await testPropertyWrite(thing, "object", [24, "dark"], true); - } catch (err) { - console.error("Script error:", err); - } - }) - .catch((err) => { - console.error("Fetch error:", err); - }); diff --git a/packages/examples/src/testthing/testthing.ts b/packages/examples/src/testthing/testthing.ts deleted file mode 100644 index 4590ee58b..000000000 --- a/packages/examples/src/testthing/testthing.ts +++ /dev/null @@ -1,307 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2020 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 - ********************************************************************************/ - -function checkPropertyWrite(expected: string, actual: unknown) { - const output = "Property " + expected + " written with " + actual; - if (expected === actual) { - console.info("PASS: " + output); - } else { - throw new Error("FAIL: " + output); - } -} - -function checkActionInvocation(name: string, expected: string, actual: unknown) { - const output = "Action " + name + " invoked with " + actual; - if (expected === actual) { - console.info("PASS: " + output); - } else { - throw new Error("FAIL: " + output); - } -} - -// init property values -let bool = false; -let int = 42; -let num = 3.14; -let string = "unset"; -let array: unknown[] = [2, "unset"]; -let object: Record = { id: 123, name: "abc" }; - -WoT.produce({ - title: "TestThing", - properties: { - bool: { - title: "Boolean", - description: "Property that can be set to true or false", - type: "boolean", - }, - int: { - title: "Integer", - description: "An integer value that can be read and written", - type: "integer", - }, - num: { - title: "Number", - description: "A floating point value that can be read and written", - type: "number", - }, - string: { - title: "String", - description: "A string value that can be read and written", - type: "string", - }, - array: { - title: "Array", - description: "An Array (List) with no structure that can be read and written", - type: "array", - items: {}, - }, - object: { - title: "Object", - description: "An object with id and name that can be read and written", - type: "object", - properties: { - id: { - title: "ID", - description: "Integer identifier", - type: "integer", - }, - name: { - title: "Name", - description: "Name associated to the identifier", - type: "string", - }, - }, - }, - }, - actions: { - "void-void": { - title: "void-void Action", - description: "Action without input nor output", - }, - "void-int": { - title: "void-int Action", - description: "Action without input, but with integer output", - }, - "int-void": { - title: "int-void Action", - description: "Action with integer input, but without output", - input: { type: "integer" }, - }, - "int-int": { - title: "int-int Action", - description: "Action with integer input and output", - input: { type: "integer" }, - output: { type: "integer" }, - }, - "int-string": { - title: "int-string Action", - description: "Action with integer input and string output", - input: { type: "integer" }, - output: { type: "string" }, - }, - "void-obj": { - title: "void-obj Action", - description: "Action without input, but with object output", - output: { - type: "object", - properties: { - prop1: { - type: "integer", - }, - prop2: { - type: "string", - }, - }, - required: ["prop1", "prop2"], - }, - }, - "obj-void": { - title: "obj-void Action", - description: "Action with object input, but without output", - input: { - type: "object", - properties: { - prop1: { type: "integer" }, - prop2: { type: "string" }, - }, - required: ["prop1", "prop2"], - }, - }, - }, - events: { - "on-bool": { - title: "Bool Property Change", - description: "Event with boolean data that is emitted when the bool property is written to", - data: { type: "boolean" }, - }, - "on-int": { - title: "Int Property Change", - description: "Event with integer data that is emitted when the int property is written to ", - data: { type: "integer" }, - }, - "on-num": { - title: "Num Property Change", - description: "Event with number data that is emitted when the num property is written to", - data: { type: "number" }, - }, - "on-string": { - title: "String Property Change", - description: "Event with number data that is emitted when the string property is written to", - data: { type: "number" }, - }, - "on-array": { - title: "Array Property Change", - description: "Event with number data that is emitted when the array property is written to", - data: { type: "number" }, - }, - "on-object": { - title: "Object Property Change", - description: "Event with number data that is emitted when the object property is written to", - data: { type: "number" }, - }, - }, -}) - .then((thing) => { - console.log("Produced " + thing.getThingDescription().title); - - // set property read/write handlers - thing - .setPropertyWriteHandler("bool", async (value) => { - const localBool = await value.value(); - checkPropertyWrite("boolean", typeof localBool); - bool = localBool as boolean; - thing.emitEvent("on-bool", bool); - }) - .setPropertyReadHandler("bool", async () => bool) - .setPropertyWriteHandler("int", async (value) => { - const localInt = await value.value(); - if (localInt === Math.floor(localInt as number)) { - checkPropertyWrite("integer", "integer"); - } else { - checkPropertyWrite("integer", typeof value); - } - int = localInt as number; - thing.emitEvent("on-int", int); - }) - .setPropertyReadHandler("int", async () => int) - .setPropertyWriteHandler("num", async (value) => { - const localNum = await value.value(); - checkPropertyWrite("number", typeof localNum); - num = localNum as number; - thing.emitEvent("on-num", num); - }) - .setPropertyReadHandler("num", async () => num) - .setPropertyWriteHandler("string", async (value) => { - const localString = await value.value(); - checkPropertyWrite("string", typeof localString); - string = localString as string; - thing.emitEvent("on-string", string); - }) - .setPropertyReadHandler("string", async () => string) - .setPropertyWriteHandler("array", async (value) => { - const localArray = await value.value(); - if (Array.isArray(localArray)) { - checkPropertyWrite("array", "array"); - } else { - checkPropertyWrite("array", typeof localArray); - } - array = localArray as unknown[]; - thing.emitEvent("on-array", array); - }) - .setPropertyReadHandler("array", async () => array) - .setPropertyWriteHandler("object", async (value) => { - const localObject = await value.value(); - if (Array.isArray(localObject)) { - checkPropertyWrite("object", "array"); - } else { - checkPropertyWrite("object", typeof localObject); - } - object = localObject as Record; - thing.emitEvent("on-object", object); - }) - .setPropertyReadHandler("object", async () => object); - - // set action handlers - thing - .setActionHandler("void-void", async (parameters) => { - checkActionInvocation("void-void", "undefined", typeof (await parameters.value())); - return undefined; - }) - .setActionHandler("void-int", async (parameters) => { - checkActionInvocation("void-int", "undefined", typeof (await parameters.value())); - return 0; - }) - .setActionHandler("int-void", async (parameters) => { - const localParameters = await parameters.value(); - if (localParameters === Math.floor(localParameters as number)) { - checkActionInvocation("int-void", "integer", "integer"); - } else { - checkActionInvocation("int-void", "integer", typeof parameters); - } - return undefined; - }) - .setActionHandler("int-int", async (parameters) => { - const localParameters = await parameters.value(); - if (localParameters === Math.floor(localParameters as number)) { - checkActionInvocation("int-int", "integer", "integer"); - } else { - checkActionInvocation("int-int", "integer", typeof localParameters); - } - return (localParameters as number) + 1; - }) - .setActionHandler("int-string", async (parameters) => { - const localParameters = await parameters.value(); - const inputtype = typeof localParameters; - if (localParameters === Math.floor(localParameters as number)) { - checkActionInvocation("int-string", "integer", "integer"); - } else { - checkActionInvocation("int-string", "integer", typeof localParameters); - } - - if (inputtype === "number") { - // eslint-disable-next-line no-new-wrappers - return new String(localParameters) - .replace(/0/g, "zero-") - .replace(/1/g, "one-") - .replace(/2/g, "two-") - .replace(/3/g, "three-") - .replace(/4/g, "four-") - .replace(/5/g, "five-") - .replace(/6/g, "six-") - .replace(/7/g, "seven-") - .replace(/8/g, "eight-") - .replace(/9/g, "nine-"); - } else { - throw new Error("ERROR"); - } - }) - .setActionHandler("void-obj", async (parameters) => { - checkActionInvocation("void-complex", "undefined", typeof (await parameters.value())); - return { prop1: 123, prop2: "abc" }; - }) - .setActionHandler("obj-void", async (parameters) => { - checkActionInvocation("complex-void", "object", typeof (await parameters.value())); - return undefined; - }); - - // expose the thing - thing.expose().then(() => { - console.info(thing.getThingDescription().title + " ready"); - }); - }) - .catch((e) => { - console.log(e); - }); diff --git a/packages/examples/tsconfig.json b/packages/examples/tsconfig.json deleted file mode 100644 index 63049fbba..000000000 --- a/packages/examples/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src", - "target": "ES2018", - "sourceMap": false, - "removeComments": false - }, - "include": ["src/**/*"], - "references": [{ "path": "../td-tools" }] -}