added mqtt device setup feature

This commit is contained in:
Felix Baumgärtner 2024-01-18 15:36:16 +01:00
parent cf128088f6
commit 8db9cbd7b5
6 changed files with 576 additions and 116 deletions

436
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.0.1",
"dependencies": {
"@floating-ui/dom": "1.5.4",
"mqtt": "^5.3.4",
"nipplejs": "^0.10.1"
},
"devDependencies": {
@ -1781,8 +1782,6 @@
"version": "7.23.8",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz",
"integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==",
"dev": true,
"peer": true,
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@ -2204,12 +2203,24 @@
"version": "20.11.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz",
"integrity": "sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==",
"dev": true,
"peer": true,
"dependencies": {
"undici-types": "~5.26.4"
}
},
"node_modules/@types/readable-stream": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.10.tgz",
"integrity": "sha512-AbUKBjcC8SHmImNi4yK2bbjogQlkFSg7shZCcicxPQapniOlajG8GCc39lvXzCWX4lLRRs7DM3VAeSlqmEVZUA==",
"dependencies": {
"@types/node": "*",
"safe-buffer": "~5.1.1"
}
},
"node_modules/@types/readable-stream/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -2227,6 +2238,14 @@
"dev": true,
"peer": true
},
"node_modules/@types/ws": {
"version": "8.5.10",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
"integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@vite-pwa/sveltekit": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@vite-pwa/sveltekit/-/sveltekit-0.3.0.tgz",
@ -2246,6 +2265,17 @@
"vite-plugin-pwa": ">=0.17.4 <1"
}
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"dependencies": {
"event-target-shim": "^5.0.0"
},
"engines": {
"node": ">=6.5"
}
},
"node_modules/acorn": {
"version": "8.11.3",
"dev": true,
@ -2480,9 +2510,27 @@
},
"node_modules/balanced-match": {
"version": "1.0.2",
"dev": true,
"license": "MIT"
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"dev": true,
@ -2491,9 +2539,18 @@
"node": ">=8"
}
},
"node_modules/bl": {
"version": "6.0.10",
"resolved": "https://registry.npmjs.org/bl/-/bl-6.0.10.tgz",
"integrity": "sha512-F14DFhDZfxtVm2FY0k9kG2lWAwzZkO9+jX3Ytuoy/V0E1/5LBuBzzQHXAjqpxXEDIpmTPZZf5GVIGPQcLxFpaA==",
"dependencies": {
"buffer": "^6.0.3",
"inherits": "^2.0.4",
"readable-stream": "^4.2.0"
}
},
"node_modules/brace-expansion": {
"version": "2.0.1",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@ -2541,12 +2598,33 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"peer": true
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"node_modules/builtin-modules": {
"version": "3.3.0",
@ -2721,6 +2799,11 @@
"node": ">= 6"
}
},
"node_modules/commist": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz",
"integrity": "sha512-4PIMoPniho+LqXmpS5d3NuGYncG6XWlkBSVGiWycL22dd42OYdUGil2CWuzklaJoNxyxUSpO4MKIBU94viWNAw=="
},
"node_modules/common-tags": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
@ -2738,6 +2821,33 @@
"dev": true,
"peer": true
},
"node_modules/concat-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
"engines": [
"node >= 6.0"
],
"dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.0.2",
"typedarray": "^0.0.6"
}
},
"node_modules/concat-stream/node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@ -2815,7 +2925,6 @@
},
"node_modules/debug": {
"version": "4.3.4",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "2.1.2"
@ -3089,6 +3198,22 @@
"node": ">=0.10.0"
}
},
"node_modules/event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"engines": {
"node": ">=6"
}
},
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
"engines": {
"node": ">=0.8.x"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@ -3129,6 +3254,18 @@
"dev": true,
"peer": true
},
"node_modules/fast-unique-numbers": {
"version": "8.0.13",
"resolved": "https://registry.npmjs.org/fast-unique-numbers/-/fast-unique-numbers-8.0.13.tgz",
"integrity": "sha512-7OnTFAVPefgw2eBJ1xj2PGGR9FwYzSUso9decayHgCDX4sJkHLdcsYTytTg+tYv+wKF3U8gJuSBz2jJpQV4u/g==",
"dependencies": {
"@babel/runtime": "^7.23.8",
"tslib": "^2.6.2"
},
"engines": {
"node": ">=16.1.0"
}
},
"node_modules/fastq": {
"version": "1.16.0",
"dev": true,
@ -3227,8 +3364,7 @@
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/fsevents": {
"version": "2.3.3",
@ -3505,6 +3641,57 @@
"node": ">= 0.4"
}
},
"node_modules/help-me": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz",
"integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==",
"dependencies": {
"glob": "^8.0.0",
"readable-stream": "^3.6.0"
}
},
"node_modules/help-me/node_modules/glob": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/help-me/node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/help-me/node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/idb": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz",
@ -3512,6 +3699,25 @@
"dev": true,
"peer": true
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/import-meta-resolve": {
"version": "4.0.0",
"dev": true,
@ -3525,7 +3731,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@ -3534,8 +3739,7 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/internal-slot": {
"version": "1.0.6",
@ -4025,6 +4229,15 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/js-sdsl"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -4178,7 +4391,6 @@
},
"node_modules/lru-cache": {
"version": "10.1.0",
"dev": true,
"license": "ISC",
"engines": {
"node": "14 || >=16.14"
@ -4250,6 +4462,14 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minipass": {
"version": "7.0.4",
"dev": true,
@ -4258,6 +4478,48 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mqtt": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-5.3.4.tgz",
"integrity": "sha512-nyhr2bnFtyiv68jV3yfR6eQtGcGs/jr2l3ETKXYc0amttsasXa1KgvETHRNRjfeDt/yc68IqoEjFzKkHpoQUPQ==",
"dependencies": {
"@types/readable-stream": "^4.0.5",
"@types/ws": "^8.5.9",
"commist": "^3.2.0",
"concat-stream": "^2.0.0",
"debug": "^4.3.4",
"help-me": "^4.2.0",
"lru-cache": "^10.0.1",
"minimist": "^1.2.8",
"mqtt": "^5.2.0",
"mqtt-packet": "^9.0.0",
"number-allocator": "^1.0.14",
"readable-stream": "^4.4.2",
"reinterval": "^1.1.0",
"rfdc": "^1.3.0",
"split2": "^4.2.0",
"worker-timers": "^7.0.78",
"ws": "^8.14.2"
},
"bin": {
"mqtt": "build/bin/mqtt.js",
"mqtt_pub": "build/bin/pub.js",
"mqtt_sub": "build/bin/sub.js"
},
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/mqtt-packet": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.0.tgz",
"integrity": "sha512-8v+HkX+fwbodsWAZIZTI074XIoxVBOmPeggQuDFCGg1SqNcC+uoRMWu7J6QlJPqIUIJXmjNYYHxBBLr1Y/Df4w==",
"dependencies": {
"bl": "^6.0.8",
"debug": "^4.3.4",
"process-nextick-args": "^2.0.1"
}
},
"node_modules/mri": {
"version": "1.2.0",
"dev": true,
@ -4276,7 +4538,6 @@
},
"node_modules/ms": {
"version": "2.1.2",
"dev": true,
"license": "MIT"
},
"node_modules/mz": {
@ -4332,6 +4593,15 @@
"node": ">=0.10.0"
}
},
"node_modules/number-allocator": {
"version": "1.0.14",
"resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.14.tgz",
"integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==",
"dependencies": {
"debug": "^4.3.1",
"js-sdsl": "4.3.0"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"dev": true,
@ -4391,7 +4661,6 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dev": true,
"dependencies": {
"wrappy": "1"
}
@ -4628,6 +4897,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@ -4730,6 +5012,21 @@
"pify": "^2.3.0"
}
},
"node_modules/readable-stream": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
"dependencies": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
"events": "^3.3.0",
"process": "^0.11.10",
"string_decoder": "^1.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/readdirp": {
"version": "3.6.0",
"dev": true,
@ -4764,9 +5061,7 @@
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"dev": true,
"peer": true
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/regenerator-transform": {
"version": "0.15.2",
@ -4837,6 +5132,11 @@
"jsesc": "bin/jsesc"
}
},
"node_modules/reinterval": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@ -4872,6 +5172,11 @@
"node": ">=0.10.0"
}
},
"node_modules/rfdc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
},
"node_modules/rollup": {
"version": "4.9.2",
"dev": true,
@ -4956,7 +5261,6 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
@ -4970,8 +5274,7 @@
"type": "consulting",
"url": "https://feross.org/support"
}
],
"peer": true
]
},
"node_modules/safe-regex-test": {
"version": "1.0.2",
@ -5155,6 +5458,22 @@
"dev": true,
"peer": true
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-width": {
"version": "5.1.2",
"dev": true,
@ -5623,6 +5942,11 @@
"dev": true,
"license": "Apache-2.0"
},
"node_modules/tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/type-fest": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz",
@ -5705,6 +6029,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"node_modules/unbox-primitive": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
@ -5724,9 +6053,7 @@
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true,
"peer": true
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
@ -5847,7 +6174,6 @@
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"dev": true,
"license": "MIT"
},
"node_modules/vite": {
@ -6424,6 +6750,37 @@
"workbox-core": "7.0.0"
}
},
"node_modules/worker-timers": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/worker-timers/-/worker-timers-7.1.1.tgz",
"integrity": "sha512-axtq83GwPqYwkQmQmei2abQ9cT7oSwmLw4lQCZ9VmMH9g4t4kuEF1Gw+tdnIJGHCiZ2QPDnr/+307bYx6tynLA==",
"dependencies": {
"@babel/runtime": "^7.23.8",
"tslib": "^2.6.2",
"worker-timers-broker": "^6.1.1",
"worker-timers-worker": "^7.0.65"
}
},
"node_modules/worker-timers-broker": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/worker-timers-broker/-/worker-timers-broker-6.1.1.tgz",
"integrity": "sha512-CTlDnkXAewtYvw5gOwVIc6UuIPcNHJrqWxBMhZbCWOmadvl20nPs9beAsXlaTEwW3G2KBpuKiSgkhBkhl3mxDA==",
"dependencies": {
"@babel/runtime": "^7.23.8",
"fast-unique-numbers": "^8.0.13",
"tslib": "^2.6.2",
"worker-timers-worker": "^7.0.65"
}
},
"node_modules/worker-timers-worker": {
"version": "7.0.65",
"resolved": "https://registry.npmjs.org/worker-timers-worker/-/worker-timers-worker-7.0.65.tgz",
"integrity": "sha512-Dl4nGONr8A8Fr+vQnH7Ee+o2iB480S1fBcyJYqnMyMwGRVyQZLZU+o91vbMvU1vHqiryRQmjXzzMYlh86wx+YQ==",
"dependencies": {
"@babel/runtime": "^7.23.8",
"tslib": "^2.6.2"
}
},
"node_modules/wrap-ansi": {
"version": "8.1.0",
"dev": true,
@ -6511,8 +6868,27 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"dev": true
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
"version": "8.16.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/yallist": {
"version": "3.1.1",

View File

@ -28,6 +28,7 @@
"type": "module",
"dependencies": {
"@floating-ui/dom": "1.5.4",
"mqtt": "^5.3.4",
"nipplejs": "^0.10.1"
}
}

View File

@ -0,0 +1,52 @@
<script>
export let deviceId;
import { getDrawerStore } from "@skeletonlabs/skeleton";
const drawerStore = getDrawerStore();
const settings = { id: deviceId };
function openDeviceSettings() {
drawerStore.open(settings);
}
import { localStorageStore } from '@skeletonlabs/skeleton';
const devicesStats = localStorageStore('devicesStats', []);
var online = false;
$: if ($devicesStats[deviceId]) {
online = $devicesStats[deviceId].connectionOk;
};
var imgSource;
if (deviceId != 3) {
imgSource = "/images/agv-blue.png";
} else {
imgSource = "/images/agv-yellow.png";
}
</script>
<article class="card mb-6 p-4 relative">
<img class="mb-2 px-4 py-14 {!online ? "opacity-50" : ""}" src="{imgSource}" alt="Device preview">
<div class="flex justify-between items-center">
<h2 class="text-2xl">{deviceId} #{deviceId}</h2>
<div class="flex gap-2">
<button type="button" class="btn-icon fill-dark-token bg-surface-200 dark:bg-surface-600" on:click={openDeviceSettings}>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="4" viewBox="0 0 128 512">
<!--!Font Awesome Pro 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.-->
<path d="M64 368a48 48 0 1 0 0 96 48 48 0 1 0 0-96zm0-160a48 48 0 1 0 0 96 48 48 0 1 0 0-96zM112 96A48 48 0 1 0 16 96a48 48 0 1 0 96 0z"/>
</svg>
</button>
</div>
</div>
{#if online}
<div class="badge variant-glass-surface dark:variant-filled-surface absolute top-4 right-4">
<div class="w-2 h-2 rounded-full bg-success-500"></div>
<span>Online</span>
</div>
{:else}
<div class="badge variant-glass-surface absolute top-4 right-4">
<div class="w-2 h-2 rounded-full bg-error-500"></div>
<span>Offline</span>
</div>
{/if}
</article>

View File

@ -2,81 +2,124 @@
import { onMount } from 'svelte';
import { Stepper, Step } from '@skeletonlabs/skeleton';
import { ListBox, ListBoxItem } from '@skeletonlabs/skeleton';
import { ProgressBar } from '@skeletonlabs/skeleton';
import { localStorageStore } from '@skeletonlabs/skeleton';
import { get } from 'svelte/store';
const devicesObj = localStorageStore('devicesObj', []);
const devicesList = localStorageStore('devicesList', []);
const deviceSetupShow = localStorageStore('deviceSetupShow', false);
var loadFoundDevices = false;
let selectedDevice = '0';
onMount(() => {
setTimeout(() => {
loadFoundDevices = true;
}, 3000);
});
function onAbortHandler() {
$deviceSetupShow = false;
}
function onCompleteHandler(e) {
$devicesObj.push(defaultDevice);
console.log($devicesObj);
$deviceSetupShow = false;
}
// add device to devicesList
let arr = $devicesList;
arr.push(selectedDevice);
$devicesList = arr;
var defaultDevice = {
id: selectedDevice,
title: "AGV device",
image: "/images/fts_first-render_minified.png",
stats: ""
// stop device setup
$deviceSetupShow = false;
}
var foundDevicesObj = [
{
id: "1",
title: "AGV device #1",
image: "/images/fts_first-render_minified.png",
image: "/images/agv-blue.png",
stats: ""
},
{
id: "2",
title: "AGV device #2",
image: "/images/fts_first-render_minified.png",
image: "/images/agv-blue.png",
stats: ""
},
{
id: "3",
title: "AGV device #3",
image: "/images/fts_first-render_minified.png",
image: "/images/agv-yellow.png",
stats: ""
},
{
id: "4",
title: "AGV device #4",
image: "/images/agv-blue.png",
stats: ""
},
];
import mqtt from "mqtt";
const connectedIds = localStorageStore('connectedIds', []);
$connectedIds = [];
var loadFoundDevices = false;
function searchDevices() {
let client = mqtt.connect("mqtt://sxl6.feba.me:9002", {"clientId": "app.craft.vin/setup"});
var collectingAnswers = true;
loadFoundDevices = false;
function onMessage(topic, message) {
if (collectingAnswers) {
if (topic.includes("connectionOk") && !$connectedIds.includes(topic.split("/")[1]) && message == "true") {
var list = $connectedIds;
list.push(topic.split("/")[1]);
$connectedIds = list;
}
}
}
client.subscribe("fts/+/receive/connectionOk");
client.on("message", onMessage);
setTimeout(() => {
collectingAnswers = false;
$connectedIds = $connectedIds.filter(val => !$devicesList.includes(val));
loadFoundDevices = true;
client.unsubscribe("fts/+/receive/connectionOk");
client.end();
client.removeListener("message", onMessage);
}, 6000);
}
onMount(() => {
searchDevices();
});
</script>
<div id="stepper-wrapper" class="fixed top-0 left-0 w-full h-full p-12 bg-slate-50 z-10">
<div id="stepper-wrapper" class="fixed top-0 left-0 w-full h-full p-12 bg-slate-200 z-10">
<Stepper on:complete={onCompleteHandler} class="h-full flex flex-col" regionContent="grow" buttonCompleteLabel="Add device" buttonNext='btn-lg variant-filled-primary' buttonBack='btn-lg variant-filled-surface' buttonComplete='btn-lg variant-filled-primary'>
<Step class="h-full flex flex-col" regionContent="grow" locked={selectedDevice == "0" ? true : false}>
<svelte:fragment slot="header">
<h1>Searching</h1>
<h1>Discovery</h1>
</svelte:fragment>
{#if !loadFoundDevices}
<p>Searching for devices in network ...</p>
<ProgressBar />
{:else}
<p>Found devices:</p>
<ListBox active="variant-filled-primary" spacing="space-y-2">
{#each foundDevicesObj as item}
<ListBoxItem bind:group={selectedDevice} name="medium" value="{item.id}">
<svelte:fragment slot="lead">
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512">
<!--!Font Awesome Pro 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.-->
<path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36H344.3c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36H167.7c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12H344.3c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM232 344V280H168c-13.3 0-24-10.7-24-24s10.7-24 24-24h64V168c0-13.3 10.7-24 24-24s24 10.7 24 24v64h64c13.3 0 24 10.7 24 24s-10.7 24-24 24H280v64c0 13.3-10.7 24-24 24s-24-10.7-24-24z"/>
</svg>
</svelte:fragment>
{item.title}
{#each $connectedIds as id}
<ListBoxItem bind:group={selectedDevice} name="medium" value="{id}" class="card mb-6 p-4 relative">
<img src="{foundDevicesObj[id - 1].image}" class="inline w-20" alt="">
AGV device #{id}
</ListBoxItem>
{/each}
<button type="button" class="btn btn-lg variant-ghost-surface w-full" on:click={() => {searchDevices()}}>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512">
<!--!Font Awesome Pro 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.-->
<path d="M472 224c13.3 0 24-10.7 24-24V56c0-13.3-10.7-24-24-24s-24 10.7-24 24v80.1l-20-23.5C387 63.4 325.1 32 256 32C132.3 32 32 132.3 32 256s100.3 224 224 224c50.4 0 97-16.7 134.4-44.8c10.6-8 12.7-23 4.8-33.6s-23-12.7-33.6-4.8C332.2 418.9 295.7 432 256 432c-97.2 0-176-78.8-176-176s78.8-176 176-176c54.3 0 102.9 24.6 135.2 63.4l.1 .2 0 0L418.9 176H328c-13.3 0-24 10.7-24 24s10.7 24 24 24H472z"/>
</svg>
<span>Search again</span>
</button>
</ListBox>
{/if}
<svelte:fragment slot="navigation">

View File

@ -26,6 +26,32 @@
import { localStorageStore } from '@skeletonlabs/skeleton';
const onboardingShow = localStorageStore('onboarding', true);
const devicesList = localStorageStore('devicesList', []);
const devicesStats = localStorageStore('devicesStats', []);
$devicesStats = [];
import mqtt from "mqtt";
let client = mqtt.connect("mqtt://sxl6.feba.me:9002", {"clientId": "app.craft.vin"});
const connectedIds = localStorageStore('connectedIds', []);
$connectedIds = [];
function onMessage(topic, message) {
let deviceId = topic.split("/")[1];
if ($devicesStats[deviceId]) {
topic = topic.split("/")[3];
message = message.toString();
$devicesStats[deviceId][topic] = message;
} else {
$devicesStats[deviceId] = {};
}
// console.log($devicesStats);
}
$: $devicesList.forEach(deviceId => {
client.subscribe("fts/" + deviceId + "/receive/#")
});
client.on("message", onMessage);
</script>
<main class="min-h-screen p-8 pb-32">
@ -40,11 +66,11 @@
{/if}
</main>
<Drawer position="right">
{#if $drawerStore.id === 'edit-device'}
{#if $drawerStore.id}
<div class="w-full h-full flex justify-center items-center">
<div class="text-center space-y-2">
<img class="mb-2 px-8 py-10" src="/images/fts_first-render_minified.png" alt="Device preview">
<h2 class="h2">AGV device</h2>
<img class="mb-2 px-8 py-10" src="/images/agv-blue.png" alt="Device preview">
<h2 class="h2">AGV device #{$drawerStore.id}</h2>
<span class="block">List of stats</span>
<button type="button" class="btn variant-filled-warning mr-2">
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 512 512">

View File

@ -1,58 +1,26 @@
<script>
import Device from "../../components/Device.svelte";
import DeviceSetup from "../../components/DeviceSetup.svelte";
import deviceImage from "./fts_first-render_minified.png";
var online = true;
var devicesList = ["AGV device #1", "AGV device #2", "AGV device #3"];
import { localStorageStore } from '@skeletonlabs/skeleton';
const devicesList = localStorageStore('devicesList', []);
const deviceSetupShow = localStorageStore('deviceSetupShow', false);
function startDeviceSetup() {
$deviceSetupShow = true;
}
import { getDrawerStore } from "@skeletonlabs/skeleton";
const drawerStore = getDrawerStore();
const settings = { id: 'edit-device' };
// drawerStore.open(settings);
function openDeviceSettings() {
drawerStore.open(settings);
}
</script>
<h1 class="text-6xl font-bold">
Devices
</h1>
{#each devicesList as device}
<article class="card mb-6 p-4 relative">
<img class="mb-2 px-4 py-14" src="{deviceImage}" alt="Device preview">
<div class="flex justify-between items-center">
<h2 class="text-2xl">{device}</h2>
<div class="flex gap-2">
<button type="button" class="btn-icon fill-dark-token bg-surface-200 dark:bg-surface-600" on:click={openDeviceSettings}>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="4" viewBox="0 0 128 512">
<!--!Font Awesome Pro 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.-->
<path d="M64 368a48 48 0 1 0 0 96 48 48 0 1 0 0-96zm0-160a48 48 0 1 0 0 96 48 48 0 1 0 0-96zM112 96A48 48 0 1 0 16 96a48 48 0 1 0 96 0z"/>
</svg>
</button>
</div>
</div>
{#if online}
<div class="badge variant-glass-surface dark:variant-filled-surface absolute top-4 right-4">
<div class="w-2 h-2 rounded-full bg-success-500"></div>
<span>Online</span>
</div>
{:else}
<div class="badge variant-glass-surface absolute top-4 right-4">
<div class="w-2 h-2 rounded-full bg-error-500"></div>
<span>Offline</span>
</div>
{/if}
</article>
{/each}
<h1 class="text-6xl font-bold">Devices</h1>
{#if $devicesList.length}
{#each $devicesList as deviceId}
<Device deviceId={deviceId} />
{/each}
{:else}
<p>No devices added</p>
{/if}
<button type="button" class="btn btn-lg variant-filled-primary w-full" on:click={startDeviceSetup}>
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" class="w-5 h-5" viewBox="0 0 512 512">
<!--!Font Awesome Pro 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2024 Fonticons, Inc.-->
@ -62,10 +30,4 @@
</button>
{#if $deviceSetupShow}
<DeviceSetup />
{/if}
<!-- <style lang="postcss">
svg {
@apply fill-gray-950;
}
</style> -->
{/if}