Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6144b60541 | |||
| 42f5a37e4d | |||
| 2b4f9bb90c | |||
| 63d0b4d79a | |||
| d7675c0b6a | |||
| 1fc202c785 | |||
| 804d95d493 | |||
| 8925bbe343 | |||
| a64f0d93da | |||
| ac3b303b2e |
@@ -0,0 +1,14 @@
|
||||
### 2022.12.30
|
||||
- file system
|
||||
|
||||
### 2022.12.06
|
||||
- e-chart
|
||||
- mqtt
|
||||
- new page data-analysis
|
||||
|
||||
### 2022.11.30
|
||||
|
||||
- setup environment
|
||||
- vite config add path
|
||||
- import windicss
|
||||
- add vue-shim.d.ts file (TS2307)
|
||||
Generated
+288
-3
@@ -1315,6 +1315,30 @@
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
|
||||
},
|
||||
"bl": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer": "^5.5.0",
|
||||
"inherits": "^2.0.4",
|
||||
"readable-stream": "^3.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
@@ -1395,6 +1419,16 @@
|
||||
"update-browserslist-db": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"base64-js": "^1.3.1",
|
||||
"ieee754": "^1.1.13"
|
||||
}
|
||||
},
|
||||
"buffer-equal": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
|
||||
@@ -1555,6 +1589,16 @@
|
||||
"integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==",
|
||||
"dev": true
|
||||
},
|
||||
"commist": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz",
|
||||
"integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"leven": "^2.1.0",
|
||||
"minimist": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -2029,6 +2073,31 @@
|
||||
"readable-stream": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"duplexify": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz",
|
||||
"integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"end-of-stream": "^1.4.1",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.1.1",
|
||||
"stream-shift": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"earcut": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.3.tgz",
|
||||
@@ -2040,6 +2109,24 @@
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"dev": true
|
||||
},
|
||||
"echarts": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/echarts/-/echarts-5.4.0.tgz",
|
||||
"integrity": "sha512-uPsO9VRUIKAdFOoH3B0aNg7NRVdN7aM39/OjovjO9MwmWsAkfGyeXJhK+dbRi51iDrQWliXV60/XwLA7kg3z0w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "2.3.0",
|
||||
"zrender": "5.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.167",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.167.tgz",
|
||||
@@ -2052,6 +2139,15 @@
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"epic-spinners": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/epic-spinners/-/epic-spinners-2.0.0.tgz",
|
||||
@@ -2685,9 +2781,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
|
||||
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
@@ -2855,6 +2951,29 @@
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||
"dev": true
|
||||
},
|
||||
"help-me": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz",
|
||||
"integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.6",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"human-signals": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz",
|
||||
@@ -3027,6 +3146,12 @@
|
||||
"integrity": "sha512-L3BJStEf5NAqNuzrpfbN71dp43mYIcBUlCRea/vdyv5dW/AYa1d4bpelko4SHdY3I6eN9Wzyasxirj1/vv5kmg==",
|
||||
"dev": true
|
||||
},
|
||||
"js-sdsl": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
|
||||
"integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==",
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
@@ -3132,6 +3257,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"leven": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
|
||||
"dev": true
|
||||
},
|
||||
"levn": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
|
||||
@@ -3428,6 +3559,67 @@
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
|
||||
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
|
||||
},
|
||||
"mqtt": {
|
||||
"version": "4.3.7",
|
||||
"resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.3.7.tgz",
|
||||
"integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"commist": "^1.0.0",
|
||||
"concat-stream": "^2.0.0",
|
||||
"debug": "^4.1.1",
|
||||
"duplexify": "^4.1.1",
|
||||
"help-me": "^3.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"lru-cache": "^6.0.0",
|
||||
"minimist": "^1.2.5",
|
||||
"mqtt-packet": "^6.8.0",
|
||||
"number-allocator": "^1.0.9",
|
||||
"pump": "^3.0.0",
|
||||
"readable-stream": "^3.6.0",
|
||||
"reinterval": "^1.1.0",
|
||||
"rfdc": "^1.3.0",
|
||||
"split2": "^3.1.0",
|
||||
"ws": "^7.5.5",
|
||||
"xtend": "^4.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"concat-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^3.0.2",
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mqtt-packet": {
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz",
|
||||
"integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bl": "^4.0.2",
|
||||
"debug": "^4.1.1",
|
||||
"process-nextick-args": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
@@ -3504,6 +3696,16 @@
|
||||
"boolbase": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"number-allocator": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.12.tgz",
|
||||
"integrity": "sha512-sGB0qoQGmKimery9JubBQ9pQUr1V/LixJAk3Ygp7obZf6mpSXime8d7XHEobbIimkdZpgjkNlLt6G7LPEWFYWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.3.1",
|
||||
"js-sdsl": "4.1.4"
|
||||
}
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.12.2",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
|
||||
@@ -3721,6 +3923,16 @@
|
||||
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
|
||||
"integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"punycode": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||
@@ -3796,6 +4008,18 @@
|
||||
"resolved": "https://registry.npmjs.org/regression/-/regression-2.0.1.tgz",
|
||||
"integrity": "sha512-A4XYsc37dsBaNOgEjkJKzfJlE394IMmUPlI/p3TTI9u3T+2a+eox5Pr/CPUqF0eszeWZJPAc6QkroAhuUpWDJQ=="
|
||||
},
|
||||
"reinterval": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
|
||||
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==",
|
||||
"dev": true
|
||||
},
|
||||
"resize-detector": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/resize-detector/-/resize-detector-0.3.0.tgz",
|
||||
"integrity": "sha512-R/tCuvuOHQ8o2boRP6vgx8hXCCy87H1eY9V5imBYeVNyNVpuL9ciReSccLj2gDcax9+2weXy3bc8Vv+NRXeEvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
@@ -4026,6 +4250,28 @@
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
|
||||
},
|
||||
"split2": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
|
||||
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"readable-stream": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ssf": {
|
||||
"version": "0.11.2",
|
||||
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||
@@ -4073,6 +4319,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"stream-shift": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
|
||||
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
|
||||
"dev": true
|
||||
},
|
||||
"string-argv": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
|
||||
@@ -4352,6 +4604,16 @@
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.4.tgz",
|
||||
"integrity": "sha512-KP4lq9uSz0KZbaqCllRhnxMV3mYRsRWJfdsAhZyt5bV5O1RTpoeDptBRV9NOa/JgOpfaA9ane88VF7OjWNK/DA=="
|
||||
},
|
||||
"vue-echarts": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vue-echarts/-/vue-echarts-6.2.3.tgz",
|
||||
"integrity": "sha512-xHzUvgsgk/asJTcNa8iVVwoovZU3iEUHvmBa3bzbiP3Y6OMxM1YXsoWOKVmVVaUusGs4ob4pSwjwNy2FemAz9w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"resize-detector": "^0.3.0",
|
||||
"vue-demi": "^0.13.2"
|
||||
}
|
||||
},
|
||||
"vue-eslint-parser": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz",
|
||||
@@ -4512,6 +4774,12 @@
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"dev": true
|
||||
},
|
||||
"xlsx": {
|
||||
"version": "0.18.5",
|
||||
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
|
||||
@@ -4575,6 +4843,23 @@
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"zrender": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/zrender/-/zrender-5.4.0.tgz",
|
||||
"integrity": "sha512-rOS09Z2HSVGFs2dn/TuYk5BlCaZcVe8UDLLjj1ySYF828LATKKdxuakSZMvrDz54yiKPDYVfjdKqcX8Jky3BIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "2.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,16 +52,19 @@
|
||||
"@vue/eslint-config-prettier": "^7.0.0",
|
||||
"@vue/eslint-config-typescript": "^10.0.0",
|
||||
"autoprefixer": "^10.4.4",
|
||||
"echarts": "^5.4.0",
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.7.0",
|
||||
"husky": "^8.0.1",
|
||||
"lint-staged": "^13.0.1",
|
||||
"mqtt": "^4.3.7",
|
||||
"postcss": "^8.4.12",
|
||||
"prettier": "^2.6.2",
|
||||
"typescript": "^4.5.4",
|
||||
"vite": "^2.9.9",
|
||||
"vite-plugin-windicss": "^1.8.8",
|
||||
"vue-echarts": "^6.2.3",
|
||||
"vue-eslint-parser": "^8.3.0",
|
||||
"vue-tsc": "^1.0.10",
|
||||
"windicss": "^3.5.6"
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-card class="h-full">
|
||||
<va-card-content class="h-full w-full">
|
||||
<EChart ref="chart_ref" :option="option" :autoresize="true" />
|
||||
</va-card-content>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const option = ref({
|
||||
title: {
|
||||
text: 'Traffic Sources',
|
||||
left: 'center',
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{a} <br/>{b} : {c} ({d}%)',
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
data: ['Direct', 'Email', 'Ad Networks', 'Video Ads', 'Search Engines'],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Traffic Sources',
|
||||
type: 'pie',
|
||||
radius: '55%',
|
||||
center: ['50%', '60%'],
|
||||
data: [
|
||||
{ value: 335, name: 'Direct' },
|
||||
{ value: 310, name: 'Email' },
|
||||
{ value: 234, name: 'Ad Networks' },
|
||||
{ value: 135, name: 'Video Ads' },
|
||||
{ value: 1548, name: 'Search Engines' },
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const chart_ref = ref<HTMLElement | null>(null)
|
||||
onMounted(() => {
|
||||
console.log(chart_ref.value)
|
||||
})
|
||||
|
||||
return { option, chart_ref }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang=""></style>
|
||||
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-card class="h-full">
|
||||
<va-card-content>
|
||||
<va-select
|
||||
v-model="simpleSelectModel"
|
||||
:label="'Filter'"
|
||||
text-by="description"
|
||||
track-by="id"
|
||||
:options="simpleOptions"
|
||||
/>
|
||||
<va-button class="mt-2" @click="filterData">Start</va-button>
|
||||
<!-- <div v-if="simpleSelectModel.id === 1">
|
||||
<va-button>test</va-button>
|
||||
<va-input></va-input>
|
||||
</div> -->
|
||||
</va-card-content>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
emits: ['filter-data'],
|
||||
setup(props, { emit }) {
|
||||
const simpleSelectModel = ref({})
|
||||
const simpleOptions = ref([
|
||||
{
|
||||
id: 1,
|
||||
description: 'First option',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
description: 'Second option',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
description: 'Third option',
|
||||
},
|
||||
])
|
||||
const filterData = function () {
|
||||
emit('filter-data')
|
||||
}
|
||||
|
||||
return { props, simpleSelectModel, simpleOptions, filterData }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang=""></style>
|
||||
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<va-card class="">
|
||||
<div class="h-200px">
|
||||
<va-button @click="showModal">FILE</va-button>
|
||||
<Suspense>
|
||||
<FileModal ref="file_modal_ref"></FileModal>
|
||||
</Suspense>
|
||||
</div>
|
||||
</va-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import FileModal from '@/components/data-analysis/FileModal.vue'
|
||||
|
||||
// file modal control
|
||||
let file_modal_ref = ref<InstanceType<typeof FileModal> | null>(null)
|
||||
const showModal = function () {
|
||||
file_modal_ref.value?.showModal()
|
||||
}
|
||||
|
||||
defineExpose({ file_modal_ref, showModal })
|
||||
</script>
|
||||
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-modal v-model="show" :fixed-layout="true" size="large">
|
||||
<!-- File Container-->
|
||||
<div class="h-[75vh] w-[50vw]">
|
||||
<!-- Control Bar -->
|
||||
<div class="d-flex align-center">
|
||||
<va-input v-model="filter" placeholder="Filter..." class="mr-3" style="flex: 0 200px" clearable />
|
||||
<!-- <va-checkbox v-model="isFilterCaseSensitive" label="Case sensitive" /> -->
|
||||
<va-button-group class="mr-3">
|
||||
<va-button @click="changeFileView('time')">Time</va-button>
|
||||
<va-button @click="changeFileView('folder')">Folder</va-button>
|
||||
<va-button @click="changeFileView('project')">Project</va-button>
|
||||
</va-button-group>
|
||||
<va-button-group>
|
||||
<va-button @click="expandAll(true)">Expand</va-button>
|
||||
<va-button @click="expandAll(false)">Close</va-button>
|
||||
</va-button-group>
|
||||
</div>
|
||||
<!-- File Window-->
|
||||
<div class="grid grid-cols-4 gap-6">
|
||||
<!-- File View-->
|
||||
<div class="h-full col-span-3">
|
||||
<va-tree-view
|
||||
v-model:checked="selectedNodes"
|
||||
v-model:expanded="expanedNodes"
|
||||
:nodes="nodes"
|
||||
class="customizable-content"
|
||||
:filter="filter"
|
||||
:filter-method="customFilterMethod"
|
||||
:track-by="'idType'"
|
||||
:value-by="'idType'"
|
||||
selectable
|
||||
>
|
||||
<template #content="node">
|
||||
<div class="align-center">
|
||||
<va-icon v-if="node.type === 'Folder' && node.expanded === false" class="fas fa-folder" />
|
||||
<va-icon v-if="node.type === 'Folder' && node.expanded === true" class="fas fa-folder-open" />
|
||||
<va-icon v-if="node.type === 'MetaFile'" class="fas fa-file" />
|
||||
{{ node.name }}
|
||||
</div>
|
||||
</template>
|
||||
</va-tree-view>
|
||||
<!-- <p class="mt-4">Expanded nodes: {{ expanedNodes.join(',') || 'none' }}</p> -->
|
||||
<p class="mt-4">Selected nodes: {{ selectedNodes.join(',') || 'none' }}</p>
|
||||
</div>
|
||||
<!-- Channel & Group setting-->
|
||||
<div class="h-full col-span-1">XY</div>
|
||||
</div>
|
||||
</div>
|
||||
</va-modal>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { Ref, ref, computed } from 'vue'
|
||||
import { FileView, Project, MetaFile, Folder, Time } from '@/utils/file'
|
||||
|
||||
const customFilterMethod = computed(() => {
|
||||
return (node: Project | MetaFile, filterText: string, key: string) => {
|
||||
// console.log('customFilterMethod', node, filterText, key, node.name.includes(filterText))
|
||||
return node.name.includes(filterText)
|
||||
}
|
||||
})
|
||||
|
||||
// handling show modal
|
||||
let show = ref(false)
|
||||
const showModal = function () {
|
||||
show.value = !show.value
|
||||
}
|
||||
|
||||
// handling init file
|
||||
const fileView = new FileView()
|
||||
await fileView.appendChildren(1)
|
||||
let fileViewChildrenForNodes = fileView.getChildren()
|
||||
|
||||
// handling modal header
|
||||
const changeFileView = async function (view: string) {
|
||||
fileView.changeView(view)
|
||||
await fileView.appendChildren(1)
|
||||
fileViewChildrenForNodes = fileView.getChildren()
|
||||
nodes.value.length = 0
|
||||
nodes.value.push(...fileViewChildrenForNodes)
|
||||
expanedNodes.value.length = 0
|
||||
expanedNodes.value.push(nodes.value[0].idType)
|
||||
}
|
||||
|
||||
const expandAll = function (expandOrNot: boolean) {
|
||||
expanedNodes.value.length = 0
|
||||
if (!expandOrNot) return
|
||||
for (const node of nodes.value) {
|
||||
expanedNodes.value.push(node.idType)
|
||||
}
|
||||
}
|
||||
|
||||
// handling tree view
|
||||
const filter = ref('')
|
||||
const isFilterCaseSensitive = ref(false)
|
||||
const selectedNodes = ref([])
|
||||
const expanedNodes: Ref<(never | string)[]> = ref([])
|
||||
const nodes: Ref<(never | Project | Folder | Time | MetaFile)[]> = ref([])
|
||||
|
||||
nodes.value.push(...fileViewChildrenForNodes)
|
||||
expanedNodes.value.push(nodes.value[0].idType)
|
||||
console.log('nodes', nodes)
|
||||
|
||||
defineExpose({ show, showModal, nodes, expanedNodes, selectedNodes })
|
||||
</script>
|
||||
<style lang="scss"></style>
|
||||
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div>
|
||||
<va-card class="h-full">
|
||||
<va-card-content class="h-full w-full">
|
||||
<EChart ref="chart_ref" :option="option" :autoresize="true" :loading="loading" />
|
||||
</va-card-content>
|
||||
</va-card>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import LineChart from '@/data/echart/composables/LineChart'
|
||||
import { EChartsCoreOption } from 'echarts'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const loading = ref(false)
|
||||
const { chart_ref, option } = LineChart()
|
||||
|
||||
const setOption = function (option: EChartsCoreOption) {
|
||||
chart_ref.value?.setOption(option)
|
||||
}
|
||||
|
||||
const appendData = function (seriesIndex: number, data: Array<number | string>) {
|
||||
chart_ref.value?.appendData({
|
||||
seriesIndex: seriesIndex,
|
||||
data: data,
|
||||
})
|
||||
chart_ref.value?.resize()
|
||||
}
|
||||
|
||||
const markLine = function (
|
||||
seriesIndex: number,
|
||||
markLineIndex: number,
|
||||
header: string,
|
||||
value: number | Array<number> | string,
|
||||
) {
|
||||
chart_ref.value?.setOption({
|
||||
series: [
|
||||
{
|
||||
markLine: {
|
||||
data: [{ name: header, yAxis: value }],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
const startLoading = function () {
|
||||
loading.value = true
|
||||
}
|
||||
|
||||
const stopLoading = function () {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
startLoading,
|
||||
stopLoading,
|
||||
setOption,
|
||||
appendData,
|
||||
markLine,
|
||||
})
|
||||
</script>
|
||||
<style lang=""></style>
|
||||
@@ -0,0 +1,37 @@
|
||||
import MQTT from '@/utils/mqtt'
|
||||
import type { OnMessageCallback } from 'mqtt'
|
||||
import { onUnmounted, ref } from 'vue'
|
||||
|
||||
export default function useMqtt() {
|
||||
const PublicMqtt = ref<MQTT | null>(null)
|
||||
|
||||
const startMqtt = (val: string, callback: OnMessageCallback) => {
|
||||
// set mqtt topic
|
||||
PublicMqtt.value = new MQTT(val)
|
||||
// init mqtt
|
||||
PublicMqtt.value.init()
|
||||
// link mqtt
|
||||
PublicMqtt.value.link()
|
||||
getMessage(callback)
|
||||
}
|
||||
|
||||
const publish = (topic: string, message: string) => {
|
||||
PublicMqtt.value?.publish(topic, message)
|
||||
}
|
||||
|
||||
const getMessage = (callback: OnMessageCallback) => {
|
||||
// PublicMqtt.value?.client.on('message', callback);
|
||||
PublicMqtt.value?.get(callback)
|
||||
}
|
||||
onUnmounted(() => {
|
||||
if (PublicMqtt.value) {
|
||||
PublicMqtt.value.unsubscribes()
|
||||
PublicMqtt.value.over()
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
startMqtt,
|
||||
publish,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import axios, { Axios } from 'axios'
|
||||
|
||||
export const setBaseURL = function (baseURL: string) {
|
||||
if (baseURL) {
|
||||
axios.defaults.baseURL = `http://${baseURL}:3000`
|
||||
}
|
||||
}
|
||||
|
||||
setBaseURL(location.href.split('/')[2].split(':')[0])
|
||||
|
||||
export const getAxios = function (): Axios {
|
||||
return axios
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { EChartsOption } from 'echarts'
|
||||
import { generateLegend } from './legend'
|
||||
import { generateGrid } from './grid'
|
||||
import { generateXAxis } from './xAxis'
|
||||
import { generateYAxis } from './yAxis'
|
||||
import { generateTooltip } from './tooltip'
|
||||
import { generateSeries } from './series'
|
||||
import { generateDataZoom } from './datazoom'
|
||||
|
||||
export const generateChart = function (): EChartsOption {
|
||||
return {
|
||||
legend: generateLegend(),
|
||||
tooltip: generateTooltip(),
|
||||
grid: [generateGrid()],
|
||||
xAxis: [generateXAxis()],
|
||||
yAxis: [generateYAxis()],
|
||||
series: [generateSeries('')],
|
||||
dataZoom: generateDataZoom(),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { ref } from 'vue'
|
||||
import { ECharts } from 'echarts'
|
||||
import { generateChart } from '@/data/echart/chart'
|
||||
|
||||
export default function lineChart() {
|
||||
const chart_ref = ref<ECharts | null>(null)
|
||||
const option = generateChart()
|
||||
|
||||
return { option, chart_ref }
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { DataZoomComponentOption } from 'echarts'
|
||||
|
||||
export const generateDataZoom = function (): DataZoomComponentOption | DataZoomComponentOption[] {
|
||||
return [
|
||||
{
|
||||
show: true,
|
||||
realtime: true,
|
||||
start: 0,
|
||||
end: 100,
|
||||
xAxisIndex: [0, 1],
|
||||
},
|
||||
{
|
||||
type: 'inside',
|
||||
realtime: true,
|
||||
start: 0,
|
||||
end: 100,
|
||||
xAxisIndex: [0, 1],
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { TooltipComponentFormatterCallbackParams } from 'echarts'
|
||||
|
||||
export const generateFormatter = function (params: TooltipComponentFormatterCallbackParams): string {
|
||||
return String(params[0].value)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { GridComponentOption } from 'echarts'
|
||||
|
||||
export const generateGrid = function (): GridComponentOption {
|
||||
const index = 0
|
||||
const length = 1
|
||||
// const chartID = 1
|
||||
const _height = 82 / length - 2 + '%'
|
||||
const _top = index * (82 / length) + 1 + '%'
|
||||
const _left = '8%'
|
||||
const _right = '8%'
|
||||
|
||||
return {
|
||||
top: _top,
|
||||
height: _height,
|
||||
left: _left,
|
||||
right: _right,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { LegendComponentOption } from 'echarts'
|
||||
|
||||
export const generateLegend = function (): LegendComponentOption {
|
||||
return {
|
||||
type: 'scroll',
|
||||
data: [],
|
||||
// x: 'center',
|
||||
// y: '-10%',
|
||||
bottom: '0%',
|
||||
textStyle: {
|
||||
color: '#34495e',
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { MarkLineComponentOption } from 'echarts'
|
||||
|
||||
export const generateMarkLine = function (): MarkLineComponentOption {
|
||||
return {
|
||||
symbol: ['none', 'none'],
|
||||
// cannot create empty mark line data
|
||||
data: [
|
||||
// {
|
||||
// name: 'ceiling',
|
||||
// },
|
||||
// {
|
||||
// name: 'ground',
|
||||
// },
|
||||
// {
|
||||
// name: 'middle',
|
||||
// },
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { LineSeriesOption } from 'echarts'
|
||||
import { generateMarkLine } from './markLine'
|
||||
|
||||
export const generateSeries = function (name: string): LineSeriesOption {
|
||||
return {
|
||||
type: 'line',
|
||||
name: name || '',
|
||||
showSymbol: false,
|
||||
// silent: true,
|
||||
data: [],
|
||||
// markLine: {
|
||||
// data: [
|
||||
// {
|
||||
// // 固定起点的 x 像素位置,用于模拟一条指向最大值的水平线
|
||||
// name: 'test',
|
||||
// yAxis: '200',
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// xAxisIndex: xAxisIndex,
|
||||
// yAxisIndex: yAxisIndex,
|
||||
// AxisSource: [deviceID, channel], use it to get data stream from buffer
|
||||
// xAxisSource: xAxisSource,
|
||||
// yAxisSource: yAxisSource,
|
||||
animation: false,
|
||||
// dataXMax: null,
|
||||
// dataXMin: null,
|
||||
// dataYMax: null,
|
||||
// dataYMin: null,
|
||||
// itemStyle: {},
|
||||
// lineStyle: {
|
||||
// width: 1.5,
|
||||
// },
|
||||
markLine: generateMarkLine(),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { TooltipComponentOption } from 'echarts'
|
||||
import { generateFormatter } from './formatter'
|
||||
|
||||
export const generateTooltip = function (): TooltipComponentOption {
|
||||
return {
|
||||
padding: 10,
|
||||
backgroundColor: '#fff',
|
||||
borderColor: 'rgba(0, 0, 200, 0.2)',
|
||||
borderWidth: 1,
|
||||
borderRadius: 0,
|
||||
trigger: 'axis',
|
||||
hideDelay: 5000,
|
||||
formatter: generateFormatter,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { XAXisComponentOption } from 'echarts'
|
||||
|
||||
declare const AXIS_TYPES: {
|
||||
readonly value: 1
|
||||
readonly category: 1
|
||||
readonly time: 1
|
||||
readonly log: 1
|
||||
}
|
||||
declare type OptionAxisType = keyof typeof AXIS_TYPES
|
||||
|
||||
export const generateXAxis = function (
|
||||
type?: OptionAxisType,
|
||||
gridIndex?: number,
|
||||
// boundaryGap?: [string | number, string | number],
|
||||
): XAXisComponentOption {
|
||||
return {
|
||||
type: type || 'value',
|
||||
show: true,
|
||||
gridIndex: gridIndex || 0,
|
||||
// scale: true,
|
||||
// boundaryGap: true,
|
||||
axisLine: { onZero: false, lineStyle: { color: '#aaa' } },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
show: true,
|
||||
showMinLabel: false,
|
||||
showMaxLabel: false,
|
||||
color: '#34495e',
|
||||
},
|
||||
splitLine: { show: true, lineStyle: { color: '#aaa' } },
|
||||
min: 'dataMin',
|
||||
max: 'dataMax',
|
||||
// interval: undefined,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { YAXisComponentOption } from 'echarts'
|
||||
|
||||
declare const AXIS_TYPES: {
|
||||
readonly value: 1
|
||||
readonly category: 1
|
||||
readonly time: 1
|
||||
readonly log: 1
|
||||
}
|
||||
declare type OptionAxisType = keyof typeof AXIS_TYPES
|
||||
|
||||
export const generateYAxis = function (
|
||||
type?: OptionAxisType,
|
||||
gridIndex?: number,
|
||||
// boundaryGap?: [string | number, string | number],
|
||||
): YAXisComponentOption {
|
||||
return {
|
||||
type: type || 'value',
|
||||
show: true,
|
||||
gridIndex: gridIndex || 0,
|
||||
// scale: true,
|
||||
// boundaryGap: true,
|
||||
axisLine: { onZero: false, lineStyle: { color: '#aaa' } },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
show: true,
|
||||
showMinLabel: false,
|
||||
showMaxLabel: false,
|
||||
color: '#34495e',
|
||||
},
|
||||
splitLine: { show: true, lineStyle: { color: '#aaa' } },
|
||||
min: 'dataMin',
|
||||
max: 'dataMax',
|
||||
// interval: undefined,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { getAxios } from '@/data/axios'
|
||||
import { AxiosResponse } from 'axios'
|
||||
|
||||
const axios = getAxios()
|
||||
const FOLDER_TYPE = 'folder'
|
||||
|
||||
const getCollection = async function (
|
||||
parent: number,
|
||||
offset: number,
|
||||
limit: number,
|
||||
order: Array<string>,
|
||||
): Promise<AxiosResponse<any, any>> {
|
||||
let url = `api/file/collection/get?type=${FOLDER_TYPE}&`
|
||||
if (parent) url += `parent=${parent}&`
|
||||
if (offset) url += `offset=${offset}&`
|
||||
if (limit) url += `limit=${limit}&`
|
||||
if (order) {
|
||||
const _order = order?.join('-')
|
||||
url += `order=${_order}`
|
||||
}
|
||||
const result = await axios.get(url)
|
||||
return result
|
||||
}
|
||||
|
||||
const meta = {
|
||||
getCollection,
|
||||
}
|
||||
|
||||
export default meta
|
||||
@@ -0,0 +1,11 @@
|
||||
import meta from './meta'
|
||||
import collection from './collection'
|
||||
import project from './project'
|
||||
|
||||
const api = {
|
||||
collection,
|
||||
meta,
|
||||
project,
|
||||
}
|
||||
|
||||
export default api
|
||||
@@ -0,0 +1,51 @@
|
||||
import { getAxios } from '@/data/axios'
|
||||
import { AxiosResponse } from 'axios'
|
||||
|
||||
const FOLDER_TYPE = 'folder'
|
||||
|
||||
const axios = getAxios()
|
||||
|
||||
const getMetaWithTypeFolder = async function (
|
||||
parent: number,
|
||||
offset: number,
|
||||
limit: number,
|
||||
order: Array<string>,
|
||||
): Promise<AxiosResponse<any, any>> {
|
||||
let url = `api/file/meta/get?type=${FOLDER_TYPE}&`
|
||||
if (parent) url += `parent=${parent}&`
|
||||
if (offset) url += `offset=${offset}&`
|
||||
if (limit) url += `limit=${limit}&`
|
||||
if (order) {
|
||||
const _order = order?.join('-')
|
||||
url += `order=${_order}`
|
||||
}
|
||||
const result = await axios.get(url)
|
||||
return result
|
||||
}
|
||||
|
||||
const getMetaByTime = async function (time: string): Promise<AxiosResponse<any, any>> {
|
||||
const url = `api/file/meta/get?time=${time}`
|
||||
const result = await axios.get(url)
|
||||
return result
|
||||
}
|
||||
|
||||
const getMetaGroupByTime = async function (): Promise<AxiosResponse<any, any>> {
|
||||
const url = `api/file/meta/get?group=time`
|
||||
const result = await axios.get(url)
|
||||
return result
|
||||
}
|
||||
|
||||
const getMetaByProject = async function (uuid: string): Promise<AxiosResponse<any, any>> {
|
||||
const url = `api/file/meta/get?type=project&project=${uuid}`
|
||||
const result = await axios.get(url)
|
||||
return result
|
||||
}
|
||||
|
||||
const meta = {
|
||||
getMetaWithTypeFolder,
|
||||
getMetaByTime,
|
||||
getMetaByProject,
|
||||
getMetaGroupByTime,
|
||||
}
|
||||
|
||||
export default meta
|
||||
@@ -0,0 +1,17 @@
|
||||
import { getAxios } from '@/data/axios'
|
||||
import { AxiosResponse } from 'axios'
|
||||
|
||||
const axios = getAxios()
|
||||
|
||||
const getProjectGroup = async function (attrs?: Array<string>): Promise<AxiosResponse<any, any>> {
|
||||
let url = `api/project/report/get?`
|
||||
if (attrs) url += `attrs=${attrs.join('-')}`
|
||||
const result = await axios.get(url)
|
||||
return result
|
||||
}
|
||||
|
||||
const project = {
|
||||
getProjectGroup,
|
||||
}
|
||||
|
||||
export default project
|
||||
+38
@@ -9,6 +9,40 @@ import vuesticGlobalConfig from './services/vuestic-ui/global-config'
|
||||
import App from './App.vue'
|
||||
import 'virtual:windi.css'
|
||||
|
||||
// import ECharts modules
|
||||
import ECharts from 'vue-echarts'
|
||||
import { use } from 'echarts/core'
|
||||
// import ECharts modules manually to reduce bundle size
|
||||
import { CanvasRenderer } from 'echarts/renderers'
|
||||
import { LineChart, BarChart, PieChart } from 'echarts/charts'
|
||||
import {
|
||||
TitleComponent,
|
||||
LegendComponent,
|
||||
GridComponent,
|
||||
TooltipComponent,
|
||||
DataZoomComponent,
|
||||
MarkLineComponent,
|
||||
ToolboxComponent,
|
||||
BrushComponent,
|
||||
} from 'echarts/components'
|
||||
|
||||
use([
|
||||
CanvasRenderer,
|
||||
LineChart,
|
||||
PieChart,
|
||||
BarChart,
|
||||
GridComponent,
|
||||
TooltipComponent,
|
||||
TitleComponent,
|
||||
LegendComponent,
|
||||
DataZoomComponent,
|
||||
ToolboxComponent,
|
||||
BrushComponent,
|
||||
MarkLineComponent,
|
||||
])
|
||||
|
||||
import serverApi from '@/data/server-api'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(stores)
|
||||
@@ -16,6 +50,10 @@ app.use(router)
|
||||
app.use(i18n)
|
||||
app.use(createVuestic({ config: vuesticGlobalConfig }))
|
||||
|
||||
app.component('EChart', ECharts)
|
||||
|
||||
app.provide('server-api', serverApi)
|
||||
|
||||
if (import.meta.env.VITE_APP_GTM_ENABLED) {
|
||||
app.use(
|
||||
createGtm({
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="h-[88vh] grid grid-cols-3 gap-6">
|
||||
<div class="h-full col-span-1">
|
||||
<div class="h-1/3">
|
||||
<FileContainer class="h-9/10"></FileContainer>
|
||||
</div>
|
||||
<div class="h-2/3">
|
||||
<ControlPanel class="h-9/10" @filter-data="filterData"></ControlPanel>
|
||||
</div>
|
||||
</div>
|
||||
<LineChartContainer ref="linechart_ref" class="h-[50%] col-span-2"></LineChartContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import useMqtt from '@/composables/utils/useMqtt'
|
||||
import FileContainer from '@/components/data-analysis/FileContainer.vue'
|
||||
import ControlPanel from '@/components/data-analysis/ControlPanel.vue'
|
||||
import LineChartContainer from '@/components/data-analysis/LineChartContainer.vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
// mqtt init
|
||||
const { startMqtt, publish } = useMqtt()
|
||||
const controllerID = 'b8:27:eb:18:f8:cc'
|
||||
|
||||
// define subscribe and callback
|
||||
startMqtt(`${controllerID}/data_analysis/#`, (topic: string, message: ArrayBuffer) => {
|
||||
// [data, data, ceiling, ground]
|
||||
const msg = JSON.parse(message.toString())
|
||||
|
||||
// try draw line
|
||||
// msg.push(1500000, -1500000)
|
||||
|
||||
// reformat data
|
||||
const _msg = []
|
||||
for (let i = 0; i < msg[0].length; i++) {
|
||||
_msg.push([msg[0][i], msg[1][i]])
|
||||
}
|
||||
|
||||
// append Data
|
||||
linechart_ref.value?.appendData(0, _msg)
|
||||
|
||||
// stop loading
|
||||
linechart_ref.value?.stopLoading()
|
||||
|
||||
// draw line
|
||||
if (msg.length < 3) return true
|
||||
linechart_ref.value.setOption({
|
||||
series: [
|
||||
{
|
||||
markLine: {
|
||||
data: [{ yAxis: msg[2] }, { yAxis: msg[3] }],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
// reference
|
||||
const linechart_ref = ref()
|
||||
|
||||
// methods
|
||||
const filterData = function () {
|
||||
linechart_ref.value?.startLoading()
|
||||
publish(`${controllerID}_data_analysis/get_analysis_data`, JSON.stringify({}))
|
||||
}
|
||||
|
||||
defineExpose({ linechart_ref, filterData })
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
@@ -22,6 +22,11 @@ const routes: Array<RouteRecordRaw> = [
|
||||
path: 'dashboard',
|
||||
component: () => import('../pages/admin/dashboard/Dashboard.vue'),
|
||||
},
|
||||
{
|
||||
name: 'data-analysis',
|
||||
path: 'data-analysis',
|
||||
component: () => import('../pages/admin/data-analysis/DataAnalysis.vue'),
|
||||
},
|
||||
{
|
||||
name: 'statistics',
|
||||
path: 'statistics',
|
||||
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
interface collection {
|
||||
id: number
|
||||
name: string
|
||||
parent: object
|
||||
controller_id: number
|
||||
size: number
|
||||
type: string
|
||||
description: string
|
||||
deleted: bool
|
||||
}
|
||||
|
||||
export { collection }
|
||||
@@ -0,0 +1,355 @@
|
||||
import api from '@/data/server-api'
|
||||
|
||||
declare type FolderType = {
|
||||
file: number
|
||||
collection: number
|
||||
}
|
||||
|
||||
class FileView {
|
||||
children: Array<Project | Folder | Time | MetaFile>
|
||||
viewBy: string
|
||||
offset: number
|
||||
limit: number
|
||||
|
||||
constructor() {
|
||||
this.children = []
|
||||
this.viewBy = 'time'
|
||||
this.offset = 0
|
||||
this.limit = 20
|
||||
}
|
||||
|
||||
init() {
|
||||
this.children.length = 0
|
||||
this.offset = 0
|
||||
this.limit = 20
|
||||
}
|
||||
|
||||
changeView(viewBy: string) {
|
||||
this.viewBy = viewBy
|
||||
this.init()
|
||||
}
|
||||
|
||||
async appendChildren(id: number) {
|
||||
if (this.viewBy === 'folder') {
|
||||
// append children folder
|
||||
const folderResult = await this.getCollectionsFromServer(id)
|
||||
for (const _data of folderResult.rows) {
|
||||
const folder = new Folder(_data.id, _data.name)
|
||||
// console.log('folder', folder)
|
||||
await folder.init()
|
||||
this.children.push(folder)
|
||||
}
|
||||
} else if (this.viewBy == 'time') {
|
||||
const timeGroup = await this.getTimeGroupFromServer()
|
||||
for (const time in timeGroup) {
|
||||
const timeInstance = new Time(time, timeGroup[time]?.date)
|
||||
await timeInstance.appendChildren()
|
||||
this.children.push(timeInstance)
|
||||
}
|
||||
} else if (this.viewBy == 'project') {
|
||||
const projectGroup = await this.getProjectGroupFromServer(['id', 'name', 'uuid', 'created_at'])
|
||||
for (const project of projectGroup) {
|
||||
const projectInstance = new Project(project.id, project.name, project.uuid, project.created_at)
|
||||
await projectInstance.appendChildren()
|
||||
this.children.push(projectInstance)
|
||||
}
|
||||
}
|
||||
// console.log('children', this.children)
|
||||
}
|
||||
|
||||
async getCollectionsFromServer(id: number, order: string[] = ['id', 'desc']) {
|
||||
const result = await api.collection.getCollection(id, this.offset, this.limit, order)
|
||||
return result.data
|
||||
}
|
||||
|
||||
async getFilesByIdFromServer(id: number, order: string[] = ['id', 'desc']) {
|
||||
const result = await api.meta.getMetaWithTypeFolder(id, this.offset, this.limit, order)
|
||||
return result.data
|
||||
}
|
||||
|
||||
async getTimeGroupFromServer() {
|
||||
const result = await api.meta.getMetaGroupByTime()
|
||||
return result.data
|
||||
}
|
||||
|
||||
async getProjectGroupFromServer(attrs: string[]) {
|
||||
const result = await api.project.getProjectGroup(attrs)
|
||||
return result.data
|
||||
}
|
||||
|
||||
getChildren() {
|
||||
return this.children
|
||||
}
|
||||
}
|
||||
|
||||
class Time {
|
||||
id: string
|
||||
type: string
|
||||
idType: string
|
||||
name: string
|
||||
children: Array<Time | MetaFile>
|
||||
offset: number
|
||||
limit: number
|
||||
maxFiles: number
|
||||
|
||||
constructor(id: string, date: string) {
|
||||
this.id = id
|
||||
this.type = 'Time'
|
||||
this.idType = 'Time-' + id
|
||||
this.name = date
|
||||
this.children = []
|
||||
this.offset = 0
|
||||
this.limit = 20
|
||||
this.maxFiles = 0
|
||||
}
|
||||
|
||||
async getFilesFromServer(id: string) {
|
||||
const result = await api.meta.getMetaByTime(id)
|
||||
return result.data
|
||||
}
|
||||
|
||||
async appendChildren() {
|
||||
const metaFile = await this.getFilesFromServer(this.name)
|
||||
for (const _metaFile of metaFile) {
|
||||
const channels = _metaFile.channels === null ? _metaFile.channels : JSON.parse(_metaFile.channels)
|
||||
const meta = new MetaFile(
|
||||
_metaFile.id,
|
||||
_metaFile.uuid,
|
||||
_metaFile.name,
|
||||
channels,
|
||||
_metaFile.device,
|
||||
_metaFile.parameter_set,
|
||||
_metaFile.parent,
|
||||
_metaFile.raw_data,
|
||||
_metaFile.mini_data,
|
||||
_metaFile.size,
|
||||
_metaFile.time_duration,
|
||||
_metaFile.created_at,
|
||||
)
|
||||
this.children.push(meta)
|
||||
console.log('time', meta)
|
||||
}
|
||||
}
|
||||
|
||||
getChildren() {
|
||||
return this.children
|
||||
}
|
||||
}
|
||||
|
||||
class Project {
|
||||
id: string
|
||||
type: string
|
||||
idType: string
|
||||
name: string
|
||||
uuid: string
|
||||
created_at: Date
|
||||
children: Array<Project | MetaFile>
|
||||
offset: number
|
||||
limit: number
|
||||
maxFiles: number
|
||||
|
||||
constructor(id: string, name: string, uuid: string, created_at: Date) {
|
||||
this.id = id
|
||||
this.type = 'Project'
|
||||
this.idType = 'Project-' + id
|
||||
this.name = name
|
||||
this.uuid = uuid
|
||||
this.created_at = created_at
|
||||
this.children = []
|
||||
this.offset = 0
|
||||
this.limit = 20
|
||||
this.maxFiles = 0
|
||||
}
|
||||
|
||||
async getFilesFromServer(id: string) {
|
||||
const result = await api.meta.getMetaByProject(id)
|
||||
return result.data
|
||||
}
|
||||
|
||||
async appendChildren() {
|
||||
const metaFile = await this.getFilesFromServer(this.uuid)
|
||||
for (const _metaFile of metaFile) {
|
||||
const channels = _metaFile.channels === null ? _metaFile.channels : JSON.parse(_metaFile.channels)
|
||||
const meta = new MetaFile(
|
||||
_metaFile.id,
|
||||
_metaFile.uuid,
|
||||
_metaFile.name,
|
||||
channels,
|
||||
_metaFile.device,
|
||||
_metaFile.parameter_set,
|
||||
_metaFile.parent,
|
||||
_metaFile.raw_data,
|
||||
_metaFile.mini_data,
|
||||
_metaFile.size,
|
||||
_metaFile.time_duration,
|
||||
_metaFile.created_at,
|
||||
)
|
||||
this.children.push(meta)
|
||||
// console.log('project', meta)
|
||||
}
|
||||
}
|
||||
|
||||
getChildren() {
|
||||
return this.children
|
||||
}
|
||||
}
|
||||
|
||||
class Folder {
|
||||
id: number
|
||||
idType: string
|
||||
name: string
|
||||
children: Array<Folder | MetaFile>
|
||||
offset: FolderType
|
||||
limit: FolderType
|
||||
maxNumber: FolderType
|
||||
type: string
|
||||
|
||||
constructor(id: number, name: string) {
|
||||
this.id = id
|
||||
this.type = 'Folder'
|
||||
this.idType = 'Folder' + id
|
||||
this.name = name
|
||||
this.children = []
|
||||
this.offset = { file: 0, collection: 0 }
|
||||
this.limit = { file: 20, collection: 20 }
|
||||
this.maxNumber = { file: 0, collection: 0 }
|
||||
}
|
||||
|
||||
async init() {
|
||||
await this.appendChildren()
|
||||
}
|
||||
|
||||
async getFilesFromServer(id: number, offset: number, limit: number, order: Array<string> = ['id', 'desc']) {
|
||||
const result = await api.meta.getMetaWithTypeFolder(id, offset, limit, order)
|
||||
return result
|
||||
}
|
||||
|
||||
async getCollectionsFromServer(id: number, offset: number, limit: number, order: Array<string> = ['id', 'desc']) {
|
||||
const result = await api.collection.getCollection(id, offset, limit, order)
|
||||
return result
|
||||
}
|
||||
|
||||
async appendChildren() {
|
||||
// append children folder
|
||||
await this.appendFolder()
|
||||
// append children file
|
||||
await this.appendFile()
|
||||
}
|
||||
|
||||
async appendFolder() {
|
||||
const folder = await this.getCollectionsFromServer(this.id, this.offset.collection, this.limit.collection)
|
||||
for (const _data of folder.data.rows) {
|
||||
const folder = new Folder(_data.id, _data.name)
|
||||
await folder.appendChildren()
|
||||
this.children.push(folder)
|
||||
}
|
||||
this.maxNumber.collection = folder.data.count
|
||||
this.offset.collection += this.limit.collection
|
||||
}
|
||||
|
||||
async appendFile() {
|
||||
const metaFile = await this.getFilesFromServer(this.id, this.offset.file, this.limit.file)
|
||||
for (const _metaFile of metaFile.data.rows) {
|
||||
const channels = _metaFile.channels === null ? _metaFile.channels : JSON.parse(_metaFile.channels)
|
||||
const meta = new MetaFile(
|
||||
_metaFile.id,
|
||||
_metaFile.uuid,
|
||||
_metaFile.name,
|
||||
channels,
|
||||
_metaFile.device,
|
||||
_metaFile.parameter_set,
|
||||
_metaFile.parent,
|
||||
_metaFile.raw_data,
|
||||
_metaFile.mini_data,
|
||||
_metaFile.size,
|
||||
_metaFile.time_duration,
|
||||
_metaFile.created_at,
|
||||
)
|
||||
this.children.push(meta)
|
||||
// console.log('folder', meta)
|
||||
}
|
||||
this.maxNumber.file = metaFile.data.count
|
||||
this.offset.file += this.limit.file
|
||||
}
|
||||
|
||||
getChildren() {
|
||||
return this.children
|
||||
}
|
||||
}
|
||||
|
||||
class MetaFile {
|
||||
id: number
|
||||
idType: string
|
||||
uuid: string
|
||||
name: string
|
||||
channels: Array<number>
|
||||
device: Device
|
||||
parameter: any
|
||||
parent: object
|
||||
rawData: Array<Array<number>>
|
||||
miniData: Array<Array<number>>
|
||||
size: string
|
||||
time: string
|
||||
created: Date
|
||||
type: string
|
||||
|
||||
constructor(
|
||||
id: number,
|
||||
uuid: string,
|
||||
name: string,
|
||||
channels: Array<number>,
|
||||
parent: object,
|
||||
device: Device,
|
||||
parameter: any,
|
||||
rawData: Array<Array<number>>,
|
||||
miniData: Array<Array<number>>,
|
||||
size: string,
|
||||
time: string,
|
||||
created: Date,
|
||||
) {
|
||||
this.id = id
|
||||
this.type = 'MetaFile'
|
||||
this.idType = 'MetaFile-' + id
|
||||
this.uuid = uuid
|
||||
this.name = name
|
||||
this.channels = channels
|
||||
this.parent = parent
|
||||
this.device = device
|
||||
this.parameter = parameter
|
||||
this.rawData = rawData
|
||||
this.miniData = miniData
|
||||
this.size = size
|
||||
this.time = time
|
||||
this.created = created
|
||||
}
|
||||
|
||||
getMetaInfo() {
|
||||
return {
|
||||
id: this.id,
|
||||
uuid: this.uuid,
|
||||
name: this.name,
|
||||
channels: this.channels,
|
||||
parent: this.parent,
|
||||
device: this.device,
|
||||
parameter: this.parameter,
|
||||
rawData: this.rawData,
|
||||
miniData: this.miniData,
|
||||
size: this.size,
|
||||
time: this.time,
|
||||
created: this.created,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Device {
|
||||
id: number
|
||||
name: string
|
||||
version: string
|
||||
macAddress: string
|
||||
memoryBoard: number
|
||||
serialNumber: Array<number>
|
||||
libraryName: string
|
||||
libraryVersion: string
|
||||
}
|
||||
|
||||
export { FileView, Project, MetaFile, Folder, Time }
|
||||
@@ -0,0 +1,67 @@
|
||||
import type { MqttClient, OnMessageCallback } from 'mqtt'
|
||||
import * as mqtt from 'mqtt/dist/mqtt.min.js'
|
||||
|
||||
class MQTT {
|
||||
url: string
|
||||
topic: string
|
||||
client!: MqttClient
|
||||
constructor(topic: string) {
|
||||
this.topic = topic
|
||||
this.url = 'ws://192.168.2.1:8083'
|
||||
}
|
||||
|
||||
// init mqtt
|
||||
init() {
|
||||
const options = {
|
||||
clean: true,
|
||||
clientId: 'mqttjs_' + Math.random().toString(16).substring(2, 8),
|
||||
// password: '111',
|
||||
// username: '1111',
|
||||
connectTimeout: 4000,
|
||||
}
|
||||
this.client = mqtt.connect(this.url, options)
|
||||
this.client.on('error', (error: any) => {
|
||||
console.log(error)
|
||||
})
|
||||
this.client.on('reconnect', (error: Error) => {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
// unsubscribes
|
||||
unsubscribes() {
|
||||
this.client.unsubscribe(this.topic, (error: Error) => {
|
||||
if (!error) {
|
||||
console.log(this.topic, 'cancel subscribe success')
|
||||
} else {
|
||||
console.log(this.topic, 'cancel subscribe fail')
|
||||
}
|
||||
})
|
||||
}
|
||||
// subscribe
|
||||
link() {
|
||||
this.client.on('connect', () => {
|
||||
this.client.subscribe(this.topic, (error: any) => {
|
||||
if (!error) {
|
||||
console.log('subscribe success')
|
||||
} else {
|
||||
console.log('subscribe fail')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// publish
|
||||
publish(topic: string, message: string) {
|
||||
this.client.publish(topic, message)
|
||||
}
|
||||
|
||||
// message callback
|
||||
get(callback: OnMessageCallback) {
|
||||
this.client.on('message', callback)
|
||||
}
|
||||
// close client
|
||||
over() {
|
||||
this.client.end()
|
||||
}
|
||||
}
|
||||
export default MQTT
|
||||
Reference in New Issue
Block a user