Browse Source

initial v1.4.0

v1.4.0
sean.zhou 2 years ago
parent
commit
f3e92fa131
  1. 453
      package-lock.json
  2. 5
      package.json
  3. 58
      src/api/drc.ts
  4. 58
      src/api/drone-control/drone.ts
  5. 93
      src/api/drone-control/payload.ts
  6. 23
      src/api/wayline.ts
  7. 54
      src/components/GMap.vue
  8. 16
      src/components/devices/device-hms/DeviceHmsDrawer.vue
  9. 2
      src/components/devices/device-upgrade/DeviceFirmwareUpgrade.vue
  10. 4
      src/components/g-map/DeviceSettingBox.vue
  11. 10
      src/components/g-map/DockControlPanel.vue
  12. 34
      src/components/g-map/DroneControlInfoPanel.vue
  13. 756
      src/components/g-map/DroneControlPanel.vue
  14. 115
      src/components/g-map/DroneControlPopover.vue
  15. 71
      src/components/g-map/use-connect-mqtt.ts
  16. 0
      src/components/g-map/use-device-setting.ts
  17. 20
      src/components/g-map/use-dock-control.ts
  18. 61
      src/components/g-map/use-drone-control-mqtt-event.ts
  19. 97
      src/components/g-map/use-drone-control-ws-event.ts
  20. 40
      src/components/g-map/use-drone-control.ts
  21. 162
      src/components/g-map/use-manual-control.ts
  22. 132
      src/components/g-map/use-mqtt.ts
  23. 120
      src/components/g-map/use-payload-control.ts
  24. 3
      src/components/task/CreatePlan.vue
  25. 59
      src/components/task/TaskPanel.vue
  26. 2
      src/event-bus/index.ts
  27. 3
      src/hooks/use-g-map-tsa.ts
  28. 12
      src/mqtt/config.ts
  29. 117
      src/mqtt/index.ts
  30. 6
      src/pages/page-web/projects/Firmwares.vue
  31. 17
      src/pages/page-web/projects/devices.vue
  32. 2
      src/pages/page-web/projects/dock.vue
  33. 5
      src/pages/page-web/projects/livestream.vue
  34. 43
      src/pages/page-web/projects/tsa.vue
  35. 9
      src/pages/page-web/projects/workspace.vue
  36. 4
      src/shims-mqtt.d.ts
  37. 22
      src/store/index.ts
  38. 21
      src/types/device-cmd.ts
  39. 103
      src/types/device.ts
  40. 71
      src/types/drc.ts
  41. 68
      src/types/drone-control.ts
  42. 9
      src/types/enums.ts
  43. 71
      src/types/live-stream.ts
  44. 6
      src/types/task.ts
  45. 189
      yarn.lock

453
package-lock.json generated

@ -15,7 +15,9 @@ @@ -15,7 +15,9 @@
"agora-rtc-sdk-ng": "^4.12.1",
"ant-design-vue": "^2.2.8",
"axios": "^0.21.1",
"eventemitter3": "^5.0.0",
"mitt": "^3.0.0",
"mqtt": "^4.3.7",
"query-string": "^7.0.1",
"reconnecting-websocket": "^4.4.0",
"vconsole": "^3.8.1",
@ -1535,6 +1537,11 @@ @@ -1535,6 +1537,11 @@
"node": ">=0.10.0"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"node_modules/big-integer": {
"version": "1.6.51",
"resolved": "https://registry.npmmirror.com/big-integer/download/big-integer-1.6.51.tgz",
@ -1576,6 +1583,16 @@ @@ -1576,6 +1583,16 @@
"node": ">=8"
}
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz",
@ -1635,6 +1652,20 @@ @@ -1635,6 +1652,20 @@
"url": "https://opencollective.com/browserslist"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"node_modules/buffer-indexof-polyfill": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/buffer-indexof-polyfill/download/buffer-indexof-polyfill-1.0.2.tgz",
@ -2000,6 +2031,15 @@ @@ -2000,6 +2031,15 @@
"node": ">= 10"
}
},
"node_modules/commist": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/commist/-/commist-1.1.0.tgz",
"integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
"dependencies": {
"leven": "^2.1.0",
"minimist": "^1.1.0"
}
},
"node_modules/component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz",
@ -2019,6 +2059,20 @@ @@ -2019,6 +2059,20 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"license": "MIT"
},
"node_modules/concat-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/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/constant-case": {
"version": "3.0.4",
"resolved": "https://registry.npm.taobao.org/constant-case/download/constant-case-3.0.4.tgz?cache=0&sync_timestamp=1606867325763&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconstant-case%2Fdownload%2Fconstant-case-3.0.4.tgz",
@ -2467,6 +2521,17 @@ @@ -2467,6 +2521,17 @@
"safe-buffer": "~5.1.0"
}
},
"node_modules/duplexify": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/duplexify/-/duplexify-4.1.2.tgz",
"integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==",
"dependencies": {
"end-of-stream": "^1.4.1",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1",
"stream-shift": "^1.0.0"
}
},
"node_modules/electron-to-chromium": {
"version": "1.4.43",
"resolved": "https://registry.npmmirror.com/electron-to-chromium/download/electron-to-chromium-1.4.43.tgz",
@ -2490,6 +2555,14 @@ @@ -2490,6 +2555,14 @@
"node": ">= 4"
}
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/enquirer": {
"version": "2.3.6",
"resolved": "https://registry.npm.taobao.org/enquirer/download/enquirer-2.3.6.tgz",
@ -3421,6 +3494,11 @@ @@ -3421,6 +3494,11 @@
"node": ">= 0.6"
}
},
"node_modules/eventemitter3": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.0.tgz",
"integrity": "sha512-riuVbElZZNXLeLEoprfNYoDSwTBRR44X3mnhdI1YcnENpWTCsTTVZ2zFuqQcpoyqPQIUXdiPEU0ECAq0KQRaHg=="
},
"node_modules/expand-brackets": {
"version": "2.1.4",
"resolved": "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz",
@ -3745,7 +3823,6 @@ @@ -3745,7 +3823,6 @@
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true,
"license": "ISC"
},
"node_modules/fsevents": {
@ -3858,7 +3935,6 @@ @@ -3858,7 +3935,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/glob/download/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
@ -4120,6 +4196,15 @@ @@ -4120,6 +4196,15 @@
"dev": true,
"license": "0BSD"
},
"node_modules/help-me": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/help-me/-/help-me-3.0.0.tgz",
"integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==",
"dependencies": {
"glob": "^7.1.6",
"readable-stream": "^3.6.0"
}
},
"node_modules/htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmmirror.com/htmlparser2/download/htmlparser2-3.10.1.tgz?cache=0&sync_timestamp=1636640933377&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-3.10.1.tgz",
@ -4135,6 +4220,11 @@ @@ -4135,6 +4220,11 @@
"readable-stream": "^3.1.1"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"node_modules/ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmmirror.com/ignore/download/ignore-5.2.0.tgz",
@ -4196,7 +4286,6 @@ @@ -4196,7 +4286,6 @@
"version": "1.0.6",
"resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"license": "ISC",
"dependencies": {
"once": "^1.3.0",
@ -4207,7 +4296,6 @@ @@ -4207,7 +4296,6 @@
"version": "2.0.4",
"resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz",
"integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=",
"dev": true,
"license": "ISC"
},
"node_modules/internal-slot": {
@ -4611,6 +4699,11 @@ @@ -4611,6 +4699,11 @@
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.3.0.tgz",
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz?cache=0&sync_timestamp=1619345098261&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fjs-tokens%2Fdownload%2Fjs-tokens-4.0.0.tgz",
@ -4692,6 +4785,14 @@ @@ -4692,6 +4785,14 @@
"node": ">=0.10.0"
}
},
"node_modules/leven": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/leven/-/leven-2.1.0.tgz",
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npm.taobao.org/levn/download/levn-0.4.1.tgz",
@ -4801,7 +4902,6 @@ @@ -4801,7 +4902,6 @@
"version": "6.0.0",
"resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-6.0.0.tgz?cache=0&sync_timestamp=1599054167787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flru-cache%2Fdownload%2Flru-cache-6.0.0.tgz",
"integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=",
"dev": true,
"license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
@ -4979,6 +5079,48 @@ @@ -4979,6 +5079,48 @@
"node": "*"
}
},
"node_modules/mqtt": {
"version": "4.3.7",
"resolved": "https://registry.npmmirror.com/mqtt/-/mqtt-4.3.7.tgz",
"integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==",
"dependencies": {
"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"
},
"bin": {
"mqtt": "bin/mqtt.js",
"mqtt_pub": "bin/pub.js",
"mqtt_sub": "bin/sub.js"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/mqtt-packet": {
"version": "6.10.0",
"resolved": "https://registry.npmmirror.com/mqtt-packet/-/mqtt-packet-6.10.0.tgz",
"integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==",
"dependencies": {
"bl": "^4.0.2",
"debug": "^4.1.1",
"process-nextick-args": "^2.0.1"
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/ms/download/ms-2.1.2.tgz",
@ -5159,6 +5301,15 @@ @@ -5159,6 +5301,15 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/number-allocator": {
"version": "1.0.14",
"resolved": "https://registry.npmmirror.com/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",
"resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
@ -5374,7 +5525,6 @@ @@ -5374,7 +5525,6 @@
"version": "1.4.0",
"resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"license": "ISC",
"dependencies": {
"wrappy": "1"
@ -5525,7 +5675,6 @@ @@ -5525,7 +5675,6 @@
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@ -5695,7 +5844,6 @@ @@ -5695,7 +5844,6 @@
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz",
"integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=",
"dev": true,
"license": "MIT"
},
"node_modules/progress": {
@ -5708,6 +5856,15 @@ @@ -5708,6 +5856,15 @@
"node": ">=0.4.0"
}
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/punycode": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz",
@ -5760,7 +5917,6 @@ @@ -5760,7 +5917,6 @@
"version": "3.6.0",
"resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz",
"integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
"dev": true,
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
@ -5873,6 +6029,11 @@ @@ -5873,6 +6029,11 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
"node_modules/reinterval": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/reinterval/-/reinterval-1.1.0.tgz",
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
},
"node_modules/repeat-element": {
"version": "1.1.4",
"resolved": "https://registry.nlark.com/repeat-element/download/repeat-element-1.1.4.tgz",
@ -5963,6 +6124,11 @@ @@ -5963,6 +6124,11 @@
"node": ">=0.10.0"
}
},
"node_modules/rfdc": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz",
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/rimraf/download/rimraf-3.0.2.tgz",
@ -6541,6 +6707,14 @@ @@ -6541,6 +6707,14 @@
"node": ">=0.10.0"
}
},
"node_modules/split2": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/split2/-/split2-3.2.2.tgz",
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
"dependencies": {
"readable-stream": "^3.0.0"
}
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz",
@ -6649,6 +6823,11 @@ @@ -6649,6 +6823,11 @@
"node": ">=0.10.0"
}
},
"node_modules/stream-shift": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/stream-shift/-/stream-shift-1.0.1.tgz",
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
},
"node_modules/strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-2.0.0.tgz",
@ -6662,7 +6841,6 @@ @@ -6662,7 +6841,6 @@
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.3.0.tgz",
"integrity": "sha1-QvEUWUpGzxqOMLCoT1bHjD7awh4=",
"dev": true,
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.2.0"
@ -6672,7 +6850,6 @@ @@ -6672,7 +6850,6 @@
"version": "5.2.1",
"resolved": "https://registry.nlark.com/safe-buffer/download/safe-buffer-5.2.1.tgz",
"integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=",
"dev": true,
"funding": [
{
"type": "github",
@ -7343,6 +7520,11 @@ @@ -7343,6 +7520,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"node_modules/typescript": {
"version": "4.5.4",
"resolved": "https://registry.npmmirror.com/typescript/download/typescript-4.5.4.tgz",
@ -7577,7 +7759,6 @@ @@ -7577,7 +7759,6 @@
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true,
"license": "MIT"
},
"node_modules/v8-compile-cache": {
@ -7970,14 +8151,40 @@ @@ -7970,14 +8151,40 @@
"version": "1.0.2",
"resolved": "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true,
"license": "ISC"
},
"node_modules/ws": {
"version": "7.5.9",
"resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.9.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"engines": {
"node": ">=8.3.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"engines": {
"node": ">=0.4"
}
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz",
"integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=",
"dev": true,
"license": "ISC"
}
},
@ -9002,6 +9209,11 @@ @@ -9002,6 +9209,11 @@
}
}
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"big-integer": {
"version": "1.6.51",
"resolved": "https://registry.npmmirror.com/big-integer/download/big-integer-1.6.51.tgz",
@ -9030,6 +9242,16 @@ @@ -9030,6 +9242,16 @@
"integrity": "sha1-dfUC7q+f/eQvyYgpZFvk6na9ni0=",
"devOptional": true
},
"bl": {
"version": "4.1.0",
"resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"requires": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz",
@ -9071,6 +9293,20 @@ @@ -9071,6 +9293,20 @@
"picocolors": "^1.0.0"
}
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"buffer-indexof-polyfill": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/buffer-indexof-polyfill/download/buffer-indexof-polyfill-1.0.2.tgz",
@ -9354,6 +9590,15 @@ @@ -9354,6 +9590,15 @@
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true
},
"commist": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/commist/-/commist-1.1.0.tgz",
"integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==",
"requires": {
"leven": "^2.1.0",
"minimist": "^1.1.0"
}
},
"component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz",
@ -9370,6 +9615,17 @@ @@ -9370,6 +9615,17 @@
"resolved": "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"concat-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/concat-stream/-/concat-stream-2.0.0.tgz",
"integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
"requires": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.0.2",
"typedarray": "^0.0.6"
}
},
"constant-case": {
"version": "3.0.4",
"resolved": "https://registry.npm.taobao.org/constant-case/download/constant-case-3.0.4.tgz?cache=0&sync_timestamp=1606867325763&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconstant-case%2Fdownload%2Fconstant-case-3.0.4.tgz",
@ -9700,6 +9956,17 @@ @@ -9700,6 +9956,17 @@
}
}
},
"duplexify": {
"version": "4.1.2",
"resolved": "https://registry.npmmirror.com/duplexify/-/duplexify-4.1.2.tgz",
"integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==",
"requires": {
"end-of-stream": "^1.4.1",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1",
"stream-shift": "^1.0.0"
}
},
"electron-to-chromium": {
"version": "1.4.43",
"resolved": "https://registry.npmmirror.com/electron-to-chromium/download/electron-to-chromium-1.4.43.tgz",
@ -9717,6 +9984,14 @@ @@ -9717,6 +9984,14 @@
"integrity": "sha1-VXBmIEatKeLpFucariYKvf9Pang=",
"dev": true
},
"end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"requires": {
"once": "^1.4.0"
}
},
"enquirer": {
"version": "2.3.6",
"resolved": "https://registry.npm.taobao.org/enquirer/download/enquirer-2.3.6.tgz",
@ -10310,6 +10585,11 @@ @@ -10310,6 +10585,11 @@
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
"dev": true
},
"eventemitter3": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.0.tgz",
"integrity": "sha512-riuVbElZZNXLeLEoprfNYoDSwTBRR44X3mnhdI1YcnENpWTCsTTVZ2zFuqQcpoyqPQIUXdiPEU0ECAq0KQRaHg=="
},
"expand-brackets": {
"version": "2.1.4",
"resolved": "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz",
@ -10545,8 +10825,7 @@ @@ -10545,8 +10825,7 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.3.2",
@ -10624,7 +10903,6 @@ @@ -10624,7 +10903,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/glob/download/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -10806,6 +11084,15 @@ @@ -10806,6 +11084,15 @@
}
}
},
"help-me": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/help-me/-/help-me-3.0.0.tgz",
"integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==",
"requires": {
"glob": "^7.1.6",
"readable-stream": "^3.6.0"
}
},
"htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmmirror.com/htmlparser2/download/htmlparser2-3.10.1.tgz?cache=0&sync_timestamp=1636640933377&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-3.10.1.tgz",
@ -10820,6 +11107,11 @@ @@ -10820,6 +11107,11 @@
"readable-stream": "^3.1.1"
}
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmmirror.com/ignore/download/ignore-5.2.0.tgz",
@ -10858,7 +11150,6 @@ @@ -10858,7 +11150,6 @@
"version": "1.0.6",
"resolved": "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@ -10867,8 +11158,7 @@ @@ -10867,8 +11158,7 @@
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz",
"integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=",
"dev": true
"integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w="
},
"internal-slot": {
"version": "1.0.3",
@ -11132,6 +11422,11 @@ @@ -11132,6 +11422,11 @@
"integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==",
"dev": true
},
"js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.3.0.tgz",
"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz?cache=0&sync_timestamp=1619345098261&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fjs-tokens%2Fdownload%2Fjs-tokens-4.0.0.tgz",
@ -11188,6 +11483,11 @@ @@ -11188,6 +11483,11 @@
"integrity": "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=",
"dev": true
},
"leven": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/leven/-/leven-2.1.0.tgz",
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA=="
},
"levn": {
"version": "0.4.1",
"resolved": "https://registry.npm.taobao.org/levn/download/levn-0.4.1.tgz",
@ -11276,7 +11576,6 @@ @@ -11276,7 +11576,6 @@
"version": "6.0.0",
"resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-6.0.0.tgz?cache=0&sync_timestamp=1599054167787&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flru-cache%2Fdownload%2Flru-cache-6.0.0.tgz",
"integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=",
"dev": true,
"requires": {
"yallist": "^4.0.0"
}
@ -11401,6 +11700,40 @@ @@ -11401,6 +11700,40 @@
"resolved": "https://registry.npmmirror.com/moment/download/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"mqtt": {
"version": "4.3.7",
"resolved": "https://registry.npmmirror.com/mqtt/-/mqtt-4.3.7.tgz",
"integrity": "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw==",
"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"
}
},
"mqtt-packet": {
"version": "6.10.0",
"resolved": "https://registry.npmmirror.com/mqtt-packet/-/mqtt-packet-6.10.0.tgz",
"integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==",
"requires": {
"bl": "^4.0.2",
"debug": "^4.1.1",
"process-nextick-args": "^2.0.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmmirror.com/ms/download/ms-2.1.2.tgz",
@ -11536,6 +11869,15 @@ @@ -11536,6 +11869,15 @@
"boolbase": "^1.0.0"
}
},
"number-allocator": {
"version": "1.0.14",
"resolved": "https://registry.npmmirror.com/number-allocator/-/number-allocator-1.0.14.tgz",
"integrity": "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA==",
"requires": {
"debug": "^4.3.1",
"js-sdsl": "4.3.0"
}
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
@ -11688,7 +12030,6 @@ @@ -11688,7 +12030,6 @@
"version": "1.4.0",
"resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
@ -11809,8 +12150,7 @@ @@ -11809,8 +12150,7 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-key": {
"version": "3.1.1",
@ -11926,8 +12266,7 @@ @@ -11926,8 +12266,7 @@
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz",
"integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=",
"dev": true
"integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I="
},
"progress": {
"version": "2.0.3",
@ -11935,6 +12274,15 @@ @@ -11935,6 +12274,15 @@
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz",
@ -11961,7 +12309,6 @@ @@ -11961,7 +12309,6 @@
"version": "3.6.0",
"resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz",
"integrity": "sha1-M3u9o63AcGvT4CRCaihtS0sskZg=",
"dev": true,
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
@ -12039,6 +12386,11 @@ @@ -12039,6 +12386,11 @@
"integrity": "sha1-BCWido2PI7rXDKS5BGH6LxIT4bI=",
"dev": true
},
"reinterval": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/reinterval/-/reinterval-1.1.0.tgz",
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
},
"repeat-element": {
"version": "1.1.4",
"resolved": "https://registry.nlark.com/repeat-element/download/repeat-element-1.1.4.tgz",
@ -12095,6 +12447,11 @@ @@ -12095,6 +12447,11 @@
"resolved": "https://registry.npm.taobao.org/reusify/download/reusify-1.0.4.tgz",
"integrity": "sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY="
},
"rfdc": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz",
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/rimraf/download/rimraf-3.0.2.tgz",
@ -12516,6 +12873,14 @@ @@ -12516,6 +12873,14 @@
}
}
},
"split2": {
"version": "3.2.2",
"resolved": "https://registry.npmmirror.com/split2/-/split2-3.2.2.tgz",
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
"requires": {
"readable-stream": "^3.0.0"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz",
@ -12600,6 +12965,11 @@ @@ -12600,6 +12965,11 @@
}
}
},
"stream-shift": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/stream-shift/-/stream-shift-1.0.1.tgz",
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
},
"strict-uri-encode": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-2.0.0.tgz",
@ -12609,7 +12979,6 @@ @@ -12609,7 +12979,6 @@
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.3.0.tgz",
"integrity": "sha1-QvEUWUpGzxqOMLCoT1bHjD7awh4=",
"dev": true,
"requires": {
"safe-buffer": "~5.2.0"
},
@ -12617,8 +12986,7 @@ @@ -12617,8 +12986,7 @@
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.nlark.com/safe-buffer/download/safe-buffer-5.2.1.tgz",
"integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY=",
"dev": true
"integrity": "sha1-Hq+fqb2x/dTsdfWPnNtOa3gn7sY="
}
}
},
@ -13093,6 +13461,11 @@ @@ -13093,6 +13461,11 @@
"integrity": "sha1-G/IH9LKPkVg2ZstfvTJ4hzAc1fQ=",
"dev": true
},
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"typescript": {
"version": "4.5.4",
"resolved": "https://registry.npmmirror.com/typescript/download/typescript-4.5.4.tgz",
@ -13282,8 +13655,7 @@ @@ -13282,8 +13655,7 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"v8-compile-cache": {
"version": "2.3.0",
@ -13544,14 +13916,23 @@ @@ -13544,14 +13916,23 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "7.5.9",
"resolved": "https://registry.npmmirror.com/ws/-/ws-7.5.9.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"requires": {}
},
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz",
"integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=",
"dev": true
"integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI="
}
}
}

