Browse Source

V1.1.0 for dock

v1.1.0
sean.zhou 3 years ago
parent
commit
9b2eedb85d
  1. 6
      README.md
  2. 328
      api/Cloud API Demo.postman_collection.json
  3. 6
      api/Cloud API Demo.postman_environment.json
  4. 31
      pom.xml
  5. 157
      sql/cloud_sample.sql
  6. 1
      src/main/java/com/dji/sample/CloudApiSampleApplication.java
  7. 10
      src/main/java/com/dji/sample/common/error/CommonErrorEnum.java
  8. 38
      src/main/java/com/dji/sample/common/error/StorageErrorEnum.java
  9. 4
      src/main/java/com/dji/sample/common/util/JwtUtil.java
  10. 24
      src/main/java/com/dji/sample/component/ApplicationBootInitial.java
  11. 53
      src/main/java/com/dji/sample/component/GlobalScheduleService.java
  12. 5
      src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java
  13. 52
      src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java
  14. 39
      src/main/java/com/dji/sample/component/mqtt/handler/AbstractStateTopicHandler.java
  15. 48
      src/main/java/com/dji/sample/component/mqtt/handler/EventsRouter.java
  16. 118
      src/main/java/com/dji/sample/component/mqtt/handler/InboundMessageRouter.java
  17. 49
      src/main/java/com/dji/sample/component/mqtt/handler/RequestsRouter.java
  18. 26
      src/main/java/com/dji/sample/component/mqtt/handler/StateDefaultHandler.java
  19. 38
      src/main/java/com/dji/sample/component/mqtt/handler/StateDeviceBasicHandler.java
  20. 62
      src/main/java/com/dji/sample/component/mqtt/handler/StateFirmwareVersionHandler.java
  21. 39
      src/main/java/com/dji/sample/component/mqtt/handler/StateLiveCapacityHandler.java
  22. 104
      src/main/java/com/dji/sample/component/mqtt/handler/StateRouter.java
  23. 67
      src/main/java/com/dji/sample/component/mqtt/handler/StatusRouter.java
  24. 45
      src/main/java/com/dji/sample/component/mqtt/model/Chan.java
  25. 19
      src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java
  26. 6
      src/main/java/com/dji/sample/component/mqtt/model/CommonTopicReceiver.java
  27. 2
      src/main/java/com/dji/sample/component/mqtt/model/CommonTopicResponse.java
  28. 23
      src/main/java/com/dji/sample/component/mqtt/model/ErrorInfoReply.java
  29. 36
      src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java
  30. 21
      src/main/java/com/dji/sample/component/mqtt/model/EventsReceiver.java
  31. 29
      src/main/java/com/dji/sample/component/mqtt/model/MapKeyConst.java
  32. 38
      src/main/java/com/dji/sample/component/mqtt/model/RequestsMethodEnum.java
  33. 44
      src/main/java/com/dji/sample/component/mqtt/model/RequestsReply.java
  34. 20
      src/main/java/com/dji/sample/component/mqtt/model/ServiceReply.java
  35. 29
      src/main/java/com/dji/sample/component/mqtt/model/ServicesMethodEnum.java
  36. 26
      src/main/java/com/dji/sample/component/mqtt/model/StateDataEnum.java
  37. 4
      src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java
  38. 10
      src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java
  39. 38
      src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java
  40. 8
      src/main/java/com/dji/sample/component/mybatis/MybatisPlusMetaObjectHandler.java
  41. 94
      src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java
  42. 28
      src/main/java/com/dji/sample/component/oss/model/enums/OssTypeEnum.java
  43. 18
      src/main/java/com/dji/sample/component/oss/service/IOssService.java
  44. 69
      src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java
  45. 135
      src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java
  46. 54
      src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java
  47. 33
      src/main/java/com/dji/sample/component/oss/service/impl/OssAspectHandler.java
  48. 58
      src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java
  49. 63
      src/main/java/com/dji/sample/component/redis/RedisConfiguration.java
  50. 29
      src/main/java/com/dji/sample/component/redis/RedisConst.java
  51. 187
      src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java
  52. 2
      src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java
  53. 7
      src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultFactory.java
  54. 18
      src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultHandler.java
  55. 8
      src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java
  56. 23
      src/main/java/com/dji/sample/component/websocket/service/IWebSocketManageService.java
  57. 7
      src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java
  58. 90
      src/main/java/com/dji/sample/component/websocket/service/impl/WebSocketManageServiceImpl.java
  59. 49
      src/main/java/com/dji/sample/configuration/SpringBeanConfiguration.java
  60. 104
      src/main/java/com/dji/sample/manage/controller/DeviceController.java
  61. 53
      src/main/java/com/dji/sample/manage/controller/DeviceHmsController.java
  62. 26
      src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java
  63. 21
      src/main/java/com/dji/sample/manage/controller/LiveStreamController.java
  64. 5
      src/main/java/com/dji/sample/manage/controller/LoginController.java
  65. 41
      src/main/java/com/dji/sample/manage/controller/UserController.java
  66. 12
      src/main/java/com/dji/sample/manage/dao/IDeviceHmsMapper.java
  67. 49
      src/main/java/com/dji/sample/manage/model/common/HmsJsonUtil.java
  68. 16
      src/main/java/com/dji/sample/manage/model/common/HmsMessage.java
  69. 4
      src/main/java/com/dji/sample/manage/model/dto/CapacityCameraDTO.java
  70. 2
      src/main/java/com/dji/sample/manage/model/dto/CapacityVideoDTO.java
  71. 22
      src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java
  72. 57
      src/main/java/com/dji/sample/manage/model/dto/DeviceHmsDTO.java
  73. 4
      src/main/java/com/dji/sample/manage/model/dto/TelemetryDTO.java
  74. 11
      src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java
  75. 34
      src/main/java/com/dji/sample/manage/model/dto/UserListDTO.java
  76. 3
      src/main/java/com/dji/sample/manage/model/dto/UserLoginDTO.java
  77. 4
      src/main/java/com/dji/sample/manage/model/dto/WorkspaceDTO.java
  78. 19
      src/main/java/com/dji/sample/manage/model/entity/DeviceEntity.java
  79. 76
      src/main/java/com/dji/sample/manage/model/entity/DeviceHmsEntity.java
  80. 4
      src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java
  81. 2
      src/main/java/com/dji/sample/manage/model/entity/UserEntity.java
  82. 2
      src/main/java/com/dji/sample/manage/model/entity/WorkspaceEntity.java
  83. 14
      src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java
  84. 155
      src/main/java/com/dji/sample/manage/model/enums/HmsEnum.java
  85. 61
      src/main/java/com/dji/sample/manage/model/enums/PayloadModelEnum.java
  86. 26
      src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java
  87. 45
      src/main/java/com/dji/sample/manage/model/param/DeviceHmsQueryParam.java
  88. 6
      src/main/java/com/dji/sample/manage/model/param/DeviceQueryParam.java
  89. 18
      src/main/java/com/dji/sample/manage/model/receiver/AlternateLandPointReceiver.java
  90. 22
      src/main/java/com/dji/sample/manage/model/receiver/BindDeviceReceiver.java
  91. 30
      src/main/java/com/dji/sample/manage/model/receiver/BindStatusReceiver.java
  92. 6
      src/main/java/com/dji/sample/manage/model/receiver/DeviceBasicReceiver.java
  93. 28
      src/main/java/com/dji/sample/manage/model/receiver/DeviceHmsReceiver.java
  94. 3
      src/main/java/com/dji/sample/manage/model/receiver/DevicePayloadReceiver.java
  95. 14
      src/main/java/com/dji/sample/manage/model/receiver/DockMediaFileDetailReceiver.java
  96. 18
      src/main/java/com/dji/sample/manage/model/receiver/DockSdrReceiver.java
  97. 20
      src/main/java/com/dji/sample/manage/model/receiver/DockSubDeviceReceiver.java
  98. 16
      src/main/java/com/dji/sample/manage/model/receiver/DroneChargeStateReceiver.java
  99. 29
      src/main/java/com/dji/sample/manage/model/receiver/FirmwareVersionReceiver.java
  100. 18
      src/main/java/com/dji/sample/manage/model/receiver/HmsArgsReceiver.java
  101. Some files were not shown because too many files have changed in this diff Show More

6
README.md

