new mqtt server for tinygs
This commit is contained in:
267
server/package-lock.json
generated
267
server/package-lock.json
generated
@@ -11,6 +11,7 @@
|
|||||||
"@scalar/express-api-reference": "^0.10.4",
|
"@scalar/express-api-reference": "^0.10.4",
|
||||||
"@ztimson/utils": "^0.29.5",
|
"@ztimson/utils": "^0.29.5",
|
||||||
"adm-zip": "^0.5.17",
|
"adm-zip": "^0.5.17",
|
||||||
|
"aedes": "^1.1.2",
|
||||||
"better-sqlite3": "^12.11.1",
|
"better-sqlite3": "^12.11.1",
|
||||||
"cheerio": "^1.2.0",
|
"cheerio": "^1.2.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
@@ -90,6 +91,24 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "22.20.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.2.tgz",
|
||||||
|
"integrity": "sha512-xlvWf4Vs9n1PEVYwP1n4vvG07M6y8WgvJ2t0vbrWTmijsIHp1cS+uJ2kMIRdY3nHZK0nCYKrPeD171+SzF4/zw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/readable-stream": {
|
||||||
|
"version": "4.0.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.24.tgz",
|
||||||
|
"integrity": "sha512-NRvUNC/JFGPJvqdAfEve8oginbM6V08u5NzLWpG8MwA2kTPOLnqk+wpwuPT+mp3aUsxyuT6m2gnrPuHYCruzEg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ztimson/utils": {
|
"node_modules/@ztimson/utils": {
|
||||||
"version": "0.29.5",
|
"version": "0.29.5",
|
||||||
"resolved": "https://registry.npmjs.org/@ztimson/utils/-/utils-0.29.5.tgz",
|
"resolved": "https://registry.npmjs.org/@ztimson/utils/-/utils-0.29.5.tgz",
|
||||||
@@ -99,6 +118,18 @@
|
|||||||
"var-persist": "^1.0.1"
|
"var-persist": "^1.0.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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"event-target-shim": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
@@ -121,6 +152,66 @@
|
|||||||
"node": ">=12.0"
|
"node": ">=12.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/aedes": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/aedes/-/aedes-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-prT8Zr4JkqpJMb5rMlLrW54oRyKPNgpRgqrF6PWQedL4ju+1YIwzkraxr16Rm4QyEkpqmZUdOEkfGp7zaDd5Lw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"aedes-packet": "^4.0.1",
|
||||||
|
"aedes-persistence": "^10.3.1",
|
||||||
|
"mqemitter": "^7.1.0",
|
||||||
|
"mqtt-packet": "^9.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/aedes"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"aedes-persistence-level": "^9.1.2",
|
||||||
|
"aedes-persistence-mongodb": "^9.3.1",
|
||||||
|
"aedes-persistence-redis": "^11.2.1"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"aedes-persistence-level": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"aedes-persistence-mongodb": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"aedes-persistence-redis": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aedes-packet": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/aedes-packet/-/aedes-packet-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-PLjKJElXEYB66RzHhJCw0SrRLfSmGRbbg2mtO5t/6FAbFp8vC0cG5ErhvPvfa9iKBrKZwoluWLgn8doBU8sRAw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mqtt-packet": "^9.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aedes-persistence": {
|
||||||
|
"version": "10.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/aedes-persistence/-/aedes-persistence-10.3.1.tgz",
|
||||||
|
"integrity": "sha512-C/z0zLEXY9PkUH+7pz31H5gGzlQZxqhFONK1lt5VON0hiHXQq6tr4cSIAtFUVQ1kyUdd7SsfkeKLAECp3gjjpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"aedes-packet": "^4.0.1",
|
||||||
|
"qlobber": "^8.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/array-flatten": {
|
"node_modules/array-flatten": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
@@ -633,6 +724,24 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expand-template": {
|
"node_modules/expand-template": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
|
||||||
@@ -688,6 +797,16 @@
|
|||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fastparallel": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"reusify": "^1.0.4",
|
||||||
|
"xtend": "^4.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/file-uri-to-path": {
|
"node_modules/file-uri-to-path": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
@@ -1024,6 +1143,105 @@
|
|||||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/mqemitter": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mqemitter/-/mqemitter-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-GnBDNz3lxmllW201ne0mrmdy5tPOTnc79jjVcsfUa2LG2pUGeyGWVeiae6ZysfC/64XrYOqCKRAQYrB7pGyBVQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"fastparallel": "^2.4.1",
|
||||||
|
"qlobber": "^8.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mqtt-packet": {
|
||||||
|
"version": "9.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-9.0.2.tgz",
|
||||||
|
"integrity": "sha512-MvIY0B8/qjq7bKxdN1eD+nrljoeaai+qjLJgfRn3TiMuz0pamsIWY2bFODPZMSNmabsLANXsLl4EMoWvlaTZWA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bl": "^6.0.8",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"process-nextick-args": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mqtt-packet/node_modules/bl": {
|
||||||
|
"version": "6.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-6.1.6.tgz",
|
||||||
|
"integrity": "sha512-jLsPgN/YSvPUg9UX0Kd73CXpm2Psg9FxMeCSXnk3WBO3CMT10JMwijubhGfHCnFu6TPn1ei3b975dxv7K2pWVg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/readable-stream": "^4.0.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mqtt-packet/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"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mqtt-packet/node_modules/debug": {
|
||||||
|
"version": "4.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mqtt-packet/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/mqtt-packet/node_modules/readable-stream": {
|
||||||
|
"version": "4.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
|
||||||
|
"integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
@@ -1211,6 +1429,21 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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==",
|
||||||
|
"license": "MIT",
|
||||||
|
"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==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/proxy-addr": {
|
"node_modules/proxy-addr": {
|
||||||
"version": "2.0.7",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
@@ -1234,6 +1467,15 @@
|
|||||||
"once": "^1.3.1"
|
"once": "^1.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/qlobber": {
|
||||||
|
"version": "8.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/qlobber/-/qlobber-8.0.1.tgz",
|
||||||
|
"integrity": "sha512-O+Wd1chXj5YE1DwmD+ae0bXiSLehmnS3czlC1R9FL/Nt/3q8uMS1bIHmg2lJfCoiimCxClWM8AAuJrF0EvNiog==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.15.3",
|
"version": "6.15.3",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz",
|
||||||
@@ -1303,6 +1545,16 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/reusify": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"iojs": ">=1.0.0",
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@@ -1634,6 +1886,12 @@
|
|||||||
"node": ">=20.18.1"
|
"node": ">=20.18.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "6.21.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
|
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/unpipe": {
|
"node_modules/unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
@@ -1713,6 +1971,15 @@
|
|||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/xtend": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yaml": {
|
"node_modules/yaml": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"@scalar/express-api-reference": "^0.10.4",
|
"@scalar/express-api-reference": "^0.10.4",
|
||||||
"@ztimson/utils": "^0.29.5",
|
"@ztimson/utils": "^0.29.5",
|
||||||
"adm-zip": "^0.5.17",
|
"adm-zip": "^0.5.17",
|
||||||
|
"aedes": "^1.1.2",
|
||||||
"better-sqlite3": "^12.11.1",
|
"better-sqlite3": "^12.11.1",
|
||||||
"cheerio": "^1.2.0",
|
"cheerio": "^1.2.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ export function cfg() {
|
|||||||
ADSB_URL: process.env.ADSB_URL || '',
|
ADSB_URL: process.env.ADSB_URL || '',
|
||||||
TINYGS_URL: process.env.TINYGS_URL || '',
|
TINYGS_URL: process.env.TINYGS_URL || '',
|
||||||
TINYGS_AUTH: process.env.TINYGS_AUTH || '',
|
TINYGS_AUTH: process.env.TINYGS_AUTH || '',
|
||||||
|
TINYGS_MQTT_PORT: process.env.TINYGS_MQTT_PORT || 1883,
|
||||||
|
TINYGS_MQTT_USER: process.env.TINYGS_MQTT_USER || 'admin',
|
||||||
|
TINYGS_MQTT_PASS: process.env.TINYGS_MQTT_PASS || 'admin',
|
||||||
DB_HOST: process.env.DB_HOST || 'http://localhost:8428',
|
DB_HOST: process.env.DB_HOST || 'http://localhost:8428',
|
||||||
EMAIL: process.env.EMAIL,
|
EMAIL: process.env.EMAIL,
|
||||||
LATITUDE: parseFloat(process.env.LATITUDE || '0'),
|
LATITUDE: parseFloat(process.env.LATITUDE || '0'),
|
||||||
|
|||||||
@@ -1,69 +1,86 @@
|
|||||||
|
import {Aedes} from 'aedes';
|
||||||
|
import {createServer} from 'net';
|
||||||
import {cfg} from './config.mjs';
|
import {cfg} from './config.mjs';
|
||||||
import {isEqual} from '@ztimson/utils';
|
|
||||||
|
|
||||||
const HISTORY_LIMIT = 500;
|
const HISTORY_LIMIT = 500;
|
||||||
const POLL_MS = 5_000;
|
|
||||||
const TTL_MS = 60_000;
|
const TTL_MS = 60_000;
|
||||||
|
|
||||||
function parseWm(raw) {
|
|
||||||
const f = raw.replace(/<[^>]+>/g, '').split(',').map(s => s.trim());
|
|
||||||
const [latitude, longitude] = f[15].split('/').map(s => parseFloat(s));
|
|
||||||
const [az, el] = f[16].split('/').map(s => parseFloat(s));
|
|
||||||
return {
|
|
||||||
timestamp: Date.now(),
|
|
||||||
freqMHz: parseFloat(f[3]),
|
|
||||||
satellite: f[14],
|
|
||||||
latitude, longitude,
|
|
||||||
az, el,
|
|
||||||
packetRssi: parseFloat(f[21]),
|
|
||||||
packetSnr: parseFloat(f[22]),
|
|
||||||
freqError: parseFloat(f[23]),
|
|
||||||
crcOk: !/CRC ERROR/i.test(f[24]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const satellites = new Map();
|
const satellites = new Map();
|
||||||
|
|
||||||
function pruneStale() {
|
function pruneStale() {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
for (const [name, bucket] of satellites) {
|
for (const [key, bucket] of satellites) {
|
||||||
if (now - bucket.lastSeen > TTL_MS) satellites.delete(name);
|
if (now - bucket.lastSeen > TTL_MS) satellites.delete(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pollTinyGS() {
|
function safeJson(buf) {
|
||||||
const { TINYGS_URL, TINYGS_AUTH } = cfg();
|
try { return JSON.parse(buf.toString()); } catch { return null; }
|
||||||
try {
|
|
||||||
const raw = await fetch(TINYGS_URL + '/wm', {
|
|
||||||
headers: TINYGS_AUTH ? {Authorization: `Basic ${TINYGS_AUTH}`} : {}
|
|
||||||
}).then(r => r.text());
|
|
||||||
const reading = parseWm(raw);
|
|
||||||
if (!reading.satellite || reading.satellite === '-') return;
|
|
||||||
|
|
||||||
const key = reading.satellite + '-' + reading.freqMHz;
|
|
||||||
let bucket = satellites.get(key);
|
|
||||||
if (!bucket) {
|
|
||||||
bucket = { history: [], lastSeen: 0 };
|
|
||||||
satellites.set(key, bucket);
|
|
||||||
}
|
|
||||||
|
|
||||||
bucket.lastSeen = reading.timestamp;
|
|
||||||
if (!isEqual(bucket.history.at(-1), reading)) {
|
|
||||||
bucket.history.push(reading);
|
|
||||||
if (bucket.history.length > HISTORY_LIMIT) bucket.history.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
pruneStale();
|
|
||||||
} catch (err) {
|
|
||||||
console.error('[tinygs] poll failed', err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(pollTinyGS, POLL_MS);
|
/**
|
||||||
|
* Best-effort field mapping — adjust once real TinyGS payload shape is confirmed
|
||||||
|
* from the console logs. Unknown fields are kept under `raw` for inspection.
|
||||||
|
*/
|
||||||
|
function extractReading(topic, payload) {
|
||||||
|
const data = safeJson(payload) ?? {raw: payload.toString()};
|
||||||
|
return {
|
||||||
|
timestamp: Date.now(),
|
||||||
|
topic,
|
||||||
|
satellite: data.satellite ?? data.name ?? data.sat ?? 'unknown',
|
||||||
|
norad: data.norad ?? data.noradId ?? data.NORAD ?? null,
|
||||||
|
freqMHz: data.freq ?? data.frequency ?? null,
|
||||||
|
packetRssi: data.rssi ?? null,
|
||||||
|
packetSnr: data.snr ?? null,
|
||||||
|
freqError: data.frequency_error ?? data.freqError ?? null,
|
||||||
|
crcOk: data.crc_error !== undefined ? !data.crc_error : null,
|
||||||
|
raw: data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePacket(topic, payload) {
|
||||||
|
const reading = extractReading(topic, payload);
|
||||||
|
const key = reading.norad ? `${reading.satellite}-${reading.norad}` : reading.satellite;
|
||||||
|
|
||||||
|
let bucket = satellites.get(key);
|
||||||
|
if (!bucket) {
|
||||||
|
bucket = {history: [], lastSeen: 0};
|
||||||
|
satellites.set(key, bucket);
|
||||||
|
}
|
||||||
|
bucket.lastSeen = reading.timestamp;
|
||||||
|
bucket.history.push(reading);
|
||||||
|
if (bucket.history.length > HISTORY_LIMIT) bucket.history.shift();
|
||||||
|
|
||||||
|
pruneStale();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startTinyGSServer() {
|
||||||
|
const {TINYGS_MQTT_PORT = 1883, TINYGS_MQTT_USER, TINYGS_MQTT_PASS} = cfg();
|
||||||
|
const broker = await Aedes.createBroker();
|
||||||
|
const server = createServer(broker.handle);
|
||||||
|
|
||||||
|
if (TINYGS_MQTT_USER) {
|
||||||
|
broker.authenticate = (client, username, password, cb) => {
|
||||||
|
const ok = username === TINYGS_MQTT_USER && password?.toString() === TINYGS_MQTT_PASS;
|
||||||
|
if (!ok) console.warn(`[tinygs] rejected auth from ${client.id}`);
|
||||||
|
cb(null, ok);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
broker.on('publish', (packet, client) => {
|
||||||
|
if (!client || packet.topic.startsWith('$SYS')) return;
|
||||||
|
console.info(`[tinygs] ${packet.topic}`, packet.payload.toString().slice(0, 200));
|
||||||
|
handlePacket(packet.topic, packet.payload);
|
||||||
|
});
|
||||||
|
broker.on('client', client => console.info(`[tinygs] connected: ${client.id}`));
|
||||||
|
broker.on('clientDisconnect', client => console.info(`[tinygs] disconnected: ${client.id}`));
|
||||||
|
|
||||||
|
server.listen(TINYGS_MQTT_PORT, () => console.info(`🛜 MQTT broker - http://localhost:${TINYGS_MQTT_PORT}`));
|
||||||
|
}
|
||||||
|
|
||||||
export const getTinyGSData = () => {
|
export const getTinyGSData = () => {
|
||||||
pruneStale();
|
pruneStale();
|
||||||
return Array.from(satellites.entries()).map(([name, bucket]) => ({
|
return Array.from(satellites.values()).map(bucket => ({
|
||||||
...bucket.history.at(-1),
|
...bucket.history.at(-1),
|
||||||
history: bucket.history.slice(0, -1),
|
history: bucket.history.slice(0, -1),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {getADSBImage, getADSB, getADSBHistory, getADSBRange, initAircraftDb} fro
|
|||||||
import {fetchIcon} from './openweather.mjs';
|
import {fetchIcon} from './openweather.mjs';
|
||||||
import {getForecast, getWeatherCondition, forecastTTL} from './forecast.mjs';
|
import {getForecast, getWeatherCondition, forecastTTL} from './forecast.mjs';
|
||||||
import {dailyWeather, hourlyWeather} from './openmeteo.mjs';
|
import {dailyWeather, hourlyWeather} from './openmeteo.mjs';
|
||||||
import {getTinyGSData} from './sats.mjs';
|
import {getTinyGSData, startTinyGSServer} from './sats.mjs';
|
||||||
|
|
||||||
// ── Uncaught error handlers ───────────────────────────────────────────────────
|
// ── Uncaught error handlers ───────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -209,6 +209,7 @@ const c = cfg();
|
|||||||
setTimeout(getForecast, 1)
|
setTimeout(getForecast, 1)
|
||||||
setInterval(getForecast, forecastTTL)
|
setInterval(getForecast, forecastTTL)
|
||||||
await initAircraftDb();
|
await initAircraftDb();
|
||||||
|
await startTinyGSServer();
|
||||||
|
|
||||||
app.listen(c.PORT, () => {
|
app.listen(c.PORT, () => {
|
||||||
console.log(`⛅ Weather API — http://localhost:${c.PORT}`)
|
console.log(`⛅ Weather API — http://localhost:${c.PORT}`)
|
||||||
|
|||||||
Reference in New Issue
Block a user