5
package.json

@ -15,7 +15,9 @@ @@ -15,7 +15,9 @@
"agora-rtc-sdk-ng": "^4.12.1",
"ant-design-vue": "^2.2.8",
"axios": "^0.21.1",
"eventemitter3": "^5.0.0",
"mitt": "^3.0.0",
"mqtt": "^4.3.7",
"query-string": "^7.0.1",
"reconnecting-websocket": "^4.4.0",
"vconsole": "^3.8.1",
@ -97,9 +99,12 @@ @@ -97,9 +99,12 @@
"ant-design-vue/es/tree/style/css",
"ant-design-vue/es/upload/style/css",
"axios",
"eventemitter3",
"lodash",
"mitt",
"moment",
"mqtt",
"mqtt/dist/mqtt.min",
"reconnecting-websocket",
"vconsole",
"vue",

58
src/api/drc.ts

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
import request, { IWorkspaceResponse } from '/@/api/http/request'
import { ELocalStorageKey } from '/@/types'
// DRC 链路
const DRC_API_PREFIX = '/control/api/v1'
const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || ''
export interface PostDrcBody {
client_id?: string // token过期时,用于续期则必填
expire_sec?: number // 过期时间,单位秒,默认3600
}
export interface DrcParams {
address: string
username: string
password: string
client_id: string
expire_time: number // 过期时间
enable_tls: boolean // 是否开启tls
}
// 获取 mqtt 连接认证
export async function postDrc (body: PostDrcBody): Promise<IWorkspaceResponse<DrcParams>> {
const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${workspaceId}/drc/connect`, body)
return resp.data
}
export interface DrcEnterBody {
client_id: string
dock_sn: string
expire_sec?: number // 过期时间,单位秒,默认3600
device_info?: {
osd_frequency?: number
hsi_frequency?: number
}
}
export interface DrcEnterResp {
sub: string[] // 需要订阅接收的topic
pub: string[] // 推送的topic地址
}
// 进入飞行控制 (建立drc连接&获取云控控制权)
export async function postDrcEnter (body: DrcEnterBody): Promise<IWorkspaceResponse<DrcEnterResp>> {
const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${workspaceId}/drc/enter`, body)
return resp.data
}
export interface DrcExitBody {
client_id: string
dock_sn: string
}
// 退出飞行控制 (退出drc连接&退出云控控制权)
export async function postDrcExit (body: DrcExitBody): Promise<IWorkspaceResponse<null>> {
const resp = await request.post(`${DRC_API_PREFIX}/workspaces/${workspaceId}/drc/exit`, body)
return resp.data
}

58
src/api/drone-control/drone.ts

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
import request, { IWorkspaceResponse } from '/@/api/http/request'
// import { ELocalStorageKey } from '/@/types'
const API_PREFIX = '/control/api/v1'
// const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '
// 获取飞行控制权
export async function postFlightAuth (sn: string): Promise<IWorkspaceResponse<null>> {
const resp = await request.post(`${API_PREFIX}/devices/${sn}/authority/flight`)
return resp.data
}
export enum WaylineLostControlActionInCommandFlight {
CONTINUE = 0,
EXEC_LOST_ACTION = 1
}
export enum LostControlActionInCommandFLight {
HOVER = 0, // 悬停
Land = 1, // 着陆
RETURN_HOME = 2, // 返航
}
export interface PointBody {
latitude: number;
longitude: number;
height: number;
}
export interface PostFlyToPointBody {
max_speed: number,
points: PointBody[]
}
// 飞向目标点
export async function postFlyToPoint (sn: string, body: PostFlyToPointBody): Promise<IWorkspaceResponse<null>> {
const resp = await request.post(`${API_PREFIX}/devices/${sn}/jobs/fly-to-point`, body)
return resp.data
}
// 停止飞向目标点
export async function deleteFlyToPoint (sn: string): Promise<IWorkspaceResponse<null>> {
const resp = await request.delete(`${API_PREFIX}/devices/${sn}/jobs/fly-to-point`)
return resp.data
}
export interface PostTakeoffToPointBody{
target_height: number;
target_latitude: number;
target_longitude: number;
security_takeoff_height: number; // 安全起飞高
max_speed: number; // flyto过程中能达到的最大速度, 单位m/s 跟飞机档位有关
rc_lost_action: LostControlActionInCommandFLight; // 失控行为
rth_altitude: number; // 返航高度
exit_wayline_when_rc_lost: WaylineLostControlActionInCommandFlight
}
// 一键起飞
export async function postTakeoffToPoint (sn: string, body: PostTakeoffToPointBody): Promise<IWorkspaceResponse<null>> {
const resp = await request.post(`${API_PREFIX}/devices/${sn}/jobs/takeoff-to-point`, body)
return resp.data
}

93
src/api/drone-control/payload.ts

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
import request, { IWorkspaceResponse } from '/@/api/http/request'
import { CameraType, CameraMode } from '/@/types/live-stream'
import { GimbalResetMode } from '/@/types/drone-control'
// import { ELocalStorageKey } from '/@/types'
const API_PREFIX = '/control/api/v1'
// const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) || '
export interface PostPayloadAuthBody {
payload_index: string
}
// 获取负载控制权
export async function postPayloadAuth (sn: string, body: PostPayloadAuthBody): Promise<IWorkspaceResponse<null>> {
const resp = await request.post(`${API_PREFIX}/devices/${sn}/authority/payload`, body)
return resp.data
}
// TODO: 画面拖动控制
export enum PayloadCommandsEnum {
CameraModeSwitch = 'camera_mode_switch',
CameraPhotoTake = 'camera_photo_take',
CameraRecordingStart = 'camera_recording_start',
CameraRecordingStop = 'camera_recording_stop',
CameraFocalLengthSet = 'camera_focal_length_set',
GimbalReset = 'gimbal_reset',
CameraAim = 'camera_aim'
}
export interface PostCameraModeBody {
payload_index: string
camera_mode: CameraMode
}
export interface PostCameraPhotoBody {
payload_index: string
}
export interface PostCameraRecordingBody {
payload_index: string
}
export interface DeleteCameraRecordingParams {
payload_index: string
}
export interface PostCameraFocalLengthBody {
payload_index: string,
camera_type: CameraType,
zoom_factor: number
}
export interface PostGimbalResetBody{
payload_index: string,
reset_mode: GimbalResetMode,
}
export interface PostCameraAimBody{
payload_index: string,
camera_type: CameraType,
locked: boolean,
x: number,
y: number,
}
export type PostPayloadCommandsBody = {
cmd: PayloadCommandsEnum.CameraModeSwitch,
data: PostCameraModeBody
} | {
cmd: PayloadCommandsEnum.CameraPhotoTake,
data: PostCameraPhotoBody
} | {
cmd: PayloadCommandsEnum.CameraRecordingStart,
data: PostCameraRecordingBody
} | {
cmd: PayloadCommandsEnum.CameraRecordingStop,
data: DeleteCameraRecordingParams
} | {
cmd: PayloadCommandsEnum.CameraFocalLengthSet,
data: PostCameraFocalLengthBody
} | {
cmd: PayloadCommandsEnum.GimbalReset,
data: PostGimbalResetBody
} | {
cmd: PayloadCommandsEnum.CameraAim,
data: PostCameraAimBody
}
// 发送负载名称
export async function postPayloadCommands (sn: string, body: PostPayloadCommandsBody): Promise<IWorkspaceResponse<null>> {
const resp = await request.post(`${API_PREFIX}/devices/${sn}/payload/commands`, body)
return resp.data
}

23
src/api/wayline.ts