@ -6,15 +6,15 @@ The launch of the Cloud API mainly solves the problem of developers reinventing
## Docker ## Docker
If you don't want to install the development environment, you can try deploying with docker. [Click the link to download.](https://terra-sz-hc1pro-cloudapi.oss-cn-shenzhen.aliyuncs.com/c0af9fe0d7eb4f35a8fe5b695e4d0b96/docker/cloud_api_sample_docker_1.0.0.zip) If you don't want to install the development environment, you can try deploying with docker. [Click the link to download.](https://terra-sz-hc1pro-cloudapi.oss-cn-shenzhen.aliyuncs.com/c0af9fe0d7eb4f35a8fe5b695e4d0b96/docker/cloud_api_sample_docker.zip)
## Usage ## Usage
For more documentation, please visit the [DJI Developer Documentation](https://developer.dji.com/cn/document/209883f1-f2ad-406e-b99c-be7498df7f10). For more documentation, please visit the [DJI Developer Documentation](https://developer.dji.com/doc/cloud-api-tutorial/cn/).
## Latest Release ## Latest Release
Cloud API 1.0.0 was released on 21 March 2022. For more information, please visit the [Release Note](https://developer.dji.com/cn/document/87026f9b-e906-4809-9aba-870f569061b5). Cloud API 1.1.0 was released on 22 July 2022. For more information, please visit the [Release Note](https://developer.dji.com/doc/cloud-api-tutorial/cn/).
## License ## License

328
api/Cloud API Demo.postman_collection.json

@ -18,7 +18,7 @@
"header": [], "header": [],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\r\n \"username\": \"adminPC\",\r\n \"password\": \"adminPC\"\r\n}", "raw": "{\r\n \"username\": \"adminPC\",\r\n \"password\": \"adminPC\",\r\n \"flag\": 1\r\n}",
"options": { "options": {
"raw": { "raw": {
"language": "json" "language": "json"
@ -100,12 +100,13 @@
"method": "GET", "method": "GET",
"header": [], "header": [],
"url": { "url": {
"raw": "{{base_url}}{{manage_version}}/devices/devices", "raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices",
"host": [ "host": [
"{{base_url}}{{manage_version}}" "{{base_url}}{{manage_version}}"
], ],
"path": [ "path": [
"devices", "devices",
"{{workspace_id}}",
"devices" "devices"
] ]
} }
@ -132,12 +133,23 @@
}, },
{ {
"name": "Start Livestream", "name": "Start Livestream",
"event": [
{
"listen": "test",
"script": {
"exec": [
""
],
"type": "text/javascript"
}
}
],
"request": { "request": {
"method": "POST", "method": "POST",
"header": [], "header": [],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\r\n \"url_type\": 0,\r\n \"url\": \"\",\r\n \"video_id\": \"\",\r\n \"video_quality\": 0\r\n}", "raw": "{\r\n \"url\": \"rtmp://192.168.1.1/live/1651053434895\",\r\n \"url_type\": 1,\r\n \"video_id\": \"1581F4BN/52-0-0/zoom-0\",\r\n \"video_quality\": 0\r\n}",
"options": { "options": {
"raw": { "raw": {
"language": "json" "language": "json"
@ -165,7 +177,7 @@
"header": [], "header": [],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\r\n \"video_id\": \"\"\r\n}", "raw": "{\r\n \"video_id\": \"1581F4BNDQ/39-0-7/normal-0\"\r\n}",
"options": { "options": {
"raw": { "raw": {
"language": "json" "language": "json"
@ -213,19 +225,177 @@
} }
}, },
"response": [] "response": []
},
{
"name": "Get All Users Info",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}{{manage_version}}/users/{{workspace_id}}/users?page=1&page_size=10",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"users",
"{{workspace_id}}",
"users"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "page_size",
"value": "10"
}
]
}
},
"response": []
},
{
"name": "Update User Info",
"request": {
"method": "PUT",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"mqtt_username\": \"admin\",\r\n \"mqtt_password\": \"admin\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{manage_version}}/users/{{workspace_id}}/users/a1559e7c-8dd8-4780-b952-100cc4797da2",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"users",
"{{workspace_id}}",
"users",
"a1559e7c-8dd8-4780-b952-100cc4797da2"
]
}
},
"response": []
},
{
"name": "Bind Device",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"user_id\": \"be7c6c3d-afe9-4be4-b9eb-c55066c0914e\",\r\n \"workspace_id\": \"e3dea0f5-37f2-4d79-ae58-490af3228069\",\r\n \"device_sn\": \"1ZMDG009\",\r\n \"child_device_sn\": \"\"\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{manage_version}}/devices/binding",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"devices",
"binding"
]
}
},
"response": []
},
{
"name": "Get Binding Devices",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices/bound?page=1&page_size=10&domain=sub-device",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"devices",
"{{workspace_id}}",
"devices",
"bound"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "page_size",
"value": "10"
},
{
"key": "domain",
"value": "sub-device"
}
]
}
},
"response": []
},
{
"name": "Get Device",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices/{{device_sn}}",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"devices",
"{{workspace_id}}",
"devices",
"{{device_sn}}"
]
}
},
"response": []
},
{
"name": "Unbind Device",
"request": {
"method": "DELETE",
"header": [],
"url": {
"raw": "{{base_url}}{{manage_version}}/devices/{{device_sn}}/unbinding",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"devices",
"{{device_sn}}",
"unbinding"
]
}
},
"response": []
} }
], ],
"auth": { "auth": {
"type": "apikey", "type": "apikey",
"apikey": [ "apikey": [
{ {
"key": "key", "key": "value",
"value": "x-auth-token", "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTI2OTUxOTcsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTI3ODE1OTcsImlhdCI6MTY1MjY5NTE5NywidXNlcm5hbWUiOiJhZG1pblBDIn0.BHTwW8imw5ab0GUypRyJ2gkoz5av9q99NrxoFlL53dA",
"type": "string" "type": "string"
}, },
{ {
"key": "value", "key": "key",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM", "value": "x-auth-token",
"type": "string" "type": "string"
} }
] ]
@ -390,7 +560,7 @@
"apikey": [ "apikey": [
{ {
"key": "value", "key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM", "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTMzNzI3NDUsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTM0NTkxNDUsImlhdCI6MTY1MzM3Mjc0NSwidXNlcm5hbWUiOiJhZG1pblBDIn0.Zyb_f4umcGY2-WDaQKA1LHGOs9qYfJuPc3rQeIS-4hY",
"type": "string" "type": "string"
}, },
{ {
@ -520,15 +690,12 @@
}, },
{ {
"name": "Check Tiny Fingerprints", "name": "Check Tiny Fingerprints",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": { "request": {
"method": "GET", "method": "POST",
"header": [], "header": [],
"body": { "body": {
"mode": "raw", "mode": "raw",
"raw": "{\r\n \"tiny_fingerprints\":[\r\n \r\n ]\r\n}", "raw": "{\r\n \"tiny_fingerprints\":[\r\n \"4a3a67101ffb81d079338d4729315a8c_2022_3_3_11_38_58\",\r\n \"8e0fedb981be23dd034cf7927919da51_2022_3_3_11_45_26\"\r\n ]\r\n}",
"options": { "options": {
"raw": { "raw": {
"language": "json" "language": "json"
@ -536,7 +703,7 @@
} }
}, },
"url": { "url": {
"raw": "{{base_url}}{{media_version}}/workspaces/{{workspace_id}}/files/tiny-fingerprints?tiny_fingerprint=045040860fb014916c81082407e9ff8b_2021_12_2_16_17_8,922aca3dee753f2f9ee1ad0565967334_2021_12_8_22_13_12", "raw": "{{base_url}}{{media_version}}/workspaces/{{workspace_id}}/files/tiny-fingerprints",
"host": [ "host": [
"{{base_url}}{{media_version}}" "{{base_url}}{{media_version}}"
], ],
@ -545,12 +712,6 @@
"{{workspace_id}}", "{{workspace_id}}",
"files", "files",
"tiny-fingerprints" "tiny-fingerprints"
],
"query": [
{
"key": "tiny_fingerprint",
"value": "045040860fb014916c81082407e9ff8b_2021_12_2_16_17_8,922aca3dee753f2f9ee1ad0565967334_2021_12_8_22_13_12"
}
] ]
} }
}, },
@ -562,7 +723,7 @@
"apikey": [ "apikey": [
{ {
"key": "value", "key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM", "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTgzOTIyNzksImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTg0Nzg2NzksImlhdCI6MTY1ODM5MjI3OSwidXNlcm5hbWUiOiJhZG1pblBDIn0.ErClyQS1YzoQVBcLYxpFEiyFTb1L-eg2-vsudlL9WJU",
"type": "string" "type": "string"
}, },
{ {
@ -622,7 +783,7 @@
"apikey": [ "apikey": [
{ {
"key": "value", "key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM", "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTI2OTUxOTcsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTI3ODE1OTcsImlhdCI6MTY1MjY5NTE5NywidXNlcm5hbWUiOiJhZG1pblBDIn0.BHTwW8imw5ab0GUypRyJ2gkoz5av9q99NrxoFlL53dA",
"type": "string" "type": "string"
}, },
{ {
@ -848,7 +1009,124 @@
"apikey": [ "apikey": [
{ {
"key": "value", "key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM", "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTU0NDk2MDIsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTU1MzYwMDIsImlhdCI6MTY1NTQ0OTYwMiwidXNlcm5hbWUiOiJhZG1pblBDIn0.YZWHJ65Pl_DT2Ampxk0WC01KD_fNTm_rYVUBIHAZD-4",
"type": "string"
},
{
"key": "key",
"value": "x-auth-token",
"type": "string"
}
]
},
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
},
{
"listen": "test",
"script": {
"type": "text/javascript",
"exec": [
""
]
}
}
]
},
{
"name": "job",
"item": [
{
"name": "Create Flight Job",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"name\": \"\",\r\n \"fild_id\": \"\",\r\n \"dock_sn\": \"\",\r\n \"type\": \"\",\r\n \"immediate\": false\r\n}",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{base_url}}{{wayline_version}}/workspaces/{{workspace_id}}/flight-tasks",
"host": [
"{{base_url}}{{wayline_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"flight-tasks"
]
}
},
"response": []
},
{
"name": "Get Jobs",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}{{wayline_version}}/workspaces/{{workspace_id}}/jobs?page=1&pageSize=10",
"host": [
"{{base_url}}{{wayline_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"jobs"
],
"query": [
{
"key": "page",
"value": "1"
},
{
"key": "pageSize",
"value": "10"
}
]
}
},
"response": []
},
{
"name": "Execute Job",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "{{base_url}}{{wayline_version}}/workspaces/{{workspace_id}}/jobs/{{plan_id}}",
"host": [
"{{base_url}}{{wayline_version}}"
],
"path": [
"workspaces",
"{{workspace_id}}",
"jobs",
"{{plan_id}}"
]
}
},
"response": []
}
],
"auth": {
"type": "apikey",
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTU4OTA5NTQsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTU5NzczNTQsImlhdCI6MTY1NTg5MDk1NCwidXNlcm5hbWUiOiJhZG1pblBDIn0.fd0iIzCd71LDUE6ixexUJvo-YqtnSCqRx-790snCyBI",
"type": "string" "type": "string"
}, },
{ {
@ -885,7 +1163,7 @@
"apikey": [ "apikey": [
{ {
"key": "value", "key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Mzg5MzY2OTEsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2MzkwMjMwOTEsImlhdCI6MTYzODkzNjY5MSwidXNlcm5hbWUiOiJhZG1pblBDIn0.W_v88rbhVKivl61MnJ0Cz_0Eq6Gw0RotiHCdLj0UPSQ", "value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTA0MjY3MzAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTA1MTMxMzAsImlhdCI6MTY1MDQyNjczMCwidXNlcm5hbWUiOiJhZG1pblBDIn0.-FBpi0ktuZ68jV6-HQ7mwm8iC07YH-Hw2aRiREzJ8hs",
"type": "string" "type": "string"
}, },
{ {

6
api/Cloud API Demo.postman_environment.json

@ -4,7 +4,7 @@
"values": [ "values": [
{ {
"key": "ip", "key": "ip",
"value": "192.168.1.1", "value": "localhost",
"type": "default", "type": "default",
"enabled": true "enabled": true
}, },
@ -55,6 +55,6 @@
} }
], ],
"_postman_variable_scope": "environment", "_postman_variable_scope": "environment",
"_postman_exported_at": "2022-03-29T03:52:14.600Z", "_postman_exported_at": "2022-07-21T08:35:48.441Z",
"_postman_exported_using": "Postman/9.7.1" "_postman_exported_using": "Postman/9.19.0"
} }

31
pom.xml

@ -11,7 +11,7 @@
<groupId>com.dji</groupId> <groupId>com.dji</groupId>
<artifactId>cloud-api-sample</artifactId> <artifactId>cloud-api-sample</artifactId>
<version>1.0.0</version> <version>1.1.0</version>
<name>cloud-api-sample</name> <name>cloud-api-sample</name>
<properties> <properties>
@ -127,6 +127,35 @@
<version>${glassfish-jaxb.version}</version> <version>${glassfish-jaxb.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.12.200</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-sts</artifactId>
<version>1.12.200</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

157
sql/cloud_sample.sql

@ -10,40 +10,8 @@ SET NAMES utf8mb4;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
# manage_camera_video
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_camera_video`;
CREATE TABLE `manage_camera_video` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`camera_id` int NOT NULL,
`video_index` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`video_type` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
# manage_device
# manage_capacity_camera
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_capacity_camera`;
CREATE TABLE `manage_capacity_camera` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`device_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined',
`description` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`camera_index` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`coexist_video_number_max` int NOT NULL,
`available_video_number` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
# manage_device
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_device`; DROP TABLE IF EXISTS `manage_device`;
@ -52,25 +20,31 @@ CREATE TABLE `manage_device` (
`id` int unsigned NOT NULL AUTO_INCREMENT, `id` int unsigned NOT NULL AUTO_INCREMENT,
`device_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `device_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`device_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined', `device_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined',
`workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`device_type` smallint NOT NULL, `nickname` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`sub_type` smallint NOT NULL, `workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`domain` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `device_type` smallint NOT NULL DEFAULT '-1',
`version` smallint NOT NULL, `sub_type` smallint NOT NULL DEFAULT '-1',
`device_index` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `domain` smallint NOT NULL DEFAULT '-1',
`child_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `firmware_version` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`version` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`device_index` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`child_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`create_time` bigint NOT NULL, `create_time` bigint NOT NULL,
`update_time` bigint NOT NULL, `update_time` bigint NOT NULL,
`device_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `bound_time` bigint DEFAULT NULL,
`url_normal` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `bound_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0:bund; 1:not bound',
`url_select` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `login_time` bigint DEFAULT NULL,
`device_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`url_normal` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`url_select` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `product_sn_UNIQUE` (`device_sn`) UNIQUE KEY `product_sn_UNIQUE` (`device_sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
# manage_device_dictionary # manage_device_dictionary
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_device_dictionary`; DROP TABLE IF EXISTS `manage_device_dictionary`;
@ -106,15 +80,37 @@ VALUES
(14,1,165,0,'DJI Dock Camera',NULL), (14,1,165,0,'DJI Dock Camera',NULL),
(15,1,90742,0,'L1',NULL), (15,1,90742,0,'L1',NULL),
(16,2,56,0,'DJI Smart Controller','Remote control for M300'), (16,2,56,0,'DJI Smart Controller','Remote control for M300'),
(17,2,119,0,'Matrice 30 Smart Controller','Remote control for M30'), (17,2,119,0,'DJI RC Plus','Remote control for M30'),
(18,3,1,0,'DJI Dock','DJI Airport'); (18,3,1,0,'DJI Dock','');
/*!40000 ALTER TABLE `manage_device_dictionary` ENABLE KEYS */; /*!40000 ALTER TABLE `manage_device_dictionary` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
# manage_device_payload # manage_device_hms
# ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_device_hms`;
CREATE TABLE `manage_device_hms` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`hms_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`tid` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`bid` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`sn` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`level` smallint NOT NULL,
`module` tinyint NOT NULL,
`hms_key` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`message_zh` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`message_en` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`create_time` bigint NOT NULL,
`update_time` bigint NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE_hms_id` (`hms_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
# manage_device_payload
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_device_payload`; DROP TABLE IF EXISTS `manage_device_payload`;
@ -125,7 +121,7 @@ CREATE TABLE `manage_device_payload` (
`payload_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined', `payload_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined',
`payload_type` smallint NOT NULL, `payload_type` smallint NOT NULL,
`sub_type` smallint NOT NULL, `sub_type` smallint NOT NULL,
`version` smallint DEFAULT NULL, `firmware_version` varchar(32) DEFAULT NULL,
`payload_index` smallint NOT NULL, `payload_index` smallint NOT NULL,
`device_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `device_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`payload_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `payload_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
@ -137,7 +133,7 @@ CREATE TABLE `manage_device_payload` (
# manage_user # manage_user
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_user`; DROP TABLE IF EXISTS `manage_user`;
@ -147,7 +143,7 @@ CREATE TABLE `manage_user` (
`user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`workspace_id` int NOT NULL, `workspace_id` varchar(64) NOT NULL DEFAULT '',
`user_type` smallint NOT NULL, `user_type` smallint NOT NULL,
`mqtt_username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `mqtt_username` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`mqtt_password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `mqtt_password` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
@ -162,14 +158,14 @@ LOCK TABLES `manage_user` WRITE;
INSERT INTO `manage_user` (`id`, `user_id`, `username`, `password`, `workspace_id`, `user_type`, `mqtt_username`, `mqtt_password`, `create_time`, `update_time`) INSERT INTO `manage_user` (`id`, `user_id`, `username`, `password`, `workspace_id`, `user_type`, `mqtt_username`, `mqtt_password`, `create_time`, `update_time`)
VALUES VALUES
(1,'a1559e7c-8dd8-4780-b952-100cc4797da2','adminPC','adminPC',1,1,'admin','admin',1634898410751,1634898410751), (1,'a1559e7c-8dd8-4780-b952-100cc4797da2','adminPC','adminPC','e3dea0f5-37f2-4d79-ae58-490af3228069',1,'admin','admin',1634898410751,1650880112310),
(2,'be7c6c3d-afe9-4be4-b9eb-c55066c0914e','pilot','pilot123',1,2,'pilot','pilot123',1634898410751,1634898410751); (2,'be7c6c3d-afe9-4be4-b9eb-c55066c0914e','pilot','pilot123','e3dea0f5-37f2-4d79-ae58-490af3228069',2,'pilot','pilot123',1634898410751,1634898410751);
/*!40000 ALTER TABLE `manage_user` ENABLE KEYS */; /*!40000 ALTER TABLE `manage_user` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
# manage_workspace # manage_workspace
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `manage_workspace`; DROP TABLE IF EXISTS `manage_workspace`;
@ -182,22 +178,24 @@ CREATE TABLE `manage_workspace` (
`platform_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `platform_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`create_time` bigint NOT NULL, `create_time` bigint NOT NULL,
`update_time` bigint NOT NULL, `update_time` bigint NOT NULL,
`bind_code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `workspace_id_UNIQUE` (`workspace_id`) UNIQUE KEY `workspace_id_UNIQUE` (`workspace_id`),
UNIQUE KEY `bind_code_UNIQUE` (`bind_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
LOCK TABLES `manage_workspace` WRITE; LOCK TABLES `manage_workspace` WRITE;
/*!40000 ALTER TABLE `manage_workspace` DISABLE KEYS */; /*!40000 ALTER TABLE `manage_workspace` DISABLE KEYS */;
INSERT INTO `manage_workspace` (`id`, `workspace_id`, `workspace_name`, `workspace_desc`, `platform_name`, `create_time`, `update_time`) INSERT INTO `manage_workspace` (`id`, `workspace_id`, `workspace_name`, `workspace_desc`, `platform_name`, `create_time`, `update_time`, `bind_code`)
VALUES VALUES
(1,'e3dea0f5-37f2-4d79-ae58-490af3228069','Test Group One','Cloud Sample Test Platform','Cloud Api Platform',1634898410751,1634898410751); (1,'e3dea0f5-37f2-4d79-ae58-490af3228069','Test Group One','Cloud Sample Test Platform','Cloud Api Platform',1634898410751,1634898410751,'qwe');
/*!40000 ALTER TABLE `manage_workspace` ENABLE KEYS */; /*!40000 ALTER TABLE `manage_workspace` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
# map_element_coordinate # map_element_coordinate
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `map_element_coordinate`; DROP TABLE IF EXISTS `map_element_coordinate`;
@ -213,7 +211,7 @@ CREATE TABLE `map_element_coordinate` (
# map_group # map_group
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `map_group`; DROP TABLE IF EXISTS `map_group`;
@ -244,7 +242,7 @@ VALUES
UNLOCK TABLES; UNLOCK TABLES;
# map_group_element # map_group_element
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `map_group_element`; DROP TABLE IF EXISTS `map_group_element`;
@ -267,7 +265,7 @@ CREATE TABLE `map_group_element` (
# media_file # media_file
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `media_file`; DROP TABLE IF EXISTS `media_file`;
@ -277,22 +275,22 @@ CREATE TABLE `media_file` (
`file_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `file_name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`file_path` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `file_path` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`fingerprint` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `fingerprint` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`tinny_fingerprint` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `tinny_fingerprint` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`object_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `object_key` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`sub_file_type` int NOT NULL, `sub_file_type` int DEFAULT NULL,
`is_original` tinyint(1) NOT NULL, `is_original` tinyint(1) NOT NULL,
`drone` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined', `drone` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined',
`payload` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined', `payload` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'undefined',
`job_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`create_time` bigint NOT NULL, `create_time` bigint NOT NULL,
`update_time` bigint NOT NULL, `update_time` bigint NOT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`)
UNIQUE KEY `fingerprint_UNIQUE` (`fingerprint`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
# wayline_file # wayline_file
# ------------------------------------------------------------ # ------------------------------------------------------------
DROP TABLE IF EXISTS `wayline_file`; DROP TABLE IF EXISTS `wayline_file`;
@ -304,18 +302,41 @@ CREATE TABLE `wayline_file` (
`drone_model_key` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `drone_model_key` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`payload_model_keys` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `payload_model_keys` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`sign` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'MD5',
`favorited` tinyint(1) NOT NULL DEFAULT '0', `favorited` tinyint(1) NOT NULL DEFAULT '0',
`template_types` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `template_types` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`object_key` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `object_key` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`create_time` bigint NOT NULL, `create_time` bigint NOT NULL,
`update_time` bigint NOT NULL COMMENT 'required, can not modify.', `update_time` bigint NOT NULL COMMENT 'required, can''t modify.',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `wayline_id_UNIQUE` (`wayline_id`) UNIQUE KEY `wayline_id_UNIQUE` (`wayline_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
# wayline_job
# ------------------------------------------------------------
DROP TABLE IF EXISTS `wayline_job`;
CREATE TABLE `wayline_job` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`job_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`file_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`dock_sn` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`workspace_id` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`bid` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`type` varchar(45) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`create_time` bigint NOT NULL,
`update_time` bigint NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `job_id_UNIQUE` (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;

1
src/main/java/com/dji/sample/CloudApiSampleApplication.java

@ -8,6 +8,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@MapperScan("com.dji.sample.*.dao") @MapperScan("com.dji.sample.*.dao")
@SpringBootApplication @SpringBootApplication
@EnableScheduling @EnableScheduling
//@EnableConfigurationProperties(OssConfiguration.class)
public class CloudApiSampleApplication { public class CloudApiSampleApplication {
public static void main(String[] args) { public static void main(String[] args) {

10
src/main/java/com/dji/sample/common/error/CommonErrorEnum.java

@ -7,6 +7,16 @@ package com.dji.sample.common.error;
*/ */
public enum CommonErrorEnum implements IErrorInfo { public enum CommonErrorEnum implements IErrorInfo {
ILLEGAL_ARGUMENT(200001, "illegal argument"),
GET_ORGANIZATION_FAILED(210230, "Failed to get organization."),
DEVICE_BINDING_FAILED(210231, "Failed to bind device."),
NON_REPEATABLE_BINDING(210232, "The device has been bound to another organization and can't be bound repeatedly."),
GET_DEVICE_BINDING_STATUS_FAILED(210233, "Failed to get device binding status."),
SYSTEM_ERROR(600500, "system error"), SYSTEM_ERROR(600500, "system error"),
SECRET_INVALID(600100, "secret invalid"), SECRET_INVALID(600100, "secret invalid"),

38
src/main/java/com/dji/sample/common/error/StorageErrorEnum.java

@ -0,0 +1,38 @@
package com.dji.sample.common.error;
/**
* @author sean
* @version 1.0
* @date 2022/5/25
*/
public enum StorageErrorEnum implements IErrorInfo {
GENERATE_CREDENTIALS_ERROR(217001, "Failed to generate temporary credentials."),
NO_BUCKET(217002, "The bucket does not exist."),
ILLEGAL_PATH_FORMAT(217006, "Illegal path format."),
FILE_CREATION_FAILED(217007, "File creation failed."),
DIR_CREATION_FAILED(217008, "Directory creation failed");
private String msg;
private int code;
StorageErrorEnum(int code, String msg) {
this.msg = msg;
this.code = code;
}
@Override
public String getErrorMsg() {
return msg;
}
@Override
public Integer getErrorCode() {
return code;
}
}

4
src/main/java/com/dji/sample/common/util/JwtUtil.java

@ -54,6 +54,10 @@ public class JwtUtil {
JwtUtil.algorithm = Algorithm.HMAC256(secret); JwtUtil.algorithm = Algorithm.HMAC256(secret);
} }
private JwtUtil() {
}
/** /**
* Create a token based on custom information. * Create a token based on custom information.
* @param claims custom information * @param claims custom information

24
src/main/java/com/dji/sample/component/ApplicationBootInitial.java

@ -1,15 +1,12 @@
package com.dji.sample.component; package com.dji.sample.component;
import com.dji.sample.manage.model.DeviceStatusManager; import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.manage.model.enums.DeviceDomainEnum; import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.param.DeviceQueryParam;
import com.dji.sample.manage.service.IDeviceService; import com.dji.sample.manage.service.IDeviceService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/** /**
* @author sean.zhou * @author sean.zhou
* @date 2021/11/24 * @date 2021/11/24
@ -21,20 +18,21 @@ public class ApplicationBootInitial implements CommandLineRunner {
@Autowired @Autowired
private IDeviceService deviceService; private IDeviceService deviceService;
@Autowired
private RedisOpsUtils redisOps;
/** /**
* Subscribe to the devices that exist in the database when the program starts, * Subscribe to the devices that exist in the redis when the program starts,
* to prevent the data from being different from the pilot side due to program interruptions. * to prevent the data from being different from the pilot side due to program interruptions.
* @param args * @param args
* @throws Exception * @throws Exception
*/ */
@Override @Override
public void run(String... args) throws Exception { public void run(String... args) throws Exception {
deviceService.getDevicesByParams(DeviceQueryParam.builder().build()) int start = RedisConst.DEVICE_ONLINE_PREFIX.length();
.forEach(device -> {
deviceService.subscribeTopicOnline(device.getDeviceSn()); redisOps.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*")
DeviceStatusManager.STATUS_MANAGER.put( .forEach(key -> deviceService.subscribeTopicOnline(key.substring(start)));
DeviceDomainEnum.getVal(device.getDomain()) + "/"
+ device.getDeviceSn(), LocalDateTime.now());
});
} }
} }

53
src/main/java/com/dji/sample/component/GlobalScheduleService.java

@ -1,5 +1,9 @@
package com.dji.sample.component; package com.dji.sample.component;
import com.dji.sample.component.mqtt.service.IMqttTopicService;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.DeviceDomainEnum; import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.service.IDeviceService; import com.dji.sample.manage.service.IDeviceService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -7,13 +11,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.dji.sample.manage.model.DeviceStatusManager.DEFAULT_ALIVE_SECOND;
import static com.dji.sample.manage.model.DeviceStatusManager.STATUS_MANAGER;
/** /**
* @author sean.zhou * @author sean.zhou
* @date 2021/11/24 * @date 2021/11/24
@ -26,33 +26,34 @@ public class GlobalScheduleService {
@Autowired @Autowired
private IDeviceService deviceService; private IDeviceService deviceService;
@Autowired
private RedisOpsUtils redisOps;
@Autowired
private IMqttTopicService topicService;
/** /**
* Check the status of the devices every 30 seconds. It is recommended to use cache. * Check the status of the devices every 30 seconds. It is recommended to use cache.
*/ */
@Scheduled(fixedRate = 30, timeUnit = TimeUnit.SECONDS) @Scheduled(initialDelay = 30, fixedRate = 30, timeUnit = TimeUnit.SECONDS)
private void deviceStatusListen() { private void deviceStatusListen() {
for (Map.Entry<String, LocalDateTime> entry : STATUS_MANAGER.entrySet()) { int start = RedisConst.DEVICE_ONLINE_PREFIX.length();
if (entry.getValue().isAfter(
LocalDateTime.now().minusSeconds(DEFAULT_ALIVE_SECOND))) { redisOps.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*").forEach(key -> {
continue; long expire = redisOps.getExpire(key);
} if (expire <= 30) {
DeviceDTO device = (DeviceDTO) redisOps.get(key);
String device = entry.getKey(); if (device.getDomain().equals(DeviceDomainEnum.SUB_DEVICE.getDesc())) {
int index = device.indexOf("/"); deviceService.subDeviceOffline(key.substring(start));
} else {
STATUS_MANAGER.remove(device); deviceService.unsubscribeTopicOffline(key.substring(start));
deviceService.pushDeviceOfflineTopo(device.getWorkspaceId(), device.getDeviceSn());
int type = Integer.parseInt(device.substring(0, index)); }
String sn = device.substring(index + 1); redisOps.del(key);
// Determine whether it is a gateway device.
if (DeviceDomainEnum.GATEWAY.getVal() == type) {
deviceService.deviceOffline(sn);
deviceService.unsubscribeTopicOffline(sn);
continue;
} }
});
deviceService.subDeviceOffline(sn); log.info("Subscriptions: {}", Arrays.toString(topicService.getSubscribedTopic()));
}
} }
} }

5
src/main/java/com/dji/sample/component/mqtt/config/MqttInboundConfiguration.java

@ -11,6 +11,7 @@ import org.springframework.integration.endpoint.MessageProducerSupport;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory; import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessageHandler;
@ -62,7 +63,9 @@ public class MqttInboundConfiguration {
@ServiceActivator(inputChannel = ChannelName.DEFAULT) @ServiceActivator(inputChannel = ChannelName.DEFAULT)
public MessageHandler defaultInboundHandler() { public MessageHandler defaultInboundHandler() {
return message -> { return message -> {
log.info("The default channel does not handle messages."); log.info("The default channel does not handle messages." +
"\nTopic: " + message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC) +
"\nPayload: " + message.getPayload());
}; };
} }

52
src/main/java/com/dji/sample/component/mqtt/config/MqttMessageChannel.java

@ -74,7 +74,7 @@ public class MqttMessageChannel {
@Bean(name = ChannelName.INBOUND_OSD) @Bean(name = ChannelName.INBOUND_OSD)
public MessageChannel osdChannel() { public MessageChannel osdChannel() {
return new DirectChannel(); return new ExecutorChannel(threadPool);
} }
@Bean(name = ChannelName.DEFAULT) @Bean(name = ChannelName.DEFAULT)
@ -87,4 +87,54 @@ public class MqttMessageChannel {
return new DirectChannel(); return new DirectChannel();
} }
@Bean(name = ChannelName.INBOUND_STATE_FIRMWARE_VERSION)
public MessageChannel stateFirmwareVersionChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_REQUESTS)
public MessageChannel requestsChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET)
public MessageChannel requestsConfigGetChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS)
public MessageChannel eventsChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS)
public MessageChannel eventsFlightTaskProgressChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK)
public MessageChannel eventsFileUploadCallbackChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_REQUESTS_AIRPORT_BIND_STATUS)
public MessageChannel requestsAirportBindStatusChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_GET)
public MessageChannel requestsAirportOrganizationGetChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND)
public MessageChannel requestsAirportOrganizationBindChannel() {
return new DirectChannel();
}
@Bean(name = ChannelName.INBOUND_EVENTS_HMS)
public MessageChannel eventsHms() {
return new DirectChannel();
}
} }

