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. 137
      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. 51
      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. 63
      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. 44
      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 @@ -6,15 +6,15 @@ The launch of the Cloud API mainly solves the problem of developers reinventing
## 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
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
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

328
api/Cloud API Demo.postman_collection.json

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
"header": [],
"body": {
"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": {
"raw": {
"language": "json"
@ -100,12 +100,13 @@ @@ -100,12 +100,13 @@
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}{{manage_version}}/devices/devices",
"raw": "{{base_url}}{{manage_version}}/devices/{{workspace_id}}/devices",
"host": [
"{{base_url}}{{manage_version}}"
],
"path": [
"devices",
"{{workspace_id}}",
"devices"
]
}
@ -132,12 +133,23 @@ @@ -132,12 +133,23 @@
},
{
"name": "Start Livestream",
"event": [
{
"listen": "test",
"script": {
"exec": [
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "POST",
"header": [],
"body": {
"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": {
"raw": {
"language": "json"
@ -165,7 +177,7 @@ @@ -165,7 +177,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"video_id\": \"\"\r\n}",
"raw": "{\r\n \"video_id\": \"1581F4BNDQ/39-0-7/normal-0\"\r\n}",
"options": {
"raw": {
"language": "json"
@ -213,19 +225,177 @@ @@ -213,19 +225,177 @@
}
},
"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": {
"type": "apikey",
"apikey": [
{
"key": "key",
"value": "x-auth-token",
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTI2OTUxOTcsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTI3ODE1OTcsImlhdCI6MTY1MjY5NTE5NywidXNlcm5hbWUiOiJhZG1pblBDIn0.BHTwW8imw5ab0GUypRyJ2gkoz5av9q99NrxoFlL53dA",
"type": "string"
},
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM",
"key": "key",
"value": "x-auth-token",
"type": "string"
}
]
@ -390,7 +560,7 @@ @@ -390,7 +560,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTMzNzI3NDUsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTM0NTkxNDUsImlhdCI6MTY1MzM3Mjc0NSwidXNlcm5hbWUiOiJhZG1pblBDIn0.Zyb_f4umcGY2-WDaQKA1LHGOs9qYfJuPc3rQeIS-4hY",
"type": "string"
},
{
@ -520,15 +690,12 @@ @@ -520,15 +690,12 @@
},
{
"name": "Check Tiny Fingerprints",
"protocolProfileBehavior": {
"disableBodyPruning": true
},
"request": {
"method": "GET",
"method": "POST",
"header": [],
"body": {
"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": {
"raw": {
"language": "json"
@ -536,7 +703,7 @@ @@ -536,7 +703,7 @@
}
},
"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": [
"{{base_url}}{{media_version}}"
],
@ -545,12 +712,6 @@ @@ -545,12 +712,6 @@
"{{workspace_id}}",
"files",
"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 @@ @@ -562,7 +723,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTgzOTIyNzksImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTg0Nzg2NzksImlhdCI6MTY1ODM5MjI3OSwidXNlcm5hbWUiOiJhZG1pblBDIn0.ErClyQS1YzoQVBcLYxpFEiyFTb1L-eg2-vsudlL9WJU",
"type": "string"
},
{
@ -622,7 +783,7 @@ @@ -622,7 +783,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NDg1MjI5ODAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NDg2MDkzODAsImlhdCI6MTY0ODUyMjk4MCwidXNlcm5hbWUiOiJhZG1pblBDIn0.QEDpB_60G4YLLXR_6rLZHWZNVbA1j162Xs1fZx8wEOM",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTI2OTUxOTcsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTI3ODE1OTcsImlhdCI6MTY1MjY5NTE5NywidXNlcm5hbWUiOiJhZG1pblBDIn0.BHTwW8imw5ab0GUypRyJ2gkoz5av9q99NrxoFlL53dA",
"type": "string"
},
{
@ -848,7 +1009,124 @@ @@ -848,7 +1009,124 @@
"apikey": [
{
"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"
},
{
@ -885,7 +1163,7 @@ @@ -885,7 +1163,7 @@
"apikey": [
{
"key": "value",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2Mzg5MzY2OTEsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2MzkwMjMwOTEsImlhdCI6MTYzODkzNjY5MSwidXNlcm5hbWUiOiJhZG1pblBDIn0.W_v88rbhVKivl61MnJ0Cz_0Eq6Gw0RotiHCdLj0UPSQ",
"value": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ3b3Jrc3BhY2VfaWQiOiJlM2RlYTBmNS0zN2YyLTRkNzktYWU1OC00OTBhZjMyMjgwNjkiLCJzdWIiOiJDbG91ZEFwaVNhbXBsZSIsInVzZXJfdHlwZSI6IjEiLCJuYmYiOjE2NTA0MjY3MzAsImxvZyI6IkxvZ2dlcltjb20uZGppLnNhbXBsZS5jb21tb24ubW9kZWwuQ3VzdG9tQ2xhaW1dIiwiaXNzIjoiREpJIiwiaWQiOiJhMTU1OWU3Yy04ZGQ4LTQ3ODAtYjk1Mi0xMDBjYzQ3OTdkYTIiLCJleHAiOjE2NTA1MTMxMzAsImlhdCI6MTY1MDQyNjczMCwidXNlcm5hbWUiOiJhZG1pblBDIn0.-FBpi0ktuZ68jV6-HQ7mwm8iC07YH-Hw2aRiREzJ8hs",
"type": "string"
},
{

6
api/Cloud API Demo.postman_environment.json

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

31
pom.xml

@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
<groupId>com.dji</groupId>
<artifactId>cloud-api-sample</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<name>cloud-api-sample</name>
<properties>
@ -127,6 +127,35 @@ @@ -127,6 +127,35 @@
<version>${glassfish-jaxb.version}</version>
</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>
<build>

137
sql/cloud_sample.sql

@ -10,38 +10,6 @@ SET NAMES utf8mb4; @@ -10,38 +10,6 @@ SET NAMES utf8mb4;
/*!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_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
# ------------------------------------------------------------
@ -52,18 +20,24 @@ CREATE TABLE `manage_device` ( @@ -52,18 +20,24 @@ CREATE TABLE `manage_device` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`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',
`workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`device_type` smallint NOT NULL,
`sub_type` smallint NOT NULL,
`domain` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`version` smallint NOT NULL,
`device_index` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`child_sn` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`user_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`nickname` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`workspace_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`device_type` smallint NOT NULL DEFAULT '-1',
`sub_type` smallint NOT NULL DEFAULT '-1',
`domain` smallint NOT NULL DEFAULT '-1',
`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,
`update_time` bigint NOT NULL,
`device_desc` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`url_normal` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`url_select` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`bound_time` bigint DEFAULT NULL,
`bound_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0:bund; 1:not bound',
`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`),
UNIQUE KEY `product_sn_UNIQUE` (`device_sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
@ -106,14 +80,36 @@ VALUES @@ -106,14 +80,36 @@ VALUES
(14,1,165,0,'DJI Dock Camera',NULL),
(15,1,90742,0,'L1',NULL),
(16,2,56,0,'DJI Smart Controller','Remote control for M300'),
(17,2,119,0,'Matrice 30 Smart Controller','Remote control for M30'),
(18,3,1,0,'DJI Dock','DJI Airport');
(17,2,119,0,'DJI RC Plus','Remote control for M30'),
(18,3,1,0,'DJI Dock','');
/*!40000 ALTER TABLE `manage_device_dictionary` ENABLE KEYS */;
UNLOCK TABLES;
# 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
# ------------------------------------------------------------
@ -125,7 +121,7 @@ CREATE TABLE `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_type` smallint NOT NULL,
`sub_type` smallint NOT NULL,
`version` smallint DEFAULT NULL,
`firmware_version` varchar(32) DEFAULT NULL,
`payload_index` smallint NOT NULL,
`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,
@ -147,7 +143,7 @@ CREATE TABLE `manage_user` ( @@ -147,7 +143,7 @@ CREATE TABLE `manage_user` (
`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 '',
`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,
`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 '',
@ -162,8 +158,8 @@ LOCK TABLES `manage_user` WRITE; @@ -162,8 +158,8 @@ 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`)
VALUES
(1,'a1559e7c-8dd8-4780-b952-100cc4797da2','adminPC','adminPC',1,1,'admin','admin',1634898410751,1634898410751),
(2,'be7c6c3d-afe9-4be4-b9eb-c55066c0914e','pilot','pilot123',1,2,'pilot','pilot123',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','e3dea0f5-37f2-4d79-ae58-490af3228069',2,'pilot','pilot123',1634898410751,1634898410751);
/*!40000 ALTER TABLE `manage_user` ENABLE KEYS */;
UNLOCK TABLES;
@ -182,16 +178,18 @@ CREATE TABLE `manage_workspace` ( @@ -182,16 +178,18 @@ CREATE TABLE `manage_workspace` (
`platform_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`create_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`),
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;
LOCK TABLES `manage_workspace` WRITE;
/*!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
(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 */;
UNLOCK TABLES;
@ -277,17 +275,17 @@ CREATE TABLE `media_file` ( @@ -277,17 +275,17 @@ CREATE TABLE `media_file` (
`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 '',
`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 '',
`object_key` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`sub_file_type` int NOT NULL,
`object_key` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
`sub_file_type` int DEFAULT NULL,
`is_original` tinyint(1) NOT NULL,
`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',
`job_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '',
`create_time` bigint NOT NULL,
`update_time` bigint NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `fingerprint_UNIQUE` (`fingerprint`)
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
@ -304,18 +302,41 @@ CREATE TABLE `wayline_file` ( @@ -304,18 +302,41 @@ CREATE TABLE `wayline_file` (
`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,
`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',
`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 '',
`user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci 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`),
UNIQUE KEY `wayline_id_UNIQUE` (`wayline_id`)
) 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 */;
/*!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; @@ -8,6 +8,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
@MapperScan("com.dji.sample.*.dao")
@SpringBootApplication
@EnableScheduling
//@EnableConfigurationProperties(OssConfiguration.class)
public class CloudApiSampleApplication {
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; @@ -7,6 +7,16 @@ package com.dji.sample.common.error;
*/
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"),
SECRET_INVALID(600100, "secret invalid"),

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

@ -0,0 +1,38 @@ @@ -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 { @@ -54,6 +54,10 @@ public class JwtUtil {
JwtUtil.algorithm = Algorithm.HMAC256(secret);
}
private JwtUtil() {
}
/**
* Create a token based on custom information.
* @param claims custom information

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

@ -1,15 +1,12 @@ @@ -1,15 +1,12 @@
package com.dji.sample.component;
import com.dji.sample.manage.model.DeviceStatusManager;
import com.dji.sample.manage.model.enums.DeviceDomainEnum;
import com.dji.sample.manage.model.param.DeviceQueryParam;
import com.dji.sample.component.redis.RedisConst;
import com.dji.sample.component.redis.RedisOpsUtils;
import com.dji.sample.manage.service.IDeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* @author sean.zhou
* @date 2021/11/24
@ -21,20 +18,21 @@ public class ApplicationBootInitial implements CommandLineRunner { @@ -21,20 +18,21 @@ public class ApplicationBootInitial implements CommandLineRunner {
@Autowired
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.
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
deviceService.getDevicesByParams(DeviceQueryParam.builder().build())
.forEach(device -> {
deviceService.subscribeTopicOnline(device.getDeviceSn());
DeviceStatusManager.STATUS_MANAGER.put(
DeviceDomainEnum.getVal(device.getDomain()) + "/"
+ device.getDeviceSn(), LocalDateTime.now());
});
int start = RedisConst.DEVICE_ONLINE_PREFIX.length();
redisOps.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*")
.forEach(key -> deviceService.subscribeTopicOnline(key.substring(start)));
}
}

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

@ -1,5 +1,9 @@ @@ -1,5 +1,9 @@
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.service.IDeviceService;
import lombok.extern.slf4j.Slf4j;
@ -7,13 +11,9 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -7,13 +11,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.Arrays;
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
* @date 2021/11/24
@ -26,33 +26,34 @@ public class GlobalScheduleService { @@ -26,33 +26,34 @@ public class GlobalScheduleService {
@Autowired
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.
*/
@Scheduled(fixedRate = 30, timeUnit = TimeUnit.SECONDS)
@Scheduled(initialDelay = 30, fixedRate = 30, timeUnit = TimeUnit.SECONDS)
private void deviceStatusListen() {
for (Map.Entry<String, LocalDateTime> entry : STATUS_MANAGER.entrySet()) {
if (entry.getValue().isAfter(
LocalDateTime.now().minusSeconds(DEFAULT_ALIVE_SECOND))) {
continue;
int start = RedisConst.DEVICE_ONLINE_PREFIX.length();
redisOps.getAllKeys(RedisConst.DEVICE_ONLINE_PREFIX + "*").forEach(key -> {
long expire = redisOps.getExpire(key);
if (expire <= 30) {
DeviceDTO device = (DeviceDTO) redisOps.get(key);
if (device.getDomain().equals(DeviceDomainEnum.SUB_DEVICE.getDesc())) {
deviceService.subDeviceOffline(key.substring(start));
} else {
deviceService.unsubscribeTopicOffline(key.substring(start));
deviceService.pushDeviceOfflineTopo(device.getWorkspaceId(), device.getDeviceSn());
}
String device = entry.getKey();
int index = device.indexOf("/");
STATUS_MANAGER.remove(device);
int type = Integer.parseInt(device.substring(0, index));
String sn = device.substring(index + 1);
// Determine whether it is a gateway device.
if (DeviceDomainEnum.GATEWAY.getVal() == type) {
deviceService.deviceOffline(sn);
deviceService.unsubscribeTopicOffline(sn);
continue;
redisOps.del(key);
}
});
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; @@ -11,6 +11,7 @@ import org.springframework.integration.endpoint.MessageProducerSupport;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
@ -62,7 +63,9 @@ public class MqttInboundConfiguration { @@ -62,7 +63,9 @@ public class MqttInboundConfiguration {
@ServiceActivator(inputChannel = ChannelName.DEFAULT)
public MessageHandler defaultInboundHandler() {
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 { @@ -74,7 +74,7 @@ public class MqttMessageChannel {
@Bean(name = ChannelName.INBOUND_OSD)
public MessageChannel osdChannel() {
return new DirectChannel();
return new ExecutorChannel(threadPool);
}
@Bean(name = ChannelName.DEFAULT)
@ -87,4 +87,54 @@ public class MqttMessageChannel { @@ -87,4 +87,54 @@ public class MqttMessageChannel {
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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 { @@ -43,4 +43,23 @@ public class ChannelName {
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> { @@ -26,4 +26,10 @@ public class CommonTopicReceiver<T> {
private Long timestamp;
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> { @@ -30,4 +30,6 @@ public class CommonTopicResponse<T> {
private String method;
private T data;
private Long timestamp;
}

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

@ -0,0 +1,23 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 { @@ -24,6 +24,10 @@ public class TopicConst {
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]+";
}

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

@ -1,6 +1,9 @@ @@ -1,6 +1,9 @@
package com.dji.sample.component.mqtt.service;
import com.dji.sample.component.mqtt.model.CommonTopicResponse;
import com.dji.sample.component.mqtt.model.ServiceReply;
import java.util.Optional;
/**
* @author sean.zhou
@ -24,4 +27,11 @@ public interface IMessageSenderService { @@ -24,4 +27,11 @@ public interface IMessageSenderService {
*/
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 @@ @@ -1,15 +1,20 @@
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.ServiceReply;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
import com.dji.sample.component.mqtt.service.IMqttMessageGateway;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author sean.zhou
* @date 2021/11/16
@ -22,11 +27,11 @@ public class MessageSenderServiceImpl implements IMessageSenderService { @@ -22,11 +27,11 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
@Autowired
private IMqttMessageGateway messageGateway;
@Autowired
private ObjectMapper mapper;
public void publish(String topic, CommonTopicResponse response) {
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));
} catch (JsonProcessingException e) {
@ -37,14 +42,31 @@ public class MessageSenderServiceImpl implements IMessageSenderService { @@ -37,14 +42,31 @@ public class MessageSenderServiceImpl implements IMessageSenderService {
public void publish(String topic, int qos, CommonTopicResponse response) {
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);
} catch (JsonProcessingException e) {
log.info("Failed to publish the message. {}", response.toString());
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; @@ -5,7 +5,7 @@ import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZoneId;
/**
* Automatic filling for set values
@ -20,9 +20,9 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler { @@ -20,9 +20,9 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
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,
LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli());
LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
}
/**
@ -32,6 +32,6 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler { @@ -32,6 +32,6 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
@Override
public void updateFill(MetaObject metaObject) {
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 @@ @@ -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 @@ @@ -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; @@ -11,6 +11,8 @@ import java.net.URL;
*/
public interface IOssService {
String getOssType();
/**
* Get temporary credentials.
* @return
@ -24,4 +26,20 @@ public interface IOssService { @@ -24,4 +26,20 @@ public interface IOssService {
* @return download link
*/
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);
}

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

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

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

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
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.media.model.CredentialsDTO;
import io.minio.GetPresignedObjectUrlArgs;
@ -26,16 +27,21 @@ import java.security.NoSuchAlgorithmException; @@ -26,16 +27,21 @@ import java.security.NoSuchAlgorithmException;
@Slf4j
public class MinIOServiceImpl implements IOssService {
@Autowired(required = false)
private MinioClient client;
@Autowired
private OssConfiguration configuration;
@Override
public String getOssType() {
return OssTypeEnum.MINIO.getType();
}
@Override
public CredentialsDTO getCredentials() {
try {
AssumeRoleProvider provider = new AssumeRoleProvider(MinIOConfiguration.endpoint, MinIOConfiguration.accessKey,
MinIOConfiguration.secretKey, MinIOConfiguration.expire,
null, null, null, null, null, null);
return new CredentialsDTO(provider.fetch(), MinIOConfiguration.expire);
AssumeRoleProvider provider = new AssumeRoleProvider(configuration.getEndpoint(), configuration.getAccessKey(),
configuration.getSecretKey(), Math.toIntExact(configuration.getExpire()),
null, configuration.getRegion(), null, null, null, null);
return new CredentialsDTO(provider.fetch(), Math.toIntExact(configuration.getExpire()));
} catch (NoSuchAlgorithmException e) {
log.debug("Failed to obtain sts.");
e.printStackTrace();
@ -47,20 +53,38 @@ public class MinIOServiceImpl implements IOssService { @@ -47,20 +53,38 @@ public class MinIOServiceImpl implements IOssService {
public URL getObjectUrl(String bucket, String objectKey) {
try {
return new URL(
client.getPresignedObjectUrl(
this.createClient()
.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(objectKey)
.expiry(MinIOConfiguration.expire)
.expiry(Math.toIntExact(configuration.getExpire()))
.build()));
} catch (ErrorResponseException | InsufficientDataException | InternalException |
InvalidKeyException | InvalidResponseException | IOException |
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();
}
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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 { @@ -35,7 +35,7 @@ public class AuthPrincipalHandler extends DefaultHandshakeHandler {
if (!StringUtils.hasText(token)) {
return false;
}
log.debug("token:" + token);
Optional<CustomClaim> customClaim = JwtUtil.parseToken(token);
if (customClaim.isEmpty()) {
return false;

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

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
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.web.socket.WebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
@ -13,8 +15,11 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory; @@ -13,8 +15,11 @@ import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
@Component
public class WebSocketDefaultFactory implements WebSocketHandlerDecoratorFactory {
@Autowired
private IWebSocketManageService webSocketManageService;
@Override
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 @@ @@ -1,9 +1,7 @@
package com.dji.sample.component.websocket.config;
import com.dji.sample.component.websocket.model.WebSocketManager;
import com.dji.sample.component.websocket.service.ISendMessageService;
import com.dji.sample.component.websocket.service.IWebSocketManageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketHandler;
@ -22,20 +20,20 @@ import java.security.Principal; @@ -22,20 +20,20 @@ import java.security.Principal;
@Slf4j
public class WebSocketDefaultHandler extends WebSocketHandlerDecorator {
@Autowired
private ISendMessageService sendMessageService;
private IWebSocketManageService webSocketManageService;
WebSocketDefaultHandler(WebSocketHandler delegate) {
WebSocketDefaultHandler(WebSocketHandler delegate, IWebSocketManageService webSocketManageService) {
super(delegate);
this.webSocketManageService = webSocketManageService;
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
Principal principal = session.getPrincipal();
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: {}]",
principal.getName(), session.getId(), WebSocketManager.getConnectedCount());
principal.getName(), session.getId(), webSocketManageService.getConnectedCount());
return;
}
session.close();
@ -45,9 +43,9 @@ public class WebSocketDefaultHandler extends WebSocketHandlerDecorator { @@ -45,9 +43,9 @@ public class WebSocketDefaultHandler extends WebSocketHandlerDecorator {
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
Principal principal = session.getPrincipal();
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: {}]",
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 { @@ -17,13 +17,19 @@ public enum BizCodeEnum {
GATEWAY_OSD("gateway_osd"),
DOCK_OSD("dock_osd"),
MAP_ELEMENT_CREATE("map_element_create"),
MAP_ELEMENT_UPDATE("map_element_update"),
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;

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

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

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

@ -0,0 +1,90 @@ @@ -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 @@ @@ -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 @@ @@ -1,19 +1,13 @@
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.component.AuthInterceptor;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.component.mqtt.model.CommonTopicReceiver;
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.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.dto.WorkspaceDTO;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.model.param.DeviceQueryParam;
import com.dji.sample.manage.model.receiver.FirmwareVersionReceiver;
import com.dji.sample.manage.model.receiver.StatusGatewayReceiver;
import com.dji.sample.manage.service.IDeviceService;
import lombok.extern.slf4j.Slf4j;
@ -21,12 +15,10 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -21,12 +15,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Optional;
/**
* @author sean.zhou
@ -58,10 +50,6 @@ public class DeviceController { @@ -58,10 +50,6 @@ public class DeviceController {
.tid(receiver.getTid())
.bid(receiver.getBid())
.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 { @@ -81,22 +69,16 @@ public class DeviceController {
.bid(receiver.getBid())
.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.
* @param request
* Get the topology list of all online devices in one workspace.
* @param workspaceId
* @return
*/
@GetMapping("/devices")
public ResponseResult<List<DeviceDTO>> getDevices(HttpServletRequest request) {
// 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.
@GetMapping("/{workspace_id}/devices")
public ResponseResult<List<DeviceDTO>> getDevices(@PathVariable("workspace_id") String workspaceId) {
List<DeviceDTO> devicesList = deviceService.getDevicesTopoForWeb(workspaceId);
return ResponseResult.success(devicesList);
@ -109,30 +91,54 @@ public class DeviceController { @@ -109,30 +91,54 @@ public class DeviceController {
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.
* @param deviceSn drone's sn
* Get the binding devices list in one workspace.
* @param workspaceId
* @param page
* @param pageSize
* @return
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_PAYLOAD_UPDATE)
public void pushWebSocketDevices(String deviceSn) {
List<DeviceDTO> devicesList = deviceService.getDevicesByParams(
DeviceQueryParam.builder()
.deviceSn(deviceSn)
.build());
// Get drone information based on the sn of the drone. The sn of the drone is unique.
DeviceDTO device = devicesList.get(0);
// Set the remote controller and payloads information of the drone.
deviceService.spliceDeviceTopo(device);
CustomWebSocketMessage wsMessage = CustomWebSocketMessage.builder()
.timestamp(System.currentTimeMillis())
.bizCode(BizCodeEnum.DEVICE_UPDATE_TOPO.getCode())
.data(device)
.build();
// Update the topology of the drone via WebSocket notifications to the web side.
sendMessageService.sendBatch(WebSocketManager
.getValueWithWorkspaceAndUserType(
device.getWorkspaceId(), UserTypeEnum.WEB.getVal()),
wsMessage);
@GetMapping("/{workspace_id}/devices/bound")
public ResponseResult<PaginationData<DeviceDTO>> getBoundDevicesWithDomain(
@PathVariable("workspace_id") String workspaceId, String domain,
@RequestParam(defaultValue = "1") Long page,
@RequestParam(value = "page_size", defaultValue = "50") Long pageSize) {
PaginationData<DeviceDTO> devices = deviceService.getBoundDevicesWithDomain(workspaceId, page, pageSize, domain);
return ResponseResult.success(devices);
}
@DeleteMapping("/{device_sn}/unbinding")
public ResponseResult unbindingDevice(@PathVariable("device_sn") String deviceSn) {
deviceService.unbindDevice(deviceSn);
return ResponseResult.success();
}
@PutMapping("/{workspace_id}/devices/{device_sn}")
public ResponseResult updateDevice(@RequestBody DeviceDTO device,
@PathVariable("workspace_id") String workspaceId,
@PathVariable("device_sn") String deviceSn) {
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 @@ @@ -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; @@ -2,7 +2,6 @@ package com.dji.sample.manage.controller;
import com.dji.sample.component.mqtt.model.ChannelName;
import com.dji.sample.manage.model.receiver.DeviceBasicReceiver;
import com.dji.sample.manage.model.receiver.DevicePayloadReceiver;
import com.dji.sample.manage.service.IDevicePayloadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@ -23,25 +22,6 @@ public class DevicePayloadController { @@ -23,25 +22,6 @@ public class DevicePayloadController {
@Autowired
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.
*
@ -50,9 +30,8 @@ public class DevicePayloadController { @@ -50,9 +30,8 @@ public class DevicePayloadController {
* @param deviceBasic basic drone data
* @return drone's sn
*/
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC,
outputChannel = ChannelName.INBOUND_STATE_PAYLOAD_UPDATE)
public String stateBasic(DeviceBasicReceiver deviceBasic) {
@ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_BASIC)
public void stateBasic(DeviceBasicReceiver deviceBasic) {
// Delete all payload information for the drone based on the drone's sn.
devicePayloadService.deletePayloadsByDeviceSn(List.of(deviceBasic.getDeviceSn()));
@ -61,6 +40,5 @@ public class DevicePayloadController { @@ -61,6 +40,5 @@ public class DevicePayloadController {
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; @@ -2,13 +2,13 @@ package com.dji.sample.manage.controller;
import com.dji.sample.common.model.CustomClaim;
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.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.LiveTypeDTO;
import com.dji.sample.manage.model.receiver.CapacityDeviceReceiver;
import com.dji.sample.manage.model.receiver.ServiceReplyReceiver;
import com.dji.sample.manage.model.receiver.LiveCapacityReceiver;
import com.dji.sample.manage.service.ILiveStreamService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -38,15 +38,17 @@ public class LiveStreamController { @@ -38,15 +38,17 @@ public class LiveStreamController {
@Autowired
private ILiveStreamService liveStreamService;
@Autowired
private ObjectMapper mapper;
/**
* Analyze the live streaming capabilities of drones.
* 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)
public void stateCapacity(CapacityDeviceReceiver device) {
boolean parseCapacity = liveStreamService.saveLiveCapacity(device);
log.debug("The result of parsing the live capacity is {}.", parseCapacity);
public void stateCapacity(LiveCapacityReceiver liveCapacity) {
liveStreamService.saveLiveCapacity(liveCapacity);
}
/**
@ -102,9 +104,8 @@ public class LiveStreamController { @@ -102,9 +104,8 @@ public class LiveStreamController {
@ServiceActivator(inputChannel = ChannelName.INBOUND_SERVICE_REPLY)
public void serviceReply(Message<?> message) throws IOException {
byte[] payload = (byte[])message.getPayload();
ObjectMapper mapper = new ObjectMapper();
CommonTopicReceiver<ServiceReplyReceiver> receiver = mapper.readValue(payload,
new TypeReference<CommonTopicReceiver<ServiceReplyReceiver>>() {
CommonTopicReceiver<ServiceReply> receiver = mapper.readValue(payload,
new TypeReference<CommonTopicReceiver<ServiceReply>>() {
});
Chan<CommonTopicReceiver> chan = Chan.getInstance();
// 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 { @@ -27,9 +27,10 @@ public class LoginController {
@PostMapping("/login")
public ResponseResult login(@RequestBody UserLoginDTO loginDTO) {
String username = loginDTO.getUsername();
String password = loginDTO.getPassword();
return userService.userLogin(username, password);
return userService.userLogin(username, password, loginDTO.getFlag());
}
@PostMapping("/token/refresh")
@ -42,6 +43,6 @@ public class LoginController { @@ -42,6 +43,6 @@ public class LoginController {
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 @@ @@ -1,12 +1,12 @@
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.manage.model.dto.UserListDTO;
import com.dji.sample.manage.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@ -20,10 +20,45 @@ public class UserController { @@ -20,10 +20,45 @@ public class UserController {
@Autowired
private IUserService userService;
/**
* Query the information of the current user.
* @param request
* @return
*/
@GetMapping("/current")
public ResponseResult getCurrentUserInfo(HttpServletRequest request) {
CustomClaim customClaim = (CustomClaim)request.getAttribute(TOKEN_CLAIM);
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 @@ @@ -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 @@ @@ -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 @@ @@ -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; @@ -18,14 +18,12 @@ import java.util.List;
@NoArgsConstructor
public class CapacityCameraDTO {
private Integer id;
private String id;
private String deviceSn;
private String name;
private String description;
private String index;
private String type;

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

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

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

@ -1,12 +1,11 @@ @@ -1,12 +1,11 @@
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.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
/**
@ -18,7 +17,6 @@ import java.util.List; @@ -18,7 +17,6 @@ import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class DeviceDTO {
private String deviceSn;
@ -44,4 +42,22 @@ public class DeviceDTO { @@ -44,4 +42,22 @@ public class DeviceDTO {
private List<DevicePayloadDTO> payloadsList;
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 @@ @@ -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; @@ -14,9 +14,9 @@ import lombok.NoArgsConstructor;
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class TelemetryDTO {
public class TelemetryDTO<T> {
private TelemetryDeviceDTO host;
private T host;
private String sn;
}

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

@ -22,8 +22,7 @@ public class TopologyDeviceDTO { @@ -22,8 +22,7 @@ public class TopologyDeviceDTO {
private DeviceModelDTO deviceModel;
@Builder.Default
private Boolean onlineStatus = true;
private Boolean onlineStatus;
private String deviceCallsign;
@ -32,4 +31,12 @@ public class TopologyDeviceDTO { @@ -32,4 +31,12 @@ public class TopologyDeviceDTO {
private String userCallsign;
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 @@ @@ -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 { @@ -11,4 +11,7 @@ public class UserLoginDTO {
@NonNull
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; @@ -19,8 +19,6 @@ import lombok.NoArgsConstructor;
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class WorkspaceDTO {
public static final String DEFAULT_WORKSPACE_ID = "e3dea0f5-37f2-4d79-ae58-490af3228069";
private Integer id;
private String workspaceId;
@ -30,4 +28,6 @@ public class WorkspaceDTO { @@ -30,4 +28,6 @@ public class WorkspaceDTO {
private String workspaceDesc;
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 { @@ -66,4 +66,23 @@ public class DeviceEntity implements Serializable {
@TableField(value = "url_select")
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 @@ @@ -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 { @@ -35,8 +35,8 @@ public class DevicePayloadEntity implements Serializable {
@TableField(value = "sub_type")
private Integer subType;
@TableField(value = "version")
private Integer version;
@TableField(value = "firmware_version")
private String firmwareVersion;
@TableField(value = "payload_index")
private Integer payloadIndex;

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

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

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

@ -30,4 +30,6 @@ public class WorkspaceEntity implements Serializable { @@ -30,4 +30,6 @@ public class WorkspaceEntity implements Serializable {
@TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
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 { @@ -14,6 +14,8 @@ public enum DeviceDomainEnum {
PAYLOAD(1, "payload"),
DOCK (3, "dock"),
UNKNOWN(-1, "unknown");
private int val;
@ -29,6 +31,10 @@ public enum DeviceDomainEnum { @@ -29,6 +31,10 @@ public enum DeviceDomainEnum {
return val;
}
public String getDesc() {
return desc;
}
public static String getDesc(int val) {
if (SUB_DEVICE.val == val) {
return SUB_DEVICE.desc;
@ -41,6 +47,10 @@ public enum DeviceDomainEnum { @@ -41,6 +47,10 @@ public enum DeviceDomainEnum {
if (PAYLOAD.val == val) {
return PAYLOAD.desc;
}
if (DOCK.val == val) {
return DOCK.desc;
}
return UNKNOWN.desc;
}
@ -56,6 +66,10 @@ public enum DeviceDomainEnum { @@ -56,6 +66,10 @@ public enum DeviceDomainEnum {
if (PAYLOAD.desc.equals(desc)) {
return PAYLOAD.val;
}
if (DOCK.desc.equals(desc)) {
return DOCK.val;
}
return UNKNOWN.val;
}

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

@ -0,0 +1,155 @@ @@ -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 @@ @@ -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; @@ -7,18 +7,36 @@ package com.dji.sample.manage.model.enums;
*/
public enum UserTypeEnum {
WEB(1),
WEB(1, "Web"),
PILOT(2);
PILOT(2, "Pilot"),
UNKNOWN(-1, "Unknown");
private int val;
private String desc;
UserTypeEnum(int val) {
UserTypeEnum(int val, String desc) {
this.val = val;
this.desc = desc;
}
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 @@ @@ -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; @@ -3,6 +3,8 @@ package com.dji.sample.manage.model.param;
import lombok.Builder;
import lombok.Data;
import java.util.List;
/**
* The object of the device query field.
*
@ -22,10 +24,12 @@ public class DeviceQueryParam { @@ -22,10 +24,12 @@ public class DeviceQueryParam {
private Integer subType;
private Integer domain;
private List<Integer> domains;
private String childSn;
private Boolean boundStatus;
private boolean orderBy;
private boolean isAsc;

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

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

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

@ -0,0 +1,28 @@ @@ -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 { @@ -23,7 +23,4 @@ public class DevicePayloadReceiver {
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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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