@ -42,7 +42,8 @@ export interface CreatePlan { @@ -42,7 +42,8 @@ export interface CreatePlan {
dock_sn: string,
task_type: TaskType, // 任务类型
wayline_type: WaylineType, // 航线类型
execute_time?: number // 执行时间(毫秒)
task_days?: number[] // 执行任务的日期(秒)
task_periods?: number[][] // 执行任务的时间点(秒)
rth_altitude: number // 相对机场返航高度 20 - 500
out_of_control_action: OutOfControlAction // 失控动作
}
@ -90,7 +91,7 @@ export interface DeleteTaskParams { @@ -90,7 +91,7 @@ export interface DeleteTaskParams {
job_id: string
}
// 取消机场任务
// 删除机场任务
export async function deleteTask (workspaceId: string, params: DeleteTaskParams): Promise<IWorkspaceResponse<{}>> {
const url = `${HTTP_PREFIX}/workspaces/${workspaceId}/jobs`
const result = await request.delete(url, {
@ -99,6 +100,24 @@ export async function deleteTask (workspaceId: string, params: DeleteTaskParams) @@ -99,6 +100,24 @@ export async function deleteTask (workspaceId: string, params: DeleteTaskParams)
return result.data
}
export enum UpdateTaskStatus {
Suspend = 0, // 暂停
Resume = 1, // 恢复
}
export interface UpdateTaskStatusBody {
job_id: string
status: UpdateTaskStatus
}
// 更新机场任务状态
export async function updateTaskStatus (workspaceId: string, body: UpdateTaskStatusBody): Promise<IWorkspaceResponse<{}>> {
const url = `${HTTP_PREFIX}/workspaces/${workspaceId}/jobs/${body.job_id}`
const result = await request.put(url, {
status: body.status
})
return result.data
}
// Upload Wayline file
export const importKmzFile = async function (workspaceId: string, file: {}): Promise<IWorkspaceResponse<any>> {
const url = `${HTTP_PREFIX}/workspaces/${workspaceId}/waylines/file/upload`

54
src/components/GMap.vue

@ -1,8 +1,10 @@ @@ -1,8 +1,10 @@
<template>
<div class="g-map-wrapper">
<!-- 地图区域 -->
<div id="g-container" :style="{ width: '100%', height: '100%' }" />
<!-- 绘制面板 -->
<div
class="g-action-panle"
class="g-action-panel"
:style="{ right: drawVisible ? '316px' : '16px' }"
>
<div :class="state.currentType === 'pin' ? 'g-action-item selection' : 'g-action-item'" @click="draw('pin', true)">
@ -18,6 +20,7 @@ @@ -18,6 +20,7 @@
<a style="color: red;"><CloseOutlined /></a>
</div>
</div>
<!-- 飞机OSD -->
<div v-if="osdVisible.visible && !osdVisible.is_dock" class="osd-panel fz12">
<div class="pl5 pr5 flex-align-center flex-row flex-justify-between" style="border-bottom: 1px solid #515151; height: 18%;">
<span>{{ osdVisible.callsign }}</span>
@ -270,12 +273,13 @@ @@ -270,12 +273,13 @@
</a-row>
<a-row class="p5">
<a-col span="24">
<a-button type="primary" :disabled="controlPanelVisible" size="small" @click="setControlPanelVisible(true)">
设备操作
<a-button type="primary" :disabled="dockControlPanelVisible" size="small" @click="setDockControlPanelVisible(true)">
Actions
</a-button>
</a-col>
</a-row>
<DockControlPanel v-if="controlPanelVisible" :sn="osdVisible.gateway_sn" :deviceInfo="deviceInfo" @close-control-panel="dockDebugOnOff">
<!-- 机场控制面板 -->
<DockControlPanel v-if="dockControlPanelVisible" :sn="osdVisible.gateway_sn" :deviceInfo="deviceInfo" @close-control-panel="onCloseControlPanel">
</DockControlPanel>
</div>
</div>
@ -406,7 +410,8 @@ @@ -406,7 +410,8 @@
{{ 10 > (deviceInfo.device.battery.remain_flight_time % 60) ? '0' : ''}}{{deviceInfo.device.battery.remain_flight_time % 60 }}
</div>
</div>
<!-- 飞行指令 -->
<DroneControlPanel :sn="osdVisible.gateway_sn" :deviceInfo="deviceInfo" :payloads="osdVisible.payloads"></DroneControlPanel>
</div>
</div>
</template>
@ -444,7 +449,9 @@ import { @@ -444,7 +449,9 @@ import {
} from '@ant-design/icons-vue'
import { EDeviceTypeName } from '../types'
import DockControlPanel from './g-map/DockControlPanel.vue'
import { useDockControl } from './g-map/useDockControl'
import { useDockControl } from './g-map/use-dock-control'
import DroneControlPanel from './g-map/DroneControlPanel.vue'
import { useConnectMqtt } from './g-map/use-connect-mqtt'
export default defineComponent({
components: {
@ -466,6 +473,7 @@ export default defineComponent({ @@ -466,6 +473,7 @@ export default defineComponent({
ArrowUpOutlined,
ArrowDownOutlined,
DockControlPanel,
DroneControlPanel,
CarryOutOutlined,
RocketOutlined
},
@ -567,7 +575,7 @@ export default defineComponent({ @@ -567,7 +575,7 @@ export default defineComponent({
deviceTsaUpdateHook.initMarker(EDeviceTypeName.Dock, [EDeviceTypeName.Dock], data.currentSn, data.dockInfo[data.currentSn].basic_osd?.longitude, data.dockInfo[data.currentSn].basic_osd?.latitude)
if (osdVisible.value.visible && osdVisible.value.is_dock && osdVisible.value.gateway_sn !== '') {
deviceInfo.dock = data.dockInfo[osdVisible.value.gateway_sn]
deviceInfo.device = data.deviceInfo[deviceInfo.dock.basic_osd?.sub_device?.device_sn ?? osdVisible.value.sn]
deviceInfo.device = data.deviceInfo[deviceInfo.dock.basic_osd.sub_device?.device_sn ?? osdVisible.value.sn]
}
}
}, {
@ -634,21 +642,21 @@ export default defineComponent({ @@ -634,21 +642,21 @@ export default defineComponent({
mouseMode.value = bool
}
// dock
// dock
const {
controlPanelVisible,
setControlPanelVisible,
sendDockControlCmd,
dockDebugOnOff,
dockControlPanelVisible,
setDockControlPanelVisible,
onCloseControlPanel,
} = useDockControl()
// drc
useConnectMqtt()
onMounted(() => {
const app = getApp()
useGMapManageHook.globalPropertiesConfig(app)
setInterval(() => {
console.info(deviceInfo.dock)
}, 1000)
})
function getDrawCallback ({ obj }) {
switch (state.currentType) {
case MapDoodleEnum.PIN:
@ -816,9 +824,9 @@ export default defineComponent({ @@ -816,9 +824,9 @@ export default defineComponent({
EModeCode,
str,
EDockModeCode,
controlPanelVisible,
dockDebugOnOff,
setControlPanelVisible,
dockControlPanelVisible,
setDockControlPanelVisible,
onCloseControlPanel,
NetworkStateTypeEnum,
NetworkStateQualityEnum,
RainfallEnum,
@ -834,7 +842,7 @@ export default defineComponent({ @@ -834,7 +842,7 @@ export default defineComponent({
height: 100%;
width: 100%;
.g-action-panle {
.g-action-panel {
position: absolute;
top: 16px;
right: 16px;
@ -870,12 +878,12 @@ export default defineComponent({ @@ -870,12 +878,12 @@ export default defineComponent({
left: 10px;
top: 10px;
width: 480px;
background: black;
color: white;
background: #000;
color: #fff;
border-radius: 2px;
opacity: 0.7;
opacity: 0.8;
}
.osd > div {
.osd > div:not(.dock-control-panel) {
margin-top: 5px;
padding-left: 5px;
}

16
src/components/devices/device-hms/DeviceHmsDrawer.vue

@ -67,7 +67,12 @@ @@ -67,7 +67,12 @@
</template>
<template v-for="col in ['code', 'message']" #[col]="{ text }" :key="col">
<a-tooltip :title="text">
<span>{{ text }}</span>
<div >{{ text }}</div>
</a-tooltip>
</template>
<template #domain="{text}">
<a-tooltip :title="EDeviceTypeName[text]">
<div >{{ EDeviceTypeName[text] }}</div>
</a-tooltip>
</template>
</a-table>
@ -77,7 +82,7 @@ @@ -77,7 +82,7 @@
<!-- 暂时只抽取该组件 -->
<script lang="ts" setup>
import { watchEffect, reactive, ref, defineProps, defineEmits } from 'vue'
import { watchEffect, reactive, ref, defineProps, defineEmits, watch } from 'vue'
import { getDeviceHms, HmsQueryBody } from '/@/api/manage'
import moment, { Moment } from 'moment'
import { ColumnProps, TableState } from 'ant-design-vue/lib/table/interface'
@ -95,7 +100,7 @@ const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) | @@ -95,7 +100,7 @@ const workspaceId: string = localStorage.getItem(ELocalStorageKey.WorkspaceId) |
//
const sVisible = ref(false)
watchEffect(() => {
watch(props, () => {
sVisible.value = props.visible
// hms
if (props.visible) {
@ -117,9 +122,10 @@ const loading = ref(false) @@ -117,9 +122,10 @@ const loading = ref(false)
const hmsColumns: ColumnProps[] = [
{ title: 'Alarm Begin | End Time', dataIndex: 'create_time', width: '25%', className: 'titleStyle', slots: { customRender: 'time' } },
{ title: 'Level', dataIndex: 'level', width: '120px', className: 'titleStyle', slots: { customRender: 'level' } },
{ title: 'Device', dataIndex: 'domain', width: '12%', className: 'titleStyle' },
{ title: 'Error Code', dataIndex: 'key', width: '20%', className: 'titleStyle', slots: { customRender: 'code' } },
{ title: 'Device', dataIndex: 'domain', width: '12%', className: 'titleStyle', slots: { customRender: 'domain' } },
{ title: 'Error Code', dataIndex: 'key', width: '20%', className: 'titleStyle', ellipsis: true, slots: { customRender: 'code' } },
{ title: 'Hms Message', dataIndex: 'message_en', className: 'titleStyle', ellipsis: true, slots: { customRender: 'message' } },
{ title: 'Hms Message', dataIndex: 'message_zh', className: 'titleStyle', ellipsis: true, slots: { customRender: 'message' } },
]
interface DeviceHmsData {

2
src/components/devices/device-upgrade/DeviceFirmwareUpgrade.vue

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
</span>
<!-- 进度 -->
<span v-if="device.firmware_status === DeviceFirmwareStatusEnum.DuringUpgrade">
{{ `${device.firmware_progress}%`}}
{{ `${device.firmware_progress}`}}
</span>
</div>
</template>

4
src/components/g-map/DeviceSettingBox.vue

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
<template>
<div class="device-setting-wrapper">
<div class="device-setting-header">设备属性设置</div>
<div class="device-setting-header">Device Property Set</div>
<div class="device-setting-box">
<!-- 飞行器夜航灯 -->
<div class="control-setting-item">
@ -154,7 +154,7 @@ import { useMyStore } from '/@/store' @@ -154,7 +154,7 @@ import { useMyStore } from '/@/store'
import { cloneDeep } from 'lodash'
import { initDeviceSetting, initDeviceSettingFormModel, DeviceSettingKeyEnum } from '/@/types/device-setting'
import { updateDeviceSettingInfoByOsd, updateDeviceSettingFormModelByOsd } from '/@/utils/device-setting'
import { useDeviceSetting } from './useDeviceSetting'
import { useDeviceSetting } from './use-device-setting'
import DeviceSettingPopover from './DeviceSettingPopover.vue'
const props = defineProps<{

10
src/components/g-map/DockControlPanel.vue

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
<div class="dock-control-panel">
<!-- title -->
<div class="dock-control-panel-header fz16 pl5 pr5 flex-align-center flex-row flex-justify-between">
<span>设备操作 {{ props.sn}}</span>
<span>Device Control<span class="fz12 pl15">{{ props.sn}}</span></span>
<span @click="closeControlPanel">
<CloseOutlined />
</span>
@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
<!-- cmd -->
<div class="control-cmd-wrapper">
<div class="control-cmd-header">
远程调试
Device Remote Debug
<a-switch class="debug-btn" checked-children="" un-checked-children="" v-model:checked="debugStatus" @change="onDeviceStatusChange"/>
</div>
<div class="control-cmd-box">
@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
</div>
</div>
</div>
</div>
</div>
</div>
</template>
@ -38,7 +38,7 @@ import { defineProps, defineEmits, ref, watch } from 'vue' @@ -38,7 +38,7 @@ import { defineProps, defineEmits, ref, watch } from 'vue'
import {
CloseOutlined
} from '@ant-design/icons-vue'
import { useDockControl } from './useDockControl'
import { useDockControl } from './use-dock-control'
import { DeviceInfoType, EDockModeCode } from '/@/types/device'
import { cmdList as baseCmdList, DeviceCmdItem } from '/@/types/device-cmd'
import { useMyStore } from '/@/store'
@ -76,7 +76,7 @@ watch(() => props.deviceInfo, (value) => { @@ -76,7 +76,7 @@ watch(() => props.deviceInfo, (value) => {
const emit = defineEmits(['close-control-panel'])
function closeControlPanel () {
emit('close-control-panel', props.sn, false)
emit('close-control-panel', props.sn)
}
// dock

34
src/components/g-map/DroneControlInfoPanel.vue

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
<template>
<div class="drone-control-info-wrap">
<a-textarea v-model:value="info" placeholder="drc info" :rows="5" disabled/>
</div>
</template>
<script lang="ts" setup>
import { ref, defineProps, watch } from 'vue'
const props = defineProps<{
message?: string,
}>()
const info = ref('')
watch(() => props.message, message => {
info.value = message || ''
}, {
immediate: true
})
// const emit = defineEmits(['cancel', 'confirm'])
</script>
<style lang="scss" scoped>
.drone-control-info-wrap {
&::v-deep{
textarea.ant-input {
background-color: #000;
color: #fff;
white-space: pre-wrap;
}
}
}
</style>

756
src/components/g-map/DroneControlPanel.vue

@ -0,0 +1,756 @@ @@ -0,0 +1,756 @@
<template>
<div class="drone-control-wrapper">
<div class="drone-control-header">Drone Flight Control</div>
<div class="drone-control-box">
<div class="box">
<div class="row">
<div class="drone-control"><Button :ghost="!flightController" size="small" @click="onClickFightControl">{{ flightController ? 'Exit Remote Control' : 'Enter Remote Control'}}</Button></div>
</div>
<div class="row">
<div class="drone-control-direction">
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_Q)" @onmouseup="onMouseUp">
<template #icon><UndoOutlined /></template><span class="word">Q</span>
</Button>
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_W)" @onmouseup="onMouseUp">
<template #icon><UpOutlined/></template><span class="word">W</span>
</Button>
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_E)" @onmouseup="onMouseUp">
<template #icon><RedoOutlined /></template><span class="word">E</span>
</Button>
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.ARROW_UP)" @onmouseup="onMouseUp">
<template #icon><ArrowUpOutlined /></template>
</Button>
<br />
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_A)" @onmouseup="onMouseUp">
<template #icon><LeftOutlined/></template><span class="word">A</span>
</Button>
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_S)" @onmouseup="onMouseUp">
<template #icon><DownOutlined/></template><span class="word">S</span>
</Button>
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.KEY_D)" @onmouseup="onMouseUp">
<template #icon><RightOutlined/></template><span class="word">D</span>
</Button>
<Button size="small" ghost @mousedown="onMouseDown(KeyCode.ARROW_DOWN)" @onmouseup="onMouseUp">
<template #icon><ArrowDownOutlined /></template>
</Button>
</div>
<Button type="primary" size="small" danger ghost @click="handleEmergencyStop" >
<template #icon><PauseCircleOutlined/></template><span>Break</span>
</Button>
</div>
<div class="row">
<DroneControlPopover
:visible="flyToPointPopoverData.visible"
:loading="flyToPointPopoverData.loading"
@confirm="($event) => onFlyToConfirm(true)"
@cancel="($event) =>onFlyToConfirm(false)"
>
<template #formContent>
<div class="form-content">
<div>
<span class="form-label">latitude:</span>
<a-input-number v-model:value="flyToPointPopoverData.latitude"/>
</div>
<div>
<span class="form-label">longitude:</span>
<a-input-number v-model:value="flyToPointPopoverData.longitude"/>
</div>
<div>
<span class="form-label">height(m):</span>
<a-input-number v-model:value="flyToPointPopoverData.height"/>
</div>
</div>
</template>
<Button size="small" ghost @click="onShowFlyToPopover" >
<span>Fly to</span>
</Button>
</DroneControlPopover>
<Button size="small" ghost @click="onStopFlyToPoint" >
<span>Stop Fly to</span>
</Button>
<DroneControlPopover
:visible="takeoffToPointPopoverData.visible"
:loading="takeoffToPointPopoverData.loading"
@confirm="($event) => onTakeoffToPointConfirm(true)"
@cancel="($event) =>onTakeoffToPointConfirm(false)"
>
<template #formContent>
<div class="form-content">
<div>
<span class="form-label">latitude:</span>
<a-input-number v-model:value="takeoffToPointPopoverData.latitude"/>
</div>
<div>
<span class="form-label">longitude:</span>
<a-input-number v-model:value="takeoffToPointPopoverData.longitude"/>
</div>
<div>
<span class="form-label">height(m):</span>
<a-input-number v-model:value="takeoffToPointPopoverData.height"/>
</div>
<div>
<span class="form-label">Safe Takeoff Altitude(m):</span>
<a-input-number v-model:value="takeoffToPointPopoverData.securityTakeoffHeight"/>
</div>
<div>
<span class="form-label">Return-to-Home Altitude(m):</span>
<a-input-number v-model:value="takeoffToPointPopoverData.rthAltitude"/>
</div>
<div>
<span class="form-label">Lost Action:</span>
<a-select
v-model:value="takeoffToPointPopoverData.rcLostAction"
style="width: 120px"
:options="LostControlActionInCommandFLightOptions"
></a-select>
</div>
<div>
<span class="form-label">Wayline Lost Action:</span>
<a-select
v-model:value="takeoffToPointPopoverData.exitWaylineWhenRcLost"
style="width: 120px"
:options="WaylineLostControlActionInCommandFlightOptions"
></a-select>
</div>
</div>
</template>
<Button size="small" ghost @click="onShowTakeoffToPointPopover" >
<span>Take off</span>
</Button>
</DroneControlPopover>
<Button :loading="cmdItem.loading" size="small" ghost @click="sendControlCmd(cmdItem, index)">
{{ cmdItem.operateText }}
</Button>
</div>
</div>
<div class="box">
<div class="row">
<Select v-model:value="payloadSelectInfo.value" style="width: 110px; marginRight: 5px" :options="payloadSelectInfo.options" @change="handlePayloadChange"/>
<div class="drone-control">
<Button type="primary" size="small" @click="onAuthPayload">Payload Control</Button>
</div>
</div>
<div class="row">
<DroneControlPopover
:visible="gimbalResetPopoverData.visible"
:loading="gimbalResetPopoverData.loading"
@confirm="($event) => onGimbalResetConfirm(true)"
@cancel="($event) =>onGimbalResetConfirm(false)"
>
<template #formContent>
<div class="form-content">
<div>
<span class="form-label">reset mode:</span>
<a-select
v-model:value="gimbalResetPopoverData.resetMode"
style="width: 180px"
:options="GimbalResetModeOptions"
></a-select>
</div>
</div>
</template>
<Button size="small" ghost @click="onShowGimbalResetPopover">
<span>Gimbal Reset</span>
</Button>
</DroneControlPopover>
<Button size="small" ghost @click="onSwitchCameraMode">
<span>Camera Mode Switch</span>
</Button>
</div>
<div class="row">
<Button size="small" ghost @click="onStartCameraRecording">
<span>Start Recording</span>
</Button>
<Button size="small" ghost @click="onStopCameraRecording">
<span>Stop Recording</span>
</Button>
</div>
<div class="row">
<Button size="small" ghost @click="onTakeCameraPhoto">
<span>Take Photo</span>
</Button>
<DroneControlPopover
:visible="zoomFactorPopoverData.visible"
:loading="zoomFactorPopoverData.loading"
@confirm="($event) => onZoomFactorConfirm(true)"
@cancel="($event) =>onZoomFactorConfirm(false)"
>
<template #formContent>
<div class="form-content">
<div>
<span class="form-label">camera type:</span>
<a-select
v-model:value="zoomFactorPopoverData.cameraType"
style="width: 120px"
:options="ZoomCameraTypeOptions"
></a-select>
</div>
<div>
<span class="form-label">zoom factor:</span>
<a-input-number v-model:value="zoomFactorPopoverData.zoomFactor" :min="2" :max="200" />
</div>
</div>
</template>
<Button size="small" ghost @click="($event) => onShowZoomFactorPopover()">
<span class="word" @click=";">Zoom</span>
</Button>
</DroneControlPopover>
<DroneControlPopover
:visible="cameraAimPopoverData.visible"
:loading="cameraAimPopoverData.loading"
@confirm="($event) => onCameraAimConfirm(true)"
@cancel="($event) =>onCameraAimConfirm(false)"
>
<template #formContent>
<div class="form-content">
<div>
<span class="form-label">camera type:</span>
<a-select
v-model:value="cameraAimPopoverData.cameraType"
style="width: 120px"
:options="CameraTypeOptions"
></a-select>
</div>
<div>
<span class="form-label">locked:</span>
<a-switch v-model:checked="cameraAimPopoverData.locked"/>
</div>
<div>
<span class="form-label">x:</span>
<a-input-number v-model:value="cameraAimPopoverData.x" :min="0" :max="1"/>
</div>
<div>
<span class="form-label">y:</span>
<a-input-number v-model:value="cameraAimPopoverData.y" :min="0" :max="1"/>
</div>
</div>
</template>
<Button size="small" ghost @click="($event) => onShowCameraAimPopover()">
<span class="word" @click=";">AIM</span>
</Button>
</DroneControlPopover>
</div>
</div>
</div>
<!-- 信息提示 -->
<DroneControlInfoPanel :message="drcInfo"></DroneControlInfoPanel>
</div>
</template>
<script setup lang="ts">
import { defineProps, reactive, ref, watch, computed, onMounted, watchEffect } from 'vue'
import { Select, message, Button } from 'ant-design-vue'
import { PayloadInfo, DeviceInfoType, ControlSource, DeviceOsdCamera, DrcStateEnum } from '/@/types/device'
import { useMyStore } from '/@/store'
import { postDrcEnter, postDrcExit } from '/@/api/drc'
import { useMqtt, DeviceTopicInfo } from './use-mqtt'
import { DownOutlined, UpOutlined, LeftOutlined, RightOutlined, PauseCircleOutlined, UndoOutlined, RedoOutlined, ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons-vue'
import { useManualControl, KeyCode } from './use-manual-control'
import { usePayloadControl } from './use-payload-control'
import { CameraMode, CameraType, CameraTypeOptions, ZoomCameraTypeOptions, CameraListItem } from '/@/types/live-stream'
import { useDroneControlWsEvent } from './use-drone-control-ws-event'
import { useDroneControlMqttEvent } from './use-drone-control-mqtt-event'
import { postFlightAuth, LostControlActionInCommandFLight, WaylineLostControlActionInCommandFlight } from '/@/api/drone-control/drone'
import { useDroneControl } from './use-drone-control'
import { GimbalResetMode, GimbalResetModeOptions, LostControlActionInCommandFLightOptions, WaylineLostControlActionInCommandFlightOptions } from '/@/types/drone-control'
import DroneControlPopover from './DroneControlPopover.vue'
import DroneControlInfoPanel from './DroneControlInfoPanel.vue'
import { noDebugCmdList as baseCmdList, DeviceCmdItem, DeviceCmd } from '/@/types/device-cmd'
import { useDockControl } from './use-dock-control'
const props = defineProps<{
sn: string,
deviceInfo: DeviceInfoType,
payloads: null | PayloadInfo[]
}>()
const store = useMyStore()
const clientId = computed(() => {
return store.state.clientId
})
const initCmdList = baseCmdList.find(item => item.cmdKey === DeviceCmd.ReturnHome)
const cmdItem = ref(initCmdList)
const {
sendDockControlCmd
} = useDockControl()
async function sendControlCmd (cmdItem: DeviceCmdItem, index: number) {
cmdItem.loading = true
const result = await sendDockControlCmd({
sn: props.sn,
cmd: cmdItem.cmdKey,
action: cmdItem.action
}, false)
if (result && flightController.value) {
exitFlightCOntrol()
}
cmdItem.loading = false
}
const { flyToPoint, stopFlyToPoint, takeoffToPoint } = useDroneControl()
const MAX_SPEED = 14
const flyToPointPopoverData = reactive({
visible: false,
loading: false,
latitude: null as null | number,
longitude: null as null | number,
height: null as null | number,
maxSpeed: MAX_SPEED,
})
function onShowFlyToPopover () {
flyToPointPopoverData.visible = !flyToPointPopoverData.visible
flyToPointPopoverData.loading = false
flyToPointPopoverData.latitude = null
flyToPointPopoverData.longitude = null
flyToPointPopoverData.height = null
}
async function onFlyToConfirm (confirm: boolean) {
if (confirm) {
if (!flyToPointPopoverData.height || !flyToPointPopoverData.latitude || !flyToPointPopoverData.longitude) {
message.error('Input error')
return
}
try {
await flyToPoint(props.sn, {
max_speed: flyToPointPopoverData.maxSpeed,
points: [
{
latitude: flyToPointPopoverData.latitude,
longitude: flyToPointPopoverData.longitude,
height: flyToPointPopoverData.height
}
]
})
} catch (error) {
}
}
flyToPointPopoverData.visible = false
}
async function onStopFlyToPoint () {
await stopFlyToPoint(props.sn)
}
const takeoffToPointPopoverData = reactive({
visible: false,
loading: false,
latitude: null as null | number,
longitude: null as null | number,
height: null as null | number,
securityTakeoffHeight: null as null | number,
maxSpeed: MAX_SPEED,
rthAltitude: null as null | number,
rcLostAction: LostControlActionInCommandFLight.RETURN_HOME,
exitWaylineWhenRcLost: WaylineLostControlActionInCommandFlight.RETURN_HOME
})
function onShowTakeoffToPointPopover () {
takeoffToPointPopoverData.visible = !takeoffToPointPopoverData.visible
takeoffToPointPopoverData.loading = false
takeoffToPointPopoverData.latitude = null
takeoffToPointPopoverData.longitude = null
takeoffToPointPopoverData.securityTakeoffHeight = null
takeoffToPointPopoverData.rthAltitude = null
takeoffToPointPopoverData.rcLostAction = LostControlActionInCommandFLight.RETURN_HOME
takeoffToPointPopoverData.exitWaylineWhenRcLost = WaylineLostControlActionInCommandFlight.RETURN_HOME
}
async function onTakeoffToPointConfirm (confirm: boolean) {
if (confirm) {
if (!takeoffToPointPopoverData.height ||
!takeoffToPointPopoverData.latitude ||
!takeoffToPointPopoverData.longitude ||
!takeoffToPointPopoverData.securityTakeoffHeight ||
!takeoffToPointPopoverData.rthAltitude) {
message.error('Input error')
return
}
try {
await takeoffToPoint(props.sn, {
target_latitude: takeoffToPointPopoverData.latitude,
target_longitude: takeoffToPointPopoverData.longitude,
target_height: takeoffToPointPopoverData.height,
security_takeoff_height: takeoffToPointPopoverData.securityTakeoffHeight,
rth_altitude: takeoffToPointPopoverData.rthAltitude,
max_speed: takeoffToPointPopoverData.maxSpeed,
rc_lost_action: takeoffToPointPopoverData.rcLostAction,
exit_wayline_when_rc_lost: takeoffToPointPopoverData.exitWaylineWhenRcLost
})
} catch (error) {
}
}
takeoffToPointPopoverData.visible = false
}
const deviceTopicInfo: DeviceTopicInfo = reactive({
sn: props.sn,
pubTopic: '',
subTopic: ''
})
useMqtt(deviceTopicInfo)
//
const drcState = computed(() => {
return store.state.deviceState?.dockInfo[props.sn]?.link_osd?.drc_state === DrcStateEnum.CONNECTED
})
const flightController = ref(drcState.value)
async function onClickFightControl () {
if (flightController.value) {
exitFlightCOntrol()
return
}
enterFlightControl()
}
//
async function enterFlightControl () {
try {
const { code, data } = await postDrcEnter({
client_id: clientId.value,
dock_sn: props.sn,
})
if (code === 0) {
flightController.value = true
if (data.sub && data.sub.length > 0) {
deviceTopicInfo.subTopic = data.sub[0]
}
if (data.pub && data.pub.length > 0) {
deviceTopicInfo.pubTopic = data.pub[0]
}
//
if (droneControlSource.value !== ControlSource.A) {
await postFlightAuth(props.sn)
}
message.success('Get flight control successfully')
}
} catch (error: any) {
}
}
// 退
async function exitFlightCOntrol () {
try {
const { code } = await postDrcExit({
client_id: clientId.value,
dock_sn: props.sn,
})
if (code === 0) {
flightController.value = false
deviceTopicInfo.subTopic = ''
deviceTopicInfo.pubTopic = ''
message.success('Exit flight control')
}
} catch (error: any) {
}
}
// drc mqtt message
const { drcInfo } = useDroneControlMqttEvent(props.sn)
const {
handleKeyup,
handleEmergencyStop,
resetControlState,
} = useManualControl(deviceTopicInfo, flightController)
function onMouseDown (type: KeyCode) {
handleKeyup(type)
}
function onMouseUp () {
resetControlState()
}
//
const payloadSelectInfo = {
value: null as any,
controlSource: undefined as undefined | ControlSource,
options: [] as any,
payloadIndex: '' as string,
camera: undefined as undefined | DeviceOsdCamera // osd
}
const handlePayloadChange = (value: string) => {
const payload = props.payloads?.find(item => item.payload_sn === value)
if (payload) {
payloadSelectInfo.payloadIndex = payload.payload_index || ''
payloadSelectInfo.controlSource = payload.control_source
payloadSelectInfo.camera = undefined
}
}
// function getCurrentCamera (cameraList: CameraListItem[], cameraIndex?: string):CameraListItem | null {
// let camera = null
// cameraList.forEach(item => {
// if (item.camera_index === cameraIndex) {
// camera = item
// }
// })
// return camera
// }
// const currentCamera = computed(() => {
// return getCurrentCamera(props.deviceInfo.dock.basic_osd.live_capacity?.device_list[0]?.camera_list as CameraListItem[], camera_index)
// })
//
watch(() => props.payloads, (payloads) => {
if (payloads && payloads.length > 0) {
payloadSelectInfo.value = payloads[0].payload_sn
payloadSelectInfo.controlSource = payloads[0].control_source || ControlSource.B
payloadSelectInfo.payloadIndex = payloads[0].payload_index || ''
payloadSelectInfo.options = payloads.map(item => ({ label: item.payload_name, value: item.payload_sn }))
payloadSelectInfo.camera = undefined
} else {
payloadSelectInfo.value = null
payloadSelectInfo.controlSource = undefined
payloadSelectInfo.options = []
payloadSelectInfo.payloadIndex = ''
payloadSelectInfo.camera = undefined
}
}, {
immediate: true,
deep: true
})
watch(() => props.deviceInfo.device, (droneOsd) => {
if (droneOsd && droneOsd.cameras) {
payloadSelectInfo.camera = droneOsd.cameras.find(item => item.payload_index === payloadSelectInfo.payloadIndex)
} else {
payloadSelectInfo.camera = undefined
}
}, {
immediate: true,
deep: true
})
// ws
const { droneControlSource, payloadControlSource } = useDroneControlWsEvent(props.sn, payloadSelectInfo.value)
watch(() => payloadControlSource, (controlSource) => {
payloadSelectInfo.controlSource = controlSource.value
}, {
immediate: true,
deep: true
})
const {
checkPayloadAuth,
authPayload,
resetGimbal,
switchCameraMode,
takeCameraPhoto,
startCameraRecording,
stopCameraRecording,
changeCameraFocalLength,
cameraAim,
} = usePayloadControl()
async function onAuthPayload () {
const result = await authPayload(props.sn, payloadSelectInfo.payloadIndex)
if (result) {
payloadControlSource.value = ControlSource.A
}
}
const gimbalResetPopoverData = reactive({
visible: false,
loading: false,
resetMode: null as null | GimbalResetMode,
})
function onShowGimbalResetPopover () {
gimbalResetPopoverData.visible = !gimbalResetPopoverData.visible
gimbalResetPopoverData.loading = false
gimbalResetPopoverData.resetMode = null
}
async function onGimbalResetConfirm (confirm: boolean) {
if (confirm) {
if (gimbalResetPopoverData.resetMode === null) {
message.error('Please select reset mode')
return
}
gimbalResetPopoverData.loading = true
try {
await resetGimbal(props.sn, {
payload_index: payloadSelectInfo.payloadIndex,
reset_mode: gimbalResetPopoverData.resetMode
})
} catch (err) {
}
}
gimbalResetPopoverData.visible = false
}
async function onSwitchCameraMode () {
if (!checkPayloadAuth(payloadSelectInfo.controlSource)) {
return
}
const currentCameraMode = payloadSelectInfo.camera?.camera_mode
await switchCameraMode(props.sn, {
payload_index: payloadSelectInfo.payloadIndex,
camera_mode: currentCameraMode === CameraMode.Photo ? CameraMode.Video : CameraMode.Photo
})
}
async function onTakeCameraPhoto () {
if (!checkPayloadAuth(payloadSelectInfo.controlSource)) {
return
}
await takeCameraPhoto(props.sn, payloadSelectInfo.payloadIndex)
}
async function onStartCameraRecording () {
if (!checkPayloadAuth(payloadSelectInfo.controlSource)) {
return
}
await startCameraRecording(props.sn, payloadSelectInfo.payloadIndex)
}
async function onStopCameraRecording () {
if (!checkPayloadAuth(payloadSelectInfo.controlSource)) {
return
}
await stopCameraRecording(props.sn, payloadSelectInfo.payloadIndex)
}
const zoomFactorPopoverData = reactive({
visible: false,
loading: false,
cameraType: null as null | CameraType,
zoomFactor: null as null | number,
})
function onShowZoomFactorPopover () {
zoomFactorPopoverData.visible = !zoomFactorPopoverData.visible
zoomFactorPopoverData.loading = false
zoomFactorPopoverData.cameraType = null
zoomFactorPopoverData.zoomFactor = null
}
async function onZoomFactorConfirm (confirm: boolean) {
if (confirm) {
if (!zoomFactorPopoverData.zoomFactor || zoomFactorPopoverData.cameraType === null) {
message.error('Please input Zoom Factor')
return
}
zoomFactorPopoverData.loading = true
try {
await changeCameraFocalLength(props.sn, {
payload_index: payloadSelectInfo.payloadIndex,
camera_type: zoomFactorPopoverData.cameraType,
zoom_factor: zoomFactorPopoverData.zoomFactor
})
} catch (err) {
}
}
zoomFactorPopoverData.visible = false
}
const cameraAimPopoverData = reactive({
visible: false,
loading: false,
cameraType: null as null | CameraType,
locked: false,
x: null as null | number,
y: null as null | number,
})
function onShowCameraAimPopover () {
cameraAimPopoverData.visible = !cameraAimPopoverData.visible
cameraAimPopoverData.loading = false
cameraAimPopoverData.cameraType = null
cameraAimPopoverData.locked = false
cameraAimPopoverData.x = null
cameraAimPopoverData.y = null
}
async function onCameraAimConfirm (confirm: boolean) {
if (confirm) {
if (cameraAimPopoverData.cameraType === null || cameraAimPopoverData.x === null || cameraAimPopoverData.y === null) {
message.error('Input error')
return
}
try {
await cameraAim(props.sn, {
payload_index: payloadSelectInfo.payloadIndex,
camera_type: cameraAimPopoverData.cameraType,
locked: cameraAimPopoverData.locked,
x: cameraAimPopoverData.x,
y: cameraAimPopoverData.y,
})
} catch (error) {
}
}
cameraAimPopoverData.visible = false
}
</script>
<style lang='scss' scoped>
.drone-control-wrapper{
// border-bottom: 1px solid #515151;
.drone-control-header{
font-size: 14px;
font-weight: 600;
padding: 10px 10px 0px;
}
.drone-control-box {
display: flex;
flex-wrap: 1;
.box {
width: 50%;
padding: 5px;
border: 0.5px solid rgba(255,255,255,0.3);
.row {
display: flex;
flex-wrap: wrap;
padding: 2px;
+ .row{
margin-bottom: 6px;
}
&::v-deep{
.ant-btn{
font-size: 12px;
padding: 0px 4px;
margin-right: 5px;
}
}
}
.drone-control{
&::v-deep{
.ant-select-single:not(.ant-select-customize-input) .ant-select-selector{
padding: 0 2px;
}
}
}
.drone-control-direction{
margin-right: 10px;
.ant-btn {
// padding: 0px 1px;
margin-right: 0;
}
.word{
width: 12px;
margin-left: 2px;
font-size: 12px;
color: #aaa;
}
}
}
}
}
</style>

115
src/components/g-map/DroneControlPopover.vue

@ -0,0 +1,115 @@ @@ -0,0 +1,115 @@
<template>
<a-popover :visible="state.sVisible"
trigger="click"
v-bind="$attrs"
:overlay-class-name="overlayClassName"
placement="bottom"
@visibleChange=";"
v-on="$attrs">
<template #content>
<div class="title-content">
</div>
<slot name="formContent" />
<div class="uranus-popconfirm-btns">
<a-button size="sm"
@click="onCancel">
{{ cancelText || 'cancel'}}
</a-button>
<a-button size="sm"
:loading="loading"
type="primary"
class="confirm-btn"
@click="onConfirm">
{{ okText || 'ok' }}
</a-button>
</div>
</template>
<template v-if="$slots.default">
<slot></slot>
</template>
</a-popover>
</template>
<script lang="ts" setup>
import { defineProps, defineEmits, reactive, watch, computed } from 'vue'
const props = defineProps<{
visible?: boolean,
loading?: Boolean,
disabled?: Boolean,
title?: String,
okText?: String,
cancelText?: String,
width?: Number,
}>()
const emit = defineEmits(['cancel', 'confirm'])
const state = reactive({
sVisible: false,
loading: false,
})
watch(() => props.visible, (val) => {
state.sVisible = val || false
})
const loading = computed(() => {
return props.loading
})
const okLabel = computed(() => {
return props.loading ? '' : '确定'
})
const overlayClassName = computed(() => {
const classList = ['drone-control-popconfirm']
return classList.join(' ')
})
function onConfirm (e: Event) {
if (props.disabled) {
return
}
emit('confirm', e)
}
function onCancel (e: Event) {
state.sVisible = false
emit('cancel', e)
}
</script>
<style lang="scss">
.drone-control-popconfirm {
min-width: 300px;
.uranus-popconfirm-btns{
display: flex;
padding: 10px 0px;
justify-content: flex-end;
.confirm-btn{
margin-left: 10px;
}
}
.form-content{
display: flex;
flex-direction: column;
> div {
display: flex;
margin-bottom: 5px;
.form-label {
flex: 1 0 60px;
margin-right: 10px;
}
> div {
}
}
}
}
</style>

71
src/components/g-map/use-connect-mqtt.ts

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
import {
ref,
watch,
computed,
onUnmounted,
} from 'vue'
import { useMyStore } from '/@/store'
import { postDrc } from '/@/api/drc'
import {
UranusMqtt,
} from '/@/mqtt'
type StatusOptions = {
status: 'close';
event?: CloseEvent;
} | {
status: 'open';
retryCount: number;
} | {
status: 'pending';
}
export function useConnectMqtt () {
const store = useMyStore()
const dockOsdVisible = computed(() => {
return store.state.osdVisible && store.state.osdVisible.visible && store.state.osdVisible.is_dock
})
const mqttState = ref<UranusMqtt | null>(null)
// 监听已打开的设备小窗 窗口数量
watch(() => dockOsdVisible.value, async (val) => {
// 1.打开小窗
// 2.设备拥有飞行控制权
// 3.请求建立mqtt连接的认证信息
if (val) {
if (mqttState.value) return
const result = await postDrc({})
if (result?.code === 0) {
const { address, client_id, username, password, expire_time } = result.data
// @TODO: 校验 expire_time
mqttState.value = new UranusMqtt(address, {
clientId: client_id,
username,
password,
})
mqttState.value?.initMqtt()
mqttState.value?.on('onStatus', (statusOptions: StatusOptions) => {
// @TODO: 异常case
})
store.commit('SET_MQTT_STATE', mqttState.value)
store.commit('SET_CLIENT_ID', client_id)
}
// @TODO: 认证失败case
return
}
// 关闭所有小窗后
// 1.销毁mqtt连接重置mqtt状态
if (mqttState?.value) {
mqttState.value?.destroyed()
mqttState.value = null
store.commit('SET_MQTT_STATE', null)
store.commit('SET_CLIENT_ID', '')
}
}, { immediate: true })
onUnmounted(() => {
mqttState.value?.destroyed()
})
}

0
src/components/g-map/useDeviceSetting.ts → src/components/g-map/use-device-setting.ts

20
src/components/g-map/useDockControl.ts → src/components/g-map/use-dock-control.ts

@ -4,10 +4,10 @@ import { postSendCmd } from '/@/api/device-cmd' @@ -4,10 +4,10 @@ import { postSendCmd } from '/@/api/device-cmd'
import { DeviceCmd, DeviceCmdItemAction } from '/@/types/device-cmd'
export function useDockControl () {
const controlPanelVisible = ref(false)
const dockControlPanelVisible = ref(false)
function setControlPanelVisible (visible: boolean) {
controlPanelVisible.value = visible
function setDockControlPanelVisible (visible: boolean) {
dockControlPanelVisible.value = visible
}
// 远程调试开关
@ -16,9 +16,6 @@ export function useDockControl () { @@ -16,9 +16,6 @@ export function useDockControl () {
sn: sn,
cmd: on ? DeviceCmd.DebugModeOpen : DeviceCmd.DebugModeClose
}, false)
if (result) {
setControlPanelVisible(on)
}
return result
}
@ -47,10 +44,17 @@ export function useDockControl () { @@ -47,10 +44,17 @@ export function useDockControl () {
}
}
// 控制面板关闭
async function onCloseControlPanel (sn: string) {
await dockDebugOnOff(sn, false)
setDockControlPanelVisible(false)
}
return {
controlPanelVisible,
setControlPanelVisible,
dockControlPanelVisible,
setDockControlPanelVisible,
sendDockControlCmd,
dockDebugOnOff,
onCloseControlPanel,
}
}

61
src/components/g-map/use-drone-control-mqtt-event.ts

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
import { ref, onMounted, onBeforeUnmount } from 'vue'
import EventBus from '/@/event-bus/'
import {
DRC_METHOD,
DRCHsiInfo,
DRCOsdInfo,
DRCDelayTimeInfo,
} from '/@/types/drc'
export function useDroneControlMqttEvent (sn: string) {
const drcInfo = ref('')
const hsiInfo = ref('')
const osdInfo = ref('')
const delayInfo = ref('')
function handleHsiInfo (data: DRCHsiInfo) {
hsiInfo.value = `method: ${DRC_METHOD.HSI_INFO_PUSH}\r\n ${JSON.stringify(data)}\r\n `
}
function handleOsdInfo (data: DRCOsdInfo) {
osdInfo.value = `method: ${DRC_METHOD.OSD_INFO_PUSH}\r\n ${JSON.stringify(data)}\r\n `
}
function handleDelayTimeInfo (data: DRCDelayTimeInfo) {
delayInfo.value = `method: ${DRC_METHOD.DELAY_TIME_INFO_PUSH}\r\n ${JSON.stringify(data)}\r\n `
}
function handleDroneControlMqttEvent (payload: any) {
if (!payload || !payload.method) {
return
}
switch (payload.method) {
case DRC_METHOD.HSI_INFO_PUSH: {
handleHsiInfo(payload.data)
break
}
case DRC_METHOD.OSD_INFO_PUSH: {
handleOsdInfo(payload.data)
break
}
case DRC_METHOD.DELAY_TIME_INFO_PUSH: {
handleDelayTimeInfo(payload.data)
break
}
}
drcInfo.value = hsiInfo.value + osdInfo.value + delayInfo.value
}
onMounted(() => {
EventBus.on('droneControlMqttInfo', handleDroneControlMqttEvent)
})
onBeforeUnmount(() => {
EventBus.off('droneControlMqttInfo', handleDroneControlMqttEvent)
})
return {
drcInfo: drcInfo
}
}

97
src/components/g-map/use-drone-control-ws-event.ts

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
import { message, notification } from 'ant-design-vue'
import { ref, onMounted, onBeforeUnmount } from 'vue'
import EventBus from '/@/event-bus/'
import { EBizCode } from '/@/types'
import { ControlSource } from '/@/types/device'
import { ControlSourceChangeType, ControlSourceChangeInfo, FlyToPointMessage, TakeoffToPointMessage, DrcModeExitNotifyMessage, DrcStatusNotifyMessage } from '/@/types/drone-control'
export interface UseDroneControlWsEventParams {
}
export function useDroneControlWsEvent (sn: string, payloadSn: string, funcs?: UseDroneControlWsEventParams) {
const droneControlSource = ref(ControlSource.A)
const payloadControlSource = ref(ControlSource.B)
function onControlSourceChange (data: ControlSourceChangeInfo) {
if (data.type === ControlSourceChangeType.Flight && data.sn === sn) {
droneControlSource.value = data.control_source
message.info(`Flight control is changed to ${droneControlSource.value}`)
return
}
if (data.type === ControlSourceChangeType.Payload && data.sn === payloadSn) {
payloadControlSource.value = data.control_source
message.info(`Payload control is changed to ${ payloadControlSource.value }.`)
return
}
}
function handleProgress(key: string, message: string, error: number) {
if (error !== 0) {
notification.error({
key: key,
message: key + 'Error code:' + error,
description: message,
duration: null
})
} else {
notification.info({
key: key,
message: key,
description: message,
duration: 30
})
}
}
function handleDroneControlWsEvent (payload: any) {
if (!payload) {
return
}
switch (payload.biz_code) {
case EBizCode.ControlSourceChange: {
onControlSourceChange(payload.data)
break
}
case EBizCode.FlyToPointProgress: {
const { sn: deviceSn, result, message: msg } = payload.data as FlyToPointMessage
if (deviceSn !== sn) return
handleProgress(EBizCode.FlyToPointProgress, `device(sn: ${deviceSn}) ${msg}`, result)
break
}
case EBizCode.TakeoffToPointProgress: {
const { sn: deviceSn, result, message: msg } = payload.data as TakeoffToPointMessage
if (deviceSn !== sn) return
handleProgress(EBizCode.TakeoffToPointProgress, `device(sn: ${deviceSn}) ${msg}`, result)
break
}
case EBizCode.JoystickInvalidNotify: {
const { sn: deviceSn, result, message: msg } = payload.data as DrcModeExitNotifyMessage
if (deviceSn !== sn) return
handleProgress(EBizCode.JoystickInvalidNotify, `device(sn: ${deviceSn}) ${msg}`, result)
break
}
case EBizCode.DrcStatusNotify: {
const { sn: deviceSn, result, message: msg } = payload.data as DrcStatusNotifyMessage
if (deviceSn !== sn) return
// handleProgress(EBizCode.DrcStatusNotify, `device(sn: ${deviceSn}) ${msg}`, result)
break
}
}
// eslint-disable-next-line no-unused-expressions
// console.log('payload.biz_code', payload.data)
}
onMounted(() => {
EventBus.on('droneControlWs', handleDroneControlWsEvent)
})
onBeforeUnmount(() => {
EventBus.off('droneControlWs', handleDroneControlWsEvent)
})
return {
droneControlSource: droneControlSource,
payloadControlSource: payloadControlSource
}
}

40
src/components/g-map/use-drone-control.ts

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
import { ref } from 'vue'
import { postFlyToPoint, PostFlyToPointBody, deleteFlyToPoint, postTakeoffToPoint, PostTakeoffToPointBody } from '/@/api/drone-control/drone'
import { message } from 'ant-design-vue'
export function useDroneControl () {
const droneControlPanelVisible = ref(false)
function setDroneControlPanelVisible (visible: boolean) {
droneControlPanelVisible.value = visible
}
async function flyToPoint (sn: string, body: PostFlyToPointBody) {
const { code } = await postFlyToPoint(sn, body)
if (code === 0) {
message.success('Fly to')
}
}
async function stopFlyToPoint (sn: string) {
const { code } = await deleteFlyToPoint(sn)
if (code === 0) {
message.success('Stop fly to')
}
}
async function takeoffToPoint (sn: string, body: PostTakeoffToPointBody) {
const { code } = await postTakeoffToPoint(sn, body)
if (code === 0) {
message.success('Take off successfully')
}
}
return {
droneControlPanelVisible,
setDroneControlPanelVisible,
flyToPoint,
stopFlyToPoint,
takeoffToPoint
}
}

162
src/components/g-map/use-manual-control.ts

@ -0,0 +1,162 @@ @@ -0,0 +1,162 @@
import {
ref,
onUnmounted,
watch,
Ref,
} from 'vue'
import { message } from 'ant-design-vue'
import {
DRC_METHOD,
DroneControlProtocol,
} from '/@/types/drc'
import {
useMqtt,
DeviceTopicInfo
} from './use-mqtt'
let myInterval: any
export enum KeyCode {
KEY_W = 'KeyW',
KEY_A = 'KeyA',
KEY_S = 'KeyS',
KEY_D = 'KeyD',
KEY_Q = 'KeyQ',
KEY_E = 'KeyE',
ARROW_UP = 'ArrowUp',
ARROW_DOWN = 'ArrowDown',
}
export function useManualControl (deviceTopicInfo: DeviceTopicInfo, isCurrentFlightController: Ref<boolean>) {
const activeCodeKey = ref(null) as Ref<KeyCode | null>
const mqttHooks = useMqtt(deviceTopicInfo)
function handlePublish (params: DroneControlProtocol) {
const body = {
method: DRC_METHOD.DRONE_CONTROL,
data: params,
}
handleClearInterval()
myInterval = setInterval(() => {
window.console.log('keyCode>>>>', activeCodeKey.value, body)
body.data.seq = new Date().getTime()
mqttHooks?.publishMqtt(deviceTopicInfo.pubTopic, body, { qos: 0 })
}, 50)
}
function handleKeyup (keyCode: KeyCode) {
if (!deviceTopicInfo.pubTopic) {
message.error('请确保已经建立DRC链路')
return
}
const SPEED = 5 // check
const HEIGHT = 5 // check
const W_SPEED = 20 // 机头角速度
switch (keyCode) {
case 'KeyA':
if (activeCodeKey.value === keyCode) return
handlePublish({ y: -SPEED })
activeCodeKey.value = keyCode
break
case 'KeyW':
if (activeCodeKey.value === keyCode) return
handlePublish({ x: SPEED })
activeCodeKey.value = keyCode
break
case 'KeyS':
if (activeCodeKey.value === keyCode) return
handlePublish({ x: -SPEED })
activeCodeKey.value = keyCode
break
case 'KeyD':
if (activeCodeKey.value === keyCode) return
handlePublish({ y: SPEED })
activeCodeKey.value = keyCode
break
case 'ArrowUp':
if (activeCodeKey.value === keyCode) return
handlePublish({ h: HEIGHT })
activeCodeKey.value = keyCode
break
case 'ArrowDown':
if (activeCodeKey.value === keyCode) return
handlePublish({ h: -HEIGHT })
activeCodeKey.value = keyCode
break
case 'KeyQ':
if (activeCodeKey.value === keyCode) return
handlePublish({ w: -W_SPEED })
activeCodeKey.value = keyCode
break
case 'KeyE':
if (activeCodeKey.value === keyCode) return
handlePublish({ w: W_SPEED })
activeCodeKey.value = keyCode
break
default:
break
}
}
function handleClearInterval () {
clearInterval(myInterval)
myInterval = undefined
}
function resetControlState () {
activeCodeKey.value = null
handleClearInterval()
}
function onKeyup () {
resetControlState()
}
function onKeydown (e: KeyboardEvent) {
handleKeyup(e.code as KeyCode)
}
function startKeyboardManualControl () {
window.addEventListener('keydown', onKeydown)
window.addEventListener('keyup', onKeyup)
}
function closeKeyboardManualControl () {
resetControlState()
window.removeEventListener('keydown', onKeydown)
window.removeEventListener('keyup', onKeyup)
}
watch(() => isCurrentFlightController.value, (val) => {
if (val && deviceTopicInfo.pubTopic) {
startKeyboardManualControl()
} else {
closeKeyboardManualControl()
}
}, { immediate: true })
onUnmounted(() => {
closeKeyboardManualControl()
})
function handleEmergencyStop () {
if (!deviceTopicInfo.pubTopic) {
message.error('请确保已经建立DRC链路')
return
}
const body = {
method: DRC_METHOD.DRONE_EMERGENCY_STOP,
data: {}
}
resetControlState()
window.console.log('handleEmergencyStop>>>>', deviceTopicInfo.pubTopic, body)
mqttHooks?.publishMqtt(deviceTopicInfo.pubTopic, body, { qos: 1 })
}
return {
activeCodeKey,
handleKeyup,
handleEmergencyStop,
resetControlState,
}
}

132
src/components/g-map/use-mqtt.ts

@ -0,0 +1,132 @@ @@ -0,0 +1,132 @@
import {
ref,
reactive,
computed,
watch,
onUnmounted,
} from 'vue'
import {
IClientPublishOptions,
IPublishPacket,
} from '/@/mqtt'
import { useMyStore } from '/@/store'
import {
DRC_METHOD,
} from '/@/types/drc'
import EventBus from '/@/event-bus'
export interface DeviceTopicInfo{
sn: string
pubTopic: string
subTopic: string
}
type MessageMqtt = (topic: string, payload: Buffer, packet: IPublishPacket) => void | Promise<void>
export function useMqtt (deviceTopicInfo: DeviceTopicInfo) {
let cacheSubscribeArr: {
topic: string;
callback?: MessageMqtt;
}[] = []
const store = useMyStore()
const mqttState = computed(() => {
return store.state.mqttState
})
function publishMqtt (topic: string, body: object, ots?: IClientPublishOptions) {
// const buffer = Buffer.from(JSON.stringify(body))
mqttState.value?.publishMqtt(topic, JSON.stringify(body), ots)
}
function subscribeMqtt (topic: string, handleMessageMqtt?: MessageMqtt) {
mqttState.value?.subscribeMqtt(topic)
const handler = handleMessageMqtt || onMessageMqtt
mqttState.value?.on('onMessageMqtt', handler)
cacheSubscribeArr.push({
topic,
callback: handler,
})
}
function onMessageMqtt (message: any) {
if (cacheSubscribeArr.findIndex(item => item.topic === message?.topic) !== -1) {
const payloadStr = new TextDecoder('utf-8').decode(message?.payload)
const payloadObj = JSON.parse(payloadStr)
switch (payloadObj?.method) {
case DRC_METHOD.HEART_BEAT:
break
case DRC_METHOD.DELAY_TIME_INFO_PUSH:
case DRC_METHOD.HSI_INFO_PUSH:
case DRC_METHOD.OSD_INFO_PUSH:
EventBus.emit('droneControlMqttInfo', payloadObj)
break
default:
break
}
}
}
function unsubscribeDrc () {
// 销毁已订阅事件
cacheSubscribeArr.forEach(item => {
mqttState.value?.off('onMessageMqtt', item.callback)
mqttState.value?.unsubscribeMqtt(item.topic)
})
cacheSubscribeArr = []
}
// 心跳
const heartBeatSeq = ref(0)
const state = reactive({
heartState: new Map<string, {
pingInterval: any;
}>(),
})
// 监听云控控制权
watch(() => deviceTopicInfo, (val, oldVal) => {
if (val.subTopic !== '') {
// 1.订阅topic
subscribeMqtt(deviceTopicInfo.subTopic)
// 2.发心跳
publishDrcPing(deviceTopicInfo.sn)
} else {
clearInterval(state.heartState.get(deviceTopicInfo.sn)?.pingInterval)
state.heartState.delete(deviceTopicInfo.sn)
heartBeatSeq.value = 0
}
}, { immediate: true, deep: true })
function publishDrcPing (sn: string) {
const body = {
method: DRC_METHOD.HEART_BEAT,
data: {
ts: new Date().getTime(),
seq: heartBeatSeq.value,
},
}
const pingInterval = setInterval(() => {
if (!mqttState.value) return
heartBeatSeq.value += 1
body.data.ts = new Date().getTime()
body.data.seq = heartBeatSeq.value
publishMqtt(deviceTopicInfo.pubTopic, body, { qos: 0 })
}, 1000)
state.heartState.set(sn, {
pingInterval,
})
}
onUnmounted(() => {
unsubscribeDrc()
heartBeatSeq.value = 0
})
return {
mqttState,
publishMqtt,
subscribeMqtt,
}
}

120
src/components/g-map/use-payload-control.ts

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
import { message } from 'ant-design-vue'
import {
postPayloadAuth,
postPayloadCommands,
PayloadCommandsEnum,
PostCameraModeBody,
PostCameraFocalLengthBody,
PostGimbalResetBody,
PostCameraAimBody,
} from '/@/api/drone-control/payload'
import { ControlSource } from '/@/types/device'
export function usePayloadControl () {
function checkPayloadAuth (controlSource?: ControlSource) {
if (controlSource !== ControlSource.A) {
message.error('Get Payload Control first')
return false
}
return true
}
async function authPayload (sn: string, payloadIndx: string) {
const { code } = await postPayloadAuth(sn, {
payload_index: payloadIndx
})
if (code === 0) {
message.success('Get Payload Control successfully')
return true
}
return false
}
async function resetGimbal (sn: string, data: PostGimbalResetBody) {
const { code } = await postPayloadCommands(sn, {
cmd: PayloadCommandsEnum.GimbalReset,
data: data
})
if (code === 0) {
message.success('Gimbal Reset successfully')
}
}
async function switchCameraMode (sn: string, data: PostCameraModeBody) {
const { code } = await postPayloadCommands(sn, {
cmd: PayloadCommandsEnum.CameraModeSwitch,
data: data
})
if (code === 0) {
message.success('Camera Mode Switch successfully')
}
}
async function takeCameraPhoto (sn: string, payloadIndx: string) {
const { code } = await postPayloadCommands(sn, {
cmd: PayloadCommandsEnum.CameraPhotoTake,
data: {
payload_index: payloadIndx
}
})
if (code === 0) {
message.success('Take Photo successfully')
}
}
async function startCameraRecording (sn: string, payloadIndx: string) {
const { code } = await postPayloadCommands(sn, {
cmd: PayloadCommandsEnum.CameraRecordingStart,
data: {
payload_index: payloadIndx
}
})
if (code === 0) {
message.success('Start Recording successfully')
}
}
async function stopCameraRecording (sn: string, payloadIndx: string) {
const { code } = await postPayloadCommands(sn, {
cmd: PayloadCommandsEnum.CameraRecordingStop,
data: {
payload_index: payloadIndx
}
})
if (code === 0) {
message.success('Stop Recording successfully')
}
}
async function changeCameraFocalLength (sn: string, data: PostCameraFocalLengthBody) {
const { code } = await postPayloadCommands(sn, {
cmd: PayloadCommandsEnum.CameraFocalLengthSet,
data: data,
})
if (code === 0) {
message.success('Zoom successfully')
}
}
async function cameraAim (sn: string, data: PostCameraAimBody) {
const { code } = await postPayloadCommands(sn, {
cmd: PayloadCommandsEnum.CameraAim,
data: data,
})
if (code === 0) {
message.success('Zoom Aim successfully')
}
}
return {
checkPayloadAuth,
authPayload,
resetGimbal,
switchCameraMode,
takeCameraPhoto,
startCameraRecording,
stopCameraRecording,
changeCameraFocalLength,
cameraAim,
}
}

3
src/components/task/CreatePlan.vue

@ -182,7 +182,8 @@ function onSubmit () { @@ -182,7 +182,8 @@ function onSubmit () {
disabled.value = true
const createPlanBody = { ...planBody } as unknown as CreatePlan
if (planBody.select_execute_time) {
createPlanBody.execute_time = moment(planBody.select_execute_time).valueOf()
createPlanBody.task_days = [moment(planBody.select_execute_time).unix()]
createPlanBody.task_periods = [createPlanBody.task_days]
}
createPlanBody.rth_altitude = Number(createPlanBody.rth_altitude)
if (wayline.value && wayline.value.template_types && wayline.value.template_types.length > 0) {

59
src/components/task/TaskPanel.vue

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
:pagination="paginationProp" :scroll="{ x: '100%', y: 600 }" @change="refreshData">
<!-- 执行时间 -->
<template #duration="{ record }">
<div class="flex-row">
<div class="flex-row" style="white-space: pre-wrap">
<div>
<div>{{ formatTaskTime(record.begin_time) }}</div>
<div>{{ formatTaskTime(record.end_time) }}</div>
@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
</template>
<!-- 操作 -->
<template #action="{ record }">
<span class="action-area">
<div class="action-area">
<a-popconfirm
v-if="record.status === TaskStatus.Wait"
title="Are you sure you want to delete flight task?"
@ -72,7 +72,25 @@ @@ -72,7 +72,25 @@
>
<a-button type="primary" size="small">Delete</a-button>
</a-popconfirm>
</span>
<a-popconfirm
v-if="record.status === TaskStatus.Carrying"
title="Are you sure you want to suspend?"
ok-text="Yes"
cancel-text="No"
@confirm="onSuspendTask(record.job_id)"
>
<a-button type="primary" size="small">Suspend</a-button>
</a-popconfirm>
<a-popconfirm
v-if="record.status === TaskStatus.Paused"
title="Are you sure you want to resume?"
ok-text="Yes"
cancel-text="No"
@confirm="onResumeTask(record.job_id)"
>
<a-button type="primary" size="small">Resume</a-button>
</a-popconfirm>
</div>
</template>
</a-table>
</div>
@ -84,7 +102,7 @@ import { message } from 'ant-design-vue' @@ -84,7 +102,7 @@ import { message } from 'ant-design-vue'
import { TableState } from 'ant-design-vue/lib/table/interface'
import { onMounted } from 'vue'
import { IPage } from '/@/api/http/type'
import { deleteTask, getWaylineJobs, Task, uploadMediaFileNow } from '/@/api/wayline'
import { deleteTask, updateTaskStatus, UpdateTaskStatus, getWaylineJobs, Task, uploadMediaFileNow } from '/@/api/wayline'
import { useMyStore } from '/@/store'
import { ELocalStorageKey } from '/@/types/enums'
import { useFormatTask } from './use-format-task'
@ -272,6 +290,30 @@ async function onDeleteTask (jobId: string) { @@ -272,6 +290,30 @@ async function onDeleteTask (jobId: string) {
}
}
//
async function onSuspendTask (jobId: string) {
const { code } = await updateTaskStatus(workspaceId, {
job_id: jobId,
status: UpdateTaskStatus.Suspend
})
if (code === 0) {
message.success('Suspended successfully')
getPlans()
}
}
//
async function onResumeTask (jobId: string) {
const { code } = await updateTaskStatus(workspaceId, {
job_id: jobId,
status: UpdateTaskStatus.Resume
})
if (code === 0) {
message.success('Resumed successfully')
getPlans()
}
}
//
async function onUploadMediaFileNow (jobId: string) {
const { code } = await uploadMediaFileNow(workspaceId, jobId)
@ -291,8 +333,13 @@ async function onUploadMediaFileNow (jobId: string) { @@ -291,8 +333,13 @@ async function onUploadMediaFileNow (jobId: string) {
margin-top: 10px;
}
.action-area {
color: $primary;
cursor: pointer;
&::v-deep {
.ant-btn {
margin-right: 10px;
margin-bottom: 10px;
}
}
}
.circle-icon {

2
src/event-bus/index.ts

@ -4,6 +4,8 @@ type Events = { @@ -4,6 +4,8 @@ type Events = {
deviceUpgrade: any; // 设备升级
deviceLogUploadProgress: any // 设备日志上传
flightTaskWs: any // 机场任务消息
droneControlWs: any // 飞行指令信息
droneControlMqttInfo: any // drc 链路通知
};
const emitter: Emitter<Events> = mitt<Events>()

3
src/hooks/use-g-map-tsa.ts

@ -1,12 +1,11 @@ @@ -1,12 +1,11 @@
import store from '/@/store'
import { getRoot } from '/@/root'
import { ELocalStorageKey } from '/@/types'
import { ELocalStorageKey, EDeviceTypeName } from '/@/types'
import { getDeviceBySn } from '/@/api/manage'
import { message } from 'ant-design-vue'
import dockIcon from '/@/assets/icons/dock.png'
import rcIcon from '/@/assets/icons/rc.png'
import droneIcon from '/@/assets/icons/drone.png'
import { EDeviceTypeName } from '/@/types'
export function deviceTsaUpdate () {
const root = getRoot()

12
src/mqtt/config.ts

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
import {
IClientOptions,
} from 'mqtt'
export const OPTIONS: IClientOptions = {
clean: true, // true: 清除会话, false: 保留会话
connectTimeout: 10000, // mqtt 超时时间
resubscribe: true, // 断开重连后,再次订阅原订阅
reconnectPeriod: 10000, // 重连间隔时间: 5s
keepalive: 1, // 心跳间隔时间:1s
}

117
src/mqtt/index.ts

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
import EventEmitter from 'eventemitter3'
import {
OPTIONS,
} from './config'
import {
connect,
MqttClient,
IClientPublishOptions,
IPublishPacket,
Packet,
ISubscriptionGrant,
IClientOptions,
} from 'mqtt/dist/mqtt.min'
export class UranusMqtt extends EventEmitter {
_url: string
_options?: IClientOptions
_client: MqttClient | null
_hasInit: boolean
constructor (url?: string, options?: IClientOptions) {
super()
this._url = url || ''
this._options = options
this._client = null
this._hasInit = false
}
initMqtt = () => {
// 仅初始化一次
if (this._hasInit) return
// 建立连接
this._client = connect(this._url, {
...OPTIONS,
...this._options,
})
this._hasInit = true
if (this._client) {
this._client.on('reconnect', this._onReconnect)
// 消息监听
this._client.on('message', this._onMessage)
// 连接关闭
this._client.on('close', this._onClose)
// 连接异常
this._client.on('error', this._onError)
}
}
// 发布
publishMqtt = (topic: string, body: string | Buffer, opts?: IClientPublishOptions) => {
if (!this._client?.connected) {
this.initMqtt()
}
this._client?.publish(topic, body, opts || {}, (error?: Error, packet?: Packet) => {
if (error) {
window.console.error('mqtt publish error,', error, packet)
}
})
}
// 订阅
subscribeMqtt = (topic: string) => {
if (!this._client?.connected) {
this.initMqtt()
}
window.console.log('subscribeMqtt>>>>>', topic)
this._client?.subscribe(topic, (error: Error, granted: ISubscriptionGrant[]) => {
window.console.log('mqtt subscribe,', error, granted)
})
}
// 取消订阅
unsubscribeMqtt = (topic: string) => {
window.console.log('mqtt unsubscribeMqtt,', topic)
this._client?.unsubscribe(topic)
}
// 关闭 mqtt 客户端
destroyed = () => {
window.console.log('mqtt destroyed')
this._client?.end()
}
_onReconnect = () => {
if (this._client) { window.console.error('mqtt reconnect,') }
}
_onMessage = (topic: string, payload: Buffer, packet: IPublishPacket) => {
this.emit('onMessageMqtt', { topic, payload, packet })
}
_onClose = () => {
// 连接异常关闭会自动重连
window.console.error('mqtt close,')
this.emit('onStatus', {
status: 'close',
})
}
_onError = (error: Error) => {
// 连接错误会自动重连
window.console.error('mqtt error,', error)
this.emit('onStatus', {
status: 'error',
data: error,
})
}
}
export {
IClientOptions,
IPublishPacket,
IClientPublishOptions,
}

6
src/pages/page-web/projects/Firmwares.vue

@ -242,7 +242,7 @@ const uploadFile = async () => { @@ -242,7 +242,7 @@ const uploadFile = async () => {
if (fileList.value.length === 0) {
message.error('Please select at least one file.')
}
const uploading: string = 'uploading'
let uploading: string
formRef.value.validate().then(async () => {
const file: FileItem = fileList.value[0]
const fileData = new FormData()
@ -257,6 +257,8 @@ const uploadFile = async () => { @@ -257,6 +257,8 @@ const uploadFile = async () => {
fileData.append(key, val.toString())
}
})
const timestamp = new Date().getTime()
uploading = (file.name ?? 'uploding') + timestamp
notification.open({
key: uploading,
message: `Uploading ${moment().format()}`,
@ -267,7 +269,7 @@ const uploadFile = async () => { @@ -267,7 +269,7 @@ const uploadFile = async () => {
if (res.code === 0) {
notification.success({
message: `Uploaded ${moment().format()}`,
description: `[${file.name}] file uploaded successfully.`,
description: `[${file.name}] file uploaded successfully. Duration: ${moment.duration(new Date().getTime() - timestamp).asSeconds()}`,
duration: null
})
getAllFirmwares(pageParam)

17
src/pages/page-web/projects/devices.vue

@ -20,7 +20,9 @@ @@ -20,7 +20,9 @@
style="margin: -5px 0"
/>
<template v-else>
{{ text }}
<a-tooltip :title="text">
{{ text }}
</a-tooltip>
</template>
</div>
</template>
@ -127,7 +129,7 @@ import { useDeviceUpgradeEvent } from '/@/components/devices/device-upgrade/use- @@ -127,7 +129,7 @@ import { useDeviceUpgradeEvent } from '/@/components/devices/device-upgrade/use-
import { DeviceCmdExecuteInfo, DeviceCmdExecuteStatus } from '/@/types/device-cmd'
import DeviceLogUploadRecordDrawer from '/@/components/devices/device-log/DeviceLogUploadRecordDrawer.vue'
import DeviceHmsDrawer from '/@/components/devices/device-hms/DeviceHmsDrawer.vue'
import { message } from 'ant-design-vue'
import { message, notification } from 'ant-design-vue'
interface DeviceData {
device: Device[]
@ -268,13 +270,18 @@ function updateDevicesByWs (devices: Device[], payload: DeviceCmdExecuteInfo) { @@ -268,13 +270,18 @@ function updateDevicesByWs (devices: Device[], payload: DeviceCmdExecuteInfo) {
for (let i = 0; i < devices.length; i++) {
if (devices[i].device_sn === payload.sn) {
if (!payload.output) return
const { status, progress } = payload.output
const { status, progress, ext } = payload.output
if (status === DeviceCmdExecuteStatus.Sent || status === DeviceCmdExecuteStatus.InProgress) { //
const rate = ext?.rate ? (ext.rate / 1024).toFixed(2) + 'kb/s' : ''
devices[i].firmware_status = DeviceFirmwareStatusEnum.DuringUpgrade
devices[i].firmware_progress = progress?.percent || 0
devices[i].firmware_progress = (progress?.percent || 0) + '% ' + rate
} else { //
if (status === DeviceCmdExecuteStatus.Failed || status === DeviceCmdExecuteStatus.Timeout) {
message.error(`设备(${payload.sn}) 升级失败`)
notification.error({
message: `(${payload.sn}) Upgrade failed`,
description: `Error Code: ${payload.result}`,
duration: null
})
}
//
getDevices(current.value[0], true)

2
src/pages/page-web/projects/dock.vue

@ -58,7 +58,7 @@ onMounted(() => { @@ -58,7 +58,7 @@ onMounted(() => {
getDocks()
const key = setInterval(() => {
const data = document.getElementById('data')?.lastElementChild as HTMLDivElement
if (body.total === 0 || Math.ceil(body.total / body.page_size) <= body.page || scorllHeight.value <= data?.clientHeight + data?.offsetTop) {
if (body.total === 0 || Math.ceil(body.total / body.page_size) <= body.page || scorllHeight.value + 50 <= data?.clientHeight + data?.offsetTop) {
clearInterval(key)
return
}

5
src/pages/page-web/projects/livestream.vue

@ -31,8 +31,8 @@ import { CloseOutlined } from '@ant-design/icons-vue' @@ -31,8 +31,8 @@ import { CloseOutlined } from '@ant-design/icons-vue'
import { getRoot } from '/@/root'
import { ERouterName } from '/@/types'
const root = getRoot()
const routeName = ref<string>()
const showLive = ref<boolean>(false)
const routeName = ref<string>('LiveOthers')
const showLive = ref<boolean>(root.$route.name === ERouterName.LIVING)
const options = [
{ key: 0, label: 'Agora Live', path: '/' + ERouterName.LIVESTREAM + '/' + ERouterName.LIVING, routeName: 'LiveAgora' },
@ -40,6 +40,7 @@ const options = [ @@ -40,6 +40,7 @@ const options = [
]
const selectLivestream = (route: string) => {
showLive.value = root.$route.name === ERouterName.LIVING
routeName.value = route
}

43
src/pages/page-web/projects/tsa.vue

@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
<div style="float: left; padding: 0px 5px 8px 8px; width: 88%">
<div style="width: 80%; height: 30px; line-height: 30px; font-size: 16px;">
<a-tooltip :title="`${dock.gateway.callsign} - ${dock.callsign ?? 'No Drone'}`">
<span class="text-hidden" style="max-width: 200px;">{{ dock.gateway.callsign }} - {{ dock.callsign ?? 'No Drone' }}</span>
<div class="text-hidden" style="max-width: 200px;">{{ dock.gateway.callsign }} - {{ dock.callsign ?? 'No Drone' }}</div>
</a-tooltip>
</div>
<div class="mt5 flex-align-center flex-row flex-justify-between" style="background: #595959;">
<div class="flex-align-center flex-row">
<span class="ml5 mr5"><RobotOutlined /></span>
<span class="font-bold text-hidden" style="max-width: 80px;" :style="dockInfo[dock.gateway.sn] && dockInfo[dock.gateway.sn].basic_osd?.mode_code !== EDockModeCode.Disconnected ? 'color: #00ee8b' : 'color: red;'">
<div class="font-bold text-hidden" style="max-width: 80px;" :style="dockInfo[dock.gateway.sn] && dockInfo[dock.gateway.sn].basic_osd?.mode_code !== EDockModeCode.Disconnected ? 'color: #00ee8b' : 'color: red;'">
{{ dockInfo[dock.gateway.sn] ? EDockModeCode[dockInfo[dock.gateway.sn].basic_osd?.mode_code] : EDockModeCode[EDockModeCode.Disconnected] }}
</span>
</div>
</div>
<div class="mr5 flex-align-center flex-row" style="width: 85px; margin-right: 0; height: 18px;">
<div v-if="hmsInfo[dock.gateway.sn]" class="flex-align-center flex-row">
@ -75,11 +75,11 @@ @@ -75,11 +75,11 @@
</div>
</div>
<div class="mt5 flex-align-center flex-row flex-justify-between" style="background: #595959;">
<div>
<div class="flex-row">
<span class="ml5 mr5"><RocketOutlined /></span>
<span class="font-bold" :style="deviceInfo[dock.sn] && deviceInfo[dock.sn].mode_code !== EModeCode.Disconnected ? 'color: #00ee8b' : 'color: red;'">
<div class="font-bold text-hidden" style="max-width: 80px" :style="deviceInfo[dock.sn] && deviceInfo[dock.sn].mode_code !== EModeCode.Disconnected ? 'color: #00ee8b' : 'color: red;'">
{{ deviceInfo[dock.sn] ? EModeCode[deviceInfo[dock.sn].mode_code] : EModeCode[EModeCode.Disconnected] }}
</span>
</div>
</div>
<div class="mr5 flex-align-center flex-row" style="width: 85px; margin-right: 0; height: 18px;">
<div v-if="hmsInfo[dock.sn]" class="flex-align-center flex-row">
@ -173,11 +173,11 @@ @@ -173,11 +173,11 @@
</div>
</div>
<div class="flex-row flex-justify-center flex-align-center" style="height: 40px;">
<div style="height: 20px; background: #595959; width: 94%;" >
<div class="flex-row" style="height: 20px; background: #595959; width: 94%;" >
<span class="mr5"><a-image style="margin-left: 2px; margin-top: -2px; height: 20px; width: 20px;" :src="rc" /></span>
<a-tooltip>
<template #title>{{ device.gateway.model }} - {{ device.gateway.callsign }} </template>
<span class="text-hidden" style="max-width: 200px;">{{ device.gateway.model }} - {{ device.gateway.callsign }}</span>
<div class="text-hidden" style="max-width: 200px;">{{ device.gateway.model }} - {{ device.gateway.callsign }}</div>
</a-tooltip>
</div>
</div>
@ -194,10 +194,9 @@ import { computed, onMounted, reactive, ref, watch, WritableComputedRef } from ' @@ -194,10 +194,9 @@ import { computed, onMounted, reactive, ref, watch, WritableComputedRef } from '
import { EDeviceTypeName, ELocalStorageKey } from '/@/types'
import noData from '/@/assets/icons/no-data.png'
import rc from '/@/assets/icons/rc.png'
import { DeviceStatus, EModeCode, OSDVisible, EDockModeCode, DeviceOsd } from '/@/types/device'
import { OnlineDevice, EModeCode, OSDVisible, EDockModeCode, DeviceOsd } from '/@/types/device'
import { useMyStore } from '/@/store'
import { getDeviceTopo, getUnreadDeviceHms, updateDeviceHms } from '/@/api/manage'
import { message } from 'ant-design-vue'
import { RocketOutlined, EyeInvisibleOutlined, EyeOutlined, RobotOutlined, DoubleRightOutlined } from '@ant-design/icons-vue'
import { EHmsLevel } from '/@/types/enums'
@ -208,22 +207,6 @@ const osdVisible = ref({} as OSDVisible) @@ -208,22 +207,6 @@ const osdVisible = ref({} as OSDVisible)
const hmsVisible = new Map<string, boolean>()
const scorllHeight = ref()
interface OnlineDevice {
model: string,
callsign: string,
sn: string,
mode: number,
gateway: {
model: string,
callsign: string,
sn: string,
domain: string,
},
payload: {
model: string
}[]
}
const onlineDevices = reactive({
data: [] as OnlineDevice[]
})
@ -286,7 +269,12 @@ function getOnlineTopo () { @@ -286,7 +269,12 @@ function getOnlineTopo () {
}
child?.payloads_list.forEach((payload: any) => {
device.payload.push({
model: payload.payload_name
index: payload.index,
model: payload.model,
payload_name: payload.payload_name,
payload_sn: payload.payload_sn,
control_source: payload.control_source,
payload_index: payload.payload_index
})
})
if (EDeviceTypeName.Dock === gateway.domain) {
@ -316,6 +304,7 @@ function switchVisible (e: any, device: OnlineDevice, isDock: boolean, isClick: @@ -316,6 +304,7 @@ function switchVisible (e: any, device: OnlineDevice, isDock: boolean, isClick:
osdVisible.value.gateway_sn = device.gateway.sn
osdVisible.value.is_dock = isDock
osdVisible.value.gateway_callsign = device.gateway.callsign
osdVisible.value.payloads = device.payload
}
store.commit('SET_OSD_VISIBLE_INFO', osdVisible)
}

9
src/pages/page-web/projects/workspace.vue

@ -100,6 +100,15 @@ const messageHandler = async (payload: any) => { @@ -100,6 +100,15 @@ const messageHandler = async (payload: any) => {
})
break
}
case EBizCode.ControlSourceChange:
case EBizCode.FlyToPointProgress:
case EBizCode.TakeoffToPointProgress:
case EBizCode.JoystickInvalidNotify:
case EBizCode.DrcStatusNotify:
{
EventBus.emit('droneControlWs', payload)
break
}
default:
break
}

4
src/shims-mqtt.d.ts vendored

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
declare module 'mqtt/dist/mqtt.min' {
import MQTT from 'mqtt'
export = MQTT
}

22
src/store/index.ts

@ -67,13 +67,14 @@ const initStateFunc = () => ({ @@ -67,13 +67,14 @@ const initStateFunc = () => ({
currentSn: '',
currentType: -1
},
osdVisible: {
osdVisible: { // osd 显示设备相关信息
sn: '',
callsign: '',
model: '',
visible: false,
gateway_sn: '',
is_dock: false,
payloads: null
} as OSDVisible,
waylineInfo: {
@ -86,7 +87,9 @@ const initStateFunc = () => ({ @@ -86,7 +87,9 @@ const initStateFunc = () => ({
},
// 机场指令执行状态信息
devicesCmdExecuteInfo: {
} as DevicesCmdExecuteInfo
} as DevicesCmdExecuteInfo,
mqttState: null as any, // mqtt 实例
clientId: '', // mqtt 连接 唯一客户端id
})
export type RootStateType = ReturnType<typeof initStateFunc>
@ -117,15 +120,18 @@ const mutations: MutationTree<RootStateType> = { @@ -117,15 +120,18 @@ const mutations: MutationTree<RootStateType> = {
state.deviceState.currentSn = info.sn
state.deviceState.currentType = EDeviceTypeName.Dock
const dock = state.deviceState.dockInfo[info.sn]
if (info.host.mode_code !== undefined) {
dock.basic_osd = info.host
return
}
if (info.host.sdr) {
dock.link_osd = info.host
return
}
if (info.host.job_number) {
if (info.host.job_number !== undefined) {
dock.work_osd = info.host
return
}
dock.basic_osd = info.host
},
SET_DRAW_VISIBLE_INFO (state, bool) {
state.drawVisible = bool
@ -182,7 +188,13 @@ const mutations: MutationTree<RootStateType> = { @@ -182,7 +188,13 @@ const mutations: MutationTree<RootStateType> = {
} else {
state.devicesCmdExecuteInfo[info.sn] = [info]
}
}
},
SET_MQTT_STATE (state, mqttState) {
state.mqttState = mqttState
},
SET_CLIENT_ID (state, clientId) {
state.clientId = clientId
},
}
const actions: ActionTree<RootStateType, RootStateType> = {

21
src/types/device-cmd.ts

@ -39,6 +39,16 @@ export interface DeviceCmdItem{ @@ -39,6 +39,16 @@ export interface DeviceCmdItem{
loading: boolean // 按钮loading
disabled?: boolean // 按钮disabled
}
export const noDebugCmdList: DeviceCmdItem[] = [
{
label: 'Return Home',
status: '--',
operateText: 'Return Home',
cmdKey: DeviceCmd.ReturnHome,
func: 'returnHome',
loading: false,
},
]
// 机场指令
export const cmdList: DeviceCmdItem[] = [
@ -90,14 +100,6 @@ export const cmdList: DeviceCmdItem[] = [ @@ -90,14 +100,6 @@ export const cmdList: DeviceCmdItem[] = [
func: 'chargeStatus',
loading: false,
},
{
label: '一键返航',
status: '--',
operateText: '返航',
cmdKey: DeviceCmd.ReturnHome,
func: 'returnHome',
loading: false,
},
{
label: '机场存储',
status: '--',
@ -281,6 +283,9 @@ export interface DeviceCmdExecuteInfo { @@ -281,6 +283,9 @@ export interface DeviceCmdExecuteInfo {
percent: number,
step_key: string,
step_result: number
},
ext?: {
rate?: number
}
}
result: number,

103
src/types/device.ts

@ -1,6 +1,8 @@ @@ -1,6 +1,8 @@
import { commonColor } from '/@/utils/color'
import { NightLightsStateEnum, DistanceLimitStatus, ObstacleAvoidance } from './device-setting'
import { AlarmModeEnum, BatteryStoreModeEnum, DroneBatteryStateEnum, FourGLinkStateEnum, SdrLinkStateEnum, LinkWorkModeEnum } from './airport-tsa'
import { CameraMode } from '/@/types/live-stream'
export interface DeviceValue {
key: string; // 'domain-type-subtype'
domain: string; // 表示一个领域,作为一个命名空间,暂时分 飞机类-0, 负载类-1,RC类-2,机场类-3 4种
@ -20,10 +22,6 @@ export enum DOMAIN { @@ -20,10 +22,6 @@ export enum DOMAIN {
export enum DRONE_TYPE {
M30 = 67,
M300 = 60,
Phantom4 = 11,
Phantom4Pro = 18,
Phantom4RTK = 59,
Phantom4Advanced = 27,
Mavic3EnterpriseAdvanced= 77,
}
@ -76,10 +74,6 @@ export const DEVICE_MODEL_KEY = { @@ -76,10 +74,6 @@ export const DEVICE_MODEL_KEY = {
M3T: `${DOMAIN.DRONE}-${DRONE_TYPE.Mavic3EnterpriseAdvanced}-${DEVICE_SUB_TYPE.ONE}`,
M300: `${DOMAIN.DRONE}-${DRONE_TYPE.M300}-${DEVICE_SUB_TYPE.ZERO}`,
Phantom4: `${DOMAIN.DRONE}-${DRONE_TYPE.Phantom4}-${DEVICE_SUB_TYPE.ZERO}`,
Phantom4Pro: `${DOMAIN.DRONE}-${DRONE_TYPE.Phantom4Pro}-${DEVICE_SUB_TYPE.ZERO}`,
Phantom4RTK: `${DOMAIN.DRONE}-${DRONE_TYPE.Phantom4RTK}-${DEVICE_SUB_TYPE.ZERO}`,
Phantom4Advanced: `${DOMAIN.DRONE}-${DRONE_TYPE.Phantom4Advanced}-${DEVICE_SUB_TYPE.ZERO}`,
FPV: `${DOMAIN.PAYLOAD}-${PAYLOAD_TYPE.FPV}-${DEVICE_SUB_TYPE.ZERO}`,
H20: `${DOMAIN.PAYLOAD}-${PAYLOAD_TYPE.H20}-${DEVICE_SUB_TYPE.ZERO}`,
@ -113,10 +107,6 @@ export const DEVICE_NAME = { @@ -113,10 +107,6 @@ export const DEVICE_NAME = {
[DEVICE_MODEL_KEY.M3T]: 'Mavic 3T',
// [DEVICE_MODEL_KEY.M3M]: 'Mavic 3M',
[DEVICE_MODEL_KEY.M300]: 'M300 RTK',
[DEVICE_MODEL_KEY.Phantom4]: 'Phantom 4',
[DEVICE_MODEL_KEY.Phantom4Pro]: 'Phantom 4 Pro',
[DEVICE_MODEL_KEY.Phantom4RTK]: 'Phantom 4 RTK',
[DEVICE_MODEL_KEY.Phantom4Advanced]: 'Phantom 4 Advanced',
// payload
[DEVICE_MODEL_KEY.FPV]: 'FPV',
@ -143,6 +133,36 @@ export const DEVICE_NAME = { @@ -143,6 +133,36 @@ export const DEVICE_NAME = {
[DEVICE_MODEL_KEY.Dock]: 'Dock',
}
// 控制权
export enum ControlSource {
A = 'A',
B = 'B'
}
export interface PayloadInfo {
index: number,
model: string,
control_source?: ControlSource,
payload_sn?: string,
payload_index?: string,
payload_name?: string,
}
// 设备信息
export interface OnlineDevice {
model: string,
callsign: string,
sn: string,
mode: number,
gateway: {
model: string,
callsign: string,
sn: string,
domain: string,
},
payload: PayloadInfo[]
}
// 固件升级类型
export enum DeviceFirmwareTypeEnum {
ToUpgraded = 3, // 普通升级
@ -184,7 +204,7 @@ export interface Device { @@ -184,7 +204,7 @@ export interface Device {
children?: Device[],
domain: number,
type: number,
firmware_progress?: number, // 升级进度
firmware_progress?: string, // 升级进度
}
export interface DeviceStatus {
@ -207,6 +227,7 @@ export interface OSDVisible { @@ -207,6 +227,7 @@ export interface OSDVisible {
is_dock: boolean,
gateway_sn: string,
gateway_callsign: string,
payloads: null | PayloadInfo [],
}
export interface GatewayOsd {
@ -215,6 +236,24 @@ export interface GatewayOsd { @@ -215,6 +236,24 @@ export interface GatewayOsd {
longitude: number,
latitude: number,
}
export interface OsdCameraLiveview {
bottom: number,
left: number,
right: number,
top: number,
}
export interface DeviceOsdCamera {
camera_mode: CameraMode,
payload_index: string,
photo_state: number,
record_time: number,
recording_state: number,
remain_photo_num: number,
remain_record_duration: number,
liveview_world_region: OsdCameraLiveview
}
export interface DeviceOsd {
longitude: number,
latitude: number,
@ -242,6 +281,7 @@ export interface DeviceOsd { @@ -242,6 +281,7 @@ export interface DeviceOsd {
height_limit?: number;// 限高设置
distance_limit_status?: DistanceLimitStatus;// 限远开关
obstacle_avoidance?: ObstacleAvoidance;// 飞行器避障开关设置
cameras?: DeviceOsdCamera[]
}
export enum NetworkStateTypeEnum {
@ -263,16 +303,16 @@ export enum RainfallEnum { @@ -263,16 +303,16 @@ export enum RainfallEnum {
}
export enum DroneInDockEnum {
INSIDE, OUTSIDE
OUTSIDE, INSIDE
}
export interface DockBasicOsd {
network_state: {
network_state?: {
type: NetworkStateTypeEnum,
quality: number,
rate: number,
},
drone_charge_state: {
drone_charge_state?: {
state: number,
capacity_percent: number,
},
@ -285,7 +325,7 @@ export interface DockBasicOsd { @@ -285,7 +325,7 @@ export interface DockBasicOsd {
latitude: number,
longitude: number,
height: number,
alternate_land_point: {
alternate_land_point?: {
latitude: number,
longitude: number,
height: number,
@ -293,14 +333,14 @@ export interface DockBasicOsd { @@ -293,14 +333,14 @@ export interface DockBasicOsd {
is_configured: number
}
first_power_on: number,
positionState: {
positionState?: {
gps_number: number,
is_fixed: number,
rtk_number: number,
is_calibration: number,
quality: number,
},
storage: {
storage?: {
total: number,
used: number,
},
@ -308,25 +348,32 @@ export interface DockBasicOsd { @@ -308,25 +348,32 @@ export interface DockBasicOsd {
cover_state: number,
supplement_light_state: number,
emergency_stop_state: number,
air_conditioner: {
air_conditioner?: {
air_conditioner_state: number,
switch_time: number,
}
battery_store_mode?: BatteryStoreModeEnum; // 电池保养(存储)模式
alarm_state?: AlarmModeEnum; // 机场声光报警状态
putter_state: number,
sub_device: {
sub_device?: {
device_sn?: string,
device_model_key?: string,
device_online_status: number,
device_paired: number,
},
// live_capacity?: LiveCapacity; // 直播能力
// live_status?: Array<LiveStatus>; // 直播状态
}
export enum DrcStateEnum {
DISCONNECT = 0,
CONNECTING = 1,
CONNECTED = 2
}
export interface DockLinkOsd {
drc_state: DrcStateEnum,
flighttask_prepare_capacity: number,
flighttask_step_code: number,
media_file_detail: {
media_file_detail?: {
remain_upload: number
},
sdr: {
@ -334,7 +381,7 @@ export interface DockLinkOsd { @@ -334,7 +381,7 @@ export interface DockLinkOsd {
down_quality: string,
frequency_band: number,
},
wireless_link?:{
wireless_link?:{ // 图传链路<会包括4G和sdr信息
dongle_number: number, // dongle 数量
['4g_link_state']: FourGLinkStateEnum, // 4g_link_state
sdr_link_state: SdrLinkStateEnum, // sdr链路连接状态
@ -359,13 +406,13 @@ export interface DockWorkOsd { @@ -359,13 +406,13 @@ export interface DockWorkOsd {
job_number: number,
acc_time: number,
activation_time: number,
maintain_status: {
maintain_status?: {
maintain_status_array: MaintainStatus[]
}
electric_supply_voltage: number,
working_voltage: string,
working_current: string,
backup_battery: {
backup_battery?: {
voltage: number,
temperature: number,
switch: number,
@ -379,7 +426,7 @@ export interface DockWorkOsd { @@ -379,7 +426,7 @@ export interface DockWorkOsd {
export interface DockOsd {
basic_osd: DockBasicOsd,
link_osd: DockLinkOsd,
work_osd: DockWorkOsd
work_osd: DockWorkOsd
}
export enum EModeCode {
@ -460,7 +507,7 @@ export interface DeviceHms { @@ -460,7 +507,7 @@ export interface DeviceHms {
}
// TODO: 设备拓扑管理优化
// 设备信息
// 设备osd信息
export interface DeviceInfoType {
gateway: GatewayOsd, // 遥控器
dock: DockOsd, // 机场

71
src/types/drc.ts

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
export enum DRC_METHOD {
HEART_BEAT = 'heart_beat',
DRONE_CONTROL = 'drone_control', // 飞行控制-虚拟摇杆
DRONE_EMERGENCY_STOP = 'drone_emergency_stop', // 急停
OSD_INFO_PUSH = 'osd_info_push', // 高频osd信息上报
HSI_INFO_PUSH = 'hsi_info_push', // 避障信息上报
DELAY_TIME_INFO_PUSH = 'delay_info_push', // 图传链路延时信息上报
}
// 手动控制
export interface DroneControlProtocol {
x?: number; // 水平方向速度,正值为A指令 负值为D指令 单位:m/s
y?: number; // 前进后退方向速度,正值为W指令 负值为S指令 单位:m/s
h?: number;// 上下高度值,正值为上升指令 负值为下降指令 单位:m
w?: number; // 机头角速度,正值为顺时针,负值为逆时针 单位:degree/s (web端暂无此设计)
step_x?: number; // 水平方向步长
step_y?: number; // 前后方向步长
step_h?: number; // 高度方向步长
step_w?: number; // 机头转向步长
seq?: number; // 从0计时
freq?: number; // 指令发送频率
delay_time?: number; // 指令从发送到设备端接收可容忍的时间 发送频率+链路传输时长
}
// 低延时osd
export interface DRCOsdInfo {
attitude_head: number;// 飞机姿态head角,单位:度
latitude: number;// 飞机经纬度
longitude: number;
altitude: number;
speed_x: number;
speed_y: number;
speed_z: number;
gimbal_pitch: number;// 云台pitch角
gimbal_roll: number;// 云台roll角
gimbal_yaw: number;// 云台yaw角
}
// 态势感知-HSI
export interface DRCHsiInfo {
up_distance: number;// 上方的障碍物距离,单位:mm
down_distance: number;// 下方的障碍物距离,单位:mm
around_distances: number[]; // 水平方向观察点,分布在[0,360)区间,表示障碍物与飞机距离,单位为mm。 0对应机头方向正前方,顺时针分布,例如0度为机头正前方,90度为飞机正右方
up_enable: boolean; // 上视避障开关状态,true:已开启 false:已关闭
up_work: boolean; // 上视避障工作状态,true:正常工作 false:异常或离线
down_enable: boolean; // 下视避障开关状态,true:已开启 false:已关闭
down_work: boolean; // 下视避障工作状态,true:正常工作 false:异常或离线
left_enable: boolean; // 左视避障开关状态,true:已开启 false:已关闭
left_work: boolean; // 左视避障工作状态,true:正常工作 false:异常或离线
right_enable: boolean; // 右视避障开关状态,true:已开启 false:已关闭
right_work: boolean; // 右视避障工作状态,true:正常工作 false:异常或离线
front_enable: boolean; // 前视避障开关状态,true:已开启 false:已关闭
front_work: boolean; // 前视避障工作状态,true:正常工作 false:异常或离线
back_enable: boolean; // 后视避障开关状态,true:已开启 false:已关闭
back_work: boolean; // 后视避障工作状态,true:正常工作 false:异常或离线
vertical_enable: boolean; // 垂直方向综合开关状态,当本协议中上、下视开关状态均为true时,输出true:已开启,否则输出false:已关闭
vertical_work: boolean; // 垂直方向避障工作状态,当本协议中上、下视工作均为true时,输出true:正常工作,否则输出false:异常或离线
horizontal_enable: boolean; // 水平方向综合开关状态,当本协议中前、后、左、右、开关状态均为true时,输出true:已开启,否则输出false:已关闭
horizontal_work: boolean; // 水平方向避障工作综合状态,当本协议中前、后、左、右视工作均为true时,输出true:正常工作,否则输出false:异常或离线
}
export interface LiveViewDelayItem {
video_id: string;
liveview_delay_time: number;
}
// 链路时延信息
export interface DRCDelayTimeInfo {
sdr_cmd_delay: number; // sdr链路命令延时,单位:ms
liveview_delay_list: LiveViewDelayItem[];
}

68
src/types/drone-control.ts

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
import { ControlSource } from './device'
import { LostControlActionInCommandFLight, WaylineLostControlActionInCommandFlight } from '/@/api/drone-control/drone'
export enum ControlSourceChangeType {
Flight = 1,
Payload = 2,
}
// 控制权变化消息
export interface ControlSourceChangeInfo {
sn: string,
type: ControlSourceChangeType,
control_source: ControlSource
}
// 飞向目标点结果
export interface FlyToPointMessage {
sn: string,
result: number,
message: string,
}
// 一键起飞结果
export interface TakeoffToPointMessage {
sn: string,
result: number,
message: string,
}
// 设备端退出drc模式
export interface DrcModeExitNotifyMessage {
sn: string,
result: number,
message: string,
}
// 飞行控制模式状态
export interface DrcStatusNotifyMessage {
sn: string,
result: number,
message: string,
}
export const WaylineLostControlActionInCommandFlightOptions = [
{ label: 'Continue', value: WaylineLostControlActionInCommandFlight.CONTINUE },
{ label: 'Execute Lost Action', value: WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION }
]
export const LostControlActionInCommandFLightOptions = [
{ label: 'Return Home', value: LostControlActionInCommandFLight.RETURN_HOME },
{ label: 'Hover', value: LostControlActionInCommandFLight.HOVER },
{ label: 'Landing', value: LostControlActionInCommandFLight.Land }
]
// 云台重置模式
export enum GimbalResetMode {
Recenter = 0,
Down = 1,
RecenterGimbalPan = 2,
PitchDown = 3,
}
export const GimbalResetModeOptions = [
{ label: 'Gimbal Recenter', value: GimbalResetMode.Recenter },
{ label: 'Gimbal down', value: GimbalResetMode.Down },
{ label: 'Recenter Gimbal Pan', value: GimbalResetMode.RecenterGimbalPan },
{ label: 'Gimbal Pitch Down', value: GimbalResetMode.PitchDown }
]

9
src/types/enums.ts

@ -115,7 +115,14 @@ export enum EBizCode { @@ -115,7 +115,14 @@ export enum EBizCode {
DeviceUpgrade = 'ota_progress', // 设备升级
// 设备日志
DeviceLogUploadProgress = 'fileupload_progress' // 设备日志上传上传
DeviceLogUploadProgress = 'fileupload_progress', // 设备日志上传
// 飞行指令消息
ControlSourceChange = 'control_source_change', // 控制权更新
FlyToPointProgress = 'fly_to_point_progress', // 飞向目标点
TakeoffToPointProgress = 'takeoff_to_point_progress', // 一键起飞
JoystickInvalidNotify = 'joystick_invalid_notify', // 设备端退出drc模式
DrcStatusNotify = 'drc_status_notify', // 飞行控制模式状态
}
export enum EDeviceTypeName {

71
src/types/live-stream.ts

@ -53,3 +53,74 @@ export enum ELiveTypeName { @@ -53,3 +53,74 @@ export enum ELiveTypeName {
RTSP = 'RTSP',
GB28181 = 'GB28181'
}
export enum CameraMode {
Photo = 0, // 拍照
Video = 1, // 录像
}
// 镜头类型
export enum VideoType {
NORMAL = 'normal',
WIDE = 'wide',
ZOOM = 'zoom',
IR = 'ir'
}
// 镜头类型
export enum CameraType {
WIDE = 'wide',
ZOOM = 'zoom',
IR = 'ir'
}
export const CameraTypeOptions = [
{ label: CameraType.WIDE, value: CameraType.WIDE },
{ label: CameraType.ZOOM, value: CameraType.ZOOM },
{ label: CameraType.IR, value: CameraType.IR },
]
export const ZoomCameraTypeOptions = [
{ label: CameraType.ZOOM, value: CameraType.ZOOM },
{ label: CameraType.IR, value: CameraType.IR },
]
export interface VideoListItem {
video_index: string;
video_type: VideoType;
switchable_video_types?: Array<VideoType>;
}
export interface CameraListItem {
available_video_number: number;
camera_index: string;
camera_name: string;
coexist_video_number_max: number;
video_list: VideoListItem[];
// 自定义
switchCamera?: boolean;
content?: string;
// 该camera由哪个控上报的
camera_carrier_sns?: string[];
}
export interface DeviceListItem {
sn: string;
available_video_number: number;
coexist_video_number_max: number;
camera_list: CameraListItem[];
}
// export interface LiveCapacity {
// available_video_number: number;
// coexist_video_number_max: number;
// device_list: DeviceListItem[];
// }
// export interface LiveStatus {
// live_time: number; // 直播时间 该路码流已推流时间 unit: s
// live_trendline: number; // 直播带宽的使用状态 代表直播性能趋势,0-4表示overuse,其中,数值越小,表示overuse程度越大,5表示normal状态,6~10表示underuse,其中,数值越大,表示有更多比例的带宽未能充分利用
// video_id: string; // 直播码流标识符 某路在推视频码流的标识符,格式为 #{uav_sn}/#{camera_id}/#{video_index}
// video_quality: number; // 直播码流的质量 0: 自动, 1: 流畅, 2: 高清, 3: 超清
// error_status?: number; // 设备端当前状态,是错误码,需要匹配到文案上
// }

6
src/types/task.ts

@ -37,6 +37,7 @@ export enum TaskStatus { @@ -37,6 +37,7 @@ export enum TaskStatus {
Success = 3, // 完成
CanCel = 4, // 取消
Fail = 5, // 失败
Paused = 6, // 暂停
}
export const TaskStatusMap = {
@ -45,6 +46,8 @@ export const TaskStatusMap = { @@ -45,6 +46,8 @@ export const TaskStatusMap = {
[TaskStatus.Success]: 'Task completed',
[TaskStatus.CanCel]: 'Task canceled',
[TaskStatus.Fail]: 'Task failed',
[TaskStatus.Paused]: 'Paused',
}
export const TaskStatusColor = {
@ -53,6 +56,7 @@ export const TaskStatusColor = { @@ -53,6 +56,7 @@ export const TaskStatusColor = {
[TaskStatus.Success]: commonColor.NORMAL,
[TaskStatus.CanCel]: commonColor.FAIL,
[TaskStatus.Fail]: commonColor.FAIL,
[TaskStatus.Paused]: commonColor.BLUE,
}
// 任务执行 ws 消息状态
@ -93,7 +97,7 @@ export const TaskProgressWsStatusMap = { @@ -93,7 +97,7 @@ export const TaskProgressWsStatusMap = {
[TaskProgressStatus.Failed]: TaskStatus.Fail,
[TaskProgressStatus.Canceled]: TaskStatus.CanCel,
[TaskProgressStatus.Timeout]: TaskStatus.Fail,
[TaskProgressStatus.Paused]: TaskStatus.Wait,
[TaskProgressStatus.Paused]: TaskStatus.Paused,
}
// 根据媒体文件上传进度信息,前端自己判断出的状态

189
yarn.lock

@ -819,6 +819,11 @@ @@ -819,6 +819,11 @@
"mixin-deep" "^1.2.0"
"pascalcase" "^0.1.1"
"base64-js@^1.3.1":
"integrity" "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
"resolved" "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz"
"version" "1.5.1"
"big-integer@^1.6.17":
"integrity" "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg=="
"resolved" "https://registry.npmmirror.com/big-integer/download/big-integer-1.6.51.tgz"
@ -842,6 +847,15 @@ @@ -842,6 +847,15 @@
"buffers" "~0.1.1"
"chainsaw" "~0.1.0"
"bl@^4.0.2":
"integrity" "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="
"resolved" "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz"
"version" "4.1.0"
dependencies:
"buffer" "^5.5.0"
"inherits" "^2.0.4"
"readable-stream" "^3.4.0"
"bluebird@^3.5.0":
"integrity" "sha1-nyKcFb4nJFT/qXOs4NvueaGww28="
"resolved" "https://registry.npm.taobao.org/bluebird/download/bluebird-3.7.2.tgz"
@ -899,11 +913,24 @@ @@ -899,11 +913,24 @@
"node-releases" "^2.0.1"
"picocolors" "^1.0.0"
"buffer-from@^1.0.0":
"integrity" "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
"resolved" "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz"
"version" "1.1.2"
"buffer-indexof-polyfill@~1.0.0":
"integrity" "sha1-0nMhNcWZnGSyd/z5savjSYJUcpw="
"resolved" "https://registry.npm.taobao.org/buffer-indexof-polyfill/download/buffer-indexof-polyfill-1.0.2.tgz"
"version" "1.0.2"
"buffer@^5.5.0":
"integrity" "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="
"resolved" "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz"
"version" "5.7.1"
dependencies:
"base64-js" "^1.3.1"
"ieee754" "^1.1.13"
"buffers@~0.1.1":
"integrity" "sha1-skV5w77U1tOWru5tmorn9Ugqt7s="
"resolved" "https://registry.npm.taobao.org/buffers/download/buffers-0.1.1.tgz"
@ -1079,6 +1106,14 @@ @@ -1079,6 +1106,14 @@
"resolved" "https://registry.npmmirror.com/commander/download/commander-7.2.0.tgz"
"version" "7.2.0"
"commist@^1.0.0":
"integrity" "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg=="
"resolved" "https://registry.npmmirror.com/commist/-/commist-1.1.0.tgz"
"version" "1.1.0"
dependencies:
"leven" "^2.1.0"
"minimist" "^1.1.0"
"component-emitter@^1.2.1":
"integrity" "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A="
"resolved" "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz"
@ -1094,6 +1129,16 @@ @@ -1094,6 +1129,16 @@
"resolved" "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz"
"version" "0.0.1"
"concat-stream@^2.0.0":
"integrity" "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A=="
"resolved" "https://registry.npmmirror.com/concat-stream/-/concat-stream-2.0.0.tgz"
"version" "2.0.0"
dependencies:
"buffer-from" "^1.0.0"
"inherits" "^2.0.3"
"readable-stream" "^3.0.2"
"typedarray" "^0.0.6"
"constant-case@^3.0.4":
"integrity" "sha1-O4Sprq9M8x7EXmv13pG9+wWJ+vE="
"resolved" "https://registry.npm.taobao.org/constant-case/download/constant-case-3.0.4.tgz?cache=0&sync_timestamp=1606867325763&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconstant-case%2Fdownload%2Fconstant-case-3.0.4.tgz"
@ -1216,7 +1261,7 @@ @@ -1216,7 +1261,7 @@
dependencies:
"ms" "^2.1.1"
"debug@^4.0.1", "debug@^4.1.0", "debug@^4.1.1", "debug@^4.3.2", "debug@^4.3.3":
"debug@^4.0.1", "debug@^4.1.0", "debug@^4.1.1", "debug@^4.3.1", "debug@^4.3.2", "debug@^4.3.3":
"integrity" "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q=="
"resolved" "https://registry.npmmirror.com/debug/download/debug-4.3.3.tgz"
"version" "4.3.3"
@ -1366,6 +1411,16 @@ @@ -1366,6 +1411,16 @@
dependencies:
"readable-stream" "^2.0.2"
"duplexify@^4.1.1":
"integrity" "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw=="
"resolved" "https://registry.npmmirror.com/duplexify/-/duplexify-4.1.2.tgz"
"version" "4.1.2"
dependencies:
"end-of-stream" "^1.4.1"
"inherits" "^2.0.3"
"readable-stream" "^3.1.1"
"stream-shift" "^1.0.0"
"electron-to-chromium@^1.4.17":
"integrity" "sha512-PO3kEfcxPrti/4STbXvCkNIF4fgWvCKl2508e6UI7KomCDffpIfeBZLXsh5DK/XGsjUw3kwq6WEsi0MJTlGAdg=="
"resolved" "https://registry.npmmirror.com/electron-to-chromium/download/electron-to-chromium-1.4.43.tgz"
@ -1381,6 +1436,13 @@ @@ -1381,6 +1436,13 @@
"resolved" "https://registry.npm.taobao.org/emojis-list/download/emojis-list-3.0.0.tgz"
"version" "3.0.0"
"end-of-stream@^1.1.0", "end-of-stream@^1.4.1":
"integrity" "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="
"resolved" "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz"
"version" "1.4.4"
dependencies:
"once" "^1.4.0"
"enquirer@^2.3.5":
"integrity" "sha1-Kn/l3WNKHkElqXXsmU/1RW3Dc00="
"resolved" "https://registry.npm.taobao.org/enquirer/download/enquirer-2.3.6.tgz"
@ -1728,6 +1790,11 @@ @@ -1728,6 +1790,11 @@
"resolved" "https://registry.npm.taobao.org/etag/download/etag-1.8.1.tgz"
"version" "1.8.1"
"eventemitter3@^5.0.0":
"integrity" "sha512-riuVbElZZNXLeLEoprfNYoDSwTBRR44X3mnhdI1YcnENpWTCsTTVZ2zFuqQcpoyqPQIUXdiPEU0ECAq0KQRaHg=="
"resolved" "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.0.tgz"
"version" "5.0.0"
"expand-brackets@^2.1.4":
"integrity" "sha1-t3c14xXOMPa27/D4OwQVGiJEliI="
"resolved" "https://registry.npm.taobao.org/expand-brackets/download/expand-brackets-2.1.4.tgz"
@ -1950,7 +2017,7 @@ @@ -1950,7 +2017,7 @@
dependencies:
"is-glob" "^4.0.1"
"glob@^7.1.3":
"glob@^7.1.3", "glob@^7.1.6":
"integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q=="
"resolved" "https://registry.npmmirror.com/glob/download/glob-7.2.0.tgz"
"version" "7.2.0"
@ -2081,6 +2148,14 @@ @@ -2081,6 +2148,14 @@
"capital-case" "^1.0.4"
"tslib" "^2.0.3"
"help-me@^3.0.0":
"integrity" "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ=="
"resolved" "https://registry.npmmirror.com/help-me/-/help-me-3.0.0.tgz"
"version" "3.0.0"
dependencies:
"glob" "^7.1.6"
"readable-stream" "^3.6.0"
"htmlparser2@^3.8.3":
"integrity" "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8="
"resolved" "https://registry.npmmirror.com/htmlparser2/download/htmlparser2-3.10.1.tgz?cache=0&sync_timestamp=1636640933377&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-3.10.1.tgz"
@ -2093,6 +2168,11 @@ @@ -2093,6 +2168,11 @@
"inherits" "^2.0.1"
"readable-stream" "^3.1.1"
"ieee754@^1.1.13":
"integrity" "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
"resolved" "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz"
"version" "1.2.1"
"ignore@^4.0.6":
"integrity" "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
"resolved" "https://registry.npmmirror.com/ignore/download/ignore-4.0.6.tgz"
@ -2134,7 +2214,7 @@ @@ -2134,7 +2214,7 @@
"once" "^1.3.0"
"wrappy" "1"
"inherits@^2.0.1", "inherits@^2.0.3", "inherits@~2.0.0", "inherits@~2.0.3", "inherits@2":
"inherits@^2.0.1", "inherits@^2.0.3", "inherits@^2.0.4", "inherits@~2.0.0", "inherits@~2.0.3", "inherits@2":
"integrity" "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w="
"resolved" "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz"
"version" "2.0.4"
@ -2402,6 +2482,11 @@ @@ -2402,6 +2482,11 @@
"resolved" "https://registry.npmmirror.com/js-base64/download/js-base64-2.6.4.tgz"
"version" "2.6.4"
"js-sdsl@4.3.0":
"integrity" "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ=="
"resolved" "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.3.0.tgz"
"version" "4.3.0"
"js-tokens@^3.0.0 || ^4.0.0", "js-tokens@^4.0.0":
"integrity" "sha1-GSA/tZmR35jjoocFDUZHzerzJJk="
"resolved" "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz?cache=0&sync_timestamp=1619345098261&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fjs-tokens%2Fdownload%2Fjs-tokens-4.0.0.tgz"
@ -2494,6 +2579,11 @@ @@ -2494,6 +2579,11 @@
"resolved" "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz"
"version" "6.0.3"
"leven@^2.1.0":
"integrity" "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA=="
"resolved" "https://registry.npmmirror.com/leven/-/leven-2.1.0.tgz"
"version" "2.1.0"
"levn@^0.4.1":
"integrity" "sha1-rkViwAdHO5MqYgDUAyaN0v/8at4="
"resolved" "https://registry.npm.taobao.org/levn/download/levn-0.4.1.tgz"
@ -2635,7 +2725,7 @@ @@ -2635,7 +2725,7 @@
dependencies:
"brace-expansion" "^1.1.7"
"minimist@^1.2.0", "minimist@^1.2.5":
"minimist@^1.1.0", "minimist@^1.2.0", "minimist@^1.2.5":
"integrity" "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI="
"resolved" "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz"
"version" "1.2.5"
@ -2665,6 +2755,38 @@ @@ -2665,6 +2755,38 @@
"resolved" "https://registry.npmmirror.com/moment/download/moment-2.29.1.tgz"
"version" "2.29.1"
"mqtt-packet@^6.8.0":
"integrity" "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA=="
"resolved" "https://registry.npmmirror.com/mqtt-packet/-/mqtt-packet-6.10.0.tgz"
"version" "6.10.0"
dependencies:
"bl" "^4.0.2"
"debug" "^4.1.1"
"process-nextick-args" "^2.0.1"
"mqtt@^4.3.7":
"integrity" "sha512-ew3qwG/TJRorTz47eW46vZ5oBw5MEYbQZVaEji44j5lAUSQSqIEoul7Kua/BatBW0H0kKQcC9kwUHa1qzaWHSw=="
"resolved" "https://registry.npmmirror.com/mqtt/-/mqtt-4.3.7.tgz"
"version" "4.3.7"
dependencies:
"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"
"ms@^2.1.1", "ms@2.1.2":
"integrity" "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
"resolved" "https://registry.npmmirror.com/ms/download/ms-2.1.2.tgz"
@ -2737,6 +2859,14 @@ @@ -2737,6 +2859,14 @@
dependencies:
"boolbase" "^1.0.0"
"number-allocator@^1.0.9":
"integrity" "sha512-OrL44UTVAvkKdOdRQZIJpLkAdjXGTRda052sN4sO77bKEzYYqWKMBjQvrJFzqygI99gL6Z4u2xctPW1tB8ErvA=="
"resolved" "https://registry.npmmirror.com/number-allocator/-/number-allocator-1.0.14.tgz"
"version" "1.0.14"
dependencies:
"debug" "^4.3.1"
"js-sdsl" "4.3.0"
"object-assign@^4", "object-assign@^4.1.0":
"integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
"resolved" "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz"
@ -2799,7 +2929,7 @@ @@ -2799,7 +2929,7 @@
"resolved" "https://registry.npm.taobao.org/omit.js/download/omit.js-2.0.2.tgz"
"version" "2.0.2"
"once@^1.3.0":
"once@^1.3.0", "once@^1.3.1", "once@^1.4.0":
"integrity" "sha1-WDsap3WWHUsROsF9nFC6753Xa9E="
"resolved" "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz"
"version" "1.4.0"
@ -2980,7 +3110,7 @@ @@ -2980,7 +3110,7 @@
"resolved" "https://registry.npm.taobao.org/prelude-ls/download/prelude-ls-1.2.1.tgz"
"version" "1.2.1"
"process-nextick-args@~2.0.0":
"process-nextick-args@^2.0.1", "process-nextick-args@~2.0.0":
"integrity" "sha1-eCDZsWEgzFXKmud5JoCufbptf+I="
"resolved" "https://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.1.tgz"
"version" "2.0.1"
@ -2990,6 +3120,14 @@ @@ -2990,6 +3120,14 @@
"resolved" "https://registry.npmmirror.com/progress/download/progress-2.0.3.tgz"
"version" "2.0.3"
"pump@^3.0.0":
"integrity" "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww=="
"resolved" "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz"
"version" "3.0.0"
dependencies:
"end-of-stream" "^1.1.0"
"once" "^1.3.1"
"punycode@^2.1.0":
"integrity" "sha1-tYsBCsQMIsVldhbI0sLALHv0eew="
"resolved" "https://registry.npm.taobao.org/punycode/download/punycode-2.1.1.tgz"
@ -3031,7 +3169,7 @@ @@ -3031,7 +3169,7 @@
"string_decoder" "~1.1.1"
"util-deprecate" "~1.0.1"
"readable-stream@^3.1.1":
"readable-stream@^3.0.0", "readable-stream@^3.0.2", "readable-stream@^3.1.1", "readable-stream@^3.4.0", "readable-stream@^3.6.0":
"integrity" "sha1-M3u9o63AcGvT4CRCaihtS0sskZg="
"resolved" "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.6.0.tgz"
"version" "3.6.0"
@ -3083,6 +3221,11 @@ @@ -3083,6 +3221,11 @@
"resolved" "https://registry.nlark.com/regexpp/download/regexpp-3.2.0.tgz"
"version" "3.2.0"
"reinterval@^1.1.0":
"integrity" "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
"resolved" "https://registry.npmmirror.com/reinterval/-/reinterval-1.1.0.tgz"
"version" "1.1.0"
"repeat-element@^1.1.2":
"integrity" "sha1-vmgVIIR6tYx1aKx1+/rSjtQtOek="
"resolved" "https://registry.nlark.com/repeat-element/download/repeat-element-1.1.4.tgz"
@ -3132,6 +3275,11 @@ @@ -3132,6 +3275,11 @@
"resolved" "https://registry.npm.taobao.org/reusify/download/reusify-1.0.4.tgz"
"version" "1.0.4"
"rfdc@^1.3.0":
"integrity" "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
"resolved" "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz"
"version" "1.3.0"
"rimraf@^3.0.2":
"integrity" "sha1-8aVAK6YiCtUswSgrrBrjqkn9Bho="
"resolved" "https://registry.npmmirror.com/rimraf/download/rimraf-3.0.2.tgz"
@ -3375,6 +3523,13 @@ @@ -3375,6 +3523,13 @@
dependencies:
"extend-shallow" "^3.0.0"
"split2@^3.1.0":
"integrity" "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg=="
"resolved" "https://registry.npmmirror.com/split2/-/split2-3.2.2.tgz"
"version" "3.2.2"
dependencies:
"readable-stream" "^3.0.0"
"sprintf-js@~1.0.2":
"integrity" "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
"resolved" "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz"
@ -3393,6 +3548,11 @@ @@ -3393,6 +3548,11 @@
"define-property" "^0.2.5"
"object-copy" "^0.1.0"
"stream-shift@^1.0.0":
"integrity" "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
"resolved" "https://registry.npmmirror.com/stream-shift/-/stream-shift-1.0.1.tgz"
"version" "1.0.1"
"strict-uri-encode@^1.0.0":
"integrity" "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM="
"resolved" "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-1.1.0.tgz"
@ -3636,6 +3796,11 @@ @@ -3636,6 +3796,11 @@
"resolved" "https://registry.npmmirror.com/type-fest/download/type-fest-0.20.2.tgz"
"version" "0.20.2"
"typedarray@^0.0.6":
"integrity" "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
"resolved" "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz"
"version" "0.0.6"
"typescript@^4.5.4", "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta":
"integrity" "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg=="
"resolved" "https://registry.npmmirror.com/typescript/download/typescript-4.5.4.tgz"
@ -3933,6 +4098,16 @@ @@ -3933,6 +4098,16 @@
"resolved" "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz"
"version" "1.0.2"
"ws@^7.5.5":
"integrity" "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q=="
"resolved" "https://registry.npmmirror.com/ws/-/ws-7.5.9.tgz"
"version" "7.5.9"
"xtend@^4.0.2":
"integrity" "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
"resolved" "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz"
"version" "4.0.2"
"yallist@^4.0.0":
"integrity" "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI="
"resolved" "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz"

Loading…
Cancel
Save