├── 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 | 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 | 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 | 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 | 6 | 7 | 17 | 18 | 34 | -------------------------------------------------------------------------------- /src/components/01_atoms/aInputSelector.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 7 | 8 | 23 | 24 | 45 | -------------------------------------------------------------------------------- /src/components/01_atoms/aVirtualThingStatusbar.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 14 | 15 | 38 | 39 | 52 | -------------------------------------------------------------------------------- /src/components/01_atoms/aSearchbar.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 32 | 33 | 62 | -------------------------------------------------------------------------------- /src/components/02_molecules/mTabbar.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 42 | 43 | 44 | 56 | -------------------------------------------------------------------------------- /src/components/01_atoms/aViewerMermaid.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 48 | 49 | -------------------------------------------------------------------------------- /src/components/01_atoms/aConfigStatusBar.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 15 | 16 | 40 | 41 | 60 | -------------------------------------------------------------------------------- /src/components/01_atoms/aVulnerabilityTestElement.vue: -------------------------------------------------------------------------------- 1 | 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 | 15 | 16 | 42 | 43 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/components/01_atoms/aConformanceTestElement.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/components/01_atoms/aCoverageTestElement.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 54 | 55 | -------------------------------------------------------------------------------- /src/components/01_atoms/aListSimple.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 37 | 38 | -------------------------------------------------------------------------------- /src/components/01_atoms/aIconButton.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 65 | 66 | 90 | 91 | -------------------------------------------------------------------------------- /src/components/02_molecules/mTableSimple.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 38 | 39 | -------------------------------------------------------------------------------- /src/components/02_molecules/mTestCycleElement.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 51 | 52 | -------------------------------------------------------------------------------- /src/components/02_molecules/mTestScenarioElement.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 52 | 53 | -------------------------------------------------------------------------------- /src/components/01_atoms/aTemplateSelectionMaGe.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 53 | 54 | -------------------------------------------------------------------------------- /src/components/01_atoms/aEditorMonaco.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 65 | 66 | -------------------------------------------------------------------------------- /src/components/03_organisms/oProtocolSelection.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 43 | 44 | 68 | 69 | -------------------------------------------------------------------------------- /src/components/02_molecules/mMashupElement.vue: -------------------------------------------------------------------------------- 1 | 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 | 17 | 18 | 72 | 73 | 74 | 110 | -------------------------------------------------------------------------------- /src/components/02_molecules/mCoverageTestGroup.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 67 | 68 | -------------------------------------------------------------------------------- /src/components/01_atoms/aSimpleInputField.vue: -------------------------------------------------------------------------------- 1 | 2 | 19 | 20 | 88 | 89 | 110 | -------------------------------------------------------------------------------- /src/components/01_atoms/aButtonBasic.vue: -------------------------------------------------------------------------------- 1 | 2 | 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 | 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 | 10 | 11 | 79 | 80 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /src/components/02_molecules/mGalleryMermaid.vue: -------------------------------------------------------------------------------- 1 | 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 | 40 | 41 | 55 | 56 | 145 | -------------------------------------------------------------------------------- /src/components/03_organisms/oResults.vue: -------------------------------------------------------------------------------- 1 | 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 | 47 | 48 | 81 | 82 | 196 | 197 | -------------------------------------------------------------------------------- /src/components/03_organisms/oPerformanceOutput.vue: -------------------------------------------------------------------------------- 1 | 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 | 22 | 23 | 126 | 127 | 171 | 172 | -------------------------------------------------------------------------------- /docs/SOURCES.md: -------------------------------------------------------------------------------- 1 | 2 | ### Credit and sources: 3 | 4 | - Icon burger menu :
Icons made by Chanut from www.flaticon.com is licensed by CC 3.0 BY
5 | 6 | - Icon search :
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
7 | 8 | - Icon '+':
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
9 | 10 | - Icon folder:
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
11 | 12 | - Icon computer:
Icons made by catkuro from www.flaticon.com is licensed by CC 3.0 BY
13 | 14 | - Icon website:
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
15 | 16 | - Icon download:
Icons made by Bogdan Rosu from www.flaticon.com is licensed by CC 3.0 BY
17 | 18 | - Icon performance:
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
19 | 20 | - Icon arrow down:
Icons made by Dave Gandy from www.flaticon.com is licensed by CC 3.0 BY
21 | 22 | - Icon checked:
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
23 | 24 | - Icon empty circle:
Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY
25 | 26 | - Icon trashbin:
Icons made by Kiranshastry from www.flaticon.com is licensed by CC 3.0 BY
27 | 28 | - Icon three dots / options:
Icons made by Smashicons from www.flaticon.com is licensed by CC 3.0 BY
as 29 | 30 | - Font Awesome Icons (4.7):
Font Awesome by Dave Gandy - https://fontawesome.com
31 | 32 | - Icon add plugins:
Image of raphaelsilva on Pixabay
-------------------------------------------------------------------------------- /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 | 40 | 41 | 107 | 108 | 158 | -------------------------------------------------------------------------------- /src/components/04_templates/tMashup.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 108 | 109 | 110 | 159 | -------------------------------------------------------------------------------- /src/components/01_atoms/aTab.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 140 | 141 | 227 | 228 | -------------------------------------------------------------------------------- /src/components/04_templates/tPerformance.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 128 | 129 | --------------------------------------------------------------------------------