├── docs
├── VT.png
├── STYLEGUIDE.md
├── MainEditor.png
├── Performance.png
├── ARCHITECTURE.md
└── SOURCES.md
├── electron-builder.yml
├── public
├── icon.png
├── favicon.ico
└── index.html
├── demonstration.gif
├── src
├── assets
│ ├── td.png
│ ├── add.png
│ ├── mage.png
│ ├── minus.png
│ ├── url.png
│ ├── cancel.png
│ ├── circle.png
│ ├── delete.png
│ ├── folder.png
│ ├── mashup.png
│ ├── options.png
│ ├── search.png
│ ├── upload.png
│ ├── add_white.png
│ ├── arrow_down.png
│ ├── arrow_left.png
│ ├── computer.png
│ ├── settings.png
│ ├── settings_.png
│ ├── add_plugins.png
│ ├── arrow_right.png
│ ├── circle_grey.png
│ ├── delete_white.png
│ ├── include-icon.png
│ ├── minus_white.png
│ ├── performance.png
│ ├── action-template.png
│ ├── checked_circle.png
│ ├── event-template.png
│ ├── forbidden-icon.png
│ ├── options_white.png
│ ├── read-template.png
│ ├── arrow_double_left.png
│ ├── arrow_down_white.png
│ ├── arrow_right_white.png
│ ├── must-include-icon.png
│ ├── arrow_double_right.png
│ └── font-awesome-4.7.0
│ │ └── fonts
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
├── shims-vue.d.ts
├── vue-types-global.d.ts
├── components
│ ├── 01_atoms
│ │ ├── aMashupTdInteractionElement.vue
│ │ ├── aStatusbar.vue
│ │ ├── aInputSelector.vue
│ │ ├── aPerformanceOption.vue
│ │ ├── aVirtualThingStatusbar.vue
│ │ ├── aButtonCancel.vue
│ │ ├── aFooterElement.vue
│ │ ├── aSearchbar.vue
│ │ ├── aViewerMermaid.vue
│ │ ├── aConfigStatusBar.vue
│ │ ├── aHeaderElement.vue
│ │ ├── aVulnerabilityTestElement.vue
│ │ ├── aConformanceTestElement.vue
│ │ ├── aCoverageTestElement.vue
│ │ ├── aListSimple.vue
│ │ ├── aIconButton.vue
│ │ ├── aTemplateSelectionMaGe.vue
│ │ ├── aEditorMonaco.vue
│ │ ├── aIcon.vue
│ │ ├── aSimpleInputField.vue
│ │ ├── aButtonBasic.vue
│ │ ├── aFormfield.vue
│ │ ├── aOptionElement.vue
│ │ ├── aOutputBar.vue
│ │ ├── aTabHeader.vue
│ │ └── aTab.vue
│ ├── 04_templates
│ │ ├── tFolder.vue
│ │ ├── tHomePage.vue
│ │ ├── tMashup.vue
│ │ └── tPerformance.vue
│ ├── 02_molecules
│ │ ├── mVulnerabilityTestContainer.vue
│ │ ├── mTabbar.vue
│ │ ├── mComplexOptionElement.vue
│ │ ├── mTableSimple.vue
│ │ ├── mTestCycleElement.vue
│ │ ├── mTestScenarioElement.vue
│ │ ├── mFormConfigOptions.js
│ │ ├── mTemplateSelectionAreaMaGe.vue
│ │ ├── mMashupElement.vue
│ │ ├── mUrlBar.vue
│ │ ├── mCoverageTestGroup.vue
│ │ ├── mGalleryMermaid.vue
│ │ └── mInteraction.vue
│ └── 03_organisms
│ │ ├── oProtocolSelection.vue
│ │ ├── oResults.vue
│ │ ├── oPerformanceOutput.vue
│ │ └── oModal.vue
├── backend
│ ├── MaGe
│ │ ├── corsAnywhere.ts
│ │ ├── codeGenerator.ts
│ │ ├── utils.ts
│ │ └── semantics.ts
│ ├── SD
│ │ ├── manualSD.ts
│ │ ├── validateSd.ts
│ │ └── util.ts
│ ├── MessageHandler.ts
│ ├── SizeCalculator.ts
│ ├── Td.ts
│ └── ConfidenceCalculator.ts
├── store
│ ├── store.ts
│ └── modules
│ │ ├── texts.ts
│ │ └── modal.ts
├── main.ts
├── router.ts
├── util
│ ├── defaults.ts
│ ├── helpers.ts
│ └── enums.ts
└── background.ts
├── babel.config.js
├── .editorconfig
├── .gitignore
├── vue.config.js
├── postinstall.js
├── tslint.json
├── CONTRIBUTING.md
├── tsconfig.json
├── .github
└── workflows
│ ├── release.yaml
│ ├── build.yaml
│ └── codeql.yml
├── performance-testing
├── cli_confidence.js
├── node-wot-scripts
│ └── node-wot-thing1.js
└── confidence_calculator.js
├── LICENSE
├── package.json
└── NLP
└── word2vec-api.py
/docs/VT.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/docs/VT.png
--------------------------------------------------------------------------------
/electron-builder.yml:
--------------------------------------------------------------------------------
1 | "linux": {
2 | "target": ["AppImage", "dir"]
3 | }
4 |
--------------------------------------------------------------------------------
/public/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/public/icon.png
--------------------------------------------------------------------------------
/demonstration.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/demonstration.gif
--------------------------------------------------------------------------------
/docs/STYLEGUIDE.md:
--------------------------------------------------------------------------------
1 | ### CSS Styles:
2 |
3 | - padding: 3px | 5px | 7px | 10px | 20px
--------------------------------------------------------------------------------
/src/assets/td.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/td.png
--------------------------------------------------------------------------------
/docs/MainEditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/docs/MainEditor.png
--------------------------------------------------------------------------------
/docs/Performance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/docs/Performance.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/assets/add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/add.png
--------------------------------------------------------------------------------
/src/assets/mage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/mage.png
--------------------------------------------------------------------------------
/src/assets/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/minus.png
--------------------------------------------------------------------------------
/src/assets/url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/url.png
--------------------------------------------------------------------------------
/src/assets/cancel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/cancel.png
--------------------------------------------------------------------------------
/src/assets/circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/circle.png
--------------------------------------------------------------------------------
/src/assets/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/delete.png
--------------------------------------------------------------------------------
/src/assets/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/folder.png
--------------------------------------------------------------------------------
/src/assets/mashup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/mashup.png
--------------------------------------------------------------------------------
/src/assets/options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/options.png
--------------------------------------------------------------------------------
/src/assets/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/search.png
--------------------------------------------------------------------------------
/src/assets/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/upload.png
--------------------------------------------------------------------------------
/src/assets/add_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/add_white.png
--------------------------------------------------------------------------------
/src/assets/arrow_down.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/arrow_down.png
--------------------------------------------------------------------------------
/src/assets/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/arrow_left.png
--------------------------------------------------------------------------------
/src/assets/computer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/computer.png
--------------------------------------------------------------------------------
/src/assets/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/settings.png
--------------------------------------------------------------------------------
/src/assets/settings_.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/settings_.png
--------------------------------------------------------------------------------
/src/assets/add_plugins.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/add_plugins.png
--------------------------------------------------------------------------------
/src/assets/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/arrow_right.png
--------------------------------------------------------------------------------
/src/assets/circle_grey.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/circle_grey.png
--------------------------------------------------------------------------------
/src/assets/delete_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/delete_white.png
--------------------------------------------------------------------------------
/src/assets/include-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/include-icon.png
--------------------------------------------------------------------------------
/src/assets/minus_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/minus_white.png
--------------------------------------------------------------------------------
/src/assets/performance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/performance.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/assets/action-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/action-template.png
--------------------------------------------------------------------------------
/src/assets/checked_circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/checked_circle.png
--------------------------------------------------------------------------------
/src/assets/event-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/event-template.png
--------------------------------------------------------------------------------
/src/assets/forbidden-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/forbidden-icon.png
--------------------------------------------------------------------------------
/src/assets/options_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/options_white.png
--------------------------------------------------------------------------------
/src/assets/read-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/read-template.png
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import Vue from 'vue';
3 | export default Vue;
4 | }
5 |
--------------------------------------------------------------------------------
/src/assets/arrow_double_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/arrow_double_left.png
--------------------------------------------------------------------------------
/src/assets/arrow_down_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/arrow_down_white.png
--------------------------------------------------------------------------------
/src/assets/arrow_right_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/arrow_right_white.png
--------------------------------------------------------------------------------
/src/assets/must-include-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/must-include-icon.png
--------------------------------------------------------------------------------
/src/assets/arrow_double_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/arrow_double_right.png
--------------------------------------------------------------------------------
/src/assets/font-awesome-4.7.0/fonts/FontAwesome.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/font-awesome-4.7.0/fonts/FontAwesome.otf
--------------------------------------------------------------------------------
/src/vue-types-global.d.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | declare module 'vue/types/vue' {
4 | interface Vue {
5 | $eventHub: any;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | charset = utf-8
7 | trim_trailing_whitespace = false
8 | insert_final_newline = false
--------------------------------------------------------------------------------
/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tum-esi/wade/HEAD/src/assets/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 | package-lock.json
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 |
15 | # Editor directories and files
16 | .idea
17 | .vscode
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
24 | # Word to Vector directory
25 |
26 |
27 | #Electron-builder output
28 | /dist_electron
29 | /build
30 |
31 | # A-MaGe related
32 | *.zip
33 | A-MaGe-Testing
--------------------------------------------------------------------------------
/src/components/01_atoms/aMashupTdInteractionElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
16 |
17 |
20 |
21 |
--------------------------------------------------------------------------------
/src/backend/MaGe/corsAnywhere.ts:
--------------------------------------------------------------------------------
1 | export function runServer() {
2 | var host = process.env.HOST || 'localhost';
3 | // Listen on a specific port via the PORT environment variable
4 | var port = process.env.PORT || 8082;
5 |
6 | var cors_proxy = require('cors-anywhere');
7 | cors_proxy.createServer({
8 | originWhitelist: [], // Allow all origins
9 | requireHeader: ['Origin', 'X-requested-with'],
10 | removeHeaders: ['cookie', 'cookie2']
11 | }).listen(port, host, function() {
12 | console.log('Running CORS Anywhere on ' + host + ':' + port);
13 | });
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | w-ade
9 |
10 |
11 |
12 | We're sorry but w-ade doesn't work properly without JavaScript enabled. Please enable it to continue.
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/store/store.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 | import SidebarStore from './modules/sidebar';
4 | import TdStore from './modules/td';
5 | import MashupStore from './modules/mashup';
6 | import ModalStore from './modules/modal';
7 | import TextStore from './modules/texts';
8 | import PersistedState from 'vuex-electron-store';
9 |
10 | Vue.use(Vuex);
11 |
12 | export default new Vuex.Store({
13 | modules: {
14 | SidebarStore,
15 | TdStore,
16 | MashupStore,
17 | ModalStore,
18 | TextStore,
19 | },
20 | state: {
21 |
22 | },
23 | mutations: {
24 |
25 | },
26 | actions: {
27 |
28 | },
29 | plugins: [
30 | PersistedState.create(),
31 | ],
32 | });
33 |
--------------------------------------------------------------------------------
/src/components/04_templates/tFolder.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Folders.
4 |
5 |
6 |
7 |
22 |
23 |
24 |
29 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require('@vue/cli-service')
2 | const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
3 |
4 | module.exports = defineConfig({
5 | transpileDependencies: true,
6 | pluginOptions: {
7 | electronBuilder: {
8 | nodeIntegration: true,
9 | builderOptions: {
10 | // options placed here will be merged with default configuration and passed to electron-builder
11 | extraResources: ["node_modules/core-js", "example-tds", "./node_modules/virtual-thing"],
12 | },
13 | },
14 | },
15 | configureWebpack: {
16 | devtool: 'source-map',
17 | plugins: [
18 | new MonacoWebpackPlugin({
19 | languages: ['typescript', 'javascript', 'json']
20 | })
21 | ]
22 | }
23 | })
24 |
--------------------------------------------------------------------------------
/postinstall.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A simple script that comments out parts of node-dtls-client.
3 | * Needed to make sure building wade does not fail.
4 | */
5 |
6 | fs = require("fs");
7 | const PATH_AEAD = "./node_modules/node-dtls-client/build/lib/AEADCrypto.js"
8 |
9 | // Commenting out lines in node-dtls-client
10 | let lines = [""];
11 | try {
12 | lines = fs.readFileSync(PATH_AEAD).toString().split("\n");
13 | console.log("Read file " + PATH_AEAD + " successfully");
14 | } catch (err) {
15 | console.error(err);
16 | return
17 | }
18 |
19 | for(let i=51; i<55; i++){
20 | if(!lines[i].startsWith("// ")) lines[i] = "// " + lines[i];
21 | }
22 |
23 | let text = lines.join("\n");
24 |
25 |
26 | fs.writeFile(PATH_AEAD, text, function (err) {
27 | if (err) return console.log(err)
28 | else console.log("Written to file " + PATH_AEAD + " successfully");
29 | });
30 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aStatusbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ getStatusMessage.message }}
4 |
5 |
6 |
7 |
17 |
18 |
34 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aInputSelector.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
24 |
25 |
44 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "warning",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "linterOptions": {
7 | "exclude": [
8 | "node_modules/**",
9 | "src/plugins/*/node_modules/**",
10 | "src/backend/SD/**"
11 | ]
12 | },
13 | "rules": {
14 | "quotemark": [true, "single"],
15 | "indent": [true, "spaces", 2],
16 | "interface-name": false,
17 | "ordered-imports": false,
18 | "object-literal-sort-keys": false,
19 | "no-consecutive-blank-lines": false,
20 | "trailing-comma": false,
21 | "curly": false,
22 | "align": [true, "parameters"],
23 | "arrow-parens": false,
24 | "no-bitwise": false,
25 | "no-shadowed-variable": true,
26 | "max-classes-per-file": false,
27 | "no-var-keyword": false,
28 | "variable-name": false,
29 | "class-name": false,
30 | "max-line-length": false,
31 | "radix": false,
32 | "no-string-throw": false
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mVulnerabilityTestContainer.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
34 |
35 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribution Guide
2 |
3 | ## Contributing to the Code
4 |
5 | 1. Fork the repository
6 | 2. Create a new branch with a meaningful name
7 | 3. Commit with a meaningful commit message that starts with a verb in simple present.
8 | Example: "update readme" and NOT "I have updated readme" or "Updating readme"
9 | 4. Push to your own fork. Do a pull request to the original repo
10 |
11 | ### Remarks:
12 |
13 | * Use camelCase for variable names * Write a comment block for every function you create that describes:
14 | * What the function does
15 | * What are its inputs
16 | * What are its outputs
17 |
18 | ## Contributing with Issues
19 |
20 | * Write an issue for every single thing you notice as wrong or unusual. This creates information for the upcoming users.
21 | * When writing an issue, first put a filter. E.g.:
22 | * "[documentation] Guide line X describes a wrong use case"
23 | * "[frontend] " Button in TD selection is not working"
24 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import router from './router';
4 | import store from './store/store';
5 | import * as corsAnywhere from '@/backend/MaGe/corsAnywhere';
6 |
7 | Vue.config.productionTip = false;
8 | Vue.prototype.$eventHub = new Vue(); // Global event bus
9 |
10 | corsAnywhere.runServer();
11 | // Check if element of path url is available, if not navigate home
12 | router.beforeEach((to, from, next) => {
13 | const pathAvailable = to.name === 'home' || to.name === 'mage' ? true : (to.name === 'thingDescription'
14 | || to.name === 'folder'
15 | || to.name === 'mashup'
16 | || to.name === 'config'
17 | || to.name === 'virtual')
18 | && to.params && to.params.id
19 | && store.getters['SidebarStore/doesIdAlreadyExist'](to.params.id);
20 |
21 | pathAvailable ? next() : next({name: 'home'});
22 | });
23 |
24 | new Vue({
25 | router,
26 | store,
27 | render: (h) => h(App),
28 | }).$mount('#app');
29 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aPerformanceOption.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ optionLabel }}
4 |
5 |
6 |
7 |
8 |
23 |
24 |
45 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aVirtualThingStatusbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ StatusMessage.msg }}
4 |
5 |
6 |
7 |
20 |
21 |
43 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "experimentalDecorators": true,
10 | "esModuleInterop": true,
11 | "allowSyntheticDefaultImports": true,
12 | "skipLibCheck": true,
13 | "forceConsistentCasingInFileNames": true,
14 | "useDefineForClassFields": true,
15 | "sourceMap": true,
16 | "noImplicitAny": false,
17 | "baseUrl": ".",
18 | "types": [
19 | "webpack-env"
20 | ],
21 | "paths": {
22 | "@/*": [
23 | "src/*"
24 | ]
25 | },
26 | "lib": [
27 | "esnext",
28 | "dom",
29 | "dom.iterable",
30 | "scripthost"
31 | ]
32 | },
33 | "include": [
34 | "src/**/*.ts",
35 | "src/**/*.tsx",
36 | "src/**/*.vue",
37 | "tests/**/*.ts",
38 | "tests/**/*.tsx",
39 | "vue-types-global.d.ts"
40 | ],
41 | "exclude": [
42 | "node_modules"
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | release:
10 | runs-on: ${{ matrix.os }}
11 |
12 | strategy:
13 | matrix:
14 | os: [ubuntu-latest, windows-latest, macos-latest]
15 |
16 | steps:
17 | - name: Check out Git repository
18 | uses: actions/checkout@v1
19 |
20 | - name: Install Node.js, NPM and Yarn
21 | uses: actions/setup-node@v1
22 | with:
23 | node-version: 16
24 |
25 | - name: Build/release Electron app
26 | uses: samuelmeuli/action-electron-builder@v1
27 | with:
28 | # Skips root build script (so no `yarn run build` is run)
29 | skip_build: true
30 | # Runs `vue-cli-service electron:build`
31 | use_vue_cli: true
32 |
33 | # GitHub token, automatically provided to the action
34 | # (No need to define this secret in the repo settings)
35 | github_token: ${{ secrets.github_token }}
36 | release: true
37 |
--------------------------------------------------------------------------------
/performance-testing/cli_confidence.js:
--------------------------------------------------------------------------------
1 | const fs = require("fs");
2 | const path = require("path");
3 | const ConfidenceCalculator = require("./confidence_calculator");
4 |
5 | const folderPath = process.argv.slice(2)[0];
6 | if (!folderPath) {
7 | console.info("Missing file path. Exit process.")
8 | process.exit(0);
9 | }
10 |
11 | // Create dir for results
12 | const resultPath = path.join(__dirname, 'results');
13 | if (!fs.existsSync(resultPath)) fs.mkdirSync(resultPath);
14 |
15 | // Compute results
16 | fs.readdirSync(folderPath).forEach((filePath) => {
17 | let file = fs.readFileSync(`${folderPath}/${filePath}`, "utf-8");
18 | if (!file) {
19 | console.info(`Unable to read file: ${folderPath}/${filePath}`);
20 | } else {
21 | const calc = new ConfidenceCalculator(file);
22 | const results = JSON.stringify(calc.calculateAll());
23 | const resultFileName = filePath.replace(/.json/i, '');
24 | fs.writeFileSync(path.join(resultPath, `${resultFileName}_results.json`), results);
25 | }
26 | });
27 |
28 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aButtonCancel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | # Skip if pushing to master because then other workflow will run
8 | if: ${{ (github.event_name == 'push' && github.ref != 'refs/heads/master') || github.event_name == 'pull_request' }}
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - name: Check out Git repository
13 | uses: actions/checkout@v1
14 |
15 | - name: Install Node.js, NPM and Yarn
16 | uses: actions/setup-node@v1
17 | with:
18 | node-version: 16
19 |
20 | - name: Build Electron app
21 | uses: samuelmeuli/action-electron-builder@v1
22 | with:
23 | # Skips root build script (so no `yarn run build` is run)
24 | skip_build: true
25 | # Runs `vue-cli-service electron:build`
26 | use_vue_cli: true
27 |
28 | # GitHub token, automatically provided to the action
29 | # (No need to define this secret in the repo settings)
30 | github_token: ${{ secrets.github_token }}
31 | release: false
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Associate Professorship of Embedded Systems and Internet of Things
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/backend/SD/manualSD.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import checkSD from './validateSd';
3 |
4 | // TODO add SD context (in @context) upon its publication
5 |
6 | // edit SD content directly below to benefit from intelli-sense
7 | const newSD: SDSQ.sdTemplate = {
8 | '@context': [
9 | 'https://www.w3.org/2019/wot/td/v1',
10 | {
11 | '@language': 'en'
12 | }
13 | ],
14 | 'id': 'de:tum:ei:esi:MashDE:',
15 | '@type': 'Thing',
16 | 'title': 'MashupTitle',
17 | 'description': 'a mashup generated with MashDE',
18 | 'securityDefinitions': {
19 | nosec_sc: {
20 | scheme: 'nosec'
21 | }
22 | },
23 | 'security': 'nosec_sc',
24 | 'things': {},
25 | 'variables': {},
26 | 'properties': {},
27 | 'actions': {},
28 | 'functions': {},
29 | 'events': {},
30 | 'path': [{wait: 300}]
31 | };
32 |
33 | // store to file
34 | fs.writeFileSync('./created-output/manualSD.json', JSON.stringify(newSD, undefined, 4));
35 |
36 | // validate if SD is correct
37 | checkSD(JSON.stringify(newSD)).then( () => {
38 | console.log({'SD-is-valid': ':)'});
39 | }, (err) => {
40 | console.log({'SD-invalid!': err});
41 | });
42 |
--------------------------------------------------------------------------------
/src/router.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Router from 'vue-router';
3 |
4 | Vue.use(Router);
5 |
6 | export default new Router({
7 | routes: [
8 | {
9 | path: '/',
10 | name: 'home',
11 | component: () => import ('@/components/04_templates/tHomePage.vue')
12 | },
13 | {
14 | path: '/td/:id',
15 | name: 'thingDescription',
16 | component: () => import('@/components/04_templates/tThingDescription.vue')
17 | },
18 | {
19 | path: '/folder/:id',
20 | name: 'folder',
21 | component: () => import('@/components/04_templates/tFolder.vue')
22 | },
23 | {
24 | path: '/mashup/:id',
25 | name: 'mashup',
26 | component: () => import('@/components/04_templates/tMashup.vue')
27 | },
28 | {
29 | path: '/:type/:id/:tab',
30 | name: 'config',
31 | component: () => import('@/components/03_organisms/oConfig.vue')
32 | },
33 | {
34 | path: '/:type/:id/:tab',
35 | name: 'virtual',
36 | component: () => {
37 | import('@/components/03_organisms/oVirtual.vue');
38 | import('@/components/03_organisms/oVirtualThing.vue');
39 | }
40 | }
41 | ],
42 | });
43 |
--------------------------------------------------------------------------------
/src/util/defaults.ts:
--------------------------------------------------------------------------------
1 | /* the same as in virtual thing EDIT: changed log level */
2 | export const virtualConfigDefault = {
3 | servient: {
4 | staticAddress: '127.0.0.1',
5 | http: {
6 | port: 80
7 | }
8 | },
9 | log: {
10 | level: 2
11 | },
12 | things: {
13 | 'de:tum:ei:esi:fp:coffee': {
14 | eventIntervals: {
15 | maintenance: 15,
16 | error: 15
17 | }
18 | }
19 | }
20 | };
21 |
22 | export const testbenchConfigDefault = {
23 | SchemaLocation: "Resources/InteractionSchemas/",
24 | TestReportsLocation: "Reports/",
25 | TestDataLocation: "Resources/fake-data.json",
26 | TimeBetweenRequests: 500,
27 | ActionTimeout: 4000,
28 | Scenarios: 2,
29 | Repetitions: 1,
30 | EventAndObservePOptions: {
31 | Asynchronous: {
32 | MaxAmountRecvData: 2,
33 | MsListen: 400,
34 | MsSubscribeTimeout: 400
35 | },
36 | Synchronous: {
37 | isEnabled: true,
38 | MaxAmountRecvData: 5,
39 | MsListen: 5000,
40 | MsSubscribeTimeout: 1000
41 | }
42 | },
43 | credentials: {}
44 | };
--------------------------------------------------------------------------------
/src/components/01_atoms/aFooterElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
38 |
39 |
52 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aSearchbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
12 |
13 |
14 |
15 |
32 |
33 |
62 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mTabbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
42 |
43 |
44 |
56 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aViewerMermaid.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{txt}}
4 |
5 |
6 |
7 |
48 |
49 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aConfigStatusBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ statusMessage }}
4 |
5 |
6 |
7 |
39 |
40 |
61 |
--------------------------------------------------------------------------------
/src/backend/SD/validateSd.ts:
--------------------------------------------------------------------------------
1 | import Ajv from 'ajv';
2 | import fs from 'fs';
3 | import https from 'https';
4 |
5 | const ajv = new Ajv({ loadSchema });
6 |
7 | // load SD Schema
8 | const schemaFilePath = './definitions/sdSchema.json';
9 | const schema = JSON.parse(fs.readFileSync(schemaFilePath, 'utf8'));
10 |
11 | // TODO: throw new Error for invalid SD
12 | export default function checkSD(sdFileContent: string, checkRequired = true) {
13 | return new Promise( (res, rej) => {
14 | if (checkRequired === false) {
15 | res();
16 | } else {
17 | const SD = JSON.parse(sdFileContent);
18 | let valid;
19 | ajv.compileAsync(schema).then( validation => {
20 | valid = validation(SD);
21 | if (valid) {res(); } else {rej('!!!???!!! SD Invalid: ' + ajv.errorsText(validation.errors)); }
22 | });
23 | }
24 | });
25 | }
26 |
27 |
28 | function loadSchema(uri) {
29 | return new Promise( (resolve, reject) => {
30 | https.get(uri, res => {
31 | if (res.statusCode === undefined) {throw new Error('https status Code undefined'); }
32 | if (res.statusCode >= 400) {
33 | reject('Loading error: ' + res.statusCode);
34 | }
35 | res.setEncoding('utf8');
36 | let body = '';
37 | res.on('data', data => {
38 | body += data;
39 | });
40 | res.on('end', () => {
41 | resolve(JSON.parse(body));
42 | });
43 | });
44 | });
45 | }
46 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aHeaderElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
42 |
43 |
44 |
71 |
--------------------------------------------------------------------------------
/src/backend/MessageHandler.ts:
--------------------------------------------------------------------------------
1 | import { TdStateEnum, InteractionStateEnum } from '@/util/enums';
2 |
3 | export default class MessageHandler {
4 |
5 | private tdState: TdStateEnum | null;
6 | private errorMessage: string | null;
7 | private interactionState: InteractionStateEnum | null;
8 |
9 | constructor(
10 | tdState: TdStateEnum | null,
11 | errorMessage: string | null,
12 | interactionState: InteractionStateEnum | null
13 | ) {
14 | this.tdState = tdState;
15 | this.errorMessage = errorMessage;
16 | this.interactionState = interactionState;
17 | }
18 |
19 | public getStatusMessage(): { message: string, error: boolean } {
20 | let hasError = false;
21 | const date = new Date();
22 | const currentTime = `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
23 | let message = `${currentTime}> `;
24 |
25 | if (this.tdState) {
26 | message += `${this.tdState} `;
27 | if (this.tdState === TdStateEnum.NO_TD
28 | || this.tdState === TdStateEnum.INVALID_TD_JSON
29 | || this.tdState === TdStateEnum.INVALID_TD_FETCHED
30 | || this.tdState === TdStateEnum.INVALID_TD_EMPTY
31 | || this.tdState === TdStateEnum.INVALID_CONSUMED_TD
32 | || this.tdState === TdStateEnum.INVALID_TD) hasError = true;
33 | }
34 | if (this.errorMessage) {
35 | message += `Error: ${this.errorMessage}. `;
36 | hasError = true;
37 | }
38 | if (this.interactionState) message += `${this.interactionState} `;
39 |
40 | return { message, error: hasError };
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/components/04_templates/tHomePage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Add a new Thing Description, mashup or folder by clicking on the button.
5 |
6 |
13 |
14 |
15 |
16 |
40 |
41 |
60 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aVulnerabilityTestElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ interactionName }}
6 |
9 |
12 |
13 |
14 |
15 |
16 |
44 |
45 |
--------------------------------------------------------------------------------
/src/backend/SizeCalculator.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Resource: https://stackoverflow.com/questions/23318037/size-of-json-object-in-kbs-mbs
3 | */
4 | export default class SizeCalculator {
5 |
6 | public getSize(el: any) {
7 | return this.memorySizeOf(el);
8 | }
9 |
10 | private memorySizeOf(object: any): string {
11 | let bytes = 0;
12 |
13 | function sizeOf(obj: any): number {
14 | if (obj !== null && obj !== undefined) {
15 | switch (typeof obj) {
16 | case 'number':
17 | bytes += 8;
18 | break;
19 | case 'string':
20 | bytes += obj.length * 2;
21 | break;
22 | case 'boolean':
23 | bytes += 4;
24 | break;
25 | case 'object':
26 | const objClass = Object.prototype.toString.call(obj).slice(8, -1);
27 | if (objClass === 'Object' || objClass === 'Array') {
28 | for (const key in obj) {
29 | if (!obj.hasOwnProperty(key)) continue;
30 | sizeOf(obj[key]);
31 | }
32 | } else bytes += obj.toString().length * 2;
33 | break;
34 | }
35 | }
36 | return bytes;
37 | }
38 |
39 | function formatByteSize(byt: number): string {
40 | if (byt < 1024) return byt + ' bytes';
41 | else if (byt < 1048576) return(byt / 1024).toFixed(3) + ' KiB';
42 | else if (byt < 1073741824) return(byt / 1048576).toFixed(3) + ' MiB';
43 | else return(byt / 1073741824).toFixed(3) + ' GiB';
44 | }
45 |
46 | return formatByteSize(sizeOf(object));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/util/helpers.ts:
--------------------------------------------------------------------------------
1 | import ComponentPublicInstance from 'vue';
2 |
3 | export function getFormattedJsonString(value: string): string {
4 | return JSON.stringify(JSON.parse(value), null, 2);
5 | }
6 |
7 | export function loggingError(message: any, ...optionalParams: any[]) {
8 | const isDevMode = process.env.NODE_ENV !== 'production';
9 | if (isDevMode) {
10 | // tslint:disable-next-line: no-console
11 | console.error(message, optionalParams);
12 | } else {
13 | return null; // Do nothing, because in production environment
14 | // TODO think about logging
15 | }
16 | }
17 |
18 | export function isDevelopment(): boolean {
19 | const isDevMode = process.env.NODE_ENV !== 'production';
20 | return isDevMode;
21 | }
22 |
23 | export const ConfLevel = new Map([
24 | ['80%', 1.282],
25 | ['85%', 1.440],
26 | ['90%', 1.645],
27 | ['95%', 1.960],
28 | ['99%', 2.576],
29 | ['99.5%', 2.807],
30 | ['99.9%', 3.291]
31 | ]);
32 |
33 | export const confidenceLevel = {
34 | EIGHTY_PERCENT: ['80%', 1.282],
35 | EIGHTY_FIVE_PERCENT: ['85%', 1.440],
36 | NINETY_PERCENT: ['90%', 1.645],
37 | NINETY_FIVE_PERCENT: ['95%', 1.960],
38 | NINETY_NINE_PERCENT: ['99%', 2.576],
39 | NINETY_NINE_POINT_FIVE_PERCENT: ['99.5%', 2.807],
40 | NINETY_NINE_POINT_NINE_PERCENT: ['99.9%', 3.291]
41 | };
42 |
43 | export function getCurrentDate() {
44 | const date = new Date();
45 | return `${date.getDate()}-${date.getMonth() + 1}-${date.getFullYear()}-${date.getHours()}h${date.getMinutes()}min${date.getSeconds()}sec`;
46 | }
47 |
48 | export function focusElement(refName: string, component: ComponentPublicInstance) {
49 | component.$nextTick(() => {
50 | const element = component.$refs[refName] as HTMLElement;
51 | element.focus();
52 | })
53 | }
54 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mComplexOptionElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
42 |
43 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aConformanceTestElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{interactionName}}
7 |
10 |
13 |
14 |
15 |
16 |
17 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aCoverageTestElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ interactionName }}
7 |
10 |
13 |
14 |
15 |
16 |
17 |
54 |
55 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aListSimple.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
37 |
38 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aIconButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{ iconBtnLabel }}
6 |
7 |
8 |
9 |
65 |
66 |
90 |
91 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mTableSimple.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
38 |
39 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mTestCycleElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Test Cycle {{ $vnode.key }}
7 |
8 |
9 |
10 |
13 |
19 |
20 |
21 |
22 |
23 |
51 |
52 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mTestScenarioElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Test Scenario {{ $vnode.key }}
7 |
8 |
9 |
10 |
22 |
23 |
24 |
25 |
52 |
53 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aTemplateSelectionMaGe.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{this.title}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | Use this template
13 |
14 |
15 |
16 |
17 |
53 |
54 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aEditorMonaco.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
65 |
66 |
--------------------------------------------------------------------------------
/src/components/03_organisms/oProtocolSelection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Select Protocol
5 |
6 |
7 |
8 |
9 |
17 | {{ element }}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
55 |
56 |
57 |
72 |
--------------------------------------------------------------------------------
/docs/ARCHITECTURE.md:
--------------------------------------------------------------------------------
1 | # W-ADE Software Architecture
2 |
3 | Here you find the detailed software architecture explained to better understand W-ADE's structure.
4 | First, the structure of the application logic is explained, followed by the frontend architecture.
5 |
6 |
7 | ## Application Logic
8 |
9 | W-ADE is an Electron & Vue.js based desktop application.
10 | It is mainly written in TypeScript, a typed superset of JavaScript.
11 |
12 | The application structure is as following:
13 |
14 | ```
15 | -assets
16 | -backend
17 | -components
18 | --01_atoms
19 | --02_molecules
20 | --03_organisms
21 | --04_templates
22 | -store
23 | --modules
24 | -util
25 | -App.vue
26 | -background.ts
27 | -main.ts
28 | -router.ts
29 | -shims-tsx.d.ts
30 | ```
31 |
32 | ## Fronted Architecture
33 |
34 | ---
35 | The architectural style of W-ADE's frontend is inspired by the _**Atom Design**_ design system by Brad Frost: http://atomicdesign.bradfrost.com/chapter-2/.
36 |
37 | However, instead of being divided into 5 different types, W-ADE's GUI elements consist off only 4 different modules:
38 | 1) Atoms
39 | 2) Molecules
40 | 3) Organisms
41 | 4) Templates
42 |
43 | ### Atoms
44 |
45 | *Atoms* comprise the most foundational building blocks of the user interface.
46 | They include basic GUI elements like buttons (with different styles), form fields, inputs, labels, etc.
47 | Every element that cannot be further broken down should be added to the *Atoms* folder.
48 |
49 | Most *Atom* components are dynamic. That means they can be used for building other components, as they can be dynamically be filled with different content.
50 | If you want to build plugins or work on the further development of W-ADE check out this folder to see if elements you need for your interface already exist in here.
51 | Create a new atom if needed.
52 |
53 | ### Molecules
54 |
55 | In interfaces, molecules are relatively simple groups of UI elements functioning together as a unit. For example, a form label, search input, and button can join together to create a search form molecule.
56 |
57 | ### Organisms
58 |
59 | ### Templates
60 |
61 | Templates are non-dynamic components, which shouldn't be reused.
62 | They are components, filled with specific content, displaying full pages.
63 |
64 |
65 | ### Remarks
66 |
67 | Some of the used styles are stored in the App.vue file to make them available "*globally*".
68 |
69 |
--------------------------------------------------------------------------------
/src/backend/MaGe/codeGenerator.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | export default function generateCode(mashup, tds: string[]): string {
4 | // add tds to script
5 | let script =
6 | `"use strict";
7 | /* global WoT */
8 | let tds=[`;
9 | tds.forEach(td => {
10 | const modifiedTd = td.replace(/\s|\n/g, '');
11 | script += `${modifiedTd},`; });
12 | script = script.slice(0, -1); // remove "," after last td
13 | script += `];\n`;
14 |
15 | // consume all tds and store consumed-things in id:obj map
16 | script += `
17 | let consumePromises = [];
18 | tds.forEach((td) => {
19 | const TdPromise = WoT.consume(td);
20 | consumePromises.push(TdPromise);
21 | });
22 |
23 | Promise.all(consumePromises).then((myTDs) => {
24 | let consumedThings = {};
25 |
26 | myTDs.forEach( (data) => {
27 | consumedThings[data.id] = data;
28 | });
29 |
30 | let readPromises = [];\n
31 | `;
32 | mashup.forEach(interaction => {
33 | if (interaction.interactionType === 'event-subscribe') {
34 | script +=
35 | ` readPromises.push(new Promise((resolve) => {
36 | consumedThings["${interaction.thingId}"].subscribeEvent("${interaction.name}",(data) => {
37 | resolve(data);
38 | resolve = () => {};
39 | });
40 | }));\n`;
41 | } else if (interaction.interactionType === 'property-read') {
42 | script += `\treadPromises.push(consumedThings["${interaction.thingId}"].readProperty("${interaction.name}"));\n`;
43 | } else if (interaction.interactionType === 'action-read') {
44 | script +=
45 | `\treadPromises.push(consumedThings["${interaction.thingId}"].invokeAction("${interaction.name}",
46 | // PLEASE PROVIDE AN INPUT HERE IF NECESSARY
47 | ));\n`;
48 | }
49 | });
50 |
51 | let outputs = ``;
52 | mashup.forEach(interaction => {
53 | if (interaction.interactionType === 'property-write') {
54 | outputs += `\tconsumedThings["${interaction.thingId}"].writeProperty("${interaction.name}" /*, values*/ ); // SELECT DATA TO WRITE\n`;
55 | } else if (interaction.interactionType === 'action-invoke') {
56 | outputs += `\tconsumedThings["${interaction.thingId}"].invokeAction("${interaction.name}" /*, values */ ); // SELECT DATA TO WRITE\n`;
57 | }
58 | });
59 |
60 | script +=
61 | ` Promise.all(readPromises).then((values) => {
62 | // PLEASE DO ANY DATA TRANSFORMATION NECESSARY HERE
63 | ${outputs}
64 | });
65 | });`;
66 |
67 | return script;
68 | }
69 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mFormConfigOptions.js:
--------------------------------------------------------------------------------
1 | // formDataOptions: {
2 | // http: [{
3 | // name: 'allowSelfAligned',
4 | // type: 'boolean',
5 | // value: true
6 | // }],
7 | // coap: [],
8 | // mqtt: [
9 | // {
10 | // name: 'broker',
11 | // type: 'string',
12 | // value: 'mqtt://broker.org'
13 | // },
14 | // {
15 | // name: 'username',
16 | // type: 'string',
17 | // value: 'username'
18 | // },
19 | // {
20 | // name: 'password',
21 | // type: 'string',
22 | // value: 'password'
23 | // },
24 | // {
25 | // name: 'clientId',
26 | // type: 'string',
27 | // value: 'uniqueId'
28 | // },
29 | // ],
30 | // credentials: [
31 | // {
32 | // name
33 | // }
34 | // ]
35 | // }
36 | // formDataOptions: {
37 | // http: [{
38 | // name: 'allowSelfAligned',
39 | // type: 'boolean',
40 | // value: true
41 | // }],
42 | // coap: [],
43 | // mqtt: [
44 | // {
45 | // name: 'broker',
46 | // type: 'string',
47 | // value: 'mqtt://broker.org'
48 | // },
49 | // {
50 | // name: 'username',
51 | // type: 'string',
52 | // value: 'username'
53 | // },
54 | // {
55 | // name: 'password',
56 | // type: 'string',
57 | // value: 'password'
58 | // },
59 | // {
60 | // name: 'clientId',
61 | // type: 'string',
62 | // value: 'uniqueId'
63 | // },
64 | // ],
65 | // credentials: [
66 | // {
67 | // name
68 | // }
69 | // ]
70 | // }
--------------------------------------------------------------------------------
/src/store/modules/texts.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | namespaced: true,
3 | state: {
4 | performance: {
5 | performanceOptions: {
6 | title: 'Options',
7 | titleOptions: 'Type:',
8 | selectedInteraction: 'Selected Interaction:',
9 | selectedInteractions: 'Selected Interactions:',
10 | delayTitle: 'Delay:',
11 | delayDurationPlaceholder: 'Delay in ms',
12 | delayDurationTitle: 'Delay Duration:',
13 | durationTitle: 'Duration:',
14 | durationPlaceholder: 'Duration in ms',
15 | iterationsTitle: 'Iterations:',
16 | iterationsPlaceholder: 'Number',
17 | errorNoTypeSelected: 'Please select a measurement option.',
18 | btnStart: 'Start measurements',
19 | measurementNumTitle: 'Repetitions',
20 | confidenceTitle: 'Confidence Level',
21 | calculateStatic: 'Static Timing'
22 | },
23 | performanceOutput: {
24 | title: 'Output',
25 | btnSave: 'Save Output',
26 | btnAnnotateTD: 'Annotate TD',
27 | outputSettingType: 'Type',
28 | outputSettingsInputSize: 'Input Size',
29 | outputSettingsInputValue: 'Input Value',
30 | outputSettingsOutputSize: 'Output Size',
31 | outputSettingsOutputValue: 'Output Value',
32 | outputSettingsOutputAmount: 'Output Amount',
33 | outputSettingConfLevel: 'Confidence Level',
34 | outputSettingConfFactor: 'Confidence Factor',
35 | outputSettingOverallIterations: 'Number of executed iterations',
36 | outputSettingIterations: 'Iterations',
37 | outputSettingDuration: 'Duration',
38 | outputSettingDelay: 'Delay Type',
39 | outputSettingDelayDuration: 'Delay Duration',
40 | outputSettingNumMeasurements: 'Number Measurements',
41 | outputSettingClient: 'Number Clients',
42 | outputResultoverallIteration: 'Overall Iterations',
43 | outputResultoverallDuration: 'Overall Duration',
44 | outputResultRealistic: 'Realistic',
45 | outputResultPossible: 'Possible',
46 | outputResultrealisticWithoutFirst: 'Realistic without first',
47 | outputResultpossibleWithoutFirst: 'Possible without first',
48 | outputResultSize: 'Size',
49 | outputResultFirstMeasured: 'First Measured'
50 | }
51 | }
52 |
53 | }
54 | };
55 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aIcon.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
12 |
13 |
14 |
15 |
16 |
74 |
75 |
102 |
103 |
--------------------------------------------------------------------------------
/src/backend/MaGe/utils.ts:
--------------------------------------------------------------------------------
1 | // ------------------ MATH & STATISTICS ------------------
2 |
3 | /** Coding magic that I have no idea what it does :)
4 | * To me, this is little piece of code is coding magic as I really have no idea how this calculates the cartesian product.
5 | * The editor cannot even infer what types are used
6 | * But, given that it works, I would say that maybe it is science so advanced that it is considered as magic :P
7 | * @param a an array
8 | * @param b an array
9 | * @returns an array of arrays
10 | */
11 | const f = (a, b) => [].concat(...a.map(d => b.map(e => [].concat(d, e))));
12 | /** A function that calculates the cartesian of arrays using the above-mentioned coding magic :D
13 | *
14 | * @param a an array
15 | * @param b an array
16 | * @param c an array of array
17 | * @returns the cartesian product
18 | */
19 | const cartesian = (a?, b?, ...c) => (b ? cartesian(f(a, b), ...c) : a);
20 |
21 | /** Calculates mashups using the cartesian product and removes duplicate mashups
22 | *
23 | * @param {MAGE.InteractionInterface} params a 3-dimensional array of interactions
24 | * @returns {MAGE.InteractionInterface[][]} a 2-dimensional array with cartesian product
25 | */
26 | const noDuplicatesCartesian = (...params: MAGE.InteractionInterface[][][]): MAGE.InteractionInterface[][] => {
27 | const product = cartesian(...params);
28 |
29 | const hashes: string[] = [];
30 | const newArray: MAGE.InteractionInterface[][] = [];
31 |
32 | product.forEach((element: any[]) => {
33 | // make sure that combination does not contain same output twice
34 | const ids: string[] = [];
35 | const newElement: MAGE.InteractionInterface[] = [];
36 | element.forEach(o => {
37 | if (!ids.includes(o.id)) {
38 | ids.push(o.id);
39 | newElement.push(o);
40 | }
41 | });
42 |
43 | // make sure that combination does not get added twice in different orders
44 | let elementHash = '';
45 | newElement.sort((a, b) => (a.id > b.id) ? 1 : ((b.id > a.id) ? -1 : 0));
46 | newElement.forEach(e => elementHash += e.id);
47 |
48 | if (!hashes.includes(elementHash)) {
49 | newArray.push(newElement);
50 | hashes.push(elementHash);
51 | }
52 | });
53 |
54 | return newArray;
55 | };
56 |
57 | /** Calculates the factorial of `num`
58 | *
59 | * @param {number} num the factorial number
60 | * @returns {number} the factorial of `num`
61 | */
62 | export let factorial = (num: number): number => {
63 | let result = 1;
64 | for (let i = 2; i <= num; i++) result *= i;
65 | return result;
66 | };
67 |
68 | export let modifiedCartesianProduct = noDuplicatesCartesian;
69 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mTemplateSelectionAreaMaGe.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 | The interaction sequence starts when the mashup agent receives an event.
12 | The data from the event is then sent to the matching outputs as input for an action or as a property write.
13 |
14 |
15 |
16 |
23 |
24 | The interaction sequence starts with the mashup agent reading a property from an input device.
25 | The data is then sent to the matching outputs as input for an action or as a property write.
26 |
27 |
28 |
29 |
36 |
37 | The interaction sequence starts with the mashup agent invoking an action that has an output from an input device.
38 | The received data is then sent to the matching outputs as input for an action or as a property write.
39 |
40 |
41 |
42 |
43 |
44 |
68 |
69 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mMashupElement.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
{{ this.element.id }}
8 |
15 |
22 |
23 |
24 |
25 |
63 |
64 |
97 |
--------------------------------------------------------------------------------
/src/backend/SD/util.ts:
--------------------------------------------------------------------------------
1 | export enum interactionType {
2 | subscribeEvent = 'subscribeEvent',
3 | invokeAction = 'invokeAction',
4 | readProperty = 'readProperty',
5 | writeProperty = 'writeProperty',
6 | observeProperty = 'observeProperty'
7 | }
8 |
9 | export enum interactionTypeOfReceive {
10 | subscribeEvent = 'subscribeEvent',
11 | invokeAction = 'invokeAction',
12 | readProperty = 'readProperty',
13 | observeProperty = 'observeProperty'
14 | }
15 |
16 | export enum interactionTypeOfSend {
17 | invokeAction = 'invokeAction',
18 | writeProperty = 'writeProperty',
19 | }
20 |
21 | export enum structureType {
22 | interact = 'interact',
23 | loop = 'loop',
24 | wait = 'wait',
25 | case = 'case',
26 | get = 'get',
27 | set = 'set',
28 | ref = 'ref'
29 | }
30 |
31 | export enum loopType {
32 | timed = 'timed',
33 | logic = 'logical'
34 | }
35 |
36 | export enum interactionDir {
37 | receive = 'receive',
38 | send = 'send'
39 | }
40 |
41 | export const singToPlural = {
42 | function: 'functions',
43 | action: 'actions',
44 | variable: 'variables',
45 | property: 'properties'
46 | };
47 |
48 | export const typeToOp = {
49 | subscribe: 'subscribeEvent',
50 | invoke: 'invokeAction',
51 | read: 'readProperty',
52 | write: 'writeProperty',
53 | observe: 'observeProperty'
54 | };
55 |
56 | export const typeRecToOp = {
57 | subscribe: 'subscribeEvent',
58 | invoke: 'invokeAction',
59 | read: 'readProperty',
60 | observe: 'observeProperty'
61 | };
62 |
63 |
64 |
65 | export const typeSendToOp = {
66 | invoke: 'invokeAction',
67 | write: 'writeProperty'
68 | };
69 |
70 | export const typeToTd = {
71 | subscribeEvent: 'events',
72 | invokeAction: 'actions',
73 | readProperty: 'properties',
74 | writeProperty: 'properties',
75 | observeProperty: 'properties'
76 | };
77 |
78 | export const structToUml = {
79 | interact: 'group strict',
80 | loop: 'loop',
81 | wait: '...',
82 | case: 'alt',
83 | get: 'note over',
84 | set: 'note over',
85 | ref: 'ref over'
86 |
87 | };
88 |
89 | export const recTypeToRet = {
90 | observe: 'confirmation',
91 | subscribe: 'confirmation',
92 | read: 'response',
93 | invoke: 'output'
94 | };
95 |
96 | // remove all sd specific properties
97 | export function sdToTd( sd: SDSQ.sdTemplate ) {
98 | const td = JSON.parse(JSON.stringify(sd));
99 |
100 | delete td.things;
101 | delete td.functions;
102 | delete td.variables;
103 | delete td.path;
104 |
105 | if (td.actions) {
106 | Object.keys(td.actions).forEach( name => {
107 | delete td.actions[name].path;
108 | });
109 | }
110 |
111 | if (td.properties) {
112 | Object.keys(td.properties).forEach( name => {
113 | delete td.properties[name].path;
114 | });
115 | }
116 |
117 | return td;
118 | }
119 |
--------------------------------------------------------------------------------
/performance-testing/node-wot-scripts/node-wot-thing1.js:
--------------------------------------------------------------------------------
1 | let writeString = "success";
2 | let writeBoolean = true;
3 | let writeInteger = 0;
4 |
5 | WoT.produce({
6 | title: "virtual-test-thing-1",
7 | description: "node-wot servient for virtual test #1",
8 | "@context": ["https://www.w3.org/2019/wot/td/v1", {"iot": "http://example.org/iot"}],
9 | properties: {
10 | readString: {
11 | type: "string",
12 | readOnly: true
13 | },
14 | readBoolean: {
15 | type: "boolean",
16 | readOnly: true
17 | },
18 | readInteger: {
19 | type: "integer",
20 | readOnly: true
21 | },
22 | writeString: {
23 | type: "string",
24 | writeOnly: true
25 | },
26 | writeBoolean: {
27 | type: "boolean",
28 | writeOnly: true
29 | },
30 | writeInteger: {
31 | type: "integer",
32 | writeOnly: true
33 | }
34 | }
35 | })
36 | .then((thing) => {
37 | console.info(`Produced ${thing.title}.`);
38 |
39 | thing.setPropertyWriteHandler(
40 | "writeString",
41 | (value) => {
42 | return new Promise((resolve, reject) => {
43 | writeString = value;
44 | resolve(value)
45 | })
46 | }
47 | );
48 |
49 | thing.setPropertyWriteHandler(
50 | "writeBoolean",
51 | (value) => {
52 | return new Promise((resolve, reject) => {
53 | writeBoolean = value;
54 | resolve(value)
55 | })
56 | }
57 | );
58 |
59 | thing.setPropertyWriteHandler(
60 | "writeInteger",
61 | (value) => {
62 | return new Promise((resolve, reject) => {
63 | writeInteger = value;
64 | resolve(value)
65 | })
66 | }
67 | );
68 |
69 | thing.setPropertyReadHandler(
70 | "readString",
71 | () => {
72 | return new Promise((resolve, reject) => {
73 | resolve(writeString);
74 | })
75 | }
76 | );
77 |
78 | thing.setPropertyReadHandler(
79 | "readBoolean",
80 | () => {
81 | return new Promise((resolve, reject) => {
82 | resolve(writeBoolean);
83 | })
84 | }
85 | );
86 |
87 | thing.setPropertyReadHandler(
88 | "readInteger",
89 | () => {
90 | return new Promise((resolve, reject) => {
91 | resolve(writeInteger);
92 | })
93 | }
94 | );
95 |
96 | thing.expose()
97 | .then(() => {
98 | console.info(`${thing.title} is ready`);
99 | })
100 | .catch((err) => {
101 | console.info(`Could not expose ${thing.title} due to error: ${err}`);
102 | })
103 | })
104 | .catch((error) => {
105 | console.log(error);
106 | });
--------------------------------------------------------------------------------
/src/backend/MaGe/semantics.ts:
--------------------------------------------------------------------------------
1 | import * as N3 from 'n3';
2 | const { DataFactory } = N3;
3 | const { namedNode, literal, defaultGraph, quad } = DataFactory;
4 | import { RdfXmlParser } from 'rdfxml-streaming-parser';
5 | import { JsonLdParser } from 'jsonld-streaming-parser';
6 |
7 | export const parser = new N3.Parser();
8 | export let vocabStore = new N3.Store();
9 |
10 |
11 | /** A function that fetches a semantic vocabulary and stores it in an N3 graph
12 | *
13 | * @param {string} url the url of the vocabulary
14 | * @returns {Promise}
15 | */
16 | export async function fetchAndStoreVocab(url: string): Promise {
17 | let response: Response | null = null;
18 | let contentTypeString: string | null = null;
19 | const requestInit: RequestInit = {
20 | method: 'GET',
21 | headers: {
22 | Accept: 'text/turtle, application/rdf+xml;0.9, application/ld+json;0.9',
23 | Origin: 'localhost'
24 | }
25 | };
26 | try {
27 | response = await fetch(url, requestInit);
28 | contentTypeString = response.headers.get('content-type');
29 | } catch (error) {
30 | console.error(error);
31 | return false;
32 | }
33 |
34 | if (response && response.ok) {
35 | const rdfXmlParser = new RdfXmlParser({
36 | dataFactory: DataFactory,
37 | });
38 | const jsonLdParser = new JsonLdParser({
39 | dataFactory: DataFactory,
40 | });
41 | const text = await response.text();
42 | if (!contentTypeString) {
43 | if (text.search('xml') !== -1) {
44 | rdfXmlParser
45 | .on('data', (quad) => {
46 | quad.graph = namedNode(url);
47 | vocabStore.addQuad(quad);
48 | });
49 | rdfXmlParser.write(text);
50 | rdfXmlParser.end();
51 | }
52 | } else if (contentTypeString && (contentTypeString.search('json') !== -1)) {
53 | jsonLdParser
54 | .on('data', (quad) => {
55 | quad.graph = namedNode(url);
56 | vocabStore.addQuad(quad);
57 | });
58 | rdfXmlParser.write(text);
59 | rdfXmlParser.end();
60 | } else if (contentTypeString && (contentTypeString.search('xml') !== -1)) {
61 | rdfXmlParser
62 | .on('data', (quad) => {
63 | quad.graph = namedNode(url);
64 | vocabStore.addQuad(quad);
65 | });
66 | rdfXmlParser.write(text);
67 | rdfXmlParser.end();
68 | } else if (contentTypeString && (contentTypeString.search('turtle') !== -1)) {
69 | parser.parse(text, (error, quad, prefixes) => {
70 | if (quad) {
71 | quad.graph = namedNode(url);
72 | vocabStore.addQuad(quad);
73 | }
74 | });
75 | }
76 | return true;
77 | } else {
78 | return false;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ "master" ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ "master" ]
20 | schedule:
21 | - cron: '32 14 * * 2'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'javascript']
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v3
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v2
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 |
52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
53 | # queries: security-extended,security-and-quality
54 |
55 |
56 | # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
57 | # If this step fails, then you should remove it and run the build manually (see below)
58 | - name: Autobuild
59 | uses: github/codeql-action/autobuild@v2
60 |
61 | # ℹ️ Command-line programs to run using the OS shell.
62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
63 |
64 | # If the Autobuild fails above, remove it and uncomment the following three lines.
65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
66 |
67 | # - run: |
68 | # echo "Run, Build Application using script"
69 | # ./location_of_script_within_repo/buildscript.sh
70 |
71 | - name: Perform CodeQL Analysis
72 | uses: github/codeql-action/analyze@v2
73 | with:
74 | category: "/language:${{matrix.language}}"
75 |
--------------------------------------------------------------------------------
/src/store/modules/modal.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | namespaced: true,
3 | state: {
4 | folderElement: {
5 | type: 'folder',
6 | src: 'folder',
7 | title: 'Folder',
8 | forms: [
9 | {
10 | key: 'name',
11 | title: 'Folder Name',
12 | placeholder: 'My Folder',
13 | value: '',
14 | isRequired: true,
15 | mustBeUnique: true,
16 | rules: {
17 | minChars: 5,
18 | maxChars: 30,
19 | errorMessage:
20 | 'The folder\'s name should have at least 5 and maximal 30 characters.',
21 | errorMessageDuplicate:
22 | 'Another element with the same name exists. Please change the name.'
23 | }
24 | },
25 | {
26 | key: 'description',
27 | title: 'Folder Description',
28 | placeholder: 'My Folder Description',
29 | value: '',
30 | isRequired: false
31 | }
32 | ]
33 | },
34 | mashupElement: {
35 | type: 'mashup',
36 | src: 'mashup.png',
37 | title: 'Mashup',
38 | forms: [
39 | {
40 | key: 'name',
41 | title: 'Mashup Name',
42 | placeholder: 'My Mashup',
43 | value: '',
44 | isRequired: true,
45 | mustBeUnique: true,
46 | rules: {
47 | minChars: 5,
48 | maxChars: 30,
49 | errorMessage:
50 | 'The mashup\'s name should have at least 5 and maximal 30 characters.',
51 | errorMessageDuplicate:
52 | 'Another element with the same name exists. Please change the name.'
53 | }
54 | },
55 | {
56 | key: 'description',
57 | title: 'Mashup Description',
58 | placeholder: 'My Mashup Description',
59 | value: '',
60 | isRequired: false
61 | }
62 | ]
63 | },
64 | tdElement: {
65 | type: 'td',
66 | src: 'td.png',
67 | title: 'Thing Description',
68 | forms: [
69 | {
70 | key: 'name',
71 | title: 'Thing Description Name',
72 | placeholder: 'My Thing Description',
73 | value: '',
74 | isRequired: true,
75 | mustBeUnique: true,
76 | rules: {
77 | minChars: 5,
78 | maxChars: 30,
79 | errorMessage:
80 | 'The Thing Description\'s name should have at least 5 and maximal 30 characters.',
81 | errorMessageDuplicate:
82 | 'Another element with the same name exists. Please change the name.'
83 | }
84 | }
85 | ]
86 | }
87 | },
88 | getters: {
89 | getElementTd(state: any) {
90 | return state.tdElement;
91 | },
92 | getElementMashup(state: any) {
93 | return state.mashupElement;
94 | },
95 | getElementFolder(state: any) {
96 | return state.folderElement;
97 | }
98 | }
99 | };
100 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mUrlBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
15 |
16 |
17 |
18 |
72 |
73 |
74 |
110 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mCoverageTestGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ coverageName }}
7 |
21 |
34 |
35 |
36 |
37 |
67 |
68 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aSimpleInputField.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
88 |
89 |
110 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aButtonBasic.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ btnLabel }}
4 |
5 |
6 |
51 |
52 |
144 |
145 |
--------------------------------------------------------------------------------
/performance-testing/confidence_calculator.js:
--------------------------------------------------------------------------------
1 | module.exports = class ConfidenceCalculator {
2 |
3 | // confidenceFactor99 = 2.576;
4 |
5 | constructor(jsonData) {
6 | this.jsonData = JSON.parse(jsonData);
7 | // this.confidenceFactor = this.confidenceFactor99;
8 | this.confidenceFactor = 2.576;
9 | this.percentageFactor = 0.05;
10 | }
11 |
12 | calculateAll() {
13 | let possibleResults = this.calculate(this.jsonData.possible.all, this.confidenceFactor, this.percentageFactor);
14 |
15 | let possibleWithoutFirstResults = this.calculate(this.jsonData.possibleWithoutFirst.all, this.confidenceFactor, this.percentageFactor);
16 |
17 | let realisticResults = this.calculate(this.jsonData.realistic.all, this.confidenceFactor, this.percentageFactor);
18 |
19 | let realisticWithoutFirstResults = this.calculate(this.jsonData.realisticWithoutFirst.all, this.confidenceFactor, this.percentageFactor);
20 |
21 | return { possibleResults, possibleWithoutFirstResults, realisticResults, realisticWithoutFirstResults };
22 | }
23 |
24 | calculate(data, confidenceFactor, percentageFactor) {
25 | let size = data.length;
26 | let BCET = data[0];
27 | let WCET = data[0];
28 |
29 | // Confidence interval variables
30 | let mean;
31 | let stDev;
32 | let stErr;
33 | let errMargin;
34 | let confMin;
35 | let confMax;
36 |
37 | // Percentage variables
38 | let percentageVal;
39 | let minPercentage;
40 | let maxPercentage;
41 |
42 | // Calculate confidence interval
43 | mean = data.reduce((a,b) => a+b)/ size;
44 | stDev = Math.sqrt(data.map(x => Math.pow(x-mean,2)).reduce((a,b) => a+b)/size);
45 | stErr = stDev / Math.sqrt(size);
46 | errMargin = stErr * confidenceFactor;
47 | confMax = errMargin + mean;
48 | confMin = mean - errMargin;
49 |
50 | // Confirm correctness of BCET, WCET, AET
51 | for (let i = 0; i < size; i++) {
52 | if (data[i] < BCET) BCET = data[i];
53 | if (data[i] > WCET) WCET = data[i];
54 | }
55 |
56 | // Calculate correctness up to +/-x %
57 | percentageVal = mean * percentageFactor;
58 | minPercentage = mean - percentageVal;
59 | maxPercentage = mean + percentageVal;
60 |
61 | return {
62 | confidenceFactor: confidenceFactor,
63 | mean,
64 | standardDeviation: stDev,
65 | standardError: stErr,
66 | errorMargin: errMargin,
67 | confidenceIntervalMin: confMin,
68 | confidenceIntervalMin: confMax,
69 | confidenceInterval: `${confMin} - ${confMax}`,
70 | accuracyFactor: percentageFactor,
71 | accuracyPercentageValue: percentageVal,
72 | minPercentageValue: minPercentage,
73 | maxPercentageValue: maxPercentage,
74 | accuracyRange: `${minPercentage} - ${maxPercentage}`,
75 | resultsWithinRange: confMin > minPercentage && maxPercentage > confMin,
76 | resultsWithinRangeMin: confMin > minPercentage,
77 | resultsWithinRangeMax: maxPercentage > confMin
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "w-ade",
3 | "description": "W-ADE: Web of Things API Development Environment",
4 | "author": "TUM-ESI (http://www.ei.tum.de/esi)",
5 | "contributors": [
6 | {
7 | "name": "Verena Eileen Schlott",
8 | "email": "schlott.verena.eileen@gmail.com"
9 | },
10 | {
11 | "name": "Adrian Kast"
12 | },
13 | {
14 | "name": "Ege Korkan",
15 | "email": "ege.korkan@tum.de"
16 | },
17 | {
18 | "name": "Miguel Romero Karam",
19 | "email": "miguel.romero@tum.de"
20 | },
21 | {
22 | "name": "Fady Salama",
23 | "email": "fady.salama@tum.de"
24 | }
25 | ],
26 | "version": "2.0.1",
27 | "private": true,
28 | "scripts": {
29 | "serve": "vue-cli-service serve",
30 | "build": "vue-cli-service build",
31 | "lint": "vue-cli-service lint",
32 | "electron:build": "vue-cli-service electron:build",
33 | "electron:serve": "vue-cli-service electron:serve",
34 | "postinstall": "node postinstall.js & electron-builder install-app-deps",
35 | "postuninstall": "electron-builder install-app-deps",
36 | "electron:generate-icons": "electron-icon-builder --input=./public/icon.png --output=build --flatten",
37 | "ui": "vue ui"
38 | },
39 | "main": "background.js",
40 | "dependencies": {
41 | "@node-wot/binding-coap": "~0.8.6",
42 | "@node-wot/binding-http": "~0.8.6",
43 | "@node-wot/binding-mqtt": "~0.8.6",
44 | "@node-wot/binding-websockets": "~0.8.6",
45 | "@node-wot/core": "~0.8.6",
46 | "ajv": "^8.11.0",
47 | "core-js": "^3.8.3",
48 | "cors-anywhere": "^0.4.4",
49 | "electron-builder": "^23.0.2",
50 | "electron-json-storage": "^4.5.0",
51 | "js-beautify": "^1.14.4",
52 | "js-combinatorics": "^0.6.1",
53 | "json-schema-faker": "0.5.0-rcv.46",
54 | "jsonld-streaming-parser": "^2.4.3",
55 | "mermaid": "9.1.2",
56 | "monaco-editor": "^0.33.0",
57 | "monaco-editor-webpack-plugin": "^7.0.1",
58 | "n3": "^1.6.3",
59 | "rdfxml-streaming-parser": "^1.5.0",
60 | "ts-loader": "~8.2.0",
61 | "vue": "^2.6.14",
62 | "vue-router": "^3.5.1",
63 | "vuex": "^3.6.2",
64 | "vuex-electron-store": "^1.4.26",
65 | "wot-testbench": "^1.1.2"
66 | },
67 | "devDependencies": {
68 | "@types/electron-devtools-installer": "^2.2.0",
69 | "@types/js-beautify": "^1.13.3",
70 | "@types/js-combinatorics": "^0.5.32",
71 | "@types/mermaid": "8.2.2",
72 | "@types/n3": "1.4.4",
73 | "@types/node": "^18.0.0",
74 | "@types/request": "^2.48.8",
75 | "@vue/cli-plugin-babel": "~5.0.0",
76 | "@vue/cli-plugin-router": "~5.0.0",
77 | "@vue/cli-plugin-typescript": "~5.0.0",
78 | "@vue/cli-plugin-vuex": "~5.0.0",
79 | "@vue/cli-service": "~5.0.0",
80 | "electron": "^18.3.7",
81 | "electron-devtools-installer": "^3.1.0",
82 | "less": "^4.0.0",
83 | "less-loader": "^8.0.0",
84 | "tslint": "^6.1.3",
85 | "typescript": "~4.5.5",
86 | "vue-cli-plugin-electron-builder": "~2.1.1",
87 | "vue-template-compiler": "^2.6.14"
88 | },
89 | "postcss": {
90 | "plugins": {
91 | "autoprefixer": {}
92 | }
93 | },
94 | "browserslist": [
95 | "> 1%",
96 | "last 2 versions",
97 | "not dead"
98 | ]
99 | }
100 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aFormfield.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
82 |
83 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/src/background.ts:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | declare const __static: string;
4 | import { app, protocol, BrowserWindow } from 'electron';
5 | import {
6 | createProtocol,
7 | } from 'vue-cli-plugin-electron-builder/lib';
8 | import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer';
9 | import path from 'path';
10 | import PersistedState from 'vuex-electron-store';
11 | const isDevelopment = process.env.NODE_ENV !== 'production';
12 |
13 | // Keep a global reference of the window object, if you don't, the window will
14 | // be closed automatically when the JavaScript object is garbage collected.
15 | let win: BrowserWindow | null;
16 |
17 | // Scheme must be registered before the app is ready
18 | protocol.registerSchemesAsPrivileged([{scheme: 'app', privileges: { secure: true, standard: true } }]);
19 |
20 | PersistedState.initRenderer();
21 |
22 | function createWindow() {
23 | // Create the browser window.
24 | win = new BrowserWindow({
25 | width: 1200,
26 | height: 900,
27 | minWidth: 800,
28 | minHeight: 600,
29 | autoHideMenuBar: true,
30 | webPreferences: {
31 |
32 | // Use pluginOptions.nodeIntegration, leave this alone
33 | // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
34 | nodeIntegration: (process.env
35 | .ELECTRON_NODE_INTEGRATION as unknown) as boolean,
36 | contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION
37 | },
38 | icon: path.join(__static, 'icon.png')
39 | });
40 | // win.setMenu(null);
41 |
42 | if (process.env.WEBPACK_DEV_SERVER_URL) {
43 | // Load the url of the dev server if in development mode
44 | win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string);
45 | // if (!process.env.IS_TEST) { win.webContents.openDevTools(); }
46 | if (!process.env.IS_TEST) {
47 | // do not show dev tools
48 | }
49 | } else {
50 | createProtocol('app');
51 | // Load the index.html when not in development
52 | win.loadURL('app://./index.html');
53 | }
54 |
55 | win.on('closed', () => {
56 | win = null;
57 | });
58 | }
59 |
60 | // Quit when all windows are closed.
61 | app.on('window-all-closed', () => {
62 | // On macOS it is common for applications and their menu bar
63 | // to stay active until the user quits explicitly with Cmd + Q
64 | if (process.platform !== 'darwin') {
65 | app.quit();
66 | }
67 | });
68 |
69 | app.on('activate', () => {
70 | // On macOS it's common to re-create a window in the app when the
71 | // dock icon is clicked and there are no other windows open.
72 | if (win === null) {
73 | createWindow();
74 | }
75 | });
76 |
77 | // This method will be called when Electron has finished
78 | // initialization and is ready to create browser windows.
79 | // Some APIs can only be used after this event occurs.
80 | app.on('ready', async () => {
81 | if (isDevelopment && !process.env.IS_TEST) {
82 | // Install Vue Devtools
83 | try {
84 | await installExtension(VUEJS_DEVTOOLS);
85 | } catch (e) {
86 | // console.error('Vue Devtools failed to install:', e.toString());
87 | }
88 | }
89 | createWindow();
90 | });
91 |
92 | // Exit cleanly on request from parent process in development mode.
93 | if (isDevelopment) {
94 | if (process.platform === 'win32') {
95 | process.on('message', (data) => {
96 | if (data === 'graceful-exit') {
97 | app.quit();
98 | }
99 | });
100 | } else {
101 | process.on('SIGTERM', () => {
102 | app.quit();
103 | });
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aOptionElement.vue:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
{{ firstElement }}
6 |
{{ secondElement }}
7 |
8 |
9 |
10 |
11 |
79 |
80 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mGalleryMermaid.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | No mashups could be generated according to the constraints and filters choosen!
5 |
6 |
7 |
8 |
9 |
{{txtArray.length}} mashups conform to the selected criteria from a total of {{maxPossibleMashups}} possible mashups
10 |
{{timeText}}
11 |
12 |
Mashup {{txtIndex+1}}/{{txtArray.length}}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
87 |
88 |
--------------------------------------------------------------------------------
/NLP/word2vec-api.py:
--------------------------------------------------------------------------------
1 | #Flask API for server
2 | from flask import Flask, request, jsonify
3 | from flask_restful import Resource, Api, reqparse
4 |
5 | #Gensim for NLP
6 | import gensim.downloader as modelDownloader
7 |
8 | # Import and download stopwords from NLTK.
9 | from nltk.corpus import stopwords
10 | from nltk import download
11 | download('stopwords') # Download stopwords list.
12 | stop_words = stopwords.words('english')
13 |
14 | import argparse
15 | import base64
16 | import sys
17 |
18 |
19 |
20 | def preprocess(sentence):
21 | return [w for w in sentence.lower().split() if w not in stop_words]
22 |
23 | parser = reqparse.RequestParser()
24 |
25 | class N_Similarity(Resource):
26 | def get(self):
27 | parser = reqparse.RequestParser()
28 | parser.add_argument('ws1', type=str, required=True, help="Word set 1 cannot be blank!", action='append')
29 | parser.add_argument('ws2', type=str, required=True, help="Word set 2 cannot be blank!", action='append')
30 | args = parser.parse_args()
31 | return model.n_similarity(filter_words(args['ws1']),filter_words(args['ws2']))
32 |
33 |
34 | class Similarity(Resource):
35 | def get(self):
36 | parser = reqparse.RequestParser()
37 | parser.add_argument('w1', type=str, required=True, help="Word 1 cannot be blank!")
38 | parser.add_argument('w2', type=str, required=True, help="Word 2 cannot be blank!")
39 | args = parser.parse_args()
40 | return model.similarity(args['w1'], args['w2'])
41 |
42 | class WMDistance(Resource):
43 | def get(self):
44 | parser = reqparse.RequestParser()
45 | parser.add_argument('s1', type=str, required=True, help="Sentence 1 cannot be blank!")
46 | parser.add_argument('s2', type=str, required=True, help="Sentence 2 cannot be blank!")
47 | args = parser.parse_args()
48 | sentence1 = preprocess(args['s1'])
49 | sentence2 = preprocess(args['s2'])
50 | return model.wmdistance(sentence1, sentence2)
51 |
52 | class Model(Resource):
53 | def get(self):
54 | parser = reqparse.RequestParser()
55 | parser.add_argument('word', type=str, required=True, help="word to query.")
56 | args = parser.parse_args()
57 | try:
58 | res = model[args['word']]
59 | res = base64.b64encode(res)
60 | return res
61 | except(Exception, e):
62 | print(e)
63 | return
64 |
65 | app = Flask(__name__)
66 | api = Api(app)
67 |
68 | @app.errorhandler(404)
69 | def pageNotFound(error):
70 | return "page not found"
71 |
72 | @app.errorhandler(500)
73 | def raiseError(error):
74 | return error
75 |
76 | if __name__ == '__main__':
77 | global model
78 |
79 | #----------- Parsing Arguments ---------------
80 | p = argparse.ArgumentParser()
81 | p.add_argument("--model", help="Path to the trained model")
82 | p.add_argument("--binary", help="Specifies the loaded model is binary")
83 | p.add_argument("--host", help="Host name (default: localhost)")
84 | p.add_argument("--port", help="Port (default: 5000)")
85 | p.add_argument("--path", help="Path (default: /word2vec)")
86 | args = p.parse_args()
87 |
88 | model_path = args.model if args.model else "./model.bin.gz"
89 | binary = True if args.binary else False
90 | host = args.host if args.host else "localhost"
91 | path = args.path if args.path else "/word2vec"
92 | port = int(args.port) if args.port else 5000
93 | if not args.model:
94 | print("Usage: word2vec-apy.py --model path/to/the/model [--host host --port 1234]")
95 | model = modelDownloader.load("word2vec-google-news-300")
96 | model.init_sims(replace=True)
97 | api.add_resource(N_Similarity, path+'/n_similarity')
98 | api.add_resource(Similarity, path+'/similarity')
99 | api.add_resource(WMDistance, path+'/wmd')
100 | app.run(host=host, port=port)
--------------------------------------------------------------------------------
/src/components/01_atoms/aOutputBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
{{ msg.time.h }}:{{ msg.time.m }}:{{ msg.time.s }}
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
{{ msg.content }}
35 |
36 |
37 |
38 |
39 |
40 |
41 |
55 |
56 |
145 |
--------------------------------------------------------------------------------
/src/components/03_organisms/oResults.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Results
4 |
5 |
6 |
7 |
Result Properties
8 |
20 |
21 |
22 |
37 |
38 |
51 |
52 |
53 |
54 |
{{ getResultText }}
55 |
56 |
57 |
58 |
59 |
90 |
91 |
136 |
--------------------------------------------------------------------------------
/src/backend/Td.ts:
--------------------------------------------------------------------------------
1 | import { ElementTypeEnum, VtStatus } from '@/util/enums';
2 |
3 | abstract class BasicElement implements WADE.NewStoreElementInterface {
4 | public title: string;
5 | public id: string;
6 | public type: ElementTypeEnum;
7 | public parentId: string;
8 | constructor(param: WADE.NewStoreElementInterface) {
9 | this.title = param.title;
10 | this.id = param.id;
11 | this.type = param.type;
12 | this.parentId = 'parent';
13 | }
14 | }
15 |
16 | abstract class ChildlessElement extends BasicElement implements WADE.ChildlessElementInterface {
17 | public readonly hasChildren: false;
18 | constructor(param: WADE.ChildlessElementInterface) {
19 | super(param);
20 | this.hasChildren = false;
21 | }
22 | }
23 |
24 | abstract class ParentElement extends BasicElement implements WADE.ParentElementInterface {
25 | public readonly hasChildren: true;
26 | public description: string;
27 | public children: Array;
28 | constructor(param: WADE.ParentElementInterface) {
29 | super(param);
30 | this.description = param.description;
31 | this.children = param.children;
32 | this.hasChildren = true;
33 | }
34 | }
35 |
36 | export class TD extends ChildlessElement implements WADE.TDElementInterface {
37 | public type: ElementTypeEnum.TD;
38 | public content: string;
39 | public config: {};
40 | public vconfig: {};
41 | public virtualthing: {
42 | status: VtStatus
43 | outMsg: [],
44 | vt: undefined // not necessary, but used to remember that property is used
45 | };
46 | constructor(param: WADE.TDElementInterface) {
47 | super(param);
48 | this.parentId = param.parentId;
49 | this.type = ElementTypeEnum.TD;
50 | this.content = param.content;
51 | this.config = param.config;
52 | this.vconfig = param.vconfig;
53 | this.virtualthing = param.virtualthing;
54 | }
55 | }
56 | export class Mashup extends ParentElement implements WADE.MashupElementInterface {
57 | public type: ElementTypeEnum.MASHUP;
58 | public tds: TD[] ;
59 | public mashups: Mashup[] ;
60 | public children: Array ;
61 | public systemDescription: string;
62 | public mashupCode: string;
63 |
64 | constructor(param: WADE.MashupElementInterface) {
65 | super(param);
66 | this.parentId = param.parentId;
67 | this.type = ElementTypeEnum.MASHUP;
68 | this.systemDescription = '';
69 | this.mashupCode = '';
70 | this.tds = [];
71 | this.mashups = [];
72 | this.children = [];
73 | for (const childInterface of param.children) {
74 | let child;
75 | if (childInterface.type === WADE.ElementTypeEnum.TD) {
76 | child = new TD(childInterface);
77 | this.tds.push(child);
78 | }
79 | if (childInterface.type === WADE.ElementTypeEnum.MASHUP) {
80 | child = new Mashup(childInterface);
81 | this.mashups.push(child);
82 | }
83 | this.children.push(child);
84 | }
85 | }
86 | }
87 | export class Folder extends ParentElement implements WADE.FolderElementInterface {
88 | public type: ElementTypeEnum.FOLDER;
89 | public tds: TD[] ;
90 | public mashups: Mashup[] ;
91 | public folders: Folder[];
92 | public children: Array ;
93 | public systemDescription: string | undefined;
94 |
95 | constructor(param: WADE.FolderElementInterface) {
96 | super(param);
97 | this.parentId = param.parentId;
98 | this.type = ElementTypeEnum.FOLDER;
99 | this.tds = [];
100 | this.mashups = [];
101 | this.folders = [];
102 | this.children = [];
103 | for (const childInterface of param.children) {
104 | let child;
105 | if (childInterface.type === WADE.ElementTypeEnum.TD) {
106 | child = new TD(childInterface);
107 | this.tds.push(child);
108 | }
109 | if (childInterface.type === WADE.ElementTypeEnum.MASHUP) {
110 | child = new Mashup(childInterface);
111 | this.mashups.push(child);
112 | }
113 | if (childInterface.type === WADE.ElementTypeEnum.FOLDER) {
114 | child = new Folder(childInterface);
115 | this.mashups.push(child);
116 | }
117 | this.children.push(child);
118 | }
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aTabHeader.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
46 |
47 |
48 |
81 |
82 |
196 |
197 |
--------------------------------------------------------------------------------
/src/components/03_organisms/oPerformanceOutput.vue:
--------------------------------------------------------------------------------
1 |
2 |
53 |
54 |
55 |
108 |
109 |
--------------------------------------------------------------------------------
/src/backend/ConfidenceCalculator.ts:
--------------------------------------------------------------------------------
1 | import { confidenceLevel } from '@/util/helpers';
2 |
3 | export default class ConfidenceCalculator {
4 |
5 | private data: any; // WADE.PerformanceResult[];
6 | private confLevel: number;
7 | private precisionFactor: undefined | number;
8 |
9 | constructor(data: any, confLevel: any, precisionFactor?: number) {
10 | this.data = data;
11 | this.confLevel = confLevel;
12 | this.precisionFactor = precisionFactor || undefined;
13 | }
14 |
15 | /**
16 | * Calculate confidence intervals for all measured data.
17 | */
18 | public calculateAll() {
19 | // Iterate over each timing measurement result and calculate the confidence interval for them all yeah
20 | for (let i = 0, l = this.data.length; i < l; i++) {
21 | this.data[i] = this.calculate(this.data[i]);
22 | }
23 |
24 | // Return the timing measurements results, enhanced with the calculation of confidence interval + other info
25 | return this.data;
26 | }
27 |
28 | /**
29 | * Calculate the confidence interval for each result element
30 | * (possible, possibleWithoutFirst, realistic, realisticWithoutFirst)
31 | * @param data
32 | */
33 | private calculate(resultElement: WADE.PerformanceResult): WADE.PerformanceResult {
34 | const resultElementMeasurements = ['possible', 'possibleWithoutFirst', 'realistic', 'realisticWithoutFirst'];
35 |
36 | // Calculate confidence for each result element
37 | resultElementMeasurements.forEach((element) => {
38 | if (resultElement[element] && resultElement[element].all) {
39 | // TODO
40 | // this.data[element].confidenceResults =
41 | // this.calculateConfInterval(this.data[element], this.confLevel, this.precisionFactor);
42 | resultElement[element].confidenceResults = { WHAT: 'THE FUCK'};
43 | }
44 | });
45 | return resultElement;
46 | }
47 |
48 | /**
49 | * Calculate the confidence interval for specific set of data
50 | * @param data A set of numbers
51 | * @param confLevel The chosen confidence level
52 | * @param precisionFactor validate precision factor
53 | */
54 | private calculateConfInterval(data: number[], confLevel: number, precisionFactor: number | undefined):
55 | WADE.ConfidenceLevelResults {
56 | const dataSize = data.length;
57 | let BCET = data[0]; // Initial value
58 | let WCET = data[0]; // Initial value
59 |
60 | // Confidence interval variables
61 | let mean: number;
62 | let stDev: number; // Standard deviation
63 | let stErr: number; // Standard error
64 | let errMargin: number; // Error margin
65 | let confMin: number; // Confidence interval min value
66 | let confMax: number; // Confidence interval max value
67 |
68 | // Precision variables
69 | let precVal; // Precision value (calculated with precisionFactor)
70 | let precMinVal; // Precision min value
71 | let precMaxVal; // Precision max value
72 |
73 | // Actually calculate confidence interval
74 | mean = data.reduce((a, b) => a + b) / dataSize;
75 | stDev = Math.sqrt(data.map(x => Math.pow( x - mean, 2)).reduce((a, b) => a + b) / dataSize);
76 | stErr = stDev / Math.sqrt(dataSize);
77 | errMargin = stErr * confLevel;
78 | confMin = mean - errMargin;
79 | confMax = mean - errMargin;
80 |
81 | // Confirm correctness of BCET, WCET, AET
82 | for (let i = 0; i < dataSize; i++) {
83 | if (data[i] < BCET) BCET = data[i];
84 | if (data[i] > WCET) WCET = data[i];
85 | }
86 |
87 | // Calculate precision
88 | if (!precisionFactor) {
89 | precisionFactor = 0;
90 | // TODO calculate precision factor
91 | } else {
92 | precVal = mean * precisionFactor;
93 | precMinVal = mean - precVal;
94 | precMaxVal = mean + precVal;
95 | }
96 |
97 | return {
98 | confidenceFactor: this.confLevel,
99 | mean,
100 | standardDeviation: stDev,
101 | standardError: stErr,
102 | errorMargin: errMargin,
103 | confidenceIntervalMin: confMin,
104 | confidenceIntervalMax: confMax,
105 | confidenceInterval: `${confMin}-${confMax}`,
106 | precisionFactor,
107 | precisionMinVal: precMinVal,
108 | precisionMaxVal: precMaxVal,
109 | precisionRange: `${precMinVal}-${precMaxVal}`,
110 | resultsWithinRange: precMinVal < confMin && precMaxVal > confMax,
111 | resultsWithinRangeMin: precMinVal < confMin,
112 | resultsWithinRangeMax: precMaxVal > confMax,
113 | };
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/components/03_organisms/oModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
21 |
22 |
23 |
126 |
127 |
171 |
172 |
--------------------------------------------------------------------------------
/docs/SOURCES.md:
--------------------------------------------------------------------------------
1 |
2 | ### Credit and sources:
3 |
4 | - Icon burger menu :
5 |
6 | - Icon search :
7 |
8 | - Icon '+':
9 |
10 | - Icon folder:
11 |
12 | - Icon computer:
13 |
14 | - Icon website:
15 |
16 | - Icon download:
17 |
18 | - Icon performance:
19 |
20 | - Icon arrow down:
21 |
22 | - Icon checked:
23 |
24 | - Icon empty circle:
25 |
26 | - Icon trashbin:
27 |
28 | - Icon three dots / options: as
29 |
30 | - Font Awesome Icons (4.7):
31 |
32 | - Icon add plugins:
--------------------------------------------------------------------------------
/src/util/enums.ts:
--------------------------------------------------------------------------------
1 | export enum ElementTypeEnum {
2 | FOLDER = 'folder',
3 | TD = 'td',
4 | MASHUP = 'mashup'
5 | }
6 |
7 | /**
8 | * Available Tabs for Thing Description elements
9 | */
10 | export enum TDTabsEnum {
11 | EDITOR = 'editor',
12 | CONFIG = 'config',
13 | PERFORMANCE = 'performance',
14 | TESTBENCH = 'testbench'
15 | }
16 |
17 | export enum ElementTitleEnum {
18 | FOLDER = 'Folder',
19 | TD = 'Thing Description',
20 | MASHUP = 'Mashup'
21 | }
22 |
23 | export enum PossibleInteractionTypesEnum {
24 | PROP_READ = 'property-read',
25 | PROP_READ_ALL = 'property-read-all',
26 | PROP_READ_MULTIPLE = 'property-read-multiple',
27 | PROP_WRITE = 'property-write',
28 | PROP_WRITE_ALL = 'property-write-all',
29 | PROP_WRITE_MULTIPLE = 'property-write-multiple',
30 | PROP_OBSERVE_READ = 'property-observe-read',
31 | PROP_OBSERVE_WRITE = 'property-observe-write',
32 | ACTION = 'action-invoke',
33 | EVENT_SUB = 'event-subscribe',
34 | EVENT_UNSUB = 'event-unsubscribe',
35 | }
36 |
37 | export enum MetaInteractionTypesEnum {
38 | PROP_READ_ALL = 'readallproperties',
39 | PROP_READ_MULTIPLE = 'readmultipleproperties',
40 | PROP_WRITE_ALL = 'writeallproperties',
41 | PROP_WRITE_MULTIPLE = 'writemultipleproperties',
42 | PROP_OBSERVE_ALL = 'observeallproperties',
43 | PROP_UNOBSERVE_ALL = 'unobserveallproperties',
44 | ACTION_QUERY_ALL = 'queryallactions',
45 | EVENT_SUB_ALL = 'subscribeallevents',
46 | EVENT_UNSUB_ALL = 'unsubscribeallevents'
47 | }
48 |
49 | export enum InteractionStateEnum {
50 | // No / invalid td
51 | NO_INTERACTIONS = 'No interactions can be shown.',
52 | NOT_SELECTED = 'Select an interaction to invoke it.',
53 | NOT_INVOKED = 'Interactions are selected. Click invoke button to invoke them.',
54 | INVOKED = 'Interactions have been invoked.'
55 | }
56 |
57 | // Results messages
58 | export enum RESULT_MESSAGES {
59 | NO_INTERACTIONS_SELECTED = 'No interactions have been selected',
60 | NO_INTERACTIONS_INVOKED = 'Interactions have not been invoked yet'
61 | }
62 |
63 | export enum TdStateEnum {
64 | NO_TD = 'NO TD: Paste or upload a Thing Description.',
65 | VALID_TD_JSON = 'VALID JSON: TD is valid JSON.',
66 | INVALID_TD_JSON = 'INVALID JSON: TD is invalid JSON.',
67 | VALID_CONSUMED_TD = 'CONSUMED: TD has been successfully consumed.',
68 | VALID_TD_FETCHED = 'FETCH SUCCESS: TD has successfully been fetched.',
69 | INVALID_TD_FETCHED = 'FETCH ERROR: TD could not be fetched.',
70 | INVALID_TD_EMPTY = 'INVALID TD: TD may not be empty object.',
71 | INVALID_CONSUMED_TD = 'CONSUME ERROR: TD could not be consumed.',
72 | INVALID_TD = 'INVALID TD: TD is invalid.',
73 | VALID_TD = 'VALID TD: TD is valid.',
74 | TD_FETCHING = 'FETCHING TD...'
75 | }
76 |
77 | export enum TdConfigEnum {
78 | INFO = 'This config will be used for your TD.',
79 | UNSAVED = 'Please save your changes to apply them',
80 | SAVE_SUCCESS = 'Config was safed successfully.',
81 | RESET = 'Config was resetted to default config. Click save to apply this.',
82 | ERROR = 'Error: Wrong data format. Change config to make it saveable.'
83 | }
84 |
85 | /* The enum values indexes of SAVE_SUCCESS and ERROR must be equal
86 | to the indexes at the TdConfigEnum, to ensure that aConfigStatusBar
87 | highliting works */
88 | export enum TdVirtualConfigEnum {
89 | INFO = 'This config will be used to generate a Virtual Thing for your TD',
90 | UNSAVED = 'Please save your changes to apply them',
91 | SAVE_SUCCESS = 'Virtual Thing config was safed successfully.',
92 | RESET = 'Virtual Thing config was resetted to default config. Save to apply!',
93 | ERROR = 'Error: Wrong data format. Change Virtual Thing config to make it saveable.'
94 | }
95 |
96 | export enum ProtocolEnum {
97 | HTTP = 'http',
98 | HTTPS = 'https',
99 | COAP = 'coap',
100 | COAPS = 'coaps',
101 | MQTT = 'mqtt'
102 | }
103 |
104 | export enum VtStatus {
105 | NOT_CREATED = 'Virtual Thing is not running for this TD',
106 | STARTUP = 'a Virtual Thing is currently being created',
107 | RUNNING = 'Virtual Thing is up',
108 | STOPPED = 'the virtualization is being stopped',
109 | ERROR = 'there has been an error with Virtual Thing'
110 | }
111 |
112 | export enum MeasurementTypeEnum {
113 | NUM_RUNS = 'Iteration',
114 | DURATION_RUN = 'Duration',
115 | NUM_CLIENTS_NUM_RUN = 'Multiple Clients with iterations',
116 | NUM_CLIENTS_DURATION_RUN = 'Multiple Clients with duration',
117 | }
118 |
119 | export enum DelayTypeEnum {
120 | NO_DELAY = 'No Delay',
121 | BEFORE_EACH = 'Delay before each',
122 | BEFORE_BEGIN = 'Delay before beginning'
123 | }
124 |
125 | export enum StatusEnum {
126 | NOT_STARTED = 'not-started',
127 | LOADING = 'loading',
128 | COMPUTED = 'computed',
129 | ERROR = 'error'
130 | }
131 |
132 | // For InteractionTiming vocabulary
133 | export enum TypeOfMeasurementContext {
134 | DYNAMIC_PROPERTY_READ = 'dynamicTimingContext_property_read',
135 | DYNAMIC_PROPERTY_WRITE = 'dynamicTimingContext_property_write',
136 | DYNAMIC_ACTION = 'dynamicTimingContext_action',
137 | NULL = 'null'
138 | }
139 |
140 | export enum TestbenchConfigEnum {
141 | INFO = 'This config will be used to test your TD',
142 | UNSAVED = 'Please save your changes to apply them',
143 | SAVE_SUCCESS = 'Testbench config was saved successfully.',
144 | RESET = 'Testbench config was reset to default config. Save to apply!',
145 | ERROR = 'Error: Wrong data format. Change Testbench config to make it saveable.'
146 | }
147 |
--------------------------------------------------------------------------------
/src/components/02_molecules/mInteraction.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ interactionName }}
4 |
37 |
{{interactionErrorMessage}}
38 |
39 |
40 |
41 |
107 |
108 |
158 |
--------------------------------------------------------------------------------
/src/components/04_templates/tMashup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 | {{ currentMashup.id }}
10 | : {{ currentMashup.description }}
11 |
12 |
13 |
19 |
23 |
24 |
25 |
26 |
27 |
108 |
109 |
110 |
159 |
--------------------------------------------------------------------------------
/src/components/01_atoms/aTab.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
21 |
22 |
26 | {{ tabTitle }}
27 |
28 |
29 |
30 |
31 |
140 |
141 |
227 |
228 |
--------------------------------------------------------------------------------
/src/components/04_templates/tPerformance.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
12 |
20 |
21 |
22 |
23 |
128 |
129 |
--------------------------------------------------------------------------------