├── .dockerignore ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitattributes ├── .github ├── CODEOWNERS └── workflows │ ├── browser-test.yml │ └── ci.yaml ├── .gitignore ├── .husky ├── pre-commit └── pre-push ├── .prettierignore ├── .prettierrc.json ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── API.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.md ├── NOTICE.md ├── README.md ├── SECURITY.md ├── codecov.yml ├── examples ├── browser │ ├── counter.html │ ├── counter.js │ ├── images │ │ └── coffee-161112.svg │ ├── index.html │ ├── index.js │ ├── smart-coffee-machine.html │ ├── smart-coffee-machine.js │ └── styles.css ├── quickstart │ ├── README.md │ ├── presence-sensor.js │ ├── simple-coffee-machine.js │ └── smart-clock.js ├── scripts │ ├── $DO_NOT_EDIT_JS_FILES.md │ ├── countdown.js │ ├── counter-client.js │ ├── counter.js │ ├── smart-coffee-machine-client.conf.json │ ├── smart-coffee-machine-client.js │ ├── smart-coffee-machine.js │ └── wot-servient.conf.json ├── security │ ├── README.md │ ├── certificate.pem │ ├── oauth │ │ ├── README.md │ │ ├── consumer.js │ │ ├── exposer.js │ │ ├── memory-model.js │ │ ├── package.json │ │ ├── server.js │ │ ├── wot-client-servient-conf.json │ │ └── wot-server-servient-conf.json │ ├── privatekey.pem │ └── wot-servient.conf.json ├── templates │ └── exposed-thing │ │ ├── README.md │ │ ├── index.js │ │ ├── package.json │ │ ├── src │ │ └── base.ts │ │ └── tsconfig.json └── testthing │ ├── $DO_NOT_EDIT_JS_FILES.md │ ├── testclient.js │ └── testthing.js ├── license.template.txt ├── package-lock.json ├── package.json ├── packages ├── binding-coap │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── coap-client-factory.ts │ │ ├── coap-client.ts │ │ ├── coap-server.ts │ │ ├── coap.ts │ │ ├── coaps-client-factory.ts │ │ ├── coaps-client.ts │ │ ├── mdns-introducer.ts │ │ └── util.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── coap-client-test.ts │ │ ├── coap-server-test.ts │ │ ├── coap-types-test.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── binding-file │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── file-client-factory.ts │ │ ├── file-client.ts │ │ └── file.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── .gitignore │ │ └── file-client-test.ts │ └── tsconfig.json ├── binding-http │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── codecs │ │ │ └── tuya-codec.ts │ │ ├── credential.ts │ │ ├── http-browser.ts │ │ ├── http-client-browser.ts │ │ ├── http-client-factory.ts │ │ ├── http-client-impl.ts │ │ ├── http-client.ts │ │ ├── http-server-middleware.ts │ │ ├── http-server.ts │ │ ├── http.ts │ │ ├── https-client-factory.ts │ │ ├── oauth-manager.ts │ │ ├── oauth-token-validation.ts │ │ ├── routes │ │ │ ├── action.ts │ │ │ ├── common.ts │ │ │ ├── event.ts │ │ │ ├── properties.ts │ │ │ ├── property-observe.ts │ │ │ ├── property.ts │ │ │ ├── thing-description.ts │ │ │ └── things.ts │ │ └── subscription-protocols.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── credential-test.ts │ │ ├── http-client-basic-test.ts │ │ ├── http-client-oauth-tests.ts │ │ ├── http-client-test.ts │ │ ├── http-server-oauth-tests.ts │ │ ├── http-server-test.ts │ │ ├── memory-model.ts │ │ ├── oauth-token-validation-tests.ts │ │ ├── server.cert │ │ ├── server.key │ │ └── tsconfig.json │ └── tsconfig.json ├── binding-mbus │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── mbus-client-factory.ts │ │ ├── mbus-client.ts │ │ ├── mbus-connection.ts │ │ ├── mbus.ts │ │ └── node-mbus.d.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── mbus-client-test.ts │ │ ├── mbus-connection-test.ts │ │ ├── test-servient.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── binding-modbus │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── modbus-client-factory.ts │ │ ├── modbus-client.ts │ │ ├── modbus-connection.ts │ │ ├── modbus.ts │ │ └── utils.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── modbus-client-test.ts │ │ ├── modbus-connection-test.ts │ │ ├── test-modbus-server.ts │ │ ├── test-servient.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── binding-mqtt │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── mqtt-broker-server.ts │ │ ├── mqtt-client-factory.ts │ │ ├── mqtt-client.ts │ │ ├── mqtt-message-pool.ts │ │ ├── mqtt.ts │ │ ├── mqtts-client-factory.ts │ │ └── util.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── mqtt-broker-server-interaction-test.integration.ts │ │ ├── mqtt-client-subscribe-test.integration.ts │ │ ├── mqtt-client-subscribe-test.unit.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── binding-netconf │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── async-node-netconf.ts │ │ ├── codecs │ │ │ └── netconf-codec.ts │ │ ├── netconf-client-factory.ts │ │ ├── netconf-client.ts │ │ ├── netconf.ts │ │ └── xpath2json.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── netconf-client-test.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── binding-opcua │ ├── .eslintrc.json │ ├── .mocharc.yml │ ├── README.md │ ├── package.json │ ├── src │ │ ├── codec.ts │ │ ├── factory.ts │ │ ├── index.ts │ │ └── opcua-protocol-client.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── client-test.ts │ │ ├── fixture │ │ │ └── basic-opcua-server.ts │ │ ├── full-opcua-thing-test.ts │ │ ├── opcua-codec-test.ts │ │ ├── opcua-href-test.ts │ │ └── schema-validation-test.ts │ └── tsconfig.json ├── binding-websockets │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── ws-browser.ts │ │ ├── ws-client-factory.ts │ │ ├── ws-client.ts │ │ ├── ws-server.ts │ │ ├── ws.ts │ │ └── wss-client-factory.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── tsconfig.json │ │ └── ws-tests.ts │ └── tsconfig.json ├── browser-bundle │ ├── .gitignore │ ├── README.md │ ├── esbuild.js │ ├── index.ts │ ├── package.json │ ├── test │ │ ├── main.js │ │ └── resources │ │ │ └── test-thing.tm.json │ ├── tsconfig.json │ └── web-test-runner.config.mjs ├── cli │ ├── .eslintrc.json │ ├── README.md │ ├── bin │ │ └── index.js │ ├── package.json │ ├── src │ │ ├── cli-default-servient.ts │ │ ├── cli.ts │ │ └── wot-servient-schema.conf.json │ ├── test │ │ ├── .eslintrc.json │ │ ├── RuntimeTest.ts │ │ └── tsconfig.json │ ├── tsconfig.json │ └── wot-servient.conf.json.md ├── core │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ │ ├── codecs │ │ │ ├── base64-codec.ts │ │ │ ├── cbor-codec.ts │ │ │ ├── json-codec.ts │ │ │ ├── octetstream-codec.ts │ │ │ └── text-codec.ts │ │ ├── consumed-thing.ts │ │ ├── content-serdes.ts │ │ ├── content.ts │ │ ├── core.ts │ │ ├── errors.ts │ │ ├── exposed-thing.ts │ │ ├── helpers.ts │ │ ├── interaction-output.ts │ │ ├── logger.ts │ │ ├── protocol-helpers.ts │ │ ├── protocol-interfaces.ts │ │ ├── protocol-listener-registry.ts │ │ ├── serdes.ts │ │ ├── servient.ts │ │ ├── thing-description.ts │ │ ├── validation.ts │ │ └── wot-impl.ts │ ├── test │ │ ├── .eslintrc.json │ │ ├── ClientTest.ts │ │ ├── ContentSerdesTest.ts │ │ ├── DiscoveryTest.ts │ │ ├── HelpersTest.ts │ │ ├── InteractionOutputTest.ts │ │ ├── ProtocolHelpersStreamTest.ts │ │ ├── ProtocolHelpersTest.ts │ │ ├── ProtocolListenerRegistryTest.ts │ │ ├── SerDesTest.ts │ │ ├── ServerTest.ts │ │ └── tsconfig.json │ └── tsconfig.json └── examples │ ├── .eslintrc.json │ ├── README.md │ ├── package.json │ ├── src │ ├── bindings │ │ ├── coap │ │ │ ├── example-client.ts │ │ │ └── example-server.ts │ │ ├── http │ │ │ ├── example-client.ts │ │ │ ├── example-server-secure.ts │ │ │ └── example-server.ts │ │ └── opcua │ │ │ ├── demo-opcua-thing-description.ts │ │ │ ├── demo-opcua1.ts │ │ │ ├── demo-opcua2.ts │ │ │ ├── opcua-coffee-machine-demo.ts │ │ │ └── opcua-coffee-machine-thing-description.ts │ ├── quickstart │ │ ├── README.md │ │ ├── presence-sensor.ts │ │ ├── simple-coffee-machine.ts │ │ └── smart-clock.ts │ ├── scripts │ │ ├── countdown.ts │ │ ├── counter-client.ts │ │ ├── counter.ts │ │ ├── smart-coffee-machine-client.ts │ │ └── smart-coffee-machine.ts │ ├── security │ │ ├── certificate.pem │ │ ├── oauth │ │ │ ├── README.md │ │ │ ├── consumer.ts │ │ │ ├── exposer.ts │ │ │ ├── memory-model.js │ │ │ ├── package.json │ │ │ ├── server.js │ │ │ ├── tsconfig.json │ │ │ ├── wot-client-servient-conf.json │ │ │ └── wot-server-servient-conf.json │ │ └── privatekey.pem │ └── testthing │ │ ├── testclient.ts │ │ └── testthing.ts │ └── tsconfig.json ├── tsconfig.eslint.json ├── tsconfig.json └── utils ├── .eslintrc.json └── check_package_version_consistency.js /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .vscode 3 | .idea/ 4 | .nyc_output/ 5 | examples 6 | **/node_modules/ 7 | node_modules/ 8 | coverage/ 9 | .*/ 10 | tmp/ 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [{src,test}/**.{ts,json,js}] 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 4 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | packages/browser-bundle/web-test-runner.config.mjs 2 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | parserOptions: { 4 | tsconfigRootDir: __dirname, 5 | project: ["./tsconfig.eslint.json"], 6 | }, 7 | extends: [ 8 | "eslint:recommended", 9 | "standard", 10 | "prettier", 11 | "plugin:@typescript-eslint/recommended", 12 | "plugin:workspaces/recommended", 13 | ], 14 | plugins: ["@typescript-eslint", "unused-imports", "workspaces", "notice"], 15 | env: { 16 | es6: true, 17 | node: true, 18 | }, 19 | ignorePatterns: [".eslintrc.js", "dist", "node_modules", "/examples", "bin", "*.js"], 20 | rules: { 21 | "notice/notice": [ 22 | "error", 23 | { 24 | mustMatch: "Copyright \\(c\\) [0-9]{0,4} Contributors to the Eclipse Foundation", 25 | templateFile: __dirname + "/license.template.txt", 26 | onNonMatchingHeader: "replace", 27 | }, 28 | ], 29 | "@typescript-eslint/no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off", 30 | "no-use-before-define": "off", 31 | "@typescript-eslint/no-use-before-define": ["error"], 32 | "@typescript-eslint/prefer-nullish-coalescing": "error", 33 | "unused-imports/no-unused-imports": "error", 34 | "@typescript-eslint/strict-boolean-expressions": "error", 35 | "import/no-extraneous-dependencies": "error", 36 | "guard-for-in": "error", 37 | "unused-imports/no-unused-vars": [ 38 | "warn", 39 | { 40 | args: "none", 41 | varsIgnorePattern: "Test", // Ignore test suites from unused-imports 42 | }, 43 | ], 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behaviour, in case users don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files we want to always be normalized and converted 5 | # to native line endings on checkout. 6 | 7 | # Declare files that will always have LF line endings on checkout. 8 | *.c text eol=lf 9 | *.css text eol=lf 10 | *.cpp text eol=lf 11 | .editorconfig text eol=lf 12 | .gitattributes text eol=lf 13 | .gitignore text eol=lf 14 | .gitmodules text eol=lf 15 | *.gyp text eol=lf 16 | *.h text eol=lf 17 | *.hpp text eol=lf 18 | *.js text eol=lf 19 | *.ts text eol=lf 20 | *.json text eol=lf 21 | LICENSE text eol=lf 22 | *.md text eol=lf 23 | *.svg text eol=lf 24 | *.sh text eol=lf 25 | 26 | # Declare files that will always have CRLF line endings on checkout. 27 | *.bat text eol=crlf 28 | *.cmd text eol=crlf 29 | 30 | # Denote all files that are truly binary and should not be modified. 31 | *.gif binary 32 | *.jpg binary 33 | *.node binary 34 | *.png binary 35 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Default owners (used as a fallback, last matching pattern takes the most precedence) 2 | * @danielpeintner @relu91 3 | 4 | # CoAP-Binding 5 | /packages/binding-coap/ @JKRhb 6 | 7 | # HTTP-Binding 8 | /packages/binding-http/ @danielpeintner @relu91 9 | 10 | # Mbus-Binding 11 | # /packages/binding-modbus/ 12 | 13 | # Modbus-Binding 14 | /packages/binding-modbus/ @relu91 15 | 16 | # MQTT-Binding 17 | /packages/binding-mqtt/ @sebastiankb @egekorkan 18 | 19 | # NETCONF Binding 20 | # /packages/binding-netconf/ 21 | 22 | # OPCUA Binding 23 | # /packages/binding-opcua/ 24 | 25 | # WebSockets Binding 26 | # /packages/binding-websockets/ 27 | 28 | # Browser Bundle 29 | /packages/browser-bundle/ @danielpeintner @relu91 30 | 31 | # CLI 32 | /packages/browser-bundle/ @danielpeintner @relu91 @mkovatsc 33 | 34 | # Core 35 | /packages/core/ @danielpeintner @relu91 @JKRhb 36 | 37 | # TD Tools 38 | /packages/td-tools/ @danielpeintner @relu91 39 | -------------------------------------------------------------------------------- /.github/workflows/browser-test.yml: -------------------------------------------------------------------------------- 1 | # docs https://playwright.dev/docs/ci-intro#setting-up-github-actions 2 | name: Browser Tests 3 | 4 | on: 5 | workflow_dispatch: 6 | push: 7 | branches: [master] 8 | pull_request: 9 | branches: [master] 10 | 11 | jobs: 12 | test-browser: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | - name: Use Node.js 20.x 17 | uses: actions/setup-node@v4 18 | with: 19 | node-version: 20.x 20 | cache: "npm" 21 | - name: Install Dependencies 22 | run: npm ci 23 | - name: Install linux rollup optional dependencies 24 | run: npm i @rollup/rollup-linux-x64-gnu -D 25 | - name: Install Playwright Browsers 26 | run: npx playwright install --with-deps 27 | - name: Build 28 | run: npm run build 29 | - name: Test with browser bundle 30 | timeout-minutes: 2 31 | run: | 32 | npm run test:browser 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # ignore dist 40 | dist/ 41 | 42 | # ignore compiled tests and scratch compiles 43 | test/**/*.js 44 | src/**/*.js 45 | 46 | # ignore private packages 47 | packages/* 48 | !packages/core 49 | !packages/binding-file 50 | !packages/binding-http 51 | !packages/binding-coap 52 | !packages/binding-websockets 53 | !packages/binding-mqtt 54 | !packages/binding-modbus 55 | !packages/binding-opcua 56 | !packages/binding-netconf 57 | !packages/binding-modbus 58 | !packages/binding-mbus 59 | !packages/cli 60 | !packages/browser-bundle 61 | !packages/examples 62 | 63 | # JetBrains IDEs 64 | .idea/ 65 | 66 | # tsc build info 67 | tsconfig.tsbuildinfo 68 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run format:quick -- --staged 5 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run test 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | **/dist 3 | coverage 4 | .nyc_output 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "printWidth": 120, 4 | "singleQuote": false, 5 | "tabWidth": 4, 6 | "endOfLine": "lf" 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "./node_modules/typescript/lib", 3 | "typescript.referencesCodeLens.enabled": true, 4 | "files.exclude": { 5 | "**/.git": true, 6 | "**/.svn": true, 7 | "**/.hg": true, 8 | "**/.DS_Store": true, 9 | "src/**/*.js": true, 10 | "test/**/*.js": true 11 | }, 12 | "files.encoding": "utf8", 13 | "files.eol": "\n", 14 | "files.insertFinalNewline": true, 15 | "files.trimFinalNewlines": true, 16 | "files.trimTrailingWhitespace": true, 17 | "editor.tabSize": 4, 18 | "editor.insertSpaces": true 19 | } 20 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "command": "npm", 6 | "args": ["run"], 7 | "echoCommand": true, 8 | "problemMatcher": "$tsc", 9 | "tasks": [ 10 | { 11 | "label": "build", 12 | "type": "shell", 13 | "command": "npm", 14 | "args": ["run", "build"], 15 | "group": "build" 16 | }, 17 | { 18 | "label": "test", 19 | "type": "shell", 20 | "command": "npm", 21 | "args": ["run", "test"] 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/library/node:18-alpine as BUILD 2 | RUN apk add --no-cache \ 3 | gcc \ 4 | g++ \ 5 | make \ 6 | linux-headers \ 7 | udev \ 8 | python3 9 | 10 | ## change it to maintain all the dev dependencies 11 | ARG BUILD_ENV=production 12 | WORKDIR /app 13 | COPY ./package.json ./ 14 | COPY ./package-lock.json ./ 15 | COPY ./tsconfig.json ./ 16 | COPY ./packages packages/ 17 | 18 | RUN npm install && npm run build 19 | 20 | # now remove dev dependencies by reinstalling for production 21 | # this wil reduce the size of the image built in next steps significantly 22 | RUN if [ "${BUILD_ENV}" = "production" ]; then npm prune --production; fi 23 | 24 | FROM docker.io/library/node:18-alpine 25 | 26 | COPY --from=BUILD /app /app 27 | 28 | WORKDIR /app/packages/cli 29 | 30 | EXPOSE 8080/tcp 31 | EXPOSE 5683/udp 32 | 33 | STOPSIGNAL SIGINT 34 | 35 | ENTRYPOINT [ "node", "dist/cli.js" ] 36 | CMD [ "-h" ] 37 | 38 | ## docker build -t wot-servient ./docker/Dockerfile 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Contributors to the Eclipse Foundation 2 | 3 | See the NOTICE file(s) distributed with this work for additional 4 | information regarding copyright ownership. 5 | 6 | This program and the accompanying materials are made available under the 7 | terms of the Eclipse Public License v. 2.0 which is available at 8 | http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 9 | Document License (2015-05-13) which is available at 10 | https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 11 | 12 | SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 13 | -------------------------------------------------------------------------------- /NOTICE.md: -------------------------------------------------------------------------------- 1 | # Notices for Eclipse Thingweb 2 | 3 | This content is produced and maintained by the Eclipse Thingweb project. 4 | 5 | - Project home: https://projects.eclipse.org/projects/iot.thingweb 6 | 7 | ## Trademarks 8 | 9 | Eclipse Thingweb is a trademark of the Eclipse Foundation. 10 | 11 | ## Copyright 12 | 13 | All content is the property of the respective authors or their employers. For 14 | more information regarding authorship of content, please consult the listed 15 | source code repository logs. 16 | 17 | Note: The {year} in the copyright statements is the year in which the content 18 | was created (e.g. “2004”). A range of years is not used. 19 | 20 | ## Declared Project Licenses 21 | 22 | This program and the accompanying materials are made available under the terms 23 | of the Eclipse Public License v. 2.0 which is available at 24 | http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and Document 25 | License (2015-05-13) which is available at 26 | https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 27 | 28 | SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 29 | 30 | ## Source Code 31 | 32 | The project maintains the following source code repositories: 33 | 34 | ## Third-party Content 35 | 36 | ## Cryptography 37 | 38 | Content may contain encryption software. The country in which you are currently 39 | may have restrictions on the import, possession, and use, and/or re-export to 40 | another country, of encryption software. BEFORE using any encryption software, 41 | please check the country's laws, regulations and policies concerning the import, 42 | possession, or use, and re-export of encryption software, to see if this is 43 | permitted. 44 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | _ISO 27005 defines vulnerability as: 4 | "A weakness of an asset or group of assets that can be exploited by one or more threats."_ 5 | 6 | ## Eclipse Foundation Security Team 7 | 8 | The Eclipse Foundation Security Team provides help and advice to Eclipse projects on security issues and is the first point of contact for handling security vulnerabilities. Members of the Security Team are selected from committers on Eclipse Projects, members of the [Eclipse Architecture Council](https://www.eclipse.org/projects/handbook/#roles-ac), and Eclipse Foundation staff. 9 | 10 | ## Reporting a Security Vulnerability 11 | 12 | Vulnerabilities can be reported either via email to [security@eclipse-foundation.org](mailto:security@eclipse-foundation.org) or directly with a project via the Eclipse Foundation’s [issue tracker](https://gitlab.eclipse.org/security/vulnerability-reports/-/issues/new?issuable_template=new_vulnerability). 13 | 14 | The general [security team email address](mailto:security@eclipse-foundation.org) can also be used to report vulnerabilities. Members of the Eclipse Foundation Security Team will receive messages sent to this address. This address should be used only for reporting undisclosed vulnerabilities; regular issue reports and questions unrelated to vulnerabilities in Eclipse Foundation project software will be ignored. Note that this email address is not encrypted. 15 | 16 | ## Disclosure 17 | 18 | Disclosure is initially limited to the reporter, the project team and the Eclipse Foundation Security Team, but is expanded to include other individuals, and the general public. The timing and manner of disclosure is governed by the [Eclipse Foundation Vulnerability Reporting Policy](https://www.eclipse.org/security/policy.php). 19 | 20 | Publicly disclosed issues are listed on the [Known Eclipse Security Vulnerabilities](https://www.eclipse.org/security/known.php) page. 21 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | informational: true 6 | patch: 7 | default: 8 | informational: true 9 | # When modifying this file, please validate using 10 | # curl -X POST --data-binary @codecov.yml https://codecov.io/validate 11 | -------------------------------------------------------------------------------- /examples/browser/smart-coffee-machine.js: -------------------------------------------------------------------------------- 1 | /** 2 | * In the browser, node-wot only works in client mode with limited binding support. 3 | * Supported bindings: HTTP / HTTPS / WebSockets 4 | * 5 | * After adding the following 7 | * 8 | * you can access all node-wot functionality / supported packages through the "WoT" global object. 9 | * Examples: 10 | * var servient = new WoT.Core.Servient(); 11 | * var client = new WoT.Http.HttpClient(); 12 | * 13 | **/ 14 | 15 | // A URL to the smart coffee machine Thing Description 16 | const TD_URL = "http://plugfest.thingweb.io:8083/smart-coffee-machine"; 17 | // How often to update the property values (in ms) 18 | const UPDATE_PERIOD = 2000; 19 | 20 | function get_td(addr) { 21 | servient.start().then((thingFactory) => { 22 | helpers 23 | .fetch(addr) 24 | .then((td) => { 25 | thingFactory.consume(td).then((thing) => { 26 | showProperties(thing); 27 | }); 28 | }) 29 | .catch((error) => { 30 | window.alert("Could not fetch TD.\n" + error); 31 | }); 32 | }); 33 | } 34 | 35 | function showProperties(thing) { 36 | let td = thing.getThingDescription(); 37 | let row = 0; 38 | for (let property in td.properties) { 39 | if (td.properties.hasOwnProperty(property)) { 40 | thing.readProperty(property).then(async (iOutput) => { 41 | const value = await iOutput.value(); 42 | const el = document.getElementById(property); 43 | if (!el) { 44 | // Create a property record if not found 45 | const tbody = document.getElementById("properties").getElementsByTagName("tbody")[0]; 46 | const tr = document.createElement("tr"); 47 | tr.innerHTML = `
${property}
${JSON.stringify(
48 |                         value,
49 |                         null,
50 |                         2
51 |                     )}
`; 52 | if (row % 2 !== 0) { 53 | tr.style.background = "#FFFAF0"; 54 | } 55 | tbody.appendChild(tr); 56 | row++; 57 | } else { 58 | // Otherwise just update its value 59 | el.innerHTML = `
${JSON.stringify(value, null, 2)}
`; 60 | } 61 | }); 62 | } 63 | } 64 | // Update the property values after UPDATE_PERIOD time 65 | setTimeout(function () { 66 | showProperties(thing); 67 | }, UPDATE_PERIOD); 68 | } 69 | 70 | var servient = new WoT.Core.Servient(); 71 | servient.addClientFactory(new WoT.Http.HttpClientFactory()); 72 | var helpers = new WoT.Core.Helpers(servient); 73 | get_td(TD_URL); 74 | -------------------------------------------------------------------------------- /examples/browser/styles.css: -------------------------------------------------------------------------------- 1 | /* Base styles */ 2 | body { 3 | padding: 20px; 4 | background: #f5f5f5; 5 | font-family: Arial, sans-serif; 6 | } 7 | 8 | /* Top bar */ 9 | #topbar { 10 | background: white; 11 | padding: 15px; 12 | margin-bottom: 20px; 13 | border: 1px solid #ddd; 14 | } 15 | 16 | /* Tabs */ 17 | .tabs { 18 | margin: 0 0 10px 0; 19 | padding: 0; 20 | list-style: none; 21 | border-bottom: 1px solid #ddd; 22 | } 23 | 24 | .tabs li { 25 | display: inline-block; 26 | margin-right: 5px; 27 | } 28 | 29 | .tabs a { 30 | display: block; 31 | padding: 8px 12px; 32 | text-decoration: none; 33 | color: #333; 34 | background: #f0f0f0; 35 | border: 1px solid #ddd; 36 | border-bottom: none; 37 | } 38 | 39 | .tabs .active a { 40 | background: white; 41 | border-bottom: 1px solid white; 42 | margin-bottom: -1px; 43 | } 44 | 45 | /* Tab content */ 46 | .tabs-content { 47 | background: white; 48 | padding: 15px; 49 | border: 1px solid #ddd; 50 | border-top: none; 51 | } 52 | 53 | /* Form elements */ 54 | #td_addr, 55 | #exampleUrls { 56 | width: 100%; 57 | padding: 8px; 58 | margin-bottom: 10px; 59 | border: 1px solid #ddd; 60 | } 61 | 62 | #fetch { 63 | background: #0066cc; 64 | color: white; 65 | border: none; 66 | padding: 8px 16px; 67 | cursor: pointer; 68 | } 69 | 70 | /* Interactions */ 71 | #interactions { 72 | margin-top: 20px; 73 | background: white; 74 | padding: 15px; 75 | border: 1px solid #ddd; 76 | } 77 | 78 | #interactions h4 { 79 | margin-top: 0; 80 | padding-bottom: 8px; 81 | border-bottom: 1px solid #eee; 82 | } 83 | 84 | /* Navigation */ 85 | .side-nav { 86 | margin: 0; 87 | padding: 0; 88 | list-style: none; 89 | } 90 | 91 | .side-nav li { 92 | padding: 8px 0; 93 | border-bottom: 1px solid #f0f0f0; 94 | } 95 | 96 | .side-nav li:last-child { 97 | border-bottom: none; 98 | } 99 | -------------------------------------------------------------------------------- /examples/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Quick Start Things 2 | 3 | This set of Things can be used to build mashup applications for a smart home scenario. 4 | These Things are: 5 | 6 | - Simple coffee machine that can take an order to brew a coffee. 7 | - Presence sensor that emits an event when a person is detected. 8 | - Smart clock that runs 60 times faster than real time, where 1 hour happens in 1 minute. 9 | 10 | These Things are hosted on plugfest.thingweb.io but can be also self-hosted. 11 | -------------------------------------------------------------------------------- /examples/quickstart/presence-sensor.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /******************************************************************************** 3 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 4 | * 5 | * See the NOTICE file(s) distributed with this work for additional 6 | * information regarding copyright ownership. 7 | * 8 | * This program and the accompanying materials are made available under the 9 | * terms of the Eclipse Public License v. 2.0 which is available at 10 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 11 | * Document License (2015-05-13) which is available at 12 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 13 | * 14 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 15 | ********************************************************************************/ 16 | // This is an example Thing script which is a simple presence detector 17 | // It fires an event when it detects a person (mocked as every 5 second) 18 | const core_1 = require("@node-wot/core"); 19 | const binding_mqtt_1 = require("@node-wot/binding-mqtt"); 20 | // create Servient add MQTT binding with port configuration 21 | const servient = new core_1.Servient(); 22 | servient.addServer(new binding_mqtt_1.MqttBrokerServer({ uri: "mqtt://test.mosquitto.org" })); 23 | servient.start().then((WoT) => { 24 | WoT.produce({ 25 | title: "PresenceSensor", 26 | description: "Thing that can detect presence of human nearby", 27 | support: "https://github.com/eclipse-thingweb/node-wot/", 28 | "@context": "https://www.w3.org/2022/wot/td/v1.1", 29 | events: { 30 | presenceDetected: { 31 | title: "Presence Detected", 32 | description: 33 | "An event that is emitted when a person is detected in the room. It is mocked and emitted every 5 seconds", 34 | data: { 35 | type: "number", 36 | title: "Distance", 37 | minimum: 55, 38 | maximum: 1200, 39 | }, 40 | }, 41 | }, 42 | }) 43 | .then((thing) => { 44 | console.log("Produced " + thing.getThingDescription().title); 45 | // expose the thing 46 | thing.expose().then(() => { 47 | console.info(thing.getThingDescription().title + " ready"); 48 | // mocking the detection with an event sent every 5 seconds, with a random distance 49 | setInterval(() => { 50 | const distance = Math.random() * (1200 - 55) + 55; 51 | thing.emitEvent("presenceDetected", distance); 52 | console.info("Emitted presence with distance ", distance); 53 | }, 5000); 54 | }); 55 | }) 56 | .catch((e) => { 57 | console.log(e); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /examples/scripts/$DO_NOT_EDIT_JS_FILES.md: -------------------------------------------------------------------------------- 1 | # Note 2 | 3 | The JavaScript files in this folder are generated by the workflow described [here](https://github.com/eclipse-thingweb/node-wot/tree/master/packages/examples#workflow). 4 | -------------------------------------------------------------------------------- /examples/scripts/counter-client.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | function getFormIndexForDecrementWithCoAP(thing) { 17 | const forms = thing.getThingDescription().actions?.decrement.forms; 18 | if (forms !== undefined) { 19 | for (let i = 0; i < forms.length; i++) { 20 | if (/^coaps?:\/\/.*/.test(forms[i].href)) { 21 | return i; 22 | } 23 | } 24 | } 25 | // return formIndex: 0 if no CoAP target IRI found 26 | return 0; 27 | } 28 | WoT.requestThingDescription("coap://localhost:5683/counter") 29 | .then(async (td) => { 30 | try { 31 | const thing = await WoT.consume(td); 32 | console.info("=== TD ==="); 33 | console.info(td); 34 | console.info("=========="); 35 | // read property #1 36 | const read1 = await thing.readProperty("count"); 37 | console.log("count value is", await read1.value()); 38 | // increment property #1 (without step) 39 | await thing.invokeAction("increment"); 40 | const inc1 = await thing.readProperty("count"); 41 | console.info("count value after increment #1 is", await inc1.value()); 42 | // increment property #2 (with step) 43 | await thing.invokeAction("increment", undefined, { uriVariables: { step: 3 } }); 44 | const inc2 = await thing.readProperty("count"); 45 | console.info("count value after increment #2 (with step 3) is", await inc2.value()); 46 | // look for the first form for decrement with CoAP binding 47 | await thing.invokeAction("decrement", undefined, { 48 | formIndex: getFormIndexForDecrementWithCoAP(thing), 49 | }); 50 | const dec1 = await thing.readProperty("count"); 51 | console.info("count value after decrement is", await dec1.value()); 52 | } catch (err) { 53 | console.error("Script error:", err); 54 | } 55 | }) 56 | .catch((err) => { 57 | console.error("Fetch error:", err); 58 | }); 59 | -------------------------------------------------------------------------------- /examples/scripts/smart-coffee-machine-client.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "http": { 3 | "allowSelfSigned": true 4 | }, 5 | "credentials": { 6 | "urn:dev:wot:example:smart-coffee-machine": { 7 | "clientId": "node-wot", 8 | "clientSecret": "isgreat!" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/scripts/wot-servient.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "servient": { 3 | "_staticAddress": "plugfest.thingweb.io", 4 | "scriptDir": ".", 5 | "scriptAction": true 6 | }, 7 | "http": { 8 | "port": 8080, 9 | "allowSelfSigned": true 10 | }, 11 | "coap": { 12 | "port": 5683 13 | }, 14 | "mqtt": { 15 | "broker": "mqtt://test.mosquitto.org", 16 | "_username": "username", 17 | "_password": "password", 18 | "_clientId": "uniqueId", 19 | "protocolVersion": 5 20 | }, 21 | "opcua": { 22 | "subscriptionOptions": { 23 | "requestedPublishingInterval": 1000, 24 | "requestedLifetimeCount": 100, 25 | "requestedMaxKeepAliveCount": 10, 26 | "maxNotificationsPerPublish": 100, 27 | "publishingEnabled": true, 28 | "priority": 10 29 | } 30 | }, 31 | "log": { 32 | "level": "info" 33 | }, 34 | "credentials": { 35 | "urn:dev:wot:org:eclipse:leshan": { 36 | "identity": "node-wot", 37 | "psk": "hello" 38 | }, 39 | "urn:dev:wot:org:eclipse:cf-secure": { 40 | "identity": "password", 41 | "psk": "sesame" 42 | }, 43 | "urn:dev:wot:org:eclipse:netconf-example": { 44 | "username": "root", 45 | "password": "root" 46 | }, 47 | "urn:dev:wot:org:eclipse:opcua-example-certificate": { 48 | "clientCertificate": "~/certificates/client_cert.pem", 49 | "clientPrivateKey": "~/certificates/client_private_key.pem", 50 | "serverCertificate": "~/certificates/server_cert.pem" 51 | }, 52 | "urn:dev:wot:org:eclipse:opcua-example-password": { 53 | "username": "root", 54 | "password": "root" 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/security/README.md: -------------------------------------------------------------------------------- 1 | # How to create .pem files 2 | 3 | 1. `openssl genrsa -out privatekey.pem 1024` 4 | 2. `openssl req -new -key privatekey.pem -out certrequest.csr` 5 | 3. `openssl x509 -req -in certrequest.csr -signkey privatekey.pem -out certificate.pem` 6 | 7 | # Secure Example 8 | 9 | see `example-server-secure.js` in https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-http#server-example 10 | -------------------------------------------------------------------------------- /examples/security/certificate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICYzCCAcwCCQD3LJYj+TYO2TANBgkqhkiG9w0BAQsFADB2MRkwFwYDVQQKDBBF 3 | Y2xpcHNlIFRoaW5nd2ViMREwDwYDVQQLDAhub2RlLXdvdDEdMBsGA1UEAwwUcGx1 4 | Z2Zlc3QudGhpbmd3ZWIuaW8xJzAlBgkqhkiG9w0BCQEWGGRldi10aGluZ3dlYkBl 5 | Y2xpcHNlLm9yZzAeFw0xODEwMjExMTU0MjNaFw0xODExMjAxMTU0MjNaMHYxGTAX 6 | BgNVBAoMEEVjbGlwc2UgVGhpbmd3ZWIxETAPBgNVBAsMCG5vZGUtd290MR0wGwYD 7 | VQQDDBRwbHVnZmVzdC50aGluZ3dlYi5pbzEnMCUGCSqGSIb3DQEJARYYZGV2LXRo 8 | aW5nd2ViQGVjbGlwc2Uub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDY 9 | 05qXs2BFbdtsS9dQAxIEz94vO2/VsGmJbq5eLWU+vUSt+jW5xrenfWKlqATPAiYu 10 | wH5zYa4x0Qf1HwpC4H2CP+PJOE7s+Gbt3eN9Gv3z/6LgOLrK1NlREOS9hGukEdSH 11 | bXiz4Aftz0K5NR8sAeWGaNn/OK8UlBPX7ekV6tWQ/wIDAQABMA0GCSqGSIb3DQEB 12 | CwUAA4GBAMQ8QzKoDbG6niS3lDV7oYkaJQJsk9v4dfNvg0AP8pE6Id1juw+PVLU+ 13 | wSaJh9GOKHTEvGQ/wJie6ZsdGzlKhRE4suar/gn8bh448DEpP50tLTj7PJiat1CE 14 | zt7Ng3PMPaSF2GAqD3ewdZqWbmmAkzelGaNDlp+TQUuO8aaYJFui 15 | -----END CERTIFICATE----- 16 | -------------------------------------------------------------------------------- /examples/security/oauth/README.md: -------------------------------------------------------------------------------- 1 | # oAuth JavaScript example 2 | 3 | This is 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. 4 | 5 | ## run the example 6 | 7 | Set the current working directory to this folder. Then execute: 8 | 9 | ```bash 10 | npm install 11 | ``` 12 | 13 | Now you are ready to run the example. 14 | 15 | ```bash 16 | # start the server 17 | npm run server 18 | ``` 19 | 20 | in a different terminal 21 | 22 | ```bash 23 | # start the exposer 24 | npm run start:exposer 25 | ``` 26 | 27 | Finally, in other terminal 28 | 29 | ```bash 30 | npm run start:consumer 31 | ``` 32 | 33 | you should see the following line at the end of consumer log: 34 | 35 | ```bash 36 | oAuth token was Ok! 37 | ``` 38 | 39 | This confirms that the oAuth flow was completed successfully. Now you can have fun revoking the access to the consumer script. Go 40 | to `./exposer.js` and try to remove the string `"user"` from the grants. Run again the example and you will see that the action is not executed and an error is returned by the client. 41 | 42 | ## Where is a TS version? 43 | 44 | See [here](../../../packages/examples/src/security/oauth) 45 | -------------------------------------------------------------------------------- /examples/security/oauth/consumer.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | WoT.requestThingDescription("https://localhost:8080/oauth").then((td) => { 16 | WoT.consume(td).then(async (thing) => { 17 | try { 18 | const resp = await thing.invokeAction("sayOk"); 19 | const result = await resp?.value(); 20 | console.log("oAuth token was", result); 21 | } catch (error) { 22 | console.log("It seems that I couldn't access the resource"); 23 | } 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /examples/security/oauth/exposer.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 - 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | const td = { 16 | "@context": "https://www.w3.org/2019/wot/td/v1", 17 | title: "OAuth", 18 | id: "urn:dev:wot:oauth:test", 19 | securityDefinitions: { 20 | oauth2_sc: { 21 | scheme: "oauth2", 22 | flow: "client", 23 | token: "https://localhost:3000/token", 24 | scopes: ["user", "admin"], 25 | }, 26 | }, 27 | security: ["oauth2_sc"], 28 | actions: { 29 | sayOk: { 30 | description: "A simple action protected with oauth", 31 | idempotent: true, 32 | }, 33 | }, 34 | }; 35 | try { 36 | WoT.produce(td).then((thing) => { 37 | thing.setActionHandler("sayOk", async () => "Ok!"); 38 | thing.expose(); 39 | }); 40 | } catch (err) { 41 | console.error("Script error: " + err); 42 | } 43 | -------------------------------------------------------------------------------- /examples/security/oauth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oauth-test", 3 | "version": "1.0.0", 4 | "description": "Simple project setup to test oauth functionalities", 5 | "main": "index.js", 6 | "scripts": { 7 | "server": "node server.js", 8 | "start:exposer": "node ../../../packages/cli/dist/cli.js -f ./wot-server-servient-conf.json exposer.js", 9 | "start:consumer": "node ../../../packages/cli/dist/cli.js -f ./wot-client-servient-conf.json consumer.js" 10 | }, 11 | "author": "Eclipse Thingweb (https://thingweb.io/)", 12 | "license": "EPL-2.0 OR W3C-20150513", 13 | "devDependencies": { 14 | "@node-oauth/express-oauth-server": "^3.0.1", 15 | "cors": "^2.8.5" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/security/oauth/server.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 - 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | /** 16 | * A simple oAuth test server 17 | */ 18 | const OAuthServer = require("@node-oauth/express-oauth-server"); 19 | const bodyParser = require("body-parser"); 20 | const cors = require("cors"); 21 | const https = require("https"); 22 | const fs = require("fs"); 23 | const express = require("express"); 24 | const Memory = require("./memory-model"); 25 | 26 | var app = express(); 27 | app.use(cors()); 28 | app.options("*", cors()); 29 | 30 | const model = new Memory(); 31 | 32 | app.oauth = new OAuthServer({ 33 | model: model, 34 | }); 35 | 36 | app.use(bodyParser.json()); 37 | app.use("/introspect", bodyParser.urlencoded({ extended: false })); 38 | app.use("/introspect", (req, res, next) => { 39 | if (req.method !== "POST" || !req.is("application/x-www-form-urlencoded")) { 40 | return res.status(400).end(); 41 | } 42 | 43 | // rewrite body authenticate method is not compliant to https://tools.ietf.org/html/rfc7662 44 | const token = req.body.token; 45 | delete req.body.token; 46 | req.body.access_token = token; 47 | console.log("Body changed,"); 48 | next(); 49 | }); 50 | 51 | app.use("/introspect", async (req, res, next) => { 52 | return app.oauth.authenticate()(req, res, next); 53 | }); 54 | app.use("/introspect", (req, res) => { 55 | const token = res.locals.oauth.token; 56 | console.log("Token was", token ? "Ok" : "not Ok"); 57 | res.json({ 58 | active: !!token, 59 | scope: token.client.scopes.join(" "), 60 | client_id: token.client.clientId, 61 | }).end(); 62 | }); 63 | 64 | app.use("/token", bodyParser.urlencoded({ extended: false })); 65 | app.use("/token", app.oauth.token()); 66 | 67 | app.use("/resource", (req, res) => { 68 | console.log("qui?"); 69 | res.send("Ok!"); 70 | }); 71 | 72 | https 73 | .createServer( 74 | { 75 | key: fs.readFileSync("../privatekey.pem"), 76 | cert: fs.readFileSync("../certificate.pem"), 77 | }, 78 | app 79 | ) 80 | .listen(3000, "localhost", () => { 81 | console.log("listening"); 82 | }); 83 | -------------------------------------------------------------------------------- /examples/security/oauth/wot-client-servient-conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "servient": { 3 | "clientOnly": true 4 | }, 5 | "http": { 6 | "allowSelfSigned": true 7 | }, 8 | "credentials": { 9 | "urn:dev:wot:oauth:test": { 10 | "clientId": "node-wot", 11 | "clientSecret": "isgreat!" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /examples/security/oauth/wot-server-servient-conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "servient": {}, 3 | "http": { 4 | "allowSelfSigned": true, 5 | "serverKey": "../privatekey.pem", 6 | "serverCert": "../certificate.pem", 7 | "security": [ 8 | { 9 | "scheme": "oauth2", 10 | "method": { 11 | "name": "introspection_endpoint", 12 | "endpoint": "https://localhost:3000/introspect", 13 | "allowSelfSigned": true 14 | } 15 | } 16 | ] 17 | }, 18 | "credentials": { 19 | "urn:dev:wot:oauth:test": { 20 | "clientId": "node-wot", 21 | "clientSecret": "isgreat!" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/security/privatekey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQDY05qXs2BFbdtsS9dQAxIEz94vO2/VsGmJbq5eLWU+vUSt+jW5 3 | xrenfWKlqATPAiYuwH5zYa4x0Qf1HwpC4H2CP+PJOE7s+Gbt3eN9Gv3z/6LgOLrK 4 | 1NlREOS9hGukEdSHbXiz4Aftz0K5NR8sAeWGaNn/OK8UlBPX7ekV6tWQ/wIDAQAB 5 | AoGAQeoZ/fH+2zxpTwPDQcSdLq9OeQdVmR2XB7uI8IJWW/tHrKf6uy4o2JbqbTel 6 | tpSNrPrBtivEu8oy5BZ6lRgPrwChkxTPCKSTBxlofN17Xdt7U4+WfKsEuGUO1goc 7 | xqc21Gn6Ug6Dh4KcpD5zpmnSGj9cLUe8dy/PQlO0XoLyekECQQDugAfqleAsYPLk 8 | h87yksPDMdSwcOhk1oEjJXz/JiTgfmCN+eAtOLtq98VWRXPzhHfAeolIVNhNBtnW 9 | NxMAxCehAkEA6Lx1bCyzx+clVUneD6RWqHBjoSONH5gQ/Qj0kWqlzjWidjKKCNrP 10 | /RwNzK7D0frgnLM7JAyWTCInZCdTA4x0nwJBAIT/PGrifQoCXjB2Uz8N/MCizxo9 11 | PDrPK2AwDY4y9SmDD9DcYNiW5Fx4IsFDJa/MVQMu0dNWDPCXO26rc5tfx0ECQQDS 12 | oTzkGdDbKiZvedqu7VxANPb17ubZoRY+6svsj0hfx8qwjiy+tsllmO4kQEaY0yRU 13 | rSDpDzs2y/I6ghxvKb6hAkAYOTzDSxOrjBiOi3lnybzfBBPT5j2v9kvZGE2JhLKW 14 | 7pTaU5hb6qkNVvMINAYAIZMiiriovPQOpJbWTLo0QbH4 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /examples/security/wot-servient.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "servient": { 3 | "scriptDir": ".", 4 | "scriptAction": true 5 | }, 6 | "http": { 7 | "port": 8080, 8 | "allowSelfSigned": true, 9 | "serverKey": "privatekey.pem", 10 | "serverCert": "certificate.pem", 11 | "security": { 12 | "scheme": "basic" 13 | } 14 | }, 15 | "_coap": { 16 | "port": 5683 17 | }, 18 | "_mqtt": { 19 | "broker": "mqtt://test.mosquitto.org", 20 | "port": 1883 21 | }, 22 | "log": { 23 | "level": "info" 24 | }, 25 | "credentials": { 26 | "urn:dev:wot:org:eclipse:thingweb:security-example": { 27 | "username": "node-wot", 28 | "password": "hello", 29 | "token": "1/mZ1edKKACtPAb7zGlwSzvs72PvhAbGmB8K1ZrGxpcNM" 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/templates/exposed-thing/index.js: -------------------------------------------------------------------------------- 1 | //Where your concrete implementation is included 2 | WotDevice = require("./dist/base.js").WotDevice; 3 | 4 | /* 5 | This project supports the registration of the generated TD to a TD directory 6 | Fill in the directory URI where the HTTP POST request to send the TD will be made 7 | If you leave it empty, registration thread will never execute, otherwise it will try to register every 10 seconds 8 | */ 9 | const TD_DIRECTORY = ""; 10 | 11 | Servient = require("@node-wot/core").Servient; 12 | //Importing the required bindings 13 | HttpServer = require("@node-wot/binding-http").HttpServer; 14 | //CoapServer = require("@node-wot/binding-coap").CoapServer 15 | //MqttBrokerServer = require("@node-wot/binding-mqtt").MqttBrokerServer 16 | 17 | //Creating the instances of the binding servers 18 | var httpServer = new HttpServer({ port: 8080 }); 19 | //var coapServer = new CoapServer({port: 5683}); 20 | //var mqttServer = new MqttBrokerServer("test.mosquitto.org"); //change it according to the broker address 21 | 22 | //Building the servient object 23 | var servient = new Servient(); 24 | //Adding different bindings to the server 25 | servient.addServer(httpServer); 26 | //servient.addServer(coapServer); 27 | //servient.addServer(mqttServer); 28 | 29 | servient.start().then((WoT) => { 30 | wotDevice = new WotDevice(WoT, TD_DIRECTORY); // you can change the wotDevice to something that makes more sense 31 | }); 32 | -------------------------------------------------------------------------------- /examples/templates/exposed-thing/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wot-default-change-here-", 3 | "version": "1.0.0", 4 | "description": "W3C WoT interface for base (!change here!)", 5 | "main": "index.js", 6 | "keywords": [ 7 | "wot", 8 | "w3c" 9 | ], 10 | "author": "tumeiesi", 11 | "license": "MIT", 12 | "devDependencies": { 13 | "typescript": "4.7.4", 14 | "wot-typescript-definitions": "0.8.0-SNAPSHOT.30", 15 | "@types/node": "16.18.35", 16 | "tslint": "5.12.1" 17 | }, 18 | "dependencies": { 19 | "@node-wot/binding-http": "0.8.x", 20 | "@node-wot/core": "0.8.x", 21 | "request": "2.88.0", 22 | "ajv": "^6.12.6" 23 | }, 24 | "optionalDependencies": {}, 25 | "scripts": { 26 | "build": "tsc -b", 27 | "buildAll": "npm install; tsc;", 28 | "start": "node index.js", 29 | "clean": "rm -rf node_modules; rm -rf dist; rm -rf package-lock.json" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/templates/exposed-thing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2021", 4 | "lib": ["ES2021", "dom"], 5 | "module": "commonjs", 6 | "outDir": "dist", 7 | "alwaysStrict": true, 8 | "sourceMap": true, 9 | "noLib": false, 10 | "forceConsistentCasingInFileNames": true, 11 | "noImplicitReturns": true, 12 | "noUnusedLocals": true 13 | }, 14 | "exclude": ["node_modules"], 15 | "include": ["src/**/*"] 16 | } 17 | -------------------------------------------------------------------------------- /examples/testthing/$DO_NOT_EDIT_JS_FILES.md: -------------------------------------------------------------------------------- 1 | # Note 2 | 3 | The JavaScript files in this folder are generated by the workflow described [here](https://github.com/eclipse-thingweb/node-wot/tree/master/packages/examples#workflow). 4 | -------------------------------------------------------------------------------- /license.template.txt: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) <%= YEAR %> Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | -------------------------------------------------------------------------------- /packages/binding-coap/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-coap/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-coap", 3 | "version": "0.9.2", 4 | "description": "CoAP client & server protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-coap", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "dist/coap.js", 15 | "types": "dist/coap.d.ts", 16 | "dependencies": { 17 | "@node-wot/core": "0.9.2", 18 | "coap": "^1.4.1", 19 | "dns-packet": "^5.2.2", 20 | "multicast-dns": "^7.2.5", 21 | "node-coap-client": "1.0.8", 22 | "rxjs": "5.5.11", 23 | "slugify": "^1.4.5", 24 | "wot-typescript-definitions": "0.8.0-SNAPSHOT.30" 25 | }, 26 | "scripts": { 27 | "build": "tsc -b", 28 | "test": "mocha --require ts-node/register --extension ts", 29 | "lint": "eslint .", 30 | "lint:fix": "eslint . --fix", 31 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"" 32 | }, 33 | "bugs": { 34 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 35 | }, 36 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-coap#readme", 37 | "directories": { 38 | "test": "test" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/binding-coap/src/coap-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * CoAP client Factory 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient, createLoggers } from "@node-wot/core"; 21 | import CoapClient from "./coap-client"; 22 | import CoapServer from "./coap-server"; 23 | 24 | const { debug } = createLoggers("binding-coap", "coap-client-factory"); 25 | 26 | export default class CoapClientFactory implements ProtocolClientFactory { 27 | public readonly scheme: string = "coap"; 28 | 29 | private readonly server?: CoapServer; 30 | 31 | constructor(server?: CoapServer) { 32 | this.server = server; 33 | } 34 | 35 | public getClient(): ProtocolClient { 36 | debug(`CoapClientFactory creating client for '${this.scheme}'`); 37 | return new CoapClient(this.server); 38 | } 39 | 40 | public init(): boolean { 41 | // info(`CoapClientFactory for '${this.scheme}' initializing`); 42 | // TODO uncomment info if something is executed here 43 | return true; 44 | } 45 | 46 | public destroy(): boolean { 47 | // info(`CoapClientFactory for '${this.scheme}' destroyed`); 48 | // TODO uncomment info if something is executed here 49 | return true; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/binding-coap/src/coaps-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * CoAPS client Factory 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient, createLoggers } from "@node-wot/core"; 21 | import CoapsClient from "./coaps-client"; 22 | 23 | const { debug } = createLoggers("binding-coap", "coaps-client-factory"); 24 | 25 | export default class CoapsClientFactory implements ProtocolClientFactory { 26 | public readonly scheme: string = "coaps"; 27 | 28 | public getClient(): ProtocolClient { 29 | debug(`CoapsClientFactory creating client for '${this.scheme}'`); 30 | return new CoapsClient(); 31 | } 32 | 33 | public init(): boolean { 34 | // info(`CoapsClientFactory for '${this.scheme}' initializing`); 35 | // TODO uncomment info if something is executed here 36 | return true; 37 | } 38 | 39 | public destroy(): boolean { 40 | // info(`CoapsClientFactory for '${this.scheme}' destroyed`); 41 | // TODO uncomment info if something is executed here 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/binding-coap/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-coap/test/coap-types-test.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * Protocol test suite for CoAP binding definitions 18 | */ 19 | 20 | import { suite, test } from "@testdeck/mocha"; 21 | import { expect } from "chai"; 22 | import { blockSizeToOptionValue } from "../src/coap"; 23 | 24 | @suite("CoAP Binding Definitions") 25 | class CoapDefinitionsTest { 26 | @test "should map raw blocksizes to the correct option value"() { 27 | expect(blockSizeToOptionValue(16)).to.eq(0); 28 | expect(blockSizeToOptionValue(32)).to.eq(1); 29 | expect(blockSizeToOptionValue(64)).to.eq(2); 30 | expect(blockSizeToOptionValue(128)).to.eq(3); 31 | expect(blockSizeToOptionValue(256)).to.eq(4); 32 | expect(blockSizeToOptionValue(512)).to.eq(5); 33 | expect(blockSizeToOptionValue(1024)).to.eq(6); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/binding-coap/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/binding-coap/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/binding-file/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-file/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-file", 3 | "version": "0.9.2", 4 | "description": "File client protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-file", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "dist/file.js", 15 | "types": "dist/file.d.ts", 16 | "dependencies": { 17 | "@node-wot/core": "0.9.2", 18 | "rxjs": "5.5.11" 19 | }, 20 | "scripts": { 21 | "build": "tsc -b", 22 | "test": "mocha --require ts-node/register --extension ts", 23 | "lint": "eslint .", 24 | "lint:fix": "eslint . --fix", 25 | "format": "prettier --write \"src/**/*.ts\" \"**/*.json\"" 26 | }, 27 | "bugs": { 28 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 29 | }, 30 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-file#readme", 31 | "directories": { 32 | "test": "test" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/binding-file/src/file-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * File protocol binding 18 | */ 19 | import { ProtocolClientFactory, ProtocolClient, createLoggers } from "@node-wot/core"; 20 | import FileClient from "./file-client"; 21 | 22 | const { debug } = createLoggers("binding-file", "file-client-factory"); 23 | 24 | export default class FileClientFactory implements ProtocolClientFactory { 25 | public readonly scheme: string = "file"; 26 | 27 | public getClient(): ProtocolClient { 28 | debug(`FileClientFactory creating client for '${this.scheme}'`); 29 | return new FileClient(); 30 | } 31 | 32 | public init = (): boolean => true; 33 | public destroy = (): boolean => true; 34 | } 35 | -------------------------------------------------------------------------------- /packages/binding-file/src/file.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | export { default as FileClient } from "./file-client"; 17 | export { default as FileClientFactory } from "./file-client-factory"; 18 | export * from "./file-client"; 19 | export * from "./file-client-factory"; 20 | -------------------------------------------------------------------------------- /packages/binding-file/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-file/test/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore auxiliary files created by the FileClient implementation tests 2 | test*.json 3 | test*.txt 4 | -------------------------------------------------------------------------------- /packages/binding-file/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/binding-http/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-http/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-http", 3 | "version": "0.9.2", 4 | "description": "HTTP client & server protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-http", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "dist/http.js", 15 | "types": "dist/http.d.ts", 16 | "browser": { 17 | "./dist/http.js": "./dist/http-browser.js", 18 | "./dist/http-client.js": "./dist/http-client-browser.js" 19 | }, 20 | "devDependencies": { 21 | "@node-oauth/express-oauth-server": "^3.0.1", 22 | "@node-oauth/oauth2-server": "^4.3.0", 23 | "@types/accept-language-parser": "^1.5.2", 24 | "@types/basic-auth": "1.1.3", 25 | "@types/eventsource": "^1.1.15", 26 | "@types/express": "^4.17.3", 27 | "@types/node-fetch": "^2.6.12", 28 | "body-parser": "^1.20.3", 29 | "express": "^4.20.0", 30 | "ssestream": "^1.1.0", 31 | "timekeeper": "^2.2.0" 32 | }, 33 | "dependencies": { 34 | "@node-wot/core": "0.9.2", 35 | "accept-language-parser": "1.5.0", 36 | "basic-auth": "2.0.1", 37 | "client-oauth2": "^4.2.5", 38 | "eventsource": "^2.0.2", 39 | "find-my-way": "^8.2.2", 40 | "node-fetch": "^2.7.0", 41 | "query-string": "^7.1.1", 42 | "rxjs": "^5.5.11", 43 | "slugify": "^1.4.5" 44 | }, 45 | "scripts": { 46 | "build": "tsc -b", 47 | "test": "mocha --require ts-node/register --extension ts", 48 | "lint": "eslint .", 49 | "lint:fix": "eslint . --fix", 50 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"" 51 | }, 52 | "bugs": { 53 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 54 | }, 55 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-http#readme" 56 | } 57 | -------------------------------------------------------------------------------- /packages/binding-http/src/codecs/tuya-codec.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ContentCodec, DataSchema } from "@node-wot/core"; 17 | import { DataSchemaValue } from "wot-typescript-definitions"; 18 | 19 | interface TuyaOutput { 20 | success?: boolean; 21 | msg?: string; 22 | result?: { 23 | code?: string; 24 | }[]; 25 | } 26 | 27 | export default class HttpTuyaCodec implements ContentCodec { 28 | getMediaType(): string { 29 | return "application/json+tuya"; 30 | } 31 | 32 | bytesToValue(bytes: Buffer, schema: DataSchema, parameters: { [key: string]: string }): DataSchemaValue { 33 | const parsedBody: TuyaOutput = JSON.parse(bytes.toString()); 34 | const success = parsedBody.success ?? false; 35 | 36 | if (!success) { 37 | throw new Error(parsedBody.msg ?? JSON.stringify(parsedBody)); 38 | } 39 | 40 | for (const value of Object.values(parsedBody.result ?? {})) { 41 | if (value.code === schema["tuya:PropertyName"]) { 42 | return value; 43 | } 44 | } 45 | throw new Error("Property not found"); 46 | } 47 | 48 | valueToBytes(value: unknown, schema: DataSchema, parameters?: { [key: string]: string }): Buffer { 49 | const obj = { 50 | commands: [ 51 | { 52 | code: schema["tuya:PropertyName"], 53 | value, 54 | }, 55 | ], 56 | }; 57 | const body = JSON.stringify(obj); 58 | return Buffer.from(body); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/binding-http/src/http-browser.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Form, SecurityScheme } from "@node-wot/core"; 17 | 18 | import { Headers, Response } from "node-fetch"; 19 | 20 | export { default as HttpClient } from "./http-client"; 21 | export { default as HttpClientFactory } from "./http-client-factory"; 22 | export { default as HttpsClientFactory } from "./https-client-factory"; 23 | export * from "./http-client"; 24 | export * from "./http-client-factory"; 25 | export * from "./https-client-factory"; 26 | 27 | export interface HttpProxyConfig { 28 | href: string; 29 | scheme?: string; 30 | token?: string; 31 | username?: string; 32 | password?: string; 33 | } 34 | 35 | export interface HttpConfig { 36 | port?: number; 37 | address?: string; 38 | proxy?: HttpProxyConfig; 39 | allowSelfSigned?: boolean; 40 | serverKey?: string; 41 | serverCert?: string; 42 | security?: SecurityScheme; 43 | } 44 | 45 | export class HttpHeader { 46 | public "http:fieldName": number; 47 | public "http:fieldValue": unknown; 48 | } 49 | 50 | export class HttpForm extends Form { 51 | public "http:methodName"?: string; // "GET", "PUT", "POST", "DELETE" 52 | public "http:headers"?: Array | HttpHeader; 53 | } 54 | 55 | Headers.prototype.raw = function () { 56 | const result: { [key: string]: string[] } = {}; 57 | for (const [headerKey, headerValue] of this.entries()) { 58 | result[headerKey] = headerValue.split(","); 59 | } 60 | return result; 61 | }; 62 | 63 | Response.prototype.buffer = async function () { 64 | return Buffer.from(await this.arrayBuffer()); 65 | }; 66 | -------------------------------------------------------------------------------- /packages/binding-http/src/http-client-browser.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { ProtocolHelpers } from "@node-wot/core"; 16 | import fetch, { RequestInit, Request } from "node-fetch"; 17 | import { Readable } from "stream"; 18 | import { HttpForm, HTTPMethodName } from "./http"; 19 | import HttpClient from "./http-client-impl"; 20 | 21 | export default class BrowserHttpClient extends HttpClient { 22 | protected async generateFetchRequest( 23 | form: HttpForm, 24 | defaultMethod: HTTPMethodName, 25 | additionalOptions?: RequestInit 26 | ): Promise { 27 | // See https://github.com/eclipse-thingweb/node-wot/issues/790 28 | if (additionalOptions?.body instanceof Readable) { 29 | const buffer = await ProtocolHelpers.readStreamFully(additionalOptions.body); 30 | additionalOptions.body = buffer; 31 | } 32 | return super.generateFetchRequest(form, defaultMethod, additionalOptions); 33 | } 34 | 35 | protected async _fetch(request: Request) { 36 | return fetch(request); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/binding-http/src/http-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * HTTP client Factory 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient, createLoggers } from "@node-wot/core"; 21 | import { HttpConfig } from "./http"; 22 | import HttpClient from "./http-client"; 23 | import OAuthManager from "./oauth-manager"; 24 | 25 | const { debug, warn } = createLoggers("binding-http", "http-client-factory"); 26 | 27 | export default class HttpClientFactory implements ProtocolClientFactory { 28 | public readonly scheme: string = "http"; 29 | private config: HttpConfig | null = null; 30 | private oAuthManager: OAuthManager = new OAuthManager(); 31 | 32 | constructor(config: HttpConfig | null = null) { 33 | this.config = config; 34 | } 35 | 36 | public getClient(): ProtocolClient { 37 | // HTTP over HTTPS proxy requires HttpsClient 38 | if (this.config && this.config.proxy && this.config.proxy.href && this.config.proxy.href.startsWith("https:")) { 39 | warn("HttpClientFactory creating client for 'https' due to secure proxy configuration"); 40 | return new HttpClient(this.config, true, this.oAuthManager); 41 | } else { 42 | debug(`HttpClientFactory creating client for '${this.scheme}'`); 43 | return new HttpClient(this.config); 44 | } 45 | } 46 | 47 | public init(): boolean { 48 | // info(`HttpClientFactory for '${HttpClientFactory.scheme}' initializing`); 49 | // TODO uncomment info if something is executed here 50 | return true; 51 | } 52 | 53 | public destroy(): boolean { 54 | // info(`HttpClientFactory for '${HttpClientFactory.scheme}' destroyed`); 55 | // TODO uncomment info if something is executed here 56 | return true; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/binding-http/src/http-client.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | export { default } from "./http-client-impl"; 17 | -------------------------------------------------------------------------------- /packages/binding-http/src/http-server-middleware.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * HTTP Middleware for the HTTP Server 18 | */ 19 | 20 | import * as http from "http"; 21 | 22 | /** 23 | * A middleware function for the HTTP server, which can be used to intercept requests before they are handled by the WoT Servient. 24 | * 25 | * Example: 26 | * ```javascript 27 | * import { Servient } from "@node-wot/core"; 28 | * import { HttpServer, MiddlewareRequestHandler } from "@node-wot/binding-http"; 29 | * 30 | * const servient = new Servient(); 31 | * 32 | * const middleware: MiddlewareRequestHandler = async (req, res, next) => { 33 | * // For example, reject requests in which the X-Custom-Header header is missing 34 | * // by replying with 400 Bad Request 35 | * if (!req.headers["x-custom-header"]) { 36 | * res.statusCode = 400; 37 | * res.end("Bad Request"); 38 | * return; 39 | * } 40 | * // Pass all other requests to the WoT Servient 41 | * next(); 42 | * }; 43 | 44 | * const httpServer = new HttpServer({ 45 | * middleware, 46 | * }); 47 | * 48 | * servient.addServer(httpServer); 49 | * 50 | * servient.start().then(async (WoT) => { 51 | * // ... 52 | * }); 53 | * ``` 54 | * @param req The HTTP request. 55 | * @param res The HTTP response. 56 | * @param next Call this function to pass the request to the WoT Servient. 57 | */ 58 | export type MiddlewareRequestHandler = ( 59 | req: http.IncomingMessage, 60 | res: http.ServerResponse, 61 | next: () => void 62 | ) => Promise; 63 | -------------------------------------------------------------------------------- /packages/binding-http/src/http.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { SecurityScheme, Form } from "@node-wot/core"; 17 | import { Method } from "./oauth-token-validation"; 18 | import { MiddlewareRequestHandler } from "./http-server-middleware"; 19 | 20 | export { default as HttpServer } from "./http-server"; 21 | export { default as HttpClient } from "./http-client"; 22 | export { default as HttpClientFactory } from "./http-client-factory"; 23 | export { default as HttpsClientFactory } from "./https-client-factory"; 24 | export { MiddlewareRequestHandler } from "./http-server-middleware"; 25 | export * from "./http-server"; 26 | export * from "./http-client"; 27 | export * from "./http-client-factory"; 28 | export * from "./https-client-factory"; 29 | 30 | export interface HttpProxyConfig { 31 | href: string; 32 | scheme?: "basic" | "bearer"; 33 | token?: string; 34 | username?: string; 35 | password?: string; 36 | } 37 | 38 | export interface HttpConfig { 39 | port?: number; 40 | address?: string; 41 | baseUri?: string; 42 | urlRewrite?: Record; 43 | proxy?: HttpProxyConfig; 44 | allowSelfSigned?: boolean; 45 | serverKey?: string; 46 | serverCert?: string; 47 | security?: SecurityScheme[]; 48 | middleware?: MiddlewareRequestHandler; 49 | } 50 | 51 | export interface OAuth2ServerConfig extends SecurityScheme { 52 | method: Method; 53 | /** 54 | * Regex to select the valid clients ids. Default: .* 55 | */ 56 | allowedClients?: string; 57 | } 58 | 59 | export interface TuyaCustomBearerSecurityScheme extends SecurityScheme { 60 | /** 61 | * This scheme is necessary because of the Tuya binding. 62 | * The Tuya Apis are implementing a custom security protocol that needs a custom handling 63 | */ 64 | scheme: "TuyaCustomBearer"; 65 | baseUri: string; 66 | } 67 | 68 | export type HTTPMethodName = "GET" | "PUT" | "POST" | "DELETE" | "PATCH" | "HEAD"; 69 | 70 | export class HttpHeader { 71 | public "htv:fieldName": string; 72 | public "htv:fieldValue": string; 73 | } 74 | 75 | export class HttpForm extends Form { 76 | public "htv:methodName"?: HTTPMethodName; 77 | public "htv:headers"?: Array | HttpHeader; 78 | } 79 | -------------------------------------------------------------------------------- /packages/binding-http/src/https-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * HTTPS client Factory 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient, createLoggers } from "@node-wot/core"; 21 | import { HttpConfig } from "./http"; 22 | import HttpClient from "./http-client"; 23 | 24 | const { debug, warn } = createLoggers("binding-http", "https-client-factory"); 25 | 26 | export default class HttpsClientFactory implements ProtocolClientFactory { 27 | public readonly scheme: string = "https"; 28 | private config: HttpConfig | null = null; 29 | 30 | constructor(config: HttpConfig | null = null) { 31 | this.config = config; 32 | } 33 | 34 | public getClient(): ProtocolClient { 35 | // HTTPS over HTTP proxy requires HttpClient 36 | if (this.config && this.config.proxy && this.config.proxy.href && this.config.proxy.href.startsWith("http:")) { 37 | warn("HttpsClientFactory creating client for 'http' due to insecure proxy configuration"); 38 | return new HttpClient(this.config); 39 | } else { 40 | debug(`HttpsClientFactory creating client for '${this.scheme}'`); 41 | return new HttpClient(this.config, true); 42 | } 43 | } 44 | 45 | public init(): boolean { 46 | // info(`HttpsClientFactory for '${HttpsClientFactory.scheme}' initializing`); 47 | // TODO uncomment info if something is executed here 48 | return true; 49 | } 50 | 51 | public destroy(): boolean { 52 | // info(`HttpsClientFactory for '${HttpsClientFactory.scheme}' destroyed`); 53 | // TODO uncomment info if something is executed here 54 | return true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/binding-http/src/routes/things.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { ContentSerdes, Helpers } from "@node-wot/core"; 16 | import { IncomingMessage, ServerResponse } from "http"; 17 | import HttpServer from "../http-server"; 18 | 19 | export default function thingsRoute( 20 | this: HttpServer, 21 | req: IncomingMessage, 22 | res: ServerResponse, 23 | _params: unknown 24 | ): void { 25 | res.setHeader("Access-Control-Allow-Origin", "*"); 26 | res.setHeader("Content-Type", ContentSerdes.DEFAULT); 27 | res.writeHead(200); 28 | const list = []; 29 | for (const address of Helpers.getAddresses()) { 30 | for (const name in this.getThings()) { 31 | // FIXME the undefined check should NOT be necessary (however there seems to be null in it) 32 | if (name) { 33 | list.push( 34 | this.scheme + 35 | "://" + 36 | Helpers.toUriLiteral(address) + 37 | ":" + 38 | this.getPort() + 39 | "/" + 40 | encodeURIComponent(name) 41 | ); 42 | } 43 | } 44 | } 45 | res.end(JSON.stringify(list)); 46 | } 47 | -------------------------------------------------------------------------------- /packages/binding-http/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-http/test/server.cert: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDXTCCAkWgAwIBAgIJAMsp9gVwegP9MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV 3 | BAYTAklUMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMjAwNDE0MDkxMTQzWhcNMjAwNTE0MDkxMTQzWjBF 5 | MQswCQYDVQQGEwJJVDETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 7 | CgKCAQEA3ToVq2J/9We8lYG0EWRGn0s488mp+H/8Z6GJUOabhRpdrapPS8NyFqzK 8 | wh5t/kAq3R5GH5BTTc75pF9ksIK4FfUbKtOPcubvJEpt+eCZzeD0v5oH73dwPaoY 9 | oZp8WfUkILhdMSyFBUyNLzVMrbjyCyH/J6z0QUy6Llg9nCmGh5xF0DHNApVnRpDK 10 | efVO9SVJQAi5U2DTswHYzV6H/Pi199yevepnc3qNnlGLDxr1uPzx7iZrR5GrSsjQ 11 | TtjGAMRnlF2tEinx6BEgIf1m+6PriYtCZ9FKvBCKjVwp/tvvXWQcyNDuJum8u2TE 12 | rD3T/LABP53XXnfEPdfsl7YFfWNcTQIDAQABo1AwTjAdBgNVHQ4EFgQUqQ3t0q3h 13 | J/KjeYdzwGHIAa8U0UAwHwYDVR0jBBgwFoAUqQ3t0q3hJ/KjeYdzwGHIAa8U0UAw 14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAny9MlmTVQdhDW3xV1Iwi 15 | 3fwUPEJ1Y5ACPenhbQBwet3DiwGbgrEYNp/pOgDWfQbJd7szKf4xOmC68TLnztrJ 16 | 0n7x5l3DeRJjM4d3mHZG/MwdEQe0EZr5eI3tEyHqBX9ll9ntIScbiTkPJbl/YytX 17 | PzkDar4krEKAgw9QQerYtcv85TIg0XfXcOjud6RILBYkF1B5QAFFKybj+z527FlG 18 | +mDoYKyPk0fG2q945Tzc8AU/Z3pfpRCUQAahH7uUXS4Ytk2WGCrmqW/OV93zOCfK 19 | 4KuVPJqvnTPMOZgROmNwqIgIakN6y1tUxco0fKcWz7MGYlnfB+U7bvn3cP8A9bRz 20 | Fg== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /packages/binding-http/test/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdOhWrYn/1Z7yV 3 | gbQRZEafSzjzyan4f/xnoYlQ5puFGl2tqk9Lw3IWrMrCHm3+QCrdHkYfkFNNzvmk 4 | X2SwgrgV9Rsq049y5u8kSm354JnN4PS/mgfvd3A9qhihmnxZ9SQguF0xLIUFTI0v 5 | NUytuPILIf8nrPRBTLouWD2cKYaHnEXQMc0ClWdGkMp59U71JUlACLlTYNOzAdjN 6 | Xof8+LX33J696mdzeo2eUYsPGvW4/PHuJmtHkatKyNBO2MYAxGeUXa0SKfHoESAh 7 | /Wb7o+uJi0Jn0Uq8EIqNXCn+2+9dZBzI0O4m6by7ZMSsPdP8sAE/ndded8Q91+yX 8 | tgV9Y1xNAgMBAAECggEAZd2WFsmPRA/VTT5hDNUQk87OVasZQdyk+47tLLxTBjIC 9 | yrGuO6OuR/SelE3wte8UDacgAO6y/RP97YsjUQeP/kRTkx/BYNYnbZ18EGA0UhFw 10 | gT1KxCBKJYrKNrds5Ps0/IAIIVlvkuYR6JfxS9jqUuf/lmRUQDE1VZu6GssgMBaQ 11 | uNN1eSl1abNkv+FzSpeRf64sbOjAKMYMqeVRT/OXoQ+Fed/sMR5uCRKnzf+HEOTo 12 | rRcStdqjTZfrhGsLU9PmUr5NSVojk057zg8EpMeE+AOZJg705enN17g0Lnk16wXC 13 | PTjZqlNfku4XHpAPW6Chgjy6Yq0O2plgd/VUy6BZYQKBgQD6Z1+JhoTeY3ew8pne 14 | rMrqEq0HhYx15BCvgbBi/LlLQVCk1SlEFB3Kyow9ePyJyS0gMo0s0PPg+UgTRiP6 15 | F4KKeyq+ebarQQ6cazOBkppmS+46201UjVUtWPKGxYEzXTL4eW4bNvZvPYVbZYH1 16 | sZyIqHP7IN23t5GyzKq2VdIKNQKBgQDiK8hYF/8SPRLIyoArdRhUI2j6fPLNyq6B 17 | I/Yw9/Xad17ZXSz1yp6kEjF9zMG/7RjsYPlNSMUO3qvZeb/rlr0MUcTGvnXUf2Ac 18 | D4ilL2In64hnvmVymXZsKjCdIsKXhUn2MfTut/Oxm9r/390zJ3jJJhrUxZxGiT3T 19 | pKIx55GMuQKBgQCyHEWAdQadiPLiEi4Qjafnx1D8QKogURDtRbpJLqo+NT8/f7/S 20 | hNyMGnaWYzB+cXJ/rHVuo1JVe/sgeousoHxiNCm7QqgEOEpESJxiVf0tNmVFyCfB 21 | NKaZkuMvqdy0xF41D2qaQQYZKhFpaVJ/iM5nBis5Pa93tkMUgzAKchDs4QKBgQDe 22 | 6conUVdcUYd/EV8r9dgJrXDdWWMyA27k513Ru8K8FOUOFXCnvJGJIklXNQVNNdFX 23 | wOhWDL/0PPFhgkbvWv1u8/Se8b9OtlAyt/i03jO/Jryli5mPTsPSLe8GIOlrz7or 24 | BefjlLiCOBusD6eDsIaysnTFexLgzol6XIxj5VmmOQKBgEjgJIVpdpuquIdM3a0q 25 | nUgppPhWyCxACIfWEyLWZZNi68PdM1lr3C1pm4tBJrP17poLOWKd2iQTqu5+zZaq 26 | TeC7S1quBgaBgJWPmrcG6qTzMF7gt8HMafikF2gmsOAcrhsBiPvcbl6jd9qe5toW 27 | 4uu1Qsft3nPMgpjM15neMof+ 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /packages/binding-http/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/binding-http/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/binding-mbus/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-mbus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-mbus", 3 | "version": "0.9.2", 4 | "description": "M-Bus TCP client protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/thingweb/node-wot/tree/master/packages/binding-mbus", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "dist/mbus.js", 15 | "types": "dist/mbus.d.ts", 16 | "dependencies": { 17 | "@node-wot/core": "0.9.2", 18 | "node-mbus": "^2.2.4", 19 | "rxjs": "5.5.11" 20 | }, 21 | "scripts": { 22 | "build": "tsc -b", 23 | "test": "mocha --require ts-node/register --extension ts", 24 | "lint": "eslint .", 25 | "lint:fix": "eslint . --fix", 26 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"" 27 | }, 28 | "bugs": { 29 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 30 | }, 31 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-mbus#readme", 32 | "directories": { 33 | "test": "test" 34 | }, 35 | "eslintConfig": { 36 | "extends": "../../.eslintrc.js" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/binding-mbus/src/mbus-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ProtocolClientFactory, ProtocolClient, createInfoLogger } from "@node-wot/core"; 17 | import MBusClient from "./mbus-client"; 18 | 19 | const info = createInfoLogger("binding-mbus", "mbus-client-factory"); 20 | 21 | export default class MBusClientFactory implements ProtocolClientFactory { 22 | public readonly scheme: string = "mbus+tcp"; 23 | 24 | public getClient(): ProtocolClient { 25 | info(`MBusClientFactory creating client for '${this.scheme}'`); 26 | return new MBusClient(); 27 | } 28 | 29 | public init(): boolean { 30 | return true; 31 | } 32 | 33 | public destroy(): boolean { 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/binding-mbus/src/mbus.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Form } from "@node-wot/core"; 17 | export { default as MBusClientFactory } from "./mbus-client-factory"; 18 | export { default as MBusClient } from "./mbus-client"; 19 | export * from "./mbus-client"; 20 | export * from "./mbus-client-factory"; 21 | 22 | export class MBusForm extends Form { 23 | /** 24 | * Physical address of the unit connected to the bus. 25 | */ 26 | public "mbus:unitID": number; 27 | /** 28 | * Defines the starting address of registers or coils that are 29 | * meant to be written. 30 | */ 31 | public "mbus:offset"?: number; 32 | /** 33 | * Timeout in milliseconds of the mbus request. Default to 1000 milliseconds 34 | */ 35 | public "mbus:timeout"?: number; 36 | } 37 | -------------------------------------------------------------------------------- /packages/binding-mbus/src/node-mbus.d.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | declare module "node-mbus"; 17 | -------------------------------------------------------------------------------- /packages/binding-mbus/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-mbus/test/mbus-connection-test.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { should } from "chai"; 16 | import * as chai from "chai"; 17 | import { MBusForm } from "../src/mbus"; 18 | import chaiAsPromised from "chai-as-promised"; 19 | import { MBusConnection, PropertyOperation } from "../src/mbus-connection"; 20 | 21 | // should must be called to augment all variables 22 | should(); 23 | chai.use(chaiAsPromised); 24 | 25 | describe("mbus connection test", () => { 26 | before(() => { 27 | /* nothing */ 28 | }); 29 | 30 | after(() => { 31 | /* nothing */ 32 | }); 33 | 34 | it("should throw for timeout", function () { 35 | if (process.platform === "win32") { 36 | this.skip(); 37 | } 38 | 39 | const connection = new MBusConnection("127.0.0.1", 806, { 40 | connectionTimeout: 200, 41 | connectionRetryTime: 10, 42 | maxRetries: 1, 43 | }); 44 | return connection.connect().should.eventually.be.rejectedWith("Max connection retries"); 45 | }).timeout(10000); 46 | 47 | describe("Operation", () => { 48 | it("should throw with timeout", async function () { 49 | if (process.platform === "win32") { 50 | this.skip(); 51 | } 52 | 53 | const form: MBusForm = { 54 | href: "mbus+tcp://127.0.0.1:806", 55 | "mbus:offset": 0, 56 | "mbus:unitID": 1, 57 | }; 58 | const connection = new MBusConnection("127.0.0.1", 806, { 59 | connectionTimeout: 1000, 60 | connectionRetryTime: 10, 61 | maxRetries: 1, 62 | }); 63 | const op = new PropertyOperation(form); 64 | connection.enqueue(op); 65 | 66 | await connection.execute(op).should.eventually.be.rejected; 67 | 68 | connection.close(); 69 | }).timeout(10000); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /packages/binding-mbus/test/test-servient.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | // global W3C WoT Scripting API definitions 17 | import * as WoT from "wot-typescript-definitions"; 18 | // node-wot implementation of W3C WoT Servient 19 | import { Servient } from "@node-wot/core"; 20 | 21 | import { MBusClientFactory } from "../src/mbus"; 22 | 23 | export default class DefaultServient extends Servient { 24 | public constructor() { 25 | super(); 26 | this.addClientFactory(new MBusClientFactory()); 27 | } 28 | 29 | /** 30 | * start 31 | */ 32 | public start(): Promise { 33 | return super.start(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/binding-mbus/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/binding-mbus/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/binding-modbus/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-modbus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-modbus", 3 | "version": "0.9.2", 4 | "description": "Modbus TCP client protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "contributors": [ 7 | "Siemens AG" 8 | ], 9 | "license": "EPL-2.0 OR W3C-20150513", 10 | "repository": "https://github.com/thingweb/node-wot/tree/master/packages/binding-modbus", 11 | "publishConfig": { 12 | "access": "public" 13 | }, 14 | "files": [ 15 | "dist/" 16 | ], 17 | "main": "dist/modbus.js", 18 | "types": "dist/modbus.d.ts", 19 | "dependencies": { 20 | "@node-wot/core": "0.9.2", 21 | "modbus-serial": "8.0.17", 22 | "rxjs": "5.5.11", 23 | "wot-typescript-definitions": "0.8.0-SNAPSHOT.30" 24 | }, 25 | "scripts": { 26 | "build": "tsc -b", 27 | "test": "mocha --require ts-node/register --extension ts", 28 | "lint": "eslint .", 29 | "lint:fix": "eslint . --fix", 30 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"" 31 | }, 32 | "bugs": { 33 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 34 | }, 35 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-modbus#readme", 36 | "directories": { 37 | "test": "test" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/binding-modbus/src/modbus-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { ProtocolClientFactory, ProtocolClient, createDebugLogger, createWarnLogger } from "@node-wot/core"; 16 | import ModbusClient from "./modbus-client"; 17 | 18 | const debug = createDebugLogger("binding-modbus", "modbus-client-factory"); 19 | const warn = createWarnLogger("binding-modbus", "modbus-client-factory"); 20 | 21 | export default class ModbusClientFactory implements ProtocolClientFactory { 22 | public readonly scheme: string = "modbus+tcp"; 23 | private singleton?: ModbusClient; 24 | 25 | public getClient(): ProtocolClient { 26 | debug(`Get client for '${this.scheme}'`); 27 | this.init(); 28 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- singleton is initialized in init() 29 | return this.singleton!; 30 | } 31 | 32 | public init(): boolean { 33 | if (!this.singleton) { 34 | debug(`Initializing client for '${this.scheme}'`); 35 | this.singleton = new ModbusClient(); 36 | } 37 | return true; 38 | } 39 | 40 | public destroy(): boolean { 41 | debug(`Destroying client for '${this.scheme}'`); 42 | if (!this.singleton) { 43 | warn(`Destroying a not initialized client factory for '${this.scheme}'`); 44 | return true; // do not cause an error 45 | } 46 | this.singleton.stop(); 47 | this.singleton = undefined; 48 | return true; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/binding-modbus/src/utils.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { ModbusFunction, ModbusEntity } from "./modbus"; 16 | 17 | export function modbusFunctionToEntity(modbusFun: ModbusFunction): ModbusEntity { 18 | switch (modbusFun) { 19 | case ModbusFunction.readCoil: 20 | return "Coil"; 21 | case ModbusFunction.readDiscreteInput: 22 | return "DiscreteInput"; 23 | case ModbusFunction.readInputRegister: 24 | return "InputRegister"; 25 | case ModbusFunction.readHoldingRegisters: 26 | return "HoldingRegister"; 27 | case ModbusFunction.writeMultipleCoils: 28 | return "Coil"; 29 | case ModbusFunction.writeMultipleHoldingRegisters: 30 | return "HoldingRegister"; 31 | case ModbusFunction.writeSingleCoil: 32 | return "Coil"; 33 | case ModbusFunction.writeSingleHoldingRegister: 34 | return "HoldingRegister"; 35 | default: 36 | throw new Error("Cannot convert " + modbusFun + " to ModbusEntity"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/binding-modbus/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-modbus/test/test-servient.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | // global W3C WoT Scripting API definitions 17 | import * as WoT from "wot-typescript-definitions"; 18 | // node-wot implementation of W3C WoT Servient 19 | import { Servient } from "@node-wot/core"; 20 | 21 | import { ModbusClientFactory } from "../src/modbus"; 22 | 23 | export default class DefaultServient extends Servient { 24 | public constructor() { 25 | super(); 26 | this.addClientFactory(new ModbusClientFactory()); 27 | } 28 | 29 | /** 30 | * start 31 | */ 32 | public start(): Promise { 33 | return super.start(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/binding-modbus/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/binding-modbus/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/binding-mqtt/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-mqtt/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-mqtt", 3 | "version": "0.9.2", 4 | "description": "MQTT binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-mqtt", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "dist/mqtt.js", 15 | "types": "dist/mqtt.d.ts", 16 | "dependencies": { 17 | "@node-wot/core": "0.9.2", 18 | "aedes": "^0.46.2", 19 | "mqtt": "^5.3.2", 20 | "rxjs": "5.5.11" 21 | }, 22 | "scripts": { 23 | "build": "tsc -b", 24 | "test": "mocha --require ts-node/register --extension ts", 25 | "lint": "eslint .", 26 | "lint:fix": "eslint . --fix", 27 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 31 | }, 32 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-mqtt#readme", 33 | "directories": { 34 | "test": "test" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/binding-mqtt/src/mqtt-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * Protocol test suite to test protocol implementations 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient, createDebugLogger } from "@node-wot/core"; 21 | import MqttClient from "./mqtt-client"; 22 | 23 | const debug = createDebugLogger("binding-mqtt", "mqtt-client-factory"); 24 | 25 | export default class MqttClientFactory implements ProtocolClientFactory { 26 | public readonly scheme: string = "mqtt"; 27 | private readonly clients: Array = []; 28 | 29 | getClient(): ProtocolClient { 30 | const client = new MqttClient(); 31 | this.clients.push(client); 32 | return client; 33 | } 34 | 35 | init(): boolean { 36 | return true; 37 | } 38 | 39 | destroy(): boolean { 40 | debug(`MqttClientFactory stopping all clients for '${this.scheme}'`); 41 | this.clients.forEach((client) => client.stop()); 42 | return true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/binding-mqtt/src/mqtt.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * Protocol test suite to test protocol implementations 18 | */ 19 | 20 | import { Form } from "@node-wot/core"; 21 | 22 | export { default as MqttClient } from "./mqtt-client"; 23 | export { default as MqttClientFactory } from "./mqtt-client-factory"; 24 | export { default as MqttsClientFactory } from "./mqtts-client-factory"; 25 | export { default as MqttBrokerServer } from "./mqtt-broker-server"; 26 | 27 | export * from "./mqtt-client"; 28 | export * from "./mqtt-client-factory"; 29 | export * from "./mqtts-client-factory"; 30 | export * from "./mqtt-broker-server"; 31 | 32 | export type MqttQoS = "0" | "1" | "2"; 33 | export class MqttForm extends Form { 34 | public "mqv:qos"?: MqttQoS = "0"; 35 | public "mqv:retain"?: boolean; 36 | 37 | public "mqv:topic"?: string; 38 | 39 | public "mqv:filter"?: string | string[]; 40 | 41 | public "mqv:controlPacket"?: "publish" | "subscribe" | "unsubscribe"; 42 | } 43 | 44 | export interface MqttClientConfig { 45 | // username & password are redundant here (also find them in MqttClientSecurityParameters) 46 | // because MqttClient.setSecurity() method can inject authentication credentials into this interface 47 | // which will be then passed to mqtt.connect() once for all 48 | username?: string; 49 | password?: string; 50 | rejectUnauthorized?: boolean; 51 | } 52 | 53 | export interface MqttBrokerServerConfig { 54 | uri: string; 55 | user?: string; 56 | psw?: string; 57 | clientId?: string; 58 | protocolVersion?: 3 | 4 | 5; 59 | rejectUnauthorized?: boolean; 60 | selfHost?: boolean; 61 | key?: Buffer; 62 | cert?: Buffer | undefined; 63 | selfHostAuthentication?: MqttClientConfig[]; 64 | } 65 | -------------------------------------------------------------------------------- /packages/binding-mqtt/src/mqtts-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * Protocol test suite to test protocol implementations 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient, createDebugLogger } from "@node-wot/core"; 21 | import { MqttClientConfig } from "./mqtt"; 22 | import MqttClient from "./mqtt-client"; 23 | 24 | const debug = createDebugLogger("binding-mqtt", "mqtts-client-factory"); 25 | 26 | export default class MqttsClientFactory implements ProtocolClientFactory { 27 | public readonly scheme: string = "mqtts"; 28 | private readonly clients: Array = []; 29 | 30 | // eslint-disable-next-line no-useless-constructor 31 | constructor(private readonly config: MqttClientConfig) {} 32 | getClient(): ProtocolClient { 33 | const client = new MqttClient(this.config, true); 34 | this.clients.push(client); 35 | return client; 36 | } 37 | 38 | init(): boolean { 39 | return true; 40 | } 41 | 42 | destroy(): boolean { 43 | debug(`MqttClientFactory stopping all clients for '${this.scheme}'`); 44 | this.clients.forEach((client) => client.stop()); 45 | return true; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/binding-mqtt/src/util.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { createLoggers } from "@node-wot/core"; 16 | import { MqttQoS } from "./mqtt"; 17 | import { IClientPublishOptions } from "mqtt"; 18 | 19 | const { warn } = createLoggers("binding-mqtt", "mqtt-util"); 20 | 21 | export function mapQoS(qos: MqttQoS | undefined): Required["qos"] { 22 | switch (qos) { 23 | case "0": 24 | return 0; 25 | case "1": 26 | return 1; 27 | case "2": 28 | return 2; 29 | case undefined: 30 | return 0; 31 | default: 32 | warn(`MqttClient received unsupported QoS level '${qos}'`); 33 | warn(`MqttClient falling back to QoS level '0'`); 34 | return 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/binding-mqtt/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-mqtt/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/binding-mqtt/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/binding-netconf/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-netconf/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-netconf", 3 | "version": "0.9.2", 4 | "description": "NetConf client protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/thingweb/node-wot/tree/master/packages/binding-netconf", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "dist/netconf.js", 15 | "types": "dist/netconf.d.ts", 16 | "dependencies": { 17 | "@node-wot/core": "0.9.2", 18 | "case-1.5.3": "npm:case@^1.5.3", 19 | "node-netconf": "^1.1.2", 20 | "rxjs": "5.5.11", 21 | "url-parse": "^1.5.8" 22 | }, 23 | "scripts": { 24 | "build": "tsc -b", 25 | "test": "mocha --require ts-node/register test/netconf-client-test.ts", 26 | "lint": "eslint .", 27 | "lint:fix": "eslint . --fix", 28 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 32 | }, 33 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-netconf#readme", 34 | "directories": { 35 | "test": "test" 36 | }, 37 | "keywords": [], 38 | "devDependencies": { 39 | "@types/node-netconf": "npm:@types/netconf@^2.0.0", 40 | "@types/url-parse": "^1.4.3" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/binding-netconf/src/netconf-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * Netconf protocol binding 18 | */ 19 | import { ProtocolClientFactory, ProtocolClient, ContentSerdes, createDebugLogger } from "@node-wot/core"; 20 | import NetconfClient from "./netconf-client"; 21 | import NetconfCodec from "./codecs/netconf-codec"; 22 | 23 | const debug = createDebugLogger("binding-netconf", "netconf-client-factory"); 24 | 25 | export default class NetconfClientFactory implements ProtocolClientFactory { 26 | public readonly scheme: string = "netconf"; 27 | public contentSerdes: ContentSerdes = ContentSerdes.get(); 28 | 29 | public getClient(): ProtocolClient { 30 | this.contentSerdes.addCodec(new NetconfCodec()); // add custom codec for NetConf 31 | debug(`NetconfClientFactory creating client for '${this.scheme}'`); 32 | return new NetconfClient(); 33 | } 34 | 35 | public init = (): boolean => true; 36 | public destroy = (): boolean => true; 37 | } 38 | -------------------------------------------------------------------------------- /packages/binding-netconf/src/netconf.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Form } from "@node-wot/core"; 17 | export { default as NetconfClient } from "./netconf-client"; 18 | export { default as NetconfClientFactory } from "./netconf-client-factory"; 19 | export * from "./netconf"; 20 | export * from "./netconf-client-factory"; 21 | export class NetconfForm extends Form { 22 | public "nc:NSs"?: Record; 23 | public "nc:method"?: string; 24 | public "nc:target"?: string; 25 | } 26 | 27 | export type RpcMethod = "GET-CONFIG" | "EDIT-CONFIG" | "COMMIT" | "RPC"; 28 | 29 | export interface NetConfCredentials { 30 | username: string; 31 | password?: string; 32 | 33 | privateKey?: string; 34 | } 35 | 36 | export function isRpcMethod(method?: string): method is RpcMethod { 37 | if (method == null) { 38 | return false; 39 | } 40 | return ["GET-CONFIG", "EDIT-CONFIG", "COMMIT", "RPC"].includes(method); 41 | } 42 | -------------------------------------------------------------------------------- /packages/binding-netconf/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-netconf/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/binding-netconf/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/binding-opcua/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-opcua/.mocharc.yml: -------------------------------------------------------------------------------- 1 | recursive: false 2 | require: 3 | - ts-node/register 4 | timeout: 100000 5 | enable-source-maps: true 6 | spec: "test/*-test.ts" 7 | bail: true 8 | parallel: false 9 | -------------------------------------------------------------------------------- /packages/binding-opcua/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-opcua", 3 | "version": "0.9.2", 4 | "description": "opcua client protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/thingweb/node-wot/tree/master/packages/binding-opcua", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist", 13 | "src" 14 | ], 15 | "main": "dist/index.js", 16 | "types": "dist/index.d.ts", 17 | "devDependencies": { 18 | "should": "^13.2.3" 19 | }, 20 | "dependencies": { 21 | "@node-wot/core": "0.9.2", 22 | "ajv": "^8.11.0", 23 | "ajv-formats": "^2.1.1", 24 | "node-opcua": "2.143.0", 25 | "node-opcua-address-space": "2.143.0", 26 | "node-opcua-basic-types": "2.139.0", 27 | "node-opcua-binary-stream": "2.139.0", 28 | "node-opcua-buffer-utils": "2.139.0", 29 | "node-opcua-client": "2.143.0", 30 | "node-opcua-constants": "2.139.0", 31 | "node-opcua-data-model": "2.139.0", 32 | "node-opcua-data-value": "2.142.0", 33 | "node-opcua-date-time": "2.139.0", 34 | "node-opcua-debug": "2.139.0", 35 | "node-opcua-extension-object": "2.139.0", 36 | "node-opcua-factory": "2.139.0", 37 | "node-opcua-json": "0.50.0", 38 | "node-opcua-nodeid": "2.139.0", 39 | "node-opcua-numeric-range": "2.139.0", 40 | "node-opcua-pseudo-session": "2.143.0", 41 | "node-opcua-service-browse": "2.143.0", 42 | "node-opcua-service-translate-browse-path": "2.143.0", 43 | "node-opcua-status-code": "2.139.0", 44 | "node-opcua-types": "2.143.0", 45 | "node-opcua-variant": "2.142.0", 46 | "rxjs": "5.5.11", 47 | "url": "^0.11.4" 48 | }, 49 | "scripts": { 50 | "build": "tsc -b", 51 | "lint": "eslint .", 52 | "lint:fix": "eslint . --fix", 53 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"", 54 | "ncu:opcua": "npx -y npm-check-updates -u -f \"node-opcua*\" -t newest", 55 | "test": "mocha" 56 | }, 57 | "bugs": { 58 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 59 | }, 60 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-opcua#readme", 61 | "directories": { 62 | "test": "test" 63 | }, 64 | "keywords": [] 65 | } 66 | -------------------------------------------------------------------------------- /packages/binding-opcua/src/factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ProtocolClientFactory, ProtocolClient, ContentSerdes, createLoggers } from "@node-wot/core"; 17 | import { OpcuaJSONCodec, OpcuaBinaryCodec } from "./codec"; 18 | import { OPCUAProtocolClient } from "./opcua-protocol-client"; 19 | 20 | const { debug } = createLoggers("binding-opcua", "factory"); 21 | 22 | export class OPCUAClientFactory implements ProtocolClientFactory { 23 | readonly scheme: string = "opc.tcp"; 24 | 25 | private _clients: OPCUAProtocolClient[] = []; 26 | 27 | public contentSerdes: ContentSerdes = ContentSerdes.get(); 28 | 29 | constructor() { 30 | this.contentSerdes.addCodec(new OpcuaJSONCodec()); 31 | this.contentSerdes.addCodec(new OpcuaBinaryCodec()); 32 | } 33 | 34 | getClient(): ProtocolClient { 35 | debug(`OpcuaClientFactory creating client for '${this.scheme}'`); 36 | if (this._clients[0] != null) { 37 | return this._clients[0]; 38 | } 39 | this._clients[0] = new OPCUAProtocolClient(); 40 | return this._clients[0]; 41 | } 42 | 43 | init(): boolean { 44 | debug("init"); 45 | return true; 46 | } 47 | 48 | destroy(): boolean { 49 | debug("destroy"); 50 | 51 | const clients = this._clients; 52 | this._clients = []; 53 | (async () => { 54 | for (const client of clients) { 55 | await client.stop(); 56 | } 57 | })(); 58 | return true; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/binding-opcua/src/index.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | export * from "./factory"; 17 | export * from "./codec"; 18 | export * from "./opcua-protocol-client"; 19 | // no protocol_client here => get access from factor 20 | -------------------------------------------------------------------------------- /packages/binding-opcua/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-opcua/test/opcua-href-test.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2025 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { expect } from "chai"; 17 | 18 | import { OPCUAProtocolClient } from "../src/opcua-protocol-client"; 19 | 20 | describe("OPCUA Hrefs", () => { 21 | it("Example-1", () => { 22 | const form = { href: "opc.tcp://192.168.120.237:4840/?id=ns=10;i=12345" }; 23 | const nodeId = OPCUAProtocolClient.getNodeId(form); 24 | expect(nodeId).equal("ns=10;i=12345"); 25 | }); 26 | it("Example-2", () => { 27 | const form = { href: "opc.tcp://192.168.120.237:4840/?id=nsu=http://widgets.com/schemas/hello;s=水 World" }; 28 | const nodeId = OPCUAProtocolClient.getNodeId(form); 29 | expect(nodeId).equal("nsu=http://widgets.com/schemas/hello;s=水 World"); 30 | }); 31 | it("Example-3 #", () => { 32 | const form = { href: "opc.tcp://192.168.120.237:4840/?id=nsu=http://example.com/hello%23;s=temperature" }; 33 | const nodeId = OPCUAProtocolClient.getNodeId(form); 34 | expect(nodeId).equal("nsu=http://example.com/hello#;s=temperature"); // %23 -> # 35 | }); 36 | it("Example-4 &", () => { 37 | const form = { href: "opc.tcp://192.168.120.237:4840/?id=nsu=http://example.com/a%26b" }; 38 | const nodeId = OPCUAProtocolClient.getNodeId(form); 39 | expect(nodeId).equal("nsu=http://example.com/a&b"); // %26 -> & 40 | }); 41 | it("Example-5 relative", () => { 42 | const form = { href: "/?id=ns=10;i=12345" }; 43 | expect(() => OPCUAProtocolClient.getNodeId(form)).to.throw(Error, "Invalid URL"); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /packages/binding-opcua/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "skipLibCheck": true 7 | }, 8 | "include": ["./src/**/*"], 9 | "references": [{ "path": "../core" }] 10 | } 11 | -------------------------------------------------------------------------------- /packages/binding-websockets/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/binding-websockets/README.md: -------------------------------------------------------------------------------- 1 | # Websocket Protocol Binding of node-wot 2 | 3 | Current Maintainer(s): [@miguelrk](https://github.com/miguelrk) 4 | -------------------------------------------------------------------------------- /packages/binding-websockets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/binding-websockets", 3 | "version": "0.9.2", 4 | "description": "WebSockets client & server protocol binding for node-wot", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-websockets", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "dist/ws.js", 15 | "types": "dist/ws.d.ts", 16 | "browser": "dist/ws-browser.js", 17 | "dependencies": { 18 | "@node-wot/binding-http": "0.9.2", 19 | "@node-wot/core": "0.9.2", 20 | "rxjs": "^5.5.11", 21 | "slugify": "^1.4.5", 22 | "ws": "^7.5.10" 23 | }, 24 | "scripts": { 25 | "build": "tsc -b", 26 | "test": "mocha --require ts-node/register --extension ts", 27 | "lint": "eslint .", 28 | "lint:fix": "eslint . --fix", 29 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"" 30 | }, 31 | "bugs": { 32 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 33 | }, 34 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/binding-websockets#readme", 35 | "directories": { 36 | "test": "test" 37 | }, 38 | "keywords": [] 39 | } 40 | -------------------------------------------------------------------------------- /packages/binding-websockets/src/ws-browser.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2019 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | export { default as WebSocketClient } from "./ws-client"; 17 | export { default as WebSocketClientFactory } from "./ws-client-factory"; 18 | export { default as WebSocketSecureClientFactory } from "./wss-client-factory"; 19 | export * from "./ws-client"; 20 | export * from "./ws-client-factory"; 21 | export * from "./wss-client-factory"; 22 | -------------------------------------------------------------------------------- /packages/binding-websockets/src/ws-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * HTTP client Factory 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient, createLoggers } from "@node-wot/core"; 21 | import WebSocketClient from "./ws-client"; 22 | 23 | const { debug } = createLoggers("binding-websockets", "ws-client-factory"); 24 | 25 | export default class WebSocketClientFactory implements ProtocolClientFactory { 26 | public readonly scheme: string = "ws"; 27 | private clientSideProxy: unknown = null; 28 | 29 | constructor(proxy: unknown = null) { 30 | this.clientSideProxy = proxy; 31 | } 32 | 33 | public getClient(): ProtocolClient { 34 | debug(`HttpClientFactory creating client for '${this.scheme}'`); 35 | return new WebSocketClient(); 36 | } 37 | 38 | public init(): boolean { 39 | // info(`HttpClientFactory for '${HttpClientFactory.scheme}' initializing`); 40 | // TODO uncomment info if something is executed here 41 | return true; 42 | } 43 | 44 | public destroy(): boolean { 45 | // info(`HttpClientFactory for '${HttpClientFactory.scheme}' destroyed`); 46 | // TODO uncomment info if something is executed here 47 | return true; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/binding-websockets/src/ws.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | export { default as WebSocketServer } from "./ws-server"; 17 | export { default as WebSocketClient } from "./ws-client"; 18 | export { default as WebSocketClientFactory } from "./ws-client-factory"; 19 | export { default as WebSocketSecureClientFactory } from "./wss-client-factory"; 20 | export * from "./ws-server"; 21 | export * from "./ws-client"; 22 | export * from "./ws-client-factory"; 23 | export * from "./wss-client-factory"; 24 | -------------------------------------------------------------------------------- /packages/binding-websockets/src/wss-client-factory.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * HTTPS client Factory 18 | */ 19 | 20 | import { ProtocolClientFactory, ProtocolClient } from "@node-wot/core"; 21 | 22 | export default class WssClientFactory implements ProtocolClientFactory { 23 | public readonly scheme: string = "wss"; 24 | 25 | // eslint-disable-next-line no-useless-constructor 26 | constructor() { 27 | // TODO: implement and remove eslint-ignore-useless-constructor 28 | } 29 | 30 | public getClient(): ProtocolClient { 31 | throw new Error("WssClientFactory for 'wss' is not implemented"); 32 | } 33 | 34 | public init(): boolean { 35 | // info(`HttpsClientFactory for '${HttpsClientFactory.scheme}' initializing`); 36 | // TODO uncomment info if something is executed here 37 | return true; 38 | } 39 | 40 | public destroy(): boolean { 41 | // info(`HttpsClientFactory for '${HttpsClientFactory.scheme}' destroyed`); 42 | // TODO uncomment info if something is executed here 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/binding-websockets/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/binding-websockets/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/binding-websockets/test/ws-tests.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** 17 | * Protocol test suite to test protocol implementations 18 | */ 19 | 20 | import Servient, { createLoggers } from "@node-wot/core"; 21 | import { suite, test } from "@testdeck/mocha"; 22 | import { expect, should } from "chai"; 23 | import WebSocketServer from "../src/ws-server"; 24 | 25 | const { info } = createLoggers("binding-websockets", "ws-tests"); 26 | 27 | // should must be called to augment all variables 28 | should(); 29 | 30 | const port = 31080; 31 | @suite("WebSockets binding") 32 | class WebSocketsTest { 33 | @test async "should start and stop own server"() { 34 | const wsServer = new WebSocketServer({ port }); 35 | 36 | await wsServer.start(new Servient()); 37 | expect(wsServer.getPort()).to.eq(port); // from test 38 | 39 | info("Test stopping WebSocket server"); 40 | 41 | await wsServer.stop(); 42 | expect(wsServer.getPort()).to.eq(-1); // from getPort() when not listening 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/binding-websockets/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src" 6 | }, 7 | "include": ["src/**/*"], 8 | "references": [{ "path": "../core" }] 9 | } 10 | -------------------------------------------------------------------------------- /packages/browser-bundle/.gitignore: -------------------------------------------------------------------------------- 1 | types/ 2 | -------------------------------------------------------------------------------- /packages/browser-bundle/README.md: -------------------------------------------------------------------------------- 1 | # Browser Bundle of node-wot 2 | 3 | Bundle to run node-wot as browser-side library. Note, this will only include the node-wot in client mode with limited binding support. 4 | 5 | Current Maintainer(s): [@relu91](https://github.com/relu91) [@danielpeintner](https://github.com/danielpeintner) 6 | 7 | ## Supported bindings 8 | 9 | HTTP / HTTPS / WebSockets 10 | 11 | ## Embedding node-wot library in HTML 12 | 13 | Include the following script tag in your html 14 | 15 | ```js 16 | 17 | ``` 18 | 19 | You can access all node-wot functionality through the "WoT" global object: 20 | 21 | ```js 22 | var servient = new WoT.Core.Servient(); 23 | var client = new WoT.Http.HttpClient(); 24 | ``` 25 | 26 | ## Using node-wot browser bundle library in web frameworks (e.g., Angular) 27 | 28 | Install browser-bundle in your project by running 29 | 30 | - `npm install @node-wot/browser-bundle` 31 | 32 | ## Example and live demo 33 | 34 | An example of how to use node-wot as a browser-side library can be found under `https://github.com/eclipse-thingweb/node-wot/blob/master/examples/browser/index.html`. 35 | To run it live, open [`examples/browser/index.html`](http://plugfest.thingweb.io/webui/) in a modern browser, 36 | and consume the test Thing available under `http://plugfest.thingweb.io:8083/testthing` to interact with it. 37 | 38 | ## More Details 39 | 40 | See 41 | -------------------------------------------------------------------------------- /packages/browser-bundle/esbuild.js: -------------------------------------------------------------------------------- 1 | const { build } = require("esbuild"); 2 | const { polyfillNode } = require("esbuild-plugin-polyfill-node"); 3 | const { rimraf } = require("rimraf"); 4 | const fs = require("fs"); 5 | 6 | const outdir = "dist"; 7 | 8 | /** 9 | * @type {import('esbuild').BuildOptions} 10 | */ 11 | const options = { 12 | entryPoints: ["index.ts"], 13 | bundle: true, 14 | outfile: `${outdir}/wot-bundle.js`, 15 | format: "iife", 16 | platform: "browser", 17 | globalName: "WoT", 18 | sourcemap: true, 19 | plugins: [ 20 | polyfillNode({ 21 | globals: { 22 | global: false, 23 | __dirname: false, 24 | __filename: false, 25 | buffer: true, 26 | process: false, 27 | }, 28 | }), 29 | ], 30 | }; 31 | 32 | async function run() { 33 | const start = Date.now(); 34 | await rimraf(outdir); 35 | await build(options); 36 | 37 | options.minify = true; 38 | options.outfile = `${outdir}/wot-bundle.min.js`; 39 | await build(options); 40 | 41 | options.minify = false; 42 | options.entryPoints = ["index.ts", "../binding-http", "../core", "../binding-websockets"]; 43 | options.splitting = true; 44 | options.outfile = undefined; 45 | options.outdir = `${outdir}/esm`; 46 | options.format = "esm"; 47 | options.treeShaking = true; 48 | 49 | await build(options); 50 | 51 | console.log(`Build time: ${Date.now() - start}ms`); 52 | 53 | console.log("Build output:"); 54 | await displaySizes(`${outdir}`); 55 | } 56 | 57 | async function displaySizes(path) { 58 | // log generated files with their size in KB 59 | const files = fs.readdirSync(path); 60 | for (const file of files) { 61 | const stat = fs.statSync(`${path}/${file}`); 62 | if (stat.isDirectory()) { 63 | displaySizes(`${path}/${file}`); 64 | continue; 65 | } 66 | console.log(`- ${path}/${file} ${Math.round((stat.size / 1024) * 100) / 100} KB`); 67 | } 68 | } 69 | 70 | run().catch((e) => { 71 | console.error(e); 72 | process.exit(1); 73 | }); 74 | -------------------------------------------------------------------------------- /packages/browser-bundle/index.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2024 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | "use strict"; 16 | export * as Core from "@node-wot/core"; 17 | export * as Http from "@node-wot/binding-http"; 18 | export * as WebSocket from "@node-wot/binding-websockets"; 19 | -------------------------------------------------------------------------------- /packages/browser-bundle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/browser-bundle", 3 | "version": "0.9.2", 4 | "description": "A node-wot bundle that can run in a web browser", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/browser-bundle", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "module": "./dist/esm/browser-bundle/index.js", 12 | "types": "types/index.d.ts", 13 | "files": [ 14 | "dist/" 15 | ], 16 | "main": "dist/wot-bundle.min.js", 17 | "devDependencies": { 18 | "@esm-bundle/chai": "^4.3.4-fix.0", 19 | "@esm-bundle/chai-as-promised": "^7.1.1", 20 | "@jspm/core": "^2.1.0", 21 | "@web/test-runner": "^0.19.0", 22 | "@web/test-runner-commands": "^0.9.0", 23 | "@web/test-runner-playwright": "^0.11.0", 24 | "esbuild": "^0.25.0", 25 | "esbuild-plugin-polyfill-node": "^0.3.0", 26 | "json-schema-faker": "^0.5.6", 27 | "rimraf": "^6.0.1" 28 | }, 29 | "scripts": { 30 | "build": "node esbuild.js", 31 | "test:browser": "wtr \"test/**/*.js\" --node-resolve", 32 | "format": "prettier --write *.js test/*.js *.ts \"**/*.json\"" 33 | }, 34 | "bugs": { 35 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 36 | }, 37 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/browser-bundle#readme", 38 | "keywords": [], 39 | "dependencies": { 40 | "@node-wot/binding-http": "0.9.2", 41 | "@node-wot/binding-websockets": "0.9.2", 42 | "@node-wot/core": "0.9.2" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/browser-bundle/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "resolveJsonModule": true, 5 | "outDir": "types", 6 | "emitDeclarationOnly": true 7 | }, 8 | "include": ["index.ts"], 9 | "references": [ 10 | { 11 | "path": "../core" 12 | }, 13 | { 14 | "path": "../binding-http" 15 | }, 16 | { 17 | "path": "../binding-websockets" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/cli/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/cli/bin/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | // WARNING: this is a workaround for issue https://github.com/npm/cli/issues/2632 3 | require("../dist/cli.js"); 4 | -------------------------------------------------------------------------------- /packages/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/cli", 3 | "version": "0.9.2", 4 | "description": "servient command line interface", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/cli", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/" 13 | ], 14 | "main": "bin/index.js", 15 | "types": "dist/cli.d.ts", 16 | "bin": { 17 | "wot-servient": "bin/index.js" 18 | }, 19 | "optionalDependencies": { 20 | "ts-node": "10.9.1" 21 | }, 22 | "dependencies": { 23 | "@node-wot/binding-coap": "0.9.2", 24 | "@node-wot/binding-file": "0.9.2", 25 | "@node-wot/binding-http": "0.9.2", 26 | "@node-wot/binding-mqtt": "0.9.2", 27 | "@node-wot/core": "0.9.2", 28 | "@thingweb/thing-model": "^1.0.4", 29 | "ajv": "^8.11.0", 30 | "commander": "^9.1.0", 31 | "dotenv": "^16.4.7", 32 | "lodash": "^4.17.21", 33 | "vm2": "3.9.18" 34 | }, 35 | "scripts": { 36 | "build": "tsc -b", 37 | "start": "ts-node src/cli.ts", 38 | "debug": "node -r ts-node/register --inspect-brk=9229 src/cli.ts", 39 | "lint": "eslint .", 40 | "lint:fix": "eslint . --fix", 41 | "format": "prettier --write \"src/**/*.ts\" \"**/*.json\"", 42 | "test": "mocha --require ts-node/register --extension ts" 43 | }, 44 | "bugs": { 45 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 46 | }, 47 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/cli#readme", 48 | "keywords": [], 49 | "devDependencies": { 50 | "@types/lodash": "^4.14.199" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/cli/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/cli/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "resolveJsonModule": true, 7 | "esModuleInterop": true 8 | }, 9 | "include": ["src/**/*", "src/*.json"], 10 | "references": [ 11 | { "path": "../core" }, 12 | { "path": "../binding-http" }, 13 | { "path": "../binding-file" }, 14 | { "path": "../binding-websockets" }, 15 | { "path": "../binding-coap" }, 16 | { "path": "../binding-mqtt" } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/cli/wot-servient.conf.json.md: -------------------------------------------------------------------------------- 1 | # Configuration of WoT Servient 2 | 3 | File "wot-servient.conf.json" 4 | 5 | ``` 6 | { 7 | "servient": { 8 | "clientOnly": CLIENTONLY, 9 | "staticAddress": STATIC, 10 | "scriptAction": RUNSCRIPT 11 | }, 12 | "http": { 13 | "port": HPORT, 14 | "proxy": PROXY, 15 | "allowSelfSigned": ALLOW 16 | }, 17 | "mqtt" : { 18 | "broker": BROKER-URL, 19 | "username": BROKER-USERNAME, 20 | "password": BROKER-PASSWORD, 21 | "clientId": BROKER-UNIQUEID, 22 | "protocolVersion": MQTT_VERSION 23 | }, 24 | "log": { 25 | "level": LEVEL 26 | }, 27 | "credentials": { 28 | THING_ID1: { 29 | "token": TOKEN 30 | }, 31 | THING_ID2: { 32 | "username": USERNAME, 33 | "password": PASSWORD 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | CLIENTONLY is a boolean telling whether to start server part or not 40 | 41 | STATIC is a string indicating a static hostname / IP address 42 | 43 | RUNSCRIPT is a boolean indicating whether to provide the 'runScript' Action 44 | 45 | HPORT is a number defining the HTTP listening port 46 | 47 | PROXY is an object with `"href"` for the proxy URI, `"authorization"` for `"Basic"` or `"Bearer"`, and then corresponding credential fields `"username"`/`"password"` or `"token"` as defined below 48 | 49 | ALLOW is a boolean indicating whether self-signed certificates should be allowed 50 | 51 | BROKER-URL is a string indicating the MQTT broker URL with optional port number (default :1883) 52 | 53 | BROKER-USERNAME is a string indicating the MQTT broker username 54 | 55 | BROKER-PASSWORD is a string indicating the MQTT broker password 56 | 57 | BROKER-UNIQUEID is a string indicating an optional MQTT broker unique ID 58 | 59 | MQTT_VERSION is a number indicating the MQTT protocol version to be used (3, 4, or 5) 60 | 61 | LEVEL is a string or number to set the logging level: `{ error: 0, warn: 1, info: 2, debug: 3 }` (default `info`) 62 | 63 | THING_IDx is a TD @id for which credentials should be configured 64 | 65 | TOKEN is an OAuth (Bearer) token 66 | 67 | USERNAME is an HTTP Basic Auth username 68 | 69 | PASSWORD is an HTTP Basic Auth password 70 | -------------------------------------------------------------------------------- /packages/core/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | # Core of node-wot 2 | 3 | The core of node-wot is the entry point allowing to attach dedicated bindings such as: 4 | 5 | - [HTTP](https://github.com/eclipse-thingweb/node-wot/blob/master/packages/binding-http) 6 | - [CoAP](https://github.com/eclipse-thingweb/node-wot/blob/master/packages/binding-coap) 7 | - ... 8 | 9 | or to create user-specific bindings. 10 | 11 | Current Maintainer(s): [@danielpeintner](https://github.com/danielpeintner) [@relu91](https://github.com/relu91) [@JKRhb](https://github.com/JKRhb) 12 | 13 | ### Prerequisites 14 | 15 | - `npm install @node-wot/core` 16 | 17 | ### Examples 18 | 19 | see binding examples such as 20 | 21 | - https://github.com/eclipse-thingweb/node-wot/blob/master/packages/binding-http 22 | - https://github.com/eclipse-thingweb/node-wot/blob/master/packages/binding-coap 23 | 24 | ## Codecs 25 | 26 | ### Octet-Stream 27 | 28 | The octet-stream codec enables deserialization and serialization of binary data. To encode and decode sequences of bytes, the octet-stream codec uses the following content type parameters: 29 | | Parameter | Description | Default | 30 | | --- | --- | --- | 31 | | `length` | Number of bytes produced during serialization or consumed during deserialization | | 32 | | `signed` | Signedness of the data type, `true` or `false` | `true` | 33 | | `byteSeq` | Endianness, enum of `BIG_ENDIAN`, `LITTLE_ENDIAN`, `BIG_ENDIAN_BYTE_SWAP`, `LITTLE_ENDIAN_BYTE_SWAP` | `BIG_ENDIAN` | 34 | 35 | Additionally, the octet-stream codec supports the data schema terms below for addressing bit-fields: 36 | | Term | Description | Default | 37 | | --- | --- | --- | 38 | | `ex:bitLength` | Number of bits produced during serialization or consumed during deserialization | | 39 | | `ex:bitOffset` | Offset in bits from the beginning of the byte sequence | `0` | 40 | 41 | With the help of the terms and parameters above, the octet-stream codec can be used to serialize and deserialize objects containing bit-fields and sequences of bytes, like in the following example. 42 | 43 | #### Example 44 | 45 | To serialize the object `{ flag1: true, numberProperty: 99, stringProperty: "Web" }` to a sequence of bytes, the content type `application/octet-stream;length=4;signed=false;`, along with the following data schema can be used: 46 | 47 | ```json 48 | { 49 | "type": "object", 50 | "properties": { 51 | "flag1": { "type": "boolean", "ex:bitOffset": 0, "ex:bitLength": 1 }, 52 | "numberProperty": { "type": "integer", "ex:bitOffset": 1, "ex:bitLength": 7 }, 53 | "stringProperty": { "type": "string", "ex:bitOffset": 8, "ex:bitLength": 24 } 54 | } 55 | } 56 | ``` 57 | 58 | ## More Details 59 | 60 | See 61 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/core", 3 | "version": "0.9.2", 4 | "description": "W3C Web of Things (WoT) Servient framework", 5 | "author": "Eclipse Thingweb (https://thingweb.io/)", 6 | "license": "EPL-2.0 OR W3C-20150513", 7 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/core", 8 | "publishConfig": { 9 | "access": "public" 10 | }, 11 | "files": [ 12 | "dist/", 13 | "src/" 14 | ], 15 | "main": "dist/core.js", 16 | "types": "dist/core.d.ts", 17 | "devDependencies": { 18 | "@types/content-type": "^1.1.8", 19 | "@types/debug": "^4.1.7", 20 | "@types/uritemplate": "^0.3.4", 21 | "@types/uuid": "^8.3.1", 22 | "wot-thing-description-types": "^1.1.0-12-March-2025" 23 | }, 24 | "dependencies": { 25 | "@petamoriken/float16": "^3.1.1", 26 | "@thingweb/thing-model": "^1.0.4", 27 | "ajv": "^8.11.0", 28 | "ajv-formats": "^2.1.1", 29 | "cbor": "^8.1.0", 30 | "content-type": "^1.0.5", 31 | "debug": "^4.3.4", 32 | "is-absolute-url": "3.0.3", 33 | "rxjs": "^5.5.11", 34 | "uritemplate": "0.3.4", 35 | "url-toolkit": "2.1.6", 36 | "uuid": "^7.0.3", 37 | "web-streams-polyfill": "^4.0.0" 38 | }, 39 | "scripts": { 40 | "build": "tsc -b", 41 | "lint": "eslint .", 42 | "lint:fix": "eslint . --fix", 43 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"**/*.json\"", 44 | "test": "mocha --require ts-node/register --extension ts" 45 | }, 46 | "bugs": { 47 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 48 | }, 49 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/core#readme", 50 | "directories": { 51 | "test": "test" 52 | }, 53 | "keywords": [], 54 | "eslintConfig": { 55 | "extends": "../../.eslintrc.js" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/core/src/codecs/base64-codec.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ContentCodec } from "../content-serdes"; 17 | import { DataSchema } from "wot-typescript-definitions"; 18 | 19 | export default class Base64Codec implements ContentCodec { 20 | private subMediaType: string; 21 | 22 | constructor(subMediaType: string) { 23 | this.subMediaType = subMediaType; 24 | } 25 | 26 | getMediaType(): string { 27 | return this.subMediaType; 28 | } 29 | 30 | bytesToValue(bytes: Buffer, schema?: DataSchema, parameters?: { [key: string]: string }): string { 31 | const parsed = bytes.toString("ascii"); 32 | return parsed; 33 | } 34 | 35 | valueToBytes(value: unknown, schema?: DataSchema, parameters?: { [key: string]: string }): Buffer { 36 | let body = ""; 37 | if (value !== undefined) { 38 | body = JSON.stringify(value); 39 | } 40 | return Buffer.from(body, "base64"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/core/src/codecs/cbor-codec.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ContentCodec } from "../content-serdes"; 17 | import { DataSchema, DataSchemaValue } from "wot-typescript-definitions"; 18 | import { createLoggers } from "../logger"; 19 | import { decode, encode } from "cbor"; 20 | 21 | const { debug } = createLoggers("core", "cbor-codec"); 22 | 23 | // TODO: Add support for custom tag encoding/decoding 24 | 25 | /** Codec for CBOR de-/serialisation. */ 26 | export default class CborCodec implements ContentCodec { 27 | private subMediaType: string; 28 | 29 | constructor(subMediaType?: string) { 30 | this.subMediaType = subMediaType ?? "application/cbor"; 31 | } 32 | 33 | getMediaType(): string { 34 | return this.subMediaType; 35 | } 36 | 37 | bytesToValue(bytes: Buffer, schema?: DataSchema, parameters?: { [key: string]: string }): DataSchemaValue { 38 | debug(`CborCodec parsing '${bytes.toString()}'`); 39 | 40 | try { 41 | return decode(bytes); 42 | } catch (err) { 43 | if (bytes.byteLength === 0) { 44 | return null; 45 | } 46 | 47 | throw err; 48 | } 49 | } 50 | 51 | valueToBytes(value: unknown, schema?: DataSchema, parameters?: { [key: string]: string }): Buffer { 52 | debug("CborCodec serializing", value); 53 | 54 | if (value === undefined) { 55 | return Buffer.alloc(0); 56 | } 57 | 58 | return encode(value); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/core/src/codecs/json-codec.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ContentSerdes, ContentCodec } from "../content-serdes"; 17 | import { DataSchema, DataSchemaValue } from "wot-typescript-definitions"; 18 | import { createLoggers } from "../logger"; 19 | 20 | const { debug } = createLoggers("core", "json-codec"); 21 | 22 | /** default implementation offering JSON de-/serialisation */ 23 | export default class JsonCodec implements ContentCodec { 24 | private subMediaType: string; 25 | 26 | constructor(subMediaType?: string) { 27 | this.subMediaType = subMediaType ?? ContentSerdes.DEFAULT; 28 | } 29 | 30 | getMediaType(): string { 31 | return this.subMediaType; 32 | } 33 | 34 | bytesToValue(bytes: Buffer, schema?: DataSchema, parameters?: { [key: string]: string }): DataSchemaValue { 35 | debug(`JsonCodec parsing '${bytes.toString()}'`); 36 | 37 | let parsed; 38 | try { 39 | parsed = JSON.parse(bytes.toString()); 40 | } catch (err) { 41 | if (err instanceof SyntaxError) { 42 | if (bytes.byteLength === 0) { 43 | // empty payload -> void/undefined 44 | parsed = undefined; 45 | } else { 46 | // be relaxed about what is received -> string without quotes 47 | parsed = bytes.toString(); 48 | } 49 | } else { 50 | throw err; 51 | } 52 | } 53 | 54 | return parsed; 55 | } 56 | 57 | valueToBytes(value: unknown, schema?: DataSchema, parameters?: { [key: string]: string }): Buffer { 58 | debug("JsonCodec serializing", value); 59 | let body = ""; 60 | if (value !== undefined) { 61 | body = JSON.stringify(value); 62 | } 63 | return Buffer.from(body); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/core/src/content.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ContentSerdes } from "./content-serdes"; 17 | import ProtocolHelpers from "./protocol-helpers"; 18 | 19 | export class Content { 20 | type: string; 21 | body: NodeJS.ReadableStream; 22 | 23 | constructor(type: string, body: NodeJS.ReadableStream) { 24 | this.type = type; 25 | this.body = body; 26 | } 27 | 28 | toBuffer(): Promise { 29 | return ProtocolHelpers.readStreamFully(this.body); 30 | } 31 | } 32 | 33 | /** 34 | * Content object with the default content type (`application/json`). 35 | */ 36 | export class DefaultContent extends Content { 37 | constructor(body: NodeJS.ReadableStream) { 38 | super(ContentSerdes.DEFAULT, body); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/core/src/core.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | /** Exports of this module */ 17 | 18 | // Servient is also the default export 19 | import Servient from "./servient"; 20 | 21 | export default Servient; 22 | export { Servient }; 23 | 24 | // TD definitions 25 | export * from "./thing-description"; 26 | 27 | // SerDes functionality 28 | export * from "./serdes"; 29 | 30 | // ContentSerdes + built-in codecs 31 | export * from "./content-serdes"; 32 | export { default as JsonCodec } from "./codecs/json-codec"; 33 | export { default as CborCodec } from "./codecs/cbor-codec"; 34 | export { default as TextCodec } from "./codecs/text-codec"; 35 | export { default as Base64Codec } from "./codecs/base64-codec"; 36 | export { default as NetconfOctetstreamCodecCodec } from "./codecs/octetstream-codec"; 37 | 38 | // Protocols & Content 39 | export * from "./protocol-interfaces"; 40 | export { PropertyContentMap, ContentListener } from "./protocol-interfaces"; 41 | export { Content, DefaultContent } from "./content"; 42 | 43 | // Scripting API objects 44 | export { default as ConsumedThing } from "./consumed-thing"; 45 | export { default as ExposedThing } from "./exposed-thing"; 46 | 47 | // Helper Implementations 48 | export { default as Helpers } from "./helpers"; 49 | export { default as ProtocolHelpers } from "./protocol-helpers"; 50 | 51 | // Logger Functions 52 | export { createLoggers, createDebugLogger, createErrorLogger, createInfoLogger, createWarnLogger } from "./logger"; 53 | -------------------------------------------------------------------------------- /packages/core/src/errors.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2021 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { DataSchemaValue } from "wot-typescript-definitions"; 17 | 18 | export class NotReadableError extends Error { 19 | constructor(message: string) { 20 | super(message); 21 | 22 | // Set the prototype explicitly. 23 | // TS limitation see https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work 24 | Object.setPrototypeOf(this, NotReadableError.prototype); 25 | } 26 | } 27 | 28 | export class NotSupportedError extends Error { 29 | constructor(message: string) { 30 | super(message); 31 | 32 | // Set the prototype explicitly. 33 | // TS limitation see https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work 34 | Object.setPrototypeOf(this, NotSupportedError.prototype); 35 | } 36 | } 37 | 38 | export class DataSchemaError extends Error { 39 | value: DataSchemaValue; 40 | constructor(message: string, value: DataSchemaValue) { 41 | super(message); 42 | this.value = value; 43 | // Set the prototype explicitly. 44 | // TS limitation see https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work 45 | Object.setPrototypeOf(this, NotSupportedError.prototype); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /packages/core/src/validation.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ErrorObject } from "ajv"; 17 | import Helpers from "./helpers"; 18 | 19 | export function isThingDescription(input: unknown): input is WoT.ThingDescription { 20 | return Helpers.tsSchemaValidator(input); 21 | } 22 | 23 | export function getLastValidationErrors() { 24 | const errors = Helpers.tsSchemaValidator.errors?.map((o: ErrorObject) => o.message).join("\n"); 25 | return new Error(errors); 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/test/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.eslintrc.json", 3 | "rules": { 4 | "import/no-extraneous-dependencies": "off" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/core/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".." 5 | }, 6 | "include": ["*.ts", "**/*.ts", "../src/**/*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "resolveJsonModule": true, 5 | "outDir": "dist", 6 | "rootDir": "src" 7 | }, 8 | "include": ["src/**/*"], 9 | "references": [] 10 | } 11 | -------------------------------------------------------------------------------- /packages/examples/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../.eslintrc.js" 3 | } 4 | -------------------------------------------------------------------------------- /packages/examples/README.md: -------------------------------------------------------------------------------- 1 | # node-wot Examples 2 | 3 | ## Script Examples 4 | 5 | Script examples are located in 6 | 7 | - `src\scripts` 8 | - `src\testthing` 9 | 10 | 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. 11 | 12 | see https://github.com/eclipse-thingweb/node-wot/issues/171. 13 | 14 | ### Workflow 15 | 16 | 1. Run `npm run build` 17 | 2. Remove the following 3/4 lines in JS files of folder `dist/` 18 | 19 | ``` 20 | Object.defineProperty(exports, "__esModule", { value: true }); 21 | require("wot-typescript-definitions"); 22 | let WoT; 23 | let WoTHelpers; 24 | ``` 25 | 26 | 3. Copy the according JS file(s) to 27 | 28 | - `/examples/scripts` 29 | - `/examples/testthing` 30 | 31 | ## Test Thing 32 | 33 | Test thing and client is located in `src\testthing`. 34 | -------------------------------------------------------------------------------- /packages/examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@node-wot/examples", 3 | "version": "0.9.2", 4 | "private": true, 5 | "description": "Examples for node-wot (not published)", 6 | "author": "Eclipse Thingweb (https://thingweb.io/)", 7 | "license": "EPL-2.0 OR W3C-20150513", 8 | "repository": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/examples", 9 | "dependencies": { 10 | "@node-wot/binding-coap": "0.9.2", 11 | "@node-wot/binding-http": "0.9.2", 12 | "@node-wot/binding-mqtt": "0.9.2", 13 | "@node-wot/binding-opcua": "0.9.2", 14 | "@node-wot/core": "0.9.2" 15 | }, 16 | "scripts": { 17 | "build": "tsc -b", 18 | "lint": "eslint .", 19 | "lint:fix": "eslint . --fix", 20 | "format": "prettier --write \"src/**/*.ts\" \"**/*.json\"" 21 | }, 22 | "bugs": { 23 | "url": "https://github.com/eclipse-thingweb/node-wot/issues" 24 | }, 25 | "homepage": "https://github.com/eclipse-thingweb/node-wot/tree/master/packages/examples#readme", 26 | "main": "index.js", 27 | "keywords": [] 28 | } 29 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/coap/example-client.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Servient } from "@node-wot/core"; 17 | import { CoapClientFactory } from "@node-wot/binding-coap"; 18 | 19 | // create Servient and add CoAP binding 20 | const servient = new Servient(); 21 | servient.addClientFactory(new CoapClientFactory()); 22 | 23 | servient 24 | .start() 25 | .then(async (WoT) => { 26 | try { 27 | const td = await WoT.requestThingDescription("coap://plugfest.thingweb.io:5683/testthing"); 28 | const thing = await WoT.consume(td); 29 | 30 | // read property 31 | const read1 = await thing.readProperty("string"); 32 | console.log("string value is: ", await read1.value()); 33 | } catch (err) { 34 | console.error("Script error:", err); 35 | } 36 | }) 37 | .catch((err) => { 38 | console.error("Start error:", err); 39 | }); 40 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/coap/example-server.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Servient } from "@node-wot/core"; 17 | import { CoapServer } from "@node-wot/binding-coap"; 18 | 19 | // create Servient add HTTP binding 20 | const servient = new Servient(); 21 | servient.addServer(new CoapServer()); 22 | 23 | servient.start().then((WoT) => { 24 | WoT.produce({ 25 | title: "MyCounter", 26 | properties: { 27 | count: { 28 | type: "integer", 29 | }, 30 | }, 31 | }).then((thing) => { 32 | let count = 0; 33 | 34 | console.log("Produced " + thing.getThingDescription().title); 35 | 36 | // set property handlers (using async-await) 37 | thing.setPropertyReadHandler("count", async () => count); 38 | thing.setPropertyWriteHandler("count", async (intOutput) => { 39 | const value = await intOutput.value(); 40 | if (typeof value === "number") { 41 | count = value; 42 | } 43 | }); 44 | 45 | thing.expose().then(() => { 46 | console.info(thing.getThingDescription().title + " ready"); 47 | console.info("TD : " + JSON.stringify(thing.getThingDescription())); 48 | }); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/http/example-client.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Servient } from "@node-wot/core"; 17 | import { HttpClientFactory } from "@node-wot/binding-http"; 18 | 19 | // create Servient and add HTTP binding 20 | const servient = new Servient(); 21 | servient.addClientFactory(new HttpClientFactory()); 22 | 23 | servient 24 | .start() 25 | .then(async (WoT) => { 26 | try { 27 | const td = await WoT.requestThingDescription("http://plugfest.thingweb.io:8083/testthing"); 28 | const thing = await WoT.consume(td); 29 | 30 | // read property 31 | const read1 = await thing.readProperty("string"); 32 | console.log("string value is: ", await read1.value()); 33 | } catch (err) { 34 | console.error("Script error:", err); 35 | } 36 | }) 37 | .catch((err) => { 38 | console.error("Start error:", err); 39 | }); 40 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/http/example-server-secure.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Servient } from "@node-wot/core"; 17 | import { HttpServer } from "@node-wot/binding-http"; 18 | 19 | // create secure Servient with username & password credentials 20 | const servient = new Servient(); 21 | servient.addCredentials({ 22 | "urn:dev:wot:org:eclipse:thingweb:my-example-secure": { 23 | username: "node-wot", 24 | password: "hello", 25 | // token: "1/mZ1edKKACtPAb7zGlwSzvs72PvhAbGmB8K1ZrGxpcNM" 26 | }, 27 | }); 28 | const httpConfig = { 29 | allowSelfSigned: true, // client configuration 30 | serverKey: "privatekey.pem", 31 | serverCert: "certificate.pem", 32 | security: [ 33 | { 34 | scheme: "basic", // (username & password) 35 | }, 36 | ], 37 | }; 38 | // add HTTPS binding with configuration 39 | servient.addServer(new HttpServer(httpConfig)); 40 | 41 | servient.start().then((WoT) => { 42 | WoT.produce({ 43 | title: "MyCounter", 44 | properties: { 45 | count: { 46 | type: "integer", 47 | }, 48 | }, 49 | }).then((thing) => { 50 | // init property value 51 | let count = 0; 52 | 53 | console.log("Produced " + thing.getThingDescription().title); 54 | 55 | // set property handlers (using async-await) 56 | thing.setPropertyReadHandler("count", async () => count); 57 | thing.setPropertyWriteHandler("count", async (intOutput) => { 58 | const value = await intOutput.value(); 59 | if (typeof value === "number") { 60 | count = value; 61 | } 62 | }); 63 | 64 | thing.expose().then(() => { 65 | console.info(thing.getThingDescription().title + " ready"); 66 | console.info("TD : " + JSON.stringify(thing.getThingDescription())); 67 | }); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/http/example-server.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Servient } from "@node-wot/core"; 17 | import { HttpServer } from "@node-wot/binding-http"; 18 | 19 | // create Servient add HTTP binding with port configuration 20 | const servient = new Servient(); 21 | servient.addServer( 22 | new HttpServer({ 23 | port: 8081, // (default 8080) 24 | urlRewrite: { 25 | "/myroot/foo/cnt": "/mycounter/properties/count", 26 | "/mysecondURL/for/the/same/resource": "/mycounter/properties/count", 27 | }, 28 | }) 29 | ); 30 | 31 | servient.start().then((WoT) => { 32 | WoT.produce({ 33 | title: "MyCounter", 34 | properties: { 35 | count: { 36 | type: "integer", 37 | }, 38 | }, 39 | }).then((thing) => { 40 | // init property value 41 | let count = 0; 42 | 43 | console.log("Produced " + thing.getThingDescription().title); 44 | 45 | // set property handlers (using async-await) 46 | thing.setPropertyReadHandler("count", async () => count); 47 | thing.setPropertyWriteHandler("count", async (intOutput) => { 48 | const value = await intOutput.value(); 49 | if (typeof value === "number") { 50 | count = value; 51 | } 52 | }); 53 | 54 | thing.expose().then(() => { 55 | console.info(thing.getThingDescription().title + " ready"); 56 | console.info("TD : " + JSON.stringify(thing.getThingDescription())); 57 | }); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/opcua/demo-opcua-thing-description.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | const endpointUrl = "opc.tcp://opcuademo.sterfive.com:26543"; 17 | export const thingDescription: WoT.ThingDescription = { 18 | "@context": "https://www.w3.org/2019/wot/td/v1", 19 | "@type": ["Thing"], 20 | securityDefinitions: { 21 | nosec_sc: { 22 | scheme: "nosec", 23 | }, 24 | }, 25 | security: "nosec_sc", 26 | title: "servient", 27 | description: "node-wot CLI Servient", 28 | properties: { 29 | pumpSpeed: { 30 | description: "the pump speed", 31 | observable: true, 32 | readOnly: true, 33 | unit: "m/s", 34 | type: "number", 35 | forms: [ 36 | { 37 | href: endpointUrl + "?id=ns=1;s=PumpSpeed", 38 | op: ["readproperty", "observeproperty"], 39 | }, 40 | ], 41 | }, 42 | temperature: { 43 | description: "the temperature", 44 | observable: true, 45 | readOnly: true, 46 | unit: "m/s", 47 | type: "number", 48 | forms: [ 49 | { 50 | href: endpointUrl + "?id=ns=1;s=Temperature", 51 | op: ["readproperty", "observeproperty"], 52 | }, 53 | ], 54 | }, 55 | }, 56 | }; 57 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/opcua/demo-opcua1.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { Servient } from "@node-wot/core"; 17 | import { OPCUAClientFactory } from "@node-wot/binding-opcua"; 18 | 19 | import { thingDescription } from "./demo-opcua-thing-description"; 20 | (async () => { 21 | const servient = new Servient(); 22 | servient.addClientFactory(new OPCUAClientFactory()); 23 | 24 | const wot = await servient.start(); 25 | const thing = await wot.consume(thingDescription); 26 | 27 | const content = await thing.readProperty("pumpSpeed"); 28 | const pumpSpeed = await content.value(); 29 | 30 | console.log("------------------------------"); 31 | console.log("Pump Speed is : ", pumpSpeed, "m/s"); 32 | console.log("------------------------------"); 33 | 34 | await servient.shutdown(); 35 | })(); 36 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/opcua/demo-opcua2.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { Servient } from "@node-wot/core"; 16 | import { OPCUAClientFactory } from "@node-wot/binding-opcua"; 17 | import { thingDescription } from "./demo-opcua-thing-description"; 18 | 19 | (async () => { 20 | const servient = new Servient(); 21 | servient.addClientFactory(new OPCUAClientFactory()); 22 | 23 | const wot = await servient.start(); 24 | const thing = await wot.consume(thingDescription); 25 | 26 | thing.observeProperty("temperature", async (data) => { 27 | const temperature = await data.value(); 28 | console.log("------------------------------"); 29 | console.log("temperature : ", temperature, "m/s"); 30 | console.log("------------------------------"); 31 | }); 32 | 33 | await new Promise((resolve) => setTimeout(resolve, 10000)); 34 | 35 | await servient.shutdown(); 36 | })(); 37 | -------------------------------------------------------------------------------- /packages/examples/src/bindings/opcua/opcua-coffee-machine-demo.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2022 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | import { Servient } from "@node-wot/core"; 16 | import { OPCUAClientFactory } from "@node-wot/binding-opcua"; 17 | import { thingDescription } from "./opcua-coffee-machine-thing-description"; 18 | 19 | const pause = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); 20 | (async () => { 21 | const servient = new Servient(); 22 | servient.addClientFactory(new OPCUAClientFactory()); 23 | 24 | const wot = await servient.start(); 25 | const thing = await wot.consume(thingDescription); 26 | 27 | try { 28 | thing.observeProperty("waterTankLevel", async (data) => { 29 | const waterTankLevel = await data.value(); 30 | console.log("------------------------------"); 31 | console.log("tankLevel : ", waterTankLevel, "ml"); 32 | console.log("------------------------------"); 33 | }); 34 | thing.observeProperty("coffeeBeanLevel", async (data) => { 35 | const coffeBeanLevel = await data.value(); 36 | console.log("------------------------------"); 37 | console.log("bean level : ", coffeBeanLevel, "g"); 38 | console.log("------------------------------"); 39 | }); 40 | await thing.invokeAction("brewCoffee", { CoffeeType: 1 }); 41 | await pause(5000); 42 | await thing.invokeAction("brewCoffee", { CoffeeType: 0 }); 43 | await pause(5000); 44 | 45 | await thing.invokeAction("fillTank"); 46 | await pause(5000); 47 | } finally { 48 | await servient.shutdown(); 49 | } 50 | })(); 51 | -------------------------------------------------------------------------------- /packages/examples/src/quickstart/README.md: -------------------------------------------------------------------------------- 1 | # Quick Start Things 2 | 3 | This set of Things can be used to build mashup applications for a smart home scenario. 4 | These Things are: 5 | 6 | - Simple coffee machine that can take an order to brew a coffee. 7 | - Presence sensor that emits an event when a person is detected. 8 | - Smart clock that runs 60 times faster than real time, where 1 hour happens in 1 minute. 9 | 10 | These Things are hosted on plugfest.thingweb.io but can be also self-hosted. 11 | -------------------------------------------------------------------------------- /packages/examples/src/quickstart/presence-sensor.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2023 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | // This is an example Thing script which is a simple presence detector 17 | // It fires an event when it detects a person (mocked as every 5 second) 18 | 19 | import { Servient } from "@node-wot/core"; 20 | import { MqttBrokerServer } from "@node-wot/binding-mqtt"; 21 | 22 | // create Servient add MQTT binding with port configuration 23 | const servient = new Servient(); 24 | servient.addServer(new MqttBrokerServer({ uri: "mqtt://test.mosquitto.org" })); 25 | 26 | servient.start().then((WoT) => { 27 | WoT.produce({ 28 | title: "PresenceSensor", 29 | description: "Thing that can detect presence of human nearby", 30 | support: "https://github.com/eclipse-thingweb/node-wot/", 31 | "@context": "https://www.w3.org/2022/wot/td/v1.1", 32 | events: { 33 | presenceDetected: { 34 | title: "Presence Detected", 35 | description: 36 | "An event that is emitted when a person is detected in the room. It is mocked and emitted every 5 seconds", 37 | data: { 38 | type: "number", 39 | title: "Distance", 40 | minimum: 55, 41 | maximum: 1200, 42 | }, 43 | }, 44 | }, 45 | }) 46 | .then((thing) => { 47 | console.log("Produced " + thing.getThingDescription().title); 48 | 49 | // expose the thing 50 | thing.expose().then(() => { 51 | console.info(thing.getThingDescription().title + " ready"); 52 | 53 | // mocking the detection with an event sent every 5 seconds, with a random distance 54 | setInterval(() => { 55 | const distance: number = Math.random() * (1200 - 55) + 55; 56 | thing.emitEvent("presenceDetected", distance); 57 | console.info("Emitted presence with distance ", distance); 58 | }, 5000); 59 | }); 60 | }) 61 | .catch((e) => { 62 | console.log(e); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /packages/examples/src/scripts/counter-client.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2020 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | function getFormIndexForDecrementWithCoAP(thing: WoT.ConsumedThing): number { 17 | const forms = thing.getThingDescription().actions?.decrement.forms; 18 | if (forms !== undefined) { 19 | for (let i = 0; i < forms.length; i++) { 20 | if (/^coaps?:\/\/.*/.test(forms[i].href)) { 21 | return i; 22 | } 23 | } 24 | } 25 | // return formIndex: 0 if no CoAP target IRI found 26 | return 0; 27 | } 28 | 29 | WoT.requestThingDescription("coap://localhost:5683/counter") 30 | .then(async (td) => { 31 | try { 32 | const thing = await WoT.consume(td); 33 | console.info("=== TD ==="); 34 | console.info(td); 35 | console.info("=========="); 36 | 37 | // read property #1 38 | const read1 = await thing.readProperty("count"); 39 | console.log("count value is", await read1.value()); 40 | 41 | // increment property #1 (without step) 42 | await thing.invokeAction("increment"); 43 | const inc1 = await thing.readProperty("count"); 44 | console.info("count value after increment #1 is", await inc1.value()); 45 | 46 | // increment property #2 (with step) 47 | await thing.invokeAction("increment", undefined, { uriVariables: { step: 3 } }); 48 | const inc2 = await thing.readProperty("count"); 49 | console.info("count value after increment #2 (with step 3) is", await inc2.value()); 50 | 51 | // look for the first form for decrement with CoAP binding 52 | await thing.invokeAction("decrement", undefined, { 53 | formIndex: getFormIndexForDecrementWithCoAP(thing), 54 | }); 55 | const dec1 = await thing.readProperty("count"); 56 | console.info("count value after decrement is", await dec1.value()); 57 | } catch (err) { 58 | console.error("Script error:", err); 59 | } 60 | }) 61 | .catch((err) => { 62 | console.error("Fetch error:", err); 63 | }); 64 | -------------------------------------------------------------------------------- /packages/examples/src/security/certificate.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICDDCCAXUCFEcgrATArZXi0508eBk873JbhNT5MA0GCSqGSIb3DQEBCwUAMEUx 3 | CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl 4 | cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjAwNTA3MTcwMzEwWhcNMjAwNjA2MTcw 5 | MzEwWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE 6 | CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GN 7 | ADCBiQKBgQDB4USEKBahhOhznS3oF4C1hGi7K4j2zpJIxIKxJD8zvlV+MazQOsCv 8 | 4FtudE9Lf9JV4Cni8Ci/bLgSENgkMOK6JJrvYSZBmcO/soDoz6szzIuLJbQoZvM6 9 | wRxwKwXYP77qK+zbYhdFTZiESO77RPvnnAxU7e4Ym2bZXjghqB0GDQIDAQABMA0G 10 | CSqGSIb3DQEBCwUAA4GBAJjPDHpmbfd4QMtARLyslQ8LpE+fk/OtF58eOFF/izko 11 | DWRf3dXGGNnhZOESMbRYSgygEZR0dhbaUSdiGMrj+MapOwsmoYnvz44bSeGOHAgq 12 | cutpTJ2oXeeiHsOo18/tNc5RgvRDJivlgrheaC4LSq4eb+hUFV0Zj6cR+GRauSsL 13 | -----END CERTIFICATE----- 14 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/README.md: -------------------------------------------------------------------------------- 1 | # oAuth example 2 | 3 | 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. 4 | 5 | ## run the example 6 | 7 | Set the current working directory to this folder. Then execute: 8 | 9 | ```bash 10 | npm install 11 | npm run build 12 | ``` 13 | 14 | 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`. 15 | 16 | Now you are ready to run the example. 17 | 18 | ```bash 19 | # start the server 20 | npm run server 21 | ``` 22 | 23 | in a different terminal 24 | 25 | ```bash 26 | # start the exposer 27 | npm run start:exposer 28 | ``` 29 | 30 | Finally, in other terminal 31 | 32 | ```bash 33 | npm run start:consumer 34 | ``` 35 | 36 | you should see the following line at the end of consumer log: 37 | 38 | ```bash 39 | oAuth token was Ok! 40 | ``` 41 | 42 | This confirms that the oAuth flow was completed successfully. Now you can have fun revoking the access to the consumer script. Go 43 | 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. 44 | 45 | ## Where is a JS version? 46 | 47 | See [here](../../../examples/security/oauth) 48 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/consumer.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | WoT.requestThingDescription("https://localhost:8080/oauth").then((td) => { 17 | WoT.consume(td).then(async (thing) => { 18 | try { 19 | const resp = await thing.invokeAction("sayOk"); 20 | const result = await resp?.value(); 21 | console.log("oAuth token was", result); 22 | } catch (error) { 23 | console.log("It seems that I couldn't access the resource"); 24 | } 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/exposer.ts: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | 16 | import { ExposedThingInit } from "wot-typescript-definitions"; 17 | 18 | const td: ExposedThingInit = { 19 | "@context": "https://www.w3.org/2019/wot/td/v1", 20 | title: "OAuth", 21 | id: "urn:dev:wot:oauth:test", 22 | securityDefinitions: { 23 | oauth2_sc: { 24 | scheme: "oauth2", 25 | flow: "client", 26 | token: "https://localhost:3000/token", 27 | scopes: ["user", "admin"], 28 | }, 29 | }, 30 | security: ["oauth2_sc"], 31 | actions: { 32 | sayOk: { 33 | description: "A simple action protected with oauth", 34 | idempotent: true, 35 | }, 36 | }, 37 | }; 38 | try { 39 | WoT.produce(td).then((thing) => { 40 | thing.setActionHandler("sayOk", async () => "Ok!"); 41 | thing.expose(); 42 | }); 43 | } catch (err) { 44 | console.error("Script error: " + err); 45 | } 46 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oauth-test", 3 | "version": "1.0.0", 4 | "description": "Simple project setup to test oauth functionalities", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "tsc -b", 8 | "server": "node server.js", 9 | "start:exposer": "node ../../../../cli/dist/cli.js -f ./wot-server-servient-conf.json ../../../dist/security/oauth/exposer.js", 10 | "start:consumer": "node ../../../../cli/dist/cli.js -f ./wot-client-servient-conf.json ../../../dist/security/oauth/consumer.js", 11 | "debug:consumer": "node --inspect-brk ../../../../cli/dist/cli.js -f ./wot-client-servient-conf.json ../../../dist/security/oauth/consumer.js" 12 | }, 13 | "author": "Eclipse Thingweb (https://thingweb.io/)", 14 | "license": "EPL-2.0 OR W3C-20150513", 15 | "devDependencies": { 16 | "@node-oauth/express-oauth-server": "^3.0.0", 17 | "@types/node": "16.18.35", 18 | "cors": "^2.8.5", 19 | "ts-node": "10.9.1", 20 | "typescript": "4.7.4", 21 | "typescript-standard": "^0.3.36", 22 | "wot-typescript-definitions": "0.8.0-SNAPSHOT.30" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/server.js: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | * Copyright (c) 2018 Contributors to the Eclipse Foundation 3 | * 4 | * See the NOTICE file(s) distributed with this work for additional 5 | * information regarding copyright ownership. 6 | * 7 | * This program and the accompanying materials are made available under the 8 | * terms of the Eclipse Public License v. 2.0 which is available at 9 | * http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and 10 | * Document License (2015-05-13) which is available at 11 | * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document. 12 | * 13 | * SPDX-License-Identifier: EPL-2.0 OR W3C-20150513 14 | ********************************************************************************/ 15 | /** 16 | * A simple oAuth test server 17 | */ 18 | const OAuthServer = require("@node-oauth/express-oauth-server"); 19 | const bodyParser = require("body-parser"); 20 | const cors = require("cors"); 21 | const https = require("https"); 22 | const fs = require("fs"); 23 | const express = require("express"); 24 | const Memory = require("./memory-model"); 25 | 26 | var app = express(); 27 | app.use(cors()); 28 | app.options("*", cors()); 29 | 30 | const model = new Memory(); 31 | 32 | app.oauth = new OAuthServer({ 33 | model: model, 34 | }); 35 | 36 | app.use(bodyParser.json()); 37 | app.use("/introspect", bodyParser.urlencoded({ extended: false })); 38 | app.use("/introspect", (req, res, next) => { 39 | if (req.method !== "POST" || !req.is("application/x-www-form-urlencoded")) { 40 | return res.status(400).end(); 41 | } 42 | 43 | // rewrite body authenticate method is not compliant to https://tools.ietf.org/html/rfc7662 44 | const token = req.body.token; 45 | delete req.body.token; 46 | req.body.access_token = token; 47 | console.log("Body changed,"); 48 | next(); 49 | }); 50 | 51 | app.use("/introspect", async (req, res, next) => { 52 | return app.oauth.authenticate()(req, res, next); 53 | }); 54 | app.use("/introspect", (req, res) => { 55 | const token = res.locals.oauth.token; 56 | console.log("Token was", token ? "Ok" : "not Ok"); 57 | res.json({ 58 | active: !!token, 59 | scope: token.client.scopes.join(" "), 60 | client_id: token.client.clientId, 61 | }).end(); 62 | }); 63 | 64 | app.use("/token", bodyParser.urlencoded({ extended: false })); 65 | app.use("/token", app.oauth.token()); 66 | 67 | app.use("/resource", (req, res) => { 68 | console.log("qui?"); 69 | res.send("Ok!"); 70 | }); 71 | 72 | https 73 | .createServer( 74 | { 75 | key: fs.readFileSync("../privatekey.pem"), 76 | cert: fs.readFileSync("../certificate.pem"), 77 | }, 78 | app 79 | ) 80 | .listen(3000, "localhost", () => { 81 | console.log("listening"); 82 | }); 83 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "../../../dist" 4 | }, 5 | "extends": "../../../tsconfig.json", 6 | "include": [], 7 | "files": ["consumer.ts", "exposer.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/wot-client-servient-conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "servient": { 3 | "clientOnly": true 4 | }, 5 | "http": { 6 | "allowSelfSigned": true 7 | }, 8 | "credentials": { 9 | "urn:dev:wot:oauth:test": { 10 | "clientId": "node-wot", 11 | "clientSecret": "isgreat!" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/examples/src/security/oauth/wot-server-servient-conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "servient": {}, 3 | "http": { 4 | "allowSelfSigned": true, 5 | "serverKey": "../privatekey.pem", 6 | "serverCert": "../certificate.pem", 7 | "security": [ 8 | { 9 | "scheme": "oauth2", 10 | "method": { 11 | "name": "introspection_endpoint", 12 | "endpoint": "https://localhost:3000/introspect", 13 | "allowSelfSigned": true 14 | } 15 | } 16 | ] 17 | }, 18 | "credentials": { 19 | "urn:dev:wot:oauth:test": { 20 | "clientId": "node-wot", 21 | "clientSecret": "isgreat!" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/examples/src/security/privatekey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQDB4USEKBahhOhznS3oF4C1hGi7K4j2zpJIxIKxJD8zvlV+MazQ 3 | OsCv4FtudE9Lf9JV4Cni8Ci/bLgSENgkMOK6JJrvYSZBmcO/soDoz6szzIuLJbQo 4 | ZvM6wRxwKwXYP77qK+zbYhdFTZiESO77RPvnnAxU7e4Ym2bZXjghqB0GDQIDAQAB 5 | AoGBAIZCwXfjawifSXoGtuuqmu8Yqo4zL736f0L1EqwpNbtXa0zgiZQJm7Yv4CE1 6 | WlQmSDo/6cHGHfGyECYyk/s7/0VDdfS6jf5AMzpkCXP+32FZZegN7JxasgYsddZC 7 | LlpYhxjUd1vnYEIvvAefJ7N3Y0jdp1gR1Iri9+7vJjuFXJoBAkEA6foaD4sFDJhO 8 | /zYPPOJljtwtQz+ik4nXJCIvzLYAIKBcOgFirqLqcHfRnHh17DrumqVB3IhtjyoX 9 | XAQ0+uFZnQJBANQg/Xpijb5NuK43cg1q/MLyR8vdp1AxvmpS0YnsObxJAqp79oT/ 10 | EEU+WXEJKmxBWtVbwryraAnUamyUtG3rqzECQQCqUGSR9dcKEQBH47j5z66va/QC 11 | pJqaHNcfNUdoEv9KwJABpSqJBovyrDVHWaQ0/bzbkvm7Jw/hC3mPgHx0Nn89AkBj 12 | E+2QhguSQRbrODZrEfdwzly+WY7WJAW9/2SjONRWnvtByZiA0ek1jkOUSiWoXnYg 13 | hTVVjfGP9cinYmVLmfFhAkA+L4iyT0uKjXoqugJU2wYDdLDNh3zPg4xu+Pg2Ua62 14 | SFr28bvOWI7g2DV6KX/gS1wKbSHbctUylJHQRxFaHSlX 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /packages/examples/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "module": "Node16", 6 | "rootDir": "src", 7 | "target": "ES2021", 8 | "sourceMap": false, 9 | "removeComments": false 10 | }, 11 | "include": ["src/**/*"], 12 | "references": [] 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "experimentalDecorators": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2021", 4 | "skipLibCheck": false, 5 | "module": "Node16", 6 | "moduleResolution": "Node16", 7 | "outDir": "dist", 8 | "strict": true, 9 | "composite": true, 10 | "incremental": true, 11 | "sourceMap": true, 12 | "noImplicitReturns": true, 13 | "removeComments": true, 14 | "noLib": false, 15 | "preserveConstEnums": true, 16 | "experimentalDecorators": true, 17 | "declaration": true, 18 | "esModuleInterop": true, 19 | "resolveJsonModule": false, 20 | "skipDefaultLibCheck": false, 21 | "allowJs": false, 22 | "strictNullChecks": true 23 | }, 24 | "references": [ 25 | { "path": "./packages/binding-coap" }, 26 | { "path": "./packages/binding-file" }, 27 | { "path": "./packages/binding-http" }, 28 | { "path": "./packages/binding-mbus" }, 29 | { "path": "./packages/binding-modbus" }, 30 | { "path": "./packages/binding-mqtt" }, 31 | { "path": "./packages/binding-netconf" }, 32 | { "path": "./packages/binding-opcua" }, 33 | { "path": "./packages/binding-websockets" }, 34 | { "path": "./packages/cli" }, 35 | { "path": "./packages/core" }, 36 | { "path": "./packages/browser-bundle" }, 37 | { "path": "./packages/examples" } 38 | ], 39 | "include": [ 40 | /** specifically nothing here */ 41 | ], 42 | "exclude": [] 43 | } 44 | -------------------------------------------------------------------------------- /utils/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended", "standard", "prettier"], 3 | "env": { 4 | "es6": true, 5 | "node": true 6 | } 7 | } 8 | --------------------------------------------------------------------------------