39
src/main/java/com/dji/sample/component/mqtt/handler/AbstractStateTopicHandler.java

@ -0,0 +1,39 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Map;
/**
* @author sean
* @version 0.3
* @date 2022/2/21
*/
public abstract class AbstractStateTopicHandler {
protected AbstractStateTopicHandler handler;
@Autowired
protected ObjectMapper mapper;
@Autowired
protected RedisOpsUtils redisOps;
protected AbstractStateTopicHandler(AbstractStateTopicHandler handler) {
this.handler = handler;
}
/**
* Passing dataNode data, using different processing methods depending on the data selection.
* @param dataNode
* @param stateReceiver
* @param sn
* @return
* @throws JsonProcessingException
*/
public abstract CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException;
}

48
src/main/java/com/dji/sample/component/mqtt/handler/EventsRouter.java

@ -0,0 +1,48 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.EventsMethodEnum;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import java.io.IOException;
/**
* @author sean
* @version 1.1
* @date 2022/6/1
*/
@Configuration
public class EventsRouter {
@Autowired
private ObjectMapper mapper;
@Bean
public IntegrationFlow eventsMethodRouterFlow() {
return IntegrationFlows
.from(ChannelName.INBOUND_EVENTS)
.<byte[], CommonTopicReceiver>transform(payload -> {
try {
return mapper.readValue(payload, CommonTopicReceiver.class);
} catch (IOException e) {
e.printStackTrace();
}
return new CommonTopicReceiver();
})
.<CommonTopicReceiver, EventsMethodEnum>route(
receiver -> EventsMethodEnum.find(receiver.getMethod()),
mapping -> {
mapping.channelMapping(EventsMethodEnum.FILE_UPLOAD_CALLBACK, ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK);
mapping.channelMapping(EventsMethodEnum.FLIGHT_TASK_PROGRESS, ChannelName.INBOUND_EVENTS_FLIGHT_TASK_PROGRESS);
mapping.channelMapping(EventsMethodEnum.HMS, ChannelName.INBOUND_EVENTS_HMS);
mapping.channelMapping(EventsMethodEnum.UNKNOWN, ChannelName.DEFAULT);
})
.get();
}
}

118
src/main/java/com/dji/sample/component/mqtt/handler/InboundMessageRouter.java

@ -0,0 +1,118 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.ChannelName;
import lombok.extern.slf4j.Slf4j;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Pattern;
import static com.dji.sample.component.mqtt.model.TopicConst.*;
/**
*
* @author sean.zhou
* @date 2021/11/10
* @version 0.1
*/
@Component
@Slf4j
public class InboundMessageRouter extends AbstractMessageRouter {
@Resource(name = ChannelName.INBOUND)
private MessageChannel inboundChannel;
@Resource(name = ChannelName.INBOUND_STATUS)
private MessageChannel statusChannel;
@Resource(name = ChannelName.INBOUND_STATE)
private MessageChannel stateChannel;
@Resource(name = ChannelName.DEFAULT)
private MessageChannel defaultChannel;
@Resource(name = ChannelName.INBOUND_SERVICE_REPLY)
private MessageChannel serviceReplyChannel;
@Resource(name = ChannelName.INBOUND_OSD)
private MessageChannel osdChannel;
@Resource(name = ChannelName.INBOUND_REQUESTS)
private MessageChannel requestsChannel;
@Resource(name = ChannelName.INBOUND_EVENTS)
private MessageChannel eventsChannel;
private static final Pattern PATTERN_TOPIC_STATUS =
Pattern.compile("^" + BASIC_PRE + PRODUCT + REGEX_SN + STATUS_SUF + "$");
private static final Pattern PATTERN_TOPIC_STATE =
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + STATE_SUF + "$");
private static final Pattern PATTERN_TOPIC_SERVICE_REPLY =
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + SERVICES_SUF + _REPLY_SUF + "$");
private static final Pattern PATTERN_TOPIC_OSD =
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + OSD_SUF + "$");
private static final Pattern PATTERN_TOPIC_REQUESTS =
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + REQUESTS_SUF + "$");
private static final Pattern PATTERN_TOPIC_EVENTS =
Pattern.compile("^" + THING_MODEL_PRE + PRODUCT + REGEX_SN + EVENTS_SUF + "$");
/**
* All mqtt broker messages will arrive here before distributing them to different channels.
* @param message message from mqtt broker
* @return channel
*/
@Override
@Router(inputChannel = ChannelName.INBOUND)
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
MessageHeaders headers = message.getHeaders();
String topic = headers.get(MqttHeaders.RECEIVED_TOPIC).toString();
byte[] payload = (byte[])message.getPayload();
// osd
if (PATTERN_TOPIC_OSD.matcher(topic).matches()) {
return Collections.singleton(osdChannel);
}
log.debug("received topic :{} \t payload :{}", topic, new String(payload));
// status
if (PATTERN_TOPIC_STATUS.matcher(topic).matches()) {
return Collections.singleton(statusChannel);
}
// state
if (PATTERN_TOPIC_STATE.matcher(topic).matches()) {
return Collections.singleton(stateChannel);
}
// services_reply
if (PATTERN_TOPIC_SERVICE_REPLY.matcher(topic).matches()) {
return Collections.singleton(serviceReplyChannel);
}
// requests
if (PATTERN_TOPIC_REQUESTS.matcher(topic).matches()) {
return Collections.singleton(requestsChannel);
}
// events
if (PATTERN_TOPIC_EVENTS.matcher(topic).matches()) {
return Collections.singleton(eventsChannel);
}
return Collections.singleton(defaultChannel);
}
}

49
src/main/java/com/dji/sample/component/mqtt/handler/RequestsRouter.java

@ -0,0 +1,49 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.RequestsMethodEnum;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import java.io.IOException;
/**
* @author sean
* @version 1.0
* @date 2022/5/25
*/
@Configuration
public class RequestsRouter {
@Autowired
private ObjectMapper mapper;
@Bean
public IntegrationFlow requestsMethodRouterFlow() {
return IntegrationFlows
.from(ChannelName.INBOUND_REQUESTS)
.<byte[], CommonTopicReceiver>transform(payload -> {
try {
return mapper.readValue(payload, CommonTopicReceiver.class);
} catch (IOException e) {
e.printStackTrace();
}
return new CommonTopicReceiver();
})
.<CommonTopicReceiver, RequestsMethodEnum>route(
receiver -> RequestsMethodEnum.find(receiver.getMethod()),
mapping -> {
mapping.channelMapping(RequestsMethodEnum.STORAGE_CONFIG_GET, ChannelName.INBOUND_REQUESTS_STORAGE_CONFIG_GET);
mapping.channelMapping(RequestsMethodEnum.AIRPORT_BIND_STATUS, ChannelName.INBOUND_REQUESTS_AIRPORT_BIND_STATUS);
mapping.channelMapping(RequestsMethodEnum.AIRPORT_ORGANIZATION_GET, ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_GET);
mapping.channelMapping(RequestsMethodEnum.AIRPORT_ORGANIZATION_BIND, ChannelName.INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND);
mapping.channelMapping(RequestsMethodEnum.UNKNOWN, ChannelName.DEFAULT);
})
.get();
}
}

26
src/main/java/com/dji/sample/component/mqtt/handler/StateDefaultHandler.java

@ -0,0 +1,26 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author sean
* @version 0.3
* @date 2022/3/21
*/
@Service
public class StateDefaultHandler extends AbstractStateTopicHandler {
protected StateDefaultHandler() {
super(null);
}
@Override
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
// If no suitable handler is found for the data, it is not processed.
return stateReceiver;
}
}

38
src/main/java/com/dji/sample/component/mqtt/handler/StateDeviceBasicHandler.java

@ -0,0 +1,38 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.StateDataEnum;
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author sean
* @version 0.3
* @date 2022/2/21
*/
@Service
public class StateDeviceBasicHandler extends AbstractStateTopicHandler {
public StateDeviceBasicHandler(@Autowired @Qualifier("stateLiveCapacityHandler") AbstractStateTopicHandler handler) {
super(handler);
}
@Override
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
// handle device basic data
if (dataNode.containsKey(StateDataEnum.PAYLOADS.getDesc())) {
DeviceBasicReceiver data = mapper.convertValue(stateReceiver.getData(), DeviceBasicReceiver.class);
data.setDeviceSn(sn);
data.getPayloads().forEach(payload -> payload.setDeviceSn(sn));
stateReceiver.setData(data);
return stateReceiver;
}
return handler.handleState(dataNode, stateReceiver, sn);
}
}

62
src/main/java/com/dji/sample/component/mqtt/handler/StateFirmwareVersionHandler.java

@ -0,0 +1,62 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.StateDataEnum;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.model.enums.PayloadModelEnum;
import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* @author sean
* @version 0.3
* @date 2022/2/21
*/
@Service
public class StateFirmwareVersionHandler extends AbstractStateTopicHandler {
protected StateFirmwareVersionHandler(@Autowired @Qualifier("stateDefaultHandler") AbstractStateTopicHandler handler) {
super(handler);
}
@Override
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
// Parse the firmware version of the device.
if (dataNode.containsKey(StateDataEnum.FIRMWARE_VERSION.getDesc())) {
FirmwareVersionReceiver firmware = mapper.convertValue(dataNode, FirmwareVersionReceiver.class);
firmware.setSn(sn);
firmware.setDomain(DeviceDomainEnum.SUB_DEVICE);
stateReceiver.setData(firmware);
return stateReceiver;
}
// Parse the firmware version of the payload.
List<String> payloads = PayloadModelEnum.getAllModel();
long count = dataNode.keySet()
.stream()
.map(key -> {
int end = key.indexOf("-");
return end == -1 ? key : key.substring(0, end);
})
.filter(payloads::contains)
.count();
if (count > 0) {
FirmwareVersionReceiver firmware = FirmwareVersionReceiver.builder()
.firmwareVersion(((Map<String, String>)(dataNode.values().iterator().next()))
.get(StateDataEnum.FIRMWARE_VERSION.getDesc()))
.sn(sn)
.domain(DeviceDomainEnum.PAYLOAD)
.build();
stateReceiver.setData(firmware);
return stateReceiver;
}
return handler.handleState(dataNode, stateReceiver, sn);
}
}

39
src/main/java/com/dji/sample/component/mqtt/handler/StateLiveCapacityHandler.java

@ -0,0 +1,39 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.StateDataEnum;
import com.dji.sample.manage.model.receiver.LiveCapacityReceiver;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author sean
* @version 0.3
* @date 2022/2/21
*/
@Service
@Slf4j
public class StateLiveCapacityHandler extends AbstractStateTopicHandler {
protected StateLiveCapacityHandler(@Autowired @Qualifier("stateFirmwareVersionHandler") AbstractStateTopicHandler handler) {
super(handler);
}
@Override
public CommonTopicReceiver handleState(Map<String, Object> dataNode, CommonTopicReceiver stateReceiver, String sn) throws JsonProcessingException {
// Determine if it is live capacity data based on name.
if (dataNode.containsKey(StateDataEnum.LIVE_CAPACITY.getDesc())) {
stateReceiver.setData(mapper.convertValue(
dataNode.get(StateDataEnum.LIVE_CAPACITY.getDesc()),
LiveCapacityReceiver.class));
log.info("Analyze live stream capabilities.");
return stateReceiver;
}
return handler.handleState(dataNode, stateReceiver, sn);
}
}

104
src/main/java/com/dji/sample/component/mqtt/handler/StateRouter.java

@ -0,0 +1,104 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver;
import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
import com.dji.sample.manage.model.receiver.LiveCapacityReceiver;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.annotation.Splitter;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.integration.router.MessageRouter;
import org.springframework.integration.router.PayloadTypeRouter;
import org.springframework.messaging.Message;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import static com.dji.sample.component.mqtt.model.TopicConst.*;
/**
*
* @author sean.zhou
* @date 2021/11/17
* @version 0.1
*/
@MessageEndpoint
@Slf4j
@Configuration
public class StateRouter {
@Resource(name = "stateDeviceBasicHandler")
private AbstractStateTopicHandler handler;
@Autowired
private ObjectMapper mapper;
/**
* Handles the routing of state topic messages. Depending on the data, it is assigned to different channels for handling.
* @param message
* @return
* @throws IOException
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE, outputChannel = ChannelName.INBOUND_STATE_SPLITTER)
public CommonTopicReceiver<?> resolveStateData(Message<?> message) throws IOException {
byte[] payload = (byte[])message.getPayload();
String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
CommonTopicReceiver stateReceiver = mapper.readValue(payload, CommonTopicReceiver.class);
// Get the sn of the topic source.
String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(),
topic.indexOf(STATE_SUF));
try {
Map<String, Object> data = (Map<String, Object>) (stateReceiver.getData());
return handler.handleState(data, stateReceiver, from);
} catch (UnrecognizedPropertyException e) {
log.info("The {} data is not processed.", e.getPropertyName());
}
return stateReceiver;
}
/**
* Split the state message data to different channels for handling according to their different types.
* @param receiver state message
* @return
*/
@Splitter(inputChannel = ChannelName.INBOUND_STATE_SPLITTER, outputChannel = ChannelName.INBOUND_STATE_ROUTER)
public Collection<Object> splitState(CommonTopicReceiver receiver) {
ArrayList<Object> type = new ArrayList<>();
type.add(receiver.getData());
return type;
}
@Bean
@Router(inputChannel = ChannelName.INBOUND_STATE_ROUTER)
public MessageRouter resolveStateRouter() {
PayloadTypeRouter router = new PayloadTypeRouter();
// Channel mapping for basic data.
router.setChannelMapping(DeviceBasicReceiver.class.getName(),
ChannelName.INBOUND_STATE_BASIC);
// Channel mapping for live streaming capabilities.
router.setChannelMapping(LiveCapacityReceiver.class.getName(),
ChannelName.INBOUND_STATE_CAPACITY);
router.setChannelMapping(FirmwareVersionReceiver.class.getName(),
ChannelName.INBOUND_STATE_FIRMWARE_VERSION);
router.setChannelMapping(Map.class.getName(),
ChannelName.DEFAULT);
return router;
}
}

67
src/main/java/com/dji/sample/component/mqtt/handler/StatusRouter.java

@ -0,0 +1,67 @@
package com.dji.sample.component.mqtt.handler;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.manage.model.receiver.StatusGatewayReceiver;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message;
import org.springframework.util.CollectionUtils;
import static com.dji.sample.component.mqtt.model.TopicConst.*;
/**
*
* @author sean.zhou
* @date 2021/11/12
* @version 0.1
*/
@MessageEndpoint
public class StatusRouter {
@Autowired
private ObjectMapper mapper;
/**
* Converts the status data sent by the gateway device into an object.
* @param message
* @return
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATUS, outputChannel = ChannelName.INBOUND_STATUS_ROUTER)
public CommonTopicReceiver<StatusGatewayReceiver> resolveStatus(Message<?> message) {
CommonTopicReceiver<StatusGatewayReceiver> statusReceiver = new CommonTopicReceiver<>();
try {
statusReceiver = mapper.readValue(
(byte[])message.getPayload(),
new TypeReference<CommonTopicReceiver<StatusGatewayReceiver>>() {});
String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
// set gateway's sn
statusReceiver.getData().setSn(
topic.substring((BASIC_PRE + PRODUCT).length(),
topic.indexOf(STATUS_SUF)));
} catch (Exception e) {
e.printStackTrace();
}
return statusReceiver;
}
/**
* Handles the routing of status topic messages. Depending on the data, it is assigned to different channels for handling.
* @param receiver
* @return
*/
@Router(inputChannel = ChannelName.INBOUND_STATUS_ROUTER)
public String resolveStatusRouter(CommonTopicReceiver<StatusGatewayReceiver> receiver) {
// Determine whether the drone is online or offline according to whether the data of the sub-device is empty.
return CollectionUtils.isEmpty(receiver.getData().getSubDevices()) ?
ChannelName.INBOUND_STATUS_OFFLINE : ChannelName.INBOUND_STATUS_ONLINE;
}
}

45
src/main/java/com/dji/sample/component/mqtt/model/Chan.java

@ -0,0 +1,45 @@
package com.dji.sample.component.mqtt.model;
import java.util.concurrent.locks.LockSupport;
/**
* The demo is only for functional closure, which is not recommended.
* @author sean.zhou
* @date 2021/11/22
* @version 0.1
*/
public class Chan<T> {
private static final long THREAD_WAIT_TIME = 1000_000 * 2000;
private volatile T data;
private volatile Thread t;
private Chan () {
}
public static Chan getInstance() {
return ChanSingleton.INSTANCE;
}
public T get(Object blocker) {
this.t = Thread.currentThread();
LockSupport.parkNanos(blocker, THREAD_WAIT_TIME);
this.t = null;
return data;
}
public void put(T data) {
this.data = data;
if (t == null) {
return;
}
LockSupport.unpark(t);
}
private static class ChanSingleton {
private static final Chan<?> INSTANCE = new Chan<>();
}
}

19
src/main/java/com/dji/sample/component/mqtt/model/ChannelName.java

@ -43,4 +43,23 @@ public class ChannelName {
public static final String OUTBOUND = "outbound"; public static final String OUTBOUND = "outbound";
public static final String INBOUND_STATE_FIRMWARE_VERSION = "inboundStateFirmwareVersion";
public static final String INBOUND_REQUESTS = "inboundRequests";
public static final String INBOUND_REQUESTS_STORAGE_CONFIG_GET = "inboundRequestsConfigGet";
public static final String INBOUND_EVENTS = "inboundEvents";
public static final String INBOUND_EVENTS_FLIGHT_TASK_PROGRESS = "inboundEventsFlightTaskProgress";
public static final String INBOUND_EVENTS_FILE_UPLOAD_CALLBACK = "inboundEventsFileUploadCallback";
public static final String INBOUND_REQUESTS_AIRPORT_BIND_STATUS = "inboundRequestsAirportBindStatus";
public static final String INBOUND_REQUESTS_AIRPORT_ORGANIZATION_GET = "inboundRequestsAirportOrganizationGet";
public static final String INBOUND_REQUESTS_AIRPORT_ORGANIZATION_BIND = "inboundRequestsAirportOrganizationBind";
public static final String INBOUND_EVENTS_HMS = "inboundEventsHms";
} }

6
src/main/java/com/dji/sample/component/mqtt/model/CommonTopicReceiver.java

@ -26,4 +26,10 @@ public class CommonTopicReceiver<T> {
private Long timestamp; private Long timestamp;
private T data; private T data;
private String gateway;
private Integer needReply;
private String from;
} }

2
src/main/java/com/dji/sample/component/mqtt/model/CommonTopicResponse.java

@ -30,4 +30,6 @@ public class CommonTopicResponse<T> {
private String method; private String method;
private T data; private T data;
private Long timestamp;
} }

23
src/main/java/com/dji/sample/component/mqtt/model/ErrorInfoReply.java

@ -0,0 +1,23 @@
package com.dji.sample.component.mqtt.model;
import com.dji.sample.common.model.ResponseResult;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/6/14
*/
@Data
@AllArgsConstructor
public class ErrorInfoReply {
private String sn;
private Integer errCode;
public static ErrorInfoReply success(String sn) {
return new ErrorInfoReply(sn, ResponseResult.CODE_SUCCESS);
}
}

36
src/main/java/com/dji/sample/component/mqtt/model/EventsMethodEnum.java

@ -0,0 +1,36 @@
package com.dji.sample.component.mqtt.model;
import java.util.Arrays;
/**
* @author sean
* @version 1.1
* @date 2022/6/1
*/
public enum EventsMethodEnum {
FLIGHT_TASK_PROGRESS("flighttask_progress"),
FILE_UPLOAD_CALLBACK("file_upload_callback"),
HMS("hms"),
UNKNOWN("Unknown");
private String method;
EventsMethodEnum(String method) {
this.method = method;
}
public String getMethod() {
return method;
}
public static EventsMethodEnum find(String method) {
return Arrays.stream(EventsMethodEnum.values())
.filter(methodEnum -> methodEnum.method.equals(method))
.findAny()
.orElse(UNKNOWN);
}
}

21
src/main/java/com/dji/sample/component/mqtt/model/EventsReceiver.java

@ -0,0 +1,21 @@
package com.dji.sample.component.mqtt.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/6/9
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class EventsReceiver<T> {
private Integer result;
private T output;
private String bid;
}

29
src/main/java/com/dji/sample/component/mqtt/model/MapKeyConst.java

@ -0,0 +1,29 @@
package com.dji.sample.component.mqtt.model;
/**
* @author sean
* @version 1.1
* @date 2022/6/14
*/
public final class MapKeyConst {
private MapKeyConst(){
}
public static final String ORGANIZATION_NAME = "organization_name";
public static final String DEVICES = "devices";
public static final String SN = "sn";
public static final String BIND_DEVICES = "bind_devices";
public static final String ERR_INFOS = "err_infos";
public static final String TINY_FINGERPRINTS = "tiny_fingerprints";
public static final String BIND_STATUS = "bind_status";
public static final String LIST = "list";
}

38
src/main/java/com/dji/sample/component/mqtt/model/RequestsMethodEnum.java

@ -0,0 +1,38 @@
package com.dji.sample.component.mqtt.model;
import java.util.Arrays;
/**
* @author sean
* @version 1.0
* @date 2022/5/25
*/
public enum RequestsMethodEnum {
STORAGE_CONFIG_GET("storage_config_get"),
AIRPORT_BIND_STATUS("airport_bind_status"),
AIRPORT_ORGANIZATION_BIND("airport_organization_bind"),
AIRPORT_ORGANIZATION_GET("airport_organization_get"),
UNKNOWN("Unknown");
private String method;
RequestsMethodEnum(String method) {
this.method = method;
}
public String getMethod() {
return method;
}
public static RequestsMethodEnum find(String method) {
return Arrays.stream(RequestsMethodEnum.values())
.filter(methodEnum -> methodEnum.method.equals(method))
.findAny()
.orElse(UNKNOWN);
}
}

44
src/main/java/com/dji/sample/component/mqtt/model/RequestsReply.java

@ -0,0 +1,44 @@
package com.dji.sample.component.mqtt.model;
import com.dji.sample.common.error.IErrorInfo;
import com.dji.sample.common.model.ResponseResult;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.1
* @date 2022/6/13
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RequestsReply<T> {
private Integer result;
private T output;
public static RequestsReply error(IErrorInfo errorInfo) {
return RequestsReply.builder()
.result(errorInfo.getErrorCode())
.output(errorInfo.getErrorMsg())
.build();
}
public static <T> RequestsReply success(T data) {
return RequestsReply.builder()
.result(ResponseResult.CODE_SUCCESS)
.output(data)
.build();
}
public static RequestsReply success() {
return RequestsReply.builder()
.result(ResponseResult.CODE_SUCCESS)
.build();
}
}

20
src/main/java/com/dji/sample/component/mqtt/model/ServiceReply.java

@ -0,0 +1,20 @@
package com.dji.sample.component.mqtt.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
/**
* @author sean.zhou
* @version 0.1
* @date 2021/11/22
*/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class ServiceReply<T> {
private Integer result;
private T info;
private T output;
}

29
src/main/java/com/dji/sample/component/mqtt/model/ServicesMethodEnum.java

@ -0,0 +1,29 @@
package com.dji.sample.component.mqtt.model;
/**
* @author sean.zhou
* @date 2021/11/22
* @version 0.1
*/
public enum ServicesMethodEnum {
LIVE_START_PUSH("live_start_push"),
LIVE_STOP_PUSH("live_stop_push"),
LIVE_SET_QUALITY("live_set_quality"),
FLIGHTTASK_CREATE("flighttask_create"),
UNKNOWN("unknown");
private String method;
ServicesMethodEnum(String method) {
this.method = method;
}
public String getMethod() {
return method;
}
}

26
src/main/java/com/dji/sample/component/mqtt/model/StateDataEnum.java

@ -0,0 +1,26 @@
package com.dji.sample.component.mqtt.model;
/**
*
* @author sean.zhou
* @date 2021/11/18
* @version 0.1
*/
public enum StateDataEnum {
FIRMWARE_VERSION("firmware_version"),
LIVE_CAPACITY("live_capacity"),
PAYLOADS("payloads");
private String desc;
StateDataEnum(String desc) {
this.desc = desc;
}
public String getDesc() {
return this.desc;
}
}

4
src/main/java/com/dji/sample/component/mqtt/model/TopicConst.java

@ -24,6 +24,10 @@ public class TopicConst {
public static final String OSD_SUF = "/osd"; public static final String OSD_SUF = "/osd";
public static final String REQUESTS_SUF = "/requests";
public static final String EVENTS_SUF = "/events";
public static final String REGEX_SN = "[A-Za-z0-9]+"; public static final String REGEX_SN = "[A-Za-z0-9]+";
} }

10
src/main/java/com/dji/sample/component/mqtt/service/IMessageSenderService.java

@ -1,6 +1,9 @@
package com.dji.sample.component.mqtt.service; package com.dji.sample.component.mqtt.service;
import com.dji.sample.component.mqtt.model.CommonTopicResponse; import com.dji.sample.component.mqtt.model.CommonTopicResponse;
import com.dji.sample.component.mqtt.model.ServiceReply;
import java.util.Optional;
/** /**
* @author sean.zhou * @author sean.zhou
@ -24,4 +27,11 @@ public interface IMessageSenderService {
*/ */
void publish(String topic, int qos, CommonTopicResponse response); void publish(String topic, int qos, CommonTopicResponse response);
/**
* Send live streaming start message and receive a response at the same time
* @param topic
* @param response notification of whether the start is successful.
* @return
*/
Optional<ServiceReply> publishWithReply(String topic, CommonTopicResponse response);
} }

38
src/main/java/com/dji/sample/component/mqtt/service/impl/MessageSenderServiceImpl.java

@ -1,15 +1,20 @@
package com.dji.sample.component.mqtt.service.impl; package com.dji.sample.component.mqtt.service.impl;
import com.dji.sample.component.mqtt.model.Chan;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.CommonTopicResponse; import com.dji.sample.component.mqtt.model.CommonTopicResponse;
import com.dji.sample.component.mqtt.model.ServiceReply;
import com.dji.sample.component.mqtt.service.IMessageSenderService; import com.dji.sample.component.mqtt.service.IMessageSenderService;
import com.dji.sample.component.mqtt.service.IMqttMessageGateway; import com.dji.sample.component.mqtt.service.IMqttMessageGateway;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
/** /**
* @author sean.zhou * @author sean.zhou
* @date 2021/11/16 * @date 2021/11/16
@ -22,11 +27,11 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
@Autowired @Autowired
private IMqttMessageGateway messageGateway; private IMqttMessageGateway messageGateway;
@Autowired
private ObjectMapper mapper;
public void publish(String topic, CommonTopicResponse response) { public void publish(String topic, CommonTopicResponse response) {
try { try {
ObjectMapper mapper = new ObjectMapper();
// Only parameters whose value is not null will be serialised.
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
messageGateway.publish(topic, mapper.writeValueAsBytes(response)); messageGateway.publish(topic, mapper.writeValueAsBytes(response));
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
@ -37,14 +42,31 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
public void publish(String topic, int qos, CommonTopicResponse response) { public void publish(String topic, int qos, CommonTopicResponse response) {
try { try {
ObjectMapper mapper = new ObjectMapper();
// Only parameters whose value is not null will be serialised.
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
messageGateway.publish(topic, mapper.writeValueAsBytes(response), qos); messageGateway.publish(topic, mapper.writeValueAsBytes(response), qos);
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
log.info("Failed to publish the message. {}", response.toString()); log.info("Failed to publish the message. {}", response.toString());
e.printStackTrace(); e.printStackTrace();
} }
} }
public Optional<ServiceReply> publishWithReply(String topic, CommonTopicResponse response) {
AtomicInteger time = new AtomicInteger(0);
// Retry three times
while (time.getAndIncrement() < 3) {
this.publish(topic, response);
Chan<CommonTopicReceiver<ServiceReply>> chan = Chan.getInstance();
// If the message is not received in 0.5 seconds then resend it again.
CommonTopicReceiver<ServiceReply> receiver = chan.get(response.getMethod());
if (receiver == null) {
continue;
}
// Need to match tid and bid.
if (receiver.getTid().equals(response.getTid()) &&
receiver.getBid().equals(response.getBid())) {
return Optional.ofNullable(receiver.getData());
}
}
return Optional.empty();
}
} }

8
src/main/java/com/dji/sample/component/mybatis/MybatisPlusMetaObjectHandler.java

@ -5,7 +5,7 @@ import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneOffset; import java.time.ZoneId;
/** /**
* Automatic filling for set values * Automatic filling for set values
@ -20,9 +20,9 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
@Override @Override
public void insertFill(MetaObject metaObject) { public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Long.class, this.strictInsertFill(metaObject, "createTime", Long.class,
LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()); LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
this.strictInsertFill(metaObject, "updateTime", Long.class, this.strictInsertFill(metaObject, "updateTime", Long.class,
LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()); LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
} }
/** /**
@ -32,6 +32,6 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
@Override @Override
public void updateFill(MetaObject metaObject) { public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", Long.class, this.strictUpdateFill(metaObject, "updateTime", Long.class,
LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli()); LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
} }
} }

94
src/main/java/com/dji/sample/component/oss/model/OssConfiguration.java

@ -0,0 +1,94 @@
package com.dji.sample.component.oss.model;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author sean
* @version 0.2
* @date 2021/12/9
*/
@ConfigurationProperties(prefix = "oss")
@Component
@Data
public class OssConfiguration {
/**
* @see com.dji.sample.component.oss.model.enums.OssTypeEnum
*/
private String provider;
/**
* Whether to use the object storage service.
*/
private boolean enable;
/**
* The protocol needs to be included at the beginning of the address.
*/
private String endpoint;
private String accessKey;
private String secretKey;
private String region;
private Long expire;
private String roleSessionName;
private String roleArn;
private String bucket;
private String objectDirPrefix;
public void setProvider(String provider) {
this.provider = provider;
}
public void setEnable(boolean enable) {
this.enable = enable;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public void setRegion(String region) {
this.region = region;
}
public void setExpire(Long expire) {
this.expire = expire;
}
public void setRoleSessionName(String roleSessionName) {
this.roleSessionName = roleSessionName;
}
public void setRoleArn(String roleArn) {
this.roleArn = roleArn;
}
public void setBucket(String bucket) {
this.bucket = bucket;
}
public void setObjectDirPrefix(String objectDirPrefix) {
this.objectDirPrefix = objectDirPrefix;
}
}

28
src/main/java/com/dji/sample/component/oss/model/enums/OssTypeEnum.java

@ -0,0 +1,28 @@
package com.dji.sample.component.oss.model.enums;
/**
* @author sean
* @version 1.0
* @date 2022/5/30
*/
public enum OssTypeEnum {
ALIYUN("ali"),
AWS("aws"),
/*
* MinIO is temporarily unavailable.
*/
MINIO("minio");
private String type;
OssTypeEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}

18
src/main/java/com/dji/sample/component/oss/service/IOssService.java

@ -11,6 +11,8 @@ import java.net.URL;
*/ */
public interface IOssService { public interface IOssService {
String getOssType();
/** /**
* Get temporary credentials. * Get temporary credentials.
* @return * @return
@ -24,4 +26,20 @@ public interface IOssService {
* @return download link * @return download link
*/ */
URL getObjectUrl(String bucket, String objectKey); URL getObjectUrl(String bucket, String objectKey);
/**
* Deletes the object in the storage bucket.
* @param bucket
* @param objectKey
* @return
*/
Boolean deleteObject(String bucket, String objectKey);
/**
* Get the contents of an object.
* @param bucket
* @param objectKey
* @return
*/
byte[] getObject(String bucket, String objectKey);
} }

69
src/main/java/com/dji/sample/component/oss/service/impl/AliyunOssServiceImpl.java

@ -1,13 +1,16 @@
package com.dji.sample.component.oss.service.impl; package com.dji.sample.component.oss.service.impl;
import com.aliyun.oss.OSS; import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient; import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest; import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse; import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.dji.sample.component.oss.model.AliyunOSSConfiguration; import com.dji.sample.component.oss.model.OssConfiguration;
import com.dji.sample.component.oss.model.enums.OssTypeEnum;
import com.dji.sample.component.oss.service.IOssService; import com.dji.sample.component.oss.service.IOssService;
import com.dji.sample.media.model.CredentialsDTO; import com.dji.sample.media.model.CredentialsDTO;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -15,6 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.Date; import java.util.Date;
@ -27,24 +32,29 @@ import java.util.Date;
@Slf4j @Slf4j
public class AliyunOssServiceImpl implements IOssService { public class AliyunOssServiceImpl implements IOssService {
@Autowired(required = false) @Autowired
private OSS ossClient; public OssConfiguration configuration;
@Override
public String getOssType() {
return OssTypeEnum.ALIYUN.getType();
}
@Override @Override
public CredentialsDTO getCredentials() { public CredentialsDTO getCredentials() {
try { try {
DefaultProfile profile = DefaultProfile.getProfile( DefaultProfile profile = DefaultProfile.getProfile(
AliyunOSSConfiguration.region, AliyunOSSConfiguration.accessKey, AliyunOSSConfiguration.secretKey); configuration.getRegion(), configuration.getAccessKey(), configuration.getSecretKey());
IAcsClient client = new DefaultAcsClient(profile); IAcsClient client = new DefaultAcsClient(profile);
AssumeRoleRequest request = new AssumeRoleRequest(); AssumeRoleRequest request = new AssumeRoleRequest();
request.setDurationSeconds(AliyunOSSConfiguration.expire); request.setDurationSeconds(configuration.getExpire());
request.setRoleArn(AliyunOSSConfiguration.roleArn); request.setRoleArn(configuration.getRoleArn());
request.setRoleSessionName(AliyunOSSConfiguration.roleSessionName); request.setRoleSessionName(configuration.getRoleSessionName());
AssumeRoleResponse response = client.getAcsResponse(request); AssumeRoleResponse response = client.getAcsResponse(request);
return new CredentialsDTO(response.getCredentials(), AliyunOSSConfiguration.expire); return new CredentialsDTO(response.getCredentials(), configuration.getExpire());
} catch (ClientException e) { } catch (ClientException e) {
log.debug("Failed to obtain sts."); log.debug("Failed to obtain sts.");
@ -58,16 +68,45 @@ public class AliyunOssServiceImpl implements IOssService {
if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) { if (!StringUtils.hasText(bucket) || !StringUtils.hasText(objectKey)) {
return null; return null;
} }
try { OSS ossClient = this.createClient();
// First check if the object can be fetched. // First check if the object can be fetched.
ossClient.getObject(bucket, objectKey); ossClient.getObject(bucket, objectKey);
return ossClient.generatePresignedUrl(bucket, objectKey,
new Date(System.currentTimeMillis() + configuration.getExpire() * 1000));
}
@Override
public Boolean deleteObject(String bucket, String objectKey) {
OSS ossClient = this.createClient();
ossClient.deleteObject(bucket, objectKey);
ossClient.shutdown();
return true;
}
@Override
public byte[] getObject(String bucket, String objectKey) {
OSS ossClient = this.createClient();
OSSObject object = ossClient.getObject(bucket, objectKey);
InputStream stream = object.getObjectContent();
return ossClient.generatePresignedUrl(bucket, objectKey, try {
new Date(System.currentTimeMillis() + AliyunOSSConfiguration.expire * 1000)); return stream.readAllBytes();
} catch (NullPointerException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} finally {
try {
stream.close();
ossClient.shutdown();
} catch (IOException e) {
e.printStackTrace();
}
} }
return null; return new byte[0];
} }
private OSS createClient() {
return new OSSClientBuilder()
.build(configuration.getEndpoint(), configuration.getAccessKey(), configuration.getSecretKey());
}
} }

135
src/main/java/com/dji/sample/component/oss/service/impl/AmazonS3ServiceImpl.java

@ -0,0 +1,135 @@
package com.dji.sample.component.oss.service.impl;
import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.BucketCrossOriginConfiguration;
import com.amazonaws.services.s3.model.CORSRule;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
import com.amazonaws.services.securitytoken.model.AssumeRoleResult;
import com.amazonaws.services.securitytoken.model.Credentials;
import com.dji.sample.component.AuthInterceptor;
import com.dji.sample.component.oss.model.OssConfiguration;
import com.dji.sample.component.oss.model.enums.OssTypeEnum;
import com.dji.sample.component.oss.service.IOssService;
import com.dji.sample.media.model.CredentialsDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author sean
* @version 1.0
* @date 2022/4/27
*/
@Service
public class AmazonS3ServiceImpl implements IOssService {
@Autowired
private OssConfiguration configuration;
@Override
public String getOssType() {
return OssTypeEnum.AWS.getType();
}
@Override
public CredentialsDTO getCredentials() {
AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(
new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey())))
.withRegion(configuration.getRegion()).build();
AssumeRoleRequest request = new AssumeRoleRequest()
.withRoleArn(configuration.getRoleArn())
.withRoleSessionName(configuration.getRoleSessionName())
.withDurationSeconds(Math.toIntExact(configuration.getExpire()));
AssumeRoleResult result = stsClient.assumeRole(request);
Credentials credentials = result.getCredentials();
stsClient.shutdown();
return new CredentialsDTO(credentials);
}
@Override
public URL getObjectUrl(String bucket, String objectKey) {
AmazonS3 client = this.createClient();
URL url = client.generatePresignedUrl(bucket, objectKey,
new Date(System.currentTimeMillis() + configuration.getExpire() * 1000), HttpMethod.GET);
client.shutdown();
return url;
}
@Override
public Boolean deleteObject(String bucket, String objectKey) {
AmazonS3 client = this.createClient();
client.deleteObject(bucket, objectKey);
client.shutdown();
return true;
}
public byte[] getObject(String bucket, String objectKey) {
AmazonS3 client = this.createClient();
S3Object object = client.getObject(bucket, objectKey);
InputStream stream = object.getObjectContent().getDelegateStream();
try {
return stream.readAllBytes();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
stream.close();
client.shutdown();
} catch (IOException e) {
e.printStackTrace();
}
}
return new byte[0];
}
private AmazonS3 createClient() {
return AmazonS3ClientBuilder.standard()
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials(configuration.getAccessKey(), configuration.getSecretKey())))
.withRegion(configuration.getRegion())
.build();
}
/**
* Configuring cross-origin resource sharing
*/
@PostConstruct
private void configCORS() {
if (!configuration.isEnable() || !OssTypeEnum.AWS.getType().equals(configuration.getProvider())) {
return;
}
List<CORSRule.AllowedMethods> allowedMethods = new ArrayList<>();
allowedMethods.add(CORSRule.AllowedMethods.GET);
allowedMethods.add(CORSRule.AllowedMethods.POST);
allowedMethods.add(CORSRule.AllowedMethods.DELETE);
CORSRule rule = new CORSRule()
.withId("CORSAccessRule")
.withAllowedOrigins(List.of("*"))
.withAllowedHeaders(List.of(AuthInterceptor.PARAM_TOKEN))
.withAllowedMethods(allowedMethods);
AmazonS3 client = this.createClient();
client.setBucketCrossOriginConfiguration(this.configuration.getBucket(),
new BucketCrossOriginConfiguration().withRules(rule));
client.shutdown();
}
}

54
src/main/java/com/dji/sample/component/oss/service/impl/MinIOServiceImpl.java

@ -1,6 +1,7 @@
package com.dji.sample.component.oss.service.impl; package com.dji.sample.component.oss.service.impl;
import com.dji.sample.component.oss.model.MinIOConfiguration; import com.dji.sample.component.oss.model.OssConfiguration;
import com.dji.sample.component.oss.model.enums.OssTypeEnum;
import com.dji.sample.component.oss.service.IOssService; import com.dji.sample.component.oss.service.IOssService;
import com.dji.sample.media.model.CredentialsDTO; import com.dji.sample.media.model.CredentialsDTO;
import io.minio.GetPresignedObjectUrlArgs; import io.minio.GetPresignedObjectUrlArgs;
@ -26,16 +27,21 @@ import java.security.NoSuchAlgorithmException;
@Slf4j @Slf4j
public class MinIOServiceImpl implements IOssService { public class MinIOServiceImpl implements IOssService {
@Autowired(required = false) @Autowired
private MinioClient client; private OssConfiguration configuration;
@Override
public String getOssType() {
return OssTypeEnum.MINIO.getType();
}
@Override @Override
public CredentialsDTO getCredentials() { public CredentialsDTO getCredentials() {
try { try {
AssumeRoleProvider provider = new AssumeRoleProvider(MinIOConfiguration.endpoint, MinIOConfiguration.accessKey, AssumeRoleProvider provider = new AssumeRoleProvider(configuration.getEndpoint(), configuration.getAccessKey(),
MinIOConfiguration.secretKey, MinIOConfiguration.expire, configuration.getSecretKey(), Math.toIntExact(configuration.getExpire()),
null, null, null, null, null, null); null, configuration.getRegion(), null, null, null, null);
return new CredentialsDTO(provider.fetch(), MinIOConfiguration.expire); return new CredentialsDTO(provider.fetch(), Math.toIntExact(configuration.getExpire()));
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
log.debug("Failed to obtain sts."); log.debug("Failed to obtain sts.");
e.printStackTrace(); e.printStackTrace();
@ -47,20 +53,38 @@ public class MinIOServiceImpl implements IOssService {
public URL getObjectUrl(String bucket, String objectKey) { public URL getObjectUrl(String bucket, String objectKey) {
try { try {
return new URL( return new URL(
client.getPresignedObjectUrl( this.createClient()
GetPresignedObjectUrlArgs.builder() .getPresignedObjectUrl(
.method(Method.GET) GetPresignedObjectUrlArgs.builder()
.bucket(bucket) .method(Method.GET)
.object(objectKey) .bucket(bucket)
.expiry(MinIOConfiguration.expire) .object(objectKey)
.build())); .expiry(Math.toIntExact(configuration.getExpire()))
.build()));
} catch (ErrorResponseException | InsufficientDataException | InternalException | } catch (ErrorResponseException | InsufficientDataException | InternalException |
InvalidKeyException | InvalidResponseException | IOException | InvalidKeyException | InvalidResponseException | IOException |
NoSuchAlgorithmException | XmlParserException | ServerException e) { NoSuchAlgorithmException | XmlParserException | ServerException e) {
log.error("The file does not exist on the oss."); log.error("The file does not exist on the OssConfiguration.");
e.printStackTrace(); e.printStackTrace();
} }
return null; return null;
} }
@Override
public Boolean deleteObject(String bucket, String objectKey) {
return null;
}
@Override
public byte[] getObject(String bucket, String objectKey) {
return new byte[0];
}
private MinioClient createClient() {
return MinioClient.builder()
.endpoint(configuration.getEndpoint())
.credentials(configuration.getAccessKey(), configuration.getSecretKey())
.region(configuration.getRegion())
.build();
}
} }

33
src/main/java/com/dji/sample/component/oss/service/impl/OssAspectHandler.java

@ -0,0 +1,33 @@
package com.dji.sample.component.oss.service.impl;
import com.dji.sample.component.oss.model.OssConfiguration;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author sean
* @version 1.1
* @date 2022/6/20
*/
@Component
@Aspect
public class OssAspectHandler {
@Autowired
private OssServiceContext ossServiceContext;
@Autowired
private OssConfiguration configuration;
@Before("execution(public * com.dji.sample.component.oss.service.impl.OssServiceContext.*(..))")
public void before() {
if (!this.configuration.isEnable()) {
throw new IllegalArgumentException("Please enable OssConfiguration.");
}
if (this.ossServiceContext.getOssService() == null) {
throw new IllegalArgumentException("Please check the OssConfiguration configuration.");
}
}
}

58
src/main/java/com/dji/sample/component/oss/service/impl/OssServiceContext.java

@ -0,0 +1,58 @@
package com.dji.sample.component.oss.service.impl;
import com.dji.sample.component.oss.model.OssConfiguration;
import com.dji.sample.component.oss.model.enums.OssTypeEnum;
import com.dji.sample.component.oss.service.IOssService;
import com.dji.sample.media.model.CredentialsDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
/**
* @author sean
* @version 1.0
* @date 2022/5/30
*/
@Service
public class OssServiceContext {
private IOssService ossService;
private OssConfiguration configuration;
@Autowired
public OssServiceContext(List<IOssService> ossServices, OssConfiguration configuration) {
this.configuration = configuration;
if (!configuration.isEnable()) {
return;
}
this.ossService = ossServices.stream()
.filter(ossService -> ossService.getOssType().equals(configuration.getProvider()))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Oss provider is illegal. Optional: " +
Arrays.toString(Arrays.stream(OssTypeEnum.values()).map(OssTypeEnum::getType).toArray())));
}
IOssService getOssService() {
return this.ossService;
}
public CredentialsDTO getCredentials() {
return this.ossService.getCredentials();
}
public URL getObjectUrl(String bucket, String objectKey) {
return this.ossService.getObjectUrl(bucket, objectKey);
}
public Boolean deleteObject(String bucket, String objectKey) {
return this.ossService.deleteObject(bucket, objectKey);
}
public byte[] getObject(String bucket, String objectKey) {
return this.ossService.getObject(bucket, objectKey);
}
}

63
src/main/java/com/dji/sample/component/redis/RedisConfiguration.java

@ -0,0 +1,63 @@
package com.dji.sample.component.redis;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author sean
* @version 1.0
* @date 2022/4/19
*/
@Configuration
@EnableRedisRepositories
public class RedisConfiguration {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule timeModule = new JavaTimeModule();
timeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
timeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
objectMapper.registerModules(timeModule);
objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
StringRedisSerializer serializer = new StringRedisSerializer();
redisTemplate.setKeySerializer(serializer);
redisTemplate.setHashKeySerializer(serializer);
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);
redisTemplate.setValueSerializer(jsonRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

29
src/main/java/com/dji/sample/component/redis/RedisConst.java

@ -0,0 +1,29 @@
package com.dji.sample.component.redis;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
/**
* @author sean
* @version 1.0
* @date 2022/4/21
*/
public final class RedisConst {
private RedisConst() {
}
public static final Integer DEVICE_ALIVE_SECOND = 60;
public static final Integer WEBSOCKET_ALIVE_SECOND = 60 * 60 * 24;
public static final String ONLINE_PREFIX = "online:";
public static final String DEVICE_ONLINE_PREFIX = ONLINE_PREFIX + DeviceDomainEnum.SUB_DEVICE + ":";
public static final String WEBSOCKET_PREFIX = "webSocket:";
public static final String WEBSOCKET_ALL = "webSocket:all";
public static final String HMS_PREFIX = "hms:";
}

187
src/main/java/com/dji/sample/component/redis/RedisOpsUtils.java

@ -0,0 +1,187 @@
package com.dji.sample.component.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* @author sean
* @version 1.0
* @date 2022/4/19
*/
@Component
public class RedisOpsUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* HSET
* @param key
* @param field
* @param value
*/
public void hashSet(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
/**
* HGET
* @param key
* @param field
* @return
*/
public Object hashGet(String key, String field) {
return redisTemplate.opsForHash().get(key, field);
}
/**
* HKEYS
* @param key
* @return
*/
public Set<Object> hashKeys(String key) {
return redisTemplate.opsForHash().keys(key);
}
/**
* HEXISTS
* @param key
* @param field
* @return
*/
public boolean hashCheck(String key, String field) {
return redisTemplate.opsForHash().hasKey(key, field);
}
/**
* HDEL
* @param key
* @param fields
* @return
*/
public boolean hashDel(String key, Object[] fields) {
return redisTemplate.opsForHash().delete(key, fields) > 0;
}
/**
* EXPIRE
* @param key
* @param timeout
* @return
*/
public boolean expireKey(String key, long timeout) {
return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
/**
* SET
* @param key
* @param value
*/
public void set(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
/**
* GET
* @param key
* @return
*/
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
/**
* SETEX
* @param key
* @param value
* @param expire
*/
public void setWithExpire(String key, Object value, long expire) {
redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
}
/**
* TTL
* @param key
* @return
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* EXISTS
* @param key
* @return
*/
public boolean checkExist(String key) {
return redisTemplate.hasKey(key);
}
/**
* DEL
* @param key
* @return
*/
public boolean del(String key) {
return this.checkExist(key) && redisTemplate.delete(key);
}
/**
* KEYS
* @param pattern
* @return
*/
public Set<String> getAllKeys(String pattern) {
return redisTemplate.keys(pattern);
}
/**
* RPUSH
* @param key
* @param value
*/
public void listRPush(String key, Object... value) {
if (value.length == 0) {
return;
}
for (Object val : value) {
redisTemplate.opsForList().rightPush(key, val);
}
}
/**
* LRANGE
* @param key
* @param start
* @param end
* @return
*/
public List<Object> listGet(String key, long start, long end) {
return redisTemplate.opsForList().range(key, start, end);
}
/**
* LRANGE
* @param key
* @return
*/
public List<Object> listGetAll(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
/**
* LLen
* @param key
* @return
*/
public Long listLen(String key) {
return redisTemplate.opsForList().size(key);
}
}

2
src/main/java/com/dji/sample/component/websocket/config/AuthPrincipalHandler.java

@ -35,7 +35,7 @@ public class AuthPrincipalHandler extends DefaultHandshakeHandler {
if (!StringUtils.hasText(token)) { if (!StringUtils.hasText(token)) {
return false; return false;
} }
log.debug("token:" + token);
Optional<CustomClaim> customClaim = JwtUtil.parseToken(token); Optional<CustomClaim> customClaim = JwtUtil.parseToken(token);
if (customClaim.isEmpty()) { if (customClaim.isEmpty()) {
return false; return false;

7
src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultFactory.java

@ -1,5 +1,7 @@
package com.dji.sample.component.websocket.config; package com.dji.sample.component.websocket.config;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory; import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
@ -13,8 +15,11 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
@Component @Component
public class WebSocketDefaultFactory implements WebSocketHandlerDecoratorFactory { public class WebSocketDefaultFactory implements WebSocketHandlerDecoratorFactory {
@Autowired
private IWebSocketManageService webSocketManageService;
@Override @Override
public WebSocketHandler decorate(WebSocketHandler handler) { public WebSocketHandler decorate(WebSocketHandler handler) {
return new WebSocketDefaultHandler(handler); return new WebSocketDefaultHandler(handler, webSocketManageService);
} }
} }

18
src/main/java/com/dji/sample/component/websocket/config/WebSocketDefaultHandler.java

@ -1,9 +1,7 @@
package com.dji.sample.component.websocket.config; package com.dji.sample.component.websocket.config;
import com.dji.sample.component.websocket.model.WebSocketManager; import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.component.websocket.service.ISendMessageService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
@ -22,20 +20,20 @@ import java.security.Principal;
@Slf4j @Slf4j
public class WebSocketDefaultHandler extends WebSocketHandlerDecorator { public class WebSocketDefaultHandler extends WebSocketHandlerDecorator {
@Autowired private IWebSocketManageService webSocketManageService;
private ISendMessageService sendMessageService;
WebSocketDefaultHandler(WebSocketHandler delegate) { WebSocketDefaultHandler(WebSocketHandler delegate, IWebSocketManageService webSocketManageService) {
super(delegate); super(delegate);
this.webSocketManageService = webSocketManageService;
} }
@Override @Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception { public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Principal principal = session.getPrincipal(); Principal principal = session.getPrincipal();
if (StringUtils.hasText(principal.getName())) { if (StringUtils.hasText(principal.getName())) {
WebSocketManager.put(principal.getName(), new ConcurrentWebSocketSession(session)); webSocketManageService.put(principal.getName(), new ConcurrentWebSocketSession(session));
log.debug("{} is connected. ID: {}. WebSocketSession[current count: {}]", log.debug("{} is connected. ID: {}. WebSocketSession[current count: {}]",
principal.getName(), session.getId(), WebSocketManager.getConnectedCount()); principal.getName(), session.getId(), webSocketManageService.getConnectedCount());
return; return;
} }
session.close(); session.close();
@ -45,9 +43,9 @@ public class WebSocketDefaultHandler extends WebSocketHandlerDecorator {
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception { public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
Principal principal = session.getPrincipal(); Principal principal = session.getPrincipal();
if (StringUtils.hasText(principal.getName())) { if (StringUtils.hasText(principal.getName())) {
WebSocketManager.remove(principal.getName(), session.getId()); webSocketManageService.remove(principal.getName(), session.getId());
log.debug("{} is disconnected. ID: {}. WebSocketSession[current count: {}]", log.debug("{} is disconnected. ID: {}. WebSocketSession[current count: {}]",
principal.getName(), session.getId(), WebSocketManager.getConnectedCount()); principal.getName(), session.getId(), webSocketManageService.getConnectedCount());
} }
} }

8
src/main/java/com/dji/sample/component/websocket/model/BizCodeEnum.java

@ -17,13 +17,19 @@ public enum BizCodeEnum {
GATEWAY_OSD("gateway_osd"), GATEWAY_OSD("gateway_osd"),
DOCK_OSD("dock_osd"),
MAP_ELEMENT_CREATE("map_element_create"), MAP_ELEMENT_CREATE("map_element_create"),
MAP_ELEMENT_UPDATE("map_element_update"), MAP_ELEMENT_UPDATE("map_element_update"),
MAP_ELEMENT_DELETE("map_element_delete"), MAP_ELEMENT_DELETE("map_element_delete"),
MAP_GROUP_REFRESH("map_group_refresh"); MAP_GROUP_REFRESH("map_group_refresh"),
FLIGHT_TASK_PROGRESS("flighttask_progress"),
DEVICE_HMS("device_hms");
private String code; private String code;

23
src/main/java/com/dji/sample/component/websocket/service/IWebSocketManageService.java

@ -0,0 +1,23 @@
package com.dji.sample.component.websocket.service;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import java.util.Collection;
/**
* @author sean
* @version 1.0
* @date 2022/4/25
*/
public interface IWebSocketManageService {
void put(String key, ConcurrentWebSocketSession val);
void remove(String key, String sessionId);
Collection<ConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId);
Collection<ConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType);
Long getConnectedCount();
}

7
src/main/java/com/dji/sample/component/websocket/service/impl/SendMessageServiceImpl.java

@ -5,6 +5,7 @@ import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
import com.dji.sample.component.websocket.service.ISendMessageService; import com.dji.sample.component.websocket.service.ISendMessageService;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
@ -20,6 +21,9 @@ import java.util.Collection;
@Slf4j @Slf4j
public class SendMessageServiceImpl implements ISendMessageService { public class SendMessageServiceImpl implements ISendMessageService {
@Autowired
private ObjectMapper mapper;
@Override @Override
public void sendMessage(ConcurrentWebSocketSession session, CustomWebSocketMessage message) { public void sendMessage(ConcurrentWebSocketSession session, CustomWebSocketMessage message) {
if (session == null) { if (session == null) {
@ -33,7 +37,6 @@ public class SendMessageServiceImpl implements ISendMessageService {
return; return;
} }
ObjectMapper mapper = new ObjectMapper();
session.sendMessage(new TextMessage(mapper.writeValueAsBytes(message))); session.sendMessage(new TextMessage(mapper.writeValueAsBytes(message)));
} catch (IOException e) { } catch (IOException e) {
@ -50,7 +53,6 @@ public class SendMessageServiceImpl implements ISendMessageService {
try { try {
ObjectMapper mapper = new ObjectMapper();
TextMessage data = new TextMessage(mapper.writeValueAsBytes(message)); TextMessage data = new TextMessage(mapper.writeValueAsBytes(message));
for (ConcurrentWebSocketSession session : sessions) { for (ConcurrentWebSocketSession session : sessions) {
@ -60,7 +62,6 @@ public class SendMessageServiceImpl implements ISendMessageService {
return; return;
} }
session.sendMessage(data); session.sendMessage(data);
} }
} catch (IOException e) { } catch (IOException e) {

90
src/main/java/com/dji/sample/component/websocket/service/impl/WebSocketManageServiceImpl.java

@ -0,0 +1,90 @@
package com.dji.sample.component.websocket.service.impl;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.component.websocket.config.ConcurrentWebSocketSession;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* @author sean
* @version 1.0
* @date 2022/4/25
*/
@Slf4j
@Service
public class WebSocketManageServiceImpl implements IWebSocketManageService {
private static final ConcurrentHashMap<String, ConcurrentWebSocketSession> SESSIONS = new ConcurrentHashMap<>(16);
@Autowired
private RedisOpsUtils redisOps;
@Override
public void put(String key, ConcurrentWebSocketSession val) {
String[] name = key.split("/");
if (name.length != 3) {
log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]");
return;
}
String sessionId = val.getId();
String workspaceKey = RedisConst.WEBSOCKET_PREFIX + name[0];
String userTypeKey = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])).getDesc();
redisOps.hashSet(workspaceKey, sessionId, name[2]);
redisOps.hashSet(userTypeKey, sessionId, name[2]);
SESSIONS.put(sessionId, val);
redisOps.expireKey(workspaceKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
redisOps.expireKey(userTypeKey, RedisConst.WEBSOCKET_ALIVE_SECOND);
}
@Override
public void remove(String key, String sessionId) {
String[] name = key.split("/");
if (name.length != 3) {
log.debug("The key is out of format. [{workspaceId}/{userType}/{userId}]");
return;
}
redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + name[0], new String[] {sessionId});
redisOps.hashDel(RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(Integer.parseInt(name[1])), new String[] {sessionId});
SESSIONS.remove(sessionId);
}
@Override
public Collection<ConcurrentWebSocketSession> getValueWithWorkspace(String workspaceId) {
if (!StringUtils.hasText(workspaceId)) {
return Collections.emptySet();
}
String key = RedisConst.WEBSOCKET_PREFIX + workspaceId;
return redisOps.hashKeys(key)
.stream()
.map(SESSIONS::get)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
@Override
public Collection<ConcurrentWebSocketSession> getValueWithWorkspaceAndUserType(String workspaceId, Integer userType) {
String key = RedisConst.WEBSOCKET_PREFIX + UserTypeEnum.find(userType).getDesc();
return redisOps.hashKeys(key)
.stream()
.map(SESSIONS::get)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
@Override
public Long getConnectedCount() {
return SESSIONS.mappingCount();
}
}

49
src/main/java/com/dji/sample/configuration/SpringBeanConfiguration.java

@ -0,0 +1,49 @@
package com.dji.sample.configuration;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class SpringBeanConfiguration {
@Bean
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
JavaTimeModule timeModule = new JavaTimeModule();
timeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
timeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
objectMapper.disable(MapperFeature.IGNORE_DUPLICATE_MODULE_REGISTRATIONS);
objectMapper.registerModules(timeModule);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString("");
}
});
return objectMapper;
}
}

104
src/main/java/com/dji/sample/manage/controller/DeviceController.java

@ -1,19 +1,13 @@
package com.dji.sample.manage.controller; package com.dji.sample.manage.controller;
import com.dji.sample.common.model.CustomClaim; import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult; import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.AuthInterceptor;
import com.dji.sample.component.mqtt.model.ChannelName; import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.component.mqtt.model.CommonTopicResponse; import com.dji.sample.component.mqtt.model.CommonTopicResponse;
import com.dji.sample.component.websocket.model.BizCodeEnum;
import com.dji.sample.component.websocket.model.CustomWebSocketMessage;
import com.dji.sample.component.websocket.model.WebSocketManager;
import com.dji.sample.component.websocket.service.ISendMessageService; import com.dji.sample.component.websocket.service.ISendMessageService;
import com.dji.sample.manage.model.dto.DeviceDTO; import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.WorkspaceDTO; import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.model.param.DeviceQueryParam;
import com.dji.sample.manage.model.receiver.StatusGatewayReceiver; import com.dji.sample.manage.model.receiver.StatusGatewayReceiver;
import com.dji.sample.manage.service.IDeviceService; import com.dji.sample.manage.service.IDeviceService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -21,12 +15,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.annotation.ServiceActivator; import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.mqtt.support.MqttHeaders; import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message; import org.springframework.messaging.Message;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List; import java.util.List;
import java.util.Optional;
/** /**
* @author sean.zhou * @author sean.zhou
@ -58,10 +50,6 @@ public class DeviceController {
.tid(receiver.getTid()) .tid(receiver.getTid())
.bid(receiver.getBid()) .bid(receiver.getBid())
.build()); .build());
// Publish the latest device topology information in the current workspace to the pilot.
deviceService.pushDeviceOnlineTopo(WorkspaceDTO.DEFAULT_WORKSPACE_ID,
receiver.getData().getSn(), receiver.getData().getSubDevices().get(0).getSn());
} }
} }
@ -81,22 +69,16 @@ public class DeviceController {
.bid(receiver.getBid()) .bid(receiver.getBid())
.build()); .build());
// Publish the latest device topology information in the current workspace to the pilot.
deviceService.pushDeviceOfflineTopo(WorkspaceDTO.DEFAULT_WORKSPACE_ID, receiver.getData().getSn());
} }
} }
/** /**
* Get the topology list of all devices in the current user workspace. * Get the topology list of all online devices in one workspace.
* @param request * @param workspaceId
* @return * @return
*/ */
@GetMapping("/devices") @GetMapping("/{workspace_id}/devices")
public ResponseResult<List<DeviceDTO>> getDevices(HttpServletRequest request) { public ResponseResult<List<DeviceDTO>> getDevices(@PathVariable("workspace_id") String workspaceId) {
// Get information about the current user.
CustomClaim claim = (CustomClaim)request.getAttribute(AuthInterceptor.TOKEN_CLAIM);
String workspaceId = claim.getWorkspaceId();
// Get information about the devices in the current user's workspace.
List<DeviceDTO> devicesList = deviceService.getDevicesTopoForWeb(workspaceId); List<DeviceDTO> devicesList = deviceService.getDevicesTopoForWeb(workspaceId);
return ResponseResult.success(devicesList); return ResponseResult.success(devicesList);
@ -109,30 +91,54 @@ public class DeviceController {
deviceService.handleOSD(topic, payload); deviceService.handleOSD(topic, payload);
} }
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_FIRMWARE_VERSION)
public void updateFirmwareVersion(FirmwareVersionReceiver receiver) {
deviceService.updateFirmwareVersion(receiver);
}
@PostMapping("/{device_sn}/binding")
public ResponseResult bindDevice(@RequestBody DeviceDTO device, @PathVariable("device_sn") String deviceSn) {
device.setDeviceSn(deviceSn);
boolean isUpd = deviceService.bindDevice(device);
return isUpd ? ResponseResult.success() : ResponseResult.error();
}
@GetMapping("/{workspace_id}/devices/{device_sn}")
public ResponseResult getDevice(@PathVariable("workspace_id") String workspaceId,
@PathVariable("device_sn") String deviceSn) {
Optional<DeviceDTO> deviceOpt = deviceService.getDeviceBySn(deviceSn);
return deviceOpt.isEmpty() ? ResponseResult.error("device not found.") : ResponseResult.success(deviceOpt.get());
}
/** /**
* Handles the payloads data of the drone. * Get the binding devices list in one workspace.
* @param deviceSn drone's sn * @param workspaceId
* @param page
* @param pageSize
* @return
*/ */
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_PAYLOAD_UPDATE) @GetMapping("/{workspace_id}/devices/bound")
public void pushWebSocketDevices(String deviceSn) { public ResponseResult<PaginationData<DeviceDTO>> getBoundDevicesWithDomain(
List<DeviceDTO> devicesList = deviceService.getDevicesByParams( @PathVariable("workspace_id") String workspaceId, String domain,
DeviceQueryParam.builder() @RequestParam(defaultValue = "1") Long page,
.deviceSn(deviceSn) @RequestParam(value = "page_size", defaultValue = "50") Long pageSize) {
.build()); PaginationData<DeviceDTO> devices = deviceService.getBoundDevicesWithDomain(workspaceId, page, pageSize, domain);
// Get drone information based on the sn of the drone. The sn of the drone is unique.
DeviceDTO device = devicesList.get(0); return ResponseResult.success(devices);
// Set the remote controller and payloads information of the drone. }
deviceService.spliceDeviceTopo(device);
@DeleteMapping("/{device_sn}/unbinding")
CustomWebSocketMessage wsMessage = CustomWebSocketMessage.builder() public ResponseResult unbindingDevice(@PathVariable("device_sn") String deviceSn) {
.timestamp(System.currentTimeMillis()) deviceService.unbindDevice(deviceSn);
.bizCode(BizCodeEnum.DEVICE_UPDATE_TOPO.getCode()) return ResponseResult.success();
.data(device) }
.build();
// Update the topology of the drone via WebSocket notifications to the web side. @PutMapping("/{workspace_id}/devices/{device_sn}")
sendMessageService.sendBatch(WebSocketManager public ResponseResult updateDevice(@RequestBody DeviceDTO device,
.getValueWithWorkspaceAndUserType( @PathVariable("workspace_id") String workspaceId,
device.getWorkspaceId(), UserTypeEnum.WEB.getVal()), @PathVariable("device_sn") String deviceSn) {
wsMessage); device.setDeviceSn(deviceSn);
boolean isUpd = deviceService.updateDevice(device);
return isUpd ? ResponseResult.success() : ResponseResult.error();
} }
} }

53
src/main/java/com/dji/sample/manage/controller/DeviceHmsController.java

@ -0,0 +1,53 @@
package com.dji.sample.manage.controller;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.manage.model.dto.DeviceHmsDTO;
import com.dji.sample.manage.model.param.DeviceHmsQueryParam;
import com.dji.sample.manage.service.IDeviceHmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author sean
* @version 1.1
* @date 2022/7/7
*/
@RestController
@Slf4j
@RequestMapping("${url.manage.prefix}${url.manage.version}/devices")
public class DeviceHmsController {
@Autowired
private IDeviceHmsService deviceHmsService;
@GetMapping("/{workspace_id}/devices/hms")
public ResponseResult<PaginationData<DeviceHmsDTO>> getBoundDevicesWithDomain(DeviceHmsQueryParam param,
@PathVariable("workspace_id") String workspaceId) {
PaginationData<DeviceHmsDTO> devices = deviceHmsService.getDeviceHmsByParam(param);
return ResponseResult.success(devices);
}
@PutMapping("/{workspace_id}/devices/hms/{device_sn}")
public ResponseResult updateReadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) {
deviceHmsService.updateUnreadHms(deviceSn);
return ResponseResult.success();
}
@GetMapping("/{workspace_id}/devices/hms/{device_sn}")
public ResponseResult<List<DeviceHmsDTO>> getUnreadHmsByDeviceSn(@PathVariable("device_sn") String deviceSn) {
PaginationData<DeviceHmsDTO> paginationData = deviceHmsService.getDeviceHmsByParam(
DeviceHmsQueryParam.builder()
.deviceSn(new HashSet<>(Set.of(deviceSn)))
.updateTime(0L)
.build());
return ResponseResult.success(paginationData.getList());
}
}

26
src/main/java/com/dji/sample/manage/controller/DevicePayloadController.java

@ -2,7 +2,6 @@ package com.dji.sample.manage.controller;
import com.dji.sample.component.mqtt.model.ChannelName; import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver; import com.dji.sample.manage.model.receiver.DeviceBasicReceiver;
import com.dji.sample.manage.model.receiver.DevicePayloadReceiver;
import com.dji.sample.manage.service.IDevicePayloadService; import com.dji.sample.manage.service.IDevicePayloadService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -23,25 +22,6 @@ public class DevicePayloadController {
@Autowired @Autowired
private IDevicePayloadService devicePayloadService; private IDevicePayloadService devicePayloadService;
/**
* Handles the data for the payload messages in the state topic.
* @param payloadsList List of payload information.
* @return drone's sn
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_PAYLOAD,
outputChannel = ChannelName.INBOUND_STATE_PAYLOAD_UPDATE)
public String statePayload(List<DevicePayloadReceiver> payloadsList) {
// Delete all payload information for the drone based on the drone's sn.
devicePayloadService.deletePayloadsByDeviceSn(List.of(payloadsList.get(0).getDeviceSn()));
// Save the new payload information.
devicePayloadService.savePayloadDTOs(payloadsList);
log.debug("The result of saving the payload is successful.");
return payloadsList.get(0).getDeviceSn();
}
/** /**
* Handles messages in the state topic about basic drone data. * Handles messages in the state topic about basic drone data.
* *
@ -50,9 +30,8 @@ public class DevicePayloadController {
* @param deviceBasic basic drone data * @param deviceBasic basic drone data
* @return drone's sn * @return drone's sn
*/ */
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC, @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC)
outputChannel = ChannelName.INBOUND_STATE_PAYLOAD_UPDATE) public void stateBasic(DeviceBasicReceiver deviceBasic) {
public String stateBasic(DeviceBasicReceiver deviceBasic) {
// Delete all payload information for the drone based on the drone's sn. // Delete all payload information for the drone based on the drone's sn.
devicePayloadService.deletePayloadsByDeviceSn(List.of(deviceBasic.getDeviceSn())); devicePayloadService.deletePayloadsByDeviceSn(List.of(deviceBasic.getDeviceSn()));
@ -61,6 +40,5 @@ public class DevicePayloadController {
log.debug("The result of saving the payloads is {}.", isSave); log.debug("The result of saving the payloads is {}.", isSave);
return deviceBasic.getDeviceSn();
} }
} }

21
src/main/java/com/dji/sample/manage/controller/LiveStreamController.java

@ -2,13 +2,13 @@ package com.dji.sample.manage.controller;
import com.dji.sample.common.model.CustomClaim; import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.model.ResponseResult; import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.model.Chan;
import com.dji.sample.component.mqtt.model.ChannelName; import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver; import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
import com.dji.sample.manage.model.Chan; import com.dji.sample.component.mqtt.model.ServiceReply;
import com.dji.sample.manage.model.dto.CapacityDeviceDTO; import com.dji.sample.manage.model.dto.CapacityDeviceDTO;
import com.dji.sample.manage.model.dto.LiveTypeDTO; import com.dji.sample.manage.model.dto.LiveTypeDTO;
import com.dji.sample.manage.model.receiver.CapacityDeviceReceiver; import com.dji.sample.manage.model.receiver.LiveCapacityReceiver;
import com.dji.sample.manage.model.receiver.ServiceReplyReceiver;
import com.dji.sample.manage.service.ILiveStreamService; import com.dji.sample.manage.service.ILiveStreamService;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -38,15 +38,17 @@ public class LiveStreamController {
@Autowired @Autowired
private ILiveStreamService liveStreamService; private ILiveStreamService liveStreamService;
@Autowired
private ObjectMapper mapper;
/** /**
* Analyze the live streaming capabilities of drones. * Analyze the live streaming capabilities of drones.
* This data is necessary if drones are required for live streaming. * This data is necessary if drones are required for live streaming.
* @param device the capacity of drone * @param liveCapacity the capacity of drone and dock
*/ */
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_CAPACITY) @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_CAPACITY)
public void stateCapacity(CapacityDeviceReceiver device) { public void stateCapacity(LiveCapacityReceiver liveCapacity) {
boolean parseCapacity = liveStreamService.saveLiveCapacity(device); liveStreamService.saveLiveCapacity(liveCapacity);
log.debug("The result of parsing the live capacity is {}.", parseCapacity);
} }
/** /**
@ -102,9 +104,8 @@ public class LiveStreamController {
@ServiceActivator(inputChannel = ChannelName.INBOUND_SERVICE_REPLY) @ServiceActivator(inputChannel = ChannelName.INBOUND_SERVICE_REPLY)
public void serviceReply(Message<?> message) throws IOException { public void serviceReply(Message<?> message) throws IOException {
byte[] payload = (byte[])message.getPayload(); byte[] payload = (byte[])message.getPayload();
ObjectMapper mapper = new ObjectMapper(); CommonTopicReceiver<ServiceReply> receiver = mapper.readValue(payload,
CommonTopicReceiver<ServiceReplyReceiver> receiver = mapper.readValue(payload, new TypeReference<CommonTopicReceiver<ServiceReply>>() {
new TypeReference<CommonTopicReceiver<ServiceReplyReceiver>>() {
}); });
Chan<CommonTopicReceiver> chan = Chan.getInstance(); Chan<CommonTopicReceiver> chan = Chan.getInstance();
// Put the message to the chan object. // Put the message to the chan object.

5
src/main/java/com/dji/sample/manage/controller/LoginController.java

@ -27,9 +27,10 @@ public class LoginController {
@PostMapping("/login") @PostMapping("/login")
public ResponseResult login(@RequestBody UserLoginDTO loginDTO) { public ResponseResult login(@RequestBody UserLoginDTO loginDTO) {
String username = loginDTO.getUsername(); String username = loginDTO.getUsername();
String password = loginDTO.getPassword(); String password = loginDTO.getPassword();
return userService.userLogin(username, password); return userService.userLogin(username, password, loginDTO.getFlag());
} }
@PostMapping("/token/refresh") @PostMapping("/token/refresh")
@ -42,6 +43,6 @@ public class LoginController {
return ResponseResult.error(CommonErrorEnum.NO_TOKEN.getErrorMsg()); return ResponseResult.error(CommonErrorEnum.NO_TOKEN.getErrorMsg());
} }
return ResponseResult.success(user); return ResponseResult.success(user.get());
} }
} }

41
src/main/java/com/dji/sample/manage/controller/UserController.java

@ -1,12 +1,12 @@
package com.dji.sample.manage.controller; package com.dji.sample.manage.controller;
import com.dji.sample.common.model.CustomClaim; import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult; import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.manage.model.dto.UserListDTO;
import com.dji.sample.manage.service.IUserService; import com.dji.sample.manage.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -20,10 +20,45 @@ public class UserController {
@Autowired @Autowired
private IUserService userService; private IUserService userService;
/**
* Query the information of the current user.
* @param request
* @return
*/
@GetMapping("/current") @GetMapping("/current")
public ResponseResult getCurrentUserInfo(HttpServletRequest request) { public ResponseResult getCurrentUserInfo(HttpServletRequest request) {
CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM); CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
return userService.getUserByUsername(customClaim.getUsername(), customClaim.getWorkspaceId()); return userService.getUserByUsername(customClaim.getUsername(), customClaim.getWorkspaceId());
} }
/**
* Paging to query all users in a workspace.
* @param page current page
* @param pageSize
* @param workspaceId
* @return
*/
@GetMapping("/{workspace_id}/users")
public ResponseResult<PaginationData<UserListDTO>> getUsers(@RequestParam(defaultValue = "1") Long page,
@RequestParam(value = "page_size", defaultValue = "50") Long pageSize,
@PathVariable("workspace_id") String workspaceId) {
PaginationData<UserListDTO> paginationData = userService.getUsersByWorkspaceId(page, pageSize, workspaceId);
return ResponseResult.success(paginationData);
}
/**
* Modify user information. Only mqtt account information is included, nothing else can be modified.
* @param user
* @param workspaceId
* @param userId
* @return
*/
@PutMapping("/{workspace_id}/users/{user_id}")
public ResponseResult updateUser(@RequestBody UserListDTO user,
@PathVariable("workspace_id") String workspaceId,
@PathVariable("user_id") String userId) {
userService.updateUser(workspaceId, userId, user);
return ResponseResult.success();
}
} }

12
src/main/java/com/dji/sample/manage/dao/IDeviceHmsMapper.java

@ -0,0 +1,12 @@
package com.dji.sample.manage.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dji.sample.manage.model.entity.DeviceHmsEntity;
/**
* @author sean
* @version 1.1
* @date 2022/7/6
*/
public interface IDeviceHmsMapper extends BaseMapper<DeviceHmsEntity> {
}

49
src/main/java/com/dji/sample/manage/model/common/HmsJsonUtil.java

@ -0,0 +1,49 @@
package com.dji.sample.manage.model.common;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
/**
* @author sean
* @version 1.1
* @date 2022/7/7
*/
@Slf4j
@Component
public class HmsJsonUtil {
private static ObjectMapper mapper;
@Autowired
public void setMapper(ObjectMapper mapper) {
HmsJsonUtil.mapper = mapper;
}
private static JsonNode nodes;
private HmsJsonUtil(){
}
@PostConstruct
private void loadJsonFile() {
try (InputStream inputStream = new ClassPathResource("hms.json").getInputStream()){
nodes = mapper.readTree(inputStream);
} catch (IOException e) {
log.error("hms.json failed to load.");
e.printStackTrace();
}
}
public static HmsMessage get(String key) {
return mapper.convertValue(nodes.get(key), HmsMessage.class);
}
}

16
src/main/java/com/dji/sample/manage/model/common/HmsMessage.java

@ -0,0 +1,16 @@
package com.dji.sample.manage.model.common;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/7/7
*/
@Data
public class HmsMessage {
private String zh;
private String en;
}

4
src/main/java/com/dji/sample/manage/model/dto/CapacityCameraDTO.java

@ -18,14 +18,12 @@ import java.util.List;
@NoArgsConstructor @NoArgsConstructor
public class CapacityCameraDTO { public class CapacityCameraDTO {
private Integer id; private String id;
private String deviceSn; private String deviceSn;
private String name; private String name;
private String description;
private String index; private String index;
private String type; private String type;

2
src/main/java/com/dji/sample/manage/model/dto/CapacityVideoDTO.java

@ -16,7 +16,7 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor @NoArgsConstructor
public class CapacityVideoDTO { public class CapacityVideoDTO {
private Integer id; private String id;
private String index; private String index;

22
src/main/java/com/dji/sample/manage/model/dto/DeviceDTO.java

@ -1,12 +1,11 @@
package com.dji.sample.manage.model.dto; package com.dji.sample.manage.model.dto;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
/** /**
@ -18,7 +17,6 @@ import java.util.List;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Builder @Builder
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class DeviceDTO { public class DeviceDTO {
private String deviceSn; private String deviceSn;
@ -44,4 +42,22 @@ public class DeviceDTO {
private List<DevicePayloadDTO> payloadsList; private List<DevicePayloadDTO> payloadsList;
private IconUrlDTO iconUrl; private IconUrlDTO iconUrl;
private Boolean status;
private Boolean boundStatus;
private LocalDateTime loginTime;
private LocalDateTime boundTime;
private String nickname;
private String userId;
private String firmwareVersion;
private String workspaceName;
private DeviceDTO children;
} }

57
src/main/java/com/dji/sample/manage/model/dto/DeviceHmsDTO.java

@ -0,0 +1,57 @@
package com.dji.sample.manage.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* @author sean
* @version 1.1
* @date 2022/7/8
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class DeviceHmsDTO implements Cloneable {
private String hmsId;
private String tid;
private String bid;
private String sn;
private Integer level;
private Integer module;
private String key;
private String messageZh;
private String messageEn;
private LocalDateTime createTime;
private LocalDateTime updateTime;
@Override
public DeviceHmsDTO clone() {
try {
return (DeviceHmsDTO) super.clone();
} catch (CloneNotSupportedException e) {
return DeviceHmsDTO.builder()
.sn(this.sn)
.bid(this.bid)
.tid(this.tid)
.createTime(this.createTime)
.updateTime(this.updateTime)
.build();
}
}
}

4
src/main/java/com/dji/sample/manage/model/dto/TelemetryDTO.java

@ -14,9 +14,9 @@ import lombok.NoArgsConstructor;
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class TelemetryDTO { public class TelemetryDTO<T> {
private TelemetryDeviceDTO host; private T host;
private String sn; private String sn;
} }

11
src/main/java/com/dji/sample/manage/model/dto/TopologyDeviceDTO.java

@ -22,8 +22,7 @@ public class TopologyDeviceDTO {
private DeviceModelDTO deviceModel; private DeviceModelDTO deviceModel;
@Builder.Default private Boolean onlineStatus;
private Boolean onlineStatus = true;
private String deviceCallsign; private String deviceCallsign;
@ -32,4 +31,12 @@ public class TopologyDeviceDTO {
private String userCallsign; private String userCallsign;
private IconUrlDTO iconUrls; private IconUrlDTO iconUrls;
private String model;
private Boolean boundStatus;
private String gatewaySn;
private String domain;
} }

34
src/main/java/com/dji/sample/manage/model/dto/UserListDTO.java

@ -0,0 +1,34 @@
package com.dji.sample.manage.model.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* @author sean
* @version 1.0
* @date 2022/4/18
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserListDTO {
private String userId;
private String username;
private String workspaceName;
private String userType;
private String mqttUsername;
private String mqttPassword;
private LocalDateTime createTime;
}

3
src/main/java/com/dji/sample/manage/model/dto/UserLoginDTO.java

@ -11,4 +11,7 @@ public class UserLoginDTO {
@NonNull @NonNull
private String password; private String password;
@NonNull
private Integer flag;
} }

4
src/main/java/com/dji/sample/manage/model/dto/WorkspaceDTO.java

@ -19,8 +19,6 @@ import lombok.NoArgsConstructor;
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class) @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class WorkspaceDTO { public class WorkspaceDTO {
public static final String DEFAULT_WORKSPACE_ID = "e3dea0f5-37f2-4d79-ae58-490af3228069";
private Integer id; private Integer id;
private String workspaceId; private String workspaceId;
@ -30,4 +28,6 @@ public class WorkspaceDTO {
private String workspaceDesc; private String workspaceDesc;
private String platformName; private String platformName;
private String bindCode;
} }

19
src/main/java/com/dji/sample/manage/model/entity/DeviceEntity.java

@ -66,4 +66,23 @@ public class DeviceEntity implements Serializable {
@TableField(value = "url_select") @TableField(value = "url_select")
private String urlSelect; private String urlSelect;
@TableField(value = "user_id")
private String userId;
@TableField(value = "nickname")
private String nickname;
@TableField(value = "firmware_version")
private String firmwareVersion;
@TableField(value = "bound_status")
private Boolean boundStatus;
@TableField(value = "bound_time")
private Long boundTime;
@TableField(value = "login_time")
private Long loginTime;
} }

76
src/main/java/com/dji/sample/manage/model/entity/DeviceHmsEntity.java

@ -0,0 +1,76 @@
package com.dji.sample.manage.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author sean
* @version 1.1
* @date 2022/7/6
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "manage_device_hms")
public class DeviceHmsEntity implements Serializable, Cloneable {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("hms_id")
private String hmsId;
@TableField("tid")
private String tid;
@TableField("bid")
private String bid;
@TableField("sn")
private String sn;
@TableField("level")
private Integer level;
@TableField("module")
private Integer module;
@TableField("hms_key")
private String hmsKey;
@TableField("message_zh")
private String messageZh;
@TableField("message_en")
private String messageEn;
@TableField("create_time")
private Long createTime;
@TableField("update_time")
private Long updateTime;
@Override
public DeviceHmsEntity clone() {
try {
return (DeviceHmsEntity) super.clone();
} catch (CloneNotSupportedException e) {
return DeviceHmsEntity.builder()
.bid(this.getBid())
.tid(this.getTid())
.createTime(this.getCreateTime())
.updateTime(this.getUpdateTime())
.sn(this.getSn())
.build();
}
}
}

4
src/main/java/com/dji/sample/manage/model/entity/DevicePayloadEntity.java

@ -35,8 +35,8 @@ public class DevicePayloadEntity implements Serializable {
@TableField(value = "sub_type") @TableField(value = "sub_type")
private Integer subType; private Integer subType;
@TableField(value = "version") @TableField(value = "firmware_version")
private Integer version; private String firmwareVersion;
@TableField(value = "payload_index") @TableField(value = "payload_index")
private Integer payloadIndex; private Integer payloadIndex;

2
src/main/java/com/dji/sample/manage/model/entity/UserEntity.java

@ -22,7 +22,7 @@ public class UserEntity implements Serializable {
private String password; private String password;
@TableField(value = "workspace_id") @TableField(value = "workspace_id")
private Integer workspaceId; private String workspaceId;
@TableField(value = "user_type") @TableField(value = "user_type")
private Integer userType; private Integer userType;

2
src/main/java/com/dji/sample/manage/model/entity/WorkspaceEntity.java

@ -30,4 +30,6 @@ public class WorkspaceEntity implements Serializable {
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
private Long updateTime; private Long updateTime;
@TableField(value = "bind_code")
private String bindCode;
} }

14
src/main/java/com/dji/sample/manage/model/enums/DeviceDomainEnum.java

@ -14,6 +14,8 @@ public enum DeviceDomainEnum {
PAYLOAD(1, "payload"), PAYLOAD(1, "payload"),
DOCK (3, "dock"),
UNKNOWN(-1, "unknown"); UNKNOWN(-1, "unknown");
private int val; private int val;
@ -29,6 +31,10 @@ public enum DeviceDomainEnum {
return val; return val;
} }
public String getDesc() {
return desc;
}
public static String getDesc(int val) { public static String getDesc(int val) {
if (SUB_DEVICE.val == val) { if (SUB_DEVICE.val == val) {
return SUB_DEVICE.desc; return SUB_DEVICE.desc;
@ -41,6 +47,10 @@ public enum DeviceDomainEnum {
if (PAYLOAD.val == val) { if (PAYLOAD.val == val) {
return PAYLOAD.desc; return PAYLOAD.desc;
} }
if (DOCK.val == val) {
return DOCK.desc;
}
return UNKNOWN.desc; return UNKNOWN.desc;
} }
@ -56,6 +66,10 @@ public enum DeviceDomainEnum {
if (PAYLOAD.desc.equals(desc)) { if (PAYLOAD.desc.equals(desc)) {
return PAYLOAD.val; return PAYLOAD.val;
} }
if (DOCK.desc.equals(desc)) {
return DOCK.val;
}
return UNKNOWN.val; return UNKNOWN.val;
} }

155
src/main/java/com/dji/sample/manage/model/enums/HmsEnum.java

@ -0,0 +1,155 @@
package com.dji.sample.manage.model.enums;
import lombok.Getter;
import java.util.Arrays;
/**
* @author sean
* @version 1.1
* @date 2022/7/7
*/
@Getter
public enum HmsEnum {
IN_THE_SKY("_in_the_sky", 1);
private int val;
private String text;
HmsEnum(String text, int val) {
this.text = text;
this.val = val;
}
@Getter
public enum MessageLanguage {
EN("en"),
ZH("zh");
String language;
MessageLanguage(String language) {
this.language = language;
}
}
@Getter
public enum DomainType {
DRONE_NEST("drone_nest"),
DRONE("drone");
private String domain;
DomainType(String domain) {
this.domain = domain;
}
}
@Getter
public enum HmsFaqIdEnum {
FPV_TIP("fpv_tip_");
private String text;
HmsFaqIdEnum(String text) {
this.text = text;
}
}
@Getter
public enum HmsBatteryIndexEnum {
LEFT(0, "left", "左"),
RIGHT(1, "right", "右"),
UNKNOWN(-1, "unknown", "未知");
private int val;
private String en;
private String zh;
HmsBatteryIndexEnum(int val, String en, String zh) {
this.val = val;
this.en = en;
this.zh = zh;
}
public static HmsBatteryIndexEnum find(int val) {
return Arrays.stream(HmsBatteryIndexEnum.values())
.filter(battery -> battery.val == val)
.findAny()
.orElse(UNKNOWN);
}
}
@Getter
public enum HmsDockCoverIndexEnum {
LEFT(0, "left", "左"),
RIGHT(1, "right", "右"),
UNKNOWN(-1, "unknown", "未知");
private int val;
private String en;
private String zh;
HmsDockCoverIndexEnum(int val, String en, String zh) {
this.val = val;
this.en = en;
this.zh = zh;
}
public static HmsDockCoverIndexEnum find(int val) {
return Arrays.stream(HmsDockCoverIndexEnum.values())
.filter(dockCover -> dockCover.val == val)
.findAny()
.orElse(UNKNOWN);
}
}
@Getter
public enum HmsChargingRodIndexEnum {
FRONT(0, "front", "前"),
BACK(1, "back", "后"),
LEFT(2, "left", "左"),
RIGHT(3, "right", "右"),
UNKNOWN(-1, "unknown", "未知");
private int val;
private String en;
private String zh;
HmsChargingRodIndexEnum(int val, String en, String zh) {
this.val = val;
this.en = en;
this.zh = zh;
}
public static HmsChargingRodIndexEnum find(int val) {
return Arrays.stream(HmsChargingRodIndexEnum.values())
.filter(rod -> rod.val == val)
.findAny()
.orElse(UNKNOWN);
}
}
}

61
src/main/java/com/dji/sample/manage/model/enums/PayloadModelEnum.java

@ -0,0 +1,61 @@
package com.dji.sample.manage.model.enums;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author sean
* @version 1.0
* @date 2022/4/29
*/
public enum PayloadModelEnum {
Z30("Z30", "20-0"),
XT2("XT2", "26-0"),
XTS("XTS", "41-0"),
H20("H20", "42-0"),
H20T("H20T", "43-0"),
P1("P1", "50-65535"),
M30("M30", "52-0"),
M30T("M30T", "53-0"),
H20N("H20N", "61-0"),
DOCK("DOCK", "165-0"),
L1("L1", "90742-0");
private String model;
private String index;
PayloadModelEnum(String model, String index) {
this.model = model;
this.index = index;
}
public String getModel() {
return model;
}
public String getIndex() {
return index;
}
public static List<String> getAllModel() {
return Arrays.stream(PayloadModelEnum.values()).map(PayloadModelEnum::getModel).collect(Collectors.toList());
}
public static List<String> getAllIndex() {
return Arrays.stream(PayloadModelEnum.values()).map(PayloadModelEnum::getIndex).collect(Collectors.toList());
}
}

26
src/main/java/com/dji/sample/manage/model/enums/UserTypeEnum.java

@ -7,18 +7,36 @@ package com.dji.sample.manage.model.enums;
*/ */
public enum UserTypeEnum { public enum UserTypeEnum {
WEB(1), WEB(1, "Web"),
PILOT(2); PILOT(2, "Pilot"),
UNKNOWN(-1, "Unknown");
private int val; private int val;
private String desc;
UserTypeEnum(int val) { UserTypeEnum(int val, String desc) {
this.val = val; this.val = val;
this.desc = desc;
} }
public int getVal() { public int getVal() {
return val; return this.val;
}
public String getDesc() {
return this.desc;
}
public static UserTypeEnum find(int val) {
if (val == WEB.val) {
return WEB;
}
if (val == PILOT.val) {
return PILOT;
}
return UNKNOWN;
} }
} }

45
src/main/java/com/dji/sample/manage/model/param/DeviceHmsQueryParam.java

@ -0,0 +1,45 @@
package com.dji.sample.manage.model.param;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Set;
/**
* @author sean
* @version 1.1
* @date 2022/7/8
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DeviceHmsQueryParam implements Serializable {
@JsonProperty("device_sn")
private Set<String> deviceSn;
@JsonProperty("begin_time")
private Long beginTime;
@JsonProperty("end_time")
private Long endTime;
private String language;
private String message;
private Long page;
@JsonProperty("page_size")
private Long pageSize;
private Integer level;
@JsonProperty("update_time")
private Long updateTime;
}

6
src/main/java/com/dji/sample/manage/model/param/DeviceQueryParam.java

@ -3,6 +3,8 @@ package com.dji.sample.manage.model.param;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import java.util.List;
/** /**
* The object of the device query field. * The object of the device query field.
* *
@ -22,10 +24,12 @@ public class DeviceQueryParam {
private Integer subType; private Integer subType;
private Integer domain; private List<Integer> domains;
private String childSn; private String childSn;
private Boolean boundStatus;
private boolean orderBy; private boolean orderBy;
private boolean isAsc; private boolean isAsc;

18
src/main/java/com/dji/sample/manage/model/receiver/AlternateLandPointReceiver.java

@ -0,0 +1,18 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.0
* @date 2022/5/11
*/
@Data
public class AlternateLandPointReceiver {
private Double latitude;
private Double longitude;
private Double safeLandHeight;
}

22
src/main/java/com/dji/sample/manage/model/receiver/BindDeviceReceiver.java

@ -0,0 +1,22 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/6/13
*/
@Data
public class BindDeviceReceiver {
private String deviceBindingCode;
private String organizationId;
private String deviceCallsign;
private String sn;
private String deviceModelKey;
}

30
src/main/java/com/dji/sample/manage/model/receiver/BindStatusReceiver.java

@ -0,0 +1,30 @@
package com.dji.sample.manage.model.receiver;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.1
* @date 2022/6/14
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude
public class BindStatusReceiver {
private String sn;
private Boolean isDeviceBindOrganization;
private String organizationId;
private String organizationName;
private String deviceCallsign;
}

6
src/main/java/com/dji/sample/manage/model/receiver/DeviceBasicReceiver.java

@ -21,18 +21,12 @@ public class DeviceBasicReceiver {
private String deviceSn; private String deviceSn;
private Integer flightMode;
private Integer flightStatus;
private Double homeLatitude; private Double homeLatitude;
private Double homeLongitude; private Double homeLongitude;
private Integer lowBatteryWarningThreshold; private Integer lowBatteryWarningThreshold;
private Integer positionMode;
private Integer seriousLowBatteryWarningThreshold; private Integer seriousLowBatteryWarningThreshold;
private List<DevicePayloadReceiver> payloads; private List<DevicePayloadReceiver> payloads;

28
src/main/java/com/dji/sample/manage/model/receiver/DeviceHmsReceiver.java

@ -0,0 +1,28 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/7/6
*/
@Data
public class DeviceHmsReceiver {
private String code;
private String deviceType;
private String domainType;
private Integer imminent;
private Integer inTheSky;
private Integer level;
private Integer module;
private HmsArgsReceiver args;
}

3
src/main/java/com/dji/sample/manage/model/receiver/DevicePayloadReceiver.java

@ -23,7 +23,4 @@ public class DevicePayloadReceiver {
private String sn; private String sn;
private Integer version;
private Integer workMode;
} }

14
src/main/java/com/dji/sample/manage/model/receiver/DockMediaFileDetailReceiver.java

@ -0,0 +1,14 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/6/17
*/
@Data
public class DockMediaFileDetailReceiver {
private Integer remainUpload;
}

18
src/main/java/com/dji/sample/manage/model/receiver/DockSdrReceiver.java

@ -0,0 +1,18 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/6/17
*/
@Data
public class DockSdrReceiver {
private Integer downQuality;
private Double frequencyBand;
private Integer upQuality;
}

20
src/main/java/com/dji/sample/manage/model/receiver/DockSubDeviceReceiver.java

@ -0,0 +1,20 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.0
* @date 2022/5/11
*/
@Data
public class DockSubDeviceReceiver {
private String deviceSn;
private Integer deviceOnlineStatus;
private Integer devicePaired;
private String deviceModelKey;
}

16
src/main/java/com/dji/sample/manage/model/receiver/DroneChargeStateReceiver.java

@ -0,0 +1,16 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.0
* @date 2022/5/11
*/
@Data
public class DroneChargeStateReceiver {
private Integer state;
private Integer capacityPercent;
}

29
src/main/java/com/dji/sample/manage/model/receiver/FirmwareVersionReceiver.java

@ -0,0 +1,29 @@
package com.dji.sample.manage.model.receiver;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author sean
* @version 1.0
* @date 2022/4/28
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class FirmwareVersionReceiver {
private String firmwareVersion;
private Integer compatibleStatus;
private Integer firmwareUpgradeStatus;
private String sn;
private DeviceDomainEnum domain;
}

18
src/main/java/com/dji/sample/manage/model/receiver/HmsArgsReceiver.java

@ -0,0 +1,18 @@
package com.dji.sample.manage.model.receiver;
import lombok.Data;
/**
* @author sean
* @version 1.1
* @date 2022/7/6
*/
@Data
public class HmsArgsReceiver {
private Long componentIndex;
private Integer sensorIndex;
private Integer alarmId